前言:
对这个专题总结就到此为止了。
android是一个内容庞大的操作系统,若没有足够的时间去研究学习那就只知皮毛了,遇到问题也无法真正的解决,所以深入源码、了解原理才是系统稳定性的关键,案例看起来是没有什么意义的。而且我对案例的总结只是对问题分析过程的记录,没有过多的分析代码,只是想为此类问题提供下分析的思路。
一、老化测试时SystemUI 出现anr问题
问题分析:
(1)机器在进行音视频老化测试时发生了anr
(2)音视频老化测试的操作主要有
视频播放
音频播放以及音频播放方式的循环切换(从喇叭到听筒)
(3)猜测有可能出现问题的原因
老化测试CPU资源消耗太多,系统卡顿进而导致systemui发生ANR(此种情况发生概率不大)
systemui自身操作太多,进而导致发生ANR(概率较大)
问题排查(没有anr详细信息,这个要命了):
(1)log中的报错信息:
am_anr : [0,23485,com.android.systemui,818429453,Broadcast of Intent { act=android.intent.action.TIME_TICK flg=0x50200014 (has extras) }]
从报错信息看是广播超时导致的anr,但是广播确实很常见的android.intent.action.TIME_TICK广播。那么到这里暂时就不要分析是否是接收android.intent.action.TIME_TICK时导致的anr了,因为TIME_TICK是定时发出的(系统每分钟会发出该广播),不应该是造成anr的主因。
(2)没法继续分析:
到上面为止,问题已经没有办法继续分析了
a.信息不够
b.问题原因无法定位
c.复现问题困难(老化测试耗时且不是必现)
没办法,只能交给测试的同学帮忙复现。
(3)好运气:
我在进行老化测试时,发现systemUI有个奇怪的现象,systemUI进程一直在持续的弹出有关VolumeDialogImpl的log,那anr会不会和这个有关系?
(4)找到突破点:
通过分析SystemUI对Volume的有关处理发现,SystemUI为了在实体按键按下时能够正确的改变当前音频设备的声音大小,一直在监听音频播放方式(喇叭、听筒),当听音频播放方式发生变化是,SystemUI会通过Handler的post方式去处理音频播放方式变化之后的操作。
(5)找到问题原因:
在对SystemUI的Handler的处理过程分析时发现,每次音频播放方式变化的话Handler都会post一个Runnable去处理事件,也就是说当音频播放方式变化频率很高时,Handler所在线程的Looper事件队列中可能会堆积很多等待处理的事件,这就有可能发生anr事件。
那么综上所述,SystemUI的Volume模块可能发生anr报错的条件就有两个
a.变化频率很高。这个是有可能的,毕竟老化测试是对音频模块极限的测试(看下代码发现是3秒一次切换)。
b.Volume的Handler应该是主线程。这个就可以通过以下代码证明。
private final H mHandler = new H();
private final class H extends Handler {
public H() {
super(Looper.getMainLooper());
}
}
问题总结:
此问题是在运气加成的基础上解决的(VolumeDialogImpl其实是没有这个log的,我的同事为了分析其他问题临时添加了一个log,所以运气大大的好),是Handler处理过程设计的不当造成(当然google也没想到我们这么能玩)。android对Looper的设计很棒,这样的设计对于开发者也很友好,但是如果没有真正理解Looper的原理,那就会出现不怎么好玩的问题了。