3. Camera HAL 接口定义:camera3.h 关键结构体与函数指针

camera3.h 是 Android Camera HAL3 的核心接口头文件,位于 hardware/libhardware/include/hardware/ 目录下。它定义了 HAL 层与 Camera Framework 之间交互的所有数据结构、回调函数指针以及设备操作接口。理解该文件中的关键结构体与函数指针,是进行 HAL 层移植适配的第一步。

3.1 顶层设备结构:camera3_device_t

camera3_device_t 是 HAL3 设备的抽象,继承自 hw_device_t。它包含一个指向 camera3_device_ops_t 的函数指针表,Framework 通过该表调用 HAL 的具体实现。

typedef struct camera3_device {
    hw_device_t common;
    camera3_device_ops_t *ops;
    void *priv;
} camera3_device_t;
字段类型说明
commonhw_device_t标准硬件设备结构,包含 tag、version、close 等基础字段
opscamera3_device_ops_t*函数指针表,HAL 必须实现所有接口
privvoid*HAL 私有数据指针,通常指向自定义的设备上下文
移植要点:在 camera3_device_t 的 priv 字段中,通常存放指向具体传感器驱动、ISP 控制块、Stream 管理器的指针。初始化时务必分配并绑定该结构。

3.2 核心操作接口:camera3_device_ops_t

该结构体定义了 HAL3 设备的所有操作函数指针,是移植工作中需要完整实现的接口集合。以下列出最关键的 6 个函数指针:

函数指针原型功能描述
initializeint (*)(const struct camera3_device *, const camera3_callback_ops_t *)初始化设备,注册 Framework 回调
configure_streamsint (*)(const struct camera3_device *, camera3_stream_configuration_t *)配置数据流(分辨率、格式、方向等)
process_capture_requestint (*)(const struct camera3_device *, camera3_capture_request_t *)提交一次捕获请求
flushint (*)(const struct camera3_device *)清空所有待处理的请求
dumpvoid (*)(const struct camera3_device *, int fd)导出调试信息到文件描述符
signal_stream_flushvoid (*)(const struct camera3_device *, uint32_t num_streams, const camera3_stream_t *const *streams)通知 HAL 指定流即将被清空
关键路径:configure_streams → process_capture_request → 回调通知,构成一次完整的拍照/预览生命周期。任何一环的阻塞都会导致 Camera 服务 ANR。

3.3 流配置结构:camera3_stream_configuration_t

当 Framework 需要改变输出流(如切换预览分辨率、开启录像)时,会调用 configure_streams,并传入该结构体。HAL 需要根据配置重新分配 buffer 并设置 ISP 参数。

typedef struct camera3_stream_configuration {
    uint32_t num_streams;
    camera3_stream_t **streams;
    uint32_t operation_mode;
    const camera3_stream_buffer_set_t *input_buffers;
} camera3_stream_configuration_t;
字段说明
num_streams流数量,通常为 1~3(预览、拍照、录像)
streams指向 camera3_stream_t 指针数组,每个元素描述一条流
operation_mode操作模式,如 CAMERA3_STREAM_CONFIGURATION_NORMAL_MODE 或 CONSTRAINED_HIGH_SPEED_MODE
input_buffers输入 buffer 配置(仅 reprocessing 场景使用)
常见陷阱:HAL 在 configure_streams 中必须检查 operation_mode,高速模式(如 120fps 录像)需要单独配置 ISP 时钟和 buffer 队列深度,否则会导致帧率不达标。

3.4 捕获请求与结果回调

camera3_capture_request_t 描述一次捕获请求,包含帧号、输出 buffer 列表、输入 buffer(reprocessing)、设置参数等。HAL 处理完成后,通过 camera3_callback_ops_t 中的 process_capture_result 回调返回结果。

typedef struct camera3_capture_request {
    uint32_t frame_number;
    uint32_t num_output_buffers;
    const camera3_stream_buffer_t *output_buffers;
    const camera3_stream_buffer_t *input_buffer;
    const camera_metadata_t *settings;
} camera3_capture_request_t;
字段说明
frame_number帧序号,必须与结果回调中的 frame_number 一致
output_buffers输出 buffer 数组,每个 buffer 对应一条 stream
input_buffer输入 buffer(仅 reprocessing 时有效)
settings本次请求的 metadata 参数(AE/AWB/AF 等)

3.5 关键结构体关系图

下图展示了 camera3.h 中核心结构体之间的调用与数据流向关系:

camera3.h 核心结构体关系图 camera3_device_t camera3_device_ops_t camera3_stream_configuration_t camera3_stream_t camera3_capture_request_t camera3_callback_ops_t camera3_stream_buffer_t camera_metadata_t 数据流方向 Framework → camera3_device_ops_t → process_capture_request → 硬件驱动 → 结果回调 包含 调用 调用 注册 包含 包含 包含 返回

3.6 回调接口:camera3_callback_ops_t

Framework 通过 initialize 将回调结构体注册给 HAL。HAL 在处理完请求后,必须通过以下回调通知 Framework:

回调函数触发时机说明
process_capture_result每帧处理完成返回 metadata 和填充好的 buffer
notify异步事件如快门事件、错误事件、3A 状态变化
typedef struct camera3_callback_ops {
    void (*process_capture_result)(const struct camera3_callback_ops *, const camera3_capture_result_t *);
    void (*notify)(const struct camera3_callback_ops *, const camera3_notify_msg_t *);
} camera3_callback_ops_t;
性能要求:process_capture_result 必须在帧周期内尽快返回。如果 HAL 在回调中执行耗时操作(如 JPEG 编码),会导致 buffer 无法及时归还,进而阻塞后续请求。建议将编码等重操作放在独立线程中完成。

3.7 移植适配检查清单

在开始编写 HAL 代码前,建议对照以下清单确认接口完整性:

  • camera3_device_ops_t:是否实现了全部 10 个函数指针?initialize、configure_streams、process_capture_request 为强制实现。
  • camera3_stream_t:在 configure_streams 中是否正确设置了 max_buffers 和 usage_flags?
  • camera3_capture_result_t:返回结果时 frame_number 是否与请求一致?partial_result 是否按需设置?
  • 错误处理:当硬件出错时,是否通过 notify 发送 CAMERA3_MSG_ERROR_REQUEST 或 CAMERA3_MSG_ERROR_DEVICE?
  • Buffer 管理:是否实现了 register_stream_buffers(Android N 之前)或使用 dequeue_buffer/queue_buffer 模式?
版本差异:Android 8.0 之后,register_stream_buffers 已被废弃,HAL 必须通过 process_capture_request 中的 buffer 句柄直接操作。如果仍使用旧接口,在 Treble 架构下会导致 Camera 服务崩溃。

3.8 典型初始化流程

以下伪代码展示了 HAL 设备初始化的标准步骤:

// 1. 分配 camera3_device_t
camera3_device_t *dev = malloc(sizeof(camera3_device_t));
memset(dev, 0, sizeof(camera3_device_t));

// 2. 填充 hw_device_t 公共字段
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = CAMERA_DEVICE_API_VERSION_3_5;
dev->common.close = hal_dev_close;

// 3. 绑定操作接口
static camera3_device_ops_t ops = {
    .initialize = hal_initialize,
    .configure_streams = hal_configure_streams,
    .process_capture_request = hal_process_capture_request,
    .flush = hal_flush,
    .dump = hal_dump,
    // ... 其他接口
};
dev->ops = &ops;

// 4. 分配私有上下文
dev->priv = hal_create_device_context();
调试建议:在 hal_initialize 中打印 camera3_callback_ops_t 的地址,并在 process_capture_result 入口处添加帧号日志。这能快速定位回调注册失败或帧丢失问题。