android_audio架构全分析,Android Audio代码分析=Audio Strategy

从 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 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 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& 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 )

{

// 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& 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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值