2. HIDL 基础概念:接口定义语言、语法、包名与版本管理、函数与数据类型
HIDL(HAL Interface Definition Language)是 Android 系统为 Treble 架构设计的接口定义语言,用于在 Framework 进程与 HAL 实现进程之间建立稳定的二进制契约。理解 HIDL 的核心概念是编写可维护、可调试 Camera HAL 服务的前提。
2.1 HIDL 接口定义语言概述
HIDL 是一种 描述性语言,它不定义业务逻辑,只定义接口的 形状(Shape):包括包名、版本、接口名称、方法签名、数据类型和回调结构。编译器(hidl-gen)根据 .hal 文件生成 C++ 或 Java 的客户端/服务端桩代码。
关键设计原则:HIDL 强制接口与实现分离,所有跨进程通信(IPC)都通过 Binder 或直通(Passthrough)模式进行,确保 HAL 实现可以独立升级而不影响 Framework。
2.2 .hal 文件语法结构
一个标准的 .hal 文件由 包声明、导入声明、接口定义 三部分组成。以下是一个 Camera HAL 中常用的 ICameraDevice.hal 简化示例:
// 包声明:package + 完整路径 + @版本号
package android.hardware.camera.device@3.4;
// 导入其他包中的类型
import android.hardware.camera.common@1.0::Status;
import android.hardware.camera.common@1.0::CameraMetadata;
// 接口定义:interface IMyCameraDevice {
interface ICameraDevice {
// 方法:返回类型 + 方法名 + 参数列表
getCameraCharacteristics()
generates (Status status, CameraMetadata characteristics);
// 方法:带输入参数和回调
configureStreams(vec<Stream> streams)
generates (Status status, int32_t halStreamCount);
// 单向回调(oneway):不阻塞调用方
oneway notify(CameraEvent event);
};
语法要点:
- 包声明 必须与文件系统路径严格对应,例如
android/hardware/camera/device/3.4/ICameraDevice.hal - 版本号 使用
@major.minor格式,@3.4表示 major=3, minor=4 - 方法返回值 使用
generates关键字,而非returns - 单向方法 使用
oneway修饰,不等待服务端处理完成
2.3 包名与版本管理
HIDL 的包名(Package Name)和版本号共同构成接口的唯一标识。版本管理遵循 语义化版本 原则:
| 版本段 | 含义 | 变更规则 | 示例 |
|---|---|---|---|
| Major(主版本) | 不兼容的接口变更 | 删除/修改方法签名、删除类型字段 | @3.0 → @4.0 |
| Minor(次版本) | 向后兼容的扩展 | 新增方法、新增类型、新增字段 | @3.0 → @3.1 |
在 Camera HAL 中,版本演进遵循以下模式:
// 基础版本:定义核心接口
android.hardware.camera.device@3.0
// 次版本扩展:新增特性,不破坏旧接口
android.hardware.camera.device@3.2 // 新增物理相机支持
android.hardware.camera.device@3.4 // 新增会话参数
// 主版本升级:重构接口
android.hardware.camera.device@4.0 // 完全重写流配置流程
版本兼容性陷阱:在 Camera HAL 调试中,常见的问题是 Framework 请求
@3.4 接口,但 HAL 服务只注册了 @3.2,导致服务无法被发现。务必使用 lshal 命令确认注册的版本号与 manifest.xml 中声明的一致。
2.4 函数定义与数据类型
2.4.1 函数定义规则
HIDL 函数定义包含 方法名、输入参数、输出参数 和可选的 调用方式:
// 同步方法:调用方等待服务端返回
getCameraCharacteristics()
generates (Status status, CameraMetadata characteristics);
// 带输入参数的同步方法
configureStreams(vec<Stream> streams)
generates (Status status, int32_t halStreamCount);
// 单向方法:不等待返回,无 generates
oneway notify(CameraEvent event);
// 回调方法:服务端主动调用客户端
interface ICameraDeviceCallback {
onCaptureResult(CaptureResult result);
};
2.4.2 内置数据类型
| 类型分类 | 具体类型 | 说明 | Camera HAL 典型用途 |
|---|---|---|---|
| 整数类型 | int8_t, uint8_t, int32_t, uint32_t, int64_t |
固定宽度整数 | 帧序号、错误码、流 ID |
| 浮点类型 | float, double |
IEEE 754 浮点数 | 曝光时间、增益值、物理尺寸 |
| 布尔类型 | bool |
true / false | 功能开关、状态标志 |
| 字符串类型 | string |
UTF-8 编码 | 设备名称、版本信息 |
| 枚举类型 | enum |
具名整数常量 | 相机状态、错误类型、格式枚举 |
| 结构体 | struct |
复合数据类型 | Stream 配置、CaptureResult |
| 联合体 | union |
共享内存的多种类型 | 元数据值(int/float/string 之一) |
| 向量 | vec<T> |
动态数组 | 流列表、元数据项列表 |
| 安全回调 | hidl_callback |
函数指针封装 | 异步结果通知 |
2.4.3 自定义类型示例
在 Camera HAL 中,Stream 结构体是核心数据类型之一:
struct Stream {
int32_t id; // 流唯一标识
int32_t streamType; // 0: 输出, 1: 输入, 2: 双向
int32_t width; // 图像宽度
int32_t height; // 图像高度
int32_t format; // 像素格式(如 HAL_PIXEL_FORMAT_YCbCr_420_888)
vec<uint8_t> bufferHandle; // 图形缓冲区句柄
int32_t usage; // 缓冲区使用标志(GRALLOC_USAGE_*)
int32_t rotation; // 旋转角度(0/90/180/270)
};
enum StreamType : int32_t {
OUTPUT = 0,
INPUT = 1,
BIDIRECTIONAL = 2
};
调试提示:在 HIDL 服务启动阶段,最常见的类型相关错误是 枚举值不匹配。例如 Framework 发送
StreamType::OUTPUT = 0,但 HAL 实现误判为 INPUT = 1。建议在 HAL 入口处打印所有枚举参数的原始整数值,与 .hal 文件定义逐一比对。
2.5 小结
本章涵盖了 HIDL 的核心基础概念:
- 接口定义语言 作为 Framework 与 HAL 之间的契约,通过
hidl-gen生成跨进程通信桩代码 - .hal 文件语法 包含包声明、导入、接口和方法定义,严格遵循文件系统路径映射
- 包名与版本管理 采用语义化版本,主版本不兼容、次版本向后扩展
- 函数与数据类型 提供丰富的内置类型和自定义结构体,满足 Camera HAL 复杂的参数传递需求