4. AAOS音频策略配置文件:audio_policy_configuration.xml结构解析
在AAOS(Android Automotive OS)系统中,音频路由的核心控制逻辑由音频策略配置文件(audio_policy_configuration.xml)定义。该文件是系统音频框架的“交通指挥图”,它描述了所有音频设备、输入输出端口以及音频流如何在设备之间进行路由。本章将深入解析该文件的结构、设备映射(DeviceMap)以及路由规则(Route)的定义方式。
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>
上述规则的含义:
- 主混音输出(
primary output)可以同时路由到扬声器和蓝牙SCO耳机(混音模式)。 - 内置麦克风(
BuiltInMic)通过多路复用路由到主输入(primary input),用于语音识别或免提通话。
4.5 蓝牙电话路由的SVG架构图
下图展示了蓝牙电话场景下,音频流从应用层到物理设备的完整路由路径,重点体现 deviceMap 与 routes 的协作关系:
4.6 路由规则与设备映射的协同工作
设备映射与路由规则并非独立存在,它们通过 tagName 形成强关联。当系统需要路由电话音频时,执行以下步骤:
- 策略查询:AudioPolicyManager 根据音频流类型(如
VOICE_CALL)查找可用设备。 - 设备映射解析:通过
deviceMap将 Android 设备类型(如AUDIO_DEVICE_OUT_BLUETOOTH_SCO)转换为模块内的tagName(如BT SCO Headset)。 - 路由匹配:在
routes中查找包含该tagName作为sink的条目,确认混音端口到设备端口的路径是否合法。 - 设备激活:如果路由有效,AudioFlinger 将音频数据发送到对应模块的 HAL 接口,最终输出到物理设备。
tagName(如 BT SCO Headset),确保上下行路由对称,避免出现“只听到对方声音,对方听不到自己”的单向问题。
4.7 多模块路由的SVG架构图
在复杂的车载系统中,可能存在多个音频模块(如 primary 和 bluetooth)。下图展示了跨模块路由时,deviceMap 如何在不同模块间建立映射关系:
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 可以实时查看当前加载的设备映射和路由规则,验证配置是否生效。