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 负责路由、音量、设备切换、焦点管理)。三条主线相互交织,共同决定“声音从哪里来、到哪里去、以多大声、以什么格式”。

Android 音频系统分层全景与 AudioFlinger 定位 应用框架层 MediaPlayer · AudioTrack · AudioRecord · MediaRecorder · AudioManager · SoundPool 系统服务层(Java / Native 桥接) AudioService · AudioSystem · JNI 桥接 · Binder 通信 原生框架层(libaudioflinger / libaudiopolicyservice) AudioFlinger 混音 · 线程调度 · 数据搬运 AudioPolicyService 路由 · 音量 · 焦点 · 设备切换 AudioTrack / AudioRecord Native 客户端对象 HAL 层(hardware/libhardware/modules/audio) audio_hw_device · audio_stream_out · audio_stream_in · 厂商实现 内核驱动层 ALSA / ASoC · Codec · DSP · I2S · 扬声器 / 麦克风 / 耳机 播放下行 / 录音上行

二、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 为例,数据在系统中的流动路径如下:

  1. 应用调用 AudioTrack.write(),数据进入 native AudioTrack 的共享内存缓冲区。
  2. AudioFlinger 的 MixerThread 周期性地从各 Track 的缓冲区取数据。
  3. 若采样率与输出设备不一致,先经过 AudioResampler 重采样。
  4. 多个 Track 的数据按音量系数累加,完成混音。
  5. 混音结果写入 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 音频系统。