概述

源码分析

1
2
3
4
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();
return true;
}

时间分发流程图

dispatchOnce

threadLoop()函数只是调用了InputDispatcher的dispatchOnce()函数,这个函数的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;
{
// 加锁
AutoMutex _l(mLock);
mDispatcherIsAliveCondition.broadcast();
if (! haveCommandsLocked()) { // 如果mCommandQueue队列不为NULL
dispatchOnceInnerLocked(&nextWakeupTime); // 分发消息
}
if (runCommandsLockedInterruptible()) {
nextWakeupTime = LONG_LONG_MIN;
}
}
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
mLooper->pollOnce(timeoutMillis);
}

dispatchOnce()调用dispatchOnceInnerLocked()函数来分发消息,dispatchOnceInnerLocked()函数又调用了dispatchOnceInnerLocked()函数,这个函数的代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
......
mPendingEvent = mInboundQueue.dequeueAtHead(); // 从队列中取出消息
......
switch (mPendingEvent->type) {
case EventEntry::TYPE_KEY: {
......
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason,
nextWakeupTime); // 继续处理
break;
}
}

dispatchOnceInnerLocked()函数从mInboundQueue队列中把输入消息取出来后,根据消息的类型,调用不同的函数处理,其中Key Event调用dispatchKeyLocked()函数处理。从dispatchKey Locked()函数开始,一直到消息传递出去,还要调用InputDispatcher类的多个函数,如图16.3所示。

Event传递的中间过程就不分析了,我们直接看图16.3中的最后一个函数startDispatchCycle Locked(),它的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection) {
......
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
status = connection->inputPublisher.publishKeyEvent(dispatchEntry->seq,
keyEntry->deviceId, keyEntry->source,
dispatchEntry->resolvedAction, dispatchEntry->resolvedFlags,
keyEntry->keyCode, keyEntry->scanCode,
keyEntry->metaState, keyEntry->repeatCount, keyEntry->downTime,
keyEntry->eventTime);
break;
}
......
}

startDispatchCycleLocked()函数会根据Event的类型来分别处理,我们保留了处理key消息的分支。这个分支调用了connection对象的inputPublisher变量的publishKeyEvent()函数。

这个connection对象从哪里来的呢?回答这个问题我们要看看InputManagerService的registerInputChannel()方法,下一节我们会介绍这个方法从哪里调用的。方法的代码如下:

1
2
3
4
5
public void registerInputChannel(InputChannel inputChannel,
InputWindowHandle inputWindowHandle) {
...... // 错误处理
nativeRegisterInputChannel(mPtr, inputChannel, inputWindowHandle, false);
}

registerInputChannel()函数调用了nativeRegisterInputChannel()方法,其对应的本地函数如下:

1
2
3
4
5
6
7
8
static void nativeRegisterInputChannel(JNIEnv* env, jclass clazz, ......) {
sp<InputChannel> inputChannel = android_view_InputChannel_getInputChannel(env,
inputChannelObj);
......
status_t status = im->registerInputChannel(
env, inputChannel, inputWindowHandle, monitor);
......
}

归纳总结

InputDispatcher在拿到 InputReader获取的事件之后,对事件进行包装后,寻找并分发到目标窗口;