android audio 總結

android 上層應用 控制audio 設備方法總結 

1 AudioManager.setAudioStreamType(AudioManager.STREAM_ALARM)

2 AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForMedia);

3 AudioManager.setSpeakPhoneOn(true);

方法3 最終還是通過 方法2 來 設置

4 AudioManager.setMode()--AudioSystem.setMode---AudioPolicyManger.setphoneState(). 來影響參數 mPhoneState來影響設備的選擇。

android 選擇用那些設備來進行播放的呢 

首先根據 上層傳來的 stream 來 區分 它 屬於哪個 音頻策略 

詳見:

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::ALARM:
        return STRATEGY_SONIFICATION;
    case AudioSystem::NOTIFICATION:
        return STRATEGY_SONIFICATION_RESPECTFUL;
    case AudioSystem::DTMF:
        return STRATEGY_DTMF;
    default:
        ALOGE("unknown stream type");
    case AudioSystem::SYSTEM:
        // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs
        // while key clicks are played produces a poor result
    case AudioSystem::TTS:
    case AudioSystem::MUSIC:
        return STRATEGY_MEDIA;
    case AudioSystem::ENFORCED_AUDIBLE:
        return STRATEGY_ENFORCED_AUDIBLE;
    }
}


然後根據不同的音頻策略 篩選出相應的設備 這其中也用到了 傳進來的  setForceUse裏面的 參數 

具體篩選規則:見 代碼 

audio_devices_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy,
                                                             bool fromCache)
{
    uint32_t device = AUDIO_DEVICE_NONE;


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


    switch (strategy) {


    case STRATEGY_SONIFICATION_RESPECTFUL:
        if (isInCall()) {
            device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
        } else if (isStreamActiveRemotely(AudioSystem::MUSIC,
                SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
            // while media is playing on a remote device, use the the sonification behavior.
            // Note that we test this usecase before testing if media is playing because
            //   the isStreamActive() method only informs about the activity of a stream, not
            //   if it's for local playback. Note also that we use the same delay between both tests
            device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
        } else if (isStreamActive(AudioSystem::MUSIC, SONIFICATION_RESPECTFUL_AFTER_MUSIC_DELAY)) {
            // while media is playing (or has recently played), use the same device
            device = getDeviceForStrategy(STRATEGY_MEDIA, false /*fromCache*/);
        } else {
            // when media is not playing anymore, fall back on the sonification behavior
            device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
        }


        break;


    case STRATEGY_DTMF:
        if (!isInCall()) {
        } else {
            // when media is not playing anymore, fall back on the sonification behavior
            device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/);
        }


        break;


至於我們平時的一些音頻切換異常 ,往往是由於 這些參數的變化導致的 。

比如 fm和鬧鈴切換的時候 ,就容易導致 fm切回來的時候耳機用的是 speaker的 音量 或fm切回來後壓根就沒聲,找不到可用設備

這都可以重新設下 AudioSystem.setForceUse 才能恢復正常,找個時間,好好跟一下具體哪裏出的問題。,不能老是這樣放過了。




APM::AudioPolicyManager: StartOutputSamplerate +output = 4 +stream = 0 session = 16 +samplerate=44100 mPrimaryOutput= 2
APM::AudioPolicyManager: getNewOutputDevice() selected device 1
APM::AudioPolicyManager: setOutputDevice() prevDevice 0x0001

而刷新狀態包括可用設備,forceuser設備等,都是有上層的 audioservice.java來控制的。所以 接下來 就要看下 這個 代碼了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章