ANR原理篇 - ANR弹框是如何显示出来的

系列文章目录

ANR概述

ANR基础篇 - Trace.txt文件分析

ANR基础篇 - Input系统

ANR基础篇 - 相关系统知识简介

ANR原理篇 - ANR原理总览

ANR原理篇 - ANR弹框是如何显示出来的

ANR原理篇 - service/broadcast/provider超时机制

ANR原理篇 - Input超时机制

ANR原理篇 - ANR信息收集过程

ANR实战案例 - 通用方法总结

ANR实战案例 - 锁优化

ANR实战案例 - FCM拉活启动优化

ANR实战案例 1 - Google广告导致ANR解决

ANR实战案例 2 - 不同线程状态ANR示例

ANR实战案例 3 - 应用在部分低端机ANR优化案例

ANR工具篇 - 监控工具

ANR工具篇 - 分析工具


文章目录

  • 系列文章目录
  • 前言
  • 一、ANR弹框是如何显示流程
    • 1.1 找到弹框对应类
    • 1.2 查找AppNotRespondingDialog引用
    • 1.3 小节
  • 总结


前言

这一章内容比较简单,但对于新手排查系统问题,是一个很好的参考。


一、ANR弹框是如何显示流程

想知道弹框是如何显示的,最简单的方式就是先造一个程序无响应的场景,然后打开uiautomatorviewer工具查看布局,这样我们就可以找到对应的XMl然后在源码中搜索,就能找到我们的目标类了。

1.1 找到弹框对应类

首先我们看到的是下面这样一个场景,先基于android-29的源码全局文字:没有响应,关闭应用,等待,没有搜到,正常,这些文字应该是配置在xml中的。换个思路搜id,关闭应用对应的是aerr_close,全局搜果然搜到了,在AppNotRespondingDialog类中。对应的类名正好也符合:APP无响应。所以说我们的入口找到了。

另外我们看一下AppNotRespondingDialog的包名:com.android.server.am,说明是跑在Serve端的。
ANR原理篇 - ANR弹框是如何显示出来的_第1张图片

1.2 查找AppNotRespondingDialog引用

发现有AppErrors的handleShowAnrUi方法调用的,我们先看整个调用流程:

  1. InputManagerService的notifyANR方法
 // Native callback.
    private long notifyANR(IBinder token, String reason) {
        return mWindowManagerCallbacks.notifyANR(
                token, reason);
    }
  1. InputManagerCallback的notifyANR方法
 @Override
    public long notifyANR(IBinder token, String reason) {
        AppWindowToken appWindowToken = null;
        WindowState windowState = null;
        boolean aboveSystem = false;
        synchronized (mService.mGlobalLock) {
           ...
            //存储日志的
            mService.saveANRStateLocked(appWindowToken, windowState, reason);
        }
 
        // All the calls below need to happen without the WM lock held since they call into AM.
        mService.mAtmInternal.saveANRState(reason);
 
        if (appWindowToken != null && appWindowToken.appToken != null) {
            ...
        } else if (windowState != null) {
            //通知弹出ANR的框
            long timeout = mService.mAmInternal.inputDispatchingTimedOut(
                    windowState.mSession.mPid, aboveSystem, reason);
            if (timeout >= 0) {
                // The activity manager declined to abort dispatching.
                // Wait a bit longer and timeout again later.
                return timeout * 1000000L; // nanoseconds
            }
        }
        return 0; // abort dispatching
    }
  1. ActivityManagerService.LocalService的inputDispatchingTimedOut方法
  2. ActivityManagerService的inputDispatchingTimedOut方法
  3. ProcessRecord的appNotResponding方法
if (mService.mUiHandler != null) {
                // Bring up the infamous App Not Responding dialog
                Message msg = Message.obtain();
                msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG;
                msg.obj = new AppNotRespondingDialog.Data(this, aInfo, aboveSystem);
 
                mService.mUiHandler.sendMessage(msg);
            }
  1. ProcessRecord的appNotResponding方法
case SHOW_NOT_RESPONDING_UI_MSG: {
                mAppErrors.handleShowAnrUi(msg);
                ensureBootCompleted();
            } break;
  1. ProcessRecord的appNotResponding方法
void handleShowAnrUi(Message msg) {
        Dialog dialogToShow = null;
        List<VersionedPackage> packageList = null;
        synchronized (mService) {
            AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
            final ProcessRecord proc = data.proc;
            if (proc == null) {
                Slog.e(TAG, "handleShowAnrUi: proc is null");
                return;
            }
            ...
            if (mService.mAtmInternal.canShowErrorDialogs() || showBackground) {
                dialogToShow = new AppNotRespondingDialog(mService, mContext, data);
                proc.anrDialog = dialogToShow;
            } else {
                MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_ANR,
                        AppNotRespondingDialog.CANT_SHOW);
                // Just kill the app if there is no dialog to be shown.
                mService.killAppAtUsersRequest(proc, null);
            }
        }
        // If we've created a crash dialog, show it without the lock held
        if (dialogToShow != null) {
            dialogToShow.show();//显示程序无响应的框
        }
        ...
    }

1.3 小节

总结一下,流程图如下:
ANR原理篇 - ANR弹框是如何显示出来的_第2张图片


总结

ANR弹框是最直接与用户交互的,可作为我们探索ANR原理的入口。

你可能感兴趣的:(ANR,android,ANR,性能优化,用户感知ANR,卡顿)