4. AudioFlinger核心职责

AudioFlinger 是 Android 音频系统的核心服务,运行在 mediaserver(或 audioserver)进程中,向上为 AudioTrack、AudioRecord、AudioPolicyService 等提供统一的音频流操作接口,向下通过 HAL 与 Audio HAL、ALSA 驱动、硬件编解码器交互。它并不直接决定“什么时候用哪个设备”,而是负责把上层提交的音频数据按策略混音、按路由输出、按音量曲线调节,并管理底层输出/输入设备的生命周期。理解 AudioFlinger 的五大核心职责,是掌握 Android 音频系统整体架构的关键。

一、核心职责总览

AudioFlinger 的职责可以概括为五个相互协作的维度:音频流管理、混音、路由、音量控制、设备管理。它们并非孤立存在,而是围绕“一条音频流从创建到销毁”的完整生命周期展开。下图展示了这五项职责之间的协作关系与数据流向。

上层应用 / AudioTrack / AudioRecord AudioFlinger 核心职责 音频流管理 Track / RecordTrack 创建 · 启动 · 停止 生命周期维护 混音 MixerThread 多轨叠加 · 重采样 格式转换 · 增益 路由 AudioPolicy 决策 策略 → 输出选择 流类型 → 设备映射 音量控制 音量曲线映射 软件增益 · 硬件增益 静音 · 淡入淡出 设备管理 OutputThread / InputThread 创建与销毁 HAL 设备打开 · 关闭 · 参数配置 设备热插拔 · 状态监听 Audio HAL / ALSA / 硬件设备 策略驱动 数据驱动 状态驱动 协同工作

二、音频流管理: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 设备。这一过程需要与电源管理、音频焦点机制协同工作。

常见误区:很多开发者认为 AudioFlinger 直接决定路由,实际上路由策略由 AudioPolicyService 决定,AudioFlinger 只负责执行。混淆两者会导致在排查音频输出问题时方向错误。

六、案例复盘:多应用同时播放的完整链路

假设用户同时打开音乐播放器和导航应用。音乐播放器创建 AudioTrack,流类型为 MUSIC;导航应用创建 AudioTrack,流类型为 NAVIGATION。AudioPolicyService 根据策略决定:两者都输出到扬声器,但导航音量优先。AudioFlinger 在同一个 MixerThread 中创建两个 Track,分别应用各自的音量系数,混合后写入 HAL。如果此时插入耳机,AudioPolicyService 通知 AudioFlinger 切换输出设备,AudioFlinger 关闭扬声器 OutputThread,打开耳机 OutputThread,并将两个 Track 迁移到新线程。整个过程对上层应用透明。

理解 AudioFlinger 的五大职责,有助于在排查音频问题时快速定位:是 Track 创建失败、混音 underrun、路由策略错误、音量曲线异常,还是设备打开失败。每一层都有对应的日志和调试手段,例如 dumpsys media.audio_flinger 可以查看当前所有 Track、线程、设备状态。