InputDispatcher在start() 方法中会启动一个线程,在被唤醒后会调用到dispatchOnce 方法,在该方法中,通过调用dispatchOnceInnerLocked来分发事件:
//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.java
void InputDispatcher::dispatchOnce() {
nsecs_t nextWakeupTime = LONG_LONG_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.
// 1. 如果mCommandQueue没有待处理的Command,则执行dispatchOnceInnerLocked去产生Command
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.
//2. 如果mCommandQueue队列消息不为空,则循环从中取出Command进行处理
if (runCommandsLockedInterruptable()) {
nextWakeupTime = LONG_LONG_MIN;
}
// If we are still waiting for ack on some events,
// we might have to wake up earlier to check if an app is anr'ing.
// 3.判断是否要触发ANR
const nsecs_t nextAnrCheck = processAnrsLocked();
nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
// We are about to enter an infinitely long sleep, because we have no commands or
// pending or queued events
if (nextWakeupTime == LONG_LONG_MAX) {
mDispatcherEnteredIdle.notify_all();
}
} // 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);
// 4. mLooper睡眠等待时间timeoutMillis
mLooper->pollOnce(timeoutMillis);
}
调用InputDispatcher的dispatchOnceInnerLocked方法:
//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.java
void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
nsecs_t currentTime = now();
// Reset the key repeat timer whenever normal dispatch is suspended while the
// device is in a non-interactive state. This is to ensure that we abort a key
// repeat if the device is just coming out of sleep.
// 1.当前没有在等待的事件,从mInboundQueue获取
if (!mDispatchEnabled) {
resetKeyRepeatLocked();
}
// If dispatching is frozen, do not process timeouts or try to deliver any new events.
if (mDispatchFrozen) {
if (DEBUG_FOCUS) {
ALOGD("Dispatch frozen. Waiting some more.");
}
return;
}
// Optimize latency of app switches.
// Essentially we start a short timeout when an app switch key (HOME / ENDCALL) has
// been pressed. When it expires, we preempt dispatch and drop all other pending events.
// 优化应用切换的延迟。本质上,当按下应用程序切换键(HOME)时,我们会开始一个短暂的超时。
// 当它过期时,我们会抢占调度并删除所有其他挂起的事件。
bool isAppSwitchDue = mAppSwitchDueTime <= currentTime;
if (mAppSwitchDueTime < *nextWakeupTime) {
*nextWakeupTime = mAppSwitchDueTime;
}
// Ready to start a new event.
// If we don't already have a pending event, go grab one.
// 当前没有PendingEvent(即EventEntry),则取一个
if (!mPendingEvent) {
if (mInboundQueue.empty()) {
if (isAppSwitchDue) {
// The inbound queue is empty so the app switch key we were waiting
// for will never arrive. Stop waiting for it.
resetPendingAppSwitchLocked(false);
isAppSwitchDue = false;
}
// Synthesize a key repeat if appropriate.
if (mKeyRepeatState.lastKeyEntry) {
if (currentTime >= mKeyRepeatState.nextRepeatTime) {
mPendingEvent = synthesizeKeyRepeatLocked(currentTime);
} else {
if (mKeyRepeatState.nextRepeatTime < *nextWakeupTime) {
*nextWakeupTime = mKeyRepeatState.nextRepeatTime;
}
}
}
// Nothing to do if there is no pending event.
if (!mPendingEvent) {
return;
}
} else {
// Inbound queue has at least one entry.
// mInboundQueue不为空,就从队列前面取一个PendingEvent
mPendingEvent = mInboundQueue.front();
mInboundQueue.pop_front();
traceInboundQueueLengthLocked();
}
// Poke user activity for this event.
if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
// 根据当前的event 类型,post 一个 command 到 mCommandQueue
// 最后是调用到Java层的PowerManagerService#userActivityFromNative()
pokeUserActivityLocked(*mPendingEvent);
}
}
// 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;
}
// 2.根据type分别处理
switch (mPendingEvent->type) {
case EventEntry::Type::CONFIGURATION_CHANGED: {
const ConfigurationChangedEntry& typedEntry =
static_cast<const ConfigurationChangedEntry&>(*mPendingEvent);
done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
dropReason = DropReason::NOT_DROPPED; // configuration changes are never dropped
break;
}
case EventEntry::Type::DEVICE_RESET: {
const DeviceResetEntry& typedEntry =
static_cast<const DeviceResetEntry&>(*mPendingEvent);
done = dispatchDeviceResetLocked(currentTime, typedEntry);
dropReason = DropReason::NOT_DROPPED; // device resets are never dropped
break;
}
case EventEntry::Type::FOCUS: {
std::shared_ptr<FocusEntry> typedEntry =
std::static_pointer_cast<FocusEntry>(mPendingEvent);
dispatchFocusLocked(currentTime, typedEntry);
done = true;
dropReason = DropReason::NOT_DROPPED; // focus events are never dropped
break;
}
case EventEntry::Type::TOUCH_MODE_CHANGED: {
const auto typedEntry = std::static_pointer_cast<TouchModeEntry>(mPendingEvent);
dispatchTouchModeChangeLocked(currentTime, typedEntry);
done = true;
dropReason = DropReason::NOT_DROPPED; // touch mode events are never dropped
break;
}
case EventEntry::Type::POINTER_CAPTURE_CHANGED: {
const auto typedEntry =
std::static_pointer_cast<PointerCaptureChangedEntry>(mPendingEvent);
dispatchPointerCaptureChangedLocked(currentTime, typedEntry, dropReason);
done = true;
break;
}
case EventEntry::Type::DRAG: {
std::shared_ptr<DragEntry> typedEntry =
std::static_pointer_cast<DragEntry>(mPendingEvent);
dispatchDragLocked(currentTime, typedEntry);
done = true;
break;
}
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;
}
// 最后会调用到dispatchEventLocked
done = dispatchKeyLocked(currentTime, keyEntry, &dropReason, nextWakeupTime);
break;
}
case EventEntry::Type::MOTION: {
std::shared_ptr<MotionEntry> motionEntry =
std::static_pointer_cast<MotionEntry>(mPendingEvent);
if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
dropReason = DropReason::APP_SWITCH;
}
if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) {
dropReason = DropReason::STALE;
}
if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DropReason::BLOCKED;
}
// 最后会调用到dispatchEventLocked
done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime);
break;
}
case EventEntry::Type::SENSOR: {
std::shared_ptr<SensorEntry> sensorEntry =
std::static_pointer_cast<SensorEntry>(mPendingEvent);
if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
dropReason = DropReason::APP_SWITCH;
}
// Sensor timestamps use SYSTEM_TIME_BOOTTIME time base, so we can't use
// 'currentTime' here, get SYSTEM_TIME_BOOTTIME instead.
nsecs_t bootTime = systemTime(SYSTEM_TIME_BOOTTIME);
if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(bootTime, *sensorEntry)) {
dropReason = DropReason::STALE;
}
dispatchSensorLocked(currentTime, sensorEntry, &dropReason, nextWakeupTime);
done = true;
break;
}
}
if (done) {
if (dropReason != DropReason::NOT_DROPPED) {
// 事件没有被丢弃。找到对应的原因并通知
dropInboundEventLocked(*mPendingEvent, dropReason);
}
mLastDropReason = dropReason;
// 将mPendingEvent 置为 Null,方便下次重新获取
releasePendingEventLocked();
*nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
}
}
上面方法主要处理如下:
1、根据不同的EventEntry::Type:调用不同的方法进行处理,如KEY就调用dispatchKeyLocked方法。
InputDispatcher dispatchKeyLocked
调用dispatchKeyLocked方法:
//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.java
bool InputDispatcher::dispatchKeyLocked(nsecs_t currentTime, std::shared_ptr<KeyEntry> entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
// Preprocessing.
//预处理:主要处理按键重复问题
if (!entry->dispatchInProgress) {
if (entry->repeatCount == 0 && entry->action == AKEY_EVENT_ACTION_DOWN &&
(entry->policyFlags & POLICY_FLAG_TRUSTED) &&
(!(entry->policyFlags & POLICY_FLAG_DISABLE_KEY_REPEAT))) {
if (mKeyRepeatState.lastKeyEntry &&
mKeyRepeatState.lastKeyEntry->keyCode == entry->keyCode &&
// We have seen two identical key downs in a row which indicates that the device
// driver is automatically generating key repeats itself. We take note of the
// repeat here, but we disable our own next key repeat timer since it is clear that
// we will not need to synthesize key repeats ourselves.
// 我们已经看到连续两个相同的按键,这表明设备驱动程序正在自动生成键重复。
// 我们在这里记下重复,但我们禁用了自己的下一个键重复计时器,因为很明显我们不需要自己合成键重复。
mKeyRepeatState.lastKeyEntry->deviceId == entry->deviceId) {
// 确保我们不会从其他设备获取密钥。如果按下了相同的设备 ID,则新的设备 ID 将替换当前设备 ID 以按住重复键并重置重复计数。
// 将来,当设备ID上出现KEY_UP时,请将其删除,并且不要停止当前设备上的密钥重复。
// Make sure we don't get key down from a different device. If a different
// device Id has same key pressed down, the new device Id will replace the
// current one to hold the key repeat with repeat count reset.
// In the future when got a KEY_UP on the device id, drop it and do not
// stop the key repeat on current device.
entry->repeatCount = mKeyRepeatState.lastKeyEntry->repeatCount + 1;
resetKeyRepeatLocked();
mKeyRepeatState.nextRepeatTime = LONG_LONG_MAX; // don't generate repeats ourselves
} else {
// Not a repeat. Save key down state in case we do see a repeat later.
//不是重复。保存按键down状态,以防我们稍后遇到重复。
resetKeyRepeatLocked();
mKeyRepeatState.nextRepeatTime = entry->eventTime + mConfig.keyRepeatTimeout;
}
mKeyRepeatState.lastKeyEntry = entry;
} else if (entry->action == AKEY_EVENT_ACTION_UP && mKeyRepeatState.lastKeyEntry &&
mKeyRepeatState.lastKeyEntry->deviceId != entry->deviceId) {
// The key on device 'deviceId' is still down, do not stop key repeat
if (DEBUG_INBOUND_EVENT_DETAILS) {
ALOGD("deviceId=%d got KEY_UP as stale", entry->deviceId);
}
} else if (!entry->syntheticRepeat) {
resetKeyRepeatLocked();
}
if (entry->repeatCount == 1) {
entry->flags |= AKEY_EVENT_FLAG_LONG_PRESS;
} else {
entry->flags &= ~AKEY_EVENT_FLAG_LONG_PRESS;
}
entry->dispatchInProgress = true;
logOutboundKeyDetails("dispatchKey - ", *entry);
}
// Handle case where the policy asked us to try again later last time.
// 处理policy 上次要求我们重试的情况
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER) {
if (currentTime < entry->interceptKeyWakeupTime) {
if (entry->interceptKeyWakeupTime < *nextWakeupTime) {
*nextWakeupTime = entry->interceptKeyWakeupTime;
}
return false; // wait until next wakeup
}
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_UNKNOWN;
entry->interceptKeyWakeupTime = 0;
}
// Give the policy a chance to intercept the key.
// 给policy提供拦截key的机会。
if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_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));
return false; // wait for the command to run
} else {
entry->interceptKeyResult = KeyEntry::INTERCEPT_KEY_RESULT_CONTINUE;
}
} else if (entry->interceptKeyResult == KeyEntry::INTERCEPT_KEY_RESULT_SKIP) {
if (*dropReason == DropReason::NOT_DROPPED) {
*dropReason = DropReason::POLICY;
}
}
// Clean up if dropping the event.
// 如果删除事件,则清理。
if (*dropReason != DropReason::NOT_DROPPED) {
setInjectionResult(*entry,
*dropReason == DropReason::POLICY ? InputEventInjectionResult::SUCCEEDED
: InputEventInjectionResult::FAILED);
mReporter->reportDroppedKey(entry->id);
return true;
}
// Identify targets.
// 寻找输入目标
std::vector<InputTarget> inputTargets;
InputEventInjectionResult injectionResult =
findFocusedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime);
if (injectionResult == InputEventInjectionResult::PENDING) {
return false;
}
setInjectionResult(*entry, injectionResult);
if (injectionResult != InputEventInjectionResult::SUCCEEDED) {
return true;
}
// Add monitor channels from event's or focused display.
// 从事件或焦点显示添加监视器通道。
addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
// Dispatch the key.
// 分发按键
dispatchEventLocked(currentTime, entry, inputTargets);
return true;
}
调用dispatchEventLocked方法,进行按键分发:
//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.java
void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
std::shared_ptr<EventEntry> eventEntry,
const std::vector<InputTarget>& inputTargets) {
ATRACE_CALL();
if (DEBUG_DISPATCH_CYCLE) {
ALOGD("dispatchEventToCurrentInputTargets");
}
updateInteractionTokensLocked(*eventEntry, inputTargets);
ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
pokeUserActivityLocked(*eventEntry);
for (const InputTarget& inputTarget : inputTargets) {
sp<Connection> connection =
getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
if (connection != nullptr) {
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().c_str());
}
}
}
}
dispatchEventLocked 主要是遍历inputTargets,通过prepareDispatchCycleLocked分发事件:
//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.java
void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget) {
if (ATRACE_ENABLED()) {
std::string message =
StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, id=0x%" PRIx32 ")",
connection->getInputChannelName().c_str(), eventEntry->id);
ATRACE_NAME(message.c_str());
}
if (DEBUG_DISPATCH_CYCLE) {
ALOGD("channel '%s' ~ prepareDispatchCycle - flags=0x%08x, "
"globalScaleFactor=%f, pointerIds=0x%x %s",
connection->getInputChannelName().c_str(), inputTarget.flags,
inputTarget.globalScaleFactor, inputTarget.pointerIds.value,
inputTarget.getPointerInfoString().c_str());
}
// Skip this event if the connection status is not normal.
// We don't want to enqueue additional outbound events if the connection is broken.
if (connection->status != Connection::Status::NORMAL) {
if (DEBUG_DISPATCH_CYCLE) {
ALOGD("channel '%s' ~ Dropping event because the channel status is %s",
connection->getInputChannelName().c_str(),
ftl::enum_string(connection->status).c_str());
}
return;
}
// Split a motion event if needed.
if (inputTarget.flags & InputTarget::FLAG_SPLIT) {
LOG_ALWAYS_FATAL_IF(eventEntry->type != EventEntry::Type::MOTION,
"Entry type %s should not have FLAG_SPLIT",
ftl::enum_string(eventEntry->type).c_str());
const MotionEntry& originalMotionEntry = static_cast<const MotionEntry&>(*eventEntry);
if (inputTarget.pointerIds.count() != originalMotionEntry.pointerCount) {
std::unique_ptr<MotionEntry> splitMotionEntry =
splitMotionEvent(originalMotionEntry, inputTarget.pointerIds);
if (!splitMotionEntry) {
return; // split event was dropped
}
if (splitMotionEntry->action == AMOTION_EVENT_ACTION_CANCEL) {
std::string reason = std::string("reason=pointer cancel on split window");
android_log_event_list(LOGTAG_INPUT_CANCEL)
<< connection->getInputChannelName().c_str() << reason << LOG_ID_EVENTS;
}
if (DEBUG_FOCUS) {
ALOGD("channel '%s' ~ Split motion event.",
connection->getInputChannelName().c_str());
logOutboundMotionDetails(" ", *splitMotionEntry);
}
enqueueDispatchEntriesLocked(currentTime, connection, std::move(splitMotionEntry),
inputTarget);
return;
}
}
// Not splitting. Enqueue dispatch entries for the event as is.
// 不分裂。按原样将事件的调度条目排队。
enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
}
调用enqueueDispatchEntriesLocked方法:
//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.java
void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
const sp<Connection>& connection,
std::shared_ptr<EventEntry> eventEntry,
const InputTarget& inputTarget) {
if (ATRACE_ENABLED()) {
std::string message =
StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, id=0x%" PRIx32 ")",
connection->getInputChannelName().c_str(), eventEntry->id);
ATRACE_NAME(message.c_str());
}
bool wasEmpty = connection->outboundQueue.empty();
// Enqueue dispatch entries for the requested modes.
// 1. 添加分发条目到队列连接对象 connection
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_IS);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
// If the outbound queue was previously empty, start the dispatch cycle going.
// 2. 开始分发
if (wasEmpty && !connection->outboundQueue.empty()) {
startDispatchCycleLocked(currentTime, connection);
}
}
调用InputDispatcher的startDispatchCycleLocked方法,通过connection 发布最终的事件,至此,InputDispatcher完成事件的发布,并且将发布的事件保存在connection的waitQueue中。
//frameworks/native/services/inputflinger/dispatcher/InputDispatcher.java
void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection) {
if (ATRACE_ENABLED()) {
std::string message = StringPrintf("startDispatchCycleLocked(inputChannel=%s)",
connection->getInputChannelName().c_str());
ATRACE_NAME(message.c_str());
}
if (DEBUG_DISPATCH_CYCLE) {
ALOGD("channel '%s' ~ startDispatchCycle", connection->getInputChannelName().c_str());
}
while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) {
// 从outboundQueue 队列中取出 DispatchEntry
DispatchEntry* dispatchEntry = connection->outboundQueue.front();
dispatchEntry->deliveryTime = currentTime;
const std::chrono::nanoseconds timeout = getDispatchingTimeoutLocked(connection);
dispatchEntry->timeoutTime = currentTime + timeout.count();
// Publish the event.
// 发布事件
status_t status;
const EventEntry& eventEntry = *(dispatchEntry->eventEntry);
switch (eventEntry.type) {
case EventEntry::Type::KEY: {
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(eventEntry);
std::array<uint8_t, 32> hmac = getSignature(keyEntry, *dispatchEntry);
// Publish the key event.
// 发布按键事件
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;
}
case EventEntry::Type::MOTION: {
const MotionEntry& motionEntry = static_cast<const MotionEntry&>(eventEntry);
PointerCoords scaledCoords[MAX_POINTERS];
const PointerCoords* usingCoords = motionEntry.pointerCoords;
// Set the X and Y offset and X and Y scale depending on the input source.
if ((motionEntry.source & AINPUT_SOURCE_CLASS_POINTER) &&
!(dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS)) {
float globalScaleFactor = dispatchEntry->globalScaleFactor;
if (globalScaleFactor != 1.0f) {
for (uint32_t i = 0; i < motionEntry.pointerCount; i++) {
scaledCoords[i] = motionEntry.pointerCoords[i];
// Don't apply window scale here since we don't want scale to affect raw
// coordinates. The scale will be sent back to the client and applied
// later when requesting relative coordinates.
scaledCoords[i].scale(globalScaleFactor, 1 /* windowXScale */,
1 /* windowYScale */);
}
usingCoords = scaledCoords;
}
} else {
// We don't want the dispatch target to know.
if (dispatchEntry->targetFlags & InputTarget::FLAG_ZERO_COORDS) {
for (uint32_t i = 0; i < motionEntry.pointerCount; i++) {
scaledCoords[i].clear();
}
usingCoords = scaledCoords;
}
}
std::array<uint8_t, 32> hmac = getSignature(motionEntry, *dispatchEntry);
// Publish the motion event.
// 发布运动事件。
status = connection->inputPublisher
.publishMotionEvent(dispatchEntry->seq,
dispatchEntry->resolvedEventId,
motionEntry.deviceId, motionEntry.source,
motionEntry.displayId, std::move(hmac),
dispatchEntry->resolvedAction,
motionEntry.actionButton,
dispatchEntry->resolvedFlags,
motionEntry.edgeFlags, motionEntry.metaState,
motionEntry.buttonState,
motionEntry.classification,
dispatchEntry->transform,
motionEntry.xPrecision, motionEntry.yPrecision,
motionEntry.xCursorPosition,
motionEntry.yCursorPosition,
dispatchEntry->rawTransform,
motionEntry.downTime, motionEntry.eventTime,
motionEntry.pointerCount,
motionEntry.pointerProperties, usingCoords);
break;
}
case EventEntry::Type::FOCUS: {
const FocusEntry& focusEntry = static_cast<const FocusEntry&>(eventEntry);
status = connection->inputPublisher.publishFocusEvent(dispatchEntry->seq,
focusEntry.id,
focusEntry.hasFocus);
break;
}
case EventEntry::Type::TOUCH_MODE_CHANGED: {
const TouchModeEntry& touchModeEntry =
static_cast<const TouchModeEntry&>(eventEntry);
status = connection->inputPublisher
.publishTouchModeEvent(dispatchEntry->seq, touchModeEntry.id,
touchModeEntry.inTouchMode);
break;
}
case EventEntry::Type::POINTER_CAPTURE_CHANGED: {
const auto& captureEntry =
static_cast<const PointerCaptureChangedEntry&>(eventEntry);
status = connection->inputPublisher
.publishCaptureEvent(dispatchEntry->seq, captureEntry.id,
captureEntry.pointerCaptureRequest.enable);
break;
}
case EventEntry::Type::DRAG: {
const DragEntry& dragEntry = static_cast<const DragEntry&>(eventEntry);
status = connection->inputPublisher.publishDragEvent(dispatchEntry->seq,
dragEntry.id, dragEntry.x,
dragEntry.y,
dragEntry.isExiting);
break;
}
case EventEntry::Type::CONFIGURATION_CHANGED:
case EventEntry::Type::DEVICE_RESET:
case EventEntry::Type::SENSOR: {
LOG_ALWAYS_FATAL("Should never start dispatch cycles for %s events",
ftl::enum_string(eventEntry.type).c_str());
return;
}
}
// Check the result.
//publishKeyEvent失败情况
if (status) {
if (status == WOULD_BLOCK) {
if (connection->waitQueue.empty()) {
//pipe已满,但waitQueue为空. 不正常的行为
ALOGE("channel '%s' ~ Could not publish event because the pipe is full. "
"This is unexpected because the wait queue is empty, so the pipe "
"should be empty and we shouldn't have any problems writing an "
"event to it, status=%s(%d)",
connection->getInputChannelName().c_str(), statusToString(status).c_str(),
status);
abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
} else {
// Pipe is full and we are waiting for the app to finish process some events
// before sending more events to it.
if (DEBUG_DISPATCH_CYCLE) {
ALOGD("channel '%s' ~ Could not publish event because the pipe is full, "
"waiting for the application to catch up",
connection->getInputChannelName().c_str());
}
}
} else {
ALOGE("channel '%s' ~ Could not publish event due to an unexpected error, "
"status=%s(%d)",
connection->getInputChannelName().c_str(), statusToString(status).c_str(),
status);
abortBrokenDispatchCycleLocked(currentTime, connection, true /*notify*/);
}
return;
}
// Re-enqueue the event on the wait queue.
// 将事件从outboundQueue中移除
connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
connection->outboundQueue.end(),
dispatchEntry));
traceOutboundQueueLength(*connection);
// 在waitQueue 尾部重新插入
connection->waitQueue.push_back(dispatchEntry);
if (connection->responsive) {
mAnrTracker.insert(dispatchEntry->timeoutTime,
connection->inputChannel->getConnectionToken());
}
traceWaitQueueLength(*connection);
}
}
InputPublisher publishKeyEvent
调用InputPublisher的publishKeyEvent方法:
/frameworks/native/libs/input/InputPublisher.cpp
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) {
if (ATRACE_ENABLED()) {
std::string message = StringPrintf("publishKeyEvent(inputChannel=%s, keyCode=%" PRId32 ")",
mChannel->getName().c_str(), keyCode);
ATRACE_NAME(message.c_str());
}
if (DEBUG_TRANSPORT_ACTIONS) {
ALOGD("channel '%s' publisher ~ publishKeyEvent: seq=%u, deviceId=%d, source=0x%x, "
"action=0x%x, flags=0x%x, keyCode=%d, scanCode=%d, metaState=0x%x, repeatCount=%d,"
"downTime=%" PRId64 ", eventTime=%" PRId64,
mChannel->getName().c_str(), seq, deviceId, source, action, flags, 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); //通过InputChannel来发送消息
}
InputChannel sendMessage
调用mChannel(InputChannel)的sendMessage方法:
//frameworks/native/libs/input/InputTransport.cpp
status_t InputChannel::sendMessage(const InputMessage* msg) {
const size_t msgLength = msg->size();
InputMessage cleanMsg;
msg->getSanitizedCopy(&cleanMsg);
ssize_t nWrite;
do {
nWrite = ::send(getFd(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
} while (nWrite == -1 && errno == EINTR);
if (nWrite < 0) {
int error = errno;
#if DEBUG_CHANNEL_MESSAGES
ALOGD("channel '%s' ~ error sending message of type %d, %s", mName.c_str(),
msg->header.type, strerror(error));
#endif
if (error == EAGAIN || error == EWOULDBLOCK) {
return WOULD_BLOCK;
}
if (error == EPIPE || error == ENOTCONN || error == ECONNREFUSED || error == ECONNRESET) {
return DEAD_OBJECT;
}
return -error;
}
if (size_t(nWrite) != msgLength) {
#if DEBUG_CHANNEL_MESSAGES
ALOGD("channel '%s' ~ error sending message type %d, send was incomplete",
mName.c_str(), msg->header.type);
#endif
return DEAD_OBJECT;
}
#if DEBUG_CHANNEL_MESSAGES
ALOGD("channel '%s' ~ sent message of type %d", mName.c_str(), msg->header.type);
#endif
return OK;
}
NativeInputEventReceiver handleEvent
当事件分发的时候,looper会调用到NativeInputEventReceiver的handleEvent 方法:
//frameworks/base/core/jni/android_view_inputEventReceiver.cpp
int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) {
// Allowed return values of this function as documented in LooperCallback::handleEvent
constexpr int REMOVE_CALLBACK = 0;
constexpr int KEEP_CALLBACK = 1;
if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) {
// This error typically occurs when the publisher has closed the input channel
// as part of removing a window or finishing an IME session, in which case
// the consumer will soon be disposed as well.
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Publisher closed input channel or an error occurred. events=0x%x",
getInputChannelName().c_str(), events);
}
return REMOVE_CALLBACK;
}
if (events & ALOOPER_EVENT_INPUT) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
// 调用consumeEvents 来消费事件
status_t status = consumeEvents(env, false /*consumeBatches*/, -1, nullptr);
mMessageQueue->raiseAndClearException(env, "handleReceiveCallback");
return status == OK || status == NO_MEMORY ? KEEP_CALLBACK : REMOVE_CALLBACK;
}
if (events & ALOOPER_EVENT_OUTPUT) {
const status_t status = processOutboundEvents();
if (status == OK || status == WOULD_BLOCK) {
return KEEP_CALLBACK;
} else {
return REMOVE_CALLBACK;
}
}
ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. events=0x%x",
getInputChannelName().c_str(), events);
return KEEP_CALLBACK;
}
调用NativeInputEventReceiver的consumeEvents方法:
//frameworks/base/core/jni/android_view_inputEventReceiver.cpp
status_t NativeInputEventReceiver::consumeEvents(JNIEnv* env,
bool consumeBatches, nsecs_t frameTime, bool* outConsumedBatch) {
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Consuming input events, consumeBatches=%s, frameTime=%" PRId64,
getInputChannelName().c_str(), toString(consumeBatches), frameTime);
}
if (consumeBatches) {
mBatchedInputEventPending = false;
}
if (outConsumedBatch) {
*outConsumedBatch = false;
}
ScopedLocalRef<jobject> receiverObj(env, nullptr);
bool skipCallbacks = false;
for (;;) {
uint32_t seq;
InputEvent* inputEvent;
status_t status = mInputConsumer.consume(&mInputEventFactory,
consumeBatches, frameTime, &seq, &inputEvent);
if (status != OK && status != WOULD_BLOCK) {
ALOGE("channel '%s' ~ Failed to consume input event. status=%s(%d)",
getInputChannelName().c_str(), statusToString(status).c_str(), status);
return status;
}
if (status == WOULD_BLOCK) {
if (!skipCallbacks && !mBatchedInputEventPending && mInputConsumer.hasPendingBatch()) {
// There is a pending batch. Come back later.
if (!receiverObj.get()) {
receiverObj.reset(GetReferent(env, mReceiverWeakGlobal));
if (!receiverObj.get()) {
ALOGW("channel '%s' ~ Receiver object was finalized "
"without being disposed.",
getInputChannelName().c_str());
return DEAD_OBJECT;
}
}
mBatchedInputEventPending = true;
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Dispatching batched input event pending notification.",
getInputChannelName().c_str());
}
// 调用java层的InputEventReceiver#dispatchInputEvent方法
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.onBatchedInputEventPending,
mInputConsumer.getPendingBatchSource());
if (env->ExceptionCheck()) {
ALOGE("Exception dispatching batched input events.");
mBatchedInputEventPending = false; // try again later
}
}
return OK;
}
assert(inputEvent);
if (!skipCallbacks) {
if (!receiverObj.get()) {
receiverObj.reset(GetReferent(env, mReceiverWeakGlobal));
if (!receiverObj.get()) {
ALOGW("channel '%s' ~ Receiver object was finalized "
"without being disposed.", getInputChannelName().c_str());
return DEAD_OBJECT;
}
}
jobject inputEventObj;
switch (inputEvent->getType()) {
case AINPUT_EVENT_TYPE_KEY:
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Received key event.", getInputChannelName().c_str());
}
inputEventObj = android_view_KeyEvent_fromNative(env,
static_cast<KeyEvent*>(inputEvent));
break;
case AINPUT_EVENT_TYPE_MOTION: {
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Received motion event.", getInputChannelName().c_str());
}
MotionEvent* motionEvent = static_cast<MotionEvent*>(inputEvent);
if ((motionEvent->getAction() & AMOTION_EVENT_ACTION_MOVE) && outConsumedBatch) {
*outConsumedBatch = true;
}
inputEventObj = android_view_MotionEvent_obtainAsCopy(env, motionEvent);
break;
}
case AINPUT_EVENT_TYPE_FOCUS: {
FocusEvent* focusEvent = static_cast<FocusEvent*>(inputEvent);
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Received focus event: hasFocus=%s.",
getInputChannelName().c_str(), toString(focusEvent->getHasFocus()));
}
env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.onFocusEvent,
jboolean(focusEvent->getHasFocus()));
finishInputEvent(seq, true /* handled */);
continue;
}
case AINPUT_EVENT_TYPE_CAPTURE: {
const CaptureEvent* captureEvent = static_cast<CaptureEvent*>(inputEvent);
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Received capture event: pointerCaptureEnabled=%s",
getInputChannelName().c_str(),
toString(captureEvent->getPointerCaptureEnabled()));
}
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.onPointerCaptureEvent,
jboolean(captureEvent->getPointerCaptureEnabled()));
finishInputEvent(seq, true /* handled */);
continue;
}
case AINPUT_EVENT_TYPE_DRAG: {
const DragEvent* dragEvent = static_cast<DragEvent*>(inputEvent);
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Received drag event: isExiting=%s",
getInputChannelName().c_str(), toString(dragEvent->isExiting()));
}
env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.onDragEvent,
jboolean(dragEvent->isExiting()), dragEvent->getX(),
dragEvent->getY());
finishInputEvent(seq, true /* handled */);
continue;
}
case AINPUT_EVENT_TYPE_TOUCH_MODE: {
const TouchModeEvent* touchModeEvent = static_cast<TouchModeEvent*>(inputEvent);
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Received touch mode event: isInTouchMode=%s",
getInputChannelName().c_str(), toString(touchModeEvent->isInTouchMode()));
}
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.onTouchModeChanged,
jboolean(touchModeEvent->isInTouchMode()));
finishInputEvent(seq, true /* handled */);
continue;
}
default:
assert(false); // InputConsumer should prevent this from ever happening
inputEventObj = nullptr;
}
if (inputEventObj) {
if (kDebugDispatchCycle) {
ALOGD("channel '%s' ~ Dispatching input event.", getInputChannelName().c_str());
}
env->CallVoidMethod(receiverObj.get(),
gInputEventReceiverClassInfo.dispatchInputEvent, seq, inputEventObj);
if (env->ExceptionCheck()) {
ALOGE("Exception dispatching input event.");
skipCallbacks = true;
}
env->DeleteLocalRef(inputEventObj);
} else {
ALOGW("channel '%s' ~ Failed to obtain event object.",
getInputChannelName().c_str());
skipCallbacks = true;
}
}
}
}
InputEventReceiver dispatchInputEvent
调用java层的InputEventReceiver#dispatchInputEvent方法:
//frameworks/base/core/java/android/view/InputEventReceiver.java
public abstract class InputEventReceiver {
private void dispatchInputEvent(int seq, InputEvent event) {
mSeqMap.put(event.getSequenceNumber(), seq);
onInputEvent(event);
}
}
调用InputEventReceiver的onInputEvent方法:
//frameworks/base/core/java/android/view/InputEventReceiver.java
public abstract class InputEventReceiver {
public void onInputEvent(InputEvent event) {
finishInputEvent(event, false);
}
}
WindowInputEventReceiver onInputEvent
ViewRootImpl的内部类WindowInputEventReceiver继承于InputEventReceiver,因此会调用WindowInputEventReceiver的onInputEvent方法: