android的anr
‘壹’ Android ANR 机制
广播的 ANR 处理相对简单,主要是再次判断是否超时、记录日志,记录 ANR 次数等。然后就继续调用 processNextBroadcast 函数,处理下一条广播了。
ContentProvider 超时为 CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10s
Activity 的 ANR 是相对最复杂的,也只有 Activity 中出现的 ANR 会弹出 ANR 提示框。
最终的表现形式是:弹出一个对话框,告诉用户当前某个程序无响应,输入一大堆与 ANR 相关的日志,便于开发者解决问题。
InputDispatching:
Activity 最主要的功能之一是交互,为了方便交互,Android 中的 InputDispatcher 会发出操作事件,最终在 InputManagerService 中发出事件,通过 InputChannel,向 Activity 分发事件。交互事件必须得到响应,如果不能及时处理,IMS 就会报出 ANR,交给 AMS 去弹出 ANR 提示框。
KeyDispatching:
如果输入是个 Key 事件,会从 IMS 进入 ActivityRecord.Token.keyDispatchingTimeOut,然后进入 AMS 处理,不同的是,在 ActivityRecord 中,会先截留一次 Key 的不响应,只有当 Key 连续第二次处理超时,才会弹出 ANR 提示框。
窗口焦点:
Activity 总是需要有一个当前窗口来响应事件的,但如果迟迟没有当前窗口(获得焦点),比如在 Activity 切换时,旧 Activity 已经 onPause,新的 Activity 一直没有 onResume,持续超过 5 秒,就会 ANR。
App 的生命周期太慢,或 CPU 资源不足,或 WMS 异常,都可能导致窗口焦点。
1. 判断是否有 focused 组件以及 focused Application:
这种一般是在应用启动时触发,比如启动时间过长在这过程中触发了 keyevent 或者 trackball moteionevent 就会出现。
对应于
2. 判断前面的事件是否及时完成:
对应于
出现这种问题意味着主线程正在执行其他的事件但是比较耗时导致输入事件无法及时处理。
InputDispatcher 超时是最常见的 ANR 类型,而且其类型也比较多。
当用户触摸屏幕或者按键操作,首次触发的是硬件驱动,驱动收到事件后,将该相应事件写入到输入设备节点, 这便产生了最原生态的内核事件。接着,输入系统取出原生态的事件,经过层层封装后成为 KeyEvent 或者 MotionEvent ;最后,交付给相应的目标窗口(Window)来消费该输入事件。可见,输入系统在整个过程起到承上启下的衔接作用。
Input 模块的主要组成:
每一个应用进程都会有一个 SignalCatcher 线程,专门处理 SIGQUIT,来到 art/runtime/signal_catcher.cc :
当应用发生 ANR 之后,系统会收集许多进程,来 mp 堆栈,从而生成 ANR Trace 文件。收集的第一个,也是一定会被收集到的进程,就是发生 ANR 的进程。接着系统开始向这些应用进程发送 SIGQUIT 信号,应用进程收到 SIGQUIT 后开始 mp 堆栈。
[1] developer ANRs
[2] Android ANR 分析详解
[3] 看完这篇 Android ANR 分析,就可以和面试官装逼了!
[4] 微信 Android 团队手把手教你高效监控 ANR
[5] Input 系统—ANR 原理分析 - Gityuan
[6] 彻底理解安卓应用无响应机制 - Gityuan
[7] 理解 Android ANR 的触发原理 - Gityuan
‘贰’ 【Android】ANR是如何产生的
众所周知,Android的输入事件是通过 InputReader 监听系统 dev/input 下的文件来获取输入事件,并由 InputDispatcher 来进行分发的。
而ANR事件就是在 InputDispatcher 中产生的。
InputDispatcher 内部维护了一个线程 InputDispatcherThread ,输入事件在这个线程中进行处理。这个线程在 InputManager 中进行创建和启动。
它只做了一件事,就是无限调用 dispatchOnce() 进行事件分发。
dispatchOnce() 会调用 dispatchOnceInnerLocked() 进行事件分发,而如果判断出当前事件是触摸事件,则会又调用 dispatchMotionLocked() 来分发触摸事件。在处理结束之后,会阻塞直到下一次事件的到来。
dispatchMotionLocked() 会调用 () 查找触摸事件对应窗口目标并进行分发。如果当前窗口尚有未处理完的事件,则会调用 handleTargetsNotReadyLocked 处理。
handleTargetsNotReadyLocked 会判断目标事件等待时间,如果其大于5秒,则会调用 onANRLocked 进入ANR流程。
以上便是ANR的产生过程。
ANR的产生有两个必要条件:
/frameworks/native/services/inputflinger/InputDispatcher.cpp
Android输入事件分发与拦截