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來控制的。所以 接下來 就要看下 這個 代碼了。