新媒体h5是什么,南宁网站怎么做seo,wordpress需要调用缩略图,wordpress无域名ip访问目标窗口查找时#xff0c;作为派发目标的窗口必须已经准备好接收新的输入事件#xff0c;否则判定窗口处于未响应状态#xff0c;终止事件的派发过程#xff0c;并在一段时间后再试。倘若5s后窗口仍然未准备好接收输入事件#xff0c;将导致ANR。直接引发ANR的原因有很多…目标窗口查找时作为派发目标的窗口必须已经准备好接收新的输入事件否则判定窗口处于未响应状态终止事件的派发过程并在一段时间后再试。倘若5s后窗口仍然未准备好接收输入事件将导致ANR。直接引发ANR的原因有很多
例如Activity生命周期函数调用超时
服务启动超时
以及最常见的输入事件处理超时等。
Service ANR前台20s后台200sstartForeground超时10sBroadcast ANR前台10s后台60sInput ANR按键或触摸事件在5s内无响应ContentProvider ANR10s少见
下面从输入事件超时的角度讨论ANR的产生原因与过程
inputANR 分为两种
无响应anr: 应用连接正常但是未相应事件并且发生了超时
无焦点窗口anr: 当前有焦点应用但是无焦点窗口并且超时
void InputDispatcher::dispatchOnce() {nsecs_t nextWakeupTime LLONG_MAX;{ // acquire lockstd::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 (runCommandsLockedInterruptable()) {nextWakeupTime LLONG_MIN;}// If we are still waiting for ack on some events,// we might have to wake up earlier to check if an app is anring.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 eventsif (nextWakeupTime LLONG_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);mLooper-pollOnce(timeoutMillis);
}
nsecs_t InputDispatcher::processAnrsLocked() {const nsecs_t currentTime now();nsecs_t nextAnrCheck LLONG_MAX;// Check if we are waiting for a focused window to appear. Raise ANR if waited too longif (mNoFocusedWindowTimeoutTime.has_value() mAwaitedFocusedApplication ! nullptr) {if (currentTime *mNoFocusedWindowTimeoutTime) {processNoFocusedWindowAnrLocked();// 无焦点anrmAwaitedFocusedApplication.reset();mNoFocusedWindowTimeoutTime std::nullopt;return LLONG_MIN;} else {// Keep waiting. We will drop the event when mNoFocusedWindowTimeoutTime comes.nextAnrCheck *mNoFocusedWindowTimeoutTime;}}// Check if any connection ANRs are duenextAnrCheck std::min(nextAnrCheck, mAnrTracker.firstTimeout());if (currentTime nextAnrCheck) { // most likely scenarioreturn nextAnrCheck; // everything is normal. Lets check again at nextAnrCheck}// If we reached here, we have an unresponsive connection.std::shared_ptrConnection connection getConnectionLocked(mAnrTracker.firstToken());if (connection nullptr) {ALOGE(Could not find connection for entry % PRId64, mAnrTracker.firstTimeout());return nextAnrCheck;}connection-responsive false;// Stop waking up for this unresponsive connectionmAnrTracker.eraseToken(connection-inputChannel-getConnectionToken());onAnrLocked(connection);// 无响应anrreturn LLONG_MIN;
}mNoFocusedWindowTimeoutTime 和 mAwaitedFocusedApplication 的设置是在 InputDispatcher::findFocusedWindowTargetLocked
函数中:
spWindowInfoHandle InputDispatcher::findFocusedWindowTargetLocked(nsecs_t currentTime, const EventEntry entry, nsecs_t* nextWakeupTime,InputEventInjectionResult outInjectionResult) {std::string reason;outInjectionResult InputEventInjectionResult::FAILED; // Default resultint32_t displayId getTargetDisplayId(entry);spWindowInfoHandle focusedWindowHandle getFocusedWindowHandleLocked(displayId);std::shared_ptrInputApplicationHandle focusedApplicationHandle getValueByKey(mFocusedApplicationHandlesByDisplay, displayId);// 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 .,ftl::enum_string(entry.type).c_str(), displayId);return nullptr;}// Drop key events if requested by input featureif (focusedWindowHandle ! nullptr shouldDropInput(entry, focusedWindowHandle)) {return nullptr;}// Compatibility behavior: raise ANR if there is a focused application, but no focused window.// Only start counting when we have a focused event to dispatch. The ANR is canceled if we// start interacting with another application via touch (app switch). This code can be removed// if the no focused window ANR is moved to the policy. Input doesnt know whether// an app is expected to have a focused window.if (focusedWindowHandle nullptr focusedApplicationHandle ! nullptr) {if (!mNoFocusedWindowTimeoutTime.has_value()) {// We just discovered that theres no focused window. Start the ANR timerstd::chrono::nanoseconds timeout focusedApplicationHandle-getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);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;outInjectionResult InputEventInjectionResult::PENDING;return nullptr;} else if (currentTime *mNoFocusedWindowTimeoutTime) {// Already raised ANR. Drop the eventALOGE(Dropping %s event because there is no focused window,ftl::enum_string(entry.type).c_str());return nullptr;} else {// Still waiting for the focused windowoutInjectionResult InputEventInjectionResult::PENDING;return nullptr;}}// we have a valid, non-null focused windowresetNoFocusedWindowTimeoutLocked();// Verify targeted injection.if (const auto err verifyTargetedInjection(focusedWindowHandle, entry); err) {ALOGW(Dropping injected event: %s, (*err).c_str());outInjectionResult InputEventInjectionResult::TARGET_MISMATCH;return nullptr;}if (focusedWindowHandle-getInfo()-inputConfig.test(WindowInfo::InputConfig::PAUSE_DISPATCHING)) {ALOGI(Waiting because %s is paused, focusedWindowHandle-getName().c_str());outInjectionResult InputEventInjectionResult::PENDING;return nullptr;}// If the event is a key event, then we must wait for all previous events to// complete before delivering it because previous events may have the// side-effect of transferring focus to a different window and we want to// ensure that the following keys are sent to the new window.//// Suppose the user touches a button in a window then immediately presses A.// If the button causes a pop-up window to appear then we want to ensure that// the A key is delivered to the new pop-up window. This is because users// often anticipate pending UI changes when typing on a keyboard.// To obtain this behavior, we must serialize key events with respect to all// prior input events.if (entry.type EventEntry::Type::KEY) {if (shouldWaitToSendKeyLocked(currentTime, focusedWindowHandle-getName().c_str())) {*nextWakeupTime *mKeyIsWaitingForEventsTimeout;outInjectionResult InputEventInjectionResult::PENDING;return nullptr;}}outInjectionResult InputEventInjectionResult::SUCCEEDED;return focusedWindowHandle;
}可以看出引发 无焦点ANR 的两个条件1.mNoFocusedWindowTimeoutTime.has_value() mAwaitedFocusedApplication ! nullptr 并且 currentTime *mNoFocusedWindowTimeoutTime
mNoFocusedWindowTimeoutTime 和 mAwaitedFocusedApplication 的设置是在 InputDispatcher::findFocusedWindowTargetsLocked 函数中: 当有焦点应用但没有焦点窗口设置 mNoFocusedWindowTimeoutTime 的值开启 ANR 倒计时。对于当前事件返回 PENDING 。 接着在当前的派发循环中执行 processAnrsLocked 函数判断是否引发 ANR。
重置 mNoFocusedWindowTimeoutTime 和 mAwaitedFocusedApplication 是在 InputDispatcher::resetNoFocusedWindowTimeoutLocked 中。
执行 resetNoFocusedWindowTimeoutLocked 的几个时机 (1)InputDispatcher::findFocusedWindowTargetLocked中当等待有焦点窗口后
(2)InputDispatcher::setFocusedApplication 中切换焦点应用后;
(3)InputDispatcher::setInputDispatchMode 中;
(4) InputDispatcher::resetAndDropEverythingLocked
无焦点anr
void InputDispatcher::processNoFocusedWindowAnrLocked() {// Check if the application that we are waiting for is still focused.std::shared_ptrInputApplicationHandle focusedApplication getValueByKey(mFocusedApplicationHandlesByDisplay, mAwaitedApplicationDisplayId);if (focusedApplication nullptr ||focusedApplication-getApplicationToken() !mAwaitedFocusedApplication-getApplicationToken()) {// Unexpected because we should have reset the ANR timer when focused application changedALOGE(Waited for a focused window, but focused application has already changed to %s,focusedApplication-getName().c_str());return; // The focused application has changed.}const spWindowInfoHandle focusedWindowHandle getFocusedWindowHandleLocked(mAwaitedApplicationDisplayId);if (focusedWindowHandle ! nullptr) {return; // We now have a focused window. No need for ANR.}onAnrLocked(mAwaitedFocusedApplication);
}void InputDispatcher::onAnrLocked(std::shared_ptrInputApplicationHandle application) {std::string reason StringPrintf(%s does not have a focused window, application-getName().c_str());updateLastAnrStateLocked(*application, reason);auto command [this, application std::move(application)]() REQUIRES(mLock) {scoped_unlock unlock(mLock);mPolicy.notifyNoFocusedWindowAnr(application);};postCommandLocked(std::move(command));
}无响应anr void InputDispatcher::onAnrLocked(const std::shared_ptrConnection 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. Dont raise ANR in this situationif (connection-waitQueue.empty()) {ALOGI(Not raising ANR because the connection %s has recovered,connection-inputChannel-getName().c_str());return;}/*** The oldestEntry is the entry that was first sent to the application. That entry, however,* may not be the one that caused the timeout to occur. One possibility is that window timeout* has changed. This could cause newer entries to time out before the already dispatched* entries. In that situation, the newest entries caused ANR. But in all likelihood, the app* processes the events linearly. So providing information about the oldest entry seems to be* most useful.*/DispatchEntry* oldestEntry *connection-waitQueue.begin();const nsecs_t currentWait now() - oldestEntry-deliveryTime;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());spIBinder connectionToken connection-inputChannel-getConnectionToken();updateLastAnrStateLocked(getWindowHandleLocked(connectionToken), reason);//处理无响应anr
processConnectionUnresponsiveLocked(*connection, std::move(reason));
// cnnel所有事件// Stop waking up for events on this connection, it is already unresponsivecancelEventsForAnrLocked(connection);
}void InputDispatcher::processConnectionUnresponsiveLocked(const Connection connection,std::string reason) {const spIBinder connectionToken connection.inputChannel-getConnectionToken();std::optionalint32_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 windowALOGW(Window %s is unresponsive: %s, connection.inputChannel-getName().c_str(),reason.c_str());const spWindowInfoHandle handle getWindowHandleLocked(connectionToken);if (handle ! nullptr) {pid handle-getInfo()-ownerPid;}}
//发送窗口无响应命令sendWindowUnresponsiveCommandLocked(connectionToken, pid, std::move(reason));
}
//当这个command被执行时调用的为doNotifyWindowUnresponsiveLockedInterruptible
void InputDispatcher::doNotifyWindowUnresponsiveLockedInterruptible(CommandEntry* commandEntry) {mLock.unlock();mPolicy-notifyWindowUnresponsive(commandEntry-connectionToken, commandEntry-reason); //调用到jni层向java层传递mLock.lock();
}
ANR 的通知
// Native callback
SuppressWarnings(unused)
private void notifyWindowUnresponsive(IBinder token, int pid, boolean isPidValid,String reason) {mWindowManagerCallbacks.notifyWindowUnresponsive(token,isPidValid ? OptionalInt.of(pid) : OptionalInt.empty(), reason);
}
调用java层发送弹窗命令, 就不细说了