4. Audio HAL演进

Android Audio HAL 是音频框架与底层驱动之间的关键适配层。它向上承接 AudioFlinger、AudioPolicyService 的调用,向下封装 ALSA、tinyalsa、DSP 或厂商私有音频通路。随着 Android 版本演进,Audio HAL 的接口形态经历了三次重要变化:legacy HAL(C 结构体直调)、HIDL HAL(Android 8.0 引入)、AIDL HAL(Android 13 起逐步成为主流)。理解这三代接口的差异,是音频适配、系统升级和项目迁移的基础。

一、三代 Audio HAL 的核心差异

legacy HAL 以 hw_module_t 和 audio_hw_device_t 为核心,通过函数指针直接调用,运行在同一个进程空间内,接口简单但缺乏版本管理和进程隔离。HIDL HAL 将音频服务拆分为独立进程,通过 Binder 化机制通信,支持 android.hardware.audio@2.0 到 7.0 等多个版本,并引入 IDevice、IStreamIn、IStreamOut 等接口。AIDL HAL 则使用 Android Interface Definition Language,接口更稳定、类型更安全,典型包名为 android.hardware.audio.core、android.hardware.audio.effect,并支持更灵活的版本扩展和 VINTF 声明。

对比维度 legacy HAL HIDL HAL AIDL HAL
引入版本 Android 早期至 7.x Android 8.0 起 Android 13 起重点推进
接口形式 C 结构体 + 函数指针 HIDL 接口 + Binder 化 AIDL 接口 + Binder
进程模型 通常与 framework 同进程 独立 vendor 进程 独立 vendor 进程
版本管理 弱,靠宏和私有扩展 强,按 major.minor 管理 强,支持稳定 AIDL 版本
典型包名 audio_hw_device_t android.hardware.audio@7.0 android.hardware.audio.core
适用场景 老平台维护、低版本升级 Android 8~12 主流方案 Android 13+ 新项目与长期维护

二、演进关系与调用路径

从系统架构看,三代 HAL 并不是简单替换,而是调用路径和进程边界发生了变化。legacy HAL 中,AudioFlinger 直接加载 audio.primary.default 等模块并调用函数指针;HIDL/AIDL 中,framework 通过 Binder 调用 vendor 进程中的音频服务,HAL 实现被封装在 android.hardware.audio.service 等 service 中。下面的 SVG 展示了三代 Audio HAL 的调用路径、进程边界和典型接口对象。

Audio HAL 三代演进:调用路径与进程边界 Framework 进程 AudioFlinger AudioPolicyService AudioSystem legacy HAL hw_module_t audio_hw_device_t audio_stream_out/in 函数指针直调 同进程 / 无 Binder HIDL HAL IDevice (audio@7.0) IStreamIn / IStreamOut IDevicesFactory Binder 化调用 独立 vendor 进程 AIDL HAL audio.core.IModule audio.core.IStreamOut audio.effect.IFactory 稳定 AIDL + VINTF 独立 vendor 进程 直接加载 Binder 调用 Binder 调用

三、适用场景与迁移策略

选择哪一代 Audio HAL,取决于芯片平台、Android 版本、维护周期和团队能力。对于仍停留在 Android 7.x 或更早版本的老平台,legacy HAL 仍是唯一选择,但应避免在新项目中继续使用。Android 8.0 到 Android 12 的项目,HIDL HAL 是主流方案,尤其是 android.hardware.audio@5.0、@6.0、@7.0 等版本,已经覆盖了大部分手机、平板和车机场景。Android 13 及以后,Google 要求新设备优先使用 AIDL Audio HAL,尤其是 android.hardware.audio.core 和 android.hardware.audio.effect,并通过 VINTF 声明接口版本。

迁移时建议采用“先并存、再替换、后清理”的策略。第一步,保留原有 legacy 或 HIDL 实现,新增 AIDL service,通过 audio_policy_configuration.xml 和 VINTF manifest 让 framework 能同时发现新旧接口。第二步,将 audio.primary、audio.usb、audio.bluetooth 等模块逐步切换到 AIDL 实现,并验证 dumpsys media.audio_flinger、dumpsys media.audio_policy 中的设备加载状态。第三步,确认稳定后移除旧 HAL 和冗余配置,避免 VINTF 冲突。

迁移检查清单:

  • 确认目标 Android 版本对 Audio HAL 的最低要求,Android 13+ 优先 AIDL。
  • 检查 manifest.xml 中是否声明了正确的 android.hardware.audio.core 版本。
  • 确认 audio_policy_configuration.xml 中的 module name 与 HAL service 名称一致。
  • 验证 audio.primary.default、audio.usb.default 等 service 是否正常启动。
  • 使用 lshal 或 dumpsys 检查接口注册状态和版本匹配情况。

四、常见误区与复盘

第一个误区是“HIDL 和 AIDL 只是接口语法不同”。实际上,AIDL Audio HAL 在类型系统、版本稳定性、VINTF 集成和进程模型上都有明显变化,尤其是 IModule 与 IDevice 的职责划分不同,不能简单做语法替换。第二个误区是“迁移时可以直接删除旧 HAL”。在 Android 升级过程中,framework 可能仍会回退到旧接口,直接删除会导致音频服务启动失败。第三个误区是忽略 audio_policy_configuration.xml 与 HAL service 的对应关系,导致设备节点无法被 AudioPolicy 正确识别。

复盘时建议重点关注三个信号:lshal 中是否能看到目标 AIDL 接口、dumpsys media.audio_flinger 中是否加载了正确的 HAL 模块、logcat 中是否存在 Failed to open 或 interface not found 等错误。只有接口注册、策略配置和实际音频通路三者一致,迁移才算真正完成。

# 查看当前 Audio HAL 接口注册情况
lshal | grep audio

# 查看 AudioFlinger 加载的 HAL 模块
dumpsys media.audio_flinger | grep -i "hal\|module"

# 查看 AudioPolicy 设备配置
dumpsys media.audio_policy | grep -i "device\|module"

# 典型 AIDL 服务名
android.hardware.audio.core.IModule/default
android.hardware.audio.effect.IFactory/default

总结:legacy HAL 适合老平台维护,HIDL HAL 覆盖 Android 8~12 的主流设备,AIDL HAL 是 Android 13+ 的新方向。迁移时不要只改接口定义,而要同步处理 VINTF 声明、audio_policy_configuration.xml、service 启动和音频通路验证。理解三代 HAL 的进程边界与调用路径,才能在实际项目中做出正确的适配决策。