当前位置:   article > 正文

Android audio 输出设备选择过程分析(上)_安卓开发添加扬声器设备

安卓开发添加扬声器设备

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

第一步:获取output

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

  1. status = AudioSystem::getOutputForAttr(attr, &output,
  2.                                           mSessionId, &streamType, mClientUid,
  3.                                           &config,
  4.                                           mFlags, &mRoutedDeviceId, &mPortId);

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

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

AudioPolicyManager::getOutputForAttr:

  1. //准备设置好attributes
  2. ...
  3. //根据attributes选中Strategy
  4. routing_strategy strategy = (routing_strategy) getStrategyForAttr(&attributes);
  5. ...
  6. //根据Strategy选中device
  7. audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/);
  8. ...
  9. //根据选定的device获取Output
  10. *output = getOutputForDevice(device, session, *stream,
  11.                                 config->sample_rate,
  12.                             config->format,
  13.                             config->channel_mask,
  14.                                 flags,
  15.                             &config->offload_info);

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

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

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

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

  1. //代码节选自Engine::getDeviceForStrategyInt
  2. case STRATEGY_MEDIA: {
  3.        uint32_t device2 = AUDIO_DEVICE_NONE;
  4.       ...
  5.          //device2在前面没有被选中,而且没有设置这个setForceUse(setBluetoothA2dpOn(false)的时 候,会设置
  6.           //AudioSystem.FOR_MEDIA,AudioSystem.FORCE_NO_BT_A2DP标记)
  7.        if ((device2 == AUDIO_DEVICE_NONE) &&
  8.               (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] != AUDIO_POLICY_FORCE_NO_BT_A2DP) &&
  9.               (outputs.getA2dpOutput() != 0)) {
  10.          //第一个优先项出现了.如果此时a2dp可用,直接到下面我用****标记的特殊情况
  11.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP;
  12.            if (device2 == AUDIO_DEVICE_NONE) {
  13.                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES;
  14.           }
  15.            if (device2 == AUDIO_DEVICE_NONE) {
  16.                device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER;
  17.           }
  18.       }
  19. //这次轮到了AudioSystem.FOR_MEDIA,AudioSystem.FORCE_SPEAKER这种情况,speaker胜出
  20.        if ((device2 == AUDIO_DEVICE_NONE) &&
  21.           (mForceUse[AUDIO_POLICY_FORCE_FOR_MEDIA] == AUDIO_POLICY_FORCE_SPEAKER)) {
  22.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
  23.       }  
  24. //接下来就是依据优先级去选择设备了.规则就是
  25. //选中一个就结束,直接去和特殊设备做共存
  26.        if (device2 == AUDIO_DEVICE_NONE) {
  27.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADPHONE;
  28.       }
  29.        if (device2 == AUDIO_DEVICE_NONE) {
  30.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
  31.       }
  32.        if (device2 == AUDIO_DEVICE_NONE) {
  33.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
  34.       }
  35.        if (device2 == AUDIO_DEVICE_NONE) {
  36.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
  37.       }
  38.        if (device2 == AUDIO_DEVICE_NONE) {
  39.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_LINE;
  40.       }
  41.        if (device2 == AUDIO_DEVICE_NONE) {
  42.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_WIRED_HEADSET;
  43.       }
  44.        if (device2 == AUDIO_DEVICE_NONE) {
  45.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_HEADSET;
  46.       }
  47.        if (device2 == AUDIO_DEVICE_NONE) {
  48.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_ACCESSORY;
  49.       }
  50.        if (device2 == AUDIO_DEVICE_NONE) {
  51.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_USB_DEVICE;
  52.       }
  53.        if (device2 == AUDIO_DEVICE_NONE) {
  54.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET;
  55.       }
  56.        if ((device2 == AUDIO_DEVICE_NONE) && (strategy != STRATEGY_SONIFICATION)) {
  57.            // no sonification on aux digital (e.g. HDMI)
  58.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_DIGITAL;
  59.       }
  60.        if ((device2 == AUDIO_DEVICE_NONE) &&
  61.               (mForceUse[AUDIO_POLICY_FORCE_FOR_DOCK] == AUDIO_POLICY_FORCE_ANALOG_DOCK)) {
  62.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET;
  63.       }
  64.        if (device2 == AUDIO_DEVICE_NONE) {
  65.            device2 = availableOutputDevicesType & AUDIO_DEVICE_OUT_SPEAKER;
  66.       }
  67.  ***********************************************************************************
  68. //特殊情况
  69.        int device3 = AUDIO_DEVICE_NONE;
  70.        if (strategy == STRATEGY_MEDIA) {
  71.          //如果arc,spdif,aux_line可用,赋值给device3
  72.            // ARC, SPDIF and AUX_LINE can co-exist with others.
  73.            device3 = availableOutputDevicesType & AUDIO_DEVICE_OUT_HDMI_ARC;
  74.            device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_SPDIF);
  75.            device3 |= (availableOutputDevicesType & AUDIO_DEVICE_OUT_AUX_LINE);
  76.       }
  77. //device2和arc,spdif,aux_line做一个共存
  78.        device2 |= device3;
  79.        // 一般情况下,在这之前device还是AUDIO_DEVICE_NONE
  80.        device |= device2;
  81.        // If hdmi system audio mode is on, remove speaker out of output list.
  82.        if ((strategy == STRATEGY_MEDIA) &&
  83.           (mForceUse[AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO] ==
  84.                AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED)) {
  85.            device &= ~AUDIO_DEVICE_OUT_SPEAKER;
  86.       }
  87.       } break;

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

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

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

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

AudioPolicyManager::getOutputForDevice

  1. //处理入参flags
  2. if ((flags & AUDIO_OUTPUT_FLAG_XXX) != 0) {
  3. flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_XXX);
  4. }
  5. //咱一般不是AUDIO_OUTPUT_FLAG_DIRECT,当然是
  6. goto non_direct_output;
  7. ...
  8. //播放音乐什么之类的,mediaplayer已经做完decodec.这里一般都是pcm
  9.    if (audio_is_linear_pcm(format)) {
  10.        //根据指定的stream类型获取匹配的output.实际的路由改变需要等到startOutput被调用的时候
  11.     //注意这个函数是getOutputsForDevice,要获取的是一些output,而我们当前讨论的函数是获取一个output.这些outputs从mOutputs中来.那么mOutputs来自哪里?
  12.        SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
  13.        // 从匹配到的outputs(请注意,是复数)中选出一个output
  14.        output =
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小桥流水78/article/detail/988404?site
推荐阅读
相关标签
  

闽ICP备14008679号