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 逻辑。
关键认知: HAL3 接口的核心是“请求-结果”循环。Framework 发送 camera3_capture_request_t,HAL 返回 camera3_capture_result_t。所有设备操作都通过函数指针表完成。
Camera HAL3 架构分层 Framework 层(CameraService / CameraDeviceClient) HAL 接口层 camera_module_t · camera3_device_t · camera3_callback_ops_t Vendor 实现层(Sensor / ISP / 3A 算法)

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 无法正确识别设备能力。
camera_module_t 结构体关系 camera_module_t hw_module_t 函数指针成员(必须实现) • get_number_of_cameras() → 返回相机数量 • get_camera_info() → 填充 camera_info(含 device_version) • set_callbacks() → 注册热插拔回调 • get_vendor_tag_ops() → 自定义 metadata tag 查询 • open_legacy() → HAL1 兼容(可选) • set_torch_mode() → 闪光灯 torch 控制(Android 9+) • init() → 延迟初始化(Android 10+)

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% 的运行时崩溃。
process_capture_request 调用流程 CameraService process_capture_request Vendor HAL 实现 Vendor 实现内部典型处理步骤 ① 校验 request 参数(request_id、settings、output_buffers) ② 解析 settings metadata,提取 3A 参数、AE/AWB 模式等 ③ 将 request 加入内部处理队列 ④ 驱动 sensor 曝光、ISP 处理 ⑤ 通过 camera3_callback_ops_t.notify() 和 process_capture_result() 返回结果

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 会超时
兼容性要点: 在 Android 8.0+ 中,process_capture_result 支持 partial_result 机制。HAL 可以先上报部分 metadata(如仅包含 3A 结果),再上报完整结果。这能降低预览延迟,但必须保证 partial_result 计数正确,否则 Framework 会一直等待。

2.6 平台移植中的常见兼容性陷阱

  1. device_version 不匹配:camera_info.device_version 与 hw_device_t.version 不一致,导致 Framework 拒绝打开设备。
  2. ops 函数指针未全部初始化:新增接口(如 signal_stream_flush)未实现,Framework 调用时崩溃。
  3. metadata tag 缺失:construct_default_request_settings 返回的 metadata 中缺少必要 tag,导致 3A 无法正常工作。
  4. buffer 处理顺序错误:process_capture_result 未按 request_id 顺序上报,导致 Framework 解析错乱。
  5. 回调指针未保存:initialize 中未保存 camera3_callback_ops_t,后续无法上报结果。
严重警告: 在 Android 12+ 中,Framework 增加了对 camera3_device_ops_t 函数指针的严格校验。如果某个函数指针为 nullptr 但 Framework 认为必须实现,会直接返回 -ENODEV 并断开相机连接。移植时务必对照 AOSP 源码中的 camera3.h 版本逐一检查。

2.7 小结

理解 camera_module_t 和 camera3_device_t 的结构是 HAL3 移植的基础。模块入口负责设备枚举和版本声明,设备实例负责具体的捕获流水线控制。平台移植中,90% 的兼容性问题集中在:

  • 版本号填写错误
  • 函数指针未完整实现
  • metadata 内容不完整
  • 回调上报顺序混乱