4. Camera HAL3 初始化流程:open()、init()、configure_streams()、construct_default_request_settings()

Camera HAL3 的初始化流程是相机应用从启动到能够正常预览和拍照的关键路径。该流程涉及 Framework 层与 HAL 层之间的多次双向交互,核心接口包括 open()、init()、configure_streams() 和 construct_default_request_settings()。理解这些接口的调用顺序、参数含义和实现要点,是开发稳定、高性能相机 HAL 的基础。

核心要点:HAL3 初始化流程是典型的“打开设备 → 初始化管道 → 配置数据流 → 获取默认模板”四步走模式。每一步都依赖前一步的完成状态,任何一步失败都会导致相机服务无法正常启动。

4.1 初始化流程总览

下图展示了 Camera HAL3 初始化过程中 Framework 与 HAL 之间的主要交互节点和调用顺序:

Camera HAL3 初始化流程总览 CameraService CameraDeviceClient Camera3Device camera_module_t camera3_device_t camera3_ops_t ① open() ② init() ③ configure_streams() ④ construct_default_request_settings() 返回 camera_metadata_t* 流程说明: 1. CameraService 通过 HAL Module 调用 open() 打开指定 cameraId 的设备 2. Camera3Device 调用 init() 初始化相机管道,完成传感器和 ISP 的准备工作 3. 应用层下发数据流配置请求,HAL 通过 configure_streams() 配置输出流 4. Framework 获取默认请求模板,用于构造后续的 CaptureRequest

4.2 open():打开相机设备

open() 是 HAL3 初始化流程的入口点,由 camera_module_t 结构体中的 open() 函数指针实现。Framework 通过该接口获取指定 cameraId 的设备句柄。

4.2.1 接口定义

typedef struct camera_module {
    // ... 其他成员
    int (*open)(const struct hw_module_t* module,
                const char* id,
                struct hw_device_t** device);
} camera_module_t;

4.2.2 实现要点

  • 参数校验:检查 id 是否合法,确保 cameraId 在支持的范围内
  • 设备分配:为 camera3_device_t 分配内存,并填充 common 结构体中的版本号、模块句柄、关闭函数等字段
  • ops 注册:将 camera3_ops_t 中的函数指针(包括 initialize()、configure_streams() 等)注册到设备结构体中
  • 硬件初始化:完成传感器、电源管理等底层硬件的上电和复位操作
  • 互斥保护:防止同一 cameraId 被重复打开,需加锁保护
常见陷阱:部分 HAL 实现在 open() 中执行了过多的耗时操作(如加载固件、校准数据解析),导致应用层 ANR。建议将非关键初始化延迟到 init() 或第一次 configure_streams() 时执行。

4.3 init():初始化相机管道

init() 对应 camera3_ops_t 中的 initialize() 函数。该接口在 open() 之后被调用,用于建立 Framework 与 HAL 之间的回调通道,并完成相机管道的初始化。

4.3.1 接口定义

typedef struct camera3_callback_ops {
    void (*notify)(const camera3_notify_msg_t *msg);
    void (*process_capture_result)(const camera3_capture_result_t *result);
    void (*process_capture_result_async)(
            const camera3_capture_result_t *result);
} camera3_callback_ops_t;

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

4.3.2 回调注册

callback_ops 是 Framework 向 HAL 注册的回调函数集合,HAL 通过它们将异步事件和结果返回给 Framework:

回调函数 触发时机 用途
notify() 快门事件、错误事件 通知 Framework 快门开始、曝光完成或设备错误
process_capture_result() 每一帧捕获完成 返回 metadata 和图像缓冲区给 Framework
process_capture_result_async() 部分结果可用时 支持 partial result,减少首帧延迟

4.3.3 初始化工作

  • 保存回调指针:将 callback_ops 保存到 HAL 内部,用于后续上报事件和结果
  • 传感器校准:加载 AWB、AE、AF 算法的校准参数
  • ISP 初始化:配置图像信号处理器的初始状态
  • 内存池预分配:为后续的 request 和 result 分配初始内存
  • 状态机迁移:将设备状态从 OPENED 迁移到 INITIALIZED
最佳实践:init() 中应避免分配大量内存或执行阻塞式 I/O 操作。如果传感器校准数据需要从文件系统加载,建议使用异步加载或延迟加载策略。

4.4 configure_streams():配置数据流

configure_streams() 是 HAL3 初始化流程中最关键的接口之一。应用层通过该接口告知 HAL 需要哪些数据流(预览流、拍照流、视频流等),HAL 据此配置 ISP、传感器输出格式和缓冲区分配策略。

4.4.1 接口定义

int (*configure_streams)(const struct camera3_device *device,
                         camera3_stream_configuration_t *stream_list);

4.4.2 数据结构

typedef struct camera3_stream_configuration {
    uint32_t num_streams;           // 流数量
    camera3_stream_t **streams;     // 流数组指针
    uint32_t operation_mode;        // 操作模式
    const camera_metadata_t *session_parameters; // 会话参数
} camera3_stream_configuration_t;

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;                     // HAL 私有数据
    uint32_t data_space;            // 色彩空间
    int rotation;                   // 旋转角度
    int crop_rect[4];               // 裁剪矩形
} camera3_stream_t;

4.4.3 配置流程

  1. 校验流参数:检查 width、height、format 是否在传感器支持的范围内
  2. 计算 max_buffers:根据流类型和硬件能力,设置每个流所需的缓冲区数量
  3. 配置 ISP 管线:根据所有流的组合,重新配置 ISP 的缩放、裁剪、格式转换模块
  4. 分配图形缓冲区:通过 Gralloc 分配输出流所需的缓冲区
  5. 更新传感器模式:根据最大分辨率流设置传感器的输出尺寸和帧率
  6. 状态机迁移:将设备状态迁移到 CONFIGURED
性能关键点:configure_streams() 是 HAL 初始化流程中最耗时的操作之一。优化方向包括:
• 缓存 ISP 配置参数,避免重复计算
• 使用预分配的缓冲区池,减少动态分配开销
• 支持增量配置,当流参数未变化时跳过重新配置

4.5 construct_default_request_settings():获取默认请求模板

construct_default_request_settings() 是 HAL3 初始化流程的最后一步。Framework 通过该接口获取指定模板类型的默认 metadata,用于构造后续的 CaptureRequest。

4.5.1 接口定义

const camera_metadata_t* (*construct_default_request_settings)(
        const struct camera3_device *device,
        int type);

4.5.2 模板类型

模板类型 值 典型应用场景
CAMERA3_TEMPLATE_PREVIEW 1 预览模式,优先保证帧率
CAMERA3_TEMPLATE_STILL_CAPTURE 2 拍照模式,优先保证图像质量
CAMERA3_TEMPLATE_VIDEO_RECORD 3 视频录制,平衡帧率和质量
CAMERA3_TEMPLATE_VIDEO_SNAPSHOT 4 视频录制中的抓拍
CAMERA3_TEMPLATE_ZERO_SHUTTER_LAG 5 零快门延迟模式
CAMERA3_TEMPLATE_MANUAL 6 手动模式,所有参数由应用控制

4.5.3 实现要点

  • 静态 metadata 填充:返回的 metadata 必须包含所有静态能力标签(如 ANDROID_SENSOR_INFO_*、ANDROID_SCALER_AVAILABLE_* 等)
  • 默认参数设置:根据模板类型设置合理的默认值,如 AE 模式、AWB 模式、AF 模式、帧率范围等
  • 内存管理:返回的 metadata 由 HAL 管理生命周期,Framework 只读不释放。HAL 需要保证该指针在设备关闭前始终有效
  • 线程安全:该接口可能被多个线程同时调用,需要加锁保护
常见错误:部分 HAL 在 construct_default_request_settings() 中返回了不完整的 metadata,缺少必要的控制标签(如 ANDROID_CONTROL_AE_MODE),导致 Framework 构造 CaptureRequest 时失败。建议使用 CTS 的 android.hardware.camera2.cts.CameraMetadataTest 验证返回的 metadata 完整性。

4.6 初始化流程状态机

HAL3 设备在整个生命周期中维护一个状态机,初始化流程对应从 CLOSED 到 CONFIGURED 的状态迁移:

HAL3 初始化状态机 CLOSED OPENED INITIALIZED CONFIGURED open() init() configure_streams() 状态迁移说明: • CLOSED → OPENED:open() 成功,设备句柄可用,但未初始化 • OPENED → INITIALIZED:init() 成功,回调通道建立,管道就绪 • INITIALIZED → CONFIGURED:configure_streams() 成功,数据流配置完成 • 任何步骤失败都应回退到 CLOSED 状态,并释放已分配的资源

4.7 初始化流程常见问题与调试方法

问题现象 可能原因 调试建议
open() 返回 -ENODEV cameraId 不存在或硬件故障 检查 cameraId 范围,确认硬件上电正常
init() 返回 -EINVAL callback_ops 为 NULL 或设备状态错误 确认 open() 已成功,检查回调指针有效性
configure_streams() 返回 -EINVAL 流参数超出传感器能力范围 对比 stream 参数与静态 metadata 中的可用配置
construct_default_request_settings() 返回 NULL 模板类型不支持或 metadata 构造失败 确认模板类型在支持范围内,检查内存分配
首帧延迟过高 configure_streams() 中执行了过多耗时操作 使用 systrace 分析耗时分布,优化 ISP 配置流程
调试工具推荐:使用 adb shell dumpsys media.camera 查看相机服务的状态信息,包括每个 cameraId 的当前状态、配置的流信息、缓冲区使用情况等。结合 logcat -s Camera3 可以追踪 Framework 层的初始化日志。

4.8 本章小结

Camera HAL3 的初始化流程是 Framework 与 HAL 之间建立通信通道、配置数据路径的关键阶段。开发者需要深入理解以下要点:

  • open() 负责设备句柄的创建和底层硬件的上电
  • init() 建立回调通道,完成算法和管道的初始化
  • configure_streams() 根据应用需求配置 ISP 和缓冲区分配
  • construct_default_request_settings() 提供默认的请求模板,是后续 CaptureRequest 的基础
  • 状态机管理是保证初始化流程正确性的核心,任何步骤失败都需要正确的回退处理

在实际开发中,建议使用 CTS 的 android.hardware.camera2.cts.CameraTest 和 CameraMetadataTest 验证初始化流程的正确性和完整性,确保 HAL 实现符合 Android 兼容性定义文档(CDD)的要求。