3. HAL3 核心数据结构详解
Camera HAL3 接口围绕三个核心数据结构构建:camera3_device_t、camera3_callback_ops_t 和 camera3_stream_t。它们是 HAL 层与 Camera Service 之间通信的契约基础,理解其内存布局、生命周期和线程安全模型,是进行 Vendor 层适配与调试的前提。
核心要点:这三个结构体分别代表了“设备句柄”、“回调通道”和“数据管道”。调试中 90% 的稳定性问题(如空指针、野指针、死锁)都源于对它们生命周期管理的疏忽。
3.1 camera3_device_t:HAL 设备抽象
camera3_device_t 是 HAL 层暴露给 Framework 的唯一设备句柄。它封装了所有操作相机设备的函数指针,其定义位于 hardware/libhardware/include/hardware/camera3.h。
| 字段 | 类型 | 说明 |
|---|---|---|
common |
hw_device_t |
继承自硬件抽象层基类,包含 tag、version、close 等通用字段 |
ops |
camera3_device_ops_t * |
指向操作函数表的指针,包含 initialize、configure_streams、process_capture_request 等核心接口 |
priv |
void * |
Vendor 私有数据指针,通常指向具体的 HAL 设备实现对象 |
// camera3_device_t 典型定义(简化)
typedef struct camera3_device {
hw_device_t common;
camera3_device_ops_t *ops;
void *priv;
} camera3_device_t;
调试提示:在 Vendor 层适配时,
priv 指针是最容易出问题的地方。建议在 open() 时分配一个调试专用的结构体,包含设备状态机、上次调用时间戳、错误计数器等字段,便于在 dump() 或 log 中快速定位。
下图展示了 camera3_device_t 在 HAL 层与 Framework 之间的桥梁作用:
3.2 camera3_callback_ops_t:异步回调契约
camera3_callback_ops_t 是 HAL 层向 Framework 发送异步消息的唯一通道。它由 Camera Service 在 initialize() 时传入,HAL 层必须保存此指针并在合适的线程中调用其函数。
| 回调函数 | 触发时机 | 线程安全要求 |
|---|---|---|
process_capture_result |
HAL 完成一次 Capture Request 处理后 | 可并发调用,但同一 frame_number 必须有序 |
notify |
发生错误、快门事件、3A 状态变化时 | 必须线程安全,不能阻塞 |
// camera3_callback_ops_t 定义
typedef struct camera3_callback_ops {
void (*process_capture_result)(const struct camera3_callback_ops *,
const camera3_capture_result_t *result);
void (*notify)(const struct camera3_callback_ops *,
const camera3_notify_msg_t *msg);
} camera3_callback_ops_t;
常见陷阱:Vendor 层在实现
process_capture_result 回调时,必须确保 camera3_capture_result_t 中的 output_buffers 数组在回调返回前不会被复用。许多 Vendor 在 buffer 复用逻辑上出现竞争条件,导致 Framework 读到脏数据或崩溃。
下图展示了回调的异步数据流:
3.3 camera3_stream_t:数据流管道
camera3_stream_t 描述了一条从 HAL 到 Framework 的数据流。它定义了图像的格式、分辨率、使用场景以及 buffer 管理方式。在 configure_streams() 中,Framework 会传入一个 camera3_stream_t 数组,HAL 需要验证并设置 usage、max_buffers 等字段。
| 字段 | 方向 | 说明 |
|---|---|---|
stream_type |
Framework → HAL | CAMERA3_STREAM_OUTPUT / INPUT / BIDIRECTIONAL |
width / height |
Framework → HAL | 图像分辨率,HAL 可调整(需满足最小要求) |
format |
Framework → HAL | 像素格式,如 HAL_PIXEL_FORMAT_YCbCr_420_888 |
usage |
HAL → Framework | HAL 设置的 buffer 使用标志,如 GRALLOC_USAGE_HW_TEXTURE |
max_buffers |
HAL → Framework | HAL 请求的最大 buffer 数量,Framework 据此分配 |
priv |
HAL 私有 | Vendor 可附加私有数据,如关联的 ISP 通道 ID |
// camera3_stream_t 关键字段
typedef struct camera3_stream {
int stream_type; // 输入/输出/双向
uint32_t width;
uint32_t height;
int format; // 像素格式
uint32_t usage; // Gralloc 使用标志(HAL 设置)
uint32_t max_buffers; // HAL 请求的 buffer 数量
void *priv; // Vendor 私有数据
// ... 其他字段
} camera3_stream_t;
调试技巧:在
configure_streams() 中,建议打印每个 stream 的 format、width、height 和 usage。许多 Vendor 适配问题源于 usage 设置不当——例如预览流未设置 GRALLOC_USAGE_HW_TEXTURE 导致 SurfaceFlinger 合成失败。
下图展示了多个 stream 在 HAL 中的配置关系:
3.4 三者协作关系总结
在 HAL3 的运行时模型中,这三个结构体构成了一个稳定的三角关系:
- camera3_device_t 是入口,通过
ops接收 Framework 的同步调用(如configure_streams、process_capture_request)。 - camera3_callback_ops_t 是出口,HAL 通过它异步返回结果和事件。
- camera3_stream_t 是数据通道,在
configure_streams中建立,在每次process_capture_result中携带 buffer 返回。
调试检查清单:
✅
✅
✅
✅ 所有 stream 的
✅
camera3_device_t.priv 是否在 open() 时分配,在 close() 时释放?✅
camera3_callback_ops_t 是否在 initialize() 中保存并增加引用计数?✅
camera3_stream_t.usage 是否根据 stream_type 和 format 正确设置?✅ 所有 stream 的
max_buffers 是否满足 ISP 管线的最小深度需求?