当前位置:   article > 正文

Android深入理解 ANR 触发原理:InputManager_waiting because no window has focus but there is a

waiting because no window has focus but there is a focused application that

五 、InputDispatching Timeout 

   在看这篇博文,大家可以参考看gityuan  《Input系统—InputDispatcher线程》Input系统—ANR原理分析

ANR时间区间便是指当前这次的事件dispatch过程中执行findFocusedWindowTargetsLocked()方法到下一次执行resetANRTimeoutsLocked()的时间区间. 以下5个时机会reset. 都位于InputDispatcher.cpp文件:

  • resetAndDropEverythingLocked

  • releasePendingEventLocked

  • setFocusedApplication

  • dispatchOnceInnerLocked

  • setInputDispatchMode

简单来说, 主要是以下4个场景,会有机会执行resetANRTimeoutsLocked:

  • 解冻屏幕, 系统开/关机的时刻点 (thawInputDispatchingLw, setEventDispatchingLw)

  • wms聚焦app的改变 (WMS.setFocusedApp, WMS.removeAppToken)

  • 设置input filter的过程 (IMS.setInputFilter)

  • 再次分发事件的过程(dispatchOnceInnerLocked)

InputDispatcher线程 findFocusedWindowTargetsLocked()过程调用到handleTargetsNotReadyLocked,且满足超时5s的情况则会调用onANRLocked().

5.1 dispatchMotionLocked

  1. bool InputDispatcher::dispatchMotionLocked(
  2. nsecs_t currentTime, MotionEntry* entry, DropReason* dropReason, nsecs_t* nextWakeupTime) {
  3. ATRACE_CALL();
  4. // Preprocessing.
  5. if (! entry->dispatchInProgress) {
  6. entry->dispatchInProgress = true;
  7. logOutboundMotionDetails("dispatchMotion - ", entry);
  8. }
  9. // Clean up if dropping the event.
  10. if (*dropReason != DROP_REASON_NOT_DROPPED) {
  11. setInjectionResult(entry, *dropReason == DROP_REASON_POLICY
  12. ? INPUT_EVENT_INJECTION_SUCCEEDED : INPUT_EVENT_INJECTION_FAILED);
  13. return true;
  14. }
  15. bool isPointerEvent = entry->source & AINPUT_SOURCE_CLASS_POINTER;
  16. // Identify targets.
  17. std::vector<InputTarget> inputTargets;
  18. bool conflictingPointerActions = false;
  19. int32_t injectionResult;
  20. if (isPointerEvent) {//点击事件
  21. // Pointer event. (eg. touchscreen)
  22. injectionResult = findTouchedWindowTargetsLocked(currentTime,
  23. entry, inputTargets, nextWakeupTime, &conflictingPointerActions);
  24. } else {//触摸事件
  25. // Non touch event. (eg. trackball)
  26. injectionResult = findFocusedWindowTargetsLocked(currentTime,
  27. entry, inputTargets, nextWakeupTime);
  28. }
  29. if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
  30. return false;
  31. }
  32. setInjectionResult(entry, injectionResult);
  33. if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
  34. if (injectionResult != INPUT_EVENT_INJECTION_PERMISSION_DENIED) {
  35. CancelationOptions::Mode mode(isPointerEvent ?
  36. CancelationOptions::CANCEL_POINTER_EVENTS :
  37. CancelationOptions::CANCEL_NON_POINTER_EVENTS);
  38. CancelationOptions options(mode, "input event injection failed");
  39. synthesizeCancelationEventsForMonitorsLocked(options);
  40. }
  41. return true;
  42. }
  43. // Add monitor channels from event's or focused display.
  44. addGlobalMonitoringTargetsLocked(inputTargets, getTargetDisplayId(entry));
  45. if (isPointerEvent) {
  46. ssize_t stateIndex = mTouchStatesByDisplay.indexOfKey(entry->displayId);
  47. if (stateIndex >= 0) {
  48. const TouchState& state = mTouchStatesByDisplay.valueAt(stateIndex);
  49. if (!state.portalWindows.empty()) {
  50. // The event has gone through these portal windows, so we add monitoring targets of
  51. // the corresponding displays as well.
  52. for (size_t i = 0; i < state.portalWindows.size(); i++) {
  53. const InputWindowInfo* windowInfo = state.portalWindows[i]->getInfo();
  54. addGlobalMonitoringTargetsLocked(inputTargets, windowInfo->portalToDisplayId,
  55. -windowInfo->frameLeft, -windowInfo->frameTop);
  56. }
  57. }
  58. }
  59. }
  60. // Dispatch the motion.
  61. if (conflictingPointerActions) {
  62. CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
  63. "conflicting pointer actions");
  64. synthesizeCancelationEventsForAllConnectionsLocked(options);
  65. }
  66. dispatchEventLocked(currentTime, entry, inputTargets);
  67. return true;
  68. }

当事件到来系统会分:点击事件还触摸事件来处理。 

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);
    }

5.2 findTouchedWindowTargetsLocked

  1. int32_t InputDispatcher::findFocusedWindowTargetsLocked(nsecs_t currentTime,
  2. const EventEntry* entry, Vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime) {
  3. int32_t injectionResult;
  4. String8 reason;
  5. if (mFocusedWindowHandle == NULL) {
  6. if (mFocusedApplicationHandle != NULL) {
  7. //无窗口, 有应用
  8. injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
  9. mFocusedApplicationHandle, NULL, nextWakeupTime,
  10. "Waiting because no window has focus but there is a "
  11. "focused application that may eventually add a window "
  12. "when it finishes starting up.");
  13. goto Unresponsive;
  14. }
  15. //无窗口,无应用
  16. ALOGI("Dropping event because there is no focused window or focused application.");
  17. injectionResult = INPUT_EVENT_INJECTION_FAILED;
  18. goto Failed;
  19. }
  20. //权限检查
  21. if (! checkInjectionPermission(mFocusedWindowHandle, entry->injectionState)) {
  22. injectionResult = INPUT_EVENT_INJECTION_PERMISSION_DENIED;
  23. goto Failed;
  24. }
  25. //检测窗口是否为更多的输入操作而准备就绪
  26. reason = checkWindowReadyForMoreInputLocked(currentTime,
  27. mFocusedWindowHandle, entry, "focused");
  28. if (!reason.isEmpty()) {
  29. injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
  30. mFocusedApplicationHandle, mFocusedWindowHandle, nextWakeupTime, reason.string());
  31. goto Unresponsive;
  32. }
  33. injectionResult = INPUT_EVENT_INJECTION_SUCCEEDED;
  34. //成功找到目标窗口,添加到目标窗口
  35. addWindowTargetLocked(mFocusedWindowHandle,
  36. InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS, BitSet32(0),
  37. inputTargets);
  38. Failed:
  39. Unresponsive:
  40. //TODO: 统计等待时长信息,目前没有实现,这个方法还是很值得去改造
  41. nsecs_t timeSpentWaitingForApplication = getTimeSpentWaitingForApplicationLocked(currentTime);
  42. updateDispatchStatisticsLocked(currentTime, entry,
  43. injectionResult, timeSpentWaitingForApplication);
  44. return injectionResult;
  45. }

寻找聚焦窗口失败的情况:

  • 无窗口,无应用:Dropping event because there is no focused window or focused application.(这并不导致ANR的情况,因为没有机会调用handleTargetsNotReadyLocked)
  • 无窗口, 有应用:Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.

另外,还有更多的失败场景见checkWindowReadyForMoreInputLocked的过程,如下

  1. String8 InputDispatcher::checkWindowReadyForMoreInputLocked(nsecs_t currentTime,
  2. const sp<InputWindowHandle>& windowHandle, const EventEntry* eventEntry,
  3. const char* targetType) {
  4. //当窗口暂停的情况,则保持等待
  5. if (windowHandle->getInfo()->paused) {
  6. return String8::format("Waiting because the %s window is paused.", targetType);
  7. }
  8. //当窗口连接未注册,则保持等待
  9. ssize_t connectionIndex = getConnectionIndexLocked(windowHandle->getInputChannel());
  10. if (connectionIndex < 0) {
  11. return String8::format("Waiting because the %s window's input channel is not "
  12. "registered with the input dispatcher. The window may be in the process "
  13. "of being removed.", targetType);
  14. }
  15. //当窗口连接已死亡,则保持等待
  16. sp<Connection> connection = mConnectionsByFd.valueAt(connectionIndex);
  17. if (connection->status != Connection::STATUS_NORMAL) {
  18. return String8::format("Waiting because the %s window's input connection is %s."
  19. "The window may be in the process of being removed.", targetType,
  20. connection->getStatusLabel());
  21. }
  22. // 当窗口连接已满,则保持等待
  23. if (connection->inputPublisherBlocked) {
  24. return String8::format("Waiting because the %s window's input channel is full. "
  25. "Outbound queue length: %d. Wait queue length: %d.",
  26. targetType, connection->outboundQueue.count(), connection->waitQueue.count());
  27. }
  28. if (eventEntry->type == EventEntry::TYPE_KEY) {
  29. // 按键事件,输出队列或事件等待队列不为空
  30. if (!connection->outboundQueue.isEmpty() || !connection->waitQueue.isEmpty()) {
  31. return String8::format("Waiting to send key event because the %s window has not "
  32. "finished processing all of the input events that were previously "
  33. "delivered to it. Outbound queue length: %d. Wait queue length: %d.",
  34. targetType, connection->outboundQueue.count(), connection->waitQueue.count());
  35. }
  36. } else {
  37. // 非按键事件,事件等待队列不为空且头事件分发超时500ms
  38. if (!connection->waitQueue.isEmpty()
  39. && currentTime >= connection->waitQueue.head->deliveryTime
  40. + STREAM_AHEAD_EVENT_TIMEOUT) {
  41. return String8::format("Waiting to send non-key event because the %s window has not "
  42. "finished processing certain input events that were delivered to it over "
  43. "%0.1fms ago. Wait queue length: %d. Wait queue head age: %0.1fms.",
  44. targetType, STREAM_AHEAD_EVENT_TIMEOUT * 0.000001f,
  45. connection->waitQueue.count(),
  46. (currentTime - connection->waitQueue.head->deliveryTime) * 0.000001f);
  47. }
  48. }
  49. return String8::empty();

5.3 findTouchedWindowTargetsLocked

  1. int32_t InputDispatcher::findTouchedWindowTargetsLocked(nsecs_t currentTime,
  2. const MotionEntry* entry, std::vector<InputTarget>& inputTargets, nsecs_t* nextWakeupTime,
  3. bool* outConflictingPointerActions) {
  4. ATRACE_CALL();
  5. enum InjectionPermission {
  6. INJECTION_PERMISSION_UNKNOWN,
  7. INJECTION_PERMISSION_GRANTED,
  8. INJECTION_PERMISSION_DENIED
  9. };
  10. ......
  11. // Ensure all touched foreground windows are ready for new input.
  12. for (const TouchedWindow& touchedWindow : mTempTouchState.windows) {
  13. if (touchedWindow.targetFlags & InputTarget::FLAG_FOREGROUND) {
  14. // Check whether the window is ready for more input.
  15. std::string reason = checkWindowReadyForMoreInputLocked(currentTime,
  16. touchedWindow.windowHandle, entry, "touched");
  17. if (!reason.empty()) {
  18. injectionResult = handleTargetsNotReadyLocked(currentTime, entry,
  19. nullptr, touchedWindow.windowHandle, nextWakeupTime, reason.c_str());
  20. goto Unresponsive;
  21. }
  22. }
  23. }
  24. .......
  25. }

5.4 handleTargetsNotReadyLocked

  

  1. nt32_t InputDispatcher::handleTargetsNotReadyLocked(nsecs_t currentTime,
  2. const EventEntry* entry,
  3. const sp<InputApplicationHandle>& applicationHandle,
  4. const sp<InputWindowHandle>& windowHandle,
  5. nsecs_t* nextWakeupTime, const char* reason) {
  6. if (applicationHandle == NULL && windowHandle == NULL) {
  7. if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY) {
  8. mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
  9. mInputTargetWaitStartTime = currentTime; //当前时间
  10. mInputTargetWaitTimeoutTime = LONG_LONG_MAX;
  11. mInputTargetWaitTimeoutExpired = false;
  12. mInputTargetWaitApplicationHandle.clear();
  13. }
  14. } else {
  15. if (mInputTargetWaitCause != INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY) {
  16. nsecs_t timeout;
  17. if (windowHandle != NULL) {
  18. timeout = windowHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
  19. } else if (applicationHandle != NULL) {
  20. timeout = applicationHandle->getDispatchingTimeout(DEFAULT_INPUT_DISPATCHING_TIMEOUT);
  21. } else {
  22. timeout = DEFAULT_INPUT_DISPATCHING_TIMEOUT; // 5s
  23. }
  24. mInputTargetWaitCause = INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
  25. //这里的currentTime是指执行dispatchOnceInnerLocked方法体的起点
  26. mInputTargetWaitStartTime = currentTime;
  27. mInputTargetWaitTimeoutTime = currentTime + timeout;
  28. mInputTargetWaitTimeoutExpired = false;
  29. mInputTargetWaitApplicationHandle.clear();
  30. if (windowHandle != NULL) {
  31. mInputTargetWaitApplicationHandle = windowHandle->inputApplicationHandle;
  32. }
  33. if (mInputTargetWaitApplicationHandle == NULL && applicationHandle != NULL) {
  34. mInputTargetWaitApplicationHandle = applicationHandle;
  35. }
  36. }
  37. }
  38. if (mInputTargetWaitTimeoutExpired) {
  39. return INPUT_EVENT_INJECTION_TIMED_OUT; //等待超时已过期,则直接返回
  40. }
  41. //当超时5s,则进入ANR流程
  42. if (currentTime >= mInputTargetWaitTimeoutTime) {
  43. onANRLocked(currentTime, applicationHandle, windowHandle,
  44. entry->eventTime, mInputTargetWaitStartTime, reason);
  45. *nextWakeupTime = LONG_LONG_MIN; //强制立刻执行轮询来执行ANR策略
  46. return INPUT_EVENT_INJECTION_PENDING;
  47. } else {
  48. if (mInputTargetWaitTimeoutTime < *nextWakeupTime) {
  49. *nextWakeupTime = mInputTargetWaitTimeoutTime; //当触发超时则强制执行轮询
  50. }
  51. return INPUT_EVENT_INJECTION_PENDING;
  52. }
  53. }

handleTargetsNotReadyLocked()的判断过程:

  • 当applicationHandle和windowHandle同时为空, 且system准备就绪的情况下
    • 设置等待理由 INPUT_TARGET_WAIT_CAUSE_SYSTEM_NOT_READY;
    • 设置超时等待时长为无限大;
    • 设置TimeoutExpired= false
    • 清空等待队列;
  • 当applicationHandle和windowHandle至少一个不为空, 且application准备就绪的情况下:
    • 设置等待理由 INPUT_TARGET_WAIT_CAUSE_APPLICATION_NOT_READY;
    • 设置超时等待时长为5s;
    • 设置TimeoutExpired= false
    • 清空等待队列;

5.5 onANRLocked

  1. void InputDispatcher::onANRLocked(
  2. nsecs_t currentTime, const sp<InputApplicationHandle>& applicationHandle,
  3. const sp<InputWindowHandle>& windowHandle,
  4. nsecs_t eventTime, nsecs_t waitStartTime, const char* reason) {
  5. float dispatchLatency = (currentTime - eventTime) * 0.000001f;
  6. float waitDuration = (currentTime - waitStartTime) * 0.000001f;
  7. ALOGI("Application is not responding: %s. "
  8. "It has been %0.1fms since event, %0.1fms since wait started. Reason: %s",
  9. getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(),
  10. dispatchLatency, waitDuration, reason);
  11. //捕获ANR的现场信息
  12. time_t t = time(NULL);
  13. struct tm tm;
  14. localtime_r(&t, &tm);
  15. char timestr[64];
  16. strftime(timestr, sizeof(timestr), "%F %T", &tm);
  17. mLastANRState.clear();
  18. mLastANRState.append(INDENT "ANR:\n");
  19. mLastANRState.appendFormat(INDENT2 "Time: %s\n", timestr);
  20. mLastANRState.appendFormat(INDENT2 "Window: %s\n",
  21. getApplicationWindowLabelLocked(applicationHandle, windowHandle).string());
  22. mLastANRState.appendFormat(INDENT2 "DispatchLatency: %0.1fms\n", dispatchLatency);
  23. mLastANRState.appendFormat(INDENT2 "WaitDuration: %0.1fms\n", waitDuration);
  24. mLastANRState.appendFormat(INDENT2 "Reason: %s\n", reason);
  25. dumpDispatchStateLocked(mLastANRState);
  26. //将ANR命令加入mCommandQueue
  27. CommandEntry* commandEntry = postCommandLocked(
  28. & InputDispatcher::doNotifyANRLockedInterruptible);
  29. commandEntry->inputApplicationHandle = applicationHandle;
  30. commandEntry->inputWindowHandle = windowHandle;
  31. commandEntry->reason = reason;
  32. }

5.6 InputMonitor .notifyANR

  1. public long notifyANR(InputApplicationHandle inputApplicationHandle, InputWindowHandle inputWindowHandle, String reason) {
  2. AppWindowToken appWindowToken = null;
  3. WindowState windowState = null;
  4. boolean aboveSystem = false;
  5. synchronized (mService.mWindowMap) {
  6. if (inputWindowHandle != null) {
  7. windowState = (WindowState) inputWindowHandle.windowState;
  8. if (windowState != null) {
  9. appWindowToken = windowState.mAppToken;
  10. }
  11. }
  12. if (appWindowToken == null && inputApplicationHandle != null) {
  13. appWindowToken = (AppWindowToken)inputApplicationHandle.appWindowToken;
  14. }
  15. //输出input事件分发超时log
  16. if (windowState != null) {
  17. Slog.i(WindowManagerService.TAG, "Input event dispatching timed out "
  18. + "sending to " + windowState.mAttrs.getTitle()
  19. + ". Reason: " + reason);
  20. int systemAlertLayer = mService.mPolicy.windowTypeToLayerLw(
  21. WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
  22. aboveSystem = windowState.mBaseLayer > systemAlertLayer;
  23. } else if (appWindowToken != null) {
  24. Slog.i(WindowManagerService.TAG, "Input event dispatching timed out "
  25. + "sending to application " + appWindowToken.stringName
  26. + ". Reason: " + reason);
  27. } else {
  28. Slog.i(WindowManagerService.TAG, "Input event dispatching timed out "
  29. + ". Reason: " + reason);
  30. }
  31. mService.saveANRStateLocked(appWindowToken, windowState, reason);
  32. }
  33. if (appWindowToken != null && appWindowToken.appToken != null) {
  34. //【见小节3.6.1
  35. boolean abort = appWindowToken.appToken.keyDispatchingTimedOut(reason);
  36. if (! abort) {
  37. return appWindowToken.inputDispatchingTimeoutNanos; //5s
  38. }
  39. } else if (windowState != null) {
  40. //【见小节3.6.2
  41. long timeout = ActivityManagerNative.getDefault().inputDispatchingTimedOut(
  42. windowState.mSession.mPid, aboveSystem, reason);
  43. if (timeout >= 0) {
  44. return timeout * 1000000L; //5s
  45. }
  46. }
  47. return 0;
  48. }

5.7 AMS.inputDispatchingTimedOut

  1. boolean inputDispatchingTimedOut(ProcessRecord proc, String activityShortComponentName,
  2. ApplicationInfo aInfo, String parentShortComponentName,
  3. WindowProcessController parentProcess, boolean aboveSystem, String reason) {
  4. if (checkCallingPermission(FILTER_EVENTS) != PackageManager.PERMISSION_GRANTED) {
  5. throw new SecurityException("Requires permission " + FILTER_EVENTS);
  6. }
  7. final String annotation;
  8. if (reason == null) {
  9. annotation = "Input dispatching timed out";
  10. } else {
  11. annotation = "Input dispatching timed out (" + reason + ")";
  12. }
  13. //如果进程没有被杀死
  14. if (proc != null) {
  15. synchronized (this) {
  16. if (proc.isDebugging()) {
  17. return false;
  18. }
  19. /// M: ANR Debug Mechanism @{
  20. if (mAnrManager.isAnrDeferrable())
  21. return false; /// @}
  22. //如果当前的activity还在进程内运行的情况。
  23. if (proc.getActiveInstrumentation() != null) {
  24. Bundle info = new Bundle();
  25. info.putString("shortMsg", "keyDispatchingTimedOut");
  26. info.putString("longMsg", annotation);
  27. finishInstrumentationLocked(proc, Activity.RESULT_CANCELED, info);//先是finish activity 并且输出报告,然后再杀死进程。
  28. return true;
  29. }
  30. }
  31. //进程ANR的情况,这部分可以看《深入理解 ANR 触发原理:Service》
  32. proc.appNotResponding(activityShortComponentName, aInfo,
  33. parentShortComponentName, parentProcess, aboveSystem, annotation);
  34. }
  35. return true;
  36. }
  1. public void onInstrumentationFinishedLocked(ComponentName name, int resultCode,
  2. Bundle results) {
  3. // pretty printer mode?
  4. String pretty = null;
  5. if (!mRawMode && results != null) {
  6. pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
  7. }
  8. //会有一个system.out 的log 输出,输出内容大概是:Input dispatching timed out +reason
  9. if (pretty != null) {
  10. System.out.println(pretty);
  11. } else {
  12. if (results != null) {
  13. for (String key : sorted(results.keySet())) {
  14. System.out.println(
  15. "INSTRUMENTATION_RESULT: " + key + "=" + results.get(key));
  16. }
  17. }
  18. System.out.println("INSTRUMENTATION_CODE: " + resultCode);
  19. }
  20. }

从上面的代码来看如果发生的activity 还没被杀掉的情况,就会先finish activiy ,然后结束进程,并且输出system.out。因此这个过程是不会在data/anr 目录下生成trace文件

总结:

一、input 触发ANR的情况有:                              

  1. 无窗口, 有应用:Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.
  2. 窗口暂停: Waiting because the [targetType] window is paused.
  3. 窗口未连接: Waiting because the [targetType] window’s input channel is not registered with the input dispatcher. The window may be in the process of being removed.
  4. 窗口连接已死亡:Waiting because the [targetType] window’s input connection is [Connection.Status]. The window may be in the process of being removed.
  5. 窗口连接已满:Waiting because the [targetType] window’s input channel is full. Outbound queue length: [outboundQueue长度]. Wait queue length: [waitQueue长度].
  6. 按键事件,输出队列或事件等待队列不为空:Waiting to send key event because the [targetType] window has not finished processing all of the input events that were previously delivered to it. Outbound queue length: [outboundQueue长度]. Wait queue length: [waitQueue长度].
  7. 非按键事件,事件等待队列不为空且头事件分发超时500ms:Waiting to send non-key event because the [targetType] window has not finished processing certain input events that were delivered to it over 500ms ago. Wait queue length: [waitQueue长度]. Wait queue head age: [等待时长].

 二、触发的log有哪些:   

       1.  ALOGI("Application is not responding: %s. " "It has been %0.1fms since event, %0.1fms since wait started. Reason: %s", getApplicationWindowLabelLocked(applicationHandle, windowHandle).string(), dispatchLatency, waitDuration, reason);

     2. Input event dispatching timed out xxx. Reason: + reason, 其中xxx取值:

  • 窗口类型: sending to windowState.mAttrs.getTitle()
  • 应用类型: sending to application appWindowToken.stringName
  • 其他类型: 则为空.

  3  当activity 不存在的时候: 1.)EventLog.writeEvent(EventLogTags.AM_ANR, userId, pid, processName, info.flags,
                    annotation); 这个log的输出在某些情况是不会输出的,用户定义了ANR的处理。还有就是另外几种情况,isShuttingDown ,isNotResponding ,isCrashing ,killedByAm,killed

                                          2)生成 data/anr/文件,里面保存了一些pid的trace 信息以及cpu信息。

                                           3)DropBoxManager也会输出一些anr的trace信息。

                                          4).如果是前台进程还会有一个AppNotRespondingDialog

4 当activity的进程存在的时候:就会先finish activiy ,然后结束进程,并且输出一个system.out 的log 输出,输出内容大概是:Input dispatching timed out +reason

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号