3. Camera HAL 基础数据结构:核心结构体解析

Camera HAL 层是 Android 相机框架中连接 Framework 与硬件驱动的关键桥梁。理解其核心数据结构,是进行驱动调试与性能优化的第一步。本章将深入解析 camera_module_t、camera_device_t 和 camera3_device_t 三个最基础的结构体,阐明它们在 HAL 架构中的角色、成员含义及初始化流程。

3.1 结构体总览与层级关系

在 Android Camera HAL 中,这三个结构体构成了从模块加载到设备操作的完整链路:

  • camera_module_t:HAL 模块的入口,负责枚举相机设备并创建实例。
  • camera_device_t:HAL v1 接口的设备抽象,代表一个物理或逻辑相机。
  • camera3_device_t:HAL v3 接口的设备抽象,支持更复杂的 pipeline 和 metadata 流。
调试要点: 在调试过程中,首先需要确认 HAL 库导出的 HAL_MODULE_INFO_SYM 符号是否正确初始化了 camera_module_t,这是 Framework 加载 HAL 的第一步。
Camera HAL 核心结构体层级关系 Camera HAL 核心结构体层级关系 camera_module_t camera_device_t (HAL v1) camera3_device_t (HAL v3) 物理 / 逻辑 Camera 硬件 说明:camera_module_t 负责发现设备,camera_device_t / camera3_device_t 负责具体操作。

3.2 camera_module_t:HAL 模块入口

camera_module_t 定义在 hardware/libhardware/include/hardware/camera_common.h 中,是 HAL 模块的标准接口。它继承自 hw_module_t,并扩展了相机特有的方法。

成员 类型 说明
common hw_module_t 标准 HAL 模块头,包含 tag、module_api_version、hal_api_version、id、name、author、methods 等。
get_number_of_cameras 函数指针 返回系统中可用的相机设备数量。
get_camera_info 函数指针 获取指定 ID 相机的静态信息(camera_info),包括朝向、是否支持闪光灯等。
set_callbacks 函数指针 注册 HAL 回调函数(如相机热插拔通知),仅 HAL v3 及以上版本使用。
get_vendor_tag_ops 函数指针 获取厂商自定义 metadata tag 的操作接口。
open_legacy 函数指针 以指定 HAL 版本打开相机设备(用于兼容旧版)。
set_torch_mode 函数指针 设置闪光灯 torch 模式,独立于相机打开状态。
init 函数指针 HAL 模块初始化函数,在模块加载时调用。
关键调试点: 在 get_camera_info 中返回的 camera_info.device_version 字段决定了 Framework 使用 HAL v1 还是 v3 接口。如果该值设置错误,会导致设备无法打开或功能异常。

3.3 camera_device_t:HAL v1 设备抽象

camera_device_t 是 Android Camera HAL v1 接口的核心,定义在 hardware/libhardware/include/hardware/camera.h 中。它封装了相机设备的操作句柄和所有控制方法。

typedef struct camera_device {
    hw_device_t common;                     // 标准设备头
    camera_device_ops_t *ops;               // 操作函数表
    void *priv;                             // 私有数据指针,指向驱动上下文
} camera_device_t;

核心成员解析:

  • common:继承自 hw_device_t,包含设备打开/关闭、版本号等基础信息。
  • ops:指向 camera_device_ops_t 结构体,该结构体包含约 30 个函数指针,如 set_preview_window、start_preview、take_picture 等。
  • priv:通常指向驱动自定义的上下文结构体,用于保存设备状态、流信息等。
常见陷阱: 在 HAL v1 实现中,ops 中的函数指针必须全部正确赋值,否则 Framework 调用未初始化的函数指针会导致空指针崩溃。建议在初始化时使用 memset 清零后逐一赋值。

3.4 camera3_device_t:HAL v3 设备抽象

camera3_device_t 是 HAL v3 接口的设备抽象,定义在 hardware/libhardware/include/hardware/camera3.h 中。相比 v1,v3 接口更加灵活,支持复杂的 capture session 和 metadata 流控制。

typedef struct camera3_device {
    hw_device_t common;                     // 标准设备头
    camera3_device_ops_t *ops;              // v3 操作函数表
    void *priv;                             // 私有数据指针
} camera3_device_t;

与 v1 的关键差异:

对比维度 camera_device_t (v1) camera3_device_t (v3)
操作模型 基于预览/拍照/录像的固定流程 基于 request/result 的 pipeline 模型
数据传递 直接操作 buffer 地址 通过 camera3_stream_buffer 和 metadata
同步机制 简单回调 支持 fence 和 release fence 同步
核心函数 start_preview、take_picture process_capture_request、flush
设备打开函数 camera_device_open camera3_device_open
HAL v1 vs v3 设备操作流程对比 HAL v1 vs v3 设备操作流程对比 HAL v1 流程 1. open() → 获取 camera_device_t 2. set_preview_window() 3. start_preview() / take_picture() 4. close() HAL v3 流程 1. open() → 获取 camera3_device_t 2. configure_streams() 3. process_capture_request() 循环 4. flush() → close() 说明:v3 流程通过 process_capture_request 循环处理多个并发 request,支持更灵活的流配置。

3.5 结构体初始化与生命周期

在 HAL 实现中,这三个结构体的初始化遵循严格的顺序:

  1. 模块加载阶段:HAL_MODULE_INFO_SYM 静态初始化 camera_module_t,填充 common.methods 指向 hw_module_methods_t。
  2. 设备打开阶段:Framework 调用 camera_module_t.common.methods->open(),HAL 内部创建并初始化 camera_device_t 或 camera3_device_t。
  3. 设备使用阶段:通过 ops 中的函数指针进行预览、拍照、录像等操作。
  4. 设备关闭阶段:调用 close() 释放资源,销毁设备结构体。
优化建议: 在 open() 函数中,建议使用 calloc 分配设备结构体内存,确保所有字段初始化为零,避免未初始化字段导致的不确定行为。同时,priv 指针指向的上下文结构体应包含互斥锁,以保护多线程访问。

3.6 调试实战:验证结构体正确性

在调试 Camera HAL 时,可以通过以下方法验证结构体的正确性:

  • 检查模块符号:使用 dlopen 和 dlsym 加载 HAL 库,验证 HAL_MODULE_INFO_SYM 是否指向有效的 camera_module_t。
  • 验证函数指针:在 open() 返回前,打印 ops 中关键函数指针的地址,确保不为 NULL。
  • 检查版本号:确认 common.module_api_version 和 common.hal_api_version 与预期匹配。
  • 使用 log 追踪:在 get_camera_info、open、close 等关键函数中添加 ALOGV/ALOGD 日志,追踪调用流程。
常见错误: 如果 camera_module_t 中的 get_number_of_cameras 返回 0,Framework 将认为系统没有相机设备,导致相机应用无法启动。请确保该函数返回正确的相机数量。