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)机制进行兼容性校验。
三、版本差异与适用场景对比
三种 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 的可升级性、可验证性和厂商适配成本。