从手指接触屏幕到MotionEvent被传送到Activity或者View,中间究竟经历了什么?Android中触摸事件到底是怎么来的呢?源头是哪呢?本文就直观的描述一个整个流程,不求甚解,只求了解。
Android触摸事件模型
触摸事件肯定要先捕获才能传给窗口,因此,首先应该有一个线程在不断的监听屏幕,一旦有触摸事件,就将事件捕获;其次,还应该存在某种手段可以找到目标窗口,因为可能有多个APP的多个界面为用户可见,必须确定这个事件究竟通知那个窗口;最后才是目标窗口如何消费事件的问题。
InputManagerService是Android为了处理各种用户操作而抽象的一个服务,自身可以看做是一个Binder服务实体,在SystemServer进程启动的时候实例化,并注册到ServiceManager中去,不过这个服务对外主要是用来提供一些输入设备的信息的作用,作为Binder服务的作用比较小:
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);
...
}
InputManagerService跟WindowManagerService几乎同时被添加,从一定程度上也能说明两者几乎是相生的关系,而触摸事件的处理也确实同时涉及两个服务,最好的证据就是WindowManagerService需要直接握着InputManagerService的引用,如果对照上面的处理模型,InputManagerService主要负责触摸事件的采集,而WindowManagerService负责找到目标窗口。接下来,先看看InputManagerService如何完成触摸事件的采集。
如何捕获触摸事件
InputManagerService会单独开一个线程专门用来读取触摸事件,
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,它主要是利用Linux的inotify和epoll机制,监听设备事件:包括设备插拔及各种触摸、按钮事件等,可以看做是一个不同设备的集线器,主要面向的是/dev/input目录下的设备节点,比如说/dev/input/event0上的事件就是输入事件,通过EventHub的getEvents就可以监听并获取该事件:
在new InputManager时候,会新建一个InputReader对象及InputReaderThread Loop线程,这个loop线程的主要作用就是通过EventHub的getEvents获取Input事件
InputManager::InputManager(
const sp<EventHubInterface>& eventHub,
const sp<InputReaderPolicyInterface>& readerPolicy,
const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
<!--事件分发执行类-->
mDispatcher = new InputDispatcher(dispatcherPolicy);
<!--事件读取执行类-->
mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
initialize();
}
void InputManager::initialize() {
mReaderThread = new InputReaderThread(mReader);
mDispatcherThread = new InputDispatcherThread(mDispatcher);
}
bool InputReaderThread::threadLoop() {
mReader->loopOnce();
return true;
}
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
Vector<InputDeviceInfo> inputDevices;
{
...<!--监听事件-->
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
....<!--处理事件-->
processEventsLocked(mEventBuffer, count);
...
<!--通知派发-->
mQueuedListener->flush();
}
通过上面流程&#x