3. HAL基本概念与演进

Android HAL(Hardware Abstraction Layer,硬件抽象层)是连接 Android Framework 与底层 Linux 内核驱动之间的关键桥梁。它的核心使命是:把“硬件相关”的实现细节封装在标准接口之后,让上层框架无需关心具体芯片、外设或驱动实现,从而在保证硬件差异化的同时,维持 Android 系统框架的稳定与可升级性。理解 HAL 的演进,是理解 Android 兼容性、VTS 验证以及 Treble 项目设计动机的基础。

一、核心原理:HAL 到底抽象了什么

在 Android 架构中,应用通过 Binder 调用系统服务,系统服务再通过 HAL 接口访问硬件。HAL 模块通常以共享库或独立进程的形式存在,向上暴露稳定的接口,向下调用内核驱动或直接操作设备节点。传统 HAL 使用 hw_module_t 与 hw_device_t 结构体,通过 hw_get_module() 动态加载 .so 库,接口以 C 语言函数指针表的形式定义。

这种设计在早期 Android 中足够简单,但存在明显问题:HAL 与 Framework 编译在一起、运行在同一进程,接口版本难以独立升级,硬件厂商修改 HAL 往往需要同步修改 Framework,导致 Android 版本升级困难。这正是 Treble 项目要解决的核心矛盾。

关键结论:HAL 的演进不是单纯的技术替换,而是围绕“接口稳定性、进程隔离、版本管理、独立升级”四个目标逐步推进的。

二、演进路线:传统 HAL → HIDL → AIDL

Android 8.0 引入 Treble 项目,将 HAL 从 Framework 进程中剥离,定义 HIDL(HAL Interface Definition Language)作为标准接口描述语言。HIDL 支持 Binder 化通信,HAL 可以运行在独立进程,Framework 与 HAL 之间通过 /dev/hwbinder 或 /dev/binder 通信。HIDL 接口使用 .hal 文件定义,支持版本化,例如 android.hardware.light@2.0::ILight。

Android 11 开始,AIDL 被引入用于 HAL 开发。AIDL 原本用于应用层 Binder 通信,具有更成熟的工具链、更简洁的语法和更广泛的社区支持。Android 13 之后,AIDL HAL 成为推荐方向,Google 要求新 HAL 优先使用 AIDL。AIDL HAL 使用 .aidl 文件定义接口,支持稳定版本标记 @VintfStability,并通过 VINTF(Vendor Interface)机制进行兼容性校验。

Android HAL 演进:传统 HAL → HIDL → AIDL 接口定义、进程模型、版本管理与适用场景对比 Android 7 及以前 Android 8.0 ~ 10 Android 11 至今 传统 HAL 接口定义 hw_module_t / hw_device_t C 函数指针表 进程模型 与 Framework 同进程 直接加载 .so 库 版本管理 无独立版本机制 随系统镜像整体升级 适用场景 早期设备、简单外设 已逐步淘汰 痛点:升级困难、耦合严重 HIDL 接口定义 .hal 文件 + 版本号 如 ILight@2.0 进程模型 独立 HAL 进程 hwbinder / binder 通信 版本管理 主版本 + 次版本 VINTF 兼容性校验 适用场景 Android 8~10 主流 HAL Camera、Audio、Sensor 等 优势:进程隔离、独立升级 AIDL HAL 接口定义 .aidl 文件 + @VintfStability 稳定版本标记 进程模型 独立 HAL 进程 标准 Binder 通信 版本管理 接口版本 + 稳定 ABI VINTF + frozen 接口 适用场景 Android 11+ 新 HAL Google 推荐方向 优势:工具链成熟、统一 Binder 演进驱动力:Treble 项目 → 接口稳定性 → 进程隔离 → 独立升级 → VTS 可验证性

三、版本差异与适用场景对比

三种 HAL 形态并非简单替代关系,而是在不同 Android 版本和不同硬件模块中并存。下表从接口定义、通信机制、版本管理、验证方式等维度进行对比:

对比维度 传统 HAL HIDL AIDL HAL
接口描述 hw_module_t / C 结构体 .hal 文件 .aidl 文件
通信方式 直接函数调用 hwbinder / binder 标准 Binder
进程隔离 否,同进程 是,独立进程 是,独立进程
版本管理 无 主版本.次版本 接口版本 + frozen
VTS 验证 有限 支持 原生支持
推荐版本 Android 7 及以前 Android 8~10 Android 11+

四、案例与场景:一个 Light HAL 的演进

以控制屏幕背光的 Light HAL 为例。传统 HAL 中,Framework 直接加载 lights.default.so,调用 set_light() 函数指针。HIDL 版本中,接口定义为 android.hardware.light@2.0::ILight,HAL 运行在独立进程,Framework 通过 hwbinder 调用 setLightState()。AIDL 版本中,接口定义为 android.hardware.light.ILights,使用 @VintfStability 标记,通过标准 Binder 通信,并纳入 VINTF 清单校验。

// AIDL Light HAL 接口片段(示意)
@VintfStability
interface ILights {
    void setLightState(in LightState state);
    LightState getLightState();
}

parcelable LightState {
    int color;
    int flashMode;
    int flashOnMs;
    int flashOffMs;
    int brightnessMode;
}

这个案例说明:接口定义语言的变化,直接影响了 HAL 的编译方式、部署形态、通信路径和验证手段。VTS 测试需要针对不同 HAL 类型编写对应的测试用例,HIDL 使用 VtsHalLightV2_0TargetTest,AIDL 则使用 VtsHalLightTargetTest。

五、常见误区与复盘

误区一:认为 AIDL HAL 只是 HIDL 的语法替换。实际上,AIDL HAL 引入了稳定 ABI、frozen 接口和更严格的 VINTF 校验,兼容性要求更高。

误区二:认为所有 HAL 都必须迁移到 AIDL。Google 允许 HIDL 与 AIDL 长期共存,已有 HIDL HAL 可继续维护,但新 HAL 应优先选择 AIDL。

误区三:忽略 VINTF 清单的作用。无论 HIDL 还是 AIDL,HAL 都必须在 manifest.xml 中声明,否则 Framework 无法发现该 HAL,VTS 也会失败。

复盘要点:理解 HAL 演进,关键抓住三条线——接口定义语言(C 结构体 → .hal → .aidl)、通信机制(直接调用 → hwbinder → Binder)、版本管理(无 → 主次版本 → 稳定 ABI + frozen)。这三条线共同决定了 HAL 的可升级性、可验证性和厂商适配成本。