frameworks\native\services\inputflinger\dispatcher\InputDispatcher.cpp
frameworks\native\services\inputflinger\dispatcher\InputDispatcher.h
frameworks\native\include\android\input.h
frameworks\native\services\inputflinger\dispatcher\InputState.cpp
frameworks\native\services\inputflinger\dispatcher\InputState.h
frameworks\native\libs\input\InputTransport.cpp
sourcecode\frameworks\base\core\jni\android_view_InputEventReceiver.cpp
sourcecode\frameworks\base\core\java\android\view\InputEventReceiver.java
sourcecode\frameworks\base\core\java\android\view\ViewRootImpl.java
sourcecode\frameworks\base\core\java\android\view\View.java
frameworks\base\core\java\android\view\ViewGroup.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.
//判断是否有命令,此处的命令是在事件分发的过程中产生的,刷新设备,丢弃事件等等,被封装的命令对象
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.
if (runCommandsLockedInterruptible()) {//执行命令并将下一次唤醒时间设为c++中的最小值
nextWakeupTime = LONG_LONG_MIN;
}
} // 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);
mLooper->pollOnce(timeoutMillis);//进行下一次循环或者进入休眠
}
bool InputDispatcher::haveCommandsLocked() const {
//判断命令队列是否为null,里面存储的是CommandEntry实体
return !mCommandQueue.isEmpty();
}
bool InputDispatcher::runCommandsLockedInterruptible() {
if (mCommandQueue.isEmpty()) {
return false;
}
do {
//取出队头的命令开始执行
CommandEntry* commandEntry = mCommandQueue.dequeueAtHead();
Command command = commandEntry->command;
(this->*command)(commandEntry); // commands are implicitly 'LockedInterruptible'
commandEntry->connection.clear();
delete commandEntry;//释放内存
} while (!mCommandQueue.isEmpty());
return true;
}
void InputDispatcher::resetKeyRepeatLocked() {
if (mKeyRepeatState.lastKeyEntry) {
mKeyRepeatState.lastKeyEntry->release();
mKeyRepeatState.lastKeyEntry = nullptr;
}
}
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.
//判断事件分发是否允许,也就是在未开机、IMS未成功启动、关机等状态下是不可用的,默认值是false
if (!mDispatchEnabled) {
resetKeyRepeatLocked();//重置重复按键次数
}
// If dispatching is frozen, do not process timeouts or try to deliver any new events.
//判断分发线程是否被冻结,是否可以配发,默认值是false
if (mDispatchFrozen) {
#if DEBUG_FOCUS
ALOGD("Dispatch frozen. Waiting some more.");
#endif
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和endcall按键到来时,及时丢弃之前的事件,而直接响应特殊键
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.
if (!mPendingEvent) {//mPendingEvent是即将要被配发的事件,此处是判断是否正在配发事件
if (mInboundQueue.isEmpty()) {//判断配发事件队列
if (isAppSwitchDue) {
// The inbound queue is empty so the app switch key we were waiting
// for will never arrive. Stop waiting for it.
//如果队列是null。那么要等到的home或者挂机键永远不会到来,需要重置
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.
//如果正在配发的事件为null,那么就从配发队列中取出一个,开始配发
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.
//重置此次事件分发的ANR超时时间,如果超过5秒,就会产生ANR
resetANRTimeoutsLocked();
}
// 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 = 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 = nullptr;
}
switch (mPendingEvent->type) {
case EventEntry::TYPE_CONFIGURATION_CHANGED: {
ConfigurationChangedEntry* typedEntry =
static_cast<ConfigurationChangedEntry*>(mPendingEvent);
done = dispatchConfigurationChangedLocked(currentTime, typedEntry);
dropReason = DROP_REASON_NOT_DROPPED; // configuration changes are never dropped
break;
}
case EventEntry::TYPE_DEVICE_RESET: {
DeviceResetEntry* typedEntry = static_cast<DeviceResetEntry*>(mPendingEvent);
done = dispatchDeviceResetLocked(currentTime, typedEntry);
dropReason = DROP_REASON_NOT_DROPPED; // device resets are never dropped
break;
}
case EventEntry::TYPE_KEY: {
KeyEntry* typedEntry = static_cast<KeyEntry*>(mPendingEvent);
if (isAppSwitchDue) {
if (isAppSwitchKeyEvent(typedEntry)) {
resetPendingAppSwitchLocked(true);
isAppSwitchDue = false;
} else if (dropReason == DROP_REASON_NOT_DROPPED) {
dropReason = DROP_REASON_APP_SWITCH;
}
}
if (dropReason == DROP_REASON_NOT_DROPPED && isStaleEvent(currentTime, typedEntry)) {
dropReason = DROP_REASON_STALE;
}
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
done = dispatchKeyLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
case EventEntry::TYPE_MOTION: {
MotionEntry* typedEntry = static_cast<MotionEntry*>(mPendingEvent);
if (dropReason == DROP_REASON_NOT_DROPPED && isAppSwitchDue) {
dropReason = DROP_REASON_APP_SWITCH;
}
if (dropReason == DROP_REASON_NOT_DROPPED && isStaleEvent(currentTime, typedEntry)) {
dropReason = DROP_REASON_STALE;
}
if (dropReason == DROP_REASON_NOT_DROPPED && mNextUnblockedEvent) {
dropReason = DROP_REASON_BLOCKED;
}
done = dispatchMotionLocked(currentTime, typedEntry, &dropReason, nextWakeupTime);
break;
}
default:
ALOG_ASSERT(false);
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
}
}
bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, MotionEntry* entry,
DropReason* dropReason, nsecs_t* nextWakeupTime) {
ATRACE_CALL();
// Preprocessing.
if (!entry->dispatchInProgress) {//设置当前事件的配发进度
entry->dispatchInProgress = true;
logOutboundMotionDetails("dispatchMotion - ", entry);//打印出派发事件的详情
}
// Clean up if dropping the event.
if (*dropReason != DROP_REASON_NOT_DROPPED) {//如果是丢弃事件则直接设置派发结果
setInjectionResult(entry,
*dropReason == DROP_REASON_POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED
: INPUT_EVENT_INJECTION_FAILED);
return true;
}
//判断是不是点事件
bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
// Identify targets.
std::vector<InputTarget> inputTargets;//派发的窗口集合
bool conflictingPointerActions = false;
int32_t injectionResult;
if (isPointerEvent) {//是点事件,即就是触摸屏事件,一般情况下都是触摸屏事件
// Pointer event. (eg. touchscreen)
injectionResult =
findTouchedWindowTargetsLocked(currentTime, entry, inputTargets, nextWakeupTime,
&conflictingPointerActions);
} else {//轨迹球事件
// Non touch event. (eg. trackball)
injectionResult =
findFocusedWindowTargetsLocked(currentTime, entry, inputTargets, nextWakeupTime);
}
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}
setInjectionResult(entry, injectionResult);
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
CancelationOptions::Mode mode(isPointerEvent
? CancelationOptions::CANCEL_POINTER_EVENTS
: CancelationOptions::CANCEL_NON_POINTER_EVENTS);
CancelationOptions options(mode, "input event injection failed");
synthesizeCancelationEventsForMonitorsLocked(options);
}
return true;
}
// Add monitor channels from event's or focused display.
addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(entry));
if (isPointerEvent) {
ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(entry->displayId);
if (stateIndex >= 0) {
const TouchState& state = mTouchStatesByDisplay.valueAt(stateIndex);
if (!state.portalWindows.empty()) {
// The event has gone through these portal windows, so we add monitoring targets of
// the corresponding displays as well.
for (size_t i = 0; i < state.portalWindows.size(); i++) {
const InputWindowInfo* windowInfo = state.portalWindows[i]->getInfo();
addGlobalMonitoringTargetsLocked(inputTargets, windowInfo->portalToDisplayId,
-windowInfo->frameLeft, -windowInfo->frameTop);
}
}
}
}
// Dispatch the motion.
//指针冲突,此处可能由于触摸