本文只讨论一次成功的按键事件分发的流程。
// 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);
// ...
// policyFlags 来自于按键映射的文件
uint32_t policyFlags = args.policyFlags;
// flags 目前为 AKEY_EVENT_FLAG_FROM_SYSTEM
int32_t flags = args.flags;
// meta 按键的状态
int32_t metaState = args.metaState;
constexpr int32_t repeatCount = 0;
// ...
// 来自输入设备的按键事件,都是受信任的
policyFlags |= POLICY_FLAG_TRUSTED;
int32_t keyCode = args.keyCode;
// ...
// 这里创建 KeyEvent 保存按键数据,是为了发送给策略处理
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();
// 如果上层设置了 InputFilter,这里要把事件先发送给 InputFilter 处理
if (shouldSendKeyToInputFilterLocked(args)) {
// ...
}
// 创建 KeyEvent 保存按键事件数据,之后由 InputDispatcher 线程处理
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);
// KeyEvent 加入到 inbound queue 中
needWake = enqueueInboundEventLocked(std::move(newEntry));
mLock.unlock();
} // release lock
// 如果有必要,唤醒 InputDispatcher 线程,处理按键事件
if (needWake) {
mLooper->wake();
}
}
InputDisptcher 收到按键事件后,创建 KeyEvent 包装按键事件数据,先交给策略处理,看看其是否要截断。如果策略截断了,会在 policyFlags 中添加 POLICY_FLAG_PASS_TO_USER 标志位,InputDispatcher 会在之后的分发事件流程中,丢弃这个按键事件。截断策略是一个大课题,后面会专用一篇文章详细分析。
然后,创建 KeyEntry 包装按键事件数据,并保存到 InputDispatcher 的 inbound queue 中,随后唤醒线程处理按键事件,如下
// 通过线程循环分发按键事件
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
// ...
}
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();
}
// ...
}
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) {
// ...
}
// ...
switch (mPendingEvent->type) {
// ...
case EventEntry::Type::KEY: {
std::shared_ptr<KeyEntry> keyEntry = std::static_pointer_cast<KeyEntry>(mPendingEvent);
// ...
// 分发按键事件
done = dispatchKeyLocked(currentTime, keyEntry, &dropReason, nextWakeupTime);
break;
}
// ...
}
// ...
}
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<KeyEntry> entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
// ...
// 策略要求稍后再分发按键事件
if (entry->interceptKeyResult == KeyEntry::InterceptKeyResult::TRY_AGAIN_LATER) {
if (currentTime < entry->interceptKeyWakeupTime) {
if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
*nextWakeupTime = entry->interceptKeyWakeupTime;
}
return false; // wait until next wakeup
}
entry->interceptKeyResult = KeyEntry::InterceptKeyResult::UNKNOWN;
entry->interceptKeyWakeupTime = 0;
}
if (entry->interceptKeyResult == KeyEntry::InterceptKeyResult::UNKNOWN) {
if (entry->policyFlags & POLICY_FLAG_PASS_TO_USER) { // 策略不截断按键事件
sp<IBinder> focusedWindowToken =
mFocusResolver.getFocusedWindowToken(getTargetDisplayId(*entry));
// 1. 通过一个命令,询问策略如何分发
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) {
if (*dropReason == DropReason::NOT_DROPPED) {
// 丢弃的原因是策略要求丢弃
*dropReason = DropReason::POLICY;
}
}
// 如果有丢弃的原因,那么事件不再分发
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;
// 2. 寻找焦点窗口
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;
// 3.为焦点窗口,创建 InputTarget,保存到 inputTargets 中
addWindowTargetLocked(focusedWindow,
InputTarget::Flags::FOREGROUND | InputTarget::Flags::DISPATCH_AS_IS,
/*pointerIds=*/{}, getDownTime(*entry), inputTargets);
// global monitor 也需要创建 InputTarget,并加入到 inputTargets
addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
// 4. 把按键事件分发给每一个 InputTarget
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
InputDispatcher 通过一个线程循环,从 inbound queue 中取出一个按键事件,首先询问策略该如何分发。这个分发策略主要是为了实现组合按键的功能,例如,电源键 + 音量下键的组合键,可以实现截图。后面我将一篇文章详细分析分发策略如何实现组合按键功能,这里我们假设分发的按键事件,不属于任何一个组合键功能,因此策略会 InputDispatcher 继续后面的分发流程。
既然策略允许继续分发按键事件,那么需要为按键事件寻找一个焦点窗口,如下
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 获取焦点窗口 token
// 从数据结构 mFocusedWindowTokenByDisplay,根据 display id 获取焦点窗口 token
sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(displayId);
// 根据焦点窗口 token 获取焦点窗口
return getWindowHandleLocked(focusedToken, displayId);
}
sp<WindowInfoHandle> InputDispatcher::getWindowHandleLocked(const sp<IBinder>& windowHandleToken,
int displayId) const {
if (windowHandleToken == nullptr) {
return nullptr;
}
// 根据屏幕下所有窗口的 token,匹配出焦点窗口
for (const sp<WindowInfoHandle>& windowHandle : getWindowHandlesLocked(displayId)) {
if (windowHandle->getToken() == windowHandleToken) {
return windowHandle;
}
}
return nullptr;
}
焦点窗口,涉及 WMS,SurfaceFlinger 模块的知识,读者可以参考我写的 WMS 焦点窗口的文章,这里不详细讲解焦点窗口到底怎么来的。
当找到焦点窗口后,会给焦点窗口创建 InputTarget,并保存到集合 inputTargets 中,这个过程就不分析了。然后把按键事件分发给所有的 InputTargets ,如下
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
std::shared_ptr<EventEntry> eventEntry,
const std::vector<InputTarget>& inputTargets) {
// ...
for (const InputTarget& inputTarget : inputTargets) {
// 从 mConnectionsByToken 获取 input channel connection
std::shared_ptr<Connection> connection =
getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
if (connection != nullptr) {
// 准备分发循环
prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
} else {
}
}
}
WMS add window 时,如果窗口能够接受事件,那么 WMS 会通知 InputDispatcher 创建一个 InputChannel ,InputDispatcher 会创建 Connection 保存这个 InputChannel,然后 Connection 保存到 mConnectionsByToken 中,如下
Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
// ...
std::unique_ptr<InputChannel> serverChannel;
std::unique_ptr<InputChannel> clientChannel;
// 创建 socketpair,两端分别保存到 serverChannel 和 clientChannel
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
// ...
{ // acquire lock
std::scoped_lock _l(mLock);
const sp<IBinder>& token = serverChannel->getConnectionToken();
int fd = serverChannel->getFd();
// 为 socketpair 的服务端窗口 Connection
std::shared_ptr<Connection> connection =
std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/false,
mIdGenerator);
// ...
// mConnectionsByToken 根据 input channel token 保存 Connection
mConnectionsByToken.emplace(token, connection);
std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
this, std::placeholders::_1, token);
// 利用 Looper 机制,监听 socketpair 服务端 fd
// 当窗口处理完事件,通过 socketpair 的 client 端反馈处理结果,socketpair 的服务端会收到数据
// 然后会回调 InputDispatcher::handleReceiveCallback()
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback),
nullptr);
} // release lock
// Wake the looper because some connections have changed.
mLooper->wake();
// socketpair 的 client 端,返回给上层窗口
return clientChannel;
}
因此,这里可以根据窗口的 input channel token 获取到 Connection。然后,通过这个 Connection,把按键事件分发给窗口,如下
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget) {
// trace
if (ATRACE_ENABLED()) {
std::string message =
StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, id=0x%" PRIx32 ")",
connection->getInputChannelName().c_str(), eventEntry->id);
ATRACE_NAME(message.c_str());
}
// ALOG
if (DEBUG_DISPATCH_CYCLE) {
ALOGD("channel '%s' ~ prepareDispatchCycle - flags=%s, "
"globalScaleFactor=%f, pointerIds=%s %s",
connection->getInputChannelName().c_str(), inputTarget.flags.string().c_str(),
inputTarget.globalScaleFactor, bitsetToString(inputTarget.pointerIds).c_str(),
inputTarget.getPointerInfoString().c_str());
}
// ...
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) {
// trace
if (ATRACE_ENABLED()) {
std::string message =
StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, id=0x%" PRIx32 ")",
connection->getInputChannelName().c_str(), eventEntry->id);
ATRACE_NAME(message.c_str());
}
// ...
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 the outbound queue was previously empty, start the dispatch cycle going.
if (wasEmpty && !connection->outboundQueue.empty()) {
// 开启分发循环
startDispatchCycleLocked(currentTime, connection);
}
}
在开启分发循环之前,首先对分发循环进行准备,主要是为了 DispatchEntry,并保存到 Connection::outboundQueue 中,如下
void InputDispatcher::enqueueDispatchEntryLocked(const std::shared_ptr<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget,
ftl::Flags<InputTarget::Flags> dispatchMode) {
// trace
if (ATRACE_ENABLED()) {
std::string message = StringPrintf("enqueueDispatchEntry(inputChannel=%s, dispatchMode=%s)",
connection->getInputChannelName().c_str(),
dispatchMode.string().c_str());
ATRACE_NAME(message.c_str());
}
// 按键事件的 InputTarget::Flags 为 InputTarget::Flags::FOREGROUND | InputTarget::Flags::DISPATCH_AS_IS
ftl::Flags<InputTarget::Flags> inputTargetFlags = inputTarget.flags;
// 检测按键事件的 InputTarget::Flags 是否包含 dispatchMode
if (!inputTargetFlags.any(dispatchMode)) {
return;
}
// inputTargetFlags 清理 DISPATCH_MASK,仅保存 dispatchMode
inputTargetFlags.clear(InputTarget::DISPATCH_MASK);
inputTargetFlags |= dispatchMode;
// 创建 DispatchEntry,之后会保存到 Connection::outboundQueue 中
std::unique_ptr<DispatchEntry> dispatchEntry =
createDispatchEntry(inputTarget, eventEntry, inputTargetFlags);
EventEntry& newEntry = *(dispatchEntry->eventEntry);
switch (newEntry.type) {
case EventEntry::Type::KEY: {
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(newEntry);
// 更新 DisplayEntry 数据
dispatchEntry->resolvedEventId = keyEntry.id;
dispatchEntry->resolvedAction = keyEntry.action;
dispatchEntry->resolvedFlags = keyEntry.flags;
// ...
break;
}
// ...
}
// Remember that we are waiting for this dispatch to complete.
// 检测事件的 InputTargets::Flags 中是否包含 InputTarget::Flags::FOREGROUND
// 按键事件恰好就满足
if (dispatchEntry->hasForegroundTarget()) {
// DispatchEntry::injectionState->pendingForegroundDispatches + 1
incrementPendingForegroundDispatches(newEntry);
}
// Enqueue the dispatch entry.
// 创建的 DispatchEntry 保存到 Connection::outboundQueue
connection->outboundQueue.push_back(dispatchEntry.release());
// trace 记录 Connection 的 outbound queue length
traceOutboundQueueLength(*connection);
}
Connection 的 outbound queue 中已经保存了要分发的事件,现在正式开启分发循环,把 outbound queue 中的事件分发给窗口,如下
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 的 outbound queue 中的按键事件,分发给窗口,如下
status_t InputPublisher::publishKeyEvent(uint32_t seq, int32_t eventId, int32_t deviceId,
int32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action,
int32_t flags, int32_t keyCode, int32_t scanCode,
int32_t metaState, int32_t repeatCount, nsecs_t downTime,
nsecs_t eventTime) {
// trace 记录了输入系统发送给窗口的 key event 数据
if (ATRACE_ENABLED()) {
std::string message =
StringPrintf("publishKeyEvent(inputChannel=%s, action=%s, keyCode=%s)",
mChannel->getName().c_str(), KeyEvent::actionToString(action),
KeyEvent::getLabel(keyCode));
ATRACE_NAME(message.c_str());
}
// log 也可以记录发送给窗口的 key evnet 数据
ALOGD_IF(debugTransportPublisher(),
"channel '%s' publisher ~ %s: seq=%u, id=%d, deviceId=%d, source=%s, "
"action=%s, flags=0x%x, keyCode=%s, scanCode=%d, metaState=0x%x, repeatCount=%d,"
"downTime=%" PRId64 ", eventTime=%" PRId64,
mChannel->getName().c_str(), __func__, seq, eventId, deviceId,
inputEventSourceToString(source).c_str(), KeyEvent::actionToString(action), flags,
KeyEvent::getLabel(keyCode), scanCode, metaState, repeatCount, downTime, eventTime);
if (!seq) {
ALOGE("Attempted to publish a key event with sequence number 0.");
return BAD_VALUE;
}
InputMessage msg;
msg.header.type = InputMessage::Type::KEY;
msg.header.seq = seq;
msg.body.key.eventId = eventId;
msg.body.key.deviceId = deviceId;
msg.body.key.source = source;
msg.body.key.displayId = displayId;
msg.body.key.hmac = std::move(hmac);
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;
return mChannel->sendMessage(&msg);
}
然后用 wait queue 保存已经分发的按键事件,是为了等待窗口返回按键事件的处理结果。这就是一个循环!
在创建 input channel 时,把 socketpair 的 client 发送给窗口,而 InputDispatcher 利用 Looper 机制(实际利用 epoll)监听 socketpair 的 server 端,如下
Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
// ...
std::unique_ptr<InputChannel> serverChannel;
std::unique_ptr<InputChannel> clientChannel;
// 创建 socketpair,两端分别保存到 serverChannel 和 clientChannel
status_t result = InputChannel::openInputChannelPair(name, serverChannel, clientChannel);
// ...
{ // acquire lock
std::scoped_lock _l(mLock);
const sp<IBinder>& token = serverChannel->getConnectionToken();
int fd = serverChannel->getFd();
// 为 socketpair 的服务端窗口 Connection
std::shared_ptr<Connection> connection =
std::make_shared<Connection>(std::move(serverChannel), /*monitor=*/false,
mIdGenerator);
// ...
// mConnectionsByToken 根据 input channel token 保存 Connection
mConnectionsByToken.emplace(token, connection);
std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
this, std::placeholders::_1, token);
// 利用 Looper 机制,监听 socketpair 服务端 fd
// 当窗口处理完事件,通过 socketpair 的 client 端反馈处理结果,socketpair 的服务端会收到数据
// 然后会回调 InputDispatcher::handleReceiveCallback()
mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, sp<LooperEventCallback>::make(callback),
nullptr);
} // release lock
// Wake the looper because some connections have changed.
mLooper->wake();
// socketpair 的 client 端,返回给上层窗口
return clientChannel;
}
当窗口反馈事件的处理结果时,会执行如下回调
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();
// 4.返回的结果不 OK,代表有错误码,例如,数据已经读完,没有数据可以读了
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();
// 5. 数据已经读完,直接返回1
if (status == WOULD_BLOCK) {
return 1;
}
}
// ...
} else {
}
// ...
}
可能很多人有疑问,为何要通过一个无线循环读取窗口反馈的结果? 因为这就是 socketpair 的特性,需要不断的读取所有数据,直到没有数据为止,我们才知道数据读完了,如下
// frameworks/native/libs/input/InputTransport.cpp
android::base::Result<InputPublisher::ConsumerResponse> InputPublisher::receiveConsumerResponse() {
InputMessage msg;
// 通过一个无线循环,不断从 socketpair 的 servier 端读取数据
status_t result = mChannel->receiveMessage(&msg);
// 有错误码,直接返回
if (result) {
ALOGD_IF(debugTransportPublisher(), "channel '%s' publisher ~ %s: %s",
mChannel->getName().c_str(), __func__, strerror(result));
return android::base::Error(result);
}
// 走到这里,代表读到正常的数据
if (msg.header.type == InputMessage::Type::FINISHED) {
ALOGD_IF(debugTransportPublisher(),
"channel '%s' publisher ~ %s: finished: seq=%u, handled=%s",
mChannel->getName().c_str(), __func__, msg.header.seq,
toString(msg.body.finished.handled));
return Finished{
.seq = msg.header.seq,
.handled = msg.body.finished.handled,
.consumeTime = msg.body.finished.consumeTime,
};
}
// TODO: 这是什么数据?
if (msg.header.type == InputMessage::Type::TIMELINE) {
ALOGD_IF(debugTransportPublisher(), "channel '%s' publisher ~ %s: timeline: id=%d",
mChannel->getName().c_str(), __func__, msg.body.timeline.eventId);
return Timeline{
.inputEventId = msg.body.timeline.eventId,
.graphicsTimeline = msg.body.timeline.graphicsTimeline,
};
}
// 这里表示,读取的不是期望的数据,代表未知异常,表示窗口反馈的数据格式有问题
ALOGE("channel '%s' publisher ~ Received unexpected %s message from consumer",
mChannel->getName().c_str(), ftl::enum_string(msg.header.type).c_str());
return android::base::Error(UNKNOWN_ERROR);
}
status_t InputChannel::receiveMessage(InputMessage* msg) {
ssize_t nRead;
// 从 socketpair 中读取 InputMessage 大小的数据
do {
nRead = ::recv(getFd(), msg, sizeof(InputMessage), MSG_DONTWAIT);
} while (nRead == -1 && errno == EINTR);
// 没有从 socketpair 读取到数据
if (nRead < 0) {
int error = errno;
ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ receive message failed, errno=%d",
mName.c_str(), errno);
// 表示没有数据可读
if (error == EAGAIN || error == EWOULDBLOCK) {
return WOULD_BLOCK;
}
// EPIPE 管道异常,ENOTCONN 代表 socket 未连接,ECONNREFUSED 代表连接被拒绝
if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED) {
return DEAD_OBJECT;
}
return -error;
}
// 代表 client 端关闭了
if (nRead == 0) { // check for EOF
ALOGD_IF(DEBUG_CHANNEL_MESSAGES,
"channel '%s' ~ receive message failed because peer was closed", mName.c_str());
return DEAD_OBJECT;
}
if (!msg->isValid(nRead)) {
ALOGE("channel '%s' ~ received invalid message of size %zd", mName.c_str(), nRead);
return BAD_VALUE;
}
ALOGD_IF(DEBUG_CHANNEL_MESSAGES, "channel '%s' ~ received message of type %s", mName.c_str(),
ftl::enum_string(msg->header.type).c_str());
return OK;
}
当成功读取到窗口返回的数据后,就要结束此次分发循环,如下
void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
const std::shared_ptr<Connection>& connection,
uint32_t seq, bool handled, nsecs_t consumeTime) {
// 结束分发循环的 log
if (DEBUG_DISPATCH_CYCLE) {
ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s",
connection->getInputChannelName().c_str(), seq, toString(handled));
}
// 创建一个命令
auto command = [this, currentTime, connection, seq, handled, consumeTime]() REQUIRES(mLock) {
doDispatchCycleFinishedCommand(currentTime, connection, seq, handled, consumeTime);
};
// 命令被保存到 mCommandQueue 集合中
postCommandLocked(std::move(command));
}
结束分发循环只是创建一个命令并保存到集合中,然后执行第3步,执行命令,如下
bool InputDispatcher::runCommandsLockedInterruptable() {
if (mCommandQueue.empty()) {
return false;
}
do {
// 从 mCommandQueue 取出命令,并执行
auto command = std::move(mCommandQueue.front());
mCommandQueue.pop_front();
// Commands are run with the lock held, but may release and re-acquire the lock from within.
command();
} while (!mCommandQueue.empty());
return true;
}
结束分发循环的命令,主要就是从 Connection 的 wait queue 中移除按键事件,如下
void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime,
const std::shared_ptr<Connection>& connection,
uint32_t seq, bool handled,
nsecs_t consumeTime) {
// ...
// 从 Connection 的 wait queue 中获取事件
dispatchEntryIt = connection->findWaitQueueEntry(seq);
if (dispatchEntryIt != connection->waitQueue.end()) {
dispatchEntry = *dispatchEntryIt;
// 从 Connection 的 wait queue 中移除事件
connection->waitQueue.erase(dispatchEntryIt);
// ...
}
// 如果 Connection 的 outbound queue 中还有按键事件,那么再次启动分发循环,进行分发
startDispatchCycleLocked(now(), connection);
}
自此,Connection 的按键事件分发循环就成功结束了,也代表 InputDispatcher 一次按键事件的分发完成。