本文只讨论一次成功的按键事件分发的流程。
InputDispatcher 处理按键事件
// InputDispatcher.cpp
void InputDispatcher::notifyKey(const NotifyKeyArgs& args) {
ALOGD_IF(debugInboundEventDetails(),
"notifyKey - id=%" PRIx32 ", eventTime=%" PRId64
", deviceId=%d, source=%s, displayId=%" PRId32
"policyFlags=0x%x, action=%s, flags=0x%x, keyCode=%s, scanCode=0x%x, metaState=0x%x, "
"downTime=%" PRId64,
args.id, args.eventTime, args.deviceId, inputEventSourceToString(args.source).c_str(),
args.displayId, args.policyFlags, KeyEvent::actionToString(args.action), args.flags,
KeyEvent::getLabel(args.keyCode), args.scanCode, args.metaState, args.downTime);
Result<void> keyCheck = validateKeyEvent(args.action);
if (!keyCheck.ok()) {
LOG(ERROR) << "invalid key event: " << keyCheck.error();
return;
}
// policyFlags 来自于按键映射的文件
uint32_t policyFlags = args.policyFlags;
// flags 目前为 AKEY_EVENT_FLAG_FROM_SYSTEM
int32_t flags = args.flags;
// meta 按键的状态
int32_t metaState = args.metaState;
// InputDispatcher tracks and generates key repeats on behalf of
// whatever notifies it, so repeatCount should always be set to 0
constexpr int32_t repeatCount = 0;
if ((policyFlags & POLICY_FLAG_VIRTUAL) || (flags & AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY)) {
policyFlags |= POLICY_FLAG_VIRTUAL;
flags |= AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
}
if (policyFlags & POLICY_FLAG_FUNCTION) {
metaState |= AMETA_FUNCTION_ON;
}
// 来自输入设备的按键事件,都是受信任的
policyFlags |= POLICY_FLAG_TRUSTED;
int32_t keyCode = args.keyCode;
// 根据 meta state 转换 key code
accelerateMetaShortcuts(args.deviceId, args.action, keyCode, metaState);
KeyEvent event;
event.initialize(args.id, args.deviceId, args.source, args.displayId, INVALID_HMAC, args.action,
flags, keyCode, args.scanCode, metaState, repeatCount, args.downTime,
args.eventTime);
android::base::Timer t;
// 按键事件加入到队列前,先让策略尝试截断处理
mPolicy.interceptKeyBeforeQueueing(event, /*byref*/ policyFlags);
if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
std::to_string(t.duration().count()).c_str());
}
bool needWake = false;
{ // acquire lock
mLock.lock();
if (shouldSendKeyToInputFilterLocked(args)) {
mLock.unlock();
policyFlags |= POLICY_FLAG_FILTERED;
if (!mPolicy.filterInputEvent(event, policyFlags)) {
return; // event was consumed by the filter
}
mLock.lock();
}
std::unique_ptr<KeyEntry> newEntry =
std::make_unique<KeyEntry>(args.id, args.eventTime, args.deviceId, args.source,
args.displayId, policyFlags, args.action, flags, keyCode,
args.scanCode, metaState, repeatCount, args.downTime);
// 按键事件加入到 inbound queue 中
needWake = enqueueInboundEventLocked(std::move(newEntry));
mLock.unlock();
} // release lock
// 如果有必要,唤醒 InputDispatcher 线程,处理按键事件
if (needWake) {
mLooper->wake();
}
}
当 InputDispatcher 收到按键事件时,首先是询问策略,如果策略允许分发事件,那么会在 policyFlags 中添加 POLICY_FLAG_PASS_TO_USER ,表示策略允许分发按键事件给窗口,否则表示策略不允许分发事件。
策略不在本文的讨论范围。
策略处理了之后,按键事件加入到 InputDispatcher 的 inbound queue 中,然后唤醒 InputDispatcher 线程开始分发按键事件
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LLONG_MAX;
{ // acquire lock
std::scoped_lock _l(mLock);
mDispatcherIsAlive.notify_all();
// Run a dispatch loop if there are no pending commands.
// The dispatch loop might enqueue commands to run afterwards.
// 如果没有命令,就执行一次分发循环
// 何为循环,就是是把事件发送给窗口,窗口反馈处理事件的结果
if (!haveCommandsLocked()) {
dispatchOnceInnerLocked(&nextWakeupTime);
}
// ...
}
} // release lock
// ...
}
假设此时没有命令需要执行,那么会先执行一次分发循环(dispatch loop)
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
// ...
if (!mPendingEvent) {
if (mInboundQueue.empty()) {
// ...
} else {
// Inbound queue has at least one entry.
// 从 inbound queue 队头取出事件
mPendingEvent = mInboundQueue.front();
mInboundQueue.pop_front();
traceInboundQueueLengthLocked();
}
// ...
}
// 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 != nullptr);
bool done = false;
DropReason dropReason = DropReason::NOT_DROPPED;
if (!(mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER)) {
// 策略不允许分发
dropReason = DropReason::POLICY;
} else if (!mDispatchEnabled) {
dropReason = DropReason::DISABLED;
}
if (mNextUnblockedEvent == mPendingEvent) {
mNextUnblockedEvent = nullptr;
}
switch (mPendingEvent->type) {
// ...
case EventEntry::Type::KEY: {
std::shared_ptr<KeyEntry> keyEntry = std::static_pointer_cast<KeyEntry>(mPendingEvent);
if (isAppSwitchDue) {
if (isAppSwitchKeyEvent(*keyEntry)) {
resetPendingAppSwitchLocked(true);
isAppSwitchDue = false;
} else if (dropReason == DropReason::NOT_DROPPED) {
dropReason = DropReason::APP_SWITCH;
}
}
if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *keyEntry)) {
dropReason = DropReason::STALE;
}
if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DropReason::BLOCKED;
}
// 分发按键事件
done = dispatchKeyLocked(currentTime, keyEntry, &dropReason, nextWakeupTime);
break;
}
// ...
}
// ...
}
从 InputDispatcher inbound queue 中取出按键事件,然后开始分发
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<KeyEntry> entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
// ...
// 1. 再次循环策略
if (entry->interceptKeyResult == KeyEntry::InterceptKeyResult::TRY_AGAIN_LATER) {
// ...
}
if (entry->interceptKeyResult == KeyEntry::InterceptKeyResult::UNKNOWN) {
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) {
sp<IBinder> focusedWindowToken =
mFocusResolver.getFocusedWindowToken(getTargetDisplayId(*entry));
// 通过一个命令再次询问策略
auto command = [this, focusedWindowToken, entry]() REQUIRES(mLock) {
doInterceptKeyBeforeDispatchingCommand(focusedWindowToken, *entry);
};
postCommandLocked(std::move(command));
// Poke user activity for keys not passed to user
pokeUserActivityLocked(*entry);
// 此次分发循环结束
return false; // wait for the command to run
} else {
entry->interceptKeyResult = KeyEntry::InterceptKeyResult::CONTINUE;
}
} else if (entry->interceptKeyResult == KeyEntry::InterceptKeyResult::SKIP) {
// ...
}
// 2. 如果有丢弃的原因,那么事件不再分发
if (*dropReason != DropReason::NOT_DROPPED) {
setInjectionResult(*entry,
*dropReason == DropReason::POLICY ? InputEventInjectionResult::SUCCEEDED
: InputEventInjectionResult::FAILED);
mReporter->reportDroppedKey(entry->id);
// Poke user activity for undispatched keys
pokeUserActivityLocked(*entry);
return true;
}
// Identify targets.
InputEventInjectionResult injectionResult;
// 3. 寻找焦点窗口
sp<WindowInfoHandle> focusedWindow =
findFocusedWindowTargetLocked(currentTime, *entry, nextWakeupTime,
/*byref*/ injectionResult);
if (injectionResult == InputEventInjectionResult::PENDING) {
return false;
}
setInjectionResult(*entry, injectionResult);
if (injectionResult != InputEventInjectionResult::SUCCEEDED) {
return true;
}
LOG_ALWAYS_FATAL_IF(focusedWindow == nullptr);
// inputTargets 保存的事件要分发的目标
std::vector<InputTarget> inputTargets;
// 4.为焦点窗口,创建 InputTarget,保存到 inputTargets 中
addWindowTargetLocked(focusedWindow,
InputTarget::Flags::FOREGROUND | InputTarget::Flags::DISPATCH_AS_IS,
/*pointerIds=*/{}, getDownTime(*entry), inputTargets);
// TODO: 暂不讨论 global monitor
addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
// 5.继续分发事件
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
按键事件,在分发之前,会通过一个命令,再次询问策略,而此次询问策略,一般是为了实现组合按键的功能,本文不深入讨论。
假设此次策略仍然允许按键事件分发,那么会为这个按键事件寻找焦点窗口
sp<WindowInfoHandle> InputDispatcher::findFocusedWindowTargetLocked(
nsecs_t currentTime, const EventEntry& entry, nsecs_t* nextWakeupTime,
InputEventInjectionResult& outInjectionResult) {
std::string reason;
outInjectionResult = InputEventInjectionResult::FAILED; // Default result
int32_t displayId = getTargetDisplayId(entry);
// 获取屏幕的焦点窗口
sp<WindowInfoHandle> focusedWindowHandle = getFocusedWindowHandleLocked(displayId);
// ...
outInjectionResult = InputEventInjectionResult::SUCCEEDED;
return focusedWindowHandle;
}
sp<WindowInfoHandle> InputDispatcher::getFocusedWindowHandleLocked(int displayId) const {
// 先从 FocusResolver 获取焦点窗口
sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(displayId);
// 验证这个焦点窗口是否存在 diaplay 下
// 因此焦点窗口可能过期了,但是屏幕下的所有窗口,是会实时更新的
return getWindowHandleLocked(focusedToken, displayId);
}
sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(const sp<IBinder>& windowHandleToken,
int displayId) const {
if (windowHandleToken == nullptr) {
return nullptr;
}
// 根据 token 匹配 display 下的窗口
for (const sp<WindowInfoHandle>& windowHandle : getWindowHandlesLocked(displayId)) {
if (windowHandle->getToken() == windowHandleToken) {
return windowHandle;
}
}
return nullptr;
}
焦点窗口是从 FocusResolver 获取的
// FocusResolver.cpp
sp<IBinder> FocusResolver::getFocusedWindowToken(int32_t displayId) const {
// 这个焦点窗口,是从 WMS 设置下来的,或者 FocusResolver 根据屏幕下的所有窗口解析出来的
auto it = mFocusedWindowTokenByDisplay.find(displayId);
return it != mFocusedWindowTokenByDisplay.end() ? it->second.second : nullptr;
}
FocusResolver 中通过一个数据结构,保存了焦点窗口。那么这个焦点窗口哪里来的呢? 有两种情况,一种是 WMS 设置下来的,另外一种情况是 FocusResolver 自己解析出来。本文不深入探讨这个焦点窗口的话题。
当找到焦点窗口后,会继续分发按键事件
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
std::shared_ptr<EventEntry> eventEntry,
const std::vector<InputTarget>& inputTargets) {
// ...
for (const InputTarget& inputTarget : inputTargets) {
// 根据 InputChannel token 获取 Connection
std::shared_ptr<Connection> connection =
getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
if (connection != nullptr) {
// 准备分发循环
prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
} else {
}
}
}
当 ViewRootImpl 向 WMS add window 时,如果窗口能够接受事件,那么 WMS 会通知 InputDispather 创建一个 InputChannel ,InputDispather 会创建 Connection 保存这个 InputChannel,然后 Connection 保存到 mConnectionsByToken 中。
因此,这里可以通过 InputChannel token 获取到 Connection,然后准备分发循环
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget) {
// ...
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget) {
// ...
const bool wasEmpty = connection->outboundQueue.empty();
// Enqueue dispatch entries for the requested modes.
// ...
// 向 connection->outboundQueue 保存按键事件
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::Flags::DISPATCH_AS_IS);
// ...
// 启动分发循环
if (wasEmpty && !connection->outboundQueue.empty()) {
startDispatchCycleLocked(currentTime, connection);
}
}
void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget,
ftl::Flags<InputTarget::Flags> dispatchMode) {
// ...
inputTargetFlags.clear(InputTarget::DISPATCH_MASK);
// 保存 InputTarget::Flags::DISPATCH_AS_I
inputTargetFlags |= dispatchMode;
// 1.创建 DispatchEntry
std::unique_ptr<DispatchEntry> dispatchEntry =
createDispatchEntry(inputTarget, eventEntry, inputTargetFlags);
EventEntry& newEntry = *(dispatchEntry->eventEntry);
switch (newEntry.type) {
case EventEntry::Type::KEY: {
// 2.向 DispatchEntry 填充数据
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(newEntry);
dispatchEntry->resolvedEventId = keyEntry.id;
dispatchEntry->resolvedAction = keyEntry.action;
dispatchEntry->resolvedFlags = keyEntry.flags;
// ...
break;
}
// ...
}
// Remember that we are waiting for this dispatch to complete.
if (dispatchEntry->hasForegroundTarget()) {
incrementPendingForegroundDispatches(newEntry);
}
// 3. DispatchEntry 保存到 connection->outboundQueue
connection->outboundQueue.push_back(dispatchEntry.release());
traceOutboundQueueLength(*connection);
}
所谓的准备分发循环,其实就是创建 dispatchEntry,保存按键事件信息,然后 dispatchEntry 保存到 connection->outboundQueue 中。最后,真正开始分发循环
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection) {
// ...
// 通过一个 while 循环,把 onnection->outboundQueue 中保存的事件全部发送出去
while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) {
// 1.从 onnection->outboundQueue 获取事件
DispatchEntry* dispatchEntry = connection->outboundQueue.front();
// ...
status_t status;
const EventEntry& eventEntry = *(dispatchEntry->eventEntry);
switch (eventEntry.type) {
case EventEntry::Type::KEY: {
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(eventEntry);
// ...
// 2. 发布事件给窗口
status = connection->inputPublisher
.publishKeyEvent(dispatchEntry->seq,
dispatchEntry->resolvedEventId, keyEntry.deviceId,
keyEntry.source, keyEntry.displayId,
std::move(hmac), dispatchEntry->resolvedAction,
dispatchEntry->resolvedFlags, keyEntry.keyCode,
keyEntry.scanCode, keyEntry.metaState,
keyEntry.repeatCount, keyEntry.downTime,
keyEntry.eventTime);
break;
}
// ...
}
// ...
// 3. 把已经发布的事件从 onnection->outboundQueue 中移除
connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
connection->outboundQueue.end(),
dispatchEntry));
// 4. 需要等待窗口反馈事件处理结果,因此需要把已经发送的事件保存到 connection->waitQueue.
connection->waitQueue.push_back(dispatchEntry);
// ...
}
}
分发循环,就是把 connection->outboundQueue 中的事件发送给窗口。但是,为了防止窗口无响应,或者响应慢,因此还需要把已经发送的事件保存到 connection->waitQueue。
至此,按键事件的分发已经完成。但是,既然分发循环,就得有来有回,当窗口处理完事件后,会反馈时间处理结果给 InpputDispatcher。 InputDispatcher 利用 Looper 机制,会收到回调
int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionToken) {
std::scoped_lock _l(mLock);
std::shared_ptr<Connection> connection = getConnectionLocked(connectionToken);
bool notify;
if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
nsecs_t currentTime = now();
bool gotOne = false;
status_t status = OK;
// 通过一个无线循环,读取所有消息
for (;;) {
// 1 获取窗口返回的结果
Result<InputPublisher::ConsumerResponse> result =
connection->inputPublisher.receiveConsumerResponse();
if (!result.ok()) {
status = result.error().code();
break;
}
if (std::holds_alternative<InputPublisher::Finished>(*result)) {
const InputPublisher::Finished& finish =
std::get<InputPublisher::Finished>(*result);
// 2 完成此次分发循环
finishDispatchCycleLocked(currentTime, connection, finish.seq, finish.handled,
finish.consumeTime);
} else if (std::holds_alternative<InputPublisher::Timeline>(*result)) {
}
gotOne = true;
}
if (gotOne) {
// 3 运行完成分发循环中保存的命令
runCommandsLockedInterruptable();
if (status == WOULD_BLOCK) {
return 1;
}
}
notify = status != DEAD_OBJECT || !connection->monitor;
if (notify) {
ALOGE("channel '%s' ~ Failed to receive finished signal. status=%s(%d)",
connection->getInputChannelName().c_str(), statusToString(status).c_str(),
status);
}
} else {
}
// TODO: 为何要移除 InputChannel 呢?
removeInputChannelLocked(connection->inputChannel->getConnectionToken(), notify);
return 0; // remove the callback
}
收到窗口的反馈后,立即完成此次分发循环
void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection,
uint32_t seq, bool handled, nsecs_t consumeTime) {
// ...
// 创建一个命令保存到 mCommandQueue 中
auto command = [this, currentTime, connection, seq, handled, consumeTime]() REQUIRES(mLock) {
doDispatchCycleFinishedCommand(currentTime, connection, seq, handled, consumeTime);
};
postCommandLocked(std::move(command));
}
完成分发循环只是保存了一个命令,而下一步就是执行这个命令
void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime,
const std::shared_ptr<Connection>& connection,
uint32_t seq, bool handled,
nsecs_t consumeTime) {
// ...
// 从 wait queue 中获取事件
dispatchEntryIt = connection->findWaitQueueEntry(seq);
if (dispatchEntryIt != connection->waitQueue.end()) {
dispatchEntry = *dispatchEntryIt;
// 从 wait queue 中移除事件
connection->waitQueue.erase(dispatchEntryIt);
// ...
}
// 如果 connection 的 outbound queu 中还有事件,那么再次启动分发循环
startDispatchCycleLocked(now(), connection);
}
完成分发循环是,事件从 connection 的 wait queue 中移除,这样就不会发生 ANR。