2. HAL接口规范详解:Camera HAL3核心数据结构
Camera HAL3 接口规范是 Android 相机子系统与硬件抽象层之间的契约。平台移植过程中,绝大多数兼容性问题都源于对核心数据结构的理解偏差或错误实现。本节将深入解析 camera_module_t 与 camera3_device_t 两个关键结构体,帮助开发者建立清晰的接口认知。
2.1 Camera HAL3 架构概览
HAL3 采用流水线式请求-响应模型,相比 HAL1 的静态预览/拍照模式,提供了更灵活的逐帧控制能力。整个架构分为三层:
- Framework 层:CameraService 管理客户端连接,下发 CaptureRequest。
- HAL 接口层:定义
camera_module_t和camera3_device_t等标准结构体。 - Vendor 实现层:芯片厂商实现具体的 sensor 驱动、ISP 算法和 3A 逻辑。
camera3_capture_request_t,HAL 返回 camera3_capture_result_t。所有设备操作都通过函数指针表完成。
2.2 camera_module_t 结构体解析
camera_module_t 是 HAL 模块的入口结构体,定义在 hardware/libhardware/include/hardware/camera_common.h 中。它继承自 hw_module_t,是 Framework 加载 HAL 库后第一个访问的对象。
| 成员 | 类型 | 说明 | 平台移植关注点 |
|---|---|---|---|
common |
hw_module_t |
基础模块信息,包含 tag、module_api_version、hal_api_version、id、name、author、methods 等 | 必须正确填充 hal_api_version 为 HARDWARE_HAL_API_VERSION;id 必须为 CAMERA_HARDWARE_MODULE_ID |
get_number_of_cameras |
函数指针 | 返回设备上可用的 camera 数量 | 返回值必须与 camera_info 数组长度一致;热插拔场景需动态更新 |
get_camera_info |
函数指针 | 填充 camera_info 结构体,包含设备方向、是否可调焦、设备版本等 |
常见问题: device_version 必须设为 HARDWARE_DEVICE_API_VERSION(3, x),否则 Framework 拒绝打开设备 |
set_callbacks |
函数指针 | 注册 HAL 模块级回调(如相机热插拔通知) | Android 8.0+ 必须实现;若不支持热插拔,回调函数可返回 -ENOSYS |
get_vendor_tag_ops |
函数指针 | 提供 vendor 自定义 metadata tag 的查询操作 | 若使用自定义 tag,必须实现此接口;否则 Framework 无法解析 vendor 元数据 |
open_legacy |
函数指针 | 可选接口,用于打开 HAL1 兼容设备 | 若平台同时支持 HAL1/HAL3,需实现此接口;否则返回 -ENOSYS |
set_torch_mode |
函数指针 | 控制闪光灯 torch 模式(Android 9+) | 必须实现;若硬件不支持,返回 -ENOSYS 或 -EINVAL |
init |
函数指针 | 模块初始化(Android 10+) | 用于延迟初始化;若不需要,可设为 nullptr |
get_camera_info 中错误地设置了 device_version。例如将 HAL3 设备版本设为 HARDWARE_DEVICE_API_VERSION(3, 0) 而非 HARDWARE_DEVICE_API_VERSION(3, 3)(对应 Android 8.0+),导致 Framework 无法正确识别设备能力。
2.3 camera3_device_t 结构体解析
camera3_device_t 是 HAL3 设备实例的核心结构体,定义在 hardware/libhardware/include/hardware/camera3.h 中。它继承自 hw_device_t,包含一个关键成员 ops——指向 camera3_device_ops_t 函数指针表。
| 成员 | 类型 | 说明 | 平台移植关注点 |
|---|---|---|---|
common |
hw_device_t |
基础设备信息,包含 tag、version、module、close 函数指针等 | close 函数指针必须实现;version 必须与 camera_info.device_version 一致 |
ops |
camera3_device_ops_t* |
设备操作函数指针表,包含 initialize、configure_streams、process_capture_request 等 | 核心接口: 所有函数指针必须非空;Framework 直接通过此表调用 HAL |
priv |
void* |
私有数据指针,HAL 实现方用于关联设备上下文 | 通常指向自定义的设备结构体(如 camera_device_impl_t) |
2.4 camera3_device_ops_t 核心函数指针
camera3_device_ops_t 是 HAL3 设备操作的核心,包含约 20 个函数指针。以下列出平台移植中必须正确实现的 8 个关键接口:
| 函数指针 | 调用时机 | 典型移植问题 |
|---|---|---|
initialize |
打开设备后立即调用 | 未正确保存 camera3_callback_ops_t 回调指针,导致后续结果无法上报 |
configure_streams |
每次配置流时调用(如切换预览/拍照) | 未正确处理 hal_pixel_format 映射;stream 数量超过硬件限制时未返回错误 |
register_stream_buffers |
配置流后注册 buffer 句柄(Android 8.0+ 已废弃) | 新平台可返回 -ENOSYS;旧平台必须实现 |
process_capture_request |
每次捕获请求下发时调用 | 最常见问题: 未正确处理 input_buffer( reprocess 场景);未校验 settings 是否为 nullptr |
flush |
快速关闭所有正在处理的请求 | 未实现或实现不完整,导致相机关闭时 ANR |
dump |
dumpsys 时调用 | 未输出关键调试信息,增加问题排查难度 |
construct_default_request_settings |
创建默认请求模板时调用 | 返回的 metadata 中缺少必要 tag(如 ANDROID_SENSOR_FRAME_DURATION) |
signal_stream_flush |
流 flush 通知(Android 10+) | 新接口未实现,导致 Framework 无法正确处理流切换 |
process_capture_request 入口处添加参数校验:检查 request 非空、settings 非空(除非是 reprocess 场景)、output_buffers 中每个 buffer 的 stream 指针有效。这能避免 90% 的运行时崩溃。
2.5 camera3_callback_ops_t:结果上报通道
camera3_callback_ops_t 是 Framework 提供给 HAL 的回调接口,HAL 通过它上报捕获结果、通知事件和 buffer 状态。该结构体在 initialize 时传入,HAL 必须保存此指针。
| 回调函数 | 用途 | 移植注意事项 |
|---|---|---|
process_capture_result |
上报捕获结果(metadata + output buffers) | 必须按 request 顺序上报;partial_result 用于分阶段上报 |
notify |
上报事件通知(如快门、错误、请求完成) | 错误事件必须及时上报,否则 Framework 会超时 |
process_capture_result 支持 partial_result 机制。HAL 可以先上报部分 metadata(如仅包含 3A 结果),再上报完整结果。这能降低预览延迟,但必须保证 partial_result 计数正确,否则 Framework 会一直等待。
2.6 平台移植中的常见兼容性陷阱
- device_version 不匹配:
camera_info.device_version与hw_device_t.version不一致,导致 Framework 拒绝打开设备。 - ops 函数指针未全部初始化:新增接口(如
signal_stream_flush)未实现,Framework 调用时崩溃。 - metadata tag 缺失:
construct_default_request_settings返回的 metadata 中缺少必要 tag,导致 3A 无法正常工作。 - buffer 处理顺序错误:
process_capture_result未按 request_id 顺序上报,导致 Framework 解析错乱。 - 回调指针未保存:
initialize中未保存camera3_callback_ops_t,后续无法上报结果。
camera3_device_ops_t 函数指针的严格校验。如果某个函数指针为 nullptr 但 Framework 认为必须实现,会直接返回 -ENODEV 并断开相机连接。移植时务必对照 AOSP 源码中的 camera3.h 版本逐一检查。
2.7 小结
理解 camera_module_t 和 camera3_device_t 的结构是 HAL3 移植的基础。模块入口负责设备枚举和版本声明,设备实例负责具体的捕获流水线控制。平台移植中,90% 的兼容性问题集中在:
- 版本号填写错误
- 函数指针未完整实现
- metadata 内容不完整
- 回调上报顺序混乱