ANR

/data/anr/traces.txt

ANR触发类型

  1. service 前台服务20秒内未执行完成
  2. BroadcastQueue 前台广播10s,后台60s
  3. ContentProvider 内容提供者在publish时超过10s
  4. InputDispathcing 输入时间分发超时5s

触发流程

在Service创建时

ActiveServices.realStartServiceLocked中再通知AMS创建服务时会发送一个延时10s的消息

ActivityThread.handleCreateService中在onCreate执行时会把消息取消,如果超过10s没有取消,ActiveServices会收到消息,会直接调动anr相关方法截取日志并记录

input超时机制

  • InputReader线程负责通过EventHub(监听目录/dev/input)读取输入事件,一旦监听到输入事件则放入到InputDispatcher的mInBoundQueue队列,并通知其处理该事件;
  • InputDispatcher线程负责将接收到的输入事件分发给目标应用窗口,分发过程使用到3个事件队列:
    • mInBoundQueue用于记录InputReader发送过来的输入事件;
    • outBoundQueue用于记录即将分发给目标应用窗口的输入事件;
    • waitQueue用于记录已分发给目标应用,且应用尚未处理完成的输入事件;

input的超时机制并非时间到了一定就会爆炸,而是处理后续上报事件的过程才会去检测是否该爆炸,所以更像是扫雷的过程

线上解决方案

抓取系统traces.txt 上传

1、traces.txt 里面包含所有线程的信息,上传之后需要人工过滤分析
2、很多高版本系统需要root权限才能读取 /data/anr这个目录

ANRWatchDog

开启一个线程,死循环,循环中睡眠5s

往UI线程post 一个Runnable,将_tick 赋值为0,将 _reported 赋值为false

线程睡眠5s之后检查_tick和_reported字段是否被修改

如果_tick和_reported没有被修改,说明给主线程post的Runnable一直没有被执行,也就说明主线程卡顿至少5s(只能说至少,这里存在5s内的误差)

将线程堆栈信息输出