android的ANR原理剖析及图解(基于android9.0)
16lz
2021-01-24
android中如果在主线程执行耗时操作,那么将会弹出系统弹窗ANR,那么framework层是如何实现超时的判定、都有哪些情况会产生ANR呢?
经过分析framework源码发现,有以下四种场景会引起ANR
- InputDispatching Timeout: 输入事件分发超时5s,包括按键分发事件的超时
- Service Timeout:服务在12s内未执行完成
- BroadcastQueue Timeout:比如前台广播在10s内执行完成
- ContentProvider Timeout:内容提供者执行超时
Service的ANR判定及处理
首先我们来看一下从启动service到弹出ANR dialog的调用时序图
一共有4个大步骤
- ams先startService
- ActiveServices启动service后,通过ams中的handler发送一个延迟执行消息,低版本android是20秒,9.0的android是12秒,期间如果service执行完成,将会移除这个msg,如果未移除,则在12秒后,ams会执行ActiveServices的serviceTimeout方法进行超时判定
- 执行ActiveServices的serviceTimeout方法,如果 执行开始时间 > (当前时间-超时时间) 时,则超时,调用AppErrors的appNotResponding方法进行超时处理
- AppErrors的appNotResponding超时处理分为以下6个步骤
- 忽略关机时的ANR
- 记录ANR事件
- 记录ANR,打印到main log中
- dump栈信息,输出CPU相关信息
- 添加ANR信息到dropbox日志
- 通知UI线程弹出anr的dialog
输入事件超时判定
和service不同的是,输入事件的超时是在C层的InputDispatcher.cpp中进行判断的,在c中判定超时后通知ams,ams再调用AppErrors进行处理ANR,详细的时序图如下
整个过程一共分为4个大步骤
- dispatchMotionLocked: 分发输入事件
- handleTargetsNotReadyLocked:处理输入事件,并判定是否超时
- notifyANR:一步步通知ANR,通知次序如图所示
- appNotResponding:处理超时,记录日志、弹出ANR的dialog等,此处和service中的处理逻辑一致
在这里我们详细剖析以下handleTargetsNotReadyLocked方法来看一下超时的判定
int32_t InputDispatcher::handleTargetsNotReadyLocked(){...//记录当前事件为第一次分发时间 mInputTargetWaitStartTime = currentTime; //设置超时时间 mInputTargetWaitTimeoutTime = currentTime + timeout;...//判断是否超时超时,当前时间大于上次输入事件记录超时时间,说明有事件分发超时了,需要触发ANR if (currentTime >= mInputTargetWaitTimeoutTime) { onANRLocked(currentTime, applicationHandle, windowHandle, entry->eventTime, mInputTargetWaitStartTime, reason); *nextWakeupTime = LONG_LONG_MIN; return INPUT_EVENT_INJECTION_PENDING; }}
更多相关文章
- 写一个android小闹钟
- 一些databinding 赋值小技巧
- Android(安卓)ANR原因分析(基于traces.txt文件),
- Android:全面&详细的解析Android数据流量统计流程与分析方法(流量
- Android系统input系统(1)
- Android通知——Notification
- 自定义程序实现Android(安卓)EditText只允许输入指定字符
- Android端腾讯性能监控框架Matrix源码分析之第一篇
- [置顶] 超赞!!Android视图讲解!!以及Android内坐标分析!!!