当前位置:   article > 正文

Android ANR 起因的探究_dialog显示会导致anr吗

dialog显示会导致anr吗

        一直以来只知道Android上ANR是因为主线程卡住了,一般5秒就会出现ANR的dialog,一直也没有去深究这个来源。最近在写一个测试程序的时候发现,在主线程上调用了一个阻塞的binder 调用,阻塞了很长时间居然没有ANR,很奇怪,所以终于下决心好好研究下这个问题。

        要搞清楚这个问题,所掌握的线索就只有ANR的时候所弹出的dialog,那么就从dialog上的字符串开始,还好这个“not responding”还是比较独特的。很容易就找到了AppNotResponding这个dilaog类,他是BaseErrorDialog类的子类,果然不出所料他是一个WindowManager.LayoutParams.TYPE_SYSTEM_ALERT的类,而且设置了很多的flag,保证它能显示在APP的前面,不去深究这个了,还是看看是谁让它显示的呢?

早ActivityManagerService里找到一段代码:

  1. case SHOW_NOT_RESPONDING_MSG: {
  2. synchronized (ActivityManagerService.this) {
  3. HashMap data = (HashMap) msg.obj;
  4. ProcessRecord proc = (ProcessRecord)data.get("app");
  5. if (proc != null && proc.anrDialog != null) {
  6. Slog.e(TAG, "App already has anr dialog: " + proc);
  7. return;
  8. }
  9. Intent intent = new Intent("android.intent.action.ANR");
  10. if (!mProcessesReady) {
  11. intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
  12. | Intent.FLAG_RECEIVER_FOREGROUND);
  13. }
  14. broadcastIntentLocked(null, null, intent,
  15. null, null, 0, null, null, null, AppOpsManager.OP_NONE,
  16. false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
  17. if (mShowDialogs) {
  18. Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
  19. mContext, proc, (ActivityRecord)data.get("activity"),
  20. msg.arg1 != 0);
  21. d.show();
  22. proc.anrDialog = d;
  23. } else {
  24. // Just kill the app if there is no dialog to be shown.
  25. killAppAtUsersRequest(proc, null);
  26. }
  27. }
  28. ensureBootCompleted();
  29. } break;
可以发现有人给ActivityManagerService发了这个
SHOW_NOT_RESPONDING_MSG
的消息,才导致了这个可恶的dialog给show了出来,是谁,站出来,我保证不打死它。

在同一个文件里发现了

  1. final void appNotResponding(ProcessRecord app, ActivityRecord activity,
  2. ActivityRecord parent, boolean aboveSystem, final String annotation) {
  3. ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
  4. SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
  5. ......
  6. // Bring up the infamous App Not Responding dialog
  7. Message msg = Message.obtain();
  8. HashMap map = new HashMap();
  9. msg.what = <span style="color: rgb(255, 102, 102);">SHOW_NOT_RESPONDING_MSG</span>;
  10. msg.obj = map;
  11. msg.arg1 = aboveSystem ? 1 : 0;
  12. map.put("app", app);
  13. if (activity != null) {
  14. map.put("activity", activity);
  15. }
  16. mHandler.sendMessage(msg);
  17. }
  18. }
再继续往前追溯真凶 ,原来是InputMonitor搞得鬼。而InputMonitor是WindowManager放到InputManager中的回调。它有一个notifyANR的方法才是这个事件的源头。

  1. // Native callback.
  2. private long notifyANR(InputApplicationHandle inputApplicationHandle,
  3. InputWindowHandle inputWindowHandle) {
  4. return mWindowManagerCallbacks.notifyANR(inputApplicationHandle, inputWindowHandle);
  5. }
这是InputManagerService里面的代码,Native callback,看到这个注释会崩溃,有木有。

等一等,ANR和InputManagerService 扯上了,什么情况。看来不追到native的代码是不行了。

  1. void InputDispatcher::doNotifyANRLockedInterruptible(
  2. CommandEntry* commandEntry) {
  3. mLock.unlock();
  4. nsecs_t newTimeout = mPolicy-><span style="color:#ff6666;">notifyANR</span>(
  5. commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle,
  6. commandEntry->reason);
  7. mLock.lock();
  8. resumeAfterTargetsNotReadyTimeoutLocked(newTimeout,
  9. commandEntry->inputWindowHandle != NULL
  10. ? commandEntry->inputWindowHandle->getInputChannel() : NULL);
  11. }
Native的InputDispatcher会报告这个情况。 在InputDispatcher::handleTargetsNotReadyLocked方法中有这么段代码:

  1. if (<span style="color:#ff6666;">currentTime >= mInputTargetWaitTimeoutTime</span>) {
  2. onANRLocked(currentTime, applicationHandle, windowHandle,
  3. ......
  4. }

mInputTargetWaitTimeoutTime = currentTime + timeout;
timeout =  DEFAULT_INPUT_DISPATCHING_TIMEOUT;
DEFAULT_INPUT_DISPATCHING_TIMEOUT 就是5秒。ok就是这个了。

再进一步查看是谁调用这个doNotifyANRLockedInterruptible, 最终可以发现是在:

  1. bool InputDispatcherThread::threadLoop() {
  2. mDispatcher->dispatchOnce();
  3. return true;
  4. }
这个loop中,这样就可以理解了,原来是在分发input事件 的时候超时了,才会出现这个一连串的反映,最终导致ANR 的dialog给show了出来。

再度感叹,好复杂。不过借此倒可以学习到InputManager - WindowManger -ActivityManager 三者的一定的概念。


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/989668
推荐阅读
相关标签
  

闽ICP备14008679号