Android ANR原理分析

一、概述

ANR(Application Not responding),是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。一般地,这时往往会弹出一个提示框,告知用户当前xxx未响应,用户可选择继续等待或者Force Close。

那么哪些场景会造成ANR呢?

  • Service Timeout:服务在20s内未执行完成;
  • BroadcastQueue Timeout:比如前台广播在10s内执行完成
  • ContentProvider Timeout:内容提供者执行超时
  • inputDispatching Timeout: 输入事件分发超时5s,包括按键分发事件的超时。

二、ANR触发时机

2.1 Service Timeout

Service Timeout触发时机,简单说就是AMS中的mHandler收到SERVICE_TIMEOUT_MSG消息时触发。

在前面文章startService流程分析详细介绍Service启动流程,在Service所在进程attach到system_server进程的过程中会调用realStartServiceLocked()方法

2.1.1 realStartServiceLocked

[-> ActiveServices.java]

2.1.2 bumpServiceExecutingLocked

该方法的主要工作发送delay消息(SERVICE_TIMEOUT_MSG)

  • 对于前台服务,则超时为SERVICE_TIMEOUT,即timeout=20s;
  • 对于后台服务,则超时为SERVICE_BACKGROUND_TIMEOUT,即timeout=200s;

2.1.3 serviceDoneExecutingLocked

该方法的主要工作是当service启动完成,则移除service Timeout消息。

2.1.4 SERVICE_TIMEOUT_MSG

到此不难理解,当SERVICE_TIMEOUT_MSG消息成功发送时,则AMS中的mHandler收到该消息则触发调用serviceTimeout

2.1.5 serviceTimeout

[-> ActiveServices.java]

其中anrMessage的内容为”executing service [发送超时serviceRecord信息]”;

2.2 BroadcastQueue Timeout

BroadcastQueue Timeout触发时机,简单说就是BroadcastQueue中的mHandler收到BROADCAST_TIMEOUT_MSG消息时触发。

在前面文章Android Broadcast广播机制分析详细介绍广播启动流程,在发送广播过程中会执行scheduleBroadcastsLocked方法来处理相关的广播,然后会调用到processNextBroadcast方法来处理下一条广播。

processNextBroadcast执行过程分4步骤:

  • step1. 处理并行广播
  • step2. 处理当前有序广播
  • step3. 获取下条有序广播
  • step4. 处理下条有序广播

2.2.1 processNextBroadcast

[-> BroadcastQueue.java]

对于广播超时处理时机:

  1. 首先在step3的过程中setBroadcastTimeoutLocked(timeoutTime) 设置超时广播消息;
  2. 然后在step2根据广播处理情况来处理:
    • 当广播接收者等待时间过长,则调用broadcastTimeoutLocked(false);
    • 当,cancelBroadcastTimeoutLocked

2.2.2 setBroadcastTimeoutLocked

设置定时广播BROADCAST_TIMEOUT_MSG,即当前往后推mTimeoutPeriod时间广播还没处理完毕,则进入广播超时流程。

  • 对于前台广播,则超时为BROADCAST_FG_TIMEOUT,即timeout=10s;
  • 对于后台广播,则超时为BROADCAST_BG_TIMEOUT,即timeout=60s。

2.2.3 cancelBroadcastTimeoutLocked

移除广播超时消息BROADCAST_TIMEOUT_MSG

2.2.4 BROADCAST_TIMEOUT_MSG

到此不难理解,当BROADCAST_TIMEOUT_MSG消息成功发送时,则AMS中的mHandler收到该消息则触发调用serviceTimeout

2.2.5 broadcastTimeoutLocked

[-> BroadcastRecord.java]

2.2.6 AppNotResponding

[-> BroadcastQueue.java]

2.3 ContentProvider Timeout

2.3.1 AMS.appNotRespondingViaProvider

Timeout时间20s

调用链:

2.4 inputDispatching Timeout

在native层InputDispatcher.cpp中经过层层调用,此处先省略过程,后续再展开,从native层com_android_server_input_InputManagerService调用到java层InputManagerService。

2.4.1 IMS.notifyANR

[-> InputManagerService.java]

mWindowManagerCallbacks为InputMonitor对象

2.4.2 notifyANR

[-> InputMonitor.java]

2.4.3 AMS.inputDispatchingTimedOut

inputDispatching的超时为KEY_DISPATCHING_TIMEOUT,即timeout = 5s

2.4.4 AMS.inputDispatchingTimedOut

调用链:

2.5 keyDispatching Timeout

keyDispatching timout与inputDispatching Timeout流畅基本一致。

调用链:

Token.keyDispatchingTimedOut

[-> ActivityRecord.java]

对于keyDispatching Timeout的ANR,当触发该类型ANR时,如果不再有输入事件,则不会弹出ANR对话框;只有在下一次input事件产生后5s才弹出ANR提示框。

三、ANR工作

3.1 appNotResponding

[-> ActivityManagerService.java]

主要发送ANR, 则会输出

  • 各个进程的CPU使用情况;
  • CPU负载;
  • IOWait;
  • traces文件

四、其他

导致ANR常见情形:

  • I/O阻塞
  • 网络阻塞;
  • onReceiver执行时间超过10s;
  • 多线程死锁

避免ANR:

  • UI线程尽量只做跟UI相关的工作
  • 耗时的工作()比如数据库操作,I/O,网络操作),采用单独的工作线程处理
  • 用Handler来处理UIthread和工作thread的交互

UI线程,例如:

  • Activity:onCreate(), onResume(), onDestroy(), onKeyDown(), onClick(),etc
  • AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel,etc
  • Mainthread handler: handleMessage(), post*(runnable r), etc

ANR分析:需要关注CPU/IO,trace死锁等数据。


先写到这,本文尚未写完,待续…

作者微博:@Gityuan

原文出处:Gityuan.com

1 1 收藏 评论

关于作者:gityuan

Android系统工程师,www.gityuan.com博主,个人新浪微博:http://weibo.com/gityuan 个人主页 · 我的文章 · 3 ·     

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部