第九板块:Android 多媒体体系 | 第二十三篇:AudioFlinger 与 AudioPolicyService 音频架构

32 阅读6分钟

第九板块:Android 多媒体体系 | 第二十三篇:AudioFlinger 与 AudioPolicyService 音频架构

所属板块:第九板块 — Android 多媒体体系

前置知识:第二十二篇中的网络体系、Linux 内核驱动、Binder IPC、SELinux、Cgroup 资源隔离

本篇定位:这是 Android 设备听觉体验的中央处理器。如果说屏幕是输出视觉,那么音频系统就是输出声音的神经中枢。本篇将彻底拆解 AudioFlinger 的混音(Mixing)引擎、AudioPolicyService 的策略决策逻辑、音频流(AudioTrack/AudioRecord) 的生命周期、音频焦点(Audio Focus) 的仲裁机制、低延迟音频(Fast Mixer) 的实现。我们将深入 HAL(Hardware Abstraction Layer)Kernel ALSA 驱动Framework Native 层,揭示 Android 如何在多应用同时发声时,既保证低延迟又保证互不干扰。


1. 核心结论先行(Thesis Statement)

Android 的音频系统是一个基于策略与合成的实时流水线

  • AudioFlinger 的本质音频合成工厂。它运行在 System Server 之外的独立 Native 进程中,负责接收所有应用的音频数据(PCM),进行混音(Mixing)重采样(Resampling)格式转换,并最终写入 HAL 接口。
  • AudioPolicyService 的本质音频交通警。它运行在 System Server 中,负责制定规则:哪个设备(Speaker/Headset/BT)发声、音量多大、是否允许某个应用发声(音频焦点)。
  • 音频流的本质共享内存(Shared Memory)的搬运。应用通过 AudioTrack 将 PCM 数据写入匿名共享内存(Ashmem),AudioFlinger 读取并混音。
  • 低延迟的本质绕过普通混音器。通过 Fast Mixer 线程,建立从应用到底层驱动的直通路径(Passthrough),减少缓冲区拷贝。

2. 音频架构全景图

2.1 从应用播放到喇叭发声

graph TB
    subgraph App ["应用进程"]
        AT["AudioTrack (Java/Native)"]
        AFocus["AudioManager (请求焦点)"]
    end

    subgraph SystemServer ["System Server"]
        APS["AudioPolicyService"]
        AFlinger["AudioFlinger"]
    end

    subgraph HAL ["硬件抽象层"]
        AudioHAL["audio.primary.so"]
    end

    subgraph Kernel ["Linux 内核"]
        ALSA["ALSA Driver (snd_pcm)"]
        Dev["/dev/snd/pcmC0D0p"]
    end

    subgraph Hardware ["硬件"]
        Codec["Audio Codec"]
        Speaker["Speaker/Headset"]
    end

    AT -->|"1. 写入 PCM 数据"| AFlinger
    AFocus -->|"2. 请求焦点"| APS
    APS -->|"3. 决策 (选设备/算音量)"| AFlinger
    AFlinger -->|"4. 混音/重采样"| AudioHAL
    AudioHAL -->|"5. pcm_write()"| ALSA
    ALSA -->|"6. DMA 传输"| Dev
    Dev -->|"7. I2S 信号"| Codec
    Codec -->|"8. 模拟信号"| Speaker

2.2 核心组件职责表

组件层级职责学术定义
AudioPolicyServiceFramework决策者管理音频路由、音量曲线、音频焦点、设备选择。
AudioFlingerNative执行者管理音频流、混音线程、重采样、与 HAL 交互。
PlaybackThreadNative工作线程AudioFlinger 中的线程,负责特定输出设备的混音循环。
AudioTrackFramework客户端接口应用向音频系统输送数据的接口。
AudioHALHAL硬件接口厂商实现的库,屏蔽不同硬件的差异。

3. AudioFlinger 的混音引擎

3.1 音频流(Track)的生命周期

AudioFlinger 为每个播放请求创建一个 Track

stateDiagram-v2
    [*] --> Idle: 创建 AudioTrack
    Idle --> Active: start()
    Active --> Flushing: flush()
    Flushing --> Active
    Active --> Paused: pause()
    Paused --> Active: start()
    Active --> Stopped: stop()
    Stopped --> [*]: 释放资源

3.2 混音线程(PlaybackThread)

AudioFlinger 针对不同的输出设备创建不同的线程。

线程类型特点适用场景
MixerThread最常用。支持多路混音,重采样。音乐、游戏音效。
DirectOutputThread直通。不经过混音器,直接写入 HAL。HDMI 源码输出、USB 音频。
OffloadThread硬解码。将压缩数据(MP3/AAC)直接送给 DSP 解码。音乐播放(省电)。

3.3 混音算法(Mixing)

AudioFlinger 使用 Fixed-point Arithmetic(定点运算) 进行混音,以保证性能和精度。

学术定义

  • 混音公式Output=(Inputi×Volumei)Output = \sum (Input_i \times Volume_i)
  • 重采样(Resampling):如果应用的采样率(如 44.1kHz)与硬件采样率(如 48kHz)不匹配,必须进行重采样。AudioFlinger 使用 SRC(Sample Rate Converter) 算法。
  • 溢出处理:混音后的值可能超过 16-bit 范围(-32768 ~ 32767),需要进行 Clipping(削波) 处理。

4. AudioPolicyService 的策略决策

4.1 音频焦点(Audio Focus)仲裁

当多个应用同时请求播放时,APS 决定谁有权发声。

学术定义

  • 焦点类型
    • AUDIOFOCUS_GAIN:长时间播放(音乐)。
    • AUDIOFOCUS_GAIN_TRANSIENT:短暂播放(导航提示)。
    • AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:短暂播放,允许原声音量降低(通知音)。
  • 仲裁逻辑
    1. 新应用请求焦点。
    2. APS 检查当前焦点持有者。
    3. 根据焦点类型和优先级,决定是 抢占(Abandon) 还是 拒绝(Fail)
sequenceDiagram
    participant Nav as 导航应用
    participant Music as 音乐应用
    participant APS as AudioPolicyService

    Music->>APS: requestFocus(GAIN)
    APS->>Music: 授予焦点 (AUDIOFOCUS_REQUEST_GRANTED)
    Music->>Music: 开始播放

    Nav->>APS: requestFocus(GAIN_TRANSIENT_MAY_DUCK)
    APS->>Music: 通知降低音量 (onAudioFocusChange)
    APS->>Nav: 授予焦点
    Nav->>Nav: 播放导航音 (音乐音量变小)

4.2 设备路由选择

APS 根据设备连接状态和策略选择输出设备。

设备状态路由决策
仅扬声器路由到 Speaker。
插入有线耳机路由到 Headset(强制切换)。
连接蓝牙 A2DP路由到 Bluetooth(如果未插耳机)。
HDMI 连接路由到 HDMI(数字音频)。

5. 低延迟音频(Fast Mixer)

5.1 普通路径 vs 快速路径

特性普通路径 (MixerThread)快速路径 (Fast Mixer)
缓冲区大小大 (20-100ms)极小 (2-5ms)
线程优先级普通SCHED_FIFO (实时)
重采样支持不支持 (必须匹配硬件)
混音多路混音单路直通
适用场景音乐、视频游戏、VOIP、乐器

5.2 Fast Mixer 的实现

Fast Mixer 是一个独立的线程,绑定到特定的 CPU 核心,使用 FIFO 调度策略。

学术定义

  • SCHED_FIFO:实时调度策略。一旦线程运行,除非主动放弃或更高优先级抢占,否则不会被切换出去。
  • CPU Affinity:将线程绑定到特定的 CPU 核心,避免缓存失效和上下文切换延迟。

6. 关键源码深度解析

6.1 AudioFlinger 的混音循环

// frameworks/av/services/audioflinger/Threads.cpp
void AudioFlinger::MixerThread::threadLoop() {
    while (!exitPending()) {
        // 1. 等待音频硬件就绪 (poll)
        waitForPcmSync();

        // 2. 准备混音缓冲区
        memset(mMixBuffer, 0, mMixBufferSize);

        // 3. 遍历所有活跃的 Track
        for (const sp<Track>& track : mActiveTracks) {
            // 读取 Track 数据
            track->getNextBuffer(&buffer);
            // 重采样
            resample(buffer);
            // 混音 (定点运算)
            mix(mMixBuffer, buffer, track->volume);
        }

        // 4. 写入 HAL
        mOutput->write(mMixBuffer, mMixBufferSize);
    }
}

6.2 AudioPolicyService 的焦点管理

// frameworks/av/services/audiopolicy/service/AudioPolicyService.cpp
status_t AudioPolicyService::requestAudioFocus(...) {
    // 1. 检查是否已有焦点持有者
    sp<AudioFocusInfo> current = mFocusStack.top();

    // 2. 检查优先级
    if (newFocus.priority <= current.priority) {
        // 抢占当前焦点
        current->client->onAudioFocusChange(AUDIOFOCUS_LOSS);
        mFocusStack.pop();
    }

    // 3. 授予新焦点
    mFocusStack.push(newFocus);
    return NO_ERROR;
}

7. 音频系统的常见误区

误区学术解释
音量越大,声音越响音量是数字增益(Digital Gain),过大会导致 Clipping(削波失真)。
采样率越高,音质越好如果源文件是 44.1kHz,强行升到 48kHz 会有损音质(SRC 误差)。
蓝牙音频是无损的绝大多数蓝牙音频使用 SBC 编码(有损压缩),LDAC/aptX HD 才是接近无损。
应用可以直接控制硬件不可以。所有音频必须经过 AudioFlinger 混音,应用只能控制自己的 Track 音量。

8. 本篇总结(Knowledge Closure)

关键点纯学术定义
AudioFlinger 的本质音频合成工厂,负责混音、重采样、格式转换。
AudioPolicyService 的本质音频交通警,负责路由、音量、焦点仲裁。
音频流路径应用 -> AudioTrack -> Shared Memory -> AudioFlinger -> HAL -> Kernel。
低延迟实现Fast Mixer + SCHED_FIFO + CPU Affinity + 小缓冲区。
音频焦点基于优先级的抢占式仲裁机制。

9. 第九板块结语

至此,第九板块:Android 多媒体体系 已完成核心架构解析。

我们从 AudioFlinger 的混音引擎 出发,深入 AudioPolicyService 的策略决策,探索 音频焦点的仲裁逻辑,最终抵达 低延迟音频的实时实现

我们揭示了 Android 音频系统的设计哲学:用策略隔离应用,用混音共享硬件,用实时线程保障延迟。

下一篇预告第九板块:Android 多媒体体系 | 第二十四篇:Camera Service 与 HAL3 成像流水线