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工具篇 - 分析工具
这一章内容比较简单,但对于新手排查系统问题,是一个很好的参考。
想知道弹框是如何显示的,最简单的方式就是先造一个程序无响应的场景,然后打开uiautomatorviewer工具查看布局,这样我们就可以找到对应的XMl然后在源码中搜索,就能找到我们的目标类了。
首先我们看到的是下面这样一个场景,先基于android-29的源码全局文字:没有响应,关闭应用,等待,没有搜到,正常,这些文字应该是配置在xml中的。换个思路搜id,关闭应用对应的是aerr_close,全局搜果然搜到了,在AppNotRespondingDialog类中。对应的类名正好也符合:APP无响应。所以说我们的入口找到了。
另外我们看一下AppNotRespondingDialog的包名:com.android.server.am,说明是跑在Serve端的。
发现有AppErrors的handleShowAnrUi方法调用的,我们先看整个调用流程:
// Native callback.
private long notifyANR(IBinder token, String reason) {
return mWindowManagerCallbacks.notifyANR(
token, reason);
}
@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
}
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);
}
case SHOW_NOT_RESPONDING_UI_MSG: {
mAppErrors.handleShowAnrUi(msg);
ensureBootCompleted();
} break;
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();//显示程序无响应的框
}
...
}
ANR弹框是最直接与用户交互的,可作为我们探索ANR原理的入口。