3. Android音频架构总览
Android 音频系统是一条从应用层一直贯穿到内核驱动的纵向链路。理解这条链路的分层职责,是进行 Audio HAL 适配的前提。很多适配问题表面看是“没声音”“录音失败”“切设备不生效”,本质上都是某一层的状态、策略或数据流没有正确传递到下一层。因此,本节先建立一张完整的架构地图,再逐层拆解职责与交互关系。
一、六层纵向架构与核心职责
Android 音频栈自上而下可以划分为六个关键层次,每一层都有明确的边界:
- Application Framework 层:面向 App 的 API 层,包括
MediaPlayer、AudioTrack、AudioRecord、MediaRecorder、AudioManager等。App 只关心“播放/录音/调音量”,不感知设备与通路。 - AudioService 层:运行在 system_server 中的 Java 服务,负责音量策略、音频焦点、设备路由决策、铃声与通知管理,是“策略与状态”的集中管理者。
- AudioFlinger 层:Native 混音与音频流调度中心,负责创建 Track/RecordThread、混音、重采样、时间戳计算,并把数据推送给 HAL。
- AudioPolicy 层:Native 策略服务,决定“什么流走什么设备”,负责输出/输入设备选择、通道路由、音量曲线与策略配置解析。
- Audio HAL 层:厂商适配的核心层,向上提供统一的
audio_hw_device_t接口,向下操作具体硬件,是 Android 与芯片/Codec 之间的契约层。 - Kernel 驱动层:包括 ALSA/ASoC、DAPM、Codec 驱动、I2S/PDM 总线驱动、DMA 与时钟管理,最终把 PCM 数据送到扬声器、耳机或麦克风。
核心记忆法:App 提需求 → AudioService 定策略 → AudioPolicy 选设备 → AudioFlinger 混数据 → HAL 控硬件 → Kernel 传数据。数据流向下,控制流与状态反馈向上。
二、架构分层与数据/控制流示意
三、关键交互流程:一次播放请求的完整路径
以“App 播放一段音乐并插入耳机”为例,链路大致如下:
- App 通过
MediaPlayer或AudioTrack创建播放实例,携带AudioAttributes(用途、内容类型)。 - AudioService 根据焦点与音量策略分配音频焦点,并把流类型与属性传递给 Native 层。
- AudioPolicy 依据当前设备连接状态(耳机已插入)选择输出设备,并决定是否切换通路。
- AudioFlinger 创建对应的
Track与MixerThread,完成混音与重采样。 - AudioFlinger 通过 HAL 的
out_write()把 PCM 写入 HAL 缓冲区。 - HAL 调用 Kernel 的 ALSA/ASoC 接口,经 I2S 把数据送到 Codec,最终由耳机输出。
当耳机拔出时,Kernel 上报事件 → HAL 通过 get_parameters 或事件回调通知上层 → AudioPolicy 重新选设备 → AudioFlinger 切换输出通路。这条“事件上行、策略下行”的闭环,是音频适配中最常调试的路径。
四、各层职责与适配关注点对照
| 层次 | 核心职责 | 适配关注点 | 常见问题 |
|---|---|---|---|
| Application Framework | 提供播放/录音 API,传递属性 | 属性配置是否正确 | 属性不匹配导致路由错误 |
| AudioService | 音量、焦点、设备决策 | 音量曲线、设备优先级 | 音量档位异常、焦点丢失 |
| AudioPolicy | 选设备、通道路由 | audio_policy_configuration.xml | 设备未识别、路由不切换 |
| AudioFlinger | 混音、重采样、时间戳 | 线程与缓冲区配置 | 卡顿、爆音、延迟高 |
| Audio HAL | 硬件抽象与参数控制 | 接口实现、参数映射 | 无声、录音失败、切换无效 |
| Kernel 驱动 | PCM 传输与硬件控制 | DTS/ACPI、时钟、DMA | 时钟错乱、DMA 溢出 |
五、典型适配场景与复盘
假设某项目插入耳机后声音仍从扬声器输出。排查应自下而上进行:
# 1. 查看 HAL 是否上报耳机插入
adb shell dumpsys media.audio_flinger | grep -i "device"
adb shell dumpsys media.audio_policy | grep -i "output"
# 2. 查看内核事件
adb shell cat /proc/asound/cards
adb shell dmesg | grep -i "headset\|jack"
# 3. 查看策略配置
adb shell cat /vendor/etc/audio_policy_configuration.xml
常见误区:只改 HAL 而不检查 AudioPolicy 配置。HAL 负责“能不能用”,AudioPolicy 负责“用不用”。若策略配置中未声明耳机设备或路由规则缺失,HAL 实现再正确也不会被选中。
适配建议:先确认 Kernel 能识别设备,再确认 HAL 能正确上报与切换,最后确认 AudioPolicy 配置与 AudioService 策略一致。三层对齐后,绝大多数路由与音量问题都能定位。
总结来看,Android 音频架构是一条“策略在上、数据在下、HAL 居中”的分层链路。Audio HAL 适配的本质,是在 HAL 层把厂商硬件能力准确映射为 Android 标准接口,同时保证与 AudioPolicy、AudioFlinger、AudioService 的状态与策略保持一致。掌握这张分层地图,后续的 HAL 接口实现、参数调试与问题定位才有清晰的坐标系。