reference: [RK3399][Android7.1]修改系统配置同时输出Speaker和USB音频
Android Audio代码分析 - Audio Strategy
一.Android5.1 音频切换
frameworksavservicesaudiopolicyAudioPolicyManager.cpp
1.1.策略对应的 stream type
AudioPolicyManager::routing_strategy AudioPolicyManager::getStrategy( audio_stream_type_t stream) { ALOG_ASSERT(stream != AUDIO_STREAM_PATCH,"getStrategy() called for AUDIO_STREAM_PATCH"); // stream to strategy mapping switch (stream) { case AUDIO_STREAM_VOICE_CALL:// 电话来了 case AUDIO_STREAM_BLUETOOTH_SCO:// 蓝牙耳机接通了 return STRATEGY_PHONE; case AUDIO_STREAM_RING:// 铃声响了 case AUDIO_STREAM_ALARM:// 警告,电池没电时的警告了 return STRATEGY_SONIFICATION; case AUDIO_STREAM_NOTIFICATION:?// 通知,例如界面中最上面一栏中有消息了 return STRATEGY_SONIFICATION_RESPECTFUL; case AUDIO_STREAM_DTMF: return STRATEGY_DTMF; default: ALOGE("unknown stream type %d", stream); case AUDIO_STREAM_SYSTEM: // NOTE: SYSTEM stream uses MEDIA strategy because muting music and switching outputs // while key clicks are played produces a poor result case AUDIO_STREAM_MUSIC: return STRATEGY_MEDIA; case AUDIO_STREAM_ENFORCED_AUDIBLE: return STRATEGY_ENFORCED_AUDIBLE; case AUDIO_STREAM_TTS: return STRATEGY_TRANSMITTED_THROUGH_SPEAKER; case AUDIO_STREAM_ACCESSIBILITY: return STRATEGY_ACCESSIBILITY; case AUDIO_STREAM_REROUTING: return STRATEGY_REROUTING; } }
1.2.其中添加的判断语句意思为:判断声音是否通话 . isCall 直接返回 SPEAKER和USB_DEVICE
audio_devices_t AudioPolicyManager::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]; } audio_devices_t availableOutputDeviceTypes = mAvailableOutputDevices.types(); switch (strategy) { case STRATEGY_TRANSMITTED_THROUGH_SPEAKER: device = availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER; if (!device) { ALOGE("getDeviceForStrategy() no device found for " "STRATEGY_TRANSMITTED_THROUGH_SPEAKER"); } break; case STRATEGY_SONIFICATION_RESPECTFUL: if (isInCall()) { device = getDeviceForStrategy(STRATEGY_SONIFICATION, false /*fromCache*/); } else if (isStreamActiveRemotely(AUDIO_STREAM_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*/); //user "safe" speaker if available instead of normal speaker to avoid triggering //other acoustic safety mechanisms for notification if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) device = AUDIO_DEVICE_OUT_SPEAKER_SAFE; } else if (isStreamActive(AUDIO_STREAM_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*/); //user "safe" speaker if available instead of normal speaker to avoid triggering //other acoustic safety mechanisms for notification if (device == AUDIO_DEVICE_OUT_SPEAKER && (availableOutputDeviceTypes & AUDIO_DEVICE_OUT_SPEAKER_SAFE)) device = AUDIO_DEVICE_OUT_SPEAKER_SAFE; } break; ………………………………………… default: ALOGW("getDeviceForStrategy() unknown strategy: %d", strategy); break; } ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device); + if(isInCall()){ + ALOGD("Gatsby getDeviceForStrategy() strategy "); + return AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_USB_DEVICE; + } return device; }
二.Android 7.1 音频策略
2.1.media.audio.device_policy media.audio.device_policy 默认音频
audio_devices_t Engine::getDeviceForStrategyInt(routing_strategy strategy, DeviceVector availableOutputDevices, DeviceVector availableInputDevices, const SwAudioOutputCollection &outputs) const { uint32_t device = AUDIO_DEVICE_NONE; uint32_t availableOutputDevicesType = availableOutputDevices.types(); switch (strategy) { …………………………………… char value[PROPERTY_VALUE_MAX]; property_get("media.audio.device_policy", value, ""); if (value[0]) { uint32_t new_device = AUDIO_DEVICE_NONE; if (strstr(value, "hdmi")) { ALOGD("set audio policy to hdmi, availableOutputDevicesType : 0x%x", availableOutputDevicesType); if (availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI) { ALOGD("set audio policy to hdmi succeed"); new_device |= AUDIO_DEVICE_OUT_HDMI; } } if (strstr(value, "speaker")) { ALOGD("set audio policy to speaker, availableOutputDevicesType : 0x%x", availableOutputDevicesType); if (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER) { ALOGD("set audio policy to speaker succeed"); new_device |= AUDIO_DEVICE_OUT_SPEAKER; } } if (strstr(value, "usb")) { ALOGD("set audio policy to usb, availableOutputDevicesType : 0x%x", availableOutputDevicesType); if (availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE) { ALOGD("set audio policy to usb succeed"); new_device |= AUDIO_DEVICE_OUT_USB_DEVICE; } } if (strstr(value, "bluetooth")) { ALOGD("set audio policy to bluetooth, availableOutputDevicesType : 0x%x", availableOutputDevicesType); if (availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP) new_device |= AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; else if (availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) new_device |= AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; else if (availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER) new_device |= AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; } if (new_device != AUDIO_DEVICE_NONE) { device = new_device; } } ALOGVV("getDeviceForStrategy() strategy %d, device %x", strategy, device); return device; }