2. HAL 概念与设计哲学
硬件抽象层(HAL,Hardware Abstraction Layer)是 Android 系统架构中连接 Linux 内核与 Android 框架的关键中间层。本章将深入剖析 HAL 的核心定义、设计动机及其演进历史,帮助读者建立对 HAL 架构的全局认知。
2.1 HAL 的定义
HAL 是一个位于 Android 系统服务(System Server)与 Linux 内核驱动之间的接口层。它将硬件设备的具体操作封装成标准化的函数接口,使得上层应用框架无需关心底层硬件的实现细节。
hw_module_t 和 hw_device_t 结构体进行抽象。
HAL 模块通常以共享库(.so)的形式存在,由 Android 系统在运行时动态加载。每个 HAL 模块必须实现以下两个核心结构体:
| 结构体 | 作用 | 关键字段 |
|---|---|---|
hw_module_t |
描述 HAL 模块的元信息(版本、作者、ID) | tag, module_api_version, hal_api_version, id, name, methods |
hw_device_t |
描述具体硬件设备的操作接口 | tag, version, module, close |
2.2 为什么需要 HAL
Android 引入 HAL 并非偶然,而是由三大核心驱动力共同作用的结果:硬件抽象、厂商兼容性和GPL 规避。
2.2.1 硬件抽象
Android 需要运行在数以万计的不同硬件平台上。如果没有 HAL,每个硬件厂商都必须为 Android 框架定制驱动接口,导致系统碎片化严重。HAL 通过定义统一接口,将硬件差异隔离在 HAL 层之下。
2.2.2 厂商兼容性
硬件厂商(如 Qualcomm、MTK、Samsung)需要在不公开核心 IP 的前提下,让硬件正常工作。HAL 提供了二进制兼容的接口标准,厂商只需编译出符合 HAL 规范的 .so 文件,即可被 Android 系统加载。
| 场景 | 无 HAL | 有 HAL |
|---|---|---|
| 更换 WiFi 芯片 | 需修改 Android 框架代码 | 仅替换 WiFi HAL 模块 |
| 升级内核版本 | 驱动接口可能不兼容 | HAL 接口保持稳定 |
| 多厂商适配 | 每个厂商一套框架 | 统一框架 + 厂商 HAL |
2.2.3 GPL 规避
Linux 内核采用 GPLv2 许可证,要求基于内核的衍生作品也必须开源。Android 框架采用 Apache 2.0 许可证,两者存在冲突。HAL 作为用户空间(Userspace)的库,运行在内核之上,不受 GPL 传染。厂商可以将 HAL 实现作为闭源二进制发布,从而保护硬件 IP。
2.3 HAL 的发展历史
HAL 架构经历了从 libhardware 到 Treble 的重大演进,每一次变革都深刻影响了 Android 的生态格局。
2.3.1 libhardware 时代(Android 1.0 ~ 7.x)
早期的 HAL 实现集中在 hardware/libhardware 目录下,采用 C 语言编写,通过 hw_get_module() 函数动态加载 HAL 模块。这种架构虽然简单直接,但存在严重问题:HAL 与框架进程运行在同一地址空间,HAL 模块的崩溃会直接导致系统服务挂掉。
// libhardware 时代的典型 HAL 加载方式
#include <hardware/hardware.h>
hw_module_t* module = NULL;
int ret = hw_get_module("camera", (const hw_module_t**)&module);
if (ret == 0) {
camera_device_t* device = NULL;
module->methods->open(module, "0", (hw_device_t**)&device);
// 使用 device 操作摄像头
}
2.3.2 Treble 架构(Android 8.0+)
Google 在 Android 8.0 中推出了 Project Treble,这是 HAL 架构史上最重大的变革。Treble 将 HAL 从框架进程中剥离,放入独立的 HAL 守护进程(HAL Server),通过 HIDL(HAL Interface Definition Language)进行跨进程通信。
| 对比维度 | libhardware | Treble (HIDL) |
|---|---|---|
| 通信方式 | 函数直接调用(同进程) | Binder 跨进程调用 |
| 接口定义 | C 头文件 | .hal 文件(HIDL) |
| 进程隔离 | 无 | 强隔离(HAL Server) |
| 升级灵活性 | 需随系统一起升级 | 可独立升级 HAL |
| 稳定性 | 低(HAL 崩溃影响框架) | 高(HAL 崩溃可重启) |
2.3.3 Treble 的核心组件
Treble 架构引入了以下关键组件:
- HIDL:接口定义语言,用于描述 HAL 接口,自动生成 C++ 客户端和服务端代码。
- HAL Server:独立的守护进程,加载并管理 HAL 模块,通过 Binder 接收框架请求。
- VINTF(Vendor Interface):厂商接口清单文件,声明设备支持的 HAL 版本和接口。
- Passthrough 模式:兼容旧版 libhardware 的过渡模式,允许 Treble 框架加载传统 HAL 模块。
2.3.4 从 HIDL 到 AIDL HAL(Android 11+)
Android 11 进一步统一了接口定义语言,将 HIDL 逐步迁移到 AIDL(Android Interface Definition Language)。AIDL HAL 使用与 Android 框架相同的 Binder 通信机制,减少了维护两套 IPC 系统的成本。
// AIDL HAL 接口示例 (IExample.aidl)
package vendor.example.hardware.example;
interface IExample {
int doSomething(int input);
String getHardwareInfo();
}
| 特性 | HIDL HAL | AIDL HAL |
|---|---|---|
| 接口语言 | .hal 文件 | .aidl 文件 |
| IPC 机制 | Binder (HwBinder) | 标准 Binder |
| 稳定性 | 稳定(长期支持) | 稳定(推荐新项目使用) |
| 代码生成 | hidl-gen | aidl 工具 |
| 向后兼容 | 支持 | 通过兼容层支持 HIDL |
截至 Android 14,Google 已明确推荐新开发的 HAL 使用 AIDL 接口,HIDL 将逐步被淘汰。但大量现有设备仍运行在 HIDL HAL 上,因此理解两者对底层开发者而言都至关重要。