Android Audio代码分析 - Audio Strategy

本文深入探讨了Android Audio的各种策略,特别是在Audio Policy Manager中的实现方式。内容包括不同策略如STRATEGY_PHONE、STRATEGY_SONIFICATION、STRATEGY_MEDIA和STRATEGY_DTMF与对应stream type的关联,以及如何根据状态调整音量,以实现特定的声音优先级效果。
摘要由CSDN通过智能技术生成
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);
            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;
}
复制代码
复制代码
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);
}
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);

}
// 主要的处理是从这儿开始的 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);
复制代码

需要知道每种策略分别是用来做什么的。
所以首先要知道策略对应的 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;
    }
}
复制代码
复制代码
    // 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);
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]);
}
复制代码
复制代码

    setOutputDevice(output, getNewDevice(output));


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 。
//
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值