Android系统分析之Audio音频流, 音频策略, 输出设备之间的关系

mac2022-06-30  17

音频流, 音频策略, 输出设备之间的关系

只针对 AudioManager.STREAM_VOICE_CALL 音频流类型进行分析

涉及到的类:

hardware/libhardware_legacy/audio/AudioPolicyManagerBase.cpp frameworks/base/media/java/android/media/AudioManager.java frameworks/base/media/java/android/media/AudioService.java frameworks/base/media/java/android/media/AudioSystem.java

涉及到的方法及执行顺序:

AudioPolicyManagerBase.getStrategy(AudioSystem::stream_type stream); AudioPolicyManagerBase.getDeviceForStrategy(routing_strategy strategy, bool fromCache);

一. 通过音频流的类型获取对应的音频策略

AudioPolicyManagerBase.cpp: 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; ... } }

二. 通过音频策略获取到对应的输出设备

AudioPolicyManagerBase.cpp: audio_devices_t AudioPolicyManagerBase::getDeviceForStrategy(routing_strategy strategy, bool fromCache) { uint32_t device = AUDIO_DEVICE_NONE; ... // 省略 switch (strategy) { ... // 省略 case STRATEGY_PHONE: // 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) { device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT; if (device) break; } device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_SCO; if (device) break; // if SCO device is requested but no SCO device is available, fall back to default case // FALL THROUGH default: // FORCE_NONE 没有设置通讯过程中, 强制使用某种输出设备 // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to A2DP if (mHasA2dp && !isInCall() && (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) && (getA2dpOutput() != 0) && !mA2dpSuspended) { device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES; if (device) break; } device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADPHONE; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_WIRED_HEADSET; if (device) break; if (mPhoneState != AudioSystem::MODE_IN_CALL) { device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; if (device) break; } // 没有设置通讯过程中, 音频的输出设备, 则默认使用听筒作为输出设备 device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_EARPIECE; if (device) break; device = mDefaultOutputDevice; if (device == AUDIO_DEVICE_NONE) { ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE"); } break; case AudioSystem::FORCE_SPEAKER: // 强制使用扬声器, 作为输出设备 // when not in a phone call, phone strategy should route STREAM_VOICE_CALL to // A2DP speaker when forcing to speaker output if (mHasA2dp && !isInCall() && (mForceUse[AudioSystem::FOR_MEDIA] != AudioSystem::FORCE_NO_BT_A2DP) && (getA2dpOutput() != 0) && !mA2dpSuspended) { device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER; if (device) break; } if (mPhoneState != AudioSystem::MODE_IN_CALL) { device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_ACCESSORY; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_USB_DEVICE; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_AUX_DIGITAL; if (device) break; device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET; if (device) break; } device = mAvailableOutputDevices & AUDIO_DEVICE_OUT_SPEAKER; if (device) break; device = mDefaultOutputDevice; if (device == AUDIO_DEVICE_NONE) { ALOGE("getDeviceForStrategy() no device found for STRATEGY_PHONE, FORCE_SPEAKER"); } break; } break; // 关于上面default位置的问题, 如果每个case选择(包括default)最终都有break语句, 则default的位置不影响执行顺序 // 当每个case选择(包括default)不一定有break语句时, 如果输入不满足其他选择, 最终执行default. 程序会从default处从上向下执行, 直到遇到break语句停止 // 此处的default位置并不影响执行顺序 ... // 省略 } return device; }

三. 音频流, 音频策略, 输出设备之间的关系

音频的流类型决定音频的策略, 音频的策略决定输出设备. 但是最终的输出设备的确定, 受强制设置输出设备影响.

四. 分析AudioManager.setSpeakerphoneOn(boolean on)方法, 查看强制设置对音频输出设备选择的影响

涉及到的类及方法:

1. AudioManager.setSpeakerphoneOn(boolean on); 2. AudioService.setSpeakerphoneOn(boolean on); 3. AudioService.AudioHandler.setForceUse(int usage, int config); 4. AudioSystem.setForceUse(int usage, int config); 5. AudioPolicyManagerBase.setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config); 4.1. AudioManager.java: public void setSpeakerphoneOn(boolean on){ IAudioService service = getService(); service.setSpeakerphoneOn(on); } 4.2. AudioService.java: public void setSpeakerphoneOn(boolean on){ if (on) { if (mForcedUseForComm == AudioSystem.FORCE_BT_SCO) { sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_RECORD, AudioSystem.FORCE_NONE, null, 0); } mForcedUseForComm = AudioSystem.FORCE_SPEAKER; } else if (mForcedUseForComm == AudioSystem.FORCE_SPEAKER){ mForcedUseForComm = AudioSystem.FORCE_NONE; } // 从此处可以看到 setSpeakerphoneOn(boolean on) 只针对 AudioSystem.FOR_COMMUNICATION 有效 // 而 AudioSystem.FOR_COMMUNICATION 最终影响到的是输出设备的选择 sendMsg(mAudioHandler, MSG_SET_FORCE_USE, SENDMSG_QUEUE, AudioSystem.FOR_COMMUNICATION, mForcedUseForComm, null, 0); } private class AudioHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_SET_FORCE_USE: case MSG_SET_FORCE_BT_A2DP_USE: setForceUse(msg.arg1, msg.arg2); break; } } private void setForceUse(int usage, int config) { AudioSystem.setForceUse(usage, config); } } 4.3. AudioSystem.java: public static native int setForceUse(int usage, int config); 4.4. AudioPolicyManagerBase.cpp: void AudioPolicyManagerBase::setForceUse(AudioSystem::force_use usage, AudioSystem::forced_config config) { bool forceVolumeReeval = false; switch(usage) { case AudioSystem::FOR_COMMUNICATION: if (config != AudioSystem::FORCE_SPEAKER && config != AudioSystem::FORCE_BT_SCO && config != AudioSystem::FORCE_NONE) { ALOGW("setForceUse() invalid config %d for FOR_COMMUNICATION", config); return; } forceVolumeReeval = true; // 保存设置到数组中, 最终在 getDeviceForStrategy(routing_strategy strategy, bool fromCache) 中被调用 mForceUse[usage] = config; break; ... // 省略 } ... // 省略 }

转载于:https://www.cnblogs.com/firmly-believe/p/10991077.html

最新回复(0)