在上篇文章中,介绍ANR产生的原因、ANR的分类以及ANR问题的分析。本篇文章接下来将从源码的角度来分析ANR产生的过程,首先介绍InputDispatcher Timeout产生的过程。在ANR产生时,最终都会调用到appNotResponding()方法,该方法在Android 7.0以前定义在ActivityManagerService.java类中,在Android 7.0中定义在AppErrors.java类中,本文将以Android 7.0源码来分析ANR的产生过程。首先来分析appNotResponding()方法,在该方法中将记录一些ANR的信息到event、system、trace日志文件中,并发送应用未响应Dialog给系统显示。ANR日志分析将在下一个小节中描述,appNotResponding()在frameworks/base/services/core/java/com/android/server/am/AppErrors.java文件中实现:
/*
* 该函数的主要作用是记录发生ANR的信息到日志文件中,包括event日志、system日志以及trace日志中,
* 同时在应用显示一个ANR Dialog通知应用发生了ANR
*/
final void appNotResponding(ProcessRecord app, ActivityRecord activity,
ActivityRecord parent, boolean aboveSystem, final String annotation) {
//保存最近执行的进程号
ArrayList<Integer> firstPids = new ArrayList<Integer>(5);
SparseArray<Boolean> lastPids = new SparseArray<Boolean>(20);
...........
//记录发生ANR的时间
long anrTime = SystemClock.uptimeMillis();
if (ActivityManagerService.MONITOR_CPU_USAGE) {
//第一次更新CPU的状态
mService.updateCpuStatsNow();
}
// Unless configured otherwise, swallow ANRs in background processes & kill the process.
boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ANR_SHOW_BACKGROUND, 0) != 0;
boolean isSilentANR;
//在system日志中,打印ANR发生的原因
synchronized (mService) {
.........
app.notResponding = true;
//1.记录ANR日志到event日志中
EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid,
app.processName, app.info.flags, annotation);
// 将应用pid添加到firstPids集合中
firstPids.add(app.pid);
isSilentANR = !showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID;
if (!isSilentANR) {
int parentPid = app.pid;
if (parent != null && parent.app != null && parent.app.pid > 0) {
parentPid = parent.app.pid;
}
if (parentPid != app.pid) firstPids.add(parentPid);//添加父进程的pid到firstPids集合中
if (MY_PID != app.pid && MY_PID != parentPid) firstPids.add(MY_PID);//再将当前应用的pid添加到firstPids集合中
//将最近使用的进程pid添加到firstPids和lastPids集合中
for (int i = mService.mLruProcesses.size() - 1; i >= 0; i--) {
ProcessRecord r = mService.mLruProcesses.get(i);
if (r != null && r.thread != null) {
int pid = r.pid;
if (pid > 0 && pid != app.pid && pid != parentPid && pid != MY_PID) {
if (r.persistent) {
firstPids.add(pid);
if (DEBUG_ANR) Slog.i(TAG, "Adding persistent proc: " + r);
} else {
lastPids.put(pid, Boolean.TRUE);
if (DEBUG_ANR) Slog.i(TAG, "Adding ANR proc: " + r);
}
}
}
}
}
}
// 2.记录ANR信息到system日志中
StringBuilder info = new StringBuilder();
info.setLength(0);
info.append("ANR in ").append(app.processName);
if (activity != null && activity.shortComponentName != null) {
info.append(" (").append(activity.shortComponentName).append(")");
}
info.append("\n");
info.append("PID: ").append(app.pid).append("\n");
if (annotation != null) {
info.append("Reason: ").append(annotation).append("\n");
}
if (parent != null && parent != activity) {
info.append("Parent: ").append(parent.shortComponentName).append("\n");
}
ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
String[] nativeProcs = NATIVE_STACKS_OF_INTEREST;
// 3.记录ANR信息到trace日志文件中
File tracesFile = null;
if (isSilentANR) {
tracesFile = mService.dumpStackTraces(true, firstPids, null, lastPids,
null);
} else {
//调用AMS的dumpStackTraces记录ANR日志到trace文件中
tracesFile = mService.dumpStackTraces(true, firstPids, processCpuTracker, lastPids,
nativeProcs);
}
String cpuInfo = null;
if (ActivityManagerService.MONITOR_CPU_USAGE) {
//第二次更新CPU的状态
mService.updateCpuStatsNow();
synchronized (mService.mProcessCpuTracker) {
//记录第一次CPU的信息
cpuInfo = mService.mProcessCpuTracker.printCurrentState(anrTime);
}
info.append(processCpuTracker.printCurrentLoad());
info.append(cpuInfo);
}
//记录第二次CPU的信息
info.append(processCpuTracker.printCurrentState(anrTime));
//记录ANR信息到system日志中
Slog.e(TAG, info.toString());
if (tracesFile == null) {
// There is no trace file, so dump (only) the alleged culprit's threads to the log