4. AudioFlinger核心职责
AudioFlinger 是 Android 音频系统的核心服务,运行在 mediaserver(或 audioserver)进程中,向上为 AudioTrack、AudioRecord、AudioPolicyService 等提供统一的音频流操作接口,向下通过 HAL 与 Audio HAL、ALSA 驱动、硬件编解码器交互。它并不直接决定“什么时候用哪个设备”,而是负责把上层提交的音频数据按策略混音、按路由输出、按音量曲线调节,并管理底层输出/输入设备的生命周期。理解 AudioFlinger 的五大核心职责,是掌握 Android 音频系统整体架构的关键。
一、核心职责总览
AudioFlinger 的职责可以概括为五个相互协作的维度:音频流管理、混音、路由、音量控制、设备管理。它们并非孤立存在,而是围绕“一条音频流从创建到销毁”的完整生命周期展开。下图展示了这五项职责之间的协作关系与数据流向。
二、音频流管理:Track 的创建与生命周期
音频流管理是 AudioFlinger 最基础的职责。上层通过 AudioTrack 或 AudioRecord 发起请求,AudioFlinger 在对应的 PlaybackThread 或 RecordThread 中创建 Track(播放轨)或 RecordTrack(录音轨)。每个 Track 都持有共享内存缓冲区、音频格式、采样率、声道掩码、流类型等元数据。
Track 的生命周期包括:创建、启动、运行、暂停、停止、销毁。AudioFlinger 通过 createTrack() 分配 Track 对象并返回共享内存句柄;通过 start() 将 Track 加入活动列表,使其参与混音;通过 stop() 将其移出活动列表;通过 destroyTrack() 释放资源。Track 的状态变化必须与线程循环同步,避免在混音过程中修改链表结构。
// 简化示意:AudioFlinger::createTrack 关键流程
sp<IAudioTrack> AudioFlinger::createTrack(
const audio_attributes_t& attr,
const sp<AudioTrack::IAudioTrackCallback>& callback,
uint32_t *sampleRate, audio_format_t *format,
audio_channel_mask_t *channelMask,
size_t *frameCount, IAudioTrack **trackOut) {
// 1. 根据流类型和策略选择输出线程
// 2. 创建 Track 对象,分配共享内存
// 3. 将 Track 加入线程的 mTracks 列表
// 4. 返回 IAudioTrack 接口给上层
}
三、混音:多轨叠加与格式转换
混音是 AudioFlinger 最核心的数据处理职责。当多个应用同时播放音频时,AudioFlinger 需要将它们的数据在 MixerThread 中按帧叠加。混音过程包括:重采样(不同采样率统一到输出采样率)、格式转换(PCM 8/16/24/32 位、浮点)、声道映射(单声道转立体声、5.1 下混)、增益应用(每个 Track 的音量)、最终饱和截断。
Android 的混音器采用 AudioMixer 类实现,支持 NEON 和 SSE 优化。混音线程以固定周期(通常 5ms~20ms)运行,每次从各 Track 的共享内存读取数据,混合后写入 HAL 输出缓冲区。如果某个 Track 数据不足,会触发 underrun 处理;如果数据过多,则进行丢弃或等待。
fastMixer 或 normalMixer 决定。Fast Track 使用更小的缓冲区(如 2ms~5ms)以降低延迟,普通 Track 使用较大缓冲区以节省功耗。
四、路由与音量控制:策略与执行的分离
路由决策由 AudioPolicyService 负责,AudioFlinger 负责执行。当 AudioPolicyService 决定某条流应该输出到扬声器、耳机还是蓝牙设备时,它会通知 AudioFlinger 打开对应的输出线程或切换输出设备。AudioFlinger 通过 openOutput()、closeOutput()、setParameters() 等接口与 HAL 交互。
音量控制分为软件增益和硬件增益。软件增益在混音阶段对每个 Track 应用音量系数;硬件增益通过 HAL 设置设备音量。Android 使用音量曲线(Volume Curve)将用户界面的音量档位映射为分贝值,不同流类型(音乐、铃声、通话、闹钟)有独立的音量曲线和档位范围。
| 职责 | 核心类/线程 | 关键接口 | 典型场景 |
|---|---|---|---|
| 音频流管理 | Track / RecordTrack | createTrack / start / stop | 音乐播放、录音 |
| 混音 | MixerThread / AudioMixer | threadLoop / mix | 多应用同时播放 |
| 路由 | AudioPolicyService + OutputThread | openOutput / setParameters | 耳机插入切换 |
| 音量控制 | AudioService + AudioFlinger | setStreamVolume / setMasterVolume | 音量键调节 |
| 设备管理 | OutputThread / InputThread | open / close / standby | 蓝牙连接、USB 声卡 |
五、设备管理:输出/输入线程与 HAL 交互
设备管理负责创建和维护 OutputThread 与 InputThread。每个输出设备对应一个 OutputThread,每个输入设备对应一个 InputThread。线程内部包含一个 HAL 输出流或输入流,通过 audio_stream_out 或 audio_stream_in 与硬件通信。当设备热插拔时,AudioPolicyService 会触发 AudioFlinger 打开新设备或关闭旧设备。
设备管理还需要处理 standby 状态:当没有音频播放时,OutputThread 进入 standby 以节省功耗;当有新 Track 启动时,线程被唤醒并重新打开 HAL 设备。这一过程需要与电源管理、音频焦点机制协同工作。
六、案例复盘:多应用同时播放的完整链路
假设用户同时打开音乐播放器和导航应用。音乐播放器创建 AudioTrack,流类型为 MUSIC;导航应用创建 AudioTrack,流类型为 NAVIGATION。AudioPolicyService 根据策略决定:两者都输出到扬声器,但导航音量优先。AudioFlinger 在同一个 MixerThread 中创建两个 Track,分别应用各自的音量系数,混合后写入 HAL。如果此时插入耳机,AudioPolicyService 通知 AudioFlinger 切换输出设备,AudioFlinger 关闭扬声器 OutputThread,打开耳机 OutputThread,并将两个 Track 迁移到新线程。整个过程对上层应用透明。
理解 AudioFlinger 的五大职责,有助于在排查音频问题时快速定位:是 Track 创建失败、混音 underrun、路由策略错误、音量曲线异常,还是设备打开失败。每一层都有对应的日志和调试手段,例如 dumpsys media.audio_flinger 可以查看当前所有 Track、线程、设备状态。