原创内容,转载请注明出处,多谢配合。
上一篇分析了InputReader获取事件过程,最终InputReader将input event放到InputDispatcher的mInboundQueue后唤醒InputDispacher。本篇就来分析下InputDispatcher的事件分发过程。
一、InputDispatcher初始化
frameworks/native/services/inputflinger/InputManager.cpp
InputManager::InputManager(
const sp& eventHub,
const sp& readerPolicy,
const sp& dispatcherPolicy) {
mDispatcher = new InputDispatcher(dispatcherPolicy);//创建InputDispatcher
...
}
frameworks/native/services/inputflinger/InputDispatcher.cpp
InputDispatcher::InputDispatcher(const sp& policy) ... : {
mLooper = new Looper(false);//这里InputDispatcher新建了一个Looper
...
}
InputDispatcherThread::InputDispatcherThread(const sp& dispatcher) :
Thread(/*canCallJava*/ true), mDispatcher(dispatcher) {
}
bool InputDispatcherThread::threadLoop() {
mDispatcher->dispatchOnce();//开始处理分发
return true;
}
二、InputDispatcher运行
frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_MAX;register_android_server_InputManager
...
//优先处理Command
if (!haveCommandsLocked()) {
//这里处理input event
dispatchOnceInnerLocked(&nextWakeupTime);
}
if (runCommandsLockedInterruptible()) {
// 处理完Command,立即唤醒loop来处理input event
nextWakeupTime = LONG_LONG_MIN;
}
...
nsecs_t currentTime = now();
int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
// 这里进入epoll_wait,
// InputReader可以用Looper::wake()唤醒InputDispacher
// 窗口也可以通过回执event唤醒Looper
mLooper->pollOnce(timeoutMillis);
}
InputDispatcher处理的事件主要分两种:一种是command命令(Command是mPolicy处理的具体事务,这个mPolicy就是NativeInputManager,最终对应的上层是InputManagerService),一种是input event。每次dispatchOnce,会优先执行前者。
这里Command一些列回调命令保存在mCommandQueue中,主要包括:
doPokeUserActivityLockedInterruptible
doNotifyANRLockedInterruptible
doInterceptKeyBeforeDispatchingLockedInterruptible
doDispatchCycleFinishedLockedInterruptible
doNotifyInputChannelBrokenLockedInterruptible
doNotifyConfigurationChangedInterruptible
再看dispatchOnceInnerLocked处理input event部分:
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
nsecs_t currentTime = now();
...
//当事件分发的时间点距离该事件加入mInboundQueue的时间超过500ms,则认为app切换过期,即
//isAppSwitchDue=true;
bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
...
if (!mPendingEvent) {
return;
}
} else {
//事件是从InboundQueue头部取的
mPendingEvent = mInboundQueue.dequeueAtHead();
traceInboundQueueLengthLocked();
}
// Poke user activity for this event.
if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
pokeUserActivityLocked(mPendingEvent);
}
// Get ready to dispatch the event.
resetANRTimeoutsLocked(); //重置ANR 超时时间
}
// Now we have an event to dispatch.
// All events are eventually dequeued and processed this way, even if we intend to drop them.
ALOG_ASSERT(mPendingEvent != NULL);
bool done = false;
DropReason dropReason = DROP_REASON_NOT_DROPPED;
if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
dropReason = DROP_REASON_POLICY;
} else if (!mDispatchEnabled) {
dropReason = DROP_REASON_DISABLED;
}
if (mNextUnblockedEvent == mPendingEvent) {
mNextUnblockedEvent = NULL;
}
switch (mPendingEvent->type) {
…
//这里有很多类型的EventEntry type 重点看看key
case EventEntry::TYPE_KEY: {
KeyEntry* typedEntry = static_cast(mPendingEvent);
if (isAppSwitchDue) {
if (isAppSwitchKeyEventLocked(typedEntry)) {
resetPendingAppSwitchLocked(true);
isAppSwitchDue = false;
} else if (dropReason == DROP_REASON_NOT_DROPPED) {
dropReason = DROP_REASON_APP_SWITCH;
}
}
if (dropReason == DROP_REASON_NOT_DROPPED
&& isStaleEventLocked(currentTime, typedEntry)) {
dropReason = DROP_REASON_STALE;
}
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
//分发事件处理
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
...
}
//分发操作完成
if (done) {
if (dropReason != DROP_REASON_NOT_DROPPED) {
dropInboundEventLocked(mPendingEvent, dropReason);//丢弃事件
}
mLastDropReason = dropReason;
releasePendingEventLocked();//释放当前正在处理的事件
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
这个过程简单看就是从mInboundQueue头部取出事件交给dispatchKeyLocked执行分发处理,并重置ANR时间,以及执行完之后根据done来做一些收尾操作。
接下来看看dispatchKeyLocked:
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, KeyEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
...
//寻找焦点窗口inputTargets
int32_t injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, inputTargets, nextWakeupTime);
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}
setInjectionResultLocked(entry, injectionResult);
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
return true;
}
addMonitoringTargetsLocked(inputTargets);
//只有injectionResult为true才会继续往下执行分发操作
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
这个方法核心内容是执行findFocusedWindowTargetsLocked寻找焦点窗口inputTargets,但是在此之前会有若干判断有可能直接return 。
int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
const EventEntry* entry, Vector& inputTargets, nsecs_t* nextWakeupTime) {
int32_t injectionResult;
String8 reason;
...
// Check permissions.
if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
goto Failed;
}
// 检测窗口是否为更多的输入操作而准备就绪
reason = checkWindowReadyForMoreInputLocked(currentTime,
mFocusedWindowHandle, entry, "focused");
if (!reason.isEmpty()) { //如果满足,handleTargetsNotReadyLocked会触发anr判断
injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, reason.string());
goto Unresponsive;
}
// Success! Output targets.
injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
//添加目标窗口
addWindowTargetLocked(mFocusedWindowHandle,
InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
inputTargets);
// Done.
Failed:
Unresponsive:
nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
updateDispatchStatisticsLocked(currentTime, entry,
injectionResult, timeSpentWaitingForApplication);
#if DEBUG_FOCUS
ALOGD("findFocusedWindow finished: injectionResult=%d, "
"timeSpentWaitingForApplication=%0.1fms",
injectionResult, timeSpentWaitingForApplication / 1000000.0);
#endif
return injectionResult;
}
这里主要就是添加目标窗口,与目前窗口建立InputChannel连接
void InputDispatcher::addWindowTargetLocked(const sp& windowHandle,
int32_t targetFlags, BitSet32 pointerIds, Vector& inputTargets) {
inputTargets.push();
const InputWindowInfo* windowInfo = windowHandle->getInfo();
InputTarget& target = inputTargets.editTop();
target.inputChannel = windowInfo->inputChannel;
target.flags = targetFlags;
target.xOffset = - windowInfo->frameLeft;
target.yOffset = - windowInfo->frameTop;
target.scaleFactor = windowInfo->scaleFactor;
target.pointerIds = pointerIds;
}
将当前聚焦窗口mFocusedWindowHandle的inputChannel传递到inputTargets。
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
EventEntry* eventEntry, const Vector& inputTargets) {
#if DEBUG_DISPATCH_CYCLE
ALOGD("dispatchEventToCurrentInputTargets");
#endif
ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
//调用到Java层的PowerManagerService.java中的userActivityFromNative()方法. 这也是PMS中唯一的native call方法
pokeUserActivityLocked(eventEntry);
for (size_t i = 0; i < inputTargets.size(); i++) {
const InputTarget& inputTarget = inputTargets.itemAt(i);
//根据inputChannel的fd从mConnectionsByFd队列中查询目标connection.
ssize_t connectionIndex = getConnectionIndexLocked(inputTarget.inputChannel);
if (connectionIndex >= 0) {
sp connection = mConnectionsByFd.valueAt(connectionIndex);
//找到目标连接
prepareDispatchCycleLocked(currentTime, connection, eventEntry, &inputTarget);
} else {
#if DEBUG_FOCUS
ALOGD("Dropping event delivery to target with channel '%s' because it "
"is no longer registered with the input dispatcher.",
inputTarget.inputChannel->getName().string());
#endif
}
}
}
该方法主要功能是将eventEntry发送到目标inputTargets。
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
...
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime, const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget) {
bool wasEmpty = connection->outboundQueue.isEmpty();
...
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget, InputTarget::FLAG_DISPATCH_AS_IS);
...
if (wasEmpty && !connection->outboundQueue.isEmpty()) {
startDispatchCycleLocked(currentTime, connection);
}
}
void InputDispatcher::enqueueDispatchEntryLocked(const sp& connection, EventEntry* eventEntry, const InputTarget* inputTarget, int32_t dispatchMode) {
int32_t inputTargetFlags = inputTarget->flags;
if (!(inputTargetFlags & dispatchMode)) {
return;
}
//这里又转了一次数据结构,生成新的事件, 加入connection的outbound队列。
DispatchEntry* dispatchEntry = new DispatchEntry(eventEntry, inputTargetFlags, inputTarget->xOffset, inputTarget->yOffset, inputTarget->scaleFactor);
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast(eventEntry);
dispatchEntry->resolvedAction = keyEntry->action;
dispatchEntry->resolvedFlags = keyEntry->flags;
break;
}
//添加到outboundQueue队尾
connection->outboundQueue.enqueueAtTail(dispatchEntry);
}
执行到这里,其实等于由做了一次搬运的工作,将InputDispatcher中mInboundQueue中的eventEntry事件取出后, 找到目标window后,将eventEntry封装dispatchEntry加入到connection的outbound队列。
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime, const sp& connection) {
while (connection->status == Connection::STATUS_NORMAL && !connection->outboundQueue.isEmpty()) {
DispatchEntry* dispatchEntry = connection->outboundQueue.head;
dispatchEntry->deliveryTime = currentTime;
// Publish the event.
status_t status;
EventEntry* eventEntry = dispatchEntry->eventEntry;
switch (eventEntry->type) {
case EventEntry::TYPE_KEY: {
KeyEntry* keyEntry = static_cast(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;
}
...
}
// Re-enqueue the event on the wait queue.
connection->outboundQueue.dequeue(dispatchEntry);
connection->waitQueue.enqueueAtTail(dispatchEntry);
}
通过InputPublisher将DispatchEntry发送给窗口,再将DispatchEntry从outboundQueue移到waitQueue里。该通信过程是异步的,当窗口处理完事件后会通过handleReceiveCallback()回调函数通知InputDispatcher。
status_t InputPublisher::publishKeyEvent(...) {
if (!seq) {
return BAD_VALUE;
}
InputMessage msg;
msg.header.type = InputMessage::TYPE_KEY;
msg.body.key.seq = seq;
msg.body.key.deviceId = deviceId;
msg.body.key.source = source;
msg.body.key.action = action;
msg.body.key.flags = flags;
msg.body.key.keyCode = keyCode;
msg.body.key.scanCode = scanCode;
msg.body.key.metaState = metaState;
msg.body.key.repeatCount = repeatCount;
msg.body.key.downTime = downTime;
msg.body.key.eventTime = eventTime;
//通过InputChannel来发送消息
return mChannel->sendMessage(&msg);
}
publishKeyEvent调用InputChanel的SendMessage(),SendMessage()再动用socket的send()函数,将打包好的Message发送给窗口。
最后看看handleReceiveCallback回调:
frameworks/native/services/inputflinger/InputDispatcher.cpp
int InputDispatcher::handleReceiveCallback(int fd, int events, void* data) {
InputDispatcher* d = static_cast(data);
ssize_t connectionIndex = d->mConnectionsByFd.indexOfKey(fd);
sp connection = d->mConnectionsByFd.valueAt(connectionIndex);
if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
nsecs_t currentTime = now();
bool gotOne = false;
status_t status;
for (;;) {
uint32_t seq;
bool handled;
//接收窗口处理完成的消息
status = connection->inputPublisher.receiveFinishedSignal(&seq, &handled);
if (status) { // 读完socket即返回WOULD_BLOCK
break;
}
// 这里post一个command
d->finishDispatchCycleLocked(currentTime, connection, seq, handled);
gotOne = true;
}
if (gotOne) {
// 这里执行command的handle
d->runCommandsLockedInterruptible();
if (status == WOULD_BLOCK) { // 正常流程走这里
return 1;
}
}
}
// 这里是socket链接出现异常的情况
d->unregisterInputChannelLocked(connection->inputChannel, notify);
return 0; // remove the callback
}
再看看post command
frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime, const sp& connection, uint32_t seq, bool handled) {
...
onDispatchCycleFinishedLocked(currentTime, connection, seq, handled);
}
void InputDispatcher::onDispatchCycleFinishedLocked(nsecs_t currentTime, const sp& connection, uint32_t seq, bool handled) {
CommandEntry* commandEntry = postCommandLocked( & InputDispatcher::doDispatchCycleFinishedLockedInterruptible);
commandEntry->connection = connection;
commandEntry->eventTime = currentTime;
commandEntry->seq = seq;
commandEntry->handled = handled;
}
frameworks/native/services/inputflinger/InputDispatcher.cpp
void InputDispatcher::doDispatchCycleFinishedLockedInterruptible(CommandEntry* commandEntry) {
sp connection = commandEntry->connection;
nsecs_t finishTime = commandEntry->eventTime;
uint32_t seq = commandEntry->seq;
bool handled = commandEntry->handled;
// Handle post-event policy actions.
DispatchEntry* dispatchEntry = connection->findWaitQueueEntry(seq);
if (dispatchEntry) {
nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
// 如果一个dispatch周期超过2秒,将打印警告信息
if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT /* 2sec */) {
String8 msg;
msg.appendFormat("Window '%s' spent %0.1fms processing the last input event: ", connection->getWindowName(), eventDuration * 0.000001f);
dispatchEntry->eventEntry->appendDescription(msg);
ALOGI("%s", msg.string());
}
bool restartEvent;
if (dispatchEntry->eventEntry->type == EventEntry::TYPE_KEY) {
KeyEntry* keyEntry = static_cast(dispatchEntry->eventEntry);
// 主要是对unhandle key的policy,这里不做分析
restartEvent = afterKeyEventLockedInterruptible(connection, dispatchEntry, keyEntry, handled);
} else if (dispatchEntry->eventEntry->type == EventEntry::TYPE_MOTION) {
MotionEntry* motionEntry = static_cast(dispatchEntry->eventEntry);
restartEvent = afterMotionEventLockedInterruptible(connection, dispatchEntry, motionEntry, handled);
} else {
restartEvent = false;
}
if (dispatchEntry == connection->findWaitQueueEntry(seq)) {
// 从waitQueue中将当前entry移除
connection->waitQueue.dequeue(dispatchEntry);
traceWaitQueueLengthLocked(connection);
if (restartEvent && connection->status == Connection::STATUS_NORMAL) {
connection->outboundQueue.enqueueAtHead(dispatchEntry);
traceOutboundQueueLengthLocked(connection);
} else {
// 释放内存
releaseDispatchEntryLocked(dispatchEntry);
}
}
// 如果当前connection的outBoundQueque里还有Event,则继续下一轮的Dispatch周期
startDispatchCycleLocked(now(), connection);
}
}
从waitQueue中将当前DispatchEntry移除,如果当前connection的outBoundQueque里还有EventEntry,则继续下一轮的Dispatch周期。
最后放上整体流程图和时序图:
简单总结下InputDispatcher分发事件流程:
1)InputReader唤醒InputDispacher执行分发处理。
InputReader主要是将EventHub中的input_event转换成具体的EventEntry,并添加到InputDispatcher的mInboundQueue里,然后唤醒InputDispacher线程。InputDispacher线程有自己的Looper,被唤醒后会执行dispatchOnce方法,InputDispatcher处理的事件主要分两种:一种是command命令(Command是mPolicy处理的具体事务,这个mPolicy就是NativeInputManager,最终对应的上层是InputManagerService),一种是input event。每次dispatchOnce,会优先执行前者。
2)InboundQueue队头取出事件,匹配焦点窗口,传递eventEntry。
从mInboundQueue队列头部取出一个事件,寻找与之匹配的焦点窗口的inputTargets,这里先通过InputWindowHandle找到InputWindowInfo,再找到InputChannel,最终找到Connection,每个焦点窗口在InputDispacher里都有一个对应的Connection,通过这个Connection可以跟InputDispacher通信。然后会将eventEntry转为DispatchEntry放入Connection的outboundQueue。通过InputPublisher通过 InputChannel::sendMessage将DispatchEntry发送给窗口,再将dispatchEntry从outboundQueue移到waitQueue里。该通信过程是异步的,也就是说当InputDispatcher将Input事件发送给目标窗口后会立即返回,并不会等待窗口的处理结果。
3)窗口处理完又将处理结果返回给InputDispatcher
当窗口处理完事件后,会通过handleReceiveCallback()回调函数通知InputDispatcher。回调主要是post一个command,从waitQueue中将当前DispatchEntry移除,如果当前connection的outBoundQueque里还有DispatchEntry,则继续下一轮的Dispatch周期。
到这里InputDispatcher分发事件过程就介绍完了。
下一篇文章:
Android Input(五)-InputChannel通信