Ref:
http://developer.android.com/training/articles/perf-anr.html
http://stackoverflow.com/questions/3467205/android-key-dispatching-timed-out
http://blog.csdn.net/wuhengde/article/details/8007448
谷歌develop官网上对ANR触发机制是这样描述的:
此处从源码角度分析下AMS和WMS是如何monitor ANR的。
Android版本:Android 5.0
分析对象:keyDispatchingTimedOut的monitor机制
1. keyDispatchingTimedOut(此处‘key‘不准确,其实是InputEvent(包含KeyEvent和TouchEvent)派发超时,当前触屏手机上,以TouchEvent/MotionEvent为主),先看下这块的类图:
可以看到真正干活的是在Native侧,由native侧monitor事件是否超时,并触发调用Java侧notifyANR逻辑。
anr monitor的大概时序如下:
ANR monitor核心工作由InputDispatcher.cpp完成,在每次派发事件时,需要进行如下判断:
1. 判断是否有focused组件及focusedApplication
2. 判断前面的事件是否及时完成
对于1,一般是在启动时可能触发,比如启动时间过长,在这过程中触发keyevent或trackball motionevent, 则进行如下逻辑判断:
这种情况下,对应的ANR log如下:
Reason: Input dispatching timed out (Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.)
对于2,KeyEvent和MotionEvent对“及时性”的策略不同,KeyEvent需要判断上一个事件是否做完(由于涉及focus的问题,KeyEvent必须等wms处理前一个事件,才把新的事件派发过去):
checkWindowReadyForMoreInputLocked
而touchevent(touch screen,e.g.),则需判断事件等待队列里的head的事件时间是否已经过去0.5秒了,相对来说,touchevent的要求更
低些,允许的执行时延更大,此时,说明UI线程卡住了,一堆touch event在等待执行,需要停止event delivery,
因此无论是keyevent(实体键输入)还是touchevent(点击view)都是因为UI线程没及时处理完前面的事件导致.
设置anr的start和timeout值,在timeout时刻唤醒事件,再依据上述条件判断是否可以event delivery,
若满足事件派发条件, 则可以走正常派发流程,否则(如UI线程卡住、UI线程抢不到CPU等), 则触发onANRLocked,后续流程如时序图所示。