在看示例代码 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 中是否使用了指定的 strategyuint32_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 对应的所有 streamvoid 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 scalingstatic const float dBPerStep = 0.5f;// shouldn't need to touch thesestatic 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


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

更多相关文章

  1. C语言函数的递归(上)
  2. Android(安卓)OpenGL ES 分析与实践
  3. Android(安卓)4.0 Service Framework
  4. 在 Android(安卓)上使用协程(二):Getting started
  5. android HAL知识
  6. Android(安卓)的Bitmap的修改方法
  7. Android使用ViewFlipper做页面切换,与手势滑动切换的使用
  8. Android(安卓)用 libusb 操作 USB 设备,无须 root
  9. Android中的自绘View的那些事儿(四)之 ComposeShader组合渲染器的

随机推荐

  1. 用鸿蒙开发AI应用(五)HDF 驱动补光灯
  2. 一文详解 Linux系统常用监控工具
  3. 数据库中间件 MyCAT源码分析:【单库单表】
  4. linux系统中重启网卡后网络不通(NetworkMa
  5. 分布式事务 TCC-Transaction 源码分析 —
  6. Redis 哈希结构内存模型剖析
  7. FAlinux01-1基础
  8. 注册中心 Eureka 源码解析 —— Eureka-C
  9. 分布式消息队列 RocketMQ源码解析:事务消
  10. 数据库中间件 MyCAT 源码分析 —— 【单