KunSpace
返回博客

Android 音频框架总览:从 App 到 ALSA 的分层与两大服务

2026年6月23日
尚无阅读

读完了?别空手走啊 😏

白嫖可以,但点个赞显得有教养

写评论

读完了不评论,作者会以为你在沉思

这篇写什么?

做 TV / Soundbar / HDMI 音频时,一堆问题最后都会问到同一句:

声音是从哪一层发出去的?谁决定走喇叭还是 ARC?谁真正打开设备?

本文按 分层架构 把 Android 音频框架捋一遍:入口谁注册、两大服务各干什么、mediaserver / audioserver 怎么起来,以及 AudioPatch 如何把「源 → 宿」接到 HAL。

一句话:

App(MediaPlayer / AudioTrack …)
  → Framework Java + Binder
  → audioserver:AudioFlinger(干活)+ AudioPolicyService(定策略)
  → HAL(audio.primary / policy)
  → TinyALSA / ALSA → 芯片与喇叭

Android 音频框架分层总览

相关:音量设置流程HDMI-IN Patch


一、先看整张分层图(从上往下)

典型组件 干什么
Application 音乐、录音、通话… 用户场景
Framework(Java) MediaPlayer / AudioTrack / AudioRecord / AudioManager / AudioService App 调用的 API;AudioManagerAudioService 走 Binder
Libraries Client libmedia.so 里的 native Track/Record App 进程内的客户端代理
Binder IPC 虚线隔开 Client / Server 跨进程调用系统服务
Libraries Server AudioFlingerAudioPolicyService、Mixer/Resampler、MediaPlayerService 混音、策略、播放器服务
HAL audio.primary.*.soaudio_policy.*.so 统一接口对接厂商实现
TinyALSA / alsa-lib 用户态访问 PCM/CONTROL 简化 ALSA 调用
Kernel ALSA / ASoC、DAI、Codec、DAPM 驱动与功耗路径
Hardware Speaker / Mic / Headset… 真实器件

记两个中枢:

  • AudioFlinger:真正混音、开输出、碰硬件(经 HAL)
  • AudioPolicyService:设备连接状态、路由策略(定主意;真正 openOutput 仍多在 Flinger 侧执行)

二、AndroidRuntime:框架侧起点与 JNI 注册

系统 Framework 启动路径里,一个重要入口是:

frameworks/base/core/jni/AndroidRuntime.cpp

它更像 系统主线程 / Runtime 侧总装点 之一:注册大量模块的 JNI(native、sensor、media、audioflinger、display、camera、binder…)。
与音频相关的是:在 media 服务完全起来之前,就会把 AudioRecord / AudioSystem / AudioTrack 等 JNI 挂好,让 Java API 能落到 native。

同时源码里大量使用:

sp<IServiceManager> sm(defaultServiceManager());

通过 ServiceManager 添加 / 查找 系统服务。App 侧则通过 Context.getSystemService(...)(底层仍是 Binder + SM)拿到 audio 等服务——理解「安卓一切皆服务」时,从这条线最直观。


三、两大音频服务:Flinger 与 Policy

服务 职责(口语) 要点
AudioFlinger 音频「工厂车间」 经 HAL/AudioHardwareInterface 与底层交互;PCM 混音、输入输出、音量等
AudioPolicyService 音频「调度台」 设备插拔状态、选哪条路由(本机 Codec / A2DP / Headset / HDMI…);策略在这,切换执行多在 Flinger

二者都是 Framework 本地服务,由 audioserver 进程拉起(现代 Android 已把音频从早期 mediaserver 里拆出,见下一节)。

口诀:

Policy 决定「该走哪」
Flinger 负责「真的走」

四、mediaserveraudioserver

都由 init 拉起,但 职责与优先级不同

4.1 mediaserver(偏「媒体播放器」)

mediaserver.rc 里多为 class main,例如启动:

  • MediaPlayerService
  • ResourceManagerService

main_mediaserver.cpp 典型流程:拿到 ProcessState / ServiceManagerMediaPlayerService::instantiate() → 线程池 join

4.2 audioserver(偏「音频中枢」,往往更早)

audioserver.rc 常见为 class core,比一般 main 更早进入就绪;zygote 重启时也会 onrestart restart audioserver

main_audioserver.cpp 核心两句:

AudioFlinger::instantiate();
AudioPolicyService::instantiate();

rc 里还能看到:audioserver 挂掉时会 重启 vendor audio HALvendor.audio-hal 等),保证音频服务与 HAL 生命周期绑在一起。

对比 mediaserver audioserver
典型 class main core(更早)
核心实例 MediaPlayerService… AudioFlinger + AudioPolicyService
和 HAL 间接 直接依赖,挂了会拉 HAL

排查「开机无声 / 音频服务反复起」时:先看 audioservervendor.audio-hal 是否成对崩溃。


五、AudioFlinger:如何挂进 ServiceManager

AudioFlinger 继承大致是:

AudioFlinger
  : BinderService<AudioFlinger>
  , BnAudioFlinger

BinderService<T>::instantiate()publish() →:

sm->addService(String16(SERVICE::getServiceName()), new SERVICE(), ...);

于是系统里出现可被 Binder 查到的 audio flinger 服务
智能指针首次引用会走到 onFirstRef():读 standby 时间属性、设 AUDIO_MODE_NORMAL、挂 HAL factory 回调等——对象真正「可用」。

构造阶段还会创建:

  • DevicesFactoryHalInterface / EffectsFactoryHalInterface(对接 HAL / 音效)
  • PatchPanel(和 AudioPatch 强相关)
  • 主音量、mute、metrics 等状态

承上启下可以记成:

上层 Track / Record / Policy
        ↕ Binder
    AudioFlinger
        ↕ HAL
   primary / a2dp / usb …
        ↕ TinyALSA
      Kernel ALSA

音量路径细节见 Android 音量设置流程


六、AudioPatch:逻辑「线」,接源和宿

TV 上切 HDMI-IN、DTV、线路输入,几乎都会碰到 Audio Patch:不是「再开一个普通 App Track」那么简单,而是 Framework / Policy 声明:

把某些 source port 连到某些 sink port

6.1 数据结构(框架认识)

system/media/audio/include/system/audio.h 里:

struct audio_patch {
    audio_patch_handle_t id;
    unsigned int num_sources;
    struct audio_port_config sources[AUDIO_PATCH_PORTS_MAX];
    unsigned int num_sinks;
    struct audio_port_config sinks[AUDIO_PATCH_PORTS_MAX];
};

audio_port_config 描述某一端的配置:采样率、声道、格式、增益,以及 device / mix / session 扩展。

设备侧扩展里关键字段:

struct audio_port_device_ext {
    audio_module_handle_t hw_module;
    audio_devices_t type;   // 如 SPEAKER、HDMI、… 
    char address[...];
};

这就是 Framework 与底层 HAL 设备 的衔接点之一:策略层选 type,HAL 打开对应通路。

6.2 谁创建、谁真正连线?

角色 常见动作
AudioPolicy / App API 决定要建哪条 patch(哪些源、哪些宿)
AudioFlinger(PatchPanel) 协调、下发
audio HAL create_audio_patch / release_audio_patch 等,落到厂商实现

TV HDMI-IN 的线程与缓冲细节,见 TV 切到 HDMI-IN:Audio Patch 流程

口诀:

port = 逻辑插头(设备或 mix)
patch = 若干插头之间的连线
HAL  = 把连线落到真实硬件路径

七、再往下:HAL → TinyALSA → Kernel

图的下半部分在适配时同样关键:

含义
audio_hw_device / stream_out / stream_in HAL 设备与流
audio_policy_device 策略 HAL(与 Framework Policy 配合)
TinyALSA / alsa-lib 用户态读写 PCM、改 control
ALSA Core(PCM / CONTROL) 内核音频核心
ASoC(Machine / Platform / Codec、I2S、DAPM) SoC 上 CPU DAI ↔ Codec DAI、动态功耗

厂商 audio.primary.xxx.so 往往在这里和 MS12、HDMI、eARC、功放 纠缠——上层策略对了、HAL/驱动错了,一样无声或爆音。


八、对照排查时怎么用这张图?

现象 优先看哪一层
App 能播系统铃、某 App 不行 App / AudioTrack 用法、usage、focus
所有声音都没有 audioserver、HAL 是否起来
设备插了但路由不对 AudioPolicy(策略)
路由对了仍无声 / 爆音 AudioFlinger 输出、HAL、ALSA
TV 切 HDMI / 直播 AudioPatch + 厂商 patch 线程
单核打满、卡顿 Flinger/MS12 线程与 CPU(见性能相关文)

九、小结

  1. 分层:App → Java Framework → Binder → Flinger/Policy → HAL → ALSA → 硬件。
  2. 两大服务:Policy 定路由,Flinger 做混音与开流。
  3. 进程:现代系统音频核心在 audioserver(常 class core)mediaserver 更偏播放器服务。
  4. Patch:用 audio_port / audio_patch 描述逻辑连线,是 TV 外输入的关键抽象。
  5. Runtime:JNI 与 ServiceManager 是「服务能被 App 找到」的前提。

先把这张图装进脑子,再看音量、HDMI-IN、ARC、MS12 单点文章,就不容易在层与层之间迷路。


相关阅读

评论

还没有评论,来做第一个吧

读完了不评论,作者会以为你在沉思