一 ANR原理
我们平时遇到的ANR问题大部分是input ANR类型,本文以input ANR为例进行梳理,这块机制并不复杂,受限于篇幅,本文只介绍埋下计时和check超时的代码部分。
正常输入事件的分发流程如下
InputDispatcher::dispatchOnce()
->InputDispatcher::dispatchOnceInnerLocked
->InputDispatcher::dispatchKeyLocked
->InputDispatcher::findFocusedWindowTargetsLocked
......
findFocusedWindowTargetsLocked这个函数从字面不难猜出其意图: 查找有焦点的window。
该函数较长,我们将其拆分开来进行梳理
未找到focused的window,也未找到focused的application
// If there is no currently focused window and no focused application
// then drop the event.
if (focusedWindowHandle == nullptr && focusedApplicationHandle == nullptr) {
ALOGI("Dropping %s event because there is no focused window or focused application in "
"display %" PRId32 ".",
NamedEnum::string(entry.type).c_str(), displayId);
return InputEventInjectionResult::FAILED;
}
这种情况下,则drop该事件
未找到focused的window,有focused的application
if (focusedWindowHandle == nullptr && focusedApplicationHandle != nullptr) {
if (!mNoFocusedWindowTimeoutTime.has_value()) {
// We just discovered that there's no focused window. Start the ANR timer
std::chrono::nanoseconds timeout = focusedApplicationHandle->getDispatchingTimeout(
DEFAULT_INPUT_DISPATCHING_TIMEOUT);
//更新超时时间,该focused事件开始进入计时
mNoFocusedWindowTimeoutTime = currentTime + timeout.count();
mAwaitedFocusedApplication = focusedApplicationHandle;
mAwaitedApplicationDisplayId = displayId;
ALOGW("Waiting because no window has focus but %s may eventually add a "
"window when it finishes starting up. Will wait for %" PRId64 "ms",
mAwaitedFocusedApplication->getName().c_str(), millis(timeout));
*nextWakeupTime = *mNoFocusedWindowTimeoutTime;
return InputEventInjectionResult::PENDING;
} else if (currentTime > *mNoFocusedWindowTimeoutTime) {
// Already raised ANR. Drop the event
ALOGE("Dropping %s event because there is no focused window",
NamedEnum::string(entry.type).c_str());
return InputEventInjectionResult::FAILED;
} else {
//说明之前已经埋过计时,此时还未到超时时间则继续等待
// Still waiting for the focused window
return InputEventInjectionResult::PENDING;
}
}
重置超时时间
/ we have a val