android ANR源码分析 --- 之四

来源:互联网 发布:注册淘宝用什么名字好 编辑:程序博客网 时间:2024/05/20 05:29

5,小结

Timeout时长

对于前台服务,则超时为SERVICE_TIMEOUT = 20s;

对于后台服务,则超时为SERVICE_BACKGROUND_TIMEOUT = 200s

对于前台广播,则超时为BROADCAST_FG_TIMEOUT = 10s;

对于后台广播,则超时为BROADCAST_BG_TIMEOUT = 60s;

ContentProvider超时为CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10s;

按键事件为5s;

超时检测

Service超时检测机制:

超过一定时间没有执行完相应操作来触发移除延时消息,则会触发anr;

BroadcastReceiver超时检测机制:

有序广播的总执行时间超过 2* receiver个数 * timeout时长,则会触发anr;

有序广播的某一个receiver执行过程超过 timeout时长,则会触发anr;

另外:

对于Service, Broadcast, Input发生ANR之后,最终都会调用AMS.appNotResponding;

对于provider,在其进程启动时publish过程可能会出现ANR, 则会直接杀进程以及清理相应信息,而不会弹出ANR的对话框.

 appNotRespondingViaProvider()过程会走appNotResponding(), 这个就不介绍了,很少使用,由用户自定义超时时间.

 

6,ANR处理

以下场景都会触发调用AMS.appNotResponding方法:

1,ServiceTimeout:比如前台服务在20s内未执行完成;

2,BroadcastQueueTimeout:比如前台广播在10s内未执行完成

3,InputDispatchingTimeout: 输入事件分发超时5s,包括按键和触摸事件。

 

AMS的appNotResponding方法主要逻辑如下,

1, 输出ANR Reason信息到EventLog. 也就是说ANR触发的时间点最接近的就是EventLog中输出的am_anr信息;

updateCpuStatsNow(); //第一次 更新cpu统计信息synchronized (this) {//PowerManager.reboot() 会阻塞很长时间,因此忽略关机时的ANRif (mShuttingDown) {    return;} else if (app.notResponding) {    return;} else if (app.crashing) {    return;}//记录ANR到EventLogEventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid, app.processName, app.info.flags, annotation);•••

2,收集并输出重要进程列表中的各个线程的traces信息,该方法较耗时;

//创建CPU tracker对象final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);//输出traces信息File tracesFile = dumpStackTraces(true, firstPids, processCpuTracker, lastPids, NATIVE_STACKS_OF_INTEREST);

3, 输出当前各个进程的CPU使用情况以及CPU负载情况;

updateCpuStatsNow(); //第二次更新cpu统计信息//记录当前各个进程的CPU使用情况synchronized (mProcessCpuTracker) {  cpuInfo = mProcessCpuTracker.printCurrentState(anrTime);}//记录当前CPU负载情况info.append(processCpuTracker.printCurrentLoad());info.append(cpuInfo);//记录从anr时间开始的Cpu使用情况info.append(processCpuTracker.printCurrentState(anrTime));//输出当前ANR的reason,以及CPU使用率、负载信息Slog.e(TAG, info.toString()); 

4, 将traces文件和 CPU使用情况信息保存到dropbox,即data/system/dropbox目录

//将traces文件 和 CPU使用率信息保存到dropbox,即data/system/dropbox目录addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,            cpuInfo, tracesFile, null);

5, 根据进程类型,来决定直接后台杀掉,还是弹框告知用户.

synchronized (this) {   ...  //后台ANR的情况, 则直接杀掉  if (!showBackground && !app.isInterestingToUserLocked() && app.pid != MY_PID) {      app.kill("bg anr", true);     return;}•••//弹出ANR对话框Message msg = Message.obtain();HashMap<String, Object> map = new HashMap<String, Object>();msg.what = SHOW_NOT_RESPONDING_MSG;msg.obj = map;msg.arg1 = aboveSystem ? 1 : 0;map.put("app", app);if (activity != null) {   map.put("activity", activity);}//向ui线程发送,内容为SHOW_NOT_RESPONDING_MSG的消息 mUiHandler.sendMessage(msg);}

可以看出,最后终于向ui线程发送内容为SHOW_NOT_RESPONDING_MSG的消息。

这样就是发生ANR时的弹出框。

原创粉丝点击