3. Camera HAL 关键数据结构详解
Camera HAL 层通过一组标准化的数据结构实现 Framework 与硬件驱动的解耦。理解这些结构体是定位 HAL 层问题的前提。本章逐一拆解 camera_module_t、camera_device_t、camera3_device_t 和 camera3_callback_ops_t 的核心字段、生命周期与常见故障点。
3.1 数据结构总览与层级关系
四个结构体在 HAL 架构中分别承担模块加载、设备抽象、Camera 3 设备接口、回调通知的角色。其调用关系如下:
关键原则: Framework 通过
camera_module_t 枚举设备,通过 camera3_device_t 下发请求,通过 camera3_callback_ops_t 接收结果。任何一层的空指针、未初始化或回调缺失都会导致相机服务崩溃或预览黑屏。
3.2 camera_module_t —— HAL 模块入口
camera_module_t 定义在 hardware/libhardware/include/hardware/camera_common.h 中,是 HAL 模块的顶层接口。Framework 通过 hw_get_module() 获取该结构体指针。
| 字段 | 类型 | 说明 | 常见问题 |
|---|---|---|---|
| common | hw_module_t | 标准 HAL 模块头,包含 module_api_version | 版本号不匹配导致加载失败 |
| get_number_of_cameras | 函数指针 | 返回设备上可用的摄像头数量 | 返回 0 或负值 → 枚举失败 |
| get_camera_info | 函数指针 | 填充 camera_info 结构体,包含设备方向、静态信息 | info 字段未初始化 → 空指针崩溃 |
| set_callbacks | 函数指针 | 注册 HAL 模块级回调(如摄像头热插拔通知) | 未实现 → 热插拔事件丢失 |
| get_vendor_tag_ops | 函数指针 | 提供厂商自定义 metadata tag 的查询接口 | 返回空 → 厂商 tag 无法解析 |
| open_legacy | 函数指针 | 打开 Camera 1.x 兼容设备(可选) | 未实现时调用返回 -ENOSYS |
排查技巧: 当 logcat 中出现
get_number_of_cameras: error -1 或 Failed to open camera HAL 时,优先检查 camera_module_t 的 common.module_api_version 是否与 Framework 期望的 HAL_MODULE_API_VERSION(2,4) 一致。
3.3 camera_device_t —— Camera 1.x 设备接口
camera_device_t 是 Camera 1.x HAL 的设备抽象层,在 Camera 3 HAL 中作为遗留兼容路径存在。其核心字段如下:
typedef struct camera_device {
hw_device_t common; // 标准设备头
camera_device_ops_t *ops; // 操作函数表
void *priv; // HAL 私有数据指针
} camera_device_t;
camera_device_ops_t 包含约 30 个函数指针,覆盖预览、拍照、参数设置、内存管理等。调试中重点关注:
- set_preview_window:绑定 Surface 到 HAL,失败会导致预览黑屏。
- start_preview / stop_preview:预览启停,未正确实现会导致 ANR。
- take_picture:拍照触发,返回 JPEG 数据。
- set_parameters:参数设置入口,格式错误会静默失败。
注意: 在 Camera 3 HAL 实现中,
camera_device_t 通常只作为过渡层存在。如果 open_legacy 返回的 ops 表中有空函数指针,调用时直接段错误。
3.4 camera3_device_t —— Camera 3 核心设备接口
camera3_device_t 是 Camera 3.x HAL 的设备抽象,定义在 camera3.h 中。它替代了 camera_device_ops_t 的庞大函数表,采用精简的 ops 结构:
typedef struct camera3_device {
hw_device_t common; // 标准设备头
camera3_device_ops_t *ops; // Camera 3 操作函数表
void *priv; // HAL 私有数据
} camera3_device_t;
camera3_device_ops_t 包含以下关键函数:
| 函数 | 触发时机 | 典型故障 |
|---|---|---|
| initialize | Framework 打开设备后立即调用 | callback_ops 为空 → 返回 -EINVAL |
| configure_streams | 应用设置预览/拍照分辨率时 | 流格式不支持 → 返回 -EINVAL |
| construct_default_request_settings | 创建默认 capture request 模板 | 返回 NULL → 相机无法启动 |
| process_capture_request | 下发拍照/预览请求 | 未及时返回 → 预览卡顿 |
| flush | 快速关闭所有未完成请求 | 未实现 → 关闭延迟 |
| dump | dumpsys 调用时输出 HAL 状态 | 未实现 → 调试信息缺失 |
调试黄金法则: 当 Camera 3 HAL 出现
configure_streams 失败时,检查 camera3_stream_t.format 是否在 HAL 的 get_supported_formats() 列表中。常见不支持的格式包括 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED 与 YCbCr_420_SP 的混用。
3.5 camera3_callback_ops_t —— 结果回调通道
camera3_callback_ops_t 是 Framework 注册给 HAL 的回调接口,HAL 通过它返回捕获结果和通知事件。定义如下:
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;
两个回调函数的作用与故障模式:
- process_capture_result:返回一帧的 metadata 和图像缓冲区。如果 HAL 不调用此回调,Framework 会一直等待,导致预览超时 ANR。
- notify:发送错误、快门、请求完成等事件。例如
CAMERA3_MSG_ERROR_REQUEST表示某请求处理失败。
排查案例: 某项目预览黑屏,logcat 无错误。通过加 log 发现
process_capture_result 中 result->output_buffers 的 release_fence 始终为 -1,且 status 为 CAMERA3_BUFFER_STATUS_ERROR。原因是 ISP 驱动未正确填充缓冲区,导致 HAL 跳过回调。
3.6 数据结构对比总结
| 结构体 | 所属 HAL 版本 | 核心职责 | 初始化时机 | 常见崩溃原因 |
|---|---|---|---|---|
| camera_module_t | 1.x / 3.x | 模块加载与设备枚举 | 进程启动时 | so 加载失败、版本号不匹配 |
| camera_device_t | 1.x | 设备操作接口(ops 表) | open() 调用时 | ops 表空指针、set_preview_window 失败 |
| camera3_device_t | 3.x | 精简设备接口 | open() 调用时 | configure_streams 返回错误 |
| camera3_callback_ops_t | 3.x | 结果与事件回调 | initialize() 时注册 | 未实现回调、回调中空指针解引用 |
3.7 调试 Checklist
当遇到 Camera HAL 相关问题时,按以下顺序检查数据结构:
- camera_module_t:确认
get_number_of_cameras返回值 > 0,get_camera_info填充了正确的设备方向。 - camera3_device_t:确认
ops指针非空,initialize被调用且 callback_ops 已保存。 - configure_streams:检查流格式、分辨率、usage 标志是否在 HAL 支持范围内。
- process_capture_request:确认 HAL 在收到请求后调用了
process_capture_result。 - camera3_callback_ops_t:确认
notify回调在错误时被正确调用,且process_capture_result中的status字段为OK。
常见陷阱: 部分 HAL 实现中
camera3_device_t.priv 指向内部状态结构体。如果 initialize 时未正确初始化 priv,后续所有 ops 调用都会访问野指针。建议在 initialize 入口处加 log 打印 priv 地址。