3、Camera HAL 核心数据结构解析

Camera HAL 的移植与稳定性优化,本质上是围绕一组核心数据结构进行实例化、回调注册与状态管理的过程。本章深入解析 camera_module_t、camera_device_t 和 camera3_device_ops_t 三个关键结构体,理解它们的职责、成员布局与生命周期,是编写可移植、高性能 HAL 的基础。

3.1 camera_module_t:HAL 模块的入口

camera_module_t 是 HAL 层暴露给 Camera Service 的第一个结构体,定义在 hardware/libhardware/include/hardware/camera_common.h 中。它继承自 hw_module_t,并扩展了摄像头枚举与打开接口。

成员 类型 说明
common hw_module_t 标准 HAL 模块头,包含 tag、module_api_version、hal_api_version、id、name、author、methods 等
get_number_of_cameras int (*)(void) 返回设备上可用的摄像头总数(包括前后摄、深度、ToF 等)
get_camera_info int (*)(int camera_id, struct camera_info *info) 填充指定 camera_id 的静态信息:设备方向、 facing、orientation、device_version 等
set_callbacks int (*)(const camera_module_callbacks_t *callbacks) 注册 Camera Service 的回调,用于热插拔通知、Torch 模式变化等
get_vendor_tag_ops void (*)(vendor_tag_ops_t* ops) (可选)提供厂商自定义 metadata tag 的查询操作
open_legacy int (*)(const struct hw_module_t* module, const char* id, uint32_t halVersion, struct hw_device_t** device) (可选)打开旧版本 HAL 设备,用于兼容 legacy 模式
set_torch_mode int (*)(const char* camera_id, bool enabled) (可选)独立控制闪光灯 torch 模式,不依赖打开 camera device
init int (*)(void) (可选)模块级一次性初始化,在 get_number_of_cameras 之前调用
移植要点: 在实现 get_camera_info 时,device_version 必须正确设置为 CAMERA_DEVICE_API_VERSION_3_0 或更高,否则 Camera Service 不会以 Camera3 模式打开设备。同时,set_callbacks 中注册的回调指针需要保存为全局变量,用于后续热插拔事件上报。

3.2 camera_device_t:设备实例的抽象

camera_device_t 继承自 hw_device_t,代表一个已打开的摄像头设备实例。它本身是一个轻量级包装,真正的操作接口通过 ops 指针指向 camera3_device_ops_t。

typedef struct camera_device {
    hw_device_t common;               // 标准设备头,包含 close 函数指针
    camera3_device_ops_t *ops;        // Camera3 操作接口表
    void *priv;                       // 私有数据指针,通常指向自定义的设备上下文
} camera_device_t;

三个关键字段的职责:

  • common.close:关闭设备时调用,负责释放所有资源、停止流、销毁 pipeline。
  • ops:指向 camera3_device_ops_t 结构体,所有请求处理、流配置、metadata 交互都通过此表完成。
  • priv:HAL 实现者自定义的上下文结构体,通常包含 sensor 驱动句柄、ISP 实例、stream 列表、buffer 管理器等。
常见错误: 在 open() 函数中,必须将 camera_device_t 的 ops 指针指向一个静态或持久化的 camera3_device_ops_t 实例,不能是栈变量。同时 priv 指针应在 open 时分配内存,在 close 时释放,避免内存泄漏或野指针。

3.3 camera3_device_ops_t:Camera3 操作接口表

这是 Camera HAL 中最核心的函数指针集合,Camera Service 通过它向 HAL 下发配置、请求和 buffer。结构体定义在 hardware/libhardware/include/hardware/camera3.h 中,包含约 20 个函数指针。

函数指针 调用时机 核心职责
initialize open 之后立即调用 传入 camera3_callback_ops_t,HAL 保存回调用于上报结果、事件、buffer
configure_streams 每次配置流时 接收 camera3_stream_configuration_t,HAL 根据 stream 格式/尺寸/usage 配置 ISP 和 sensor
register_stream_buffers (已废弃,可置 NULL) 早期版本用于预注册 buffer,Camera3 已改为 request 时传递
process_capture_request 每帧请求 接收 camera3_capture_request_t,包含 settings、input/output buffer、物理 camera id 等
flush 快速停止所有请求 丢弃所有未处理的请求,已处理的正常返回,未处理的返回错误状态
dump dumpsys 时 输出 HAL 内部状态、buffer 队列、pipeline 延迟等信息用于调试
construct_default_request_settings 创建默认 settings 根据模板类型(PREVIEW/STILL_CAPTURE/VIDEO_RECORD 等)返回默认 metadata
is_reconfiguration_required (可选)物理 camera 切换时 判断是否需要重新 configure_streams
性能关键路径: process_capture_request 是每一帧的入口,必须做到无锁或低锁设计,避免在回调中做 IO 等待。建议使用异步 pipeline + 预分配的 request 池来降低延迟抖动。

3.4 核心结构体关系图

下图展示了 Camera Service、HAL Module、Device 与 ops 之间的层级调用关系:

Camera HAL 核心结构体关系图 Camera HAL 核心结构体关系图 Camera Service (Framework) camera_module_t get_number_of_cameras | get_camera_info | set_callbacks open (返回 camera_device_t) camera_device_t common (hw_device_t) | ops (camera3_device_ops_t*) | priv (void*) common.close → 释放资源 camera3_device_ops_t initialize | configure_streams | process_capture_request flush | dump | construct_default_request_settings (约 20 个函数指针,每帧调用入口) camera3_callback_ops_t 回调 说明:虚线箭头表示回调方向(HAL → Service),实线箭头表示调用方向(Service → HAL)

3.5 生命周期与初始化顺序

理解三个结构体的初始化顺序,对移植调试至关重要:

  1. HAL 加载阶段: Camera Service 通过 hw_get_module() 加载 camera_module_t,调用 get_number_of_cameras() 和 get_camera_info() 枚举设备。
  2. 设备打开阶段: Service 调用 camera_module_t.open(),HAL 分配 camera_device_t 并填充 ops 指针。
  3. 初始化阶段: Service 调用 ops->initialize(),传入回调函数指针,HAL 保存回调并完成内部 pipeline 初始化。
  4. 配置与运行阶段: configure_streams() 配置流,process_capture_request() 处理每一帧请求。
  5. 关闭阶段: Service 调用 common.close(),HAL 释放所有资源。
调试建议: 在 initialize 和 configure_streams 入口处添加 ALOGV 日志,记录传入的参数(如 stream 数量、格式、分辨率),便于定位配置不匹配问题。同时,在 process_capture_request 中记录 frame_number,用于追踪丢帧或超时。

3.6 稳定性优化关键点

结构体 常见稳定性问题 优化策略
camera_module_t get_camera_info 返回错误信息导致枚举失败 静态验证 camera_info 字段合法性;init 中做硬件探测
camera_device_t priv 指针未初始化或重复释放 使用 RAII 思想管理 priv 生命周期;close 后置 NULL
camera3_device_ops_t process_capture_request 中死锁或长时间阻塞 使用无锁队列 + 工作线程;设置超时 watchdog
configure_streams 流配置变化时未正确处理已有 buffer 先 flush 再重新配置;保留 stream 状态机
flush flush 未及时返回导致 ANR 设置 flush 超时;异步取消所有待处理请求