大家讲起事件传递时,都会从Window RootViewImpl 讲起 然后再讲View层的一些处理逻辑,
但传递的事件到底是从哪里来的,当我们触摸屏幕的时候MotionEvent是如何被创建 并传送到目标窗口的,
这里面系统都做了什么呢?
猜想
事件一定有一个从捕获到分发的过程,为了保证实时性因此会有一个线程一直在轮询监听事件,一旦捕获到触摸事件,通过某种规则筛选出所需的窗口,然后通过某种通讯方式分发给所需窗口
一探究竟(基于Android7.1)
我们知道系统服务会在SystemServer中进行实例化操作,我们先将目光放在InputManagerService(以下简称IMS)上,InputManagerService是Android处理各种用户操作抽象的一个服务,是InputManager的真身,在SystemServer中实例化后与WindowManagerService(以下简称WMS)一起添加到ServiceManager中
private void startOtherServices() {
inputManager = new InputManagerService(context);
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
}
由上面代码片段可以看出 IMS与WMS同时被添加进ServiceManager中,WMS有着IMS的引用
有此推断IMS负责触摸事件的捕获,WMS负责将事件派发到目标窗口上。
IMS构造方法中调用nativeInit创建NativeInputManager
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
//......
sp<EventHub> eventHub = new EventHub();
mInputManager = new InputManager(eventHub, this, this);
}
这里EventHub 主要负责监听设备事件包括输入设备的拔插,触摸 按钮 鼠标事件等,通过EventHub的getEvents就可以监听并获取该事件,
主要是面向/dev/input 目录下的event设备节点,我们可以用cat 命令查看这些节点,当有输入设备有输入时对应节点会有相应的打印,或者通过getevent命令查看如下
此打印是我 按home键与返回键的打印(如果你此时触摸屏幕会看到跟多打印)
打印为16进制对应过来66 对应 102 ,9e 对应158
查看 system/usr/keylayout/ 对应关系如下
我们接下来看InputManager,InputManager 创建时伴随创建了 InputDispatcher 与 InputReader 并将
InputDispather 与EventHub传入了InputReader
通过上面可以看到 伴随创建完之后调用了initialize
并开启了两个线程 通过字面意思也可看出
InputReaderThread 负责读取 InputDispatch