请对照AOSP版本:6.0.1_r50。
1. 创建InputManager
这里和老罗当年的版本有很大不同了,有了InputManagerService管理InputManager。
1.1
想要探索如何启动的相关server,需要从SystemServer开始探寻。从SystemServer的进程开始运行开始,它就会创建一些系统server,这里就会启动other services。
其中,会创建Input Manager和Window Manager两个服务。
frameworks/base/services/java/com/android/server/SystemServer.java :
1.2
先来仔细端详一下InputManagerService的构造函数。这里会调用c++层的初始化函数。
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java :
注意这里将DisplayThread的Looper传递过去,DisplayThread是一个单例模式的类,它会启动唯一的线程。同时DisplayThread是一个HandlerThread的子类,实现了Looper循环机制。DisplayThread是用来执行和显示有关的操作,显示操作一般需要比较小的延迟。DisplayThread只能被WindowManager、DisplayManager,InputManager用来执行一些快速地实时操作。
1.3
这一步首先将java层的MessageQueue变为了c++的MessageQueue。然后构造了一个NativeInputManager对象,最后将指向该对象的指针im
返回给java层。
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp :
1.4
在构造NativeInputManager时,会创建一个InputManager对象mInputManager。
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp :
1.5
这一步会创建一个dispatcher负责分发输入事件,一个reader负责获取事件。
frameworks/native/services/inputflinger/InputManager.cpp :
1.6
这里会创建两个线程,在以后的步骤中会用来运行前面创建的dispathcer和reader。
frameworks/native/services/inputflinger/InputManager.cpp :
2. 启动InputManager
将视线再次回到SystemServer中,在创建完InputManagerService后,需要将这个Service启动,同样是在1.1的startOtherServices函数里,调用了InputManagerService的成员函数start。
2.1
这里首先调用了c++层的nativeStart,然后InputManagerService将自己交给Watchdog监视。然后注册了PointerSpeedSetting和ShowTouchesSetting两个Observer。
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java :
这两个Observer暂时还没搞清楚是干什么的。
2.2
这一步将传来的ptr参数转化为一个NativeInputManager指针,同时开始启动NativeInputManager中的InputManager。
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp :
2.3
这里会启动在1.6中创建的两个线程,分别用来分发和监听Input事件。
frameworks/native/services/inputflinger/InputManager.cpp :
3. 启动InputDispatcher
在2.3中运行的线程以threadLoop为入口,开始进入循环。
3.1
这一步直接将任务交给InputDispatcher的dispatchOnce函数。
frameworks/native/services/inputflinger/InputDispatcher.cpp :
3.2
整个函数如下:
frameworks/native/services/inputflinger/InputDispatcher.cpp :
在这一步骤中,首先判断是否有Command还未被执行,如果有去执行Command。否则,调用dispatchOnceInnerLocked函数去获取事件,这里会将nextWakeupTime传递过去,让其设置合适的苏醒时间,具体内容在以后讲解。然后runCommandsLockedInterruptible函数会执行缓存的Command,如果有Command在这一步中被执行,则需要将苏醒事件设置为LONG_LONG_MIN
,因为执行这些命令需要耗费事件,在这期间可能已经有输入事件发生了,所有下次循环不需要等待。
最后,根据等待时间和当前时间,计算出需要睡眠的时间,通过pollOnce进入睡眠,等待唤醒,或者超时。
3.3
这里和上一个章节中的pollOnce道理相同。
3.4
这里会调用epoll_wait函数,使其在mEpollFd所描述的epoll上等待一段时间,这个epoll监听着文件描述符的读写事件。如果有人在pip中写入,则会返回,否则等待指定时间后返回。
system/core/libutils/Looper.cpp
4. 启动InputReader
在2.3中运行的线程以threadLoop为入口,开始进入循环。
4.1
这一步与3.1一样,将任务丢给InputReader处理。
4.2
这一步会尝试从mEventHub中获取事件,如果获取一些事件,则进行处理。
frameworks/native/services/inputflinger/InputReader.cpp :
这里我们先考虑如何从EventHub中获取事件的。
4.3
首先这一个函数不是就获得一个event这么简单,它是想获得一组event,这里和旧版本有所不同,可见工程师对系统做了优化。这一步内容比较到,让我们通过注释来讲解。
frameworks/native/services/inputflinger/EventHub.cpp :
4.4
从这里开始扫描设备。在研究这个函数前,先看一下DEVICE_PATH
的来头:
frameworks/native/services/inputflinger/EventHub.cpp :
frameworks/native/services/inputflinger/EventHub.cpp :
4.5
这里开始扫描/dev/input/
目录下的所有设备。
frameworks/native/services/inputflinger/EventHub.cpp :
4.6
frameworks/native/services/inputflinger/EventHub.cpp :
4.7
这一步比较轻松,将创建好的device对象放入mDevices即可。