HAL接口定义演进与Camera HAL3兼容性设计 - 第4节
4.1 HIDL 接口定义文件 (.hal) 语法与结构
HIDL (HAL Interface Definition Language) 是 Android 8.0 引入的接口定义语言,用于实现 Treble 架构中 Framework 与 HAL 之间的进程间通信。.hal 文件是 HIDL 的核心载体,其语法结构直接决定了生成的 C++/Java 代码质量。
4.1.1 包名与版本管理策略
HIDL 包名采用反向域名风格,版本号使用主版本.次版本格式。包名与版本号共同构成接口的唯一标识,直接影响生成的代码命名空间和目录结构。
| 组件 | 格式 | 示例 | 说明 |
|---|---|---|---|
| 包名前缀 | android.hardware.xxx | android.hardware.camera | 固定前缀,表示硬件抽象层 |
| 模块名 | 小写字母+下划线 | provider | 具体硬件模块名称 |
| 主版本 | 正整数 | 3 | 不兼容变更时递增 |
| 次版本 | 正整数 | 5 | 向后兼容扩展时递增 |
// Camera HAL3 典型包名声明示例
package android.hardware.camera.provider@3.5;
// 完整包名:android.hardware.camera.provider@3.5
// 生成代码目录:android/hardware/camera/provider/3.5/
// C++ namespace:android::hardware::camera::provider::V3_5
// Java package:android.hardware.camera.provider.V3_5
4.1.2 类型定义与接口声明
.hal 文件支持基本类型、结构体、枚举、联合体、函数指针和接口类型。Camera HAL3 中大量使用结构体描述相机元数据、流配置和缓冲区信息。
// Camera HAL3 核心类型定义示例
package android.hardware.camera.device@3.5;
// 枚举类型:相机状态
enum CameraDeviceStatus : int32_t {
PRESENT = 0,
ENUMERATING = 1,
NOT_PRESENT = 2,
};
// 结构体类型:流配置
struct StreamConfiguration {
int32_t width;
int32_t height;
int32_t format;
int32_t rotation;
vec<Stream> streams;
};
// 接口声明:相机设备操作
interface ICameraDevice {
// 打开相机会话
open(ICameraDeviceCallback callback) generates (Status status);
// 配置流
configureStreams(StreamConfiguration config)
generates (Status status, StreamConfiguration outConfig);
// 捕获请求
processCaptureRequest(vec<CaptureRequest> requests,
vec<BufferCache> cachesToRemove)
generates (Status status, uint32_t frameNumber);
};
generates 关键字表示异步回调返回值,使用 returns 表示同步返回值。Camera HAL3 中大部分操作采用异步模式,以匹配相机 pipeline 的实时性要求。
4.2 代码生成流程与工具链
HIDL 编译器 hidl-gen 负责将 .hal 文件转换为 C++ 和 Java 代码。整个代码生成流程涉及接口定义、编译配置、代码生成和集成验证四个阶段。
4.2.1 hidl-gen 编译器使用
hidl-gen 是 Android 源码中的专用工具,支持多种输出模式。Camera HAL3 的接口定义通常使用 -Lc++-impl 和 -Ljava 选项分别生成 C++ 实现骨架和 Java 客户端代码。
# 生成 C++ 接口头文件
hidl-gen -o output/cpp -Lc++-headers \
-randroid.hardware:hardware/interfaces \
android.hardware.camera.device@3.5
# 生成 C++ 实现骨架
hidl-gen -o output/cpp -Lc++-impl \
-randroid.hardware:hardware/interfaces \
android.hardware.camera.device@3.5
# 生成 Java 客户端代码
hidl-gen -o output/java -Ljava \
-randroid.hardware:hardware/interfaces \
android.hardware.camera.device@3.5
-o:指定输出目录-L:指定输出语言和模板类型(c++-headers, c++-impl, java, java-constants 等)-r:指定包名到路径的映射关系,格式为package:path
4.2.2 生成代码目录结构
hidl-gen 严格按照包名和版本号生成目录结构,确保不同版本的接口可以共存。Camera HAL3 的多个版本(3.0~3.8)可以在同一系统中并存,由 Framework 根据设备能力选择加载。
| 生成文件 | 路径示例 | 用途 |
|---|---|---|
| 接口头文件 | android/hardware/camera/device/3.5/ICameraDevice.h | C++ 接口定义,包含纯虚函数 |
| 类型头文件 | android/hardware/camera/device/3.5/types.h | 结构体、枚举等类型定义 |
| Bp 代理类 | android/hardware/camera/device/3.5/BpCameraDevice.h | 客户端代理,封装 IPC 调用 |
| Bn 桩类 | android/hardware/camera/device/3.5/BnCameraDevice.h | 服务端桩类,处理 IPC 请求 |
| Java 接口 | android/hardware/camera/device/V3_5/ICameraDevice.java | Java 层接口定义 |
| Java 代理 | android/hardware/camera/device/V3_5/ICameraDeviceProxy.java | Java 客户端代理 |
4.3 Camera HAL3 接口实战案例
以 Camera HAL3 的 ICameraDevice 接口为例,展示从 .hal 定义到 C++/Java 代码生成的全过程。Camera HAL3 的核心接口包括设备管理、流配置、捕获请求和结果回调。
4.3.1 定义 Camera HAL3 核心接口
// camera/device/3.5/ICameraDevice.hal
package android.hardware.camera.device@3.5;
import android.hardware.camera.common@3.5::Status;
import android.hardware.camera.common@3.5::Stream;
import android.hardware.camera.common@3.5::CaptureRequest;
import android.hardware.camera.common@3.5::CaptureResult;
interface ICameraDevice {
// 打开相机设备
open(ICameraDeviceCallback callback)
generates (Status status);
// 关闭相机设备
close()
generates (Status status);
// 初始化配置
initialize(ICameraDeviceSession session)
generates (Status status);
// 获取相机元数据
getCameraCharacteristics()
generates (Status status, CameraCharacteristics characteristics);
// 设置流配置
configureStreams(StreamConfiguration config)
generates (Status status, StreamConfiguration outConfig);
// 处理捕获请求
processCaptureRequest(vec<CaptureRequest> requests,
vec<BufferCache> cachesToRemove)
generates (Status status, uint32_t frameNumber);
// 刷新待处理请求
flush()
generates (Status status);
};
// 回调接口
interface ICameraDeviceCallback {
// 通知捕获结果
processCaptureResult(vec<CaptureResult> results);
// 通知错误
notify(vec<NotifyMsg> msgs);
};
4.3.2 生成的 C++ 代码结构
hidl-gen 为上述接口生成以下 C++ 代码文件,开发者只需继承 ICameraDevice 并实现纯虚函数。
// 生成的 C++ 接口头文件 (ICameraDevice.h)
namespace android {
namespace hardware {
namespace camera {
namespace device {
namespace V3_5 {
struct StreamConfiguration {
int32_t width;
int32_t height;
int32_t format;
int32_t rotation;
::android::hardware::hidl_vec<Stream> streams;
};
struct CameraCharacteristics {
int32_t deviceVersion;
int32_t supportedHardwareLevel;
// ... 其他元数据字段
};
struct ICameraDevice : public ::android::hardware::IInterface {
using Status = ::android::hardware::camera::common::V3_5::Status;
virtual Status open(
const ::android::sp<ICameraDeviceCallback>& callback) = 0;
virtual Status close() = 0;
virtual Status configureStreams(
const StreamConfiguration& config,
StreamConfiguration* outConfig) = 0;
virtual Status processCaptureRequest(
const ::android::hardware::hidl_vec<CaptureRequest>& requests,
const ::android::hardware::hidl_vec<BufferCache>& cachesToRemove,
uint32_t* frameNumber) = 0;
// ... 其他纯虚函数
};
} // namespace V3_5
} // namespace device
} // namespace camera
} // namespace hardware
} // namespace android
4.3.3 生成的 Java 代码结构
Java 层代码同样遵循包名和版本号规则,Framework 通过 Java 代理类与 HAL 服务通信。
// 生成的 Java 接口 (ICameraDevice.java)
package android.hardware.camera.device.V3_5;
public interface ICameraDevice extends android.os.IInterface {
// 状态码
public static final int STATUS_OK = 0;
public static final int STATUS_ERROR = 1;
public static final int STATUS_INVALID_OPERATION = 2;
// 打开相机设备
public int open(ICameraDeviceCallback callback)
throws android.os.RemoteException;
// 关闭相机设备
public int close()
throws android.os.RemoteException;
// 配置流
public int configureStreams(StreamConfiguration config,
StreamConfiguration outConfig)
throws android.os.RemoteException;
// 处理捕获请求
public int processCaptureRequest(CaptureRequest[] requests,
BufferCache[] cachesToRemove)
throws android.os.RemoteException;
// 抽象类,提供默认实现
public abstract static class Stub extends android.os.Binder
implements ICameraDevice {
// Binder 通信逻辑自动生成
}
}
@V3_2::ICameraDevice、@V3_3::ICameraDevice 等子接口继承。Framework 通过 getInterfaceVersion() 方法检测 HAL 支持的版本,动态选择调用路径。
4.4 包名与版本管理最佳实践
在大型项目中,多个 HAL 版本共存是常态。合理的包名和版本管理策略可以避免命名冲突,降低维护成本。
4.4.1 版本演进策略
| 场景 | 版本变更 | 示例 | 兼容性 |
|---|---|---|---|
| 新增方法 | 次版本+1 | 3.4 → 3.5 | 向后兼容 |
| 新增类型 | 次版本+1 | 3.5 → 3.6 | 向后兼容 |
| 修改方法签名 | 主版本+1 | 3.6 → 4.0 | 不兼容 |
| 删除方法 | 主版本+1 | 3.7 → 4.0 | 不兼容 |
| 修改类型定义 | 主版本+1 | 3.8 → 4.0 | 不兼容 |
4.4.2 多版本共存方案
Android Treble 架构支持同一 HAL 接口的多个版本同时注册到 hwservicemanager。Camera HAL3 实现可以通过 @3.4::ICameraDevice 和 @3.5::ICameraDevice 两个服务名分别注册,Framework 根据设备能力选择连接。
// 服务注册示例 (C++ 实现)
// 注册 3.4 版本服务
android::sp<ICameraDevice> device34 = new CameraDeviceImpl34();
device34->registerAsService("camera_device@3.4");
// 注册 3.5 版本服务
android::sp<ICameraDevice> device35 = new CameraDeviceImpl35();
device35->registerAsService("camera_device@3.5");
// Framework 端获取服务
// 优先尝试 3.5 版本
sp<ICameraDevice> device = ICameraDevice::getService("camera_device@3.5");
if (device == nullptr) {
// 降级到 3.4 版本
device = ICameraDevice::getService("camera_device@3.4");
}
4.5 本章小结
HIDL 接口定义是 Camera HAL3 开发的基石。通过本章学习,应掌握以下核心技能:
- .hal 文件语法: 包名声明、类型定义、接口声明、方法签名和回调机制
- 版本管理策略: 主版本/次版本的含义、变更规则和多版本共存方案
- 代码生成流程: hidl-gen 工具使用、输出目录结构和 C++/Java 代码对应关系
- Camera HAL3 实战: 核心接口定义、回调接口设计和版本兼容性实现
在实际项目中,建议将 .hal 文件纳入版本控制,每次接口变更都同步更新版本号,并使用自动化脚本验证生成的代码与 .hal 定义的一致性。