ANR弹窗源码分析

245 阅读3分钟
一、背景
也许你的代码很优秀不怎么出现anr,但还是需要掌握anr的问题定位与处理手段,除此之外还要掌握anr源码原理,了解anr的设计初衷;不只是因为面试会问,主要还是对anr问题定位有一些帮助,尽管anr弹窗原理与导致anr的根因不完全是一件事。本文是anr弹窗原理分析,根因请看另一篇日志案列分析。

二、为什么要设计anr(什么是ANR)

GUI事件系统实时性要求,进程出现故障难以恢复,需要杀掉进程以求系统可用性,还要保障有很好的易用性。
就好比使用mac、window、linux等一样,会出现应用进程卡死等现象,这个时候你就需要通过任务管理器、终端、活动监视器、菜单等方式手动干掉故障进程。
而移动端设计成ANR自动识别或预防预判,然后弹窗,以手动方式杀进程。可以说恰到好处,有极好的易用性(区别与PC的),同时也做了自动收集现场各种日志以供定位处理。
安卓系统是分层的,安卓应用开发是组件模板个性定制化的(不用main函数开始写),fw中对暴露给业务层的一些涉及主线程的模板函数做了时效限制,app开发需要遵循保证主线程有较好的实时性的原则,进而提高系统可用性。
三、实现原理
fw(java与native)的一些逻辑在关于主线程调用的一些被调处(app层)发起anr定时展示消息到队列(事件队列、消息队列),然后及时清理anr消息,超时未清理anr消息被轮询到就展示弹窗。
这实际上是借助了系统已有的消息队列轮询机制,不是简单对主线程全程做监控,而是有针对有特色的约束,可能也是出于对性能的考量。
AMS.Handler.postDelay(ANR,timeout)
AMS.Handler.remove(ANR)
show(AppNotRespondingDialog)
anr日志信息收集与保存

四、有针对有特色的ANR

根据几类组件以及组件特性,有一些不同研判路逻辑与时效规则,网上已归纳部分,可参考文末部分链接
**InputDispatching Timeout**:5秒内无法响应屏幕触摸事件或键盘输入事件
**BroadcastQueue Timeout** :在执行前台广播(BroadcastReceiver)的onReceive()函数时10秒没有处理完成,后台为60秒。
**Service Timeout** :前台服务20秒内,后台服务在200秒内没有执行完毕。
**ContentProvider Timeout** :ContentProvider的publish在10s内没进行完。
**APP,Activity&Fragment&View的一些生命周期**(还没看到有记述,涉及native)
有一些anr发起、取消、弹窗控制是在native代码中的,网上这块儿分析相对少一些,Input有分析到
ANR能cover住各种主线程生命周期模板函数么(比如onpause,ondistroy等)?

五、anr弹窗关闭做了撒

弹窗、关闭方式逻辑差异,anr日志信息的收集与保存

六、部分源码类

AnrHelper
AppNotRespondingDialog
AnrController
InputManagerService

六、网上部分文献

大部分文献分析了java层,漏掉navtive层anr,漏掉了一些场景。

gityuan.com/2017/01/01/… gityuan.com/2016/12/02/… blog.csdn.net/yzpbright/a… blog.csdn.net/cpcpcp123/a… juejin.cn/post/708343… juejin.cn/post/684490… juejin.cn/post/701817…