1. 课程导入
车载音频不是“把手机音频搬到车上”这么简单。车内有多个音源(媒体、导航、电话、语音助手、倒车雷达、ADAS 提示音)、多个输出区(主驾、副驾、后排、头枕、外放)、多种总线(I2S、TDM、A2B、MOST、SPDIF)以及严格的实时性与安全要求。Android Audio HAL 正是连接 Android 音频框架与底层车载音频硬件的关键层:它把 AudioFlinger 的流、设备、音量、路由请求,翻译成具体 SoC/DSP/功放能执行的配置与数据通道。
一、学习目标:从“会用”到“能改、能调、能排障”
- 理解框架:掌握 Android Audio 架构中 App → AudioService → AudioFlinger → Audio HAL → Driver/DSP → Codec/Amp 的数据与控制路径。
- 掌握接口:熟悉 HIDL/AIDL 两种 HAL 形态,理解
IDevice、IStreamOut、IStreamIn等核心接口的职责边界。 - 能配路由:根据场景(媒体/导航/电话/语音)配置
audio_policy_configuration.xml、audio_policy_volumes.xml等策略文件。 - 能调参数:理解采样率、位深、通道数、period size、latency、增益、混音策略对音质与延迟的影响。
- 能排故障:从 logcat、dumpsys media.audio_flinger、tinyplay/tinycap、HAL 日志逐层定位“没声音、爆音、断续、路由错”。
二、核心概念:先建立一张“音频地图”
Android 音频系统可以按“控制面”和“数据面”两条线理解。控制面负责设备枚举、路由选择、音量映射、策略决策;数据面负责 PCM 采样数据的搬运与混音。Audio HAL 同时横跨两面:它既向上报告“我有哪些设备、支持哪些格式”,也向下执行“把这条流送到这个设备、用这个增益”。
| 概念 | 所在层 | 关键作用 | 车载关注点 |
|---|---|---|---|
| AudioTrack / AudioRecord | 应用层 | 播放/录制 PCM 流 | 多音源并发、焦点抢占 |
| AudioService / AudioPolicy | 框架层 | 策略、焦点、音量、路由决策 | 驾驶安全优先级、分区音量 |
| AudioFlinger | 框架层 | 混音、重采样、流管理 | 低延迟、多区混音 |
| Audio HAL | HAL 层 | 设备/流抽象,连接框架与驱动 | HIDL/AIDL、车规稳定性 |
| ALSA / DSP / Amp | 内核与硬件 | PCM 传输、DSP 处理、功放驱动 | I2S/TDM/A2B、上电时序 |
三、整体框架:一张图看清 Audio HAL 的位置
下面的 SVG 展示了从应用请求到扬声器输出的完整链路,以及 Audio HAL 在其中的“翻译官”角色。注意控制面与数据面是并行的:策略决定“走哪条路”,HAL 与驱动负责“把数据搬过去”。
四、方法流程:一次播放请求的完整旅程
以“导航播报同时播放音乐”为例,理解 Audio HAL 的工作流程:
- 导航 App 创建 AudioTrack,声明 usage=ASSISTANCE_NAVIGATION_GUIDANCE。
- AudioPolicy 根据策略决定导航流走“主驾扬声器”,音乐流走“全车扬声器”,并可能对音乐做闪避(duck)。
- AudioFlinger 为两条流分别建立输出线程,混音后写入对应的 HAL 输出流。
- Audio HAL 的
IStreamOut::write()接收 PCM 数据,按配置写入 ALSA 设备节点或 DSP 通道。 - DSP 执行 EQ、延时、分频,功放驱动扬声器发声。
- 若导航播报结束,AudioPolicy 恢复音乐音量,HAL 无需感知“闪避”本身,只执行音量/路由变更。
# 典型排查命令
adb shell dumpsys media.audio_flinger
adb shell dumpsys media.audio_policy
adb shell logcat -s AudioFlinger AudioPolicyManager AudioHal
adb shell tinyplay /data/test.wav -D 0 -d 0
adb shell tinycap /data/rec.wav -D 0 -d 0 -c 2 -r 48000
五、案例/场景:车载音频的典型挑战
假设车辆启动后,用户发现“导航有声音,但音乐没有”。按链路逐层排查:先确认 AudioPolicy 是否把媒体流路由到了正确设备;再检查 AudioFlinger 是否创建了对应输出流;然后看 HAL 是否收到 write 调用;最后用 tinyplay 直接测试 HAL 以下是否出声。若 tinyplay 正常而 App 无声,问题多在策略或焦点;若 tinyplay 也无声,问题在 HAL、驱动或硬件。
六、误区与复盘
- 误区一:把 HAL 当驱动。HAL 是抽象层,不直接操作寄存器;它通过 ALSA/DSP 接口与内核交互。
- 误区二:只关注数据面。大量“没声音”问题其实出在路由与音量策略,而非 PCM 搬运。
- 误区三:忽略车规时序。功放上电、I2S 时钟稳定、DSP 加载都需要时间,HAL 打开流时若未等待就绪,会出现爆音或静音。
- 复盘方法:每次排障后记录“现象 → 层级 → 证据 → 根因 → 修复”,形成自己的车载音频故障树。
七、学习路径建议
建议按“框架 → 接口 → 策略 → 调试 → 实战”五步推进:先建立整体链路认知,再深入 HIDL/AIDL 接口定义,接着掌握 audio_policy_configuration.xml 等策略配置,然后熟练使用 dumpsys、logcat、tinyplay 等工具,最后通过多音区、低延迟、语音交互等真实场景巩固。每学完一个模块,都回到本节的框架图,确认自己能在图上指出对应的位置与数据流向。