1. 课程导入
在 Android 系统中,音频是一条从应用层一直贯穿到硬件编解码器的完整链路。无论是播放一首音乐、接听一通电话、录制一段语音,还是游戏中的实时音效,最终都要经过一套高度分层的软件栈,把上层的“播放/录音意图”翻译成 PCM 采样数据,再交给 HAL 与内核驱动送到扬声器或从麦克风取回。理解这条链路,是掌握 Android 音频系统的第一步,而 AudioFlinger 正是这条链路中承上启下的核心服务。
一、Android 音频系统全景
从纵向分层来看,Android 音频系统大致可以划分为五层:应用框架层、系统服务层、原生框架层、HAL 层与内核驱动层。应用通过 MediaPlayer、AudioTrack、AudioRecord、MediaRecorder 等 API 发起音频请求;这些 API 最终通过 JNI 进入原生层,由 AudioFlinger、AudioPolicyService、AudioTrack/AudioRecord(native)等模块协同处理;再往下通过 audio_hw_device 等 HAL 接口与厂商实现对接,最后由 ALSA/ASoC 驱动操作 Codec、DSP、I2S 等硬件资源。
横向来看,音频系统又可分为三条主线:播放通路(App → AudioTrack → AudioFlinger MixerThread → HAL → 扬声器)、录音通路(麦克风 → HAL → RecordThread → AudioRecord → App)以及策略控制通路(AudioPolicyService 负责路由、音量、设备切换、焦点管理)。三条主线相互交织,共同决定“声音从哪里来、到哪里去、以多大声、以什么格式”。
二、AudioFlinger 的定位
AudioFlinger 是 Android 原生音频框架中的音频引擎与混音中心。它运行在 mediaserver 进程中,通过 Binder 向应用和系统服务提供 IAudioFlinger 接口。它的核心职责可以概括为四点:
- 创建与管理 Track:为每个播放请求创建
PlaybackThread::Track,为录音请求创建RecordThread::RecordTrack。 - 混音与重采样:把多个不同采样率、声道数、格式的 Track 混合成一条统一格式的输出流。
- 线程调度:维护 MixerThread、DirectOutputThread、OffloadThread、RecordThread 等线程模型,按场景选择不同通路。
- 与 HAL 交互:通过
audio_stream_out的write()把 PCM 数据写入 HAL,或通过audio_stream_in的read()取回录音数据。
需要特别区分的是:AudioFlinger 负责“怎么混、怎么搬”,AudioPolicyService 负责“走哪条路、用哪个设备、音量多大”。两者一个偏执行、一个偏决策,共同构成原生音频框架的双核心。
一句话定位:AudioFlinger 是 Android 音频数据的“交通枢纽”,所有播放与录音的 PCM 数据都要在这里汇聚、混合、分发。
三、核心原理:一次播放请求的完整旅程
以 AudioTrack.write() 播放一段 44.1kHz 立体声 PCM 为例,数据在系统中的流动路径如下:
- 应用调用
AudioTrack.write(),数据进入 native AudioTrack 的共享内存缓冲区。 - AudioFlinger 的 MixerThread 周期性地从各 Track 的缓冲区取数据。
- 若采样率与输出设备不一致,先经过
AudioResampler重采样。 - 多个 Track 的数据按音量系数累加,完成混音。
- 混音结果写入 HAL 的
out->write(),由驱动送到 Codec。
// 简化后的播放数据流(伪代码)
App: AudioTrack.write(pcm, size)
→ SharedMemory (client buffer)
→ AudioFlinger::MixerThread::threadLoop()
→ Track::getNextBuffer()
→ AudioResampler::resample()
→ mixBuffer 累加
→ mOutput->write(mixBuffer)
→ HAL audio_stream_out::write()
→ ALSA / Codec → Speaker
四、典型场景与常见误区
场景一:音乐播放。通常走 MixerThread 或 OffloadThread,前者由 AP 混音,后者把压缩音频直接交给 DSP 解码以省电。场景二:通话。走 DeepBuffer 或专用 Voice 通路,由 AudioPolicyService 根据 audio_mode 切换。场景三:低延迟游戏。走 FastMixerThread,通过 FAST flag 绕过普通混音路径,把延迟压到 10ms 级别。
常见误区:很多初学者以为“AudioFlinger 就是播放器”。实际上它不解析 MP3/AAC,解码由 MediaCodec 或 Offload 通路完成;AudioFlinger 只处理 PCM 层面的混音与搬运。另一个误区是认为“音量调节在 AudioFlinger 里做”,实际上音量策略由 AudioPolicyService 决定,AudioFlinger 只负责把音量系数应用到混音过程。
五、学习目标与整体框架
本课程将围绕 AudioFlinger 展开,逐层拆解其内部结构与运行机制。学习完成后,你应当能够:读懂 AudioFlinger 的启动流程与线程模型;理解 Track、Thread、Output、Patch 等核心对象的关系;掌握混音、重采样、音量应用的实现细节;能够分析音频卡顿、爆音、延迟、路由错误等典型问题。
| 模块 | 核心内容 | 关键对象 |
|---|---|---|
| 启动与初始化 | mediaserver 启动、AudioFlinger 构造、HAL 加载 | AudioFlinger、AudioHwDevice |
| 线程模型 | MixerThread、DirectOutput、Offload、RecordThread | PlaybackThread、RecordThread |
| Track 管理 | Track 创建、状态机、共享内存、回调 | Track、TrackBase、Client |
| 混音与重采样 | 混音算法、音量应用、AudioResampler | AudioMixer、AudioResampler |
| 策略与路由 | AudioPolicyService 与 AudioFlinger 协作 | AudioPolicyManager、Patch |
| 调试与排障 | dumpsys media.audio_flinger、日志、性能分析 | dumpsys、Perfetto、systrace |
建议在学习过程中配合真机或模拟器,使用 adb shell dumpsys media.audio_flinger 观察实际的线程、Track 与输出设备状态,把抽象概念与真实运行数据对应起来。只有把“代码里的对象”和“设备上的声音”建立联系,才能真正掌握 Android 音频系统。