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 传数据。数据流向下,控制流与状态反馈向上。

二、架构分层与数据/控制流示意

Android 音频架构分层:数据流 ↓ 与 控制/状态流 ↑ Application Framework AudioTrack / AudioRecord / MediaPlayer / MediaRecorder / AudioManager / AudioAttributes AudioService(system_server / Java) 音量策略 · 音频焦点 · 设备路由决策 · 铃声/通知 · AudioDeviceBroker AudioPolicy(Native) 选设备 · 通道路由 · 音量曲线 · 策略配置解析 AudioFlinger(Native) Track/RecordThread · 混音 · 重采样 · 时间戳 Audio HAL(厂商适配核心层) audio_hw_device_t · audio_stream_out/in · audio_patch · set_parameters/get_parameters 实现形态:Legacy HAL / AIDL HAL / HIDL HAL(Android 8~14 演进) Kernel 驱动层 ALSA / ASoC · DAPM · Codec 驱动 · I2S/PDM 总线 · DMA · 时钟与电源管理 最终输出:PCM 数据 → 扬声器 / 耳机 / 听筒 / 麦克风 / 蓝牙 / USB 数据流(PCM / 音频帧) 控制流 / 状态反馈(路由、参数、事件) 注:AudioPolicy 与 AudioFlinger 同处 Native 层,通过 AudioPolicyService 与 AudioFlinger 的接口协同工作。

三、关键交互流程:一次播放请求的完整路径

以“App 播放一段音乐并插入耳机”为例,链路大致如下:

  1. App 通过 MediaPlayer 或 AudioTrack 创建播放实例,携带 AudioAttributes(用途、内容类型)。
  2. AudioService 根据焦点与音量策略分配音频焦点,并把流类型与属性传递给 Native 层。
  3. AudioPolicy 依据当前设备连接状态(耳机已插入)选择输出设备,并决定是否切换通路。
  4. AudioFlinger 创建对应的 Track 与 MixerThread,完成混音与重采样。
  5. AudioFlinger 通过 HAL 的 out_write() 把 PCM 写入 HAL 缓冲区。
  6. 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 接口实现、参数调试与问题定位才有清晰的坐标系。