概述
InputManagerService构造时会构造naive的binder server inputManager。此处会创建inputReader和inputDispatcher两条死循环线程。
inputReader利用inotify机制监听/dev/input下的设备节点增删(最终也是 通过将inotify创建的fd挂到epoll下实现的),获取到新增的节点后,利用epoll监听这些设备节点的rawEvent。
监听到这些rawEvent后会通过xxxMapper将其加工为xxxArgs,再转发给监听者inputDispatcher。
inputDispatcher收到后只是做完简单的事件有效性判断后就往mInboundQueue中塞。
inputDispatcher线程就是循环读取mInboundQueue看是否有数据,有数据则开始分发。分发时先找到事件可以派发的窗口,该过程会涉及anr的判断,再将事件塞到connection.outboundqueue中,再通过socket传给app,再将事件塞到waitQueue中,等app处理完事件回调过来再将waitQueue中的事件删除。
代码分析的入口在InputManagerService#start
一些重要的类和概念
InputReader
https://blog.csdn.net/zhzhangnews/article/details/91490097
InputDispatcher
https://blog.csdn.net/zhzhangnews/article/details/106795348
InputDispatcher的实现主要涉及3个Queue: 1. InboundQueue: 这个队列里面存储的是从InputReader送来到输入事件 2. OutboundQueue:这个队列里面存储的是即将要发送给应用的输入事件 3. WaitQueue:这个队列里面存储的是已经发给应用的事件,但应用还未处理完成。(OutboundQueue和WaitQueue在存在于Connection中)
InputChannel:本质上是一对SocketPair
ACTION_CANCEL
case1:
viewGroup中有一个btn,在viewGroup中拦截第一次move事件。btn会收到一个CANCEL事件且不会收到后续事件.
如果某一个子View处理了Down事件(此时 mFirstTouchTarget不为null),那么随之而来的Move和Up事件也会交给它处理。但是交给它处理之前,父View还是可以拦截事件的,如果拦截了事件,那么子View就会收到一个Cancel事件,并且不会收到后续的Move和Up事件
https://blog.csdn.net/cufelsd/article/details/89471402
case2:
正在往window1不断派发事件如MOVE事件,此时按home键,window1会受到CANCEL事件。
原因:当焦点窗口变化时surfaceFlinger会调用到InputDispatcher::setInputWindowsLocked