简介
Android的事件处理是在Linux基础上完成的。事件的最开始是由硬件监听到,然后通过硬件分到Kernel,Kernel在分到框架层,最后最后框架层把事件分布到应用程序的UI中。下面就以触摸事件为例进行分析。
当有事件发生的时候,硬件首先监听到,然后InputDriver起作用,而框架层的EventHub类一直在InputDriver中读事件;当EventHub类读到事件之后,EventHub就会通过NativeInputManager类首先分发事件到Java层的InputManager,而Java层的InputManager又会把这个事件分发到服务WindowManagerService(WMS),之后又分发到PhoneWindowManager中,最后分发到ViewRootImpl中,ViewRootImpl将事件分发到应用程序的Activity和View中。
具体流程:首先有一个线程在不断的监听屏幕,一旦有触摸事件,就将其事件捕获;其次,还应该存在某种方式可以找到目标窗口,因为可能有多个APP的多个界面为用户可见,必须确定这个事件究竟通知哪个窗口;最后才是目标窗口如何消费事件的问题。
总体来说,Android事件投递(主要以触摸事件为主)的工作流程分为4个部分,如图所示:
(1) 采集
即对“硬件源”所产生的原始信息进行收集的过程。它需要Linux内核驱动的支持,Android系统则是通过/dev/input/下的节点来访问当前发生的事件。
(2) 前期处理
上一步采集到的信息为“原始数据”,这其中一部分内容对应程序而言并不是“必须”的,而且格式上也相对烦琐,所以需要先经过前期的提炼和转化。
(3)WMS分配
WindowManagerService是窗口的大主管,同时也是InputEvent的派发者。WMS记录了当前系统中所有窗口的完整状态信息,所以只有它才能判断出应该把事件投递给哪一个具体的应用进程进行处理。其派发策略也因事件类型的不同而有所差异,以触摸消息为例,则要先计算出触摸点落在哪个区域,然后才能传递给相应的窗口单元。
(4)应用程序处理
应用开发人员的工作主要体现在这一部分。经过前面的几个步骤的传递,应用程序端收到的事件已经相对“可理解”“好处理”了,接下来要做的就是充分利用这些事件来实现软件的功能。
1、InputManagerService(IMS)诞生
IMS服务的创建过程是在SystemServer进程启动的时候实例化的,并注册到ServiceManager中去,这个服务对外主要是用来提供一些输入设备的信息的作用。
/frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
...
//新建IMS对象
inputManager = new InputManagerService(context);
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
//将IMS发布给ServiceManager,以便其他人可以访问IMS提供的接口
ServiceManager.addService(Context.INPUT_SERVICE, inputManager);
mActivityManagerService.setWindowManager(wm);
//设置向WMS发起回调Callback对象
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
//启动IMS
inputManager.start();
...
}
InputManagerService和WindowManagerService有密切的联系,也是触摸事件处理的时候同时涉及两个服务,InputManagerService主要负责事件(以触摸事件为例)的采集,而WindowManagerService负责找到目标窗口。接下来,继续分析InputManagerService如何完成触摸事件的采集。
2、事件的采集
/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
NativeInputManager::NativeInputManager(jobject contextObj,
jobject serviceObj, const sp<Looper>& looper) :
mLooper(looper), mInteractive(true) {
...
//NativeInputManager创建了EventHub
sp<EventHub> eventHub = new EventHub();
//继续创建Native层的InputManager
mInputManager = new InputManager(eventHub, this, this);
}
这里的EventHub,可以看作是事件集线器,是利用Linux的inotify和epoll机制,对设备节点增删事件以及可读状态的监听,例如,各种触摸、按钮事件等等,主要面向的是/dev/input目录下的设备节点,比如说/dev/input/event0上的事件就是输入事件,通过EventHub的getEvents就可以监听并获取该事件。在InputManager创建的时候,同时也会再创建一个InputReader对象及InputReaderThread Loop线程,这个loop线程的主要作用就是像一台水泵一样,通过EventHub的getEvents获取Input事件。
/frameworks/native/services/inputflinger/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);
//将InputReader与InputDispatcher建立关联
initialize();
}
void InputManager::initialize() {
//创建供InputReader运行的线程InputReaderThread
mReaderThread = new InputReaderThread(mReader);
//创建供InputDispatcher运行的线程InputDispatcherThread
mDispatcherThread = new In