4. AAOS音频策略配置文件:audio_policy_configuration.xml结构解析

在AAOS(Android Automotive OS)系统中,音频路由的核心控制逻辑由音频策略配置文件(audio_policy_configuration.xml)定义。该文件是系统音频框架的“交通指挥图”,它描述了所有音频设备、输入输出端口以及音频流如何在设备之间进行路由。本章将深入解析该文件的结构、设备映射(DeviceMap)以及路由规则(Route)的定义方式。

核心概念:音频策略配置文件是AAOS音频路由的静态蓝图,系统启动时由AudioPolicyManager加载并解析,用于决定音频流(如媒体、导航、电话)的最终输出设备。

4.1 文件顶层结构

audio_policy_configuration.xml 的根元素为 <audioPolicyConfiguration>,其内部包含以下几个核心子模块:

模块名称 XML 标签 功能描述
全局配置 <globalConfiguration> 定义扬声器、耳机等设备是否开启、音量曲线等全局参数
模块集合 <modules> 包含一个或多个 <module>,每个模块对应一个音频HAL(硬件抽象层)实例
设备映射 <deviceMap> 将音频端口(Port)与物理设备类型(DeviceType)进行关联
路由规则 <routes> 定义音频源(Source)到音频接收器(Sink)的路径规则
音量曲线 <volumeCurves> 定义不同音频流类型的音量衰减曲线

以下是一个典型的顶层结构示例:

<audioPolicyConfiguration version="1.0">
    <globalConfiguration speaker_drc_enabled="false"/>
    <modules>
        <!-- 主音频模块定义 -->
        <module name="primary" halVersion="3.0">
            ...
        </module>
        <!-- 蓝牙电话专用模块 -->
        <module name="bluetooth" halVersion="2.0">
            ...
        </module>
    </modules>
    <deviceMap>
        ...
    </deviceMap>
    <routes>
        ...
    </routes>
</audioPolicyConfiguration>

4.2 模块(Module)与端口(Port)定义

每个 <module> 代表一个独立的音频HAL实例。在车载系统中,通常至少包含一个 primary 模块(负责扬声器、AUX等)和一个 bluetooth 模块(负责蓝牙电话与媒体)。模块内部通过 <attachedDevices>、<devicePorts> 和 <mixPorts> 定义物理与逻辑端口。

  • DevicePort(设备端口):代表物理音频设备,如内置扬声器、蓝牙耳机、AUX IN等。
  • MixPort(混音端口):代表音频策略引擎内部的逻辑混音点,用于连接上层音频流。
<module name="primary" halVersion="3.0">
    <attachedDevices>
        <item>Speaker</item>
        <item>BuiltInMic</item>
    </attachedDevices>
    <devicePorts>
        <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                     samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
        </devicePort>
        <devicePort tagName="BuiltInMic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                     samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
        </devicePort>
    </devicePorts>
    <mixPorts>
        <mixPort name="primary output" role="source">
            <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                     samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
        </mixPort>
    </mixPorts>
</module>
实践要点:在车载系统中,tagName 属性通常与硬件设备树(DeviceTree)中的节点名称保持一致,便于驱动层与策略层对齐。

4.3 设备映射(DeviceMap)解析

设备映射是连接 逻辑设备类型 与 物理端口标签 的桥梁。在AAOS中,<deviceMap> 使用 <device> 条目将Android定义的音频设备类型(如 AUDIO_DEVICE_OUT_BLUETOOTH_SCO)映射到模块中定义的 tagName。

以下是一个包含蓝牙SCO(同步面向连接)映射的示例:

<deviceMap>
    <device type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" tagName="BT SCO Headset"/>
    <device type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" tagName="BT SCO Headset"/>
    <device type="AUDIO_DEVICE_OUT_SPEAKER" tagName="Speaker"/>
    <device type="AUDIO_DEVICE_IN_BUILTIN_MIC" tagName="BuiltInMic"/>
</deviceMap>
Android 设备类型 映射 tagName 说明
AUDIO_DEVICE_OUT_BLUETOOTH_SCO BT SCO Headset 蓝牙电话音频输出(窄带/宽带)
AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET BT SCO Headset 蓝牙电话音频输入(麦克风)
AUDIO_DEVICE_OUT_SPEAKER Speaker 车载扬声器
AUDIO_DEVICE_IN_BUILTIN_MIC BuiltInMic 车载内置麦克风
常见错误:如果 deviceMap 中缺少蓝牙SCO设备的映射,系统将无法将电话音频路由到蓝牙耳机,导致通话无声。

4.4 路由规则(Route)定义

路由规则决定了音频数据从 混音端口(MixPort) 流向 设备端口(DevicePort) 的路径。每个 <route> 包含 type、sources 和 sinks 属性。

  • type:路由类型,通常为 mix(混音路由)或 mux(多路复用路由)。
  • sources:音频源,可以是 mixPort 的 name 或 devicePort 的 tagName。
  • sinks:音频接收器,定义数据最终流向的设备。
<routes>
    <route type="mix">
        <source name="primary output"/>
        <sink name="Speaker"/>
    </route>
    <route type="mix">
        <source name="primary output"/>
        <sink name="BT SCO Headset"/>
    </route>
    <route type="mux">
        <source name="BuiltInMic"/>
        <sink name="primary input"/>
    </route>
</routes>

上述规则的含义:

  1. 主混音输出(primary output)可以同时路由到扬声器和蓝牙SCO耳机(混音模式)。
  2. 内置麦克风(BuiltInMic)通过多路复用路由到主输入(primary input),用于语音识别或免提通话。

4.5 蓝牙电话路由的SVG架构图

下图展示了蓝牙电话场景下,音频流从应用层到物理设备的完整路由路径,重点体现 deviceMap 与 routes 的协作关系:

蓝牙电话音频路由架构(基于AAOS策略配置) 电话应用(Dialer) AudioStreamType: VOICE_CALL AudioFlinger 混音线程 AudioPolicyManager audio_policy_config.xml (deviceMap + routes) 路由决策结果 (输出设备: BT SCO) 蓝牙HAL模块 (bluetooth) 蓝牙SCO耳机(物理设备) 说明:deviceMap 将 AUDIO_DEVICE_OUT_BLUETOOTH_SCO 映射到 "BT SCO Headset";routes 定义 primary output → BT SCO Headset 路径

4.6 路由规则与设备映射的协同工作

设备映射与路由规则并非独立存在,它们通过 tagName 形成强关联。当系统需要路由电话音频时,执行以下步骤:

  1. 策略查询:AudioPolicyManager 根据音频流类型(如 VOICE_CALL)查找可用设备。
  2. 设备映射解析:通过 deviceMap 将 Android 设备类型(如 AUDIO_DEVICE_OUT_BLUETOOTH_SCO)转换为模块内的 tagName(如 BT SCO Headset)。
  3. 路由匹配:在 routes 中查找包含该 tagName 作为 sink 的条目,确认混音端口到设备端口的路径是否合法。
  4. 设备激活:如果路由有效,AudioFlinger 将音频数据发送到对应模块的 HAL 接口,最终输出到物理设备。
关键设计原则:在车载系统中,建议将蓝牙电话的输入输出映射到同一个 tagName(如 BT SCO Headset),确保上下行路由对称,避免出现“只听到对方声音,对方听不到自己”的单向问题。

4.7 多模块路由的SVG架构图

在复杂的车载系统中,可能存在多个音频模块(如 primary 和 bluetooth)。下图展示了跨模块路由时,deviceMap 如何在不同模块间建立映射关系:

跨模块设备映射与路由协同 模块: primary (HAL 3.0) MixPort: primary output DevicePort: Speaker route: mix 模块: bluetooth (HAL 2.0) MixPort: bt_sco_output DevicePort: BT SCO route: mix deviceMap 全局映射 AUDIO_DEVICE_OUT_BLUETOOTH_SCO → tagName="BT SCO" (跨模块映射) 跨模块路由 跨模块路由时,deviceMap 必须确保不同模块中的 DevicePort tagName 不冲突 且 routes 中的 source/sink 引用正确的模块内端口名称

4.8 常见配置错误与排查

错误现象 可能原因 排查方法
蓝牙通话无声音 deviceMap 中缺少 AUDIO_DEVICE_OUT_BLUETOOTH_SCO 映射 检查 deviceMap 是否包含蓝牙SCO条目
通话声音从扬声器输出而非蓝牙耳机 routes 中未定义 primary output → BT SCO Headset 路径 确认 routes 中 sink 名称与 devicePort tagName 一致
蓝牙麦克风无法拾音 缺少输入方向的 route 定义(source 为 BT SCO mic) 添加 source="BT SCO Headset" sink="primary input" 的 route
多模块路由冲突 两个模块定义了相同 tagName 的 devicePort 确保每个模块的 tagName 唯一,或使用模块前缀区分
调试技巧:使用 adb shell dumpsys audio_policy 可以实时查看当前加载的设备映射和路由规则,验证配置是否生效。