【Auido】深入AudioFlinger的混音机制总结
文章目录一、 核心架构:AudioFlinger 与线程模型二、 混音前奏:Track 的创建与共享内存三、 混音核心:AudioMixer 的工作原理实际案例分析:音乐 + 通知四、 数据流出:写入 HAL 与硬件播放五、 Android 15 的新关注点结语作为一名Android系统工程师,深入理解音频架构的每一层是我的日常。Android 15在音频领域带来了诸多改进,但混音这个核心模块依然稳固而强大。今天,我们将从源码视角深入AudioFlinger的混音引擎,解析多路音频流是如何精确混合并输出的。一、 核心架构:AudioFlinger 与线程模型在Android系统中,AudioFlinger是音频服务的核心,运行在audioserver进程中。它负责接收来自不同应用(AudioTrack)的音频数据,并统一输出到硬件设备。为了实现这一目标,AudioFlinger采用了多线程模型。每种输出设备(如扬声器、蓝牙耳机、USB声卡)通常对应一个PlaybackThread。其中,最核心的线程类型是MixerThread。+-------------------------------------------------------------------+ | App Process | | +--------+ +--------+ +--------+ | | | App 1 | | App 2 | | App 3 | (PCM Data) | | +--------+ +--------+ +--------+ | | | | | | | (Binder) (Binder) (Binder) | +-------------------------------------------------------------------+ | | | v v v +-------------------------------------------------------------------+ | audioserver Process | | +-------------------------------------------------------------+ | | | AudioFlinger | | | | +----------------------+ +--------------------------+ | | | | | MixerThread | | DirectOutputThread | | | | | | +--------+---------+| | (Low Latency Path) | | | | | | | Track1 | Track2 | | +--------------------------+ | | | | | +--------+---------+| +--------------------------+ | | | | | | | | | RecordThread | | | | | | AudioMixer | | (Input/Capture Path) | | | | | +----------------------+ +--------------------------+ | | | +-------------------------------------------------------------+ | | | | | (AIDL/HIDL) | +-------------------------------------------------------------------+ | v +-------------------------------------------------------------------+ | Vendor HAL Process | | audio.primary.default.so | | (TinyALSA) | +-------------------------------------------------------------------+MixerThread: 绝大多数音频播放场景使用的线程。它从多个Track(代表应用音频流)读取数据,混合后输出。DirectOutputThread: 用于无损或低延迟场景,绕过混音,直接将数据传给HAL。RecordThread: 负责录音数据的采集和分发。二、 混音前奏:Track 的创建与共享内存在数据混合之前,App需要先创建一个AudioTrack。这个过程涉及跨进程通信和内存共享。创建请求: App通过Binder调用AudioFlinger::createTrack()。线程分配:AudioFlinger根据AudioPolicyService的策略,找到对应的MixerThread,并调用其createTrack_l()方法创建一个Track对象。内存分配: 为了高效传输数据,避免大量数据拷贝,系统使用共享内存。AudioFlinger通过MemoryDealer分配一块共享内存,App端和AudioFlinger端都能直接访问这块内存。这块内存被设计为环形缓冲区(Ring Buffer)。App作为生产者写入PCM数据,MixerThread作为消费者读取数据。一个名为audio_track_cblk_t的控制块位于共享内存头部,管理读写指针,确保数据同步。// frameworks/av/media/libaudioclient/include/media/AudioTrack.h// App端持有的Proxy对象,操作共享内存spandroid::media::AudioTrackClientProxymProxy