输入事件派发内容比较多,只记其大概; 分两篇,本篇是InputManagerService相关,另外一篇是事件在View体系中的派发。
本篇分四部分:
- InputManagerService的启动
- InputReaderThread 和 InputDispatcherThread
- InputChannel
- Input event的拦截
1. InputManagerService的启动
SystemServer启动的时候会在startOtherServices方法中创建InputManagerService对象,调用addService@ServiceManager方法将这个对象作为“input”系统服务的server端,并调用start@InputManagerService方法开启服务。
相关代码如下:
......
traceBeginAndSlog("StartInputManagerService");
inputManager = new InputManagerService(context);//构造InputManagerService对象
traceEnd();
traceBeginAndSlog("StartWindowManagerService");
// WMS needs sensor service ready
ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
mSensorServiceStart = null;
wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());
ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);//添加到ServiceManager中。
ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
traceEnd();
......
inputManager.setWindowManagerCallbacks(wm.getInputMonitor());//设置CallBack: InputMonitor
inputManager.start();
下面是与代码相对应的流程图,也包括了WindowManagerService注册InputChannel的流程。
先看第一部分InputManagerService的初始化。InputManagerService的构造函数会调用nativeInit(…)方法,对应的JNI层方法是com_android_server_input_InputManagerService.cpp中的nativeInit(…)。
JNI层的*nativeInit(…)*方法会构造NativeInputManager对象,而后者会构造EventHub和InputManager对象。InputManager会构造InputDispatcher,InputReader,InputDispatcherThread以及InputReaderThread对象。
2. InputReaderThread 和 InputDispatcherThread
如上图第三部分所示,当SystemServer调用了新构造InputManagerService对象的start方法后,InputReaderThread和InputDispatcherThread两个线程就开始运行,分别负责完成对输入事件的读取和派发工作。
InputReaderThread和InputDispatcherThread都继承了Thread,这个Thread类的定义是在"
system/core/libutils/Threads.cpp",InputReaderThread和InputDispatcherThread都覆盖了Thread.cpp中的threadLoop方法。start@InputManager.cpp方法会调用InputReaderThread和InputDispatcherThread的run方法,在Thread.cpp中run方法会调用_threadLoop方法,这个方法有个do{}while循环,threadLoop方法会在循环体中被调用,InputReaderThread和InputDispatcherThread通过重写threadLoop方法实现各自的功能; threadLoop@InputReaderThread调用了loopOnce@InputReader方法,threadLoop@InputDispatcherThread调用了dispatchOnce@InputDispatcher方法。
2.1 loopOnce@InputReader方法
InputReader的loopOnce方法如下:
void InputReader::loopOnce() {
int32_t oldGeneration;
int32_t timeoutMillis;
bool inputDevicesChanged = false;
Vector<InputDeviceInfo> inputDevices;
{ // acquire lock
AutoMutex _l(mLock);
//省略部分代码,这部分代码用于获取时间等操作。
......
} // release lock
//获取event数量
size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
{ // acquire lock
AutoMutex _l(mLock);
mReaderIsAliveCondition.broadcast();
if (count) {//如果有event,那么调用processEventsLocked方法进行处理。
processEventsLocked(mEventBuffer, count);
}
//省略部分代码
......
if (oldGeneration != mGeneration) {
inputDevicesChanged = true;
getInputDevicesLocked(inputDevices);
}
} // release lock
// Send out a message that the describes the changed input devices.
if (inputDevicesChanged) {
mPolicy->notifyInputDevicesChanged(inputDevices);
}
//下面这句代码用于通知Listener InputDispatcher,InputDispatcher的notifyKey/notifyMotion方法会被调用。
// Flush queued events out to the listener.
// This must happen outside of the lock because the listener could potentially call
// back into the InputReader's methods, such as getScanCodeState, or become blocked
// on another thread similarly waiting to acquire the InputReader lock thereby
// resulting in a deadlock. This situation is actually quite plausible because the
// listener is actually the input dispatcher, which calls into the window manager,
// which occasionally calls into the input reader.
mQueuedListener->flush();
}
InputReader的loopOnce方法会从EventHub中获取Event数量,如果有event需要处理,那么processEventsLocked方法会被调用,代码如下:
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
for (const RawEvent* rawEvent = rawEvents; count;) {
int32_t type = rawEvent->type;
size_t batchSize = 1;
if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {//普通的输入event
int32_t deviceId = rawEvent->deviceId;
while (batchSize < count) {
if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
|| rawEvent[batchSize].deviceId != deviceId) {
break;
}
batchSize += 1;
}
#if DEBUG_RAW_EVENTS
ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
#endif
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
} else {//输入设备相关的event
switch (rawEvent->type) {
case EventHubInterface::DEVICE_ADDED:
addDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::DEVICE_REMOVED:
removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
break;
case EventHubInterface::FINISHED_DEVICE_SCAN:
handleConfigurationChangedLocked(rawEvent->when);
break;
default:
ALOG_ASSERT(false); // can't happen
break;
}
}
count -= batchSize;
rawEvent += batchSize;
}
}
processEventsLocked中if{}else{}将处理逻辑分成了两大部分:
一部分处理普通的输入event。
另外一部分处理输入设备相关的event(输入设备增加、移除和scan)。
InputReader会先收到输入设备相关的event,并添加/移除对应的设备对象InputDevice,然后将后续收到的输入event交给InputDevice处理。
当 InputReader收到新输入设备增加的"EventHubInterface::DEVICE_ADDED"后,会调用addDeviceLocked方法,此方法会调用createDeviceLocked方法构造InputDevice对象,并根据收到的设备属性为InputDevice对象构造InputMapper,有KeyboardInputMapper、SingleTouchInputMapper等,这些InputMapper对象会被存放到InputDevice对象的成员集合mMappers中保存; 新得到的InputDevice对象会放到InputReader的成员集合mDevices中保存(Map集合,deviceId做Key)。
当 InputReader收到普通输入事件后会调用processEventsForDeviceLocked方法进行处理,该方法会遍历mDevices,调用InputDevice的process方法处理event。 InputDevice的process方法会遍历mMappers,调用InputMapper的process方法处理event。不同InputMapper的process的方法处理逻辑不同,但是正常情况都会调用到Listener的notifyKey/notifyMotion方法,即InputDispatcher的notifyKey/notifyMotion 方法(InputDispatcher间接继承了InputListenerInterface类,构造InputReader对象时,InputDispatcher对象会作为一个参数(Listener)传入InputReader中)。 notifyKey/notifyMotion方法会调用enqueueInboundEventLocked方法将event加入到mInboundQueue队列中,如果有需要还会唤醒Looper; 另外nofifyKey方法在将event放进队列之前会调用NativeInputManager的interceptKeyBeforeQueueing方法,notifyMotion会调用NativeInputManager的interceptMotionBeforeQueueing方法。
2.2. dispatchOnce@InputDispatcher方法
InputDispatcher的dispatchOnce方法:
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{ // acquire lock
AutoMutex _l(mLock);
mDispatcherIsAliveCondition.broadcast();
// Run a dispatch loop if there are no pending commands.
// The dispatch loop might enqueue commands to run afterwards.
if (!haveCommandsLocked()) {
dispatchOnceInnerLocked(&nextWakeupTime);
}
// Run all pending commands if there are any.
// If any commands were run then force the next poll to wake up immediately.
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
} // release lock
// Wait for callback or timeout or wake. (make sure we round up, not down)
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
mLooper->pollOnce(timeoutMillis);
}
- 如果没有pending commands,那么就调用dispatchOnceInnerLocked方法,该方法最终通过InputPublisher调用InputChannel的sendMessage方法。
- 如果有pending commands,那么会先运行commands;这些commands是什么呢?
pending commands存放在mCommandQueue中,其中元素是CommandEntry类型的指针,指向的都是函数地址,这样就可以通过指针调用函数,比如doInterceptKeyBeforeDispatchingLockedInterruptible函数就是以这种方式调用的。如果command被执行,那么Loop中的pollOnce方法会立即被调用。
InputDispatcher派发过程中调用的主要方法如下:
dispatchOnceInnerLocked
|-->dispatchMotionLocked/dispatchKeyLocked
|-->dispatchEventLocked
|-->prepareDispatchCycleLocked
|-->enqueueDispatchEntriesLocked
|-->startDispatchCycleLocked
但是这些event要派发给那些Window呢,这是InputDispatcher要解决的问题?
新窗口添加的时候,addWindow@WindowManagerService.java方法会构建WindowState对象,后者会构建InputWindowHandle对象,这个对象会通过openInputChannel@WindowState方法注册到InputDispatcher中,如下:
void openInputChannel(InputChannel outInputChannel) {
......
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
mInputChannel = inputChannels[0];
mClientChannel = inputChannels[1];
mInputWindowHandle.inputChannel = inputChannels[0];
......
mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
}
另外,addWindow@WindowManagerService.java方法会调用InputMonitor.java的updateInputWindowsLw方法,后者会调用"mUpdateInputForAllWindowsConsumer.updateInputWindows(inDrag)";
mUpdateInputForAllWindowsConsumer是UpdateInputForAllWindowsConsumer类型的对象,updateInputWindows方法会调用InputManagerService的setInputWindows方法,如下:
private void updateInputWindows(boolean inDrag) {
//...省略...
// Send windows to native code.
mService.mInputManager.setInputWindows(mInputWindowHandles, mFocusedInputWindowHandle);
clearInputWindowHandlesLw();
}
setInputWindows@InputManagerService方法会调用nativeSetInputWindows方法将InputWindowHandle添加到InputDispatcher中。InputDispatcher在派发input event的时候可以通过InputWindowHandle找到对应的Connection和InputChannel,然后通过Connection内的InputPublisher进行派发。
InputDispatcher中的InputWindowHandle很多,InputDispatcher如何确定哪些InputWindowHandle适合处理要进行派发的event?
- 对于Key 事件,findFocusedWindowTargetsLocked(…)@@InputDispatcher方法用来确认InputWindowHandle,该方法只是用来确认"mFocusedWindowHandle"是否可以接收事件。“mFocusedWindowHandle"的值是在setInputWindows@InputDispatcher方法中更新的,也就是当有新window添加时,InputDispatcher会遍历所有的Handler,将持有焦点Window的Handle赋值给"mFocusedWindowHandle”。
- 对于Motion 事件,findTouchedWindowTargetsLocked@InputDispatcher方法用来确认InputWindowHandler, 该方法将down和up event分开处理。不过用来查找合适的InputWindowHandler的是findTouchedWindowAtLocked@InputDispatcher方法,筛选InputWindowHandler的关键点:
- 1)是否可见
- 2)是否可以触摸,是否可以有焦点
- 3)Window的可触摸区域是否包含触摸点。
3.InputChannel
InputChannel 对应了一个文件描述符,这个文件描述符被另外一个进程用来向window中发送input event。InputChannel.java是java侧的类,实现了Parcelable类,这样它就可以被发送到接收input event的进程。
input event的派发过程可以用下面的图简单表示:
图中的"Dispatcher Thread"是派发进程,运行在system_server进程中; "UI Thread"是某一进程的主线程,也可能是system_server的主线程。这两个线程需要通过一对socket来通信,图中底端用类似管道的方式表示了这对socket。"socket[0]"和"socket[1]"都有对应的文件描述符,“inputChannel”对象会持有对应的描述符,这样通过inputChannel便可以找到文件描述符,然后发送消息。
橙色 的线表示发送input event的过程; 蓝色的线表示对input event处理结果的反馈。
下面以WindowManagerService注册InputChannel的过程为例说说InputChannel的创建和注册。
第一幅图的第二部分展示的是WindowManagerService创建时注册InputChannel的过程,现在我们把它单拉出来:
SystemServer启动的时候会用InputManagerService对象为参数调用main@WindowManagerService方法创建WindowManagerService对象; 在WindowManagerService的构造函数中InputManagerService对象的monitorInput@InputManagerService方法会被调用。monitorInput@InputManagerService方法会调用
InputChannel.java中的静态方法openInputChannelPair来创建新的"input channel pair",此方法会调用nativeOpenInputChannelPair。nativeOpenInputChannelPair对应的是android_view_inputchannel.cpp中的android_view_InputChannel_nativeOpenInputChannelPair方法,此方法会调用InputChannel(定义在InputTransport.cpp中)的openInputChannelPair方法创建两个InputChannel对象,然后利用这两个对象创建两个NativeInputChannel对象以及两个Inputchannel.java对象。
下面是Native层InputChannel的openInputChannelPair方法:
status_t InputChannel::openInputChannelPair(const std::string& name,
sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel) {
int sockets[2];
//socketpair创建一对socket,并将文件描述符存到数组socket中。
//可以将这对socket类比成管道,不同的是这对socket可同时收发。
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets)) {
status_t result = -errno;
ALOGE("channel '%s' ~ Could not create socket pair. errno=%d",
name.c_str(), errno);
outServerChannel.clear();
outClientChannel.clear();
return result;
}
int bufferSize = SOCKET_BUFFER_SIZE;
setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
std::string serverChannelName = name;
serverChannelName += " (server)";
outServerChannel = new InputChannel(serverChannelName, sockets[0]);//使用socket[0]中的文件描述符为参数创建InputChannel对象。
std::string clientChannelName = name;
clientChannelName += " (client)";
outClientChannel = new InputChannel(clientChannelName, sockets[1]);//使用socket[1]中的文件描述符为参数创建InputChannel对象。
return OK;
}
openInputChannel@WindowState方法调用openInputChannelPair获取到"inputchannel pair"之后,会调用"inputChannel[1]"的transferTo方法,将"inputChannel[1]"中指向NativeInputChannel对象的"mPtr"设置到调用者生成的InputChannel.java对象之中,即addWindow@WindowManagerService方法的InputChannel参数引用的对象之中。
下面是openInputChannel@WindowState方法:
void openInputChannel(InputChannel outInputChannel) {
if (mInputChannel != null) {
throw new IllegalStateException("Window already has an input channel.");
}
String name = getName();
InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
mInputChannel = inputChannels[0];
mClientChannel = inputChannels[1];
mInputWindowHandle.inputChannel = inputChannels[0];
if (outInputChannel != null) {
mClientChannel.transferTo(outInputChannel);//调用inputChannel[1]对象的transfer方法。
mClientChannel.dispose();
mClientChannel = null;
} else {
// If the window died visible, we setup a dummy input channel, so that taps
// can still detected by input monitor channel, and we can relaunch the app.
// Create dummy event receiver that simply reports all events as handled.
mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
}
mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);//注册inputChannel[0]
}
这个方法除了将"inputChannel[1]" “转换”为InputChannel.java对象之外,还将"inputChannel[0]"保存到InputWindowHandle,并注册到InputManagerService中。registerInputChannel@InputManagerService方法会调用nativeRegisterInputChannel方法。
这个native调用对应的是com_android_server_InputManagerService.java中的nativeRegisterInputChannel方法,下面是该方法的代码:
static void nativeRegisterInputChannel(JNIEnv* env, jclass /* clazz */,
jlong ptr, jobject inputChannelObj, jobject inputWindowHandleObj, jboolean monitor) {
NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);//找到NativeInputManager对象
sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
inputChannelObj);//找到Native层的InputChannel对象。
if (inputChannel == NULL) {
throwInputChannelNotInitialized(env);
return;
}
sp<InputWindowHandle> inputWindowHandle =
android_server_InputWindowHandle_getHandle(env, inputWindowHandleObj);//找到Native层的InputWindowHandler对象。
status_t status = im->registerInputChannel(
env, inputChannel, inputWindowHandle, monitor);//注册InputChannel,注意参数是"inputChannel"和"inputWindowHandle"
if (status) {
std::string message;
message += StringPrintf("Failed to register input channel. status=%d", status);
jniThrowRuntimeException(env, message.c_str());
return;
}
if (! monitor) {
android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
handleInputChannelDisposed, im);
}
}
该方法的第一个参数(第三个开始算)是"ptr",是InputManagerService对象中保存的NativeInputManager对象的地址; 第二个参数是InputChannel对象; 第三个参数是InputWindowHandler对象。首先根据这些参数,找到对应的Native对象,然后调用NativeInputManager的registerInputChannel方法,这个方法会调用到InputDispatcher的registerInputChannel方法, 下面是该方法的部分代码:
status_t InputDispatcher::registerInputChannel(const sp<InputChannel>& inputChannel,
const sp<InputWindowHandle>& inputWindowHandle, bool monitor) {
#if DEBUG_REGISTRATION
ALOGD("channel '%s' ~ registerInputChannel - monitor=%s", inputChannel->getName().c_str(),
toString(monitor));
#endif
{ // acquire lock
AutoMutex _l(mLock);
//省略......
sp<Connection> connection = new Connection(inputChannel, inputWindowHandle, monitor);
int fd = inputChannel->getFd();
mConnectionsByFd.add(fd, connection);
if (monitor) {
mMonitoringChannels.push(inputChannel);
}
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, handleReceiveCallback, this);
} // release lock
// Wake the looper because some connections have changed.
mLooper->wake();
return OK;
}
上面的方法会用InputChannel和InputWindowHandler做参数构造Connection对象,然后用InputChannel中的文件描述符"Fd"做key,将新得到的connection对象存到"mConnectionsByFd"中。另外,调用"mLooper->addFd(…)"将InputChannel的文件描述符"Fd"加入到了Looper中,当然 这个Looper是线程"InputDispatcher"的Looper。
"inputChannel[0]"已经注册了,那么"inputChannel[1]“呢?
我们知道"inputChannel[1]” 会“转换”为InputChannel.java对象,WindowManagerService拿到这个对象之后构造了PointerEventDispatcher对象:
if(mInputManager != null) {
final InputChannel inputChannel = mInputManager.monitorInput(TAG_WM);
mPointerEventDispatcher = inputChannel != null
? new PointerEventDispatcher(inputChannel) : null;
} else {
mPointerEventDispatcher = null;
}
PointerEventDispatcher继承了InputEventReceiver,后者的构造函数里面调用了nativeInit方法:
public InputEventReceiver(InputChannel inputChannel, Looper looper) {
if (inputChannel == null) {
throw new IllegalArgumentException("inputChannel must not be null");
}
if (looper == null) {
throw new IllegalArgumentException("looper must not be null");
}
mInputChannel = inputChannel;
mMessageQueue = looper.getQueue();
mReceiverPtr = nativeInit(new WeakReference<InputEventReceiver>(this),
inputChannel, mMessageQueue);
mCloseGuard.open("dispose");
}
nativeInit方法的第二个参数是InputChannel对象,第三个参数是当前线程的MessageQueue对象。
nativeInit方法对应的JNI方法是android_view_InputEventReceiver中的nativeInit方法。
JNI层的nativeInit方法会找到InputChannel和MessageQueue对象对应的Native对象,然后用两个Native对象做为参数构造NativeInputEventReceiver对象,然后调用新对象的initialize方法,下面看看initialize方法:
status_t NativeInputEventReceiver::initialize() {
setFdEvents(ALOOPER_EVENT_INPUT);
return OK;
}
void NativeInputEventReceiver::setFdEvents(int events) {
if (mFdEvents != events) {
mFdEvents = events;
int fd = mInputConsumer.getChannel()->getFd();
if (events) {
mMessageQueue->getLooper()->addFd(fd, 0, events, this, NULL);//CallBack设置为this
} else {
mMessageQueue->getLooper()->removeFd(fd);
}
}
}
initialize方法很简单,只是调用了setFdEvents方法,而后者会将InputChannel的文件描述符"fd"添加到Looper中,这个Looper是主线程的Looper,而且将CallBack设置为自身。
当有输入事件的时候,Looper的pollInner方法会通过下面的code调用NativeInputEventReceiver的handleEvent方法。
int callbackResult = response.request.callback->handleEvent(fd, events, data);
handleEvent方法会调用consumeEvents,后者会调用到Java层InputEventReceiver的dispatchInputEvent方法,这是一个private方法,不能被重写,但它调用的onInputEvent是个public方法,子类可以重写这个方法来实现自己的派发逻辑来消耗输入事件,这样就完成了输入事件的派发。
4. Input event 的拦截
由第一部分我们知道com_android_server_input_InputManagerService.cpp中的nativeInit(…)方法会构造NativeInputManager对象,而后者会构造InputManager对象,InputManager相关的文件是InputManager.h和InputManager.cpp。InputManager.h文件中对InputManager的定义如下:
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();
}
后两个参数中,第一个是"readerPolicy",第二个是"dispatcherPolicy"。 NativeInputManager继承了InputReaderPolicyInterface和InputDispatcherPolicyInterface,在构造InputManager对象时传入的后两个参数都是this,如下:
mInputManager = new InputManager(eventHub, this, this);
InputManager.cpp的构造函数会用NativeInputManager作为参数构造InputReader对象和InputDispatcher对象,代码如下:
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();
}
InputDispatcher在派发input event之前会调用"mPolicy",即NativeInputManager的相关方法对event进行拦截,如果event被拦截掉,那么就不会进行后续派发,否则正常派发。
拦截分两类:
- 进入派发对了执行进行拦截
- 从派发队列中派发时进行拦截(只有key event)
相关的拦截流程这里就不细写了,简单列举一下相关的文件以及主要方法:
1.Motion event相关:
//进入队列之前的拦截
notifyMotion@InputDispatcher
|-->interceptMotionBeforeQueueing@NativeInputManager
|-->interceptMotionBeforeQueueingNonInteractive@InputManagerService
|-->interceptMotionBeforeQueueingNonInteractive@InputMonitor
|-->interceptMotionBeforeQueueingNonInteractive@PhoneWindowManager
2.Key event相关:
//进入队列之前的拦截
notifyKey/injectInputEvent@InputDispatcher
|-->interceptKeyBeforeQueueing@NativeInputManager
|-->interceptKeyBeforeQueueing@InputManagerService
|-->interceptKeyBeforeQueueing@InputMonitor
|-->interceptKeyBeforeQueueing@PhoneWindowManager
//从派发队列中派发时的拦截(只有key event)
dispatchKeyLocked@InputDispatcher
|-->doInterceptKeyBeforeDispatchingLockedInterruptible@InputDispatcher
|-->interceptKeyBeforeDispatching@NativeInputManager
|-->interceptKeyBeforeDispatching@InputManagerService
|-->interceptKeyBeforeDispatching@InputMonitor
|-->interceptKeyBeforeDispatching@PhoneWindowManager