【问题概要】
上一次我介绍了一种 Android 系统下发生音频 underrun 问题的解决方法(参见《记一次Android系统下解决音频UnderRun问题的过程》),这之后平静了一段时间,测试组同事也没有再报告相关的噪声问题。
但就在前 2 天,测试组同事告诉我说她们又听见噪声了,并且这次的使用场景比上次复杂了许多——由于从 Android 6.0 开始已经支持应用多开以及多窗口的功能,所以她们先在后台运行了一个程序(比如 阴阳师、全民飞机大战 这样的游戏),再在前台播放视频,于是噪声大量出现了。上次问题的情况比较简单,出现噪声时 framesReady 的值与 framesDesired 的值始终相差 2。所以我通过在 Android 原有处理 underrun 问题的方法的延时基础上增加 3 毫秒,解决了问题。但这次的问题,我们从 Log 中可以看到差值分布范围广,使用固定的延时时间已经无法消除噪声。
在 Log 中搜索包含“underrun”关键字的内容可以看到如下记录:
03-07 18:44:04.290 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(407) < framesDesired(516)
03-07 18:44:04.470 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(31) < framesDesired(516)
03-07 18:44:04.570 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(47) < framesDesired(516)
03-07 18:44:04.730 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(79) < framesDesired(516)
03-07 18:44:04.950 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(119) < framesDesired(516)
03-07 18:44:05.007 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(127) < framesDesired(516)
03-07 18:44:05.139 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(151) < framesDesired(516)
03-07 18:44:05.231 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(167) < framesDesired(516)
03-07 18:44:05.323 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(183) < framesDesired(516)
03-07 18:44:05.415 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(199) < framesDesired(516)
03-07 18:44:05.507 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(215) < framesDesired(516)
03-07 18:44:05.563 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(223) < framesDesired(516)
03-07 18:44:05.614 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(231) < framesDesired(516)
03-07 18:44:05.669 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(239) < framesDesired(516)
03-07 18:44:05.783 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(263) < framesDesired(516)
03-07 18:44:05.840 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(271) < framesDesired(516)
03-07 18:44:05.886 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(279) < framesDesired(516)
03-07 18:44:05.937 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(287) < framesDesired(516)
03-07 18:44:05.996 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(295) < framesDesired(516)
03-07 18:44:06.130 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(319) < framesDesired(516)
03-07 18:44:06.187 2828 3521 V AudioFlinger: track(0xf5ea3a80) underrun, framesReady(327) < framesDesired(516)
既然 framesReady与 framesDesired 的差值不再固定,那么我们也应该根据差值大小来调节延时时间来解决问题。只要我们检测到 framesReady 小于 framesDesired,我们就进行 1 毫秒延时,然后再获取延时后的 framesReady 值与 framesDesired 值进行比较,如果 framesReady 仍然小于 framesDesired,那么则继续延时 1 毫秒。如此循环,直到 framesReady 值大于等于 framesDesired 或者超时退出。这次的改动是在上次修复的代码基础上进行的(参见《记一次Android系统下解决音频UnderRun问题的过程》)。话不多说,直接把修复问题的 Patch 贴上来吧,如下:
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 3c941bc..614a5c2 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1454,6 +1454,8 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp& audioFlinge
type_t type,
bool systemReady)
: ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type, systemReady),
+ mLackFrames(0),
+ mNeededFrames(0),
mNormalFrameCount(0), mSinkBuffer(NULL),
mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision),
mMixerBuffer(NULL),
@@ -2729,6 +2731,7 @@ void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
bool AudioFlinger::PlaybackThread::threadLoop()
{
Vector< sp
修改完成后,编译系统并烧写镜像文件到设备上。经测试,该方法对所有之前出现过的 underrun 问题均有效。