栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Android 源码分析 - 输入 - Native层

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Android 源码分析 - 输入 - Native层

toolbox/getevent

        Getevent是android工具集中的一员。Getevent列出设备上所有输入设备的信息,并且dump 输入事件。

        源代码位于:system/core/toolbox。

toolbox/sendevent

        Sendevent是android工具集中的一员。Sendevent用来模拟底层的输入事件。

        源代码位于:system/core/toolbox。

libinput

        源代码位于:frameworks/native/libs/input。

        头文件位于:

        frameworks/native/include/android、frameworks/native/include/input。

        其中android/keycodes.h定义了android的系统键值android/input.h定义了相关flags。

        设备配置文件有三类:

  1. 配置文件(idc/*.idc)
  2. 布局映射文件(keylayout/*.kl)
  3. 字符映射文件(keychars/*.kcm)

        键值映射文件:

        frameworks/base/data/keyboards/Generic.kl

        frameworks/base/data/keyboards/Generic.kcm

        参考:

  • Key Layout Files
  • Key Character Map Files
  • Input Device Configuration Files
  • Keyboard Devices

        KeyMap管理一个设备的配置文件,并读取配置到内部KeyLayoutMap、KeyCharacterMap对象中。配置文件的搜索使用下面的顺序:

  1. ByName (name来自设备属性“keyboard.layout”或者“keyboard.characterMap”)
    1. /system/usr//.
    2. /data/system/devices//.
  2. ByDeviceIdentifier
    1. ByName(“Vendor_%04x_Product_%04x_Version_%04x”)
    2. ByName(“Vendor_%04x_Product_%04x”)
  3. ByName(“Generic”)
  4. ByName(“Virtual”)

        比如:标准键盘的名字是qwerty,所以系统里面一般都有下面两个文件:

        /system/usr/keylayout/qwerty.kl和/system/usr/keychars/qwerty.kcm。

        InputDeviceIdentifier描述一个输入设备,比如名称、GUID、厂商、产品代码、版本、描述等。

        InputDeviceInfo描述输入设备的特性(characteristics)和能力(capabilities)。

        KeyLayoutMap管理一个布局映射。查找key的时候先查找usage码(HID),再查找scan码(LKC)返回Android码(AKC)和flags。被EventHub使用。

        KeyCharacterMap管理一个字符映射,也有键击(Key)事件布局映射的功能(没有flags定义),支持用另一个KeyCharacterMap覆盖生成新的KeyCharacterMap。被java层的KeyCharacterMap类封装。(参见:PhoneWindowManager.dispatchUnhandledKey)

 

        InputEvent继承AInputEvent,定义了输入事件。有KeyEvent、MotionEvent两个派生类。

        InputEventFactoryInterface定义了生成InputEvent的工厂接口。

        PreallocatedInputEventFactory实现InputEventFactoryInterface,对各种类型的InputEvent分别有一个预先申请的对象。

        PooledInputEventFactory是InputEventFactoryInterface接口的另一个实现,用对象池处理InputEvent的申请释放。

        InputMessage定义了一个进程间传递的输入事件结构,有键盘、移动、“完成”三种类型。“完成”用于反向应答事件处理情况。

        InputChannel用于进程之间传递输入事件。两端各有一个InputChannel。使用socketpair(SOCK_SEQPACKET)实现。

        InputConsumer从InputChannel读取InputMessage转换为InputEvent,支持批处理。

        InputPublisher向InputChannel发送InputMessage,读取完成事件。

libinputservice

        libinputservice实现输入事件的读取、分派,作为动态链接库被libandroid_servers库链接,最终被SystemServer进程中加载。

        源代码位于:frameworks/base/services/input。

 

        几个关键类:InputManager、InputDispatcher、InputReader、EventHub。

        EventHub的核心在一个epoll的使用上,这个epoll包含下面这些文件描述符:

  1. mINotifyFd(监视/dev/input/目录变化,使用inotify)
  2. mWakeReadPipeFd(与mWakeWritePipeFd一起,是一个pipe,用于唤醒epoll)
  3. Device::fd(每个设备的文件描述符)

        EventHub的getEvents会收集最多外面指定数量的输入事件,包括设备“增加”、“删除”事件。如果没有事件并且没有被唤醒,则通过epoll_wait等待。epoll事件(注意与输出事件区分)被缓存在mPendingEventItems数组中。为了在关闭设备文件描述符之前读取输入事件,mINotifyFd对应的epoll事件需要延迟处理。

        EventHub内部的私有Device类,保存了设备的基本信息、事件类型、分类信息,配置、键值映射。EventHub负责维护这些信息,布局映射转换、按键状态查询。Device类还保存了字符映射与外面指定的一个字符映射(overlayKeyMap)的合并字符映射(combinedKeyMap)。

  • Inotify: 高效、实时的Linux文件系统事件监控框架

        InputMapper将原始输入事件分类转换,不同类型的InputMapper处理不同类型的输入事件。InputMapper通过process方法处理原始事件,处理完成后通知到InputListener,不同类型的事件调用InputListener对应的回调方法。

        InputDevice保存设备信息和多个InputMapper。InputDevice的process方法会遍历所有InputMapper,调用其process方法。

        NotifyArgs是一个基类,调用InputListener不同的notify接口时,传递的是对应的NotifyArgs派生类对象。NotifyArgs定义了notify虚方法,用来给InputListener发送notify事件。不同的NotifyArgs的派生类在notify方法实现中调用InputListener相应的notify方法。

        InputReader的loopOnce首先通过EventHub 的getEvents接口获取输入事件。如果是合成事件(SYNTHETIC_EVENT),比如DEVICE_ADDED事件,那么创建一个InputDevice,并根据设备的classes属性配置多个InputMapper。如果是普通事件,将连续同一个设备的事件一起处理,调用InputDevice的process接口。为了防止InputListener在加锁状态下回调InputReader,增加了QueuedInputListener来临时缓存事件。

        InputReader::QueuedInputListener继承并且封装另一个InputListenerInterface,将接收到的事件排队,在最后flush时发送给真正的Listener。排队事件是NotifyArgs对象。

        InputReader::InputReaderContext将InputReader的mPolicy、mQueuedListener、mEventHub,已经一些方法打包,传递给InputDevice和InputMapper。

        InputWindowInfo描述窗口的属性。

        InputWindowHandle是一个句柄,内部包含InputWindowInfo指针。

        InputTarget定义输入事件提交到一个窗口的方式,包含一个InputChannel、控制flags、超时时间、坐标。

        InputDispatcher继承InputListenerInterface,接收InputReader输入的事件,插入到队列中,在另一个线程loopOnce分派这些事件。InputDispatcher管理事件连接Connection、窗口句柄InputWindowHandle。

        InputDispatcher::Connection管理着一个InputChannel相关的状态,包括InputState、输出队列、等待应答队列。

        InputDispatcher::InputState跟踪已经分派的键击、移动状态,以便取消事件能够同步。

        InputManager创建InputDispatcher和InputReader,并创建InputReaderThread循环调用InputReader 的loopOnce,创建InputDispatcherThread循环调用InputDispatcher的dispatchOnce。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/345066.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号