audio 声道路由策略分析

在看示例代码 testPlaybackHeadPositionIncrease 的时候,我们对 play 函数进行了研究。 
不过,当时对 Android 中声音竞争策略相关的内容,并没有详细分析。 
今天就以 AudioTrack 的播放为引子,来仔细看看 Anroid 中各种声音是以什么样的策略来竞争的。

从 Java 侧类 AudioTrack 的 play 函数到函数 AudioFlinger::PlaybackThread::Track::start 之间的调用关系就不再叙述了。 
在看示例代码 testPlaybackHeadPositionIncrease 的时候已经说明过了。 
今天就从函数 AudioFlinger::PlaybackThread::Track::start 开始分析。

*****************************************源码************************************************* 
status_t AudioFlinger::PlaybackThread::Track::start() 

status_t status = NO_ERROR; 
LOGV("start(%d), calling thread %d session %d", 
mName, IPCThreadState::self()->getCallingPid(), mSessionId); 
sp<ThreadBase> thread = mThread.promote(); 
if (thread != 0) { 
Mutex::Autolock _l(thread->mLock); 
int state = mState; 
// here the track could be either new, or restarted 
// in both cases "unstop" the track 
if (mState == PAUSED) { 
mState = TrackBase::RESUMING; 
LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this); 
} else { 
mState = TrackBase::ACTIVE; 
LOGV("? => ACTIVE (%d) on thread %p", mName, this); 
}

if (!isOutputTrack() && state != ACTIVE && state != RESUMING) { 
thread->mLock.unlock(); 
status = AudioSystem::startOutput(thread->id(), 
(AudioSystem::stream_type)mStreamType, 
mSessionId); 
thread->mLock.lock(); 

if (status == NO_ERROR) { 
PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); 
playbackThread->addTrack_l(this); 
} else { 
mState = state; 

} else { 
status = BAD_VALUE; 

return status; 

********************************************************************************************** 
源码路径: 
frameworks\base\services\AudioFlinger.cpp

#######################说明################################ 
status_t AudioFlinger::PlaybackThread::Track::start() 

status_t status = NO_ERROR; 
LOGV("start(%d), calling thread %d session %d", 
mName, IPCThreadState::self()->getCallingPid(), mSessionId); 
sp<ThreadBase> thread = mThread.promote(); 
if (thread != 0) { 
Mutex::Autolock _l(thread->mLock); 
int state = mState; 
// here the track could be either new, or restarted 
// in both cases "unstop" the track 
if (mState == PAUSED) { 
mState = TrackBase::RESUMING; 
LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this); 
} else { 
mState = TrackBase::ACTIVE; 
LOGV("? => ACTIVE (%d) on thread %p", mName, this); 
}

if (!isOutputTrack() && state != ACTIVE && state != RESUMING) { 
thread->mLock.unlock(); 
status = AudioSystem::startOutput(thread->id(), 
(AudioSystem::stream_type)mStreamType, 
mSessionId); 
++++++++++++++++++++++++++++AudioSystem::startOutput++++++++++++++++++++++++++++++++++++ 
从函数 AudioFlinger::PlaybackThread::Track::start 进入: 
status_t AudioSystem::startOutput(audio_io_handle_t output, 
AudioSystem::stream_type stream, 
int session) 

const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service(); 
if (aps == 0) return PERMISSION_DENIED; 
return aps->startOutput(output, stream, session); 
+++++++++++++++++++++++++++++AudioPolicyService::startOutput+++++++++++++++++++++++++++++++++++
从函数 AudioSystem::startOutput 进入: 
status_t AudioPolicyService::startOutput(audio_io_handle_t output, 
AudioSystem::stream_type stream, 
int session) 

if (mpPolicyManager == NULL) { 
return NO_INIT; 

LOGV("startOutput() tid %d", gettid()); 
Mutex::Autolock _l(mLock); 
return mpPolicyManager->startOutput(output, stream, session); 
+++++++++++++++++++++++++++++AudioPolicyManagerBase::startOutput+++++++++++++++++++++++++++++++++++
从函数 AudioPolicyService::startOutput 进入: 
// 主要的处理是从这儿开始的

status_t AudioPolicyManagerBase::startOutput(audio_io_handle_t output, 
AudioSystem::stream_type stream, 
int session) 

LOGV("startOutput() output %d, stream %d, session %d", output, stream, session); 
ssize_t index = mOutputs.indexOfKey(output); 
if (index < 0) { 
LOGW("startOutput() unknow output %d", output); 
return BAD_VALUE; 
}

AudioOutputDescriptor *outputDesc = mOutputs.valueAt(index); 
// 函数 getStrategy 就是根据 stream type 返回特定的 strategy 
routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream); 
++++++++++++++++++++++++++++AudioPolicyManagerBase::getStrategy++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::startOutput 进入:

本来不打算列出该函数,不过,看到后面关于 strategy 优先级的时候,发现需要知道每种策略分别是用来干吗的。 
所以首先要知道策略对应的 stream type , 
AudioPolicyManagerBase::routing_strategy AudioPolicyManagerBase::getStrategy( 
AudioSystem::stream_type stream) { 
// stream to strategy mapping 
switch (stream) { 
case AudioSystem::VOICE_CALL: // 电话来了 
case AudioSystem::BLUETOOTH_SCO: // 蓝牙耳机接通了 
return STRATEGY_PHONE; 
case AudioSystem::RING: // 铃声响了 
case AudioSystem::NOTIFICATION: // 通知,例如界面中最上面一栏中有消息了 
case AudioSystem::ALARM: // 警告,电池没电时的警告? 
case AudioSystem::ENFORCED_AUDIBLE: 
return STRATEGY_SONIFICATION; 
case AudioSystem::DTMF: // 可参考链接:http://baike.baidu.com/view/171916.htm 
return STRATEGY_DTMF; 
default: 
LOGE("unknown stream type"); 
case AudioSystem::SYSTEM: // 系统声音采用 media strategy, 例如,如果正在播放音乐的时候按键, 
// mute 掉音乐,并切换 output 的话,将导致 很差的用户体验。 
// 其中可以得到以下信息: 
// 1、按键声音属于 system stream type 。 
// 2、策略的改变将会导致 output 的切换 
// 3、优先级高的策略 start 时会 mute 掉优先级低的策略 
// NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs 
// while key clicks are played produces a poor result 
case AudioSystem::TTS: // TTS 就是 Text To Speech 
case AudioSystem::MUSIC: 
return STRATEGY_MEDIA; 


返回到函数 AudioPolicyManagerBase::startOutput 
----------------------------AudioPolicyManagerBase::getStrategy------------------------------------

#ifdef WITH_A2DP 
if (mA2dpOutput != 0 && !a2dpUsedForSonification() && strategy == STRATEGY_SONIFICATION) { 
setStrategyMute(STRATEGY_MEDIA, true, mA2dpOutput); 

#endif

// incremenent usage count for this stream on the requested output: 
// NOTE that the usage count is the same for duplicated output and hardware output which is 
// necassary for a correct control of hardware output routing by startOutput() and stopOutput() 
// 增加请求的 output 上该 stream 的使用计数 
// 注意: duplicated output 和 hardware output 中的使用计数是相同的。 
// 因为这对通过 startOutput() 函数和 stopOutput() 函数正确地控制 hardware output routing 是必要的。 
outputDesc->changeRefCount(stream, 1); 
++++++++++++++++++++++++++++AudioPolicyManagerBase::AudioOutputDescriptor::changeRefCount++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::startOutput 进入: 
void AudioPolicyManagerBase::AudioOutputDescriptor::changeRefCount(AudioSystem::stream_type stream, int delta) 

// forward usage count change to attached outputs 
// 如果是 duplicated 的,需要改变它所包含的两个 output 中的使用计数。 
if (isDuplicated()) { 
mOutput1->changeRefCount(stream, delta); 
mOutput2->changeRefCount(stream, delta); 

if ((delta + (int)mRefCount[stream]) < 0) { 
LOGW("changeRefCount() invalid delta %d for stream %d, refCount %d", delta, stream, mRefCount[stream]); 
mRefCount[stream] = 0; 
return; 

mRefCount[stream] += delta; 
LOGV("changeRefCount() stream %d, count %d", stream, mRefCount[stream]); 

返回到函数 AudioPolicyManagerBase::startOutput 
----------------------------AudioPolicyManagerBase::AudioOutputDescriptor::changeRefCount------------------------------------

setOutputDevice(output, getNewDevice(output)); 
++++++++++++++++++++++++++++AudioPolicyManagerBase::getNewDevice++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::startOutput 进入: 
uint32_t AudioPolicyManagerBase::getNewDevice(audio_io_handle_t output, bool fromCache) 

uint32_t device = 0;

AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); 
// check the following by order of priority to request a routing change if necessary: 
// 1: we are in call or the strategy phone is active on the hardware output: 
// use device for strategy phone 
// 2: the strategy sonification is active on the hardware output: 
// use device for strategy sonification 
// 3: the strategy media is active on the hardware output: 
// use device for strategy media 
// 4: the strategy DTMF is active on the hardware output: 
// use device for strategy DTMF 
// 根据以下的优先级顺序,来检查必要的路线改变 
// 1、如果来电话了,或者 hardware output 中的 strategy phone 是活动的, 
// 则使用 phone strategy 。 
// 有两种情况会使用到 strategy phone ,来电话了和蓝牙耳机接通了。 
// 2、如果 hardware output 中的 strategy sonification 是活动的, 
// 则使用 strategy sonification . 
// 有四种情况会使用 stratety sonification ,来电铃声,通知,警告, 
// 和是 ENFORCED_AUDIBLE stream 的时候。 
// 3、如果 hardware output 中的 strategy media 是活动的, 
// 则使用 strategy media . 
// Media 播放, 系统声音和 TTS 会使用 media 策略。 
// 4、如果 hardware output 中的 strategy DTMF 是活动的, 
// 则使用 strategy DTMF . 
// 在 stream type 是 DTMF 的时候会使用 DTMF 策略。 
// 关于 DTMF 请参考 http://baike.baidu.com/view/171916.htm 
if (isInCall() || 
outputDesc->isUsedByStrategy(STRATEGY_PHONE)) { 
// bool isUsedByStrategy(routing_strategy strategy) { return (strategyRefCount(strategy) != 0);} 
+++++++++++++++++++++++++++AudioPolicyManagerBase::AudioOutputDescriptor::strategyRefCount+++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::getNewDevice 进入: 
// 检查 output 中是否使用了指定的 strategy 
uint32_t AudioPolicyManagerBase::AudioOutputDescriptor::strategyRefCount(routing_strategy strategy) 

uint32_t refCount = 0; 
for (int i = 0; i < (int)AudioSystem::NUM_STREAM_TYPES; i++) { 
if (getStrategy((AudioSystem::stream_type)i) == strategy) { 
refCount += mRefCount[i]; 


return refCount; 

返回到函数 AudioPolicyManagerBase::getNewDevice 
---------------------------AudioPolicyManagerBase::AudioOutputDescriptor::strategyRefCount------------------------------------- 
device = getDeviceForStrategy(STRATEGY_PHONE, fromCache); 
} else if (outputDesc->isUsedByStrategy(STRATEGY_SONIFICATION)) { 
device = getDeviceForStrategy(STRATEGY_SONIFICATION, fromCache); 
} else if (outputDesc->isUsedByStrategy(STRATEGY_MEDIA)) { 
device = getDeviceForStrategy(STRATEGY_MEDIA, fromCache); 
} else if (outputDesc->isUsedByStrategy(STRATEGY_DTMF)) { 
device = getDeviceForStrategy(STRATEGY_DTMF, fromCache); 

++++++++++++++++++++++++++++AudioPolicyManagerBase::isInCall++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::getNewDevice 进入: 
bool AudioPolicyManagerBase::isInCall() 

// 函数 AudioPolicyManagerBase::setPhoneState 中会改变 mPhoneState 的值

// 调用关系:android_media_AudioSystem_setPhoneState 
// 调用 AudioSystem::setPhoneState 
// 调用 AudioPolicyService::setPhoneState 
// 调用 AudioPolicyManagerBase::setPhoneState

return isStateInCall(mPhoneState); 
++++++++++++++++++++++++++++AudioPolicyManagerBase::isStateInCall++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::isInCall 进入: 
bool AudioPolicyManagerBase::isStateInCall(int state) { 
return ((state == AudioSystem::MODE_IN_CALL) || 
(state == AudioSystem::MODE_IN_COMMUNICATION)); 
+++++++++++++++++++++++++++++audio_mode+++++++++++++++++++++++++++++++++++ 
从函数 AudioPolicyManagerBase::isStateInCall 进入: 
enum audio_mode { 
MODE_INVALID = -2, 
MODE_CURRENT = -1, 
MODE_NORMAL = 0, 
MODE_RINGTONE, 
MODE_IN_CALL, 
MODE_IN_COMMUNICATION, 
NUM_MODES // not a valid entry, denotes end-of-list 
}; 
返回到函数 AudioPolicyManagerBase::isStateInCall 
-----------------------------audio_mode----------------------------------- 

返回到函数 AudioPolicyManagerBase::isInCall 
----------------------------AudioPolicyManagerBase::isStateInCall------------------------------------ 

返回到函数 AudioPolicyManagerBase::getNewDevice 
----------------------------AudioPolicyManagerBase::isInCall------------------------------------

+++++++++++++++++++++++++++AudioPolicyManagerBase::getDeviceForStrategy+++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::getNewDevice 进入: 
uint32_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache) 

uint32_t device = 0;

if (fromCache) { 
LOGV("getDeviceForStrategy() from cache strategy %d, device %x", strategy, mDeviceForStrategy[strategy]); 
return mDeviceForStrategy[strategy]; 
}

switch (strategy) { 
case STRATEGY_DTMF: 
if (!isInCall()) { 
// 不是打电话过来或者在通话中的话,DTMF strategy 和 MEDIA strategy 规则一样 
// when off call, DTMF strategy follows the same rules as MEDIA strategy 
device = getDeviceForStrategy(STRATEGY_MEDIA, false); 
break; 

// 有电话打过来,或者在通话中的话, DTMF strategy 和 PHONE strategy 规则一致 
// when in call, DTMF and PHONE strategies follow the same rules 
// FALL THROUGH

case STRATEGY_PHONE: 
// 对于 PHONE strategy , 首先判断是否强制要求使用了什么设备,然后再根据优先级顺序,寻找可用的 device 
// for phone strategy, we first consider the forced use and then the available devices by order 
// of priority 
switch (mForceUse[AudioSystem::FOR_COMMUNICATION]) { 
case AudioSystem::FORCE_BT_SCO: 
if (!isInCall() || strategy != STRATEGY_DTMF) { 
// 不是上述两种情况的话,肯定是outputDesc->isUsedByStrategy(STRATEGY_PHONE)作为条件走到这一步的 
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 
if (device) break; 

device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET; 
if (device) break; 
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO; 
if (device) break; 
// 如果请求了 SCO device ,但是没有 SCO device 可用,则进入 default case 
// if SCO device is requested but no SCO device is available, fall back to default case 
// FALL THROUGH

default: // FORCE_NONE 
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE; 
if (device) break; 
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET; 
if (device) break; 
#ifdef WITH_A2DP 
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP 
if (!isInCall()) { 
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP; 
if (device) break; 
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; 
if (device) break; 

#endif 
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_EARPIECE; 
if (device == 0) { 
LOGE("getDeviceForStrategy() earpiece device not found"); 

break;

case AudioSystem::FORCE_SPEAKER: 
if (!isInCall() || strategy != STRATEGY_DTMF) { 
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT; 
if (device) break; 

#ifdef WITH_A2DP 
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to 
// A2DP speaker when forcing to speaker output 
if (!isInCall()) { 
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; 
if (device) break; 

#endif 
device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; 
if (device == 0) { 
LOGE("getDeviceForStrategy() speaker device not found"); 

break; 

break;

case STRATEGY_SONIFICATION:

// If incall, just select the STRATEGY_PHONE device: The rest of the behavior is handled by 
// handleIncallSonification(). 
if (isInCall()) { 
device = getDeviceForStrategy(STRATEGY_PHONE, false); 
break; 

device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; 
if (device == 0) { 
LOGE("getDeviceForStrategy() speaker device not found"); 

// The second device used for sonification is the same as the device used by media strategy 
// FALL THROUGH

case STRATEGY_MEDIA: { 
uint32_t device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_AUX_DIGITAL; 
if (device2 == 0) { 
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HDMI; 

if (device2 == 0) { 
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE; 

if (device2 == 0) { 
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET; 

#ifdef WITH_A2DP 
if (mA2dpOutput != 0) { 
if (strategy == STRATEGY_SONIFICATION && !a2dpUsedForSonification()) { 
break; 

if (device2 == 0) { 
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP; 

if (device2 == 0) { 
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; 

if (device2 == 0) { 
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; 


#endif 
if (device2 == 0) { 
device2 = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_SPEAKER; 
}

// device is DEVICE_OUT_SPEAKER if we come from case STRATEGY_SONIFICATION, 0 otherwise 
device |= device2; 
if (device == 0) { 
LOGE("getDeviceForStrategy() speaker device not found"); 

} break;

default: 
LOGW("getDeviceForStrategy() unknown strategy: %d", strategy); 
break; 
}

LOGV("getDeviceForStrategy() strategy %d, device %x", strategy, device); 
return device; 

返回到函数 AudioPolicyManagerBase::getNewDevice 
---------------------------AudioPolicyManagerBase::getDeviceForStrategy-------------------------------------

LOGV("getNewDevice() selected device %x", device); 
return device; 

返回到函数 AudioPolicyManagerBase::startOutput 
----------------------------AudioPolicyManagerBase::getNewDevice------------------------------------ 
++++++++++++++++++++++++++++AudioPolicyManagerBase::setOutputDevice++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::startOutput 进入 
void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t device, bool force, int delayMs) 

LOGV("setOutputDevice() output %d device %x delayMs %d", output, device, delayMs); 
AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);

// 如果 output 是 duplicated 的,直接去处理其包含的两个 output 
if (outputDesc->isDuplicated()) { 
setOutputDevice(outputDesc->mOutput1->mId, device, force, delayMs); 
setOutputDevice(outputDesc->mOutput2->mId, device, force, delayMs); 
return; 

#ifdef WITH_A2DP 
// filter devices according to output selected 
if (output == m A2dpOutput) { 
device &= AudioSystem::DEVICE_OUT_ALL_A2DP; 
} else { 
device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP; 

#endif

uint32_t prevDevice = (uint32_t)outputDesc->device(); 
// Do not change the routing if: 
// - the requestede device is 0 
// - the requested device is the same as current device and force is not specified. 
// Doing this check here allows the caller to call setOutputDevice() without conditions 
if ((device == 0 || device == prevDevice) && !force) { 
LOGV("setOutputDevice() setting same device %x or null device for output %d", device, output); 
return; 
}

// 修改 output 中的 current device 
outputDesc->mDevice = device; 
// mute media streams if both speaker and headset are selected 
if (output == mHardwareOutput && AudioSystem::popCount(device) == 2) { 
setStrategyMute(STRATEGY_MEDIA, true, output); 
++++++++++++++++++++++++++AudioPolicyManagerBase::setStrategyMute++++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::setOutputDevice 进入 
// mute 掉指定 strategy 对应的所有 stream 
void AudioPolicyManagerBase::setStrategyMute(routing_strategy strategy, bool on, audio_io_handle_t output, int delayMs) 

LOGV("setStrategyMute() strategy %d, mute %d, output %d", strategy, on, output); 
for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { 
if (getStrategy((AudioSystem::stream_type)stream) == strategy) { 
setStreamMute(stream, on, output, delayMs); 
+++++++++++++++++++++++++++AudioPolicyManagerBase::setStreamMute+++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::setStrategyMute 进入 
void AudioPolicyManagerBase::setStreamMute(int stream, bool on, audio_io_handle_t output, int delayMs) 

StreamDescriptor &streamDesc = mStreams[stream]; 
AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output);

LOGV("setStreamMute() stream %d, mute %d, output %d, mMuteCount %d", stream, on, output, outputDesc->mMuteCount[stream]);

if (on) { 
if (outputDesc->mMuteCount[stream] == 0) { 
// 如果该 stream 还没有 mute 过,则对其进行 mute 
if (streamDesc.mCanBeMuted) { 
// mute 其实就是将 stream 的音量设置为 0 
// checkAndSetVolume 函数在此处就先不看了,等到下面看音量设置的时候在分析 
checkAndSetVolume(stream, 0, output, outputDesc->device(), delayMs); 


// increment mMuteCount after calling checkAndSetVolume() so that volume change is not ignored 
// 将 mute 计数加1,以防止声音改变被忽略 
outputDesc->mMuteCount[stream]++; 
} else { 
if (outputDesc->mMuteCount[stream] == 0) { 
// 如果 mute 计数为0,不进行任何操作 
LOGW("setStreamMute() unmuting non muted stream!"); 
return; 

if (--outputDesc->mMuteCount[stream] == 0) { 
// mute 计数减1,若 mute 计数变为0,则将 stream 变为 mute off 
// 也就是恢复 stream 的音量 
checkAndSetVolume(stream, streamDesc.mIndexCur, output, outputDesc->device(), delayMs); 



返回到函数 AudioPolicyManagerBase::setStrategyMute 
---------------------------AudioPolicyManagerBase::setStreamMute------------------------------------- 



返回到函数 AudioPolicyManagerBase::setOutputDevice 
--------------------------AudioPolicyManagerBase::setStrategyMute-------------------------------------- 
// wait for the PCM output buffers to empty before proceeding with the rest of the command 
usleep(outputDesc->mLatency*2*1000); 
}

// do the routing 
AudioParameter param = AudioParameter(); 
param.addInt(String8(AudioParameter::keyRouting), (int)device); 
// 调用的其实是函数 AudioPolicyService::setParameters 
// 会通过函数 AudioPolicyService::AudioCommandThread::parametersCommand 向 AudioCommandThread 的 command list 
// 添加一个 command 
// AudioPolicyService::AudioCommandThread::threadLoop 函数中会处理 command list 中的 command 
// 对于 SET_PARAMETERS command ,最终调用了函数 AudioSystem::setParameters 
// 调用了 AudioFlinger::setParameters 函数 
// 调用了 AudioFlinger::ThreadBase::setParameters 函数添加成员到 mNewParameters 
// 函数 AudioFlinger::MixerThread::checkForNewParameters_l 中会处理 mNewParameters 中的参数 
// 函数 AudioFlinger::MixerThread::threadLoop 会调用函数 AudioFlinger::MixerThread::checkForNewParameters_l 
mpClientInterface->setParameters(mHardwareOutput, param.toString(), delayMs); 
// update stream volumes according to new device 
applyStreamVolumes(output, device, delayMs); 
+++++++++++++++++++++++++AudioPolicyManagerBase::applyStreamVolumes+++++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::setOutputDevice 进入: 
void AudioPolicyManagerBase::applyStreamVolumes(audio_io_handle_t output, uint32_t device, int delayMs) 

LOGV("applyStreamVolumes() for output %d and device %x", output, device);

for (int stream = 0; stream < AudioSystem::NUM_STREAM_TYPES; stream++) { 
checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, device, delayMs); 
++++++++++++++++++++++++++AudioPolicyManagerBase::checkAndSetVolume++++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::applyStreamVolumes 进入: 
status_t AudioPolicyManagerBase::checkAndSetVolume(int stream, int index, audio_io_handle_t output, uint32_t device, int delayMs, bool force /* = false */) 
{

// do not change actual stream volume if the stream is muted 
// 如果 stream 是 mute ,并不真正去改变其音量 
if (mOutputs.valueFor(output)->mMuteCount[stream] != 0) { 
LOGV("checkAndSetVolume() stream %d muted count %d", stream, mOutputs.valueFor(output)->mMuteCount[stream]); 
return NO_ERROR; 
}

// do not change in call volume if bluetooth is connected and vice versa 
// 如果链接了蓝牙耳机,则不去改变 VOICE_CALL 的音量,反之亦然 
if ((stream == AudioSystem::VOICE_CALL && mForceUse[AudioSystem::FOR_COMMUNICATION] == AudioSystem::FORCE_BT_SCO) || 
(stream == AudioSystem::BLUETOOTH_SCO && mForceUse[AudioSystem::FOR_COMMUNICATION] != AudioSystem::FORCE_BT_SCO)) { 
LOGV("checkAndSetVolume() cannot set stream %d volume with force use = %d for comm", 
stream, mForceUse[AudioSystem::FOR_COMMUNICATION]); 
return INVALID_OPERATION; 
}

float volume = computeVolume(stream, index, output, device); 
+++++++++++++++++++++++++++AudioPolicyManagerBase::computeVolume+++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::checkAndSetVolume 进入: 
float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_handle_t output, uint32_t device) 

float volume = 1.0; 
AudioOutputDescriptor *outputDesc = mOutputs.valueFor(output); 
StreamDescriptor &streamDesc = mStreams[stream];

if (device == 0) { 
device = outputDesc->device(); 
}

int volInt = (100 * (index - streamDesc.mIndexMin)) / (streamDesc.mIndexMax - streamDesc.mIndexMin); 
volume = AudioSystem::linearToLog(volInt); 
++++++++++++++++++++++++++AudioSystem::linearToLog++++++++++++++++++++++++++++++++++++++ 
从函数 AudioPolicyManagerBase::computeVolume 进入: 
// convert volume steps to natural log scale

// change this value to change volume scaling 
static const float dBPerStep = 0.5f; 
// shouldn't need to touch these 
static const float dBConvert = -dBPerStep * 2.302585093f / 20.0f; 
static const float dBConvertInverse = 1.0f / dBConvert;

float AudioSystem::linearToLog(int volume) 

// float v = volume ? exp(float(100 - volume) * dBConvert) : 0; 
// LOGD("linearToLog(%d)=%f", volume, v); 
// return v; 
return volume ? exp(float(100 - volume) * dBConvert) : 0; 

返回到函数 AudioPolicyManagerBase::computeVolume 
--------------------------AudioSystem::linearToLog--------------------------------------

// if a headset is connected, apply the following rules to ring tones and notifications 
// to avoid sound level bursts in user's ears: 
// - always attenuate ring tones and notifications volume by 6dB 
// - if music is playing, always limit the volume to current music volume, 
// with a minimum threshold at -36dB so that notification is always perceived. 
// 如果连接了耳机,为了防止在用户耳朵中产生爆音,对铃声和警告声需要使用以下规则: 
// - 对铃声和警告声总是减弱 6dB。 
// - 如果正在播放音乐,铃声和警告声不应该高于音乐声音, 
// 不过,下限是 -36dB 
if ((device & 
(AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP | 
AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES | 
AudioSystem::DEVICE_OUT_WIRED_HEADSET | 
AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) && 
((getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) || 
(stream == AudioSystem::SYSTEM)) && 
streamDesc.mCanBeMuted) { 
// Attenuation applied to STRATEGY_SONIFICATION streams when a headset is connected: 6dB 
// #define SONIFICATION_HEADSET_VOLUME_FACTOR 0.5 
volume *= SONIFICATION_HEADSET_VOLUME_FACTOR; 
// when the phone is ringing we must consider that music could have been paused just before 
// by the music application and behave as if music was active if the last music track was 
// just stopped 
if (outputDesc->mRefCount[AudioSystem::MUSIC] || mLimitRingtoneVolume) { 
float musicVol = computeVolume(AudioSystem::MUSIC, mStreams[AudioSystem::MUSIC].mIndexCur, output, device); 
// Min volume for STRATEGY_SONIFICATION streams when limited by music volume: -36dB 
// #define SONIFICATION_HEADSET_VOLUME_MIN 0.016 
float minVol = (musicVol > SONIFICATION_HEADSET_VOLUME_MIN) ? musicVol : SONIFICATION_HEADSET_VOLUME_MIN; 
if (volume > minVol) { 
volume = minVol; 
LOGV("computeVolume limiting volume to %f musicVol %f", minVol, musicVol); 


}

return volume; 

返回到函数 AudioPolicyManagerBase::checkAndSetVolume 
---------------------------AudioPolicyManagerBase::computeVolume------------------------------------- 
// We actually change the volume if: 
// - the float value returned by computeVolume() changed 
// - the force flag is set 
// 只有当 compute 返回的音量与当前的音量不同,或者强制要求改音量时,才会去真正改变音量 
if (volume != mOutputs.valueFor(output)->mCurVolume[stream] || 
force) { 
mOutputs.valueFor(output)->mCurVolume[stream] = volume; 
LOGV("setStreamVolume() for output %d stream %d, volume %f, delay %d", output, stream, volume, delayMs); 
if (stream == AudioSystem::VOICE_CALL || 
stream == AudioSystem::DTMF || 
stream == AudioSystem::BLUETOOTH_SCO) { 
// offset value to reflect actual hardware volume that never reaches 0 
// 1% corresponds roughly to first step in VOICE_CALL stream volume setting (see AudioService.java) 
volume = 0.01 + 0.99 * volume; 

mpClientInterface->setStreamVolume((AudioSystem::stream_type)stream, volume, output, delayMs); 
+++++++++++++++++++++++++++AudioPolicyService::setStreamVolume+++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::checkAndSetVolume 进入:

status_t AudioPolicyService::setStreamVolume(AudioSystem::stream_type stream, 
float volume, 
audio_io_handle_t output, 
int delayMs) 

// 函数 AudioPolicyService::AudioCommandThread::volumeCommand 会调用函数 AudioPolicyService::AudioCommandThread::insertCommand_l 
// 往 mAudioCommands 中添加成员。 
// 函数 AudioPolicyService::AudioCommandThread::threadLoop 会处理 mAudioCommands 中的成员 
// 对于 SET_VOLUME 命令,调用了函数 AudioSystem::setStreamVolume 
return mAudioCommandThread->volumeCommand((int)stream, volume, (int)output, delayMs); 
+++++++++++++++++++++++++++++AudioSystem::setStreamVolume+++++++++++++++++++++++++++++++++++
从函数 AudioPolicyService::setStreamVolume 进入:

status_t AudioSystem::setStreamVolume(int stream, float value, int output) 

if (uint32_t(stream) >= NUM_STREAM_TYPES) return BAD_VALUE; 
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger(); 
if (af == 0) return PERMISSION_DENIED; 
af->setStreamVolume(stream, value, output); 
++++++++++++++++++++++++++++AudioFlinger::setStreamVolume++++++++++++++++++++++++++++++++++++
从函数 AudioSystem::setStreamVolume 进入:

status_t AudioFlinger::setStreamVolume(int stream, float value, int output) 

// check calling permissions 
if (!settingsAllowed()) { 
return PERMISSION_DENIED; 
}

if (stream < 0 || uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { 
return BAD_VALUE; 
}

AutoMutex lock(mLock); 
PlaybackThread *thread = NULL; 
if (output) { 
thread = checkPlaybackThread_l(output); 
if (thread == NULL) { 
return BAD_VALUE; 

}

mStreamTypes[stream].volume = value;

if (thread == NULL) { 
for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) { 
mPlaybackThreads.valueAt(i)->setStreamVolume(stream, value); 

} else { 
thread->setStreamVolume(stream, value); 
+++++++++++++++++++++++++++++AudioFlinger::PlaybackThread::setStreamVolume+++++++++++++++++++++++++++++++++++
从函数 AudioFlinger::setStreamVolume 进入:

status_t AudioFlinger::PlaybackThread::setStreamVolume(int stream, float value) 

#ifdef LVMX 
int audioOutputType = LifeVibes::getMixerType(mId, mType); 
if (LifeVibes::audioOutputTypeIsLifeVibes(audioOutputType)) { 
LifeVibes::setStreamVolume(audioOutputType, stream, value); 

#endif 
// 这一块在看 testPlaybackHeadPositionIncrease 代码的时候已经介绍过 
mStreamTypes[stream].volume = value; 
return NO_ERROR; 

返回到函数 AudioFlinger::setStreamVolume 
------------------------------AudioFlinger::PlaybackThread::setStreamVolume---------------------------------- 
}

return NO_ERROR; 

返回到函数 AudioSystem::setStreamVolume 
----------------------------AudioFlinger::setStreamVolume------------------------------------ 
return NO_ERROR; 

返回到函数 AudioPolicyService::setStreamVolume 
-----------------------------AudioSystem::setStreamVolume----------------------------------- 

返回到函数 AudioPolicyManagerBase::checkAndSetVolume 
---------------------------AudioPolicyService::setStreamVolume------------------------------------- 
}

if (stream == AudioSystem::VOICE_CALL || 
stream == AudioSystem::BLUETOOTH_SCO) { 
float voiceVolume; 
// Force voice volume to max for bluetooth SCO as volume is managed by the headset 
if (stream == AudioSystem::VOICE_CALL) { 
voiceVolume = (float)index/(float)mStreams[stream].mIndexMax; 
} else { 
voiceVolume = 1.0; 

if (voiceVolume != mLastVoiceVolume && output == mHardwareOutput) { 
// 这儿与 setStreamVolume 函数类似,最终调用到了函数 AudioFlinger::setVoiceVolume 
// 不过,setVoiceVolume最终会调用底层接口,改变硬件音量 
// 这一块也在看 testPlaybackHeadPositionIncrease 代码的时候有看过 
mpClientInterface->setVoiceVolume(voiceVolume, delayMs); 
mLastVoiceVolume = voiceVolume; 

}

return NO_ERROR; 

返回到函数 AudioPolicyManagerBase::applyStreamVolumes 
--------------------------AudioPolicyManagerBase::checkAndSetVolume-------------------------------------- 


返回到函数 AudioPolicyManagerBase::setOutputDevice 
-------------------------AudioPolicyManagerBase::applyStreamVolumes---------------------------------------

// if changing from a combined headset + speaker route, unmute media streams 
// 前面,如果该条件成立,我们做了 mute 操作,此处要做恢复 
if (output == mHardwareOutput && AudioSystem::popCount(prevDevice) == 2) { 
setStrategyMute(STRATEGY_MEDIA, false, output, delayMs); 


返回到函数 AudioPolicyManagerBase::startOutput 
----------------------------AudioPolicyManagerBase::setOutputDevice------------------------------------

// handle special case for sonification while in call 
if (isInCall()) { 
handleIncallSonification(stream, true, false); 
++++++++++++++++++++++++++++AudioPolicyManagerBase::handleIncallSonification++++++++++++++++++++++++++++++++++++
从函数 AudioPolicyManagerBase::startOutput 进入:

void AudioPolicyManagerBase::handleIncallSonification(int stream, bool starting, bool stateChange) 

// if the stream pertains to sonification strategy and we are in call we must 
// mute the stream if it is low visibility. If it is high visibility, we must play a tone 
// in the device used for phone strategy and play the tone if the selected device does not 
// interfere with the device used for phone strategy 
// if stateChange is true, we are called from setPhoneState() and we must mute or unmute as 
// many times as there are active tracks on the output 
// 如果 stream 是 sonification strategy 的,并且其可见性低, 如果有电话打入则 mute 该 stream 。 
// 如果其可见性高,我们必须在 phone strategy 使用的 device 中播放 tone ,并且如果选定的 device 
// 与 phone strategy 不相干的话,也要播放 tone 。 
// 如果 stateChange 是 true ,则我们肯定是从函数 setPhoneState 进来的, 
// 我们必须 mute / unmute output 中所有的 active track 。

if (getStrategy((AudioSystem::stream_type)stream) == STRATEGY_SONIFICATION) { 
AudioOutputDescriptor *outputDesc = mOutputs.valueFor(mHardwareOutput); 
LOGV("handleIncallSonification() stream %d starting %d device %x stateChange %d", 
stream, starting, outputDesc->mDevice, stateChange); 
if (outputDesc->mRefCount[stream]) { 
// 只有 output 中存在 active 的该类型的 stream 时才做处理 
int muteCount = 1; 
if (stateChange) { 
muteCount = outputDesc->mRefCount[stream]; 

if (AudioSystem::isLowVisibility((AudioSystem::stream_type)stream)) { 
++++++++++++++++++++++++++++AudioSystem::isLowVisibility++++++++++++++++++++++++++++++++++++ 
从函数 AudioPolicyManagerBase::handleIncallSonification 进入:

bool AudioSystem::isLowVisibility(stream_type stream) 

// 以下这几种 stream 的可见性低,其他的都是高的 
if (stream == AudioSystem::SYSTEM || 
stream == AudioSystem::NOTIFICATION || 
stream == AudioSystem::RING) { 
return true; 
} else { 
return false; 


返回到函数 AudioPolicyManagerBase::handleIncallSonification 
----------------------------AudioSystem::isLowVisibility------------------------------------ 
LOGV("handleIncallSonification() low visibility, muteCount %d", muteCount); 
for (int i = 0; i < muteCount; i++) { 
setStreamMute(stream, starting, mHardwareOutput); 

} else { 
LOGV("handleIncallSonification() high visibility"); 
if (outputDesc->device() & getDeviceForStrategy(STRATEGY_PHONE)) { 
LOGV("handleIncallSonification() high visibility muted, muteCount %d", muteCount); 
for (int i = 0; i < muteCount; i++) { 
setStreamMute(stream, starting, mHardwareOutput); 


if (starting) { 
mpClientInterface->startTone(ToneGenerator::TONE_SUP_CALL_WAITING, AudioSystem::VOICE_CALL); 
} else { 
mpClientInterface->stopTone(); 





返回到函数 AudioPolicyManagerBase::startOutput 
----------------------------AudioPolicyManagerBase::handleIncallSonification------------------------------------ 
}

// apply volume rules for current stream and device if necessary 
checkAndSetVolume(stream, mStreams[stream].mIndexCur, output, outputDesc->device());

return NO_ERROR; 

返回到函数 AudioPolicyService::startOutput 
-----------------------------AudioPolicyManagerBase::startOutput----------------------------------- 

返回到函数 AudioSystem::startOutput 
-----------------------------AudioPolicyService::startOutput----------------------------------- 

返回到函数 AudioFlinger::PlaybackThread::Track::start 
----------------------------AudioSystem::startOutput------------------------------------ 
thread->mLock.lock(); 

if (status == NO_ERROR) { 
PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); 
playbackThread->addTrack_l(this); 
} else { 
mState = state; 

} else { 
status = BAD_VALUE; 

return status; 

###########################################################

&&&&&&&&&&&&&&&&&&&&&&&总结&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 
各种声音控制策略的实现主要在 Audio Policy Manager 中。 
其中会根据 stream type 和当前的状态对各种 stream 的音量作必要的修改。 
以达成以下的优先级效果:

Priority Strategy Type Stream Type 
4 STRATEGY_PHONE VOICE_CALL 
BLUETOOTH_SCO 
3 STRATEGY_SONIFICATION RING 
NOTIFICATION 
ALARM 
ENFORCED_AUDIBLE 
2 STRATEGY_MEDIA SYSTEM 
TTS 
MUSIC 
1 STRATEGY_DTMF DTMF

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值