jwisp在测试耳机使用的过程中, 发现了一个奇怪的现象.
插入耳机状态, 播放音乐后, 至于后台播放, 然后进入设置铃声的界面使铃声响起,
此时会在耳机和Speaker中同时播放铃声, 但后台播放的音乐却没有了声音,
此时音乐播放器还在播放状态.
最初jwisp设想应该是铃声将音乐的播放的声道给占住了.
但jwisp试验, 若不插入耳机状态, 当音乐和铃声同时启动后, 两个声音都能听到.
看来不是声道切换抢占的问题了.
下面jwisp将自己解决这个问题的过程分享给大家.
相关类
AudioPolicyManagerBase.cpp (frameworks\base\services\audioflinger)
该类负责声音流输出的策略
在声音流的策略中, android定义了有STRATEGY_MEDIA, STRATEGY_SONIFICATION等路由策略.
在上面的情况中
当播放音乐时对应的是STRATEGY_MEDIA 路由策略, 如果没有耳机, 则输出设备为Speaker, 插入耳机则输出设备是耳机
当铃声响起时, 对应的路由策略是STRATEGY_PHONE,没有耳机时, 相应的输出设备是Speaker, 插入耳机时, 相应的输出设备是耳机和Speaker.
一开始播放音乐时,路由策略为STRATEGY_MEDIA ,
铃声响起时,需要切换路由策略,这时就变成STRATEGY_PHONE,相应输出设备也需要更新
此时就会调用到本类中一个输出设置函数 setOutputDevice()
在其代码中, 我们可用看到非常重要的一块:
void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t device, bool force, int delayMs) { ...... // mute media streams if both speaker and headset are selected if (output == mHardwareOutput && AudioSystem::popCount(device) == 2) { setStrategyMute(STRATEGY_MEDIA, true, output); // wait for the PCM output buffers to empty before proceeding with the rest of the command usleep(outputDesc->mLatency*2*1000); } ...... }
这段代码从 android已经说得很明白了, 如果耳机和Speaker同时播放时, 则使音频流静音.
而铃声和闹钟都是会使耳机和Speaker同时播放的策略.
所以这个若想解决这个问题, 想让音乐和铃声闹钟等同时响起, 只需把上面几行代码注释掉即可.