2. HIDL基础回顾:HIDL接口定义语言语法、服务注册与发现机制
在深入AIDL化Camera HAL架构之前,必须牢固掌握HIDL(HAL Interface Definition Language)的核心机制。HIDL是Android 8.0(Treble项目)引入的接口定义语言,用于实现Framework与HAL之间的稳定、可独立更新的通信边界。本章将系统回顾HIDL的语法规范、服务注册与发现流程,为后续与AIDL方案的对比奠定基础。
2.1 HIDL接口定义语言语法
HIDL语法设计目标:严格类型安全、跨进程透明、向后兼容。其核心语法元素包括包名、接口、方法、数据类型与回调。
2.1.1 包名与版本管理
每个HIDL接口必须声明唯一的包名,并附带主版本号和次版本号。版本号用于接口演进时的兼容性检查。
// 包名格式:vendor.hardware.模块名@版本
package android.hardware.camera.provider@3.5;
| 语法元素 | 说明 | 示例 |
|---|---|---|
| 包名 | 反向域名风格,标识接口所属厂商和模块 | android.hardware.camera |
| 主版本 | 不兼容变更时递增 | @3 |
| 次版本 | 向后兼容新增时递增 | .5 |
| 完整声明 | package + 版本号 | package android.hardware.camera.provider@3.5; |
2.1.2 接口定义
HIDL接口使用interface关键字声明,支持单继承。接口内可定义方法、枚举、结构体、联合体等类型。
interface ICameraDevice {
// 方法定义:返回类型 方法名(参数列表) 生成(回调)
getResourceCost() generates (CameraResourceCost cost);
// 单向方法(fire-and-forget)
oneway flush();
// 同步方法(默认)
close() generates (Status status);
};
- generates:用于声明异步回调结果,HIDL中所有返回值都通过generates传递。
- oneway:标记方法为单向调用,不等待返回,适用于通知类操作。
- 方法命名:小驼峰风格,动词开头。
2.1.3 数据类型系统
HIDL定义了完整的数据类型体系,确保跨进程传输时数据布局一致。
| 类别 | 类型 | 说明 |
|---|---|---|
| 基本类型 | int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, uint64_t, float, double |
固定宽度整数和浮点数 |
| 字符串 | string |
UTF-8编码,长度可变 |
| 数组 | T[] |
可变长度数组,如 uint8_t[] |
| 结构体 | struct |
成员按声明顺序内存对齐 |
| 联合体 | union |
共享内存区域,需显式指定判别器 |
| 枚举 | enum |
底层为int32_t,支持位掩码 |
| 句柄 | handle |
跨进程传递的文件描述符或原生句柄 |
| 接口引用 | interface |
指向另一个HIDL接口的Binder引用 |
// 结构体定义示例
struct CameraMetadata {
uint32_t tag;
uint8_t dataType;
int32_t count;
uint8_t[] data;
};
// 枚举定义示例
enum Status : int32_t {
OK = 0,
ERROR_ILLEGAL_ARGUMENT = -1,
ERROR_CAMERA_IN_USE = -2,
ERROR_MAX_CAMERAS_IN_USE = -3,
};
2.1.4 回调与异步通信
HIDL通过回调接口实现异步通知。服务端定义回调接口,客户端实现并注册,服务端在事件发生时调用回调方法。
// 回调接口定义
interface ICameraDeviceCallback {
onResult(CaptureResult result);
onError(ErrorCode error);
};
// 主接口中使用回调
interface ICameraDevice {
open(ICameraDeviceCallback callback) generates (Status status);
};
oneway或默认同步方式。Camera HAL中,onResult通常为同步调用以保证帧顺序,onError可使用oneway避免阻塞。
2.2 HIDL服务注册与发现机制
HIDL服务使用hwservicemanager作为中心注册表,负责服务的注册、发现和生命周期管理。该机制是Treble架构实现Framework与HAL解耦的关键基础设施。
2.2.1 服务注册流程
HAL服务进程在启动后,通过registerAsService将自身实例注册到hwservicemanager。注册信息包括:服务名称、接口描述符、版本号。
// C++ 服务端注册示例
using android::hardware::camera::provider::V3_5::ICameraProvider;
using android::hardware::defaultServiceManager;
sp<ICameraProvider> service = new CameraProvider();
status_t status = service->registerAsService("default");
// 注册成功后,客户端可通过 "default" 名称发现该服务
2.2.2 服务发现流程
客户端(如CameraService)通过hwservicemanager查询指定名称和版本的服务,获取Binder引用后即可跨进程调用。
// C++ 客户端发现服务示例
using android::hardware::camera::provider::V3_5::ICameraProvider;
sp<ICameraProvider> service = ICameraProvider::getService("default");
if (service != nullptr) {
// 成功获取服务引用,开始调用
service->getCameraIdList([](Status status, const hidl_vec<CameraId>& ids) {
// 处理回调
});
} else {
// 服务不可用,处理错误
}
2.2.3 服务生命周期管理
HIDL服务支持延迟注册和热插拔。Camera HAL中,物理摄像头设备可能动态插入或移除,服务注册机制需配合IServiceNotification实现动态感知。
// 注册服务通知,监听服务上线/下线
using android::hidl::manager::V1_0::IServiceNotification;
class ServiceListener : public IServiceNotification {
Return<void> onRegistration(
const hidl_string& fqName,
const hidl_string& name,
bool preexisting) override {
if (fqName == "android.hardware.camera.provider@3.5::ICameraProvider") {
// 服务已注册,可以开始使用
}
}
};
- 版本不匹配:客户端请求的版本与服务端注册的版本必须兼容(主版本相同,次版本≥客户端要求)。
- 服务死锁:在服务注册回调中直接调用getService可能导致死锁,应使用异步通知。
- 权限问题:只有system分区或vendor分区的进程才能注册HIDL服务,普通应用无法注册。
2.3 HIDL与Binder驱动的关系
HIDL通信底层依赖Binder驱动,但与Android Framework的AIDL Binder使用不同的域:
| 特性 | HIDL Binder | AIDL Binder |
|---|---|---|
| Binder域 | /dev/hwbinder | /dev/binder |
| 服务管理器 | hwservicemanager | servicemanager |
| 主要用途 | Framework ↔ HAL 通信 | 应用 ↔ Framework 通信 |
| 接口定义语言 | HIDL (.hal文件) | AIDL (.aidl文件) |
| 传输效率 | 优化大块数据(如Camera帧元数据) | 通用场景 |
hidl_memory或FMQ(快速消息队列)传输,减少Binder拷贝开销。
2.4 HIDL接口的编译与生成
HIDL接口文件(.hal)通过hidl-gen工具编译,生成C++或Java的客户端/服务端代码骨架。
# 编译HIDL接口,生成C++代码
hidl-gen -o output_dir -L c++-impl \
-randroid.hardware:hardware/interfaces \
android.hardware.camera.provider@3.5
# 生成的文件结构
output_dir/
├── CameraProvider.h # 接口头文件
├── CameraProvider.cpp # 接口实现骨架
├── CameraProviderAll.cpp # 所有接口的合并实现
└── types.h # 数据类型定义
- BpCameraProvider:客户端代理类,封装Binder调用。
- BnCameraProvider:服务端基类,处理Binder请求分发。
- ICameraProvider:纯虚接口类,定义所有方法。
- HwBinder:底层传输对象,管理跨进程通信。