每日一题:Looper无限循环的阻塞为啥没有ANR
2024-07-06发生ANR的主要四种情况:
1)Service Timeout:前台服务在20s内未执行完成; 2)BroadcastQueue Timeout:前台广播在10s内未执行完成 3)ContentProvider Timeout:内容提供者在publish过超时10s; 4)InputDispatching Timeout:输入事件分发超时5s,包括按键和触摸事件。
对于Service、Broadcast、Provider组件类的ANR而言,如果把发生ANR比作是引爆炸弹,那么整个流程包含三部分组成:
埋炸弹:中控系统(system_server进程)启动倒计时埋下定时器,在规定时间内如果目标(Servcie、Broadcast、Provider)没有干完所有的活,则中控系统会定向炸毁(杀进程)目标,就相当于埋下一个定时炸弹。 拆炸弹:在规定的时间内干完工地的所有活,并及时向中控系统报告完成,请求解除定时炸弹,则幸免于难。 引爆炸弹:中控系统立即封装现场,抓取快照,搜集目标执行慢的罪证(traces),便于后续调试分析,最后是炸毁目标。
对于输入超时,与其他3个组件类ANR是不同的,Input类型的超时机制并非时间到了一定就会爆炸,而是处理后续上报事件的过程才会去检测是否该爆炸,所以更像是扫雷过程。具体的逻辑是这样的:对于输入系统而言,即使某次事件执行时间超过预期的时长,只要用户后续没有再生成输入事件,那么也不需要ANR。而只有当新一轮的输入事件到来,此时正在分发事件的窗口(即App应用本身)迟迟无法释放资源给新的事件去分发,这时InputDispatcher才会根据超时时间,动态的判断是否需要向对应的窗口提示ANR信息。
那么明白了ANR的原因后,我们再来看一下Looper的阻塞原理。