AudioFlinger架构基础:Android音频系统的心脏

引言:谁在统管Android的声音?

你有没有想过,当你同时打开音乐APP播放歌曲、微信来了消息提示音、游戏里的背景音乐也在跑------这三路音频是怎么在同一个手机扬声器里"和平共处"的?

答案就是 AudioFlinger

AudioFlinger 是 Android 音频系统的核心服务,它扮演着"音频混音台"的角色:来自各个应用的音频流,在这里被混合、处理,最终送到硬件层播放出来。用一个类比来说:如果每个应用都是一个乐手,AudioFlinger 就是那个指挥------统筹协调,确保所有声音按时、按序、按需发出。

本文是 Android 15 音频子系统系列的第一篇,将带你建立对 Android 音频架构的整体认知,重点解析 AudioFlinger 服务的核心设计。

本文内容

  • Android 音频系统四层架构全景
  • AudioFlinger 核心组件剖析(PlaybackThread / RecordThread / Mixer)
  • 音频数据流转路径:播放 & 录音
  • AudioFlinger 服务管理机制
  • Android 15 新特性
  • 调试工具速查

一、Android 音频系统四层架构

在开始深入 AudioFlinger 之前,先搭建宏观视角。Android 音频架构由四层组成,每层职责明确、相互解耦:

1.1 应用层(Application Layer)

开发者打交道最多的一层。应用通过 Java/Kotlin API 使用音频能力:

API 用途 典型场景
AudioTrack 低延迟 PCM 播放 游戏音效、实时音频处理
AudioRecord 低层录音采集 语音识别、实时录音
MediaPlayer 高层音频/视频播放 音乐播放器
MediaRecorder 高层录音封装 录音机 APP
AudioManager 音量 / 焦点 / 路由控制 所有需要音频控制的场景

1.2 Java Framework 层

android.media.* 包中的 Java 类,它们是对 Native 层的封装。关键类:

  • AudioTrack.java --- 播放 API,最终通过 JNI 调用 Native 的 AudioTrack.cpp
  • AudioRecord.java --- 录音 API,对应 Native 的 AudioRecord.cpp
  • AudioService.java --- 系统音频服务,管理音量、路由等全局状态(运行在 system_server 进程)

💡 一个容易搞混的问题AudioServiceAudioFlinger 都是"音频服务",区别是什么?

  • AudioService(Java):负责策略层面,管理音量、铃声模式、音频焦点等用户可感知的状态
  • AudioFlinger(Native C++):负责数据层面,实际混音、路由和输出音频数据

1.3 Native 层(AudioFlinger 所在层)

这里是本文的主角地盘:

bash 复制代码
frameworks/av/services/audioflinger/    # AudioFlinger 服务实现
frameworks/av/media/libaudioclient/     # 客户端库(AudioTrack/AudioRecord Native 实现)

核心进程是 audioserver,它包含两个关键服务:

  1. AudioFlinger --- 音频数据的实际处理者
  2. AudioPolicyService --- 音频策略的决策者(选择走哪个设备、用什么流类型)

两者分工明确:AudioPolicyService 做决策("应该用哪个输出设备"),AudioFlinger 执行决策("好的,我把数据送到那个设备")。

1.4 HAL 层与硬件层

bash 复制代码
hardware/interfaces/audio/    # Audio HAL 接口定义(HIDL/AIDL)

Android 13 起,Audio HAL 已完全迁移到 AIDL 接口(此前为 HIDL)。核心接口:

  • IModule --- 音频模块管理
  • IStreamOut --- 播放流接口
  • IStreamIn --- 录音流接口

HAL 层的存在让 Android 框架与具体芯片方案解耦------高通、MTK、三星各自实现自己的 Audio HAL,但上层框架代码不变。


二、AudioFlinger 核心组件剖析

了解了整体架构,现在深入 AudioFlinger 内部。

2.1 AudioFlinger 服务启动

AudioFlinger 运行在 audioserver 进程中,在系统启动时由 init 进程启动:

cpp 复制代码
// frameworks/av/services/audioflinger/main_audioserver.cpp
int main(int argc __unused, char **argv)
{
    // 设置进程优先级
    android::hardware::configureRpcThreadpool(4, false);

    sp<ProcessState> proc(ProcessState::self());
    sp<IServiceManager> sm(defaultServiceManager());

    // 注册 AudioFlinger 到 ServiceManager
    AudioFlinger::instantiate();

    // 注册 AudioPolicyService
    AudioPolicyService::instantiate();

    ProcessState::self()->startThreadPool();
    IPCThreadState::self()->joinThreadPool();
}
cpp 复制代码
// frameworks/av/services/audioflinger/AudioFlinger.cpp
void AudioFlinger::instantiate() {
    defaultServiceManager()->addService(
        String16("media.audio_flinger"), new AudioFlinger());
}

服务注册到 ServiceManager 后,任何进程都可以通过 Binder 获取 IAudioFlinger 接口进行操作。

2.2 PlaybackThread 家族

PlaybackThread 是 AudioFlinger 中负责音频播放的核心抽象。根据不同的输出场景,它派生出四种类型:

类型 特点 适用场景
MixerThread 多路混音,最常用 普通音乐、通知音
DirectOutputThread 绕过软件混音器,直通硬件 硬件解码输出
OffloadThread 音频数据卸载到 DSP 处理 低功耗后台播放
DuplicatingThread 同一路音频广播到多个输出 蓝牙 + 扬声器同时播

每个 PlaybackThread 都是一个独立的线程,在 threadLoop() 方法中循环运行:

cpp 复制代码
// frameworks/av/services/audioflinger/Threads.cpp
bool AudioFlinger::PlaybackThread::threadLoop()
{
    // 持续循环,直到 exitPending()
    while (!exitPending()) {

        // 1. 等待新的 Track 或配置变化
        Vector<sp<Track>> tracksToRemove;

        { // AutoMutex
            Mutex::Autolock _l(mLock);
            // 准备 Track 列表
            mActiveTracks.updatePowerState(this);
            prepareTracks_l(&tracksToRemove);
        }

        // 2. 混音:调用 Mixer 处理所有活跃 Track
        if (mType == MIXER) {
            threadLoop_mix();
        }

        // 3. 写入 HAL 层
        threadLoop_write();

        // 4. 回调已完成的 Track
        threadLoop_removeTracks(tracksToRemove);
    }
    return false;
}

2.3 Mixer 与 FastMixer:两种混音策略

MixerThread 中包含两个混音器,分别针对不同的延迟需求:

普通 Mixer(软件混音)

AudioMixer 负责将多路 PCM 音频进行混合,支持:

  • 音量调节(每路独立)
  • 采样率转换(Resampler)
  • 声道数转换
  • 音频效果(EQ、混响等)
cpp 复制代码
// frameworks/av/services/audioflinger/AudioMixer.cpp
void AudioMixer::process__genericResampling(state_t* state, int64_t pts)
{
    // 遍历所有激活的 Track
    for (int i = 0; i < MAX_NUM_TRACKS; i++) {
        if (!(state->enabledTracks & (1 << i))) continue;

        track_t& t = state->tracks[i];

        // 如果需要重采样
        if (t.needsRamp()) {
            // 应用音量渐变(防止突变噪音)
            t.volumeInc[0] = ...;
        }

        // 混音:输出 += 输入 * 音量
        t.hook(&t, state->outputTemp, numFrames, state->resampleTemp);
    }
}

FastMixer(低延迟混音)

FastMixer 是专为低延迟场景设计的独立线程,目标是实现 < 20ms 的端到端延迟:

cpp 复制代码
// frameworks/av/services/audioflinger/FastMixer.cpp
bool FastMixer::threadLoop()
{
    // 使用实时调度策略 SCHED_FIFO
    // 这是最关键的设计:避免被其他线程抢占

    // Lock-free 读取状态快照(无锁设计,避免阻塞)
    const FastMixerState *current = sq.poll();

    if (current != NULL) {
        // 处理快速 Track(FastTrack)
        for (int i = 0; i < FastMixerState::kMaxFastTracks; i++) {
            FastTrack *fastTrack = &current->mFastTracks[i];
            if (fastTrack->mBufferProvider != NULL) {
                // 直接读取 Buffer,不经过普通 Mixer 的复杂处理
                fastTrack->mBufferProvider->getNextBuffer(&buffer);
                mixer.setBufferProvider(i, fastTrack->mBufferProvider);
            }
        }
        // 混音并输出
        mixer.process(pts);
    }

    // 直接写入 HAL,不排队
    outputSink->write(mixBuffer, frameCount);
    return true;
}

FastMixer 的三个核心设计原则

  1. SCHED_FIFO 实时调度:进程/线程不会被普通任务抢占
  2. Lock-free 无锁:使用双缓冲 + 原子操作,避免 mutex 锁竞争造成的抖动
  3. 最小化路径:FastTrack 跳过音量渐变、重采样等耗时操作,直连 HAL

2.4 RecordThread 录音线程

与 PlaybackThread 对应,RecordThread 负责从 HAL 读取录音数据并分发给各个 AudioRecord 客户端:

cpp 复制代码
// frameworks/av/services/audioflinger/Threads.cpp
bool AudioFlinger::RecordThread::threadLoop()
{
    while (!exitPending()) {
        // 1. 从 HAL 读取音频数据
        mInputSource->read(mRsmpInBuffer, mRsmpInFrames);

        // 2. 遍历所有 RecordTrack,写入各自的 Buffer
        Vector<sp<RecordTrack>> activeRecordTracks;
        {
            Mutex::Autolock _l(mLock);
            activeRecordTracks = mActiveTracks;
        }

        for (auto& track : activeRecordTracks) {
            // 写入到 Track 的共享内存 Buffer 中
            track->copyFramesFromProxy();
        }
    }
    return false;
}

三、音频数据流转路径

理解了各组件的职责,现在来看数据是如何在系统中流动的。

3.1 播放路径:从 App 到扬声器

一个 AudioTrack.write() 调用触发的完整数据流:

java 复制代码
App → AudioTrack (Java)
  ↓ JNI
AudioTrack (Native C++)
  ↓ 写入共享内存 Ring Buffer
AudioFlinger :: MixerThread
  ↓ Mixer 混音(多路合并 + 音量调节)
  ↓ FastMixer(低延迟路径)
Audio HAL (IStreamOut)
  ↓ 驱动写入
扬声器/耳机

共享内存(Shared Memory) 是这条路径上最关键的设计。App 进程和 AudioFlinger 进程通过一块共享内存直接交换数据,避免了 Binder IPC 的数据拷贝开销:

cpp 复制代码
// AudioFlinger 为客户端创建共享内存
sp<MemoryDealer> heap = new MemoryDealer(1024*1024, "AudioTrack Heap Base");
sp<IMemory> sharedBuffer = heap->allocate(frameCount * frameSize);

// 客户端持有 IMemory,直接读写,不需要 Binder 传输数据
client->audioTrack->setBuffer(sharedBuffer);

3.2 录音路径:从麦克风到 App

录音路径与播放路径方向相反:

css 复制代码
麦克风 → Audio Driver (ALSA/TinyALSA)
  ↓ DMA 数据传输
Audio HAL (IStreamIn)
  ↓
AudioFlinger :: RecordThread
  ↓ 重采样 / 声道转换 / 音效处理
共享内存 Ring Buffer
  ↓ AudioRecord (Native) 读取
AudioRecord (Java) read() 返回数据
  ↓
App 处理音频数据(语音识别 / 录音等)

3.3 共享内存的 Ring Buffer 机制

播放和录音都使用 环形缓冲区(Ring Buffer) 进行数据交换,这是一个经典的"生产者-消费者"模型:

复制代码
播放场景:
App(生产者)写数据  →  Ring Buffer  →  AudioFlinger(消费者)读数据混音

录音场景:
AudioFlinger(生产者)写数据  →  Ring Buffer  →  App(消费者)读数据

Ring Buffer 的关键参数是大小(Buffer Size),它直接影响延迟:

  • Buffer 太小:延迟低,但容易发生 underrun(播放断续)
  • Buffer 太大:延迟高,但稳定
java 复制代码
// 计算最小 Buffer 大小(推荐做法)
int minBufferSize = AudioTrack.getMinBufferSize(
    44100,                          // 采样率 44.1kHz
    AudioFormat.CHANNEL_OUT_STEREO, // 立体声
    AudioFormat.ENCODING_PCM_16BIT  // 16位 PCM
);
// 通常创建 2-4 倍 minBufferSize 的 Buffer
AudioTrack track = new AudioTrack.Builder()
    .setBufferSizeInBytes(minBufferSize * 2)
    .build();

四、AudioFlinger 服务管理

4.1 客户端连接与 Track 创建

当 App 创建 AudioTrack 时,最终会通过 Binder 调用 AudioFlinger 的 createTrack() 方法:

cpp 复制代码
// frameworks/av/services/audioflinger/AudioFlinger.cpp
sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
                                           CreateTrackOutput& output,
                                           status_t *status)
{
    // 1. 找到合适的 PlaybackThread(由 AudioPolicyService 决定)
    PlaybackThread *thread = checkPlaybackThread_l(output.outputId);

    // 2. 在 PlaybackThread 中创建 Track 对象
    sp<PlaybackThread::Track> track = thread->createTrack_l(
        client,
        input.attr.streamType,
        input.config.sample_rate,
        input.config.format,
        input.config.channel_mask,
        &frameCount,
        sharedBuffer,    // 共享内存
        sessionId,
        &output
    );

    // 3. 返回 TrackHandle(Binder 代理对象)给客户端
    sp<TrackHandle> trackHandle = new TrackHandle(track);
    return trackHandle;
}

4.2 线程同步与锁

AudioFlinger 是高并发服务,多个客户端可以同时操作,需要精细的锁管理:

cpp 复制代码
class AudioFlinger : public BnAudioFlinger {
    // 全局大锁,保护 Thread 列表、Client 列表等
    mutable Mutex mLock;

    // 每个 PlaybackThread 有自己的锁
    // 使用细粒度锁避免全局锁竞争
};

注意 :FastMixer 使用无锁设计(StateQueue),而普通的 MixerThread 使用互斥锁。这是因为 FastMixer 对实时性要求极高,任何锁等待都可能造成可感知的音频抖动。

4.3 AudioEffect 音效链

AudioFlinger 支持在 PlaybackThread 上挂载 AudioEffect(音频效果):

cpp 复制代码
// 在 PlaybackThread 上创建 Effect Chain
sp<EffectChain> chain = thread->getEffectChain_l(sessionId);
// 在 Chain 上创建具体的 Effect(如均衡器)
sp<EffectModule> effect = chain->createEffect_l(
    EFFECT_TYPE_EQUALIZER, // 均衡器类型
    &descOut,
    sessionId,
    ioHandle
);

Effect 分为两种作用范围:

  • Session Effect:只影响特定 AudioSession 的音频(通常是某个 App 的输出)
  • Output Effect:影响整个输出流(所有混音后的音频)

五、Android 15 音频新特性

5.1 超低延迟优化

Android 15 进一步优化了音频延迟路径,引入了 AAudio 专属低延迟通道

java 复制代码
// 使用 AAudio API 获得最低延迟
AAudioStreamBuilder *builder;
AAudio_createStreamBuilder(&builder);
AAudioStreamBuilder_setPerformanceMode(builder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
AAudioStreamBuilder_setSharingMode(builder, AAUDIO_SHARING_MODE_EXCLUSIVE);
// 独占模式 + 低延迟模式 = 端到端延迟可低至 5ms

5.2 空间音频(Spatial Audio)

Android 15 对空间音频做了架构级优化:

  • Head Tracking:通过陀螺仪/加速度计实现随头部运动的声场调整
  • Virtualizer:软件模拟 5.1/7.1 声道
  • Binaural Rendering:针对耳机的双耳渲染,提供 3D 空间感

空间音频在 AudioFlinger 层通过 AudioEffect 链实现,系统预置了 android.media.audio.HapticGenerator 等效果器。

5.3 Bluetooth Audio 改进

Android 15 中,蓝牙音频的 HAL 层完全迁移到 AIDL,支持:

  • LC3 编码(蓝牙 LE Audio 标准)
  • LE Audio 广播(一个音频源广播给多个接收者)
  • Hearing Aid 助听器支持
java 复制代码
// 检查设备是否支持 LE Audio
AudioManager am = getSystemService(AudioManager.class);
List<AudioDeviceInfo> devices = am.getAvailableCommunicationDevices();
for (AudioDeviceInfo device : devices) {
    if (device.getType() == AudioDeviceInfo.TYPE_BLE_HEADSET) {
        // 支持 LE Audio
    }
}

六、调试技巧

掌握 AudioFlinger 的调试技巧是解决音频问题的关键。

6.1 dumpsys:全景快照

bash 复制代码
# 查看 AudioFlinger 完整状态
adb shell dumpsys media.audio_flinger

# 关键输出解读:
# Output thread xxx:
#   Standby time: xxx ms    (进入待机的超时)
#   Normal frames: xxx      (普通帧计数)
#   HAL frame count: xxx    (HAL Buffer 大小)
#   Active tracks: xxx      (当前活跃的 Track 数量)
bash 复制代码
# 查看 AudioPolicy 状态(路由决策)
adb shell dumpsys media.audio_policy

# 查看音频焦点状态
adb shell dumpsys audio | grep -A 20 "Audio Focus"

6.2 实时日志过滤

bash 复制代码
# 过滤 AudioFlinger 相关日志
adb logcat -s AudioFlinger:V AudioPolicyService:V AudioTrack:V

# 查看 underrun(欠载)问题
adb logcat | grep -i "underrun\|AudioFlinger\|latency"

6.3 常见问题诊断

问题1:音频卡顿(Glitch)

bash 复制代码
# 检查是否有 underrun
adb shell dumpsys media.audio_flinger | grep -i "underrun\|underflows"

# 通常原因:
# 1. App 写入 AudioTrack 不及时(Buffer underrun)
# 2. 系统负载过高,MixerThread 得不到及时调度
# 3. 解决方法:增大 Buffer 大小,或使用 FastTrack 模式

问题2:无音频输出

bash 复制代码
# 检查输出线程是否在运行
adb shell dumpsys media.audio_flinger | grep "Output thread"

# 检查 HAL 是否正常
adb shell dumpsys media.audio_flinger | grep -A 5 "HAL"

问题3:延迟过高

bash 复制代码
# 查看当前延迟
adb shell dumpsys media.audio_flinger | grep "latency\|Latency"

# FastMixer 是否在运行
adb shell dumpsys media.audio_flinger | grep "FastMixer"

6.4 Perfetto 音频性能追踪

bash 复制代码
# 使用 Perfetto 捕获音频性能数据
adb shell perfetto \
  -c - --txt \
  -o /data/misc/perfetto-traces/trace \
<<EOF
buffers: { size_kb: 8960 fill_policy: RING_BUFFER }
data_sources: { config { name: "linux.ftrace"
  ftrace_config {
    ftrace_events: "audio/audio_flinger_set_volume"
    ftrace_events: "audio/audio_flinger_write_begin"
    ftrace_events: "audio/audio_flinger_write_end"
  }
}}
duration_ms: 5000
EOF

七、AudioFlinger 的设计思想总结

回顾 AudioFlinger 的架构,有几个核心设计思想值得反复品味:

7.1 分层与解耦

  • 策略与执行分离:AudioPolicyService 决定"怎么做",AudioFlinger 执行"做什么"
  • HAL 抽象:上层不关心底层是高通 DSP 还是联发科音频芯片
  • 共享内存:应用层与服务层的零拷贝通信

7.2 延迟分层

Android 音频系统提供了多种延迟档位,让开发者根据需求选择:

延迟档位 实现机制 典型延迟 适用场景
极低延迟 FastTrack + FastMixer ~5ms 乐器、实时效果
低延迟 FAST 模式 ~20ms 游戏音效
普通延迟 MixerThread ~50ms 音乐播放
高延迟(省电) OffloadThread >100ms 后台音乐

7.3 实时性保障

FastMixer 使用 SCHED_FIFO 实时调度 + Lock-free 设计,这是 Linux 实时音频领域的标准做法,确保音频不会因为系统负载而出现抖动。


总结

本文介绍了 Android 15 音频系统的整体架构和 AudioFlinger 的核心组件:

  1. 四层架构:应用层 → Java Framework → Native(AudioFlinger)→ HAL → 硬件
  2. PlaybackThread 家族:MixerThread(普通混音)、FastMixer(低延迟)、DirectOutputThread(直通)、OffloadThread(省电)
  3. 数据流转:共享内存 Ring Buffer 是应用与 AudioFlinger 之间高效通信的基础
  4. 双服务分工:AudioPolicyService(策略) + AudioFlinger(数据)共同构成音频 Native 层

理解 AudioFlinger 的架构,是后续深入学习 AudioTrack 播放流程、混音机制、音频焦点管理的基础。


参考资料

  • Android Audio Architecture --- 官方架构文档
  • AudioFlinger Source Code --- AOSP 源码
  • frameworks/av/services/audioflinger/AudioFlinger.cpp --- 服务实现
  • frameworks/av/services/audioflinger/Threads.cpp --- PlaybackThread/RecordThread 实现
  • frameworks/av/services/audioflinger/FastMixer.cpp --- FastMixer 低延迟混音器

本文基于Android 15 (API Level 35)源码分析,不同厂商的定制ROM可能存在差异。 欢迎来我中的个人主页找到更多有用的知识和有趣的产品

相关推荐
铁手飞鹰3 小时前
Visual Studio创建Cmake工程导出DLL,通过Python调用DLL
android·python·visual studio
冰语竹7 小时前
Android学习之相对布局
android
没有了遇见7 小时前
Android 中大型项目架构梳理
android
yashuk8 小时前
【MySQL】表的相关操作
android·mysql·adb
71-38 小时前
Android studio中真机操作
android·笔记·学习·其他·android studio
一只特立独行的Yang9 小时前
Android Focus小结
android
aaajj12 小时前
【Android】appops学习
android·学习
煤球王子12 小时前
学习记录:Android14中的Wifi_Direct(P2P)
android
找藉口是失败者的习惯12 小时前
【Android】Android 车机 + AI Agent 有没有搞头?
android·人工智能