本文是综合
《深入理解 Android 卷 III(第五章 深入理解 Android 输入系统)》
《Android 系统源代码情景分析(第 14章 Android 应用程序的键盘消息处理机制)》
《深入解析 Android 5.0 系统(第 16 章 Android 的输入管理)》
三章的总结。
一、输入系统的总体流程
. Linux 内核
接受输入设备的中断,并将原始事件的数据写入设备节点中;
. 设备节点
作为内核月 IMS 的桥梁,将原始事件的数据暴露给用户空间, 以便 IMS 可以从中读取事件;
. EventHub
直接访问所有的设备节点,将所有的输入事件通过 getEvents() 接口把多个输入设备节点中读取的数据交给 InputReader, 它是输入系统最底层的一个组件;
. InputReader
运行独立线程中,负责管理输入设备的列表与配置, 对输入事件进行加工处理,然后交给 InputDispatcher 处理;
. InputDispatcher
运行独立线程中,保存来至 WMS 的窗口信息,将从 InputReader 传过来的输入事件派发到合适的窗口;
. InputReaderPolicy
为 InputReader 的事件加工处理提供一些策略配置;
. InputDispatcherPolicy
为 InputDispatcher 的派发过程提供策略控制,例如截取某些特定的输入事件作为特殊用途,或者阻止将某些事件派发给目标窗口。例如 Home 键事件被截取到 PhoneWindowManager 中处理,并阻止窗口收到 Home 键按下的事件;
. WindowManagerService
当创建窗口时 WMS 为新窗口和 IMS 创建事件传递的通道 InputChannel;
. ViewRootImpl
对某些窗口,例如壁纸, SurfaceView 的窗口,窗口就是事件派发的终点;
对于其他例如 Activity, 对话框等使用了 Android 控件系统的窗口来说,输入终点是 View。 ViewRootImpl 将窗口所接收的输入事件沿着控件树将事件派发给感兴趣的控件。
整体流程:
内核将原始事件写入设备节点中, InputReader 不断地通过 EventHub 将原始事件取出来并翻译加工成 Android 输入事件,然后交给 InputDispatcher 。InputDispatcher 根据 WMS 提供的窗口信息将事件交给合适的窗口。窗口的 ViewRootImpl 对象再沿着控件树将事件派发给刚兴趣的控件。
二、IMS 的结构体系
- InputManagerService 在 SystemService 中的 ServerThread 线程中启动;
SystemServer.java 的 ServerThread.run() 方法中
inputManager = new InputManagerService(context, wmHandler);
wm = WindowManagerService.main(context, power, display, inputManager,
uiHandler, wmHandler,
factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL,
!firstBoot, onlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
inputManager.start();
- 在 InputManagerService 的构造函数中,调用 nativeInite(…) 方法,在该方法内创建 NativeInputManager
framework/services/jni/com_android_input_InputManagerService.cpp
NativeInputManager::NativeInputManager(…)
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper) {
JNIEnv* env = jniEnv();
...
// 创建 EventHub
sp<EventHub> eventHub = new EventHub();
// 创建 Native 层的 InputManager
mInputManager = new InputManager(eventHub, this, this);
}
- 在 InputManager 的构造函数中,创建 InputReader 和 InputDispatcher
framework/services/input/InputManager.cpp
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
// 创建 InputDispatcher
mDispatcher = new InputDispatcher(dispatcherPolicy);
// 创建 InputReader
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
void InputManager::initialize() {
// 为 InputReader 创建运行线程 In