3. Camera HAL3 核心数据结构详解
Camera HAL3 接口的设计围绕四个核心数据结构展开:camera3_device_t、camera3_callback_ops_t、camera3_stream_t 和 camera3_capture_request_t。这四个结构体构成了 HAL3 与 Camera Service 之间通信的契约基础,理解它们是开发稳定、高性能 Camera HAL 的必修课。
学习提示: 本章节所有结构体定义均基于 Android 14 (API 34) 的 hardware/libhardware/include/hardware/camera3.h 头文件。不同 Android 版本可能存在细微差异,但核心字段保持一致。
3.1 camera3_device_t:HAL 设备句柄
camera3_device_t 是 Camera Service 与 HAL 交互的入口点,代表一个物理或逻辑摄像头设备。它继承自 hw_device_t,并扩展了 HAL3 特有的操作函数指针。
typedef struct camera3_device {
hw_device_t common;
camera3_device_ops_t *ops;
void *priv;
} camera3_device_t;
| 字段 | 类型 | 说明 |
|---|---|---|
| common | hw_device_t | 标准硬件设备结构体,包含 tag、version、module、close 等基础字段 |
| ops | camera3_device_ops_t * | 指向操作函数表的指针,包含 initialize、configure_streams、process_capture_request 等核心方法 |
| priv | void * | HAL 私有数据指针,通常指向自定义的设备上下文结构体 |
实战要点: 在 open() 回调中,HAL 需要为每个摄像头实例分配并初始化 camera3_device_t。priv 字段通常指向一个包含传感器信息、流配置状态、请求队列等运行时数据的上下文结构体。切勿在 ops 返回后修改 common 字段,否则会导致 Service 端崩溃。
3.2 camera3_callback_ops_t:异步回调契约
当 Camera Service 调用 initialize() 时,会传入一个 camera3_callback_ops_t 结构体指针。HAL 通过这个结构体向 Service 异步通知事件、返回结果数据和发送信号。
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 *);
void (*process_capture_result_with_flags)(const struct camera3_callback_ops *,
const camera3_capture_result_t *,
uint32_t flags);
} camera3_callback_ops_t;
| 回调函数 | 触发时机 | 关键参数 |
|---|---|---|
| process_capture_result | HAL 完成一次 capture request 的部分或全部处理 | camera3_capture_result_t:包含 frame_number、结果 metadata、输出 buffer、partial_result 等 |
| notify | 发生异步事件(如曝光结束、快门、错误) | camera3_notify_msg_t:包含消息类型(ERROR、SHUTTER 等)及对应数据 |
| process_capture_result_with_flags | Android 14+ 新增,带标志位的结果返回 | flags:如 CAMERA3_RESULT_FLAG_FINAL 表示该 request 的所有结果已返回完毕 |
常见错误: HAL 必须在 同一个线程 中按 frame_number 递增顺序调用 process_capture_result。乱序返回会导致 Service 端 buffer 管理混乱,引发 ANR 或黑屏。notify 中的 SHUTTER 事件必须在对应的 process_capture_result 之前或同时发出。
3.3 camera3_stream_t:数据流管道
camera3_stream_t 描述一条从 HAL 到 Consumer(如 SurfaceView、ImageReader、MediaCodec)的数据流。在 configure_streams() 中,Service 向 HAL 传递一个流数组,HAL 需要验证并配置这些流。
typedef struct camera3_stream {
int stream_type; // CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL
uint32_t width;
uint32_t height;
int format; // HAL_PIXEL_FORMAT_xxx
uint32_t usage; // GRALLOC_USAGE_xxx
uint32_t max_buffers;
const camera_metadata_t *stream_configuration;
const camera_metadata_t *stream_parameters;
void *priv;
int data_space; // HAL_DATASPACE_xxx
int rotation; // CAMERA3_STREAM_ROTATION_xxx
const char *physical_camera_id;
uint64_t buffer_size;
int vndk_version;
} camera3_stream_t;
| 字段 | 设置方 | 说明 |
|---|---|---|
| stream_type | Service | CAMERA3_STREAM_OUTPUT(输出到 Surface)、CAMERA3_STREAM_INPUT(输入,如 reprocessing)、CAMERA3_STREAM_BIDIRECTIONAL(双向,如 ZSL) |
| width / height / format | Service | 分辨率与像素格式。HAL 可在 configure_streams 中修改为更接近的值 |
| max_buffers | HAL 填写 | HAL 在该流上同时需要的 buffer 最大数量,Service 据此分配 buffer 池 |
| priv | HAL 填写 | HAL 私有数据,通常指向该流对应的硬件 DMA 通道或 ISP 输入输出配置 |
| usage | Service | Gralloc buffer 的使用标志,如 GRALLOC_USAGE_HW_CAMERA_WRITE、GRALLOC_USAGE_HW_TEXTURE |
实战要点: HAL 在 configure_streams() 中必须检查所有流的组合是否可行。例如,同时请求 4K 60fps 输出流 + 1080p 输入流时,需要确认 ISP 带宽是否足够。如果组合不可行,返回 -EINVAL 并建议替代方案。max_buffers 的典型值为 3~6,过小会导致 dequeue 阻塞,过大会增加内存压力。
3.4 camera3_capture_request_t:一次捕获的完整描述
每次拍照或预览帧的请求都由 camera3_capture_request_t 描述。Service 通过 process_capture_request() 将请求下发到 HAL,HAL 解析后驱动传感器曝光、ISP 处理并最终返回结果。
typedef struct camera3_capture_request {
uint32_t frame_number;
const camera_metadata_t *settings;
camera3_stream_buffer_t *input_buffer;
uint32_t num_input_buffers;
camera3_stream_buffer_t *output_buffers;
uint32_t num_output_buffers;
const camera_metadata_t *physical_camera_settings;
int32_t *physcam_id;
uint32_t num_physcam_settings;
} camera3_capture_request_t;
| 字段 | 说明 |
|---|---|
| frame_number | 单调递增的帧序号,从 1 开始。HAL 必须在返回结果和通知中携带相同的 frame_number |
| settings | 本次请求的完整 metadata,包含 AE/AWB/AF 模式、sensitivity、exposure_time、effect 等控制参数 |
| input_buffer | 仅 reprocessing 请求使用,指向输入 buffer(如 ZSL 环形 buffer 中的一帧) |
| output_buffers | 输出 buffer 数组,每个 buffer 对应一个已配置的 stream。HAL 将处理后的数据填入这些 buffer |
| physical_camera_settings | 逻辑摄像头(multi-camera)中,为每个物理摄像头单独指定的 metadata 覆盖 |
关键约束: HAL 必须在收到 process_capture_request 后尽快返回,不能在该函数内部阻塞等待传感器曝光完成。正确的做法是:将请求加入内部队列,由独立的工作线程异步处理。如果 HAL 在 process_capture_request 中阻塞超过 500ms,Service 会触发 watchdog 并杀死 HAL 进程。
3.5 四个核心结构体的协作关系
在实际的 Camera HAL 实现中,这四个结构体通过以下时序协作完成一次完整的拍照或预览流程:
- 初始化阶段: Service 调用
open()获取camera3_device_t,然后调用ops->initialize()传入camera3_callback_ops_t。 - 流配置阶段: Service 调用
ops->configure_streams()传入camera3_stream_t数组,HAL 验证并设置max_buffers和priv。 - 请求下发阶段: Service 构造
camera3_capture_request_t,调用ops->process_capture_request()下发。 - 结果返回阶段: HAL 通过
callback_ops->notify()发送 SHUTTER 事件,通过callback_ops->process_capture_result()返回填充好的 buffer 和 metadata。
| 阶段 | 核心结构体 | 关键函数 | HAL 职责 |
|---|---|---|---|
| 初始化 | camera3_device_t | open() → initialize() | 分配设备上下文,保存 callback_ops 指针 |
| 流配置 | camera3_stream_t | configure_streams() | 验证流组合,设置 max_buffers 和 priv |
| 请求处理 | camera3_capture_request_t | process_capture_request() | 非阻塞入队,异步执行传感器曝光和 ISP 处理 |
| 结果回调 | camera3_callback_ops_t | notify() / process_capture_result() | 按序返回结果,保证 SHUTTER 先于结果 |
进阶思考: 在 multi-camera 场景下,一个逻辑 camera3_device_t 可能对应多个物理传感器。此时 physical_camera_settings 字段允许为每个物理摄像头指定独立的 AE/AWB 参数。HAL 需要将逻辑请求拆解为多个物理请求,分别驱动对应传感器,最后合成一个结果返回。