1. HAL 接口定义演进概述:从 Android 早期 HAL 到 Treble 架构的演进历程与设计哲学

1.1 背景:为什么需要 HAL?

Android 操作系统运行在数以万计的不同硬件平台上。从 SoC(骁龙、Exynos、Tensor)到外设(Camera、GPS、NFC),每个硬件厂商都有自己独特的实现方式。如果没有一个标准化的抽象层,Google 每发布一次 Android 大版本升级,芯片厂商和 OEM 都需要重写大量内核驱动和用户空间代码,导致碎片化严重、升级周期漫长。

HAL(Hardware Abstraction Layer) 正是为了解决这一问题而诞生。它位于 Android 框架(Framework)与 Linux 内核驱动之间,为上层提供统一的接口,屏蔽底层硬件的差异。

核心设计目标: 一次编写 HAL 实现,多版本 Android 框架兼容;厂商只需关注 HAL 接口适配,无需修改上层框架。
Android 系统分层与 HAL 位置 应用框架层 (Application Framework) Android 框架 (Java API / Native Service) 硬件抽象层 (HAL) Camera HAL / Audio HAL / Sensors HAL / GPS HAL ... Linux 内核驱动 (Kernel Driver) HAL 是框架与内核之间的“契约”,厂商实现 HAL 接口即可让 Android 系统识别并控制硬件

1.2 早期 HAL 架构(Android 1.0 ~ 7.x):模块化与动态加载

在 Android 早期版本中,HAL 以 共享库(.so) 的形式存在。每个硬件模块(如 camera、audio、gps)对应一个动态链接库,由 Android 的 hw_get_module() 函数在运行时加载。

关键特征

  • 模块化定义: 每个 HAL 模块通过 hw_module_t 和 hw_device_t 结构体暴露接口。
  • 动态加载: 框架通过模块 ID(如 CAMERA_HARDWARE_MODULE_ID)查找并加载对应的 .so 文件。
  • 厂商绑定: HAL 库与框架运行在同一个进程(mediaserver 或 cameraserver)中,直接函数调用,性能高但耦合紧密。
早期 HAL 的痛点: 由于 HAL 库与框架进程紧耦合,一旦 HAL 库出现内存泄漏或崩溃,会导致整个系统服务(如 camera service)挂掉。此外,每次 Android 版本升级,HAL 接口可能发生变化,厂商必须重新编译并发布新的 HAL 库。
早期 HAL 架构(Android 1.0 ~ 7.x) Framework 进程 (mediaserver / cameraserver) 直接函数调用 camera.xxx.so audio.xxx.so sensors.xxx.so gps.xxx.so Linux 内核驱动 特点:HAL 库与 Framework 同进程,性能高;但耦合紧,升级困难,稳定性风险大

1.3 Treble 架构的诞生(Android 8.0+):接口与实现分离

为了解决早期 HAL 的紧耦合问题,Google 在 Android 8.0 中推出了 Project Treble。这是 Android 系统架构史上最大的一次重构。其核心思想是:将 HAL 接口定义与厂商实现彻底分离,并通过稳定的 IPC 机制进行通信。

Treble 带来的关键变化

维度 早期 HAL Treble HAL(HIDL)
接口定义语言 C 结构体 + 头文件 HIDL(HAL Interface Definition Language)
通信方式 同进程直接函数调用 Binderized(跨进程 RPC)或 Passthrough(同进程直通)
框架与 HAL 耦合 紧耦合,同进程 松耦合,跨进程隔离
版本升级影响 HAL 接口变更需厂商重新编译 HIDL 接口稳定,厂商实现可独立更新
稳定性 HAL 崩溃导致系统服务挂掉 HAL 运行在独立进程,崩溃不影响框架
注意: Treble 架构并非完全抛弃了早期 HAL 的模块化思想,而是将接口定义提升为一种正式的、版本化的契约(HIDL .hal 文件)。厂商必须实现 HIDL 接口,而框架则通过 HIDL 服务发现机制与 HAL 通信。
Treble 架构(Android 8.0+) Framework 进程 (System Server / Camera Service) HIDL 接口契约 (.hal 文件) IPC / Binder HAL 实现进程 (vendor) (camera HAL daemon / audio HAL daemon) HIDL 服务注册 & 调用 Linux 内核驱动 核心变化:HAL 接口定义(HIDL)与厂商实现分离,跨进程通信,框架与 HAL 解耦

1.4 设计哲学演进:从“模块化”到“契约化”

回顾从早期 HAL 到 Treble 的演进,其背后设计哲学的变化可以归纳为以下几点:

  1. 从“实现共享”到“接口共享”: 早期 HAL 共享的是 .so 二进制库,厂商直接提供代码;Treble 共享的是 .hal 接口定义文件,厂商提供符合接口的服务实现。
  2. 从“进程内信任”到“进程间隔离”: 早期 HAL 假设厂商代码与框架代码运行在同一进程,彼此完全信任;Treble 通过进程边界隔离,即使 HAL 实现崩溃也不会影响框架稳定性。
  3. 从“隐式约定”到“显式版本化”: 早期 HAL 接口变更通过头文件修改和重新编译来同步,版本管理松散;Treble 的 HIDL 接口自带版本号(如 @1.0、@1.1),框架和 HAL 可以独立演进,只要遵守版本兼容规则即可。
  4. 从“厂商锁定”到“生态解耦”: 早期 HAL 使得 Android 系统升级高度依赖厂商提供新 HAL 库;Treble 允许框架单独升级(通过 Project Mainline 等),厂商 HAL 实现可以保持不变,大大加速了系统安全补丁和版本升级的推送速度。
总结: Treble 架构的引入,本质上是将 HAL 从“一组 C 函数指针”演变为“一个正式的、版本化的、跨进程的接口契约”。这一转变不仅提升了系统的稳定性和安全性,也为后续的 Camera HAL3 等复杂 HAL 的兼容性设计奠定了坚实的基础。

1.5 演进路线图

Android 版本 HAL 架构阶段 关键特征
1.0 ~ 4.4 早期 HAL hw_get_module() 动态加载 .so,同进程调用
5.0 ~ 7.x 早期 HAL + 部分 Binder 化 部分服务开始使用 Binder 通信,但 HAL 层仍以 .so 为主
8.0 ~ 9.0 Treble (HIDL) 引入 HIDL,HAL 接口与实现分离,支持 Binderized 和 Passthrough 模式
10.0+ Treble + AIDL HAL 引入 AIDL 作为 HIDL 的替代,统一接口定义语言,进一步简化 HAL 开发