3. 初始化流程:open()接口实现、initialize()接口实现、设备能力查询

Camera HAL3 的初始化流程是上层框架与底层硬件驱动建立通信通道的关键阶段。该流程涉及三个核心步骤:设备节点打开(open())、会话初始化(initialize())以及设备静态能力查询(getCameraCharacteristics())。本章将逐一剖析每个接口的实现要点、数据流走向以及常见适配陷阱。

3.1 open() 接口实现

open() 是 HAL3 模块中第一个被调用的接口,其职责是打开指定 cameraId 对应的硬件设备,并返回一个 camera3_device_t 结构体指针,供后续操作使用。

3.1.1 接口原型与调用时机

int (*open)(const struct hw_module_t* module, const char* id,
            struct hw_device_t** device);

调用时机:CameraService 启动后,通过 hw_get_module() 加载 HAL 模块,随即遍历可用 cameraId,对每个逻辑摄像头调用一次 open()。

3.1.2 实现要点

实现步骤 说明 常见错误
1. 参数校验 检查 module、id、device 指针非空;验证 cameraId 是否在支持范围内 未校验空指针导致空引用崩溃
2. 设备上下文分配 malloc 或 new 一个私有设备结构体(如 camera3_device_t 的包装类),包含打开的文件描述符、同步锁、状态机等 内存泄漏或未初始化成员变量
3. 硬件驱动打开 通过 V4L2、MIPI CSI 或私有驱动接口打开物理摄像头设备节点 驱动节点权限不足或设备忙
4. 回调函数注册 将 HAL3 定义的 camera3_device_ops_t 函数表赋值给设备结构体 函数表未完全填充导致调用空函数指针
5. 返回设备句柄 将 camera3_device_t* 转型为 hw_device_t* 返回 类型转换错误或返回野指针
关键提示: open() 调用可能发生在不同线程上下文中,建议在设备上下文内使用 std::mutex 或 pthread_mutex_t 保护共享状态,防止竞态条件。

3.2 initialize() 接口实现

initialize() 是 camera3_device_ops_t 中的第一个操作接口,用于建立 HAL 与 CameraService 之间的回调通道,并完成流配置前的准备工作。

3.2.1 接口原型

int (*initialize)(const struct camera3_device *device,
                  const camera3_callback_ops_t *callback_ops);

3.2.2 核心职责

  • 保存回调函数表: 将 callback_ops 指针保存到设备上下文中,后续通过该指针上报事件(如 notify()、process_capture_result())。
  • 初始化流管理模块: 清空或重置流列表,准备接收 configure_streams() 调用。
  • 启动传感器预览(可选): 部分硬件需要在 initialize 阶段启动传感器时钟或 MIPI 链路,以缩短后续配置延迟。
  • 资源预分配: 分配 buffer 管理池、请求队列、统计信息缓冲区等。

3.2.3 实现流程图

initialize() 接口实现流程 initialize() 接口实现流程 收到 initialize 调用 保存 callback_ops 指针 初始化流管理模块 启动传感器时钟/链路 资源预分配 返回 0 (成功) 注意 callback_ops 必须深拷贝 或确保其生命周期有效 避免野指针回调
最佳实践: 在 initialize() 中不要执行耗时超过 100ms 的操作,否则可能导致 CameraService 触发 ANR。建议将传感器预热等操作异步化。

3.3 设备能力查询

设备能力查询通过 getCameraCharacteristics() 接口实现,返回一个包含摄像头所有静态元数据的 camera_metadata_t 结构体。该查询在 open() 之后、configure_streams() 之前被调用,用于指导上层应用选择合理的配置参数。

3.3.1 关键元数据项

Tag 名称 类型 说明 适配要求
ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL byte 硬件支持级别(LIMITED/FULL/LEVEL_3) 必须正确声明,影响框架行为
ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE int32[2] 有效像素阵列宽高 与实际 sensor 输出一致
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS int32[] 支持的输出/输入流格式与分辨率组合 必须包含至少一组 YUV_420_888 和 JPEG
ANDROID_REQUEST_AVAILABLE_CAPABILITIES int64[] 设备支持的能力(如 RAW、BURST_CAPTURE、MANUAL_SENSOR) 按实际硬件能力声明
ANDROID_SYNC_MAX_LATENCY int32 最大帧同步延迟(PER_FRAME_CONTROL / UNKNOWN) 影响 3A 策略选择

3.3.2 能力查询实现步骤

  1. 创建元数据构建器: 使用 allocate_camera_metadata() 或 camera_metadata_t 辅助类分配初始缓冲区。
  2. 填充静态元数据: 从硬件驱动读取 sensor 特性、ISP 能力、闪光灯信息等,逐项写入元数据。
  3. 校验必填项: 确保所有 android.*.info 和 android.*.available* 标签已正确设置。
  4. 返回元数据指针: 将构建完成的 camera_metadata_t* 返回给框架,框架负责释放。

3.3.3 能力查询数据流

设备能力查询数据流 设备能力查询数据流 CameraService HAL getCharacteristics 硬件驱动 camera_metadata_t 请求能力 读取 sensor 参数 返回数据 构建元数据 返回给框架
常见适配陷阱:
  • 元数据不一致: ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS 中声明的分辨率,必须在 configure_streams() 时实际支持,否则会导致流配置失败。
  • 硬件级别误报: 将 LIMITED 级别设备声明为 FULL,会导致框架下发 MANUAL_SENSOR 请求,而硬件无法处理,引发崩溃。
  • 内存泄漏: 每次 getCameraCharacteristics() 调用都应返回新分配的元数据,框架负责释放;HAL 侧不应缓存同一指针重复返回。

3.4 初始化流程总结

阶段 接口 核心产出 耗时要求
设备打开 open() camera3_device_t 设备句柄 < 500ms
会话初始化 initialize() 回调通道建立、资源预分配 < 100ms
能力查询 getCameraCharacteristics() camera_metadata_t 静态元数据 < 50ms

三个接口按序执行,构成完整的初始化链路。任何一个环节的异常都会导致 Camera HAL 无法正常提供服务。在适配过程中,建议为每个接口添加详细的日志输出(使用 ALOGD 或 ALOGE),便于定位初始化失败的具体原因。