3. Camera HAL层核心数据结构详解

Camera HAL层是Android相机框架中连接Framework与底层硬件驱动的关键桥梁。理解其核心数据结构是进行HAL层开发与调试的基础。本章将详细剖析camera_module_t、camera_device_t、camera3_device_t、camera3_stream_t等关键结构体的定义、成员含义及相互关系。

3.1 结构体总览与层次关系

Camera HAL层的数据结构遵循从模块到设备、再到流和缓冲区的层次化设计。下图展示了核心结构体之间的调用与包含关系:

Camera HAL核心数据结构层次关系 camera_module_t 模块级接口,管理多个Camera设备 camera_device_t HAL1设备结构体 camera3_device_t HAL3设备结构体 camera3_stream_t 流描述结构体(图像流配置) buffer_handle_t 图形缓冲区句柄 说明:HAL3设备结构体(camera3_device_t)是当前主流架构,替代了HAL1的camera_device_t

3.2 camera_module_t:模块级入口

camera_module_t是HAL模块的顶层结构体,定义在hardware/libhardware/include/hardware/camera_common.h中。它继承自hw_module_t,是Framework加载HAL库时首先获取的对象。

成员 类型 说明
common hw_module_t 标准硬件模块结构体,包含模块ID、版本号、作者等信息
get_number_of_cameras 函数指针 返回系统中可用的Camera设备数量
get_camera_info 函数指针 获取指定Camera设备的静态信息(camera_info_t)
set_callbacks 函数指针 注册HAL模块回调函数(HAL3特有)
get_vendor_tag_ops 函数指针 获取厂商自定义标签操作接口
open_legacy 函数指针 以HAL1兼容模式打开Camera设备(可选)
set_torch_mode 函数指针 设置闪光灯手电筒模式
init 函数指针 模块初始化函数(HAL3.4+)

调试要点:当Camera HAL模块无法加载时,首先检查camera_module_t中的common.module_api_version是否正确。HAL3要求版本号至少为CAMERA_MODULE_API_VERSION_2_4。若版本不匹配,Framework将拒绝加载该模块。

3.3 camera_device_t:HAL1设备结构体

camera_device_t是HAL1架构下的设备结构体,定义在hardware/libhardware/include/hardware/camera.h中。它继承自hw_device_t,代表一个具体的Camera物理设备。

typedef struct camera_device {
    hw_device_t common;                    // 标准硬件设备结构体
    camera_device_ops_t *ops;              // 设备操作函数指针表
    void *priv;                            // 私有数据指针,指向HAL实现内部结构
} camera_device_t;

关键成员解析:

  • common:包含设备打开/关闭、版本号等基础信息。
  • ops:指向camera_device_ops_t结构体,包含预览、拍照、参数设置等操作函数。
  • priv:HAL实现者自定义的私有数据结构,通常包含设备状态、传感器信息等。

常见问题:在HAL1中,ops中的函数指针必须全部正确初始化,否则调用时会导致空指针异常。调试时建议在HAL实现中增加日志,打印ops各成员的地址,确保无NULL指针。

3.4 camera3_device_t:HAL3设备结构体

camera3_device_t是HAL3架构的核心设备结构体,定义在hardware/libhardware/include/hardware/camera3.h中。它替代了HAL1的camera_device_t,支持更灵活的请求-结果模型。

typedef struct camera3_device {
    hw_device_t common;                    // 标准硬件设备结构体
    camera3_device_ops_t *ops;             // HAL3设备操作函数指针表
    void *priv;                            // 私有数据指针
} camera3_device_t;

与camera_device_t的核心差异:

对比维度 camera_device_t (HAL1) camera3_device_t (HAL3)
操作模型 同步调用,函数直接返回结果 异步请求-结果模型,通过回调返回
流管理 固定流配置,预览/拍照分离 动态流配置,支持多流并行
缓冲区管理 HAL内部管理缓冲区 Framework管理缓冲区,HAL通过dequeue/queue操作
元数据 使用camera_parm_t结构体 使用camera_metadata_t(基于key-value的元数据包)
主要操作接口 set_parm/get_parm/preview/take_picture configure_streams/process_capture_request/flush

开发建议:在HAL3实现中,camera3_device_ops_t包含initialize、configure_streams、process_capture_request、flush等关键函数。其中configure_streams是调试高频点,需确保返回的流配置与Framework请求一致。

3.5 camera3_stream_t:流描述结构体

camera3_stream_t是HAL3中描述图像流的核心结构体,定义在camera3.h中。它定义了流的格式、尺寸、方向等属性,是configure_streams和process_capture_request之间的数据契约。

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;                  // 最大缓冲区数量(由HAL设置)
    void *priv;                            // 私有数据指针
    android_dataspace_t data_space;        // 数据空间(颜色空间、动态范围等)
    int rotation;                          // 旋转角度:0/90/180/270
    int stream_configuration;              // 流配置类型(HAL3.3+)
    const camera_metadata_t *physical_camera_id; // 物理Camera ID(多摄场景)
} camera3_stream_t;

流类型说明:

  • CAMERA3_STREAM_OUTPUT:输出流,数据从Camera HAL流向Framework(预览、拍照、录像)。
  • CAMERA3_STREAM_INPUT:输入流,数据从Framework流向Camera HAL(如YUV重处理)。
  • CAMERA3_STREAM_BIDIRECTIONAL:双向流,支持输入和输出(如ZSL场景)。

调试要点:在configure_streams回调中,Framework会传入一个camera3_stream_t数组。HAL实现必须检查每个流的format和usage是否支持。若某个流不被支持,需返回-EINVAL并打印日志。常见不支持的格式包括HAL_PIXEL_FORMAT_RAW10(部分ISP不支持)和HAL_PIXEL_FORMAT_BLOB(JPEG输出)。

3.6 结构体协作流程:从配置到捕获

下图展示了HAL3中核心结构体在典型拍照流程中的协作关系:

HAL3核心结构体协作流程(拍照场景) 1. open() 创建camera3_device_t 2. configure_streams() 配置camera3_stream_t数组 3. process_capture_request() 提交捕获请求 4. HAL处理请求 填充缓冲区,生成结果元数据 5. 回调通知 process_capture_result() 6. Framework接收结果 解析camera3_capture_result,提取图像数据和元数据 关键点:camera3_stream_t在步骤2中配置,在步骤3-6中作为数据通道使用 每个流对应一个缓冲区队列,HAL通过dequeue_buffer/queue_buffer操作管理

3.7 常见调试问题与排查方法

问题现象 可能原因 排查方法
HAL模块加载失败 camera_module_t.common.module_api_version版本过低 检查版本号是否≥CAMERA_MODULE_API_VERSION_2_4
configure_streams返回错误 流格式/尺寸不支持,或max_buffers设置不合理 打印所有流的format/width/height,对照ISP能力表
预览黑屏 camera3_stream_t.usage缺少GRALLOC_USAGE_HW_COMPOSER标志 检查usage标志位,确保包含显示相关标志
拍照无JPEG输出 JPEG流格式错误或data_space未正确设置 确认format为HAL_PIXEL_FORMAT_BLOB,data_space为HAL_DATASPACE_V0_JFIF
多摄切换失败 physical_camera_id未正确设置或与逻辑Camera不匹配 打印physical_camera_id,验证与底层传感器ID对应关系

调试工具推荐:使用adb shell dumpsys media.camera查看Camera服务状态,使用logcat -s CameraHal过滤HAL层日志。在HAL实现中增加ALOGD打印关键结构体成员值,是定位问题的最直接手段。

3.8 结构体内存布局与对齐注意事项

在嵌入式平台上,结构体的内存对齐可能影响跨进程通信和性能。以下为关键注意事项:

  • 指针大小:camera3_device_t中的ops和priv在32位平台占4字节,64位平台占8字节。跨架构编译时需注意。
  • 结构体填充:camera3_stream_t包含多个32位和64位成员,编译器可能插入填充字节。建议使用__attribute__((packed))或显式填充字段。
  • 版本兼容:不同HAL版本的结构体成员可能不同。例如camera3_stream_t在HAL3.3中新增了physical_camera_id字段。使用sizeof()检查结构体大小可快速判断版本。
// 检查结构体大小的调试代码示例
ALOGD("camera3_stream_t size: %zu", sizeof(camera3_stream_t));
ALOGD("camera3_device_t size: %zu", sizeof(camera3_device_t));
ALOGD("camera_module_t size: %zu", sizeof(camera_module_t));

重要提醒:在HAL实现中,切勿直接修改Framework传入的camera3_stream_t结构体成员(如width、format)。这些成员由Framework设置,HAL只能读取。若需要调整流参数,应在configure_streams中返回新的配置,或通过camera3_stream_configuration中的operation_mode字段协商。