安卓InputDispatching Timeout ANR 流程
- 1 ANR的检测逻辑有两个参与者: 观测者A和被观测者B,当然,这两者是不在同一个线程中的。
- 2 A在调用B中的逻辑时,同时在A中保存一个标记F,然后做个延时操作C,延时时间设为T,这一步称为: 埋雷 。
- 3 B中的逻辑如果被执行到,就会通知A去清除标记F,并且通知A解除C,这一步称为: 拆雷 。
- 4 如果C没被拆除,那么在时间T后就会被触发,就会去检测标记F是否还在,如果在,就说明B没有在指定的时间T内完成,那么就提示B发生了ANR,这一步称为: 爆雷 。
- 5 由于A和B是在不同线程中的,所以B即使死循环,也不会影响C的检测过程。
所以,我们可以将ANR更精炼的总结为: 埋雷、拆雷和爆雷三个步骤 。
InputDispatching Timeout: 输入事件(包括按键和触屏事件)在5秒内无响应,就会弹出 ANR 提示框,供用户选择继续等待程序响应或者关闭这个应用程序(也就是杀掉这个应用程序的进程)。输入超时类的 ANR 可以细分为以下两类:
1)处理消息超时: 这一类是指因为消息处理超时而发生的 ANR,在 log,会看到 “Input dispatching timed out (Waiting because the focused window has not finished processing
the input events that were previously delivered to it.)”
2)无法获取焦点: 这一类通常因为新窗口创建慢或旧窗口退出慢而造成窗口无法获得焦点从而发生 ANR,典型 Log “Reason: Waiting because no window has focus but there is a focused application
that may eventually add a window when it finishes starting up.”
这里不分析没有焦点的情形,只分析处理消息超时流程
在 input子系统中,正常逻辑是:InputDispatcher 负责将输入事件分发给 UI 主线程。UI主线程接收到输入事件后,使用 InputConsumer 来处理事件。经过一系列的 InputStage 完成事件分发后,执行finishInputEvent() 方法来告知 InputDispatcher 事件已经处理完成。InputDispatcher 中使用handleReceiveCallback() 方法来处理 UI 主线程返回的消息,最终将 dispatchEntry事件从等待队列中移除。
http://aospxref.com/android-13.0.0_r3/xref/frameworks/native/services/inputflinger/dispatcher/InputDispatcher.cpp
3975 void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
// 打开下列的开关,会打印对应的log
3976 if (DEBUG_INBOUND_EVENT_DETAILS) {
3977 ALOGD("notifyMotion - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=0x%x, "
3978 "displayId=%" PRId32 ", policyFlags=0x%x, "
3979 "action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, "
3980 "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, xCursorPosition=%f, "
3981 "yCursorPosition=%f, downTime=%" PRId64,
3982 args->id, args->eventTime, args->deviceId, args->source, args->displayId,
3983 args->policyFlags, args->action, args->actionButton, args->flags, args->metaState,
3984 args->buttonState, args->edgeFlags, args->xPrecision, args->yPrecision,
3985 args->xCursorPosition, args->yCursorPosition, args->downTime);
3986 for (uint32_t i = 0; i < args->pointerCount; i++) {
。。。。
4047 // Just enqueue a new motion event.
// 创建 MotionEntry 对象
4048 std::unique_ptr<MotionEntry> newEntry =
4049 std::make_unique<MotionEntry>(args->id, args->eventTime, args->deviceId,
4050 args->source, args->displayId, policyFlags,
4051 args->action, args->actionButton, args->flags,
4052 args->metaState, args->buttonState,
4053 args->classification, args->edgeFlags,
4054 args->xPrecision, args->yPrecision,
4055 args->xCursorPosition, args->yCursorPosition,
4056 args->downTime, args->pointerCount,
4057 args->pointerProperties, args->pointerCoords);
4058
4059 if (args->id != android::os::IInputConstants::INVALID_INPUT_EVENT_ID &&
4060 IdGenerator::getSource(args->id) == IdGenerator::Source::INPUT_READER &&
4061 !mInputFilterEnabled) {
4062 const bool isDown = args->action == AMOTION_EVENT_ACTION_DOWN;
4063 mLatencyTracker.trackListener(args->id, isDown, args->eventTime, args->readTime);
4064 }
4065
// 将 MotionEntry 事件保存到 mInboundQueue 队列中;如果保存之前 mInboundQueue是为空的,则 needWake 为true。
4066 needWake = enqueueInboundEventLocked(std::move(newEntry));
4067 mLock.unlock();
4068 } // release lock
4069
// 这里分析直接去唤醒inputdispatcher 线程
4070 if (needWake) {
4071 mLooper->wake();
4072 }
4073 }
InputDispatcher 是个线程,会循环执行 dispatchOnce 方法
602 void InputDispatcher::dispatchOnce() {
603 nsecs_t nextWakeupTime = LONG_LONG_MAX;
// 局部空间,获取同步锁
604 { // acquire lock
605 std::scoped_lock _l(mLock);
606 mDispatcherIsAlive.notify_all();
607
608 // Run a dispatch loop if there are no pending commands.
609 // The dispatch loop might enqueue commands to run afterwards.
// 如果没有 mCommandQueue ,没有 command 命令的话,
// 则执行 dispatchOnceInnerLocked,获取到下一次唤醒的时间:nextWakeupTime
// 1)如果有motion 事件,调用 dispatchOnceInnerLocked 方法
610 if (!haveCommandsLocked()) {
611 dispatchOnceInnerLocked(&nextWakeupTime);
612 }
613
// 执行command 命令,如果有的话,直接返回 true,然后马上唤醒线程
616 if (runCommandsLockedInterruptable()) {
617 nextWakeupTime = LONG_LONG_MIN;
618 }
619
// 处理anr 或者获取到下一次anr 的时间
// 2)获取超时anr 的时间:processAnrsLocked
622 const nsecs_t nextAnrCheck = processAnrsLocked();
623 nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
624
625 // We are about to enter an infinitely long sleep, because we have no commands or
626 // pending or queued events
// 如果唤醒时间为最大,则表明没有input 事件,是idle 空闲状态
627 if (nextWakeupTime == LONG_LONG_MAX) {
628 mDispatcherEnteredIdle.notify_all();
629 }
630 } // release lock
631
632 // Wait for callback or timeout or wake. (make sure we round up, not down)
633 nsecs_t currentTime = now();
// 获取到唤醒线程的时间
// 调用 mLooper->wake 函数也可以唤醒线程
634 int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
635 mLooper->pollOnce(timeoutMillis);
636 }
1)如果有motion 事件,调用 dispatchOnceInnerLocked 方法
718 void InputDispatcher::dispatchOnceInnerLocked(nsecs_t* nextWakeupTime) {
719 nsecs_t currentTime = now();
。。。
// 初始 mPendingEvent 为null
746 if (!mPendingEvent) {
// 前面notifymotion 增加了 mInboundQueue
747 if (mInboundQueue.empty()) {
。。。
770 } else {
771 // Inbound queue has at least one entry.
// 这里去获取到motion 事件
772 mPendingEvent = mInboundQueue.front();
773 mInboundQueue.pop_front();
774 traceInboundQueueLengthLocked();
775 }
776
777 // Poke user activity for this event.
778 if (mPendingEvent->policyFlags & POLICY_FLAG_PASS_TO_USER) {
779 pokeUserActivityLocked(*mPendingEvent);
780 }
781 }
。。。
798 switch (mPendingEvent->type) {
868 case EventEntry::Type::MOTION: {
869 std::shared_ptr<MotionEntry> motionEntry =
870 std::static_pointer_cast<MotionEntry>(mPendingEvent);
871 if (dropReason == DropReason::NOT_DROPPED && isAppSwitchDue) {
872 dropReason = DropReason::APP_SWITCH;
873 }
874 if (dropReason == DropReason::NOT_DROPPED && isStaleEvent(currentTime, *motionEntry)) {
875 dropReason = DropReason::STALE;
876 }
877 if (dropReason == DropReason::NOT_DROPPED && mNextUnblockedEvent) {
878 dropReason = DropReason::BLOCKED;
879 }
// dispatchMotionLocked 方法去分发motion 事件
880 done = dispatchMotionLocked(currentTime, motionEntry, &dropReason, nextWakeupTime);
881 break;
882 }
。。。
// 一般是返回true,表示分发motion 事件到应用了
902 if (done) {
903 if (dropReason != DropReason::NOT_DROPPED) {
904 dropInboundEventLocked(*mPendingEvent, dropReason);
905 }
906 mLastDropReason = dropReason;
907
// 返回true,则重新设置 mPendingEvent 为null
908 releasePendingEventLocked();
// 设置 nextWakeupTime 为最小,马上唤醒
909 *nextWakeupTime = LONG_LONG_MIN; // force next poll to wake up immediately
910 }
911 }
// dispatchMotionLocked 方法去分发motion 事件
1634 bool InputDispatcher::dispatchMotionLocked(nsecs_t currentTime, std::shared_ptr<MotionEntry> entry,
1635 DropReason* dropReason, nsecs_t* nextWakeupTime) {
// 会打印对应的trace
1636 ATRACE_CALL();
。。。
1652 const bool isPointerEvent = isFromSource(entry->source, AINPUT_SOURCE_CLASS_POINTER);
1653
1654 // Identify targets.
1655 std::vector<InputTarget> inputTargets;
1656
1657 bool conflictingPointerActions = false;
1658 InputEventInjectionResult injectionResult;
1659 if (isPointerEvent) {
1660 // Pointer event. (eg. touchscreen)
// 去根据xy 的坐标点,去找到触摸的 window
1661 injectionResult =
1662 findTouchedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime,
1663 &conflictingPointerActions);
。。。
// 增加到全局触摸事件
1687 addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(*entry));
1688
1689 // Dispatch the motion.
1690 if (conflictingPointerActions) {
1691 CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
1692 "conflicting pointer actions");
1693 synthesizeCancelationEventsForAllConnectionsLocked(options);
1694 }
// 分发event
1695 dispatchEventLocked(currentTime, entry, inputTargets);
1696 return true;
1697 }
// 分发event
1753 void InputDispatcher::dispatchEventLocked(nsecs_t currentTime,
1754 std::shared_ptr<EventEntry> eventEntry,
1755 const std::vector<InputTarget>& inputTargets) {
1756 ATRACE_CALL();
1757 if (DEBUG_DISPATCH_CYCLE) {
1758 ALOGD("dispatchEventToCurrentInputTargets");
1759 }
1760
1761 updateInteractionTokensLocked(*eventEntry, inputTargets);
1762
1763 ALOG_ASSERT(eventEntry->dispatchInProgress); // should already have been set to true
1764
1765 pokeUserActivityLocked(*eventEntry);
1766
1767 for (const InputTarget& inputTarget : inputTargets) {
// 找到对应的窗口的 connection
1768 sp<Connection> connection =
1769 getConnectionLocked(inputTarget.inputChannel->getConnectionToken());
1770 if (connection != nullptr) {
1771 prepareDispatchCycleLocked(currentTime, connection, eventEntry, inputTarget);
1772 } else {
1773 if (DEBUG_FOCUS) {
1774 ALOGD("Dropping event delivery to target with channel '%s' because it "
1775 "is no longer registered with the input dispatcher.",
1776 inputTarget.inputChannel->getName().c_str());
1777 }
1778 }
1779 }
1780 }
准备分发事件给应用 prepareDispatchCycleLocked
2887 void InputDispatcher::prepareDispatchCycleLocked(nsecs_t currentTime,
2888 const sp<Connection>& connection,
2889 std::shared_ptr<EventEntry> eventEntry,
2890 const InputTarget& inputTarget) {
2891 if (ATRACE_ENABLED()) {
2892 std::string message =
2893 StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, id=0x%" PRIx32 ")",
2894 connection->getInputChannelName().c_str(), eventEntry->id);
2895 ATRACE_NAME(message.c_str());
2896 }
。。。。。
2944
2945 // Not splitting. Enqueue dispatch entries for the event as is.
2946 enqueueDispatchEntriesLocked(currentTime, connection, eventEntry, inputTarget);
2947 }
2949 void InputDispatcher::enqueueDispatchEntriesLocked(nsecs_t currentTime,
2950 const sp<Connection>& connection,
2951 std::shared_ptr<EventEntry> eventEntry,
2952 const InputTarget& inputTarget) {
2953 if (ATRACE_ENABLED()) {
2954 std::string message =
2955 StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, id=0x%" PRIx32 ")",
2956 connection->getInputChannelName().c_str(), eventEntry->id);
2957 ATRACE_NAME(message.c_str());
2958 }
2959
2960 bool wasEmpty = connection->outboundQueue.empty();
2961
// 将触摸事件保存到 outboundQueue 中
2962 // Enqueue dispatch entries for the requested modes.
2963 enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
2964 InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT);
2965 enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
2966 InputTarget::FLAG_DISPATCH_AS_OUTSIDE);
2967 enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
2968 InputTarget::FLAG_DISPATCH_AS_HOVER_ENTER);
2969 enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
2970 InputTarget::FLAG_DISPATCH_AS_IS);
2971 enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
2972 InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT);
2973 enqueueDispatchEntryLocked(connection, eventEntry, inputTarget,
2974 InputTarget::FLAG_DISPATCH_AS_SLIPPERY_ENTER);
2975
2976 // If the outbound queue was previously empty, start the dispatch cycle going.
2977 if (wasEmpty && !connection->outboundQueue.empty()) {
// 开始socket 通信去分发给应用 startDispatchCycleLocked
2978 startDispatchCycleLocked(currentTime, connection);
2979 }
2980 }
// 开始socket 通信去分发给应用 startDispatchCycleLocked
3214 void InputDispatcher::startDispatchCycleLocked(nsecs_t currentTime,
3215 const sp<Connection>& connection) {
3216 if (ATRACE_ENABLED()) {
3217 std::string message = StringPrintf("startDispatchCycleLocked(inputChannel=%s)",
3218 connection->getInputChannelName().c_str());
3219 ATRACE_NAME(message.c_str());
3220 }
3221 if (DEBUG_DISPATCH_CYCLE) {
3222 ALOGD("channel '%s' ~ startDispatchCycle", connection->getInputChannelName().c_str());
3223 }
3224
3225 while (connection->status == Connection::Status::NORMAL && !connection->outboundQueue.empty()) {
3226 DispatchEntry* dispatchEntry = connection->outboundQueue.front();
3227 dispatchEntry->deliveryTime = currentTime;
// 获取到应用设置的超时事件,一般为 5 秒
3228 const std::chrono::nanoseconds timeout = getDispatchingTimeoutLocked(connection);
// 设置timeout 的时间
3229 dispatchEntry->timeoutTime = currentTime + timeout.count();
。。。
3252 case EventEntry::Type::MOTION: {
3253 const MotionEntry& motionEntry = static_cast<const MotionEntry&>(eventEntry);
。。。
// socket 通信发送给 应用,给到应用去处理了
3285 // Publish the motion event.
3286 status = connection->inputPublisher
3287 .publishMotionEvent(dispatchEntry->seq,
3288 dispatchEntry->resolvedEventId,
3289 motionEntry.deviceId, motionEntry.source,
3290 motionEntry.displayId, std::move(hmac),
3291 dispatchEntry->resolvedAction,
3292 motionEntry.actionButton,
3293 dispatchEntry->resolvedFlags,
3294 motionEntry.edgeFlags, motionEntry.metaState,
3295 motionEntry.buttonState,
3296 motionEntry.classification,
3297 dispatchEntry->transform,
3298 motionEntry.xPrecision, motionEntry.yPrecision,
3299 motionEntry.xCursorPosition,
3300 motionEntry.yCursorPosition,
3301 dispatchEntry->rawTransform,
3302 motionEntry.downTime, motionEntry.eventTime,
3303 motionEntry.pointerCount,
3304 motionEntry.pointerProperties, usingCoords);
3305 break;
3306 }
。。。。。
3383 // Re-enqueue the event on the wait queue.
// 将触摸事件从 outboundQueue 移除掉
3384 connection->outboundQueue.erase(std::remove(connection->outboundQueue.begin(),
3385 connection->outboundQueue.end(),
3386 dispatchEntry));
3387 traceOutboundQueueLength(*connection);
// 将其增加到 waitQueue 等待队列中
3388 connection->waitQueue.push_back(dispatchEntry);
// 如果应用没有die,则 将anr 超时时间保存到 mAnrTracker 中,还有对应的应用token
3389 if (connection->responsive) {
3390 mAnrTracker.insert(dispatchEntry->timeoutTime,
3391 connection->inputChannel->getConnectionToken());
3392 }
3393 traceWaitQueueLength(*connection);
3394 }
3395 }
2)获取超时anr 的时间:processAnrsLocked
622 const nsecs_t nextAnrCheck = processAnrsLocked();
// nextWakeupTime 由前面的分析,返回的是为 LONG_LONG_MIN,所以这里的唤醒时间为马上唤醒
623 nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
670 nsecs_t InputDispatcher::processAnrsLocked() {
671 const nsecs_t currentTime = now();
672 nsecs_t nextAnrCheck = LONG_LONG_MAX;
// 下列是处理no focus 没有焦点的情况,这里不满足
674 if (mNoFocusedWindowTimeoutTime.has_value() && mAwaitedFocusedApplication != nullptr) {
675 if (currentTime >= *mNoFocusedWindowTimeoutTime) {
676 processNoFocusedWindowAnrLocked();
677 mAwaitedFocusedApplication.reset();
678 mNoFocusedWindowTimeoutTime = std::nullopt;
679 return LONG_LONG_MIN;
680 } else {
681 // Keep waiting. We will drop the event when mNoFocusedWindowTimeoutTime comes.
682 nextAnrCheck = *mNoFocusedWindowTimeoutTime;
683 }
684 }
685
// 获取到前面保存到anr 的时间,即前面当前的时间 + timeout 5 秒
687 nextAnrCheck = std::min(nextAnrCheck, mAnrTracker.firstTimeout());
// 当前的时间是小于 nextAnrCheck,所以返回 nextAnrCheck的时间
688 if (currentTime < nextAnrCheck) { // most likely scenario
689 return nextAnrCheck; // everything is normal. Let's check again at nextAnrCheck
690 }
691
692 // If we reached here, we have an unresponsive connection.
693 sp<Connection> connection = getConnectionLocked(mAnrTracker.firstToken());
694 if (connection == nullptr) {
695 ALOGE("Could not find connection for entry %" PRId64, mAnrTracker.firstTimeout());
696 return nextAnrCheck;
697 }
698 connection->responsive = false;
699 // Stop waking up for this unresponsive connection
700 mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken());
701 onAnrLocked(connection);
702 return LONG_LONG_MIN;
703 }
但是接下有个处理 :这里返回时 MIN 的,即马上唤醒。所以再走一次线程dispatchOnce 方法
nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
602 void InputDispatcher::dispatchOnce() {
603 nsecs_t nextWakeupTime = LONG_LONG_MAX;
604 { // acquire lock
605 std::scoped_lock _l(mLock);
606 mDispatcherIsAlive.notify_all();
607
// 这时候没有inboundqueue 了
610 if (!haveCommandsLocked()) {
611 dispatchOnceInnerLocked(&nextWakeupTime);
612 }
613
// 也没有cammand
616 if (runCommandsLockedInterruptable()) {
617 nextWakeupTime = LONG_LONG_MIN;
618 }
619
// 这里就可以获取到 anr 的时间了
622 const nsecs_t nextAnrCheck = processAnrsLocked();
623 nextWakeupTime = std::min(nextWakeupTime, nextAnrCheck);
624
625 // We are about to enter an infinitely long sleep, because we have no commands or
626 // pending or queued events
627 if (nextWakeupTime == LONG_LONG_MAX) {
628 mDispatcherEnteredIdle.notify_all();
629 }
630 } // release lock
631
633 nsecs_t currentTime = now();
634 int timeoutMillis = toMillisecondTimeoutDelay(currentTime, nextWakeupTime);
// 这里去等待anr 超时的时间
635 mLooper->pollOnce(timeoutMillis);
636 }
3)排雷过程
// 在inputdispatcher 与应用创建连接的时候,会设置socket 通信的callback,执行 handleReceiveCallback 方法
5450 Result<std::unique_ptr<InputChannel>> InputDispatcher::createInputChannel(const std::string& name) {
5451 if (DEBUG_CHANNEL_CREATION) {
5452 ALOGD("channel '%s' ~ createInputChannel", name.c_str());
5453 }
。。。5475 std::function<int(int events)> callback = std::bind(&InputDispatcher::handleReceiveCallback,
5476 this, std::placeholders::_1, token);
5477
5478 mLooper->addFd(fd, 0, ALOOPER_EVENT_INPUT, new LooperEventCallback(callback), nullptr);
5479 } // release lock
5480
5481 // Wake the looper because some connections have changed.
5482 mLooper->wake();
5483 return clientChannel;
5484 }
如果应用有发送socket 消息,则执行 handleReceiveCallback 方法
int InputDispatcher::handleReceiveCallback(int events, sp<IBinder> connectionToken) {
std::scoped_lock _l(mLock);
// 通过token 获取到对应的connection
sp<Connection> connection = getConnectionLocked(connectionToken);
bool notify;
// event 不能为 ALOOPER_EVENT_ERROR 或者 ALOOPER_EVENT_HANGUP
if (!(events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP))) {
if (!(events & ALOOPER_EVENT_INPUT)) {
ALOGW("channel '%s' ~ Received spurious callback for unhandled poll event. "
"events=0x%x",
connection->getInputChannelName().c_str(), events);
return 1;
}
nsecs_t currentTime = now();
bool gotOne = false;
status_t status = OK;
// 循环操作
for (;;) {
// 通过socket 获取到消息
Result<InputPublisher::ConsumerResponse> result =
connection->inputPublisher.receiveConsumerResponse();
if (!result.ok()) {
status = result.error().code();
break;
}
// 如果result 是 Finished,则执行 finishDispatchCycleLocked
if (std::holds_alternative<InputPublisher::Finished>(*result)) {
const InputPublisher::Finished& finish =
std::get<InputPublisher::Finished>(*result);
finishDispatchCycleLocked(currentTime, connection, finish.seq, finish.handled,
finish.consumeTime);
。。。
// 设置 gotOne = true
gotOne = true;
}
if (gotOne) {
// finishDispatchCycleLocked 增加了command,这里去执行 command
runCommandsLockedInterruptable();
if (status == WOULD_BLOCK) {
return 1;
}
}
// 如果result 是 Finished,则执行 finishDispatchCycleLocked
void InputDispatcher::finishDispatchCycleLocked(nsecs_t currentTime,
const sp<Connection>& connection, uint32_t seq,
bool handled, nsecs_t consumeTime) {
if (DEBUG_DISPATCH_CYCLE) {
ALOGD("channel '%s' ~ finishDispatchCycle - seq=%u, handled=%s",
connection->getInputChannelName().c_str(), seq, toString(handled));
}
if (connection->status == Connection::Status::BROKEN ||
connection->status == Connection::Status::ZOMBIE) {
return;
}
// Notify other system components and prepare to start the next dispatch cycle.
auto command = [this, currentTime, connection, seq, handled, consumeTime]() REQUIRES(mLock) {
doDispatchCycleFinishedCommand(currentTime, connection, seq, handled, consumeTime);
};
postCommandLocked(std::move(command));
}
前面 runCommandsLockedInterruptable 方法会去执行 doDispatchCycleFinishedCommand 方法
void InputDispatcher::doDispatchCycleFinishedCommand(nsecs_t finishTime,
const sp<Connection>& connection, uint32_t seq,
bool handled, nsecs_t consumeTime) {
// Handle post-event policy actions.
std::deque<DispatchEntry*>::iterator dispatchEntryIt = connection->findWaitQueueEntry(seq);
if (dispatchEntryIt == connection->waitQueue.end()) {
return;
}
DispatchEntry* dispatchEntry = *dispatchEntryIt;
const nsecs_t eventDuration = finishTime - dispatchEntry->deliveryTime;
// 如果应用处理超过 2 秒,则会打印下列的日志
if (eventDuration > SLOW_EVENT_PROCESSING_WARNING_TIMEOUT) {
ALOGI("%s spent %" PRId64 "ms processing %s", connection->getWindowName().c_str(),
ns2ms(eventDuration), dispatchEntry->eventEntry->getDescription().c_str());
}
。。。
// 从等待队列中找到 dispatchEntryIt
dispatchEntryIt = connection->findWaitQueueEntry(seq);
if (dispatchEntryIt != connection->waitQueue.end()) {
dispatchEntry = *dispatchEntryIt;
connection->waitQueue.erase(dispatchEntryIt);
const sp<IBinder>& connectionToken = connection->inputChannel->getConnectionToken();
// 从anrtracker 中移除这个超时时间,和connection
mAnrTracker.erase(dispatchEntry->timeoutTime, connectionToken);
if (!connection->responsive) {
connection->responsive = isConnectionResponsive(*connection);
if (connection->responsive) {
// The connection was unresponsive, and now it's responsive.
processConnectionResponsiveLocked(*connection);
}
}
traceWaitQueueLength(*connection);
if (restartEvent && connection->status == Connection::Status::NORMAL) {
connection->outboundQueue.push_front(dispatchEntry);
traceOutboundQueueLength(*connection);
} else {
releaseDispatchEntry(dispatchEntry);
}
}
// Start the next dispatch cycle for this connection.
// 如果还有下一个事件的话,则调用 startDispatchCycleLocked 继续去处理
startDispatchCycleLocked(now(), connection);
}
则下次执行线程的时候,由于mAnrTracker移除了对应的conenction,则 processAnrsLocked不会触发anr 流程
4)爆雷过程
在anr 时间点触发线程执行:dispatchOnce,然后执行 processAnrsLocked 方法
nsecs_t InputDispatcher::processAnrsLocked() {
const nsecs_t currentTime = now();
nsecs_t nextAnrCheck = LONG_LONG_MAX;
// 不满足下列的条件
if (mNoFocusedWindowTimeoutTime.has_value() && mAwaitedFocusedApplication != nullptr) {
if (currentTime >= *mNoFocusedWindowTimeoutTime) {
processNoFocusedWindowAnrLocked();
mAwaitedFocusedApplication.reset();
mNoFocusedWindowTimeoutTime = std::nullopt;
return LONG_LONG_MIN;
} else {
// Keep waiting. We will drop the event when mNoFocusedWindowTimeoutTime comes.
nextAnrCheck = *mNoFocusedWindowTimeoutTime;
}
}
// Check if any connection ANRs are due
nextAnrCheck = std::min(nextAnrCheck, mAnrTracker.firstTimeout());
// 这里当前的时间点是大于 anr 的时间,即前面没有移除
if (currentTime < nextAnrCheck) { // most likely scenario
return nextAnrCheck; // everything is normal. Let's check again at nextAnrCheck
}
// 执行下列anr 的流程
// If we reached here, we have an unresponsive connection.
sp<Connection> connection = getConnectionLocked(mAnrTracker.firstToken());
if (connection == nullptr) {
ALOGE("Could not find connection for entry %" PRId64, mAnrTracker.firstTimeout());
return nextAnrCheck;
}
// 设置应用回复为 false
connection->responsive = false;
// Stop waking up for this unresponsive connection
// 从anrtracker 中移除,防止进入到线程又再次触发anr
mAnrTracker.eraseToken(connection->inputChannel->getConnectionToken());
// 走anr 流程:onAnrLocked
onAnrLocked(connection);
return LONG_LONG_MIN;
}
// 走anr 流程:onAnrLocked
void InputDispatcher::onAnrLocked(const sp<Connection>& connection) {
if (connection == nullptr) {
LOG_ALWAYS_FATAL("Caller must check for nullness");
}
// Since we are allowing the policy to extend the timeout, maybe the waitQueue
// is already healthy again. Don't raise ANR in this situation
if (connection->waitQueue.empty()) {
ALOGI("Not raising ANR because the connection %s has recovered",
connection->inputChannel->getName().c_str());
return;
}
// 从等待队列中获取
DispatchEntry* oldestEntry = *connection->waitQueue.begin();
// 获取到等待的时间
const nsecs_t currentWait = now() - oldestEntry->deliveryTime;
// 设置input dispatcher 时间分发超时的原因 reason
std::string reason =
android::base::StringPrintf("%s is not responding. Waited %" PRId64 "ms for %s",
connection->inputChannel->getName().c_str(),
ns2ms(currentWait),
oldestEntry->eventEntry->getDescription().c_str());
sp<IBinder> connectionToken = connection->inputChannel->getConnectionToken();
// 保存到dump 中
updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason);
processConnectionUnresponsiveLocked(*connection, std::move(reason));
// Stop waking up for events on this connection, it is already unresponsive
cancelEventsForAnrLocked(connection);
}
processConnectionUnresponsiveLocked 处理anr
void InputDispatcher::processConnectionUnresponsiveLocked(const Connection& connection,
std::string reason) {
const sp<IBinder>& connectionToken = connection.inputChannel->getConnectionToken();
std::optional<int32_t> pid;
// 不满足下列条件
if (connection.monitor) {
ALOGW("Monitor %s is unresponsive: %s", connection.inputChannel->getName().c_str(),
reason.c_str());
pid = findMonitorPidByTokenLocked(connectionToken);
} else {
// The connection is a window
ALOGW("Window %s is unresponsive: %s", connection.inputChannel->getName().c_str(),
reason.c_str());
const sp<WindowInfoHandle> handle = getWindowHandleLocked(connectionToken);
if (handle != nullptr) {
pid = handle->getInfo()->ownerPid;
}
}
sendWindowUnresponsiveCommandLocked(connectionToken, pid, std::move(reason));
}
void InputDispatcher::sendWindowUnresponsiveCommandLocked(const sp<IBinder>& token,
std::optional<int32_t> pid,
std::string reason) {
// 将command 保存到queue 中,因为前面会直接返回 MIN,所以线程会马山处理
auto command = [this, token, pid, reason = std::move(reason)]() REQUIRES(mLock) {
scoped_unlock unlock(mLock);
mPolicy->notifyWindowUnresponsive(token, pid, reason);
};
postCommandLocked(std::move(command));
}
// 通知到界面没有反应 notifyWindowUnresponsive
/frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
// 前面将 NativeInputManager 保存到 了InputManager中
831 void NativeInputManager::notifyWindowUnresponsive(const sp<IBinder>& token,
832 std::optional<int32_t> pid,
833 const std::string& reason) {
834 #if DEBUG_INPUT_DISPATCHER_POLICY
835 ALOGD("notifyWindowUnresponsive");
836 #endif
// 会打印对应的trace:notifyWindowUnresponsive
837 ATRACE_CALL();
838
839 JNIEnv* env = jniEnv();
840 ScopedLocalFrame localFrame(env);
841
842 jobject tokenObj = javaObjectForIBinder(env, token);
843 ScopedLocalRef<jstring> reasonObj(env, env->NewStringUTF(reason.c_str()));
844
// 调用java 层的方法
845 env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyWindowUnresponsive, tokenObj,
846 pid.value_or(0), pid.has_value(), reasonObj.get());
847 checkAndClearExceptionFromCallback(env, "notifyWindowUnresponsive");
848 }
/frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
2927 // Native callback
2928 @SuppressWarnings("unused")
2929 private void notifyWindowUnresponsive(IBinder token, int pid, boolean isPidValid,
2930 String reason) {
2931 mWindowManagerCallbacks.notifyWindowUnresponsive(token,
2932 isPidValid ? OptionalInt.of(pid) : OptionalInt.empty(), reason);
2933 }
/frameworks/base/services/core/java/com/android/server/wm/InputManagerCallback.java
102 @Override
103 public void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid,
104 @NonNull String reason) {
105 mService.mAnrController.notifyWindowUnresponsive(token, pid, reason);
106 }
/frameworks/base/services/core/java/com/android/server/wm/AnrController.java
88 void notifyWindowUnresponsive(@NonNull IBinder token, @NonNull OptionalInt pid,
89 @NonNull String reason) {
90 if (notifyWindowUnresponsive(token, reason)) {
91 return;
92 }
93 if (!pid.isPresent()) {
94 Slog.w(TAG_WM, "Failed to notify that window token=" + token + " was unresponsive.");
95 return;
96 }
97 notifyWindowUnresponsive(pid.getAsInt(), reason);
98 }
99
100 /**
101 * Notify a window identified by its input token was unresponsive.
102 *
103 * @return true if the window was identified by the given input token and the request was
104 * handled, false otherwise.
105 */
106 private boolean notifyWindowUnresponsive(@NonNull IBinder inputToken, String reason) {
107 preDumpIfLockTooSlow();
108 final int pid;
109 final boolean aboveSystem;
110 final ActivityRecord activity;
111 synchronized (mService.mGlobalLock) {
112 InputTarget target = mService.getInputTargetFromToken(inputToken);
113 if (target == null) {
114 return false;
115 }
116 WindowState windowState = target.getWindowState();
117 pid = target.getPid();
118 // Blame the activity if the input token belongs to the window. If the target is
119 // embedded, then we will blame the pid instead.
120 activity = (windowState.mInputChannelToken == inputToken)
121 ? windowState.mActivityRecord : null;
// 会打印下列的log
122 Slog.i(TAG_WM, "ANR in " + target + ". Reason:" + reason);
123 aboveSystem = isWindowAboveSystem(windowState);
124 dumpAnrStateLocked(activity, windowState, reason);
125 }
// ActivityRecord 不为空
126 if (activity != null) {
127 activity.inputDispatchingTimedOut(reason, pid);
128 } else {
129 mService.mAmInternal.inputDispatchingTimedOut(pid, aboveSystem, reason);
130 }
131 return true;
132 }
/frameworks/base/services/core/java/com/android/server/wm/ActivityRecord.java
6649 public boolean inputDispatchingTimedOut(String reason, int windowPid) {
6650 ActivityRecord anrActivity;
6651 WindowProcessController anrApp;
6652 boolean blameActivityProcess;
6653 synchronized (mAtmService.mGlobalLock) {
6654 anrActivity = getWaitingHistoryRecordLocked();
6655 anrApp = app;
6656 blameActivityProcess = hasProcess()
6657 && (app.getPid() == windowPid || windowPid == INVALID_PID);
6658 }
6659
6660 if (blameActivityProcess) {
6661 return mAtmService.mAmInternal.inputDispatchingTimedOut(anrApp.mOwner,
6662 anrActivity.shortComponentName, anrActivity.info.applicationInfo,
6663 shortComponentName, app, false, reason);
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
17647 boolean inputDispatchingTimedOut(ProcessRecord proc, String activityShortComponentName,
17648 ApplicationInfo aInfo, String parentShortComponentName,
17649 WindowProcessController parentProcess, boolean aboveSystem, String reason) {
17650 if (checkCallingPermission(FILTER_EVENTS) != PackageManager.PERMISSION_GRANTED) {
17651 throw new SecurityException("Requires permission " + FILTER_EVENTS);
17652 }
17653
17654 final String annotation;
17655 if (reason == null) {
17656 annotation = "Input dispatching timed out";
// 这里增加 Input dispatching timed out
17657 } else {
17658 annotation = "Input dispatching timed out (" + reason + ")";
17659 }
17660
17661 if (proc != null) {
17662 synchronized (this) {
17663 if (proc.isDebugging()) {
17664 return false;
17665 }
17666
17667 if (proc.getActiveInstrumentation() != null) {
17668 Bundle info = new Bundle();
17669 info.putString("shortMsg", "keyDispatchingTimedOut");
17670 info.putString("longMsg", annotation);
17671 finishInstrumentationLocked(proc, Activity.RESULT_CANCELED, info);
17672 return true;
17673 }
17674 }
// 这里去弹框
17675 mAnrHelper.appNotResponding(proc, activityShortComponentName, aInfo,
17676 parentShortComponentName, parentProcess, aboveSystem, annotation);
17677 }
17678
17679 return true;
17680 }
原文地址:https://blog.csdn.net/qq_40587575/article/details/143925387
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!