3. Camera HAL接口基础:HAL3架构、接口定义与关键数据结构
Camera HAL(硬件抽象层)是Android Camera框架中连接Framework与底层硬件驱动的关键桥梁。HAL3(即Camera3 HAL)自Android 5.0引入,取代了HAL1,为现代多帧流水线、ZSL(零快门延迟)和高级ISP控制提供了标准接口。理解HAL3架构、接口定义及核心数据结构,是进行CTS测试用例分析与HAL适配问题排查的基石。
3.1 HAL3架构概览
HAL3架构采用生产者-消费者模型,以Camera3Stream为核心,支持多个独立配置的数据流(如预览流、拍照流、视频流)同时运行。与HAL1的单一回调模式不同,HAL3要求HAL实现一个完整的管道(Pipeline),Framework通过发送捕获请求(Capture Request)来驱动每一帧的处理。
3.2 Camera HAL接口定义
HAL3接口的核心定义在 hardware/libhardware/include/hardware/camera3.h 中。HAL模块通过 hw_module_t 和 hw_device_t 标准结构暴露,但具体操作由 camera3_device_ops_t 函数指针表定义。
3.2.1 关键接口函数
| 接口函数 | 方向 | 功能描述 | CTS 关注点 |
|---|---|---|---|
initialize() |
Framework → HAL | 传入 camera3_callback_ops_t,建立通信通道 |
必须正确保存回调指针,否则后续通知无法送达 |
configure_streams() |
Framework → HAL | 配置所有活跃的 camera3_stream_t 流 |
必须验证流参数合法性,返回 CAMERA3_STATUS_OK 或错误码 |
process_capture_request() |
Framework → HAL | 提交一个捕获请求,包含所有输出缓冲区及设置 | 必须同步或异步处理,超时或错误将导致 CTS 失败 |
flush() |
Framework → HAL | 清空所有待处理的请求,停止当前操作 | 必须在 1000ms 内完成,否则 CTS 判定为 ANR |
dump() |
Framework → HAL | 输出调试信息到 fd | 必须实现,不能为空函数,否则 CTS 会调用并检查输出 |
configure_streams() 是 CTS 测试的高频调用点。HAL 必须在此函数中检查流格式(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED 的处理)、分辨率是否超出 sensor 能力、以及流数量是否超过硬件限制。错误的配置拒绝逻辑是 CTS 失败的常见原因。
3.2.2 回调接口
HAL通过 camera3_callback_ops_t 向Framework发送异步通知:
process_capture_result():返回已完成的捕获结果,包含元数据和缓冲区句柄。notify():发送错误、快门事件等异步消息。
3.3 关键数据结构
HAL3中,数据以结构体形式在Framework与HAL之间传递。以下三个结构体是CTS测试和HAL适配中最常打交道的对象。
3.3.1 camera_metadata_t
camera_metadata_t 是Android Camera系统的“通用语言”,用于编码所有控制参数和结果信息。它是一个序列化的键值对(key-value)容器,支持嵌套、数组和复杂类型。
- 存储位置:
system/media/camera/include/system/camera_metadata.h - 内部结构: 包含一个头部(entry count、data count)和两个连续区域:entry 区(存储 key、type、data offset)和 data 区(存储实际值)。
- 常用操作:
camera_metadata_get():读取指定 tag 的值。camera_metadata_set():设置指定 tag 的值。camera_metadata_allocate():预分配空间,避免动态增长。
// camera_metadata_t 使用示例:读取 ANDROID_SENSOR_EXPOSURE_TIME
camera_metadata_t *result = ...; // 从 process_capture_result 获取
camera_metadata_entry_t entry;
int ret = camera_metadata_get(result, ANDROID_SENSOR_EXPOSURE_TIME, &entry);
if (ret == 0 && entry.count > 0) {
int64_t exposure_time = entry.data.i64[0];
ALOGI("Exposure time: %ld ns", (long)exposure_time);
} else {
ALOGE("Failed to get exposure time, ret=%d", ret);
}
camera_metadata_t 中特定 tag 的存在性和值范围。例如,android.control.aeMode 必须返回 ANDROID_CONTROL_AE_MODE_ON 或 OFF 等合法枚举值。如果 HAL 返回了未定义的枚举值,CTS 将直接报错。务必使用 validate_camera_metadata_structure() 进行自检。
3.3.2 camera3_stream_t
camera3_stream_t 描述一个单向数据流,可以是输出流(到Framework)或输入流(来自Framework,用于 reprocessing)。它是 configure_streams() 的核心参数。
| 字段 | 类型 | 说明 | CTS 测试关注点 |
|---|---|---|---|
stream_type |
int | CAMERA3_STREAM_OUTPUT 或 CAMERA3_STREAM_INPUT |
必须与配置意图一致,否则 configure_streams 失败 |
width / height |
uint32_t | 图像分辨率 | 必须在 android.scaler.availableStreamConfigurations 中声明 |
format |
int | 像素格式,如 HAL_PIXEL_FORMAT_YCbCr_420_888 |
必须支持 IMPLEMENTATION_DEFINED 的灵活映射 |
usage |
uint32_t | Gralloc 使用标志,如 GRALLOC_USAGE_HW_TEXTURE |
HAL 可以修改此字段,但必须合法 |
max_buffers |
uint32_t | HAL 请求的最大缓冲区数 | 必须合理,过大或过小都会导致 CTS 性能测试失败 |
priv |
void* | HAL 私有数据指针,Framework 不解析 | 可用于关联硬件管道上下文 |
3.3.3 camera3_capture_request_t 与 camera3_capture_result_t
这两个结构体构成了HAL3 Pipeline的请求-响应循环:
- camera3_capture_request_t:由Framework发送给HAL,包含:
frame_number:帧序号,必须单调递增。settings:指向camera_metadata_t,包含该帧的3A、效果、裁剪等控制参数。input_buffer/output_buffers:输入/输出缓冲区数组。
- camera3_capture_result_t:由HAL返回给Framework,包含:
frame_number:对应请求的帧序号。result:指向camera_metadata_t,包含该帧的实际3A值、统计信息等。output_buffers:已填充数据的输出缓冲区。partial_result:部分结果序号,用于支持分阶段返回。
// process_capture_request 的典型实现骨架
int hal_process_capture_request(const camera3_capture_request_t *request) {
// 1. 校验 frame_number 连续性
if (request->frame_number <= last_frame_number) {
ALOGE("Non-monotonic frame number: %d", request->frame_number);
return -EINVAL;
}
last_frame_number = request->frame_number;
// 2. 解析 settings 元数据
camera_metadata_entry_t entry;
if (camera_metadata_get(request->settings, ANDROID_SENSOR_SENSITIVITY, &entry) == 0) {
int32_t iso = entry.data.i32[0];
// 设置硬件 ISO
}
// 3. 处理输出缓冲区
for (size_t i = 0; i < request->num_output_buffers; i++) {
const camera3_stream_buffer_t &buf = request->output_buffers[i];
// 将硬件数据填充到 buf.buffer->handle 指向的图形缓冲区
}
// 4. 异步或同步返回结果
camera3_capture_result_t result;
memset(&result, 0, sizeof(result));
result.frame_number = request->frame_number;
result.result = build_result_metadata(); // 构造结果元数据
result.num_output_buffers = request->num_output_buffers;
result.output_buffers = request->output_buffers;
callback_ops->process_capture_result(callback_ops, &result);
return 0;
}
3.4 数据结构关系总结
以下表格总结了三个关键数据结构在HAL3 Pipeline中的角色与交互关系:
| 数据结构 | 生命周期 | 传递方向 | CTS 验证重点 |
|---|---|---|---|
camera_metadata_t |
逐帧创建与销毁 | 双向(Request / Result) | Tag 完整性、值范围、枚举合法性 |
camera3_stream_t |
configure_streams 期间 | Framework → HAL | 格式支持、分辨率匹配、usage 修改合法性 |
camera3_capture_request_t |
单帧请求 | Framework → HAL | frame_number 单调性、缓冲区有效性 |
camera3_capture_result_t |
单帧响应 | HAL → Framework | 结果完整性、partial_result 顺序、缓冲区状态 |
camera_metadata_t 的读写操作,确保 configure_streams() 的流配置与静态元数据(android.scaler.availableStreamConfigurations 等)严格一致,并在 process_capture_request() 中正确管理缓冲区生命周期。任何环节的疏忽都会直接导致 CTS 测试用例失败,尤其是在 TestStreamConfiguration、TestCameraMetadata 和 TestRequestPipeline 等核心测试套件中。