Android audio 输出设备选择过程分析(上)

本文分析了Android系统在Android 5.0上选择音频输出设备的过程,从AudioPolicyManager的getOutputForAttr开始,探讨了如何根据策略、设备选择合适的输出,并涉及AudioFlinger的Track创建和设备应用。重点讲解了AudioPolicyManager的getOutputForDevice、startOutput以及设备变更的判断逻辑,同时提及AudioPatch在设备选择中的作用。
摘要由CSDN通过智能技术生成

        众(搞音频的(此处应该有个笑哭的表情)所周知的,要播放一个声音,创建AudioTrack之后,set函数设置参数的时候,会调用createTrack_l函数。

第一步:获取output

createTrack_l用binder去调用AudioFlinger的createTrack创建AudioFlinger::Track之前,首先会去调用getOutputForAttr:

status = AudioSystem::getOutputForAttr(attr, &output,
                                           mSessionId, &streamType, mClientUid,
                                           &config,
                                           mFlags, &mRoutedDeviceId, &mPortId);

根据传入的audio_attributes_t等参数,带回output(这是个出参)!

这一调用,在AudioPolicyManager中得到落实。

AudioPolicyManager::getOutputForAttr:


//准备设置好attributes
...
//根据attributes选中Strategy
routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);
...
//根据Strategy选中device
audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
...
//根据选定的device获取Output
*output = getOutputForDevice(device, session, *stream,
                                    config->sample_rate, 
                                    config->format,
                                    config->channel_mask,
                                    flags,
                                    &config->offload_info);

这个名字取得很有意思哈,一步步往下推进的感觉。

getOutputForAttr: attr>>strategy>>device>>output

其中,getDeviceForStrategy这一步真正决定了使用什么设备.

比如说,下面的例子是播放音乐(AUDIO_STREAM_MUSIC)的时候选中的Strategy:

//代码节选自Engine::getDeviceForStrategyInt
case STRATEGY_MEDIA: {
        uint32_t device2 = AUDIO_DEVICE_NONE;
        ...
          //device2在前面没有被选中,而且没有设置这个setForceUse(setBluetoothA2dpOn(false)的时                 候,会设置
           //AudioSystem.FOR_MEDIA,AudioSystem.FORCE_NO_BT_A2DP标记)
        if ((device2 == AUDIO_DEVICE_NONE) &&
                (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
                (outputs.getA2dpOutput() != 0)) {
          //第一个优先项出现了.如果此时a2dp可用,直接到下面我用****标记的特殊情况
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
            if (device2 == AUDIO_DEVICE_NONE) {
                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
            }
            if (device2 == AUDIO_DEVICE_NONE) {
                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
            }
        }
        //这次轮到了AudioSystem.FOR_MEDIA,AudioSystem.FORCE_SPEAKER这种情况,speaker胜出
        if ((device2 == AUDIO_DEVICE_NONE) &&
            (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
        }  
        //接下来就是依据优先级去选择设备了.规则就是
        //选中一个就结束,直接去和特殊设备做共存
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
        }
        if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
            // no sonification on aux digital (e.g. HDMI)
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
        }
        if ((device2 == AUDIO_DEVICE_NONE) &&
                (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
        }
        if (device2 == AUDIO_DEVICE_NONE) {
            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
        }
  ***********************************************************************************
        //特殊情况
        int device3 = AUDIO_DEVICE_NONE;
        if (strategy == STRATEGY_MEDIA) {
          //如果arc,spdif,aux_line可用,赋值给device3
            // ARC, SPDIF and AUX_LINE can co-exist with others.
            device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC;
            device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF);
            device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE);
        }
        //device2和arc,spdif,aux_line做一个共存
        device2 |= device3;
        // 一般情况下,在这之前device还是AUDIO_DEVICE_NONE
        device |= device2;
        // If hdmi system audio mode is on, remove speaker out of output list.
        if ((strategy == STRATEGY_MEDIA) &&
            (mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] ==
                AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
            device &= ~AUDIO_DEVICE_OUT_SPEAKER;
        }
        } break;

根据上面的代码,简单做个总结吧:

播放音乐选设备优先级如下


AUDIO_DEVICE_OUT_BLUETOOTH_A2DP
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES(普通蓝牙耳机)
AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER(蓝牙小音箱)
//此处属于setForceUse的强制插队
(if FORCE_SPEAKER)AUDIO_DEVICE_OUT_SPEAKER(扬声器)
AUDIO_DEVICE_OUT_WIRED_HEADPHONE(普通耳机,只能听,不能操控播放)
AUDIO_DEVICE_OUT_LINE
AUDIO_DEVICE_OUT_WIRED_HEADSET(线控耳机)
AUDIO_DEVICE_OUT_USB_HEADSET(USB耳机)
...
AUDIO_DEVICE_OUT_SPEAKER(扬声器)

选好设备就返回device,然后getOutputForDevice

AudioPolicyManager::getOutputForDevice

//处理入参flags
if ((flags & AUDIO_OUTPUT_FLAG_XXX) != 0) {
    flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_XXX);
}
//咱一般不是AUDIO_OUTPUT_FLAG_DIRECT,当然是
goto non_direct_output;
...
//播放音乐什么之类的,mediaplayer已经做完decodec.这里一般都是pcm
    if (audio_is_linear_pcm(format)) {
        //根据指定的stream类型获取匹配的output.实际的路由改变需要等到startOutput被调用的时候
        //注意这个函数是getOutputsForDevice,要获取的是一些output,而我们当前讨论的函数是获取一个output.这些outputs从mOutputs中来.那么mOutputs来自哪里?
        SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
        // 从匹配到的outputs(请注意,是复数)中选出一个output
        output = 
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值