Audio 为何没有完全迁移到 packages/modules
这是一个非常专业且深刻的问题。Audio 系统的模块化确实是 Android 架构演进中的一个特殊案例。
一、Audio 系统的现状
当前分布
-
大部分在
frameworks/av/:frameworks/av/ ├── services/audiopolicy/ # 音频策略服务 ├── media/ # 媒体框架 └── camera/ # 摄像头(共用部分基础设施) -
部分在
hardware/:hardware/interfaces/audio/ └── HIDL/AIDL 接口定义 -
少量在
packages/modules/:packages/modules/Bluetooth/audio/ # 蓝牙音频相关
二、未完全迁移的核心原因
1. 性能和延迟的硬性要求 ⏱️
- 实时性要求:音频处理需要极低延迟(<10ms)
- 硬件直通:许多编解码器需要直接访问硬件
- 中断处理:音频 DMA 需要高效中断响应
- 模块化开销:APEX 包的抽象层会引入额外延迟
对比示例:
| 场景 | 模块化音频延迟 | 当前架构延迟 |
|---|---|---|
| 游戏音频 | 20-30ms | 5-10ms |
| VoIP 通话 | 15-25ms | 8-12ms |
| 媒体播放 | 可接受 | 可接受 |
2. 硬件碎片化严重 🎚️
-
编解码器多样性:高通/联发科/三星各有私有音频 DSP
-
音频 HAL 差异 :
cpp// 不同厂商的 HAL 差异巨大 // 高通:audio.primary.msm8996.so // 三星:audio.primary.exynos.so // 联发科:audio.primary.mtk.so -
定制 DSP 算法:噪声消除、空间音频等厂商定制功能
3. 复杂的依赖关系 🔗
Audio 系统依赖网络:
├── 电源管理 (Power HAL)
├── 设备管理器 (DeviceManager)
├── 传感器 (Sensor HAL) # 用于自动音量调整
├── 相机 (Camera HAL) # 视频录制同步
├── 蓝牙 (Bluetooth) # A2DP/HFP
├── USB (USB HAL) # USB 音频
└── DRM 框架 # 受保护内容播放
4. 系统启动时序要求 🚀
- 早期启动:开机声音、TTS 需要极早可用
- 模块加载顺序:音频需要在 UI 前启动
- 恢复模式:需要在不完整系统中工作
三、部分模块化的尝试
已模块化的部分
| 组件 | 位置 | 状态 | 原因 |
|---|---|---|---|
| 蓝牙音频 | packages/modules/Bluetooth/audio |
已模块化 | 相对独立 |
| AudioFlinger插件 | 部分 HIDL 化 | 部分 | 新功能实验 |
| 空间音频 | 考虑中 | 规划 | 算法独立 |
渐进式演进策略
- Android 10-12:定义稳定的 Audio HAL 接口
- Android 13+:尝试将音频后处理链模块化
- 未来:可能将非实时路径模块化
四、技术挑战详解
挑战 1:实时性保证
cpp
// 当前的直接调用路径
app → AudioFlinger → HAL → Driver
// 延迟:~5ms
// 模块化后的路径
app → AudioService(APEX) → AudioFlinger → HAL → Driver
// 增加延迟:+3-5ms
挑战 2:内存共享
cpp
// 当前:直接内存共享
audio_buffer = malloc_shared(SHARED_BUFFER);
// 模块化:需要进程间复制
audio_buffer = binder_allocate_copy(SHARED_BUFFER);
// 额外开销:内存复制 + 同步延迟
挑战 3:硬件抽象层兼容性
makefile
# 当前:直接链接
LOCAL_SHARED_LIBRARIES := libaudiohal
# 模块化:版本化管理
LOCAL_APEX_LIBRARIES := \
com.android.audio@1.0 \
com.android.audio@2.0
# 问题:旧版 HAL 需要新版模块支持
五、Google 的折中方案
1. 接口标准化而非实现模块化
- 保持 AudioFlinger 在系统镜像中
- 但定义稳定的 HIDL/AIDL 接口
- 允许第三方替代部分功能
2. 选择性模块化
音频系统 模块化决策 实时路径
保持集成 非实时路径
可模块化 播放/录制 低延迟 通话 音频策略 格式转换 效果器管理
3. 增量改进
- Android 12:改进音频 HAL 稳定性
- Android 13:音频设备枚举模块化
- Android 14:蓝牙 LE Audio 完全模块化
六、行业对比
| 系统 | 音频架构 | 更新策略 |
|---|---|---|
| Android | 半模块化 | 大版本更新 + 部分 Mainline |
| Windows | 驱动模型 | Windows Update |
| iOS | 完全集成 | 系统更新 |
| Linux 桌面 | PulseAudio 独立 | 包管理器更新 |
七、实际影响
开发者角度
java
// 好消息:API 保持稳定
AudioManager am = (AudioManager) getSystemService(AUDIO_SERVICE);
am.setStreamVolume(...); // 接口不变
// 坏消息:底层差异仍需处理
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// 新音频功能可能依赖系统版本
}
OEM 厂商角度
- 优势:仍可深度定制音频体验
- 劣势:音频安全更新仍需自行 backport
- 责任:需维护音频 HAL 驱动
用户角度
- ✅ 获得厂商调音特色
- ❌ 安全更新可能延迟
- ⚠️ 音频质量因设备而异
八、未来可能性
可能模块化的部分
- 音频效果器框架(可独立更新算法)
- 音频策略引擎(路由逻辑)
- 格式转换库(非实时编解码)
- MIDI 子系统(专业音频)
技术前提
- 实时 Linux 改进:PREEMPT_RT 更成熟
- 硬件虚拟化:音频 DSP 虚拟化支持
- 新总线标准:更低延迟的模块间通信
九、总结
Audio 没有完全移到 packages/modules 是权衡的结果,而非技术不足:
| 因素 | 重要性 | 模块化障碍 |
|---|---|---|
| 实时性 | 🔴 极高 | 主要障碍 |
| 硬件集成 | 🔴 高 | 碎片化严重 |
| 启动顺序 | 🟡 中 | 可解决 |
| 安全更新 | 🟢 可接受 | 非主要问题 |
根本矛盾 :模块化的解耦优势 vs 音频系统的集成需求
目前 Google 采取的是渐进式、选择性模块化策略,优先模块化那些:
- 非实时路径
- 相对独立的子系统
- 安全敏感组件
- 新硬件支持
这种务实做法确保了 Android 音频在保持性能的同时,逐步获得模块化的部分好处。