3. HAL接口定义语言(HIDL & AIDL)
在Android系统中,HAL(硬件抽象层)是连接Android框架与底层硬件驱动的关键桥梁。为了定义这个桥梁的通信契约,Google引入了两种接口定义语言:HIDL(HAL Interface Definition Language)和AIDL(Android Interface Definition Language)。本章将深入剖析两者的区别,并详细讲解Camera HAL中HIDL接口的定义规范与版本管理策略。
3.1 HIDL与AIDL的核心区别
HIDL专为Android 8.0(Treble项目)设计,旨在将HAL实现与框架进程解耦,实现稳定的二进制接口。AIDL则历史悠久,主要用于Android应用层与系统服务之间的进程间通信(IPC)。在Android 11及之后版本中,AIDL被扩展以支持HAL开发,逐步统一接口定义生态。
| 对比维度 | HIDL | AIDL(用于HAL) |
|---|---|---|
| 引入版本 | Android 8.0 (Treble) | Android 11 (扩展支持HAL) |
| 设计目标 | 框架与HAL严格解耦,支持独立OTA | 统一框架与HAL的IPC接口 |
| 后端支持 | 仅支持Binderized模式(Passthrough已废弃) | 支持NDK、Java、CPP后端 |
| 接口稳定性 | 通过@1.0、@2.0等版本号强制管理 | 通过@VendorExtension注解或版本化包管理 |
| 数据类型 | HIDL原生类型(如vec<T>、fmq_sync) | Parcelable类型,支持泛型 |
| 代码生成 | hidl-gen生成C++/Java桩代码 | aidl-gen生成NDK/Java桩代码 |
| 未来趋势 | 逐步被AIDL取代,新项目推荐AIDL | 官方推荐,统一接口定义生态 |
3.2 Camera HAL的HIDL接口定义
Camera HAL的HIDL接口定义在 android.hardware.camera 包下,包含多个子包,如 device、provider、common 等。每个子包对应一个HIDL接口文件,定义了Camera设备、提供者、回调等核心交互逻辑。
3.2.1 核心接口文件结构
- ICameraDevice.hal:定义Camera设备的主要操作,如
open()、close()、configureStreams()、processCaptureRequest()。 - ICameraProvider.hal:定义Camera提供者服务,负责枚举和打开Camera设备。
- ICameraDeviceCallback.hal:定义从HAL到框架的回调接口,如
notify()、processCaptureResult()。 - types.hal:定义共享的数据类型,如
CameraMetadata、Stream、CaptureRequest。
.hal 后缀,通过 package 关键字声明包名,通过 interface 关键字定义接口。所有方法必须显式声明返回值类型和参数。
// 示例:ICameraDevice.hal 片段
package android.hardware.camera.device@3.4;
interface ICameraDevice {
/**
* 打开Camera设备,返回设备状态。
* @param callback 框架侧的回调接口
* @return Status 操作状态(OK, INTERNAL_ERROR, ...)
*/
open(ICameraDeviceCallback callback) generates (Status status);
/**
* 配置输出流。
* @param streams 待配置的流列表
* @param config 配置参数
* @return Status 配置结果
*/
configureStreams(vec<Stream> streams, StreamConfigurationMode config)
generates (Status status, vec<HalStream> halStreams);
/**
* 提交捕获请求。
* @param requests 捕获请求列表
* @return Status 提交结果
*/
processCaptureRequest(vec<CaptureRequest> requests)
generates (Status status, uint32_t numRequestProcessed);
};
3.2.2 接口版本化与演进
Camera HAL的HIDL接口采用语义化版本号管理,格式为 @major.minor。主版本号(major)表示不兼容的接口变更,次版本号(minor)表示向后兼容的扩展。
| 版本号 | Android版本 | 主要变更 |
|---|---|---|
| @3.0 | Android 8.0 | 初始Treble化Camera HAL,支持基本拍照和预览 |
| @3.2 | Android 8.1 | 添加YUV流支持、深度流支持 |
| @3.3 | Android 9 | 添加逻辑多摄像头支持、会话参数 |
| @3.4 | Android 10 | 添加物理摄像头ID、超广角/长焦切换支持 |
| @3.5 | Android 11 | 添加实时HDR、多帧处理优化 |
| @3.6 | Android 12 | 添加摄像头隐私开关、系统级摄像头禁用 |
| @3.7 | Android 13 | 添加超低延迟预览、多摄像头同步增强 |
| @3.8 | Android 14 | 添加Ultra HDR、摄像头微调控制 |
@3.4 时,框架会认为它同时支持 @3.0 到 @3.4 的所有接口。如果HAL实现未正确实现低版本接口,可能导致框架调用失败。务必使用 defaultPassthroughServiceImplementation 或显式版本检查。
3.3 接口版本管理最佳实践
在Camera HAL开发中,接口版本管理直接影响系统的稳定性和可维护性。以下是最佳实践总结:
- 始终声明支持的版本范围:在
manifest.xml中明确声明HAL实现支持的版本号,避免框架误判。 - 使用
getInterfaceVersion()方法:HIDL自动生成此方法,框架可通过它查询HAL的实际版本。 - 向后兼容性测试:每次升级次版本号后,必须验证所有低版本接口仍能正常工作。
- 避免主版本号变更:主版本号变更意味着所有HAL实现必须同步更新,成本极高。尽量通过次版本号扩展功能。
- 使用
@VendorExtension注解(AIDL):在AIDL中,通过注解标记厂商扩展接口,避免与标准接口冲突。
types.hal 中定义版本号常量,并在接口方法中显式传递版本信息。例如,在 open() 方法中返回HAL版本号,供框架校验。
// 示例:在 types.hal 中定义版本常量
package android.hardware.camera.common@3.4;
enum CameraInterfaceVersion : uint32_t {
CAMERA_DEVICE_API_VERSION_3_4 = 0x304,
CAMERA_DEVICE_API_VERSION_3_5 = 0x305,
CAMERA_DEVICE_API_VERSION_3_6 = 0x306,
};
// 在 ICameraDevice.hal 中使用
interface ICameraDevice {
open(ICameraDeviceCallback callback) generates (Status status, CameraInterfaceVersion version);
};
3.4 从HIDL到AIDL的迁移路径
随着Android生态的演进,Google推荐新项目使用AIDL定义HAL接口。迁移路径通常分为三步:
| 步骤 | 操作 | 关键注意事项 |
|---|---|---|
| 1 | 将 .hal 文件转换为 .aidl 文件 |
数据类型映射:vec<T> → List<T>,fmq_sync → MemoryFile |
| 2 | 更新 Android.bp 构建配置 |
将 hidl_interface 替换为 aidl_interface,指定后端为 ndk |
| 3 | 修改HAL实现代码 | 将 BnHwCameraDevice 替换为 BnCameraDevice(NDK后端) |
3.5 总结
HIDL与AIDL是Android HAL接口定义的两大核心语言。HIDL作为Treble项目的基石,为Camera HAL提供了稳定的版本化接口;AIDL则代表了未来统一接口定义的趋势。掌握两者的区别、接口定义规范以及版本管理策略,是成为一名合格的Camera HAL工程师的必备技能。在实际开发中,建议根据项目阶段和Android版本选择合适的接口语言,并严格遵循版本兼容性规则,确保系统的长期稳定。