Linux事件机制:
事件都是储存在文件中;
如触摸屏幕事件:存储在dev/input/event0的文件中,每次触摸都会以16进制数据储存;
INotify:监听文件状态,有变化则产生FD值
epoll机制:
epoll_create:注册监听事件类型
epoll_ctl:监听FD值,FD改变则唤醒epoll_wait()
epoll_wait:没事件则阻塞,有事件则分发;
将INotify和epoll封装为一个对象EventHub;
SystemServer进程启动时,创建了InputManagerService服务,这个IMS在native层创建了InputManager对象;
InputManager里有一个对象EventHub;
同时InputManager里面又开启了两个线程:
InputReaderThread:不断去读取EventHub里的事件;有事件时把数据封装后添加到队列,立马从队列里读取交给InputDispatcher进行分发;
InputDispatcherThread:InputDispatcher里面保存了wms中所有的window信息(wms会将window信息实时更新到InputDispatcher中),InputDispatcher就可以将事件分发给对应合适的window;
App进程中的ViewRootImpl和SystemServer中的IMS通过socketpair通信,因为事件产生的非常快且非常多使用binder通信不适合
在ViewRootImpl中setView后new了一个监听FD文件的回调,new WindowInputEventReceiver();
在回调中,底层使用epoll_ctl()函数监听FD是否变化,有变化则会回调至java层,dispatchInputEvent();
这里就是Activity-》Viewgroup->View的事件分发前置;
底层事件信号传递总结:
- 事件信号都是用物理文件存储数据的,位置在dev/input 文件夹下;touch事件存储在dev/input/event0的文件中;
- Linux有提供相关的文件监控api: inotify()和epoll机制
- android创建了一个封装了 inotify()和epoll机制的对象EventHub,来监控dev/input文件夹下面的事件信号文件;
- android自己启动两个线程来处理dev/input文件夹下面的事件信号文件:InputReaderThread和InputDispatherThread;
- 在InputReaderThread中开启循环,对EventHub对象进行getEvent();
- getEvent()中有epoll_wait;相当于wait-notif机制;唤醒的触发点时dev/input下的文件被改变;
- InputReaderThread将dev/input文件夹下面的事件信号文件数据进行 提取、封装,然后交给InputDispatherThread;
- InputDispatherThread最终选择到对应的ViewRootImpl(window)进行分发数据;
- 这里App进程和SystemServer两个进程通过Socketpair进行通信;两个进程一边一组socketpair;
- 在ViewRootImpl中对于Channel连接的文件进行监控(epoll_ctr),从而是上层接收到touch信号;