IMS(InputManagerService)是Android系统中负责处理输入事件的服务,由他负责监听和分发输入事件,事件包括键盘、鼠标、触摸屏、物理按钮、耳机插入等。
触摸事件整体工作流程
1.点击屏幕触发事件;
2.EventHub监听事件发生;
3.InputReader捕获事件,预处理后交给InputDispatcher;
4.InputDispatcher通过WMS找到事件对应的目标窗口,通过socket将事件传给目标进程;
5.目标进程的ViewRootImpl通过socket接收到事件消息,将事件交给Activity处理,然后就是应用层的事件分发流程
IMS服务
Android设备开机后,启动system_server进程,在system_server进程中,在startOtherServices方法中,创建IMS实例,将IMS和WMS做关联,给IMS设置窗体事件监听,然后启动IMS服务。创建IMS实例时,调用nativeInit方法,并传入DisplayThread线程的消息队列,启动服务时,调用nativeStart方法。在native层,EventHub利用Linux的inotify和epoll机制,可以获取到事件的输入,InputReader创建出一个单独的线程InputReaderThread,通过死循环的方式不断地从EventHub读取事件,然后将事件预处理成RawEvent交给InputDispatcher,InputDispatcher也有一个单独的线程InputDispatcherThread做事件分发,和Handler的消息分发一样,当没有事件时线程阻塞,当有事件时唤醒线程。InputDispatcher分发触摸事件时,先通过WMS找到事件对应的目标窗口,然后通过InputChannel类,通过socket方式将事件发送到目标窗口对应的App进程,由App端的WindowInputEventReceiver对象接受Input事件,然后再把事件分发到目标view,view再把事件交给对应的DecorView,DecorView再交给对应的activity或者dialog。
处理流程图如下:
InputChannel和App进程为什么采用Socket通信,不用Binder
1.Binder在处理大量连续的输入事件时,性能不如Socket
2.每创建一对Binder,就会创建一个binder线程池,而socket只需要一个线程,更节省资源
3.socket可以保证事件的有序性,binder在高频操作下无法保证有序
4.binder处理大量事件有可能会丢失