InputManagerService是Android framework中核心service之一,Android framework层涉及的代码也是非常多,
1 | frameworks/native/services/inputflinger/ |
从简单的分类可以看做是两层:
- Java层,
InputManagerService
负责对外提供服务,给WindowManagerService
提供输入信息的回调 - Native层,监控Linux上报的输入事件,把事件处理成Android的KeyCode,给想要处理的Window发送输入事件
前面介绍了Linux的输入子系统,可以看到应用层的输入子系统框架都是基于驱动抽象出来的文件系统设备节点的读写来处理的,虽然说起来比较简单,但是在整个复杂的Android操作系统中,把输入事件发送到UI层处理还是非常复杂的一个过程。
当用户按下按键或者触摸屏幕时,输入系统会取出驱动上报的时间,经过层层封装转换成Android层能识别的KeyEvent
或者MotionEvent
,最后交付给对应的目标窗口来消费输入事件。
输入模块的组成:
- Native层的
InputReader
负责从EventHub取出事件并处理,再交付给InputDispatcher
线程 - Native的
InputDispatcher
线程接收到来自InputReader
的输入事件,并记录WMS的窗口信息,用来派发到合适的窗口 - Java层的
InputManagerService
跟WMS交互,WMS记录窗口信息,同步更新到IMS,为InputDispatcher
线程正确派发事件到ViewRootImpl
提供保障
InputManagerService启动过程
InputManagerService作为system_server中的重要服务,继承与IInputManager.Stub
,作为binder的服务端,client位于InputManager的内部通过IInputManagerStub.asInterface()
获取binder的代理端,C/S两端通信协议是由IInputManager.aidl
来定义。
IMS涉及到的重要的类:
InputManagerService
- 位于Java层的InputManagerService.java文件- 其成员变量
mPtr
指向Native层的NativeInputManager
对象
- 其成员变量
NativeInputManager
- 位于Native层的com_android_server_input_InputManagerService.cpp文件- 其成员
mServiceObj
指向Java层的IMS对象 - 其成员
mLooper
是指”android.display”线程的Looper
- 其成员
InputManager
- 位于libinputflinger中的InputManager.cpp文件InputDispatcher
和InputReader
的成员变量mPolicy
都是指向NativeInputManager
对象InputReader
的成员mQueuedListener
,数据类型为QueuedInputListener
;通过其内部成员变量mInnerListener
指向InputDispatcher
对象;这就是InputReader
跟InputDispatcher
交互的中间枢纽。
InputDispatcherPolicyInterface
InputDispatcher
InputDispatcherInterface
InputReaderPolicyInterface
InputReader
InputReaderInterface
EventHubInterface
EventHub
IMS的启动
IMS是伴随着system_server进程的启动而启动的
1 | InputManagerService |
SystemServer.java
1 | private void startOtherServices() { |
IMS初始化
InputManagerService.java
1 | public InputManagerService(Context context) { |
nativeInit
调用到InputManagerService
对应的JNI代码com_android_server_input_InputManager.cpp
1 | static jlong nativeInit(JNIEnv* env, jclass /* clazz */, jobject serviceObj, jobject contextObj, jobject messageQueueObj) { |
同样的套路,在nativeInit
函数中创建了一个NativeInputManager
对象,然后转化为指针保存在一个long
类型的变量中传递给java层,这样子java层就可以利用这个指针来调用NativeInputManager
对象中的成员方法和变量。
NativeInputManager
com_android_server_input_InputManagerService.cpp
1 | NativeInputManager::NativeInputManager(jobject contextObj, |
mLooper
是从IMS的”android.display”线程的Looper对象传递下来的。
EventHub
EventHub.cpp
1 | EventHub::EventHub(void) : |
- 创建epoll实例来处理文件IO的多路复用
- 初始化INotify,监听/dev/input/目录下的文件,并且添加到epoll中
- 创建非阻塞管道文件描述符,添加到epoll中
InputManager
InputManager.cpp
1 | InputManager::InputManager( |
创建了InputDispatcher
和InputReader
对象,这里的Reader
和Dispatcher
的构造参数都是从NativeInputManager
传递过来的
InputManager初始化initialize
InputManager.cpp
1 | void InputManager::initialize() { |
创建两个可以访问InputManagerService
成员变量的native线程
InputReader
线程InputDispatcher
线程
IMS.start
InputManagerService.java
1 | public void start() { |
nativeStart
com_android_server_input_InputManagerService.cpp
1 | static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) { |
InputManager.start
InputManager.cpp
1 | status_t InputManager::start() { |
启动两个线程:
- InputReader
- InputDispatcher
1 | /* Reads raw events from the event hub and processes them, endlessly. */ |
InputReaderThread
和InputDispatcherThread
都是集成了Android::Thread,实现了threadLoop()
接口实现线程的实体。
下面来详细分析一下Android的EventHub。