1. 课程导入
在 Android 系统中,音频是最贴近用户体验、又最容易在移植阶段暴露问题的子系统之一。应用层调用 AudioTrack 播放音乐、AudioRecord 采集语音,最终都要经过 AudioFlinger、Audio HAL,落到具体芯片平台的 DSP、Codec 与功放上。Audio HAL 正是 Android 音频框架与硬件驱动之间的“适配层”,它决定了同一套 Android 音频服务能否在不同 SoC、不同 Codec、不同外设方案上稳定工作。本课程围绕“如何把 Audio HAL 适配到目标硬件并调通”展开,本章先建立整体认知地图。
一、学习目标:从“能编译”到“能量测、能定位”
Audio HAL 适配不是单纯改配置,而是一项横跨框架、HAL、内核驱动与硬件调试的系统工程。完成本课程后,应达到以下目标:
- 理解 Android 音频从 App 到硬件的完整数据通路,明确 Audio HAL 在其中的位置与职责边界。
- 掌握 Audio HAL 的接口形态演进,能区分 HIDL、AIDL 与旧版 legacy HAL 的差异与迁移要点。
- 能独立完成
audio_policy_configuration.xml、audio_device.xml等核心配置的编写与校验。 - 掌握 PCM 通路、Mixer 控件、路由切换的调试方法,能借助
tinymix、tinyplay、dumpsys media.audio_flinger定位问题。 - 具备典型故障的排障能力:无声、杂音、断续、录音异常、路由错误、延迟偏大等。
二、核心概念:先厘清五个关键对象
在动手适配前,必须把几个高频概念区分清楚,否则很容易在“配置改了却没生效”的循环里打转。
| 概念 | 所在层级 | 核心作用 | 常见载体 |
|---|---|---|---|
| AudioFlinger | Native 框架层 | 混音、重采样、输出/输入流管理 | audioserver 进程 |
| Audio HAL | HAL 层 | 向框架暴露设备与流接口,转发到驱动 | audio.primary.*.so |
| Audio Policy | 策略层 | 决定“什么声音走什么设备” | audio_policy_configuration.xml |
| ALSA / TinyALSA | 内核与用户态接口 | PCM、Mixer、Control 的实际操作 | /dev/snd/* |
| Codec / DSP | 硬件层 | 数模转换、功放、降噪、回声消除 | 芯片寄存器与固件 |
其中最容易混淆的是 Audio HAL 与 Audio Policy:HAL 负责“怎么把数据送出去”,Policy 负责“该不该送到这个设备”。很多“插耳机没声音”的问题,根因其实在 Policy 的路由规则,而不是 HAL 的 PCM 通路。
三、整体框架:一条数据通路的全貌
下图给出 Android 音频从应用到底层硬件的分层结构与数据流向,同时标出适配工作的主要切入点。理解这张图,后续每一章的调试都能快速定位到对应层级。
四、方法流程:Audio HAL 适配的标准动作
面对一块新板子,适配工作通常按“先通后优”的顺序推进,避免一开始就陷入细节。
- 确认硬件拓扑:梳理 Codec 型号、I2S/TDM 接口、功放使能脚、麦克风偏置、耳机检测方式。
- 打通内核通路:确认 DTS 中 dai-link、codec、machine driver 配置正确,
/proc/asound/cards能看到声卡。 - 验证裸 PCM:用
tinyplay直接播放,绕过 Android 框架,先证明底层能出声。 - 配置 HAL 与 Policy:编写
audio_policy_configuration.xml,声明设备、流、路由与增益。 - 框架联调:通过
dumpsys与 logcat 检查流是否创建、路由是否命中、参数是否匹配。 - 场景回归:覆盖播放、录音、通话、耳机插拔、蓝牙切换、低延迟等典型场景。
五、典型场景与误区复盘
以一个常见案例说明:某项目插入耳机后扬声器仍在响,耳机无声。排查发现 audio_policy_configuration.xml 中耳机设备未加入 attachedDevices,且路由规则缺少 WIRED_HEADSET 到 media 的映射。修正配置后,框架在检测到耳机插入时会自动切换路由。这个案例说明:路由问题优先查 Policy,通路问题优先查 HAL 与驱动。
初学者常见误区包括:
- 把 HAL 当成“驱动”,忽略 Policy 对设备选择的主导作用。
- 只改 XML 不重启
audioserver,导致配置未重新加载。 - 采样率、位宽、通道数与硬件能力不匹配,出现变速、杂音或无声。
- 忽略增益与 Mixer 控件,通路已通但音量极小或静音。
- 不做裸 PCM 验证,问题定位在框架与硬件之间反复摇摆。
六、学习路径:本课程的知识推进
后续内容将沿着“框架认知 → HAL 接口 → 配置与路由 → 通路调试 → 场景与排障”的主线展开。建议学习时同步准备一台可调试的开发板,边看边用 tinymix、tinyplay 和 dumpsys 验证,把抽象概念落到真实寄存器与日志上。只有把“框架—HAL—驱动—硬件”这条链路走通一遍,Audio HAL 适配才算真正入门。
# 快速自检常用命令
adb shell cat /proc/asound/cards
adb shell tinymix
adb shell tinyplay /data/test.wav -D 0 -d 0
adb shell dumpsys media.audio_flinger | head -n 40
adb shell dumpsys media.audio_policy | head -n 40
adb logcat -s AudioFlinger AudioPolicyManager AudioHal
掌握这些基础后,再进入具体接口实现与配置细节,就能做到“知其然,也知其所以然”。