3. HAL3 初始化流程:open()、initialize() 与静态特性配置

HAL3 初始化是 Camera HAL 移植中最关键的入口阶段,它决定了上层 Camera Service 能否成功加载 HAL 模块并与底层硬件建立通信。本章深入剖析 open() 函数实现、initialize() 回调注册机制、camera_info 填充以及静态特性配置的完整流程。

3.1 初始化流程总览

HAL3 初始化流程分为三个主要阶段,每个阶段都有明确的职责和交付物:

阶段 触发时机 核心职责 交付物
Phase 1: open() CameraService 调用 hw_module_t->open() 创建设备实例、初始化硬件抽象层、分配资源 camera3_device_t 结构体指针
Phase 2: initialize() CameraService 调用 camera3_device->ops->initialize() 注册回调接口、建立与 Framework 的通信通道 camera3_callback_ops_t 回调集
Phase 3: 静态特性配置 CameraService 调用 get_camera_info() 填充设备信息、构建静态特性元数据 camera_info + static_metadata
移植要点: 三个阶段的执行顺序严格固定,任何阶段的失败都会导致 Camera HAL 无法被 Framework 识别。建议在 open() 阶段完成所有硬件资源预分配,避免在 initialize() 中执行耗时操作。

3.2 open() 函数实现

open() 是 HAL 模块与 Framework 的第一次握手。其核心任务是创建 camera3_device_t 实例并填充操作函数表。

3.2.1 标准实现模板

static int hal3_open(const struct hw_module_t* module,
                     const char* id,
                     struct hw_device_t** device) {
    int camera_id = atoi(id);
    if (camera_id < 0 || camera_id >= MAX_CAMERAS) {
        ALOGE("Invalid camera id: %s", id);
        return -ENODEV;
    }

    // 1. 分配设备上下文
    camera3_device_t* hal3_dev = (camera3_device_t*)
        calloc(1, sizeof(camera3_device_t));
    if (!hal3_dev) return -ENOMEM;

    // 2. 填充通用设备头
    hal3_dev->common.tag     = HARDWARE_DEVICE_TAG;
    hal3_dev->common.version = CAMERA_DEVICE_API_VERSION_3_5;
    hal3_dev->common.module  = (hw_module_t*)module;
    hal3_dev->common.close   = hal3_close;

    // 3. 填充 HAL3 操作函数表
    hal3_dev->ops = &g_camera3_ops;

    // 4. 初始化私有上下文(硬件抽象层)
    camera_private_t* priv = (camera_private_t*)
        calloc(1, sizeof(camera_private_t));
    priv->camera_id = camera_id;
    priv->hal_dev   = hal3_dev;
    hal3_dev->priv  = priv;

    // 5. 初始化硬件资源
    if (init_hardware(priv) != 0) {
        ALOGE("Hardware init failed for camera %d", camera_id);
        free(priv);
        free(hal3_dev);
        return -ENODEV;
    }

    *device = &hal3_dev->common;
    ALOGI("Camera %d opened successfully", camera_id);
    return 0;
}

3.2.2 操作函数表定义

camera3_device_ops_t 是 HAL3 设备的核心接口表,必须实现所有函数指针:

static camera3_device_ops_t g_camera3_ops = {
    .initialize        = hal3_initialize,
    .configure_streams = hal3_configure_streams,
    .register_stream_buffers = NULL,  // HAL3.2+ 已废弃
    .process_capture_request  = hal3_process_capture_request,
    .get_metadata_vendor_tag_ops = NULL,
    .dump               = hal3_dump,
    .flush              = hal3_flush,
    .signal_stream_flush = NULL,
    .is_reconfiguration_required = NULL,
};
常见陷阱:
  • register_stream_buffers 在 HAL3.2 及以上版本必须设为 NULL,否则 Framework 会拒绝加载。
  • common.version 必须与 HAL 实现版本一致,推荐使用 CAMERA_DEVICE_API_VERSION_3_5。
  • 私有上下文 priv 的生命周期管理必须在 close() 中妥善处理。

3.3 initialize() 回调注册

initialize() 是 HAL3 设备初始化中唯一与 Framework 建立双向通信的入口。Framework 通过此函数将回调接口传递给 HAL,HAL 后续通过回调上报事件、返回结果。

3.3.1 回调接口结构

typedef struct camera3_callback_ops {
    // 通知回调:上报错误、快门事件等
    void (*notify)(const struct camera3_callback_ops *ops,
                   const camera3_notify_msg_t *msg);

    // 结果回调:返回捕获结果元数据
    void (*process_capture_result)(
                   const struct camera3_callback_ops *ops,
                   const camera3_capture_result_t *result);

    // HAL3.2+ 新增:返回部分元数据结果
    void (*process_capture_result_early)(
                   const struct camera3_callback_ops *ops,
                   const camera3_capture_result_t *result);

    // 缓冲区回调:返回已处理的输出缓冲区
    void (*return_stream_buffers)(
                   const struct camera3_callback_ops *ops,
                   uint32_t num_buffers,
                   const camera3_stream_buffer_t *const *buffers);
} camera3_callback_ops_t;

3.3.2 initialize() 实现要点

static int hal3_initialize(const struct camera3_device *device,
                           const camera3_callback_ops_t *callback_ops) {
    camera_private_t* priv = (camera_private_t*)device->priv;

    // 1. 保存回调指针(Framework 传入)
    priv->callback_ops = callback_ops;

    // 2. 初始化传感器驱动
    if (sensor_init(priv) != 0) {
        ALOGE("Sensor init failed");
        return -ENODEV;
    }

    // 3. 初始化 ISP 管线
    if (isp_init(priv) != 0) {
        ALOGE("ISP init failed");
        return -ENODEV;
    }

    // 4. 初始化元数据缓冲区池
    priv->metadata_pool = metadata_pool_create(64);
    if (!priv->metadata_pool) {
        ALOGE("Metadata pool creation failed");
        return -ENOMEM;
    }

    ALOGI("Camera %d initialized", priv->camera_id);
    return 0;
}
最佳实践:
  • 回调指针 callback_ops 必须保存到私有上下文中,后续所有结果上报都依赖此指针。
  • 不要在 initialize() 中执行耗时超过 500ms 的操作,否则 Framework 会触发 ANR。
  • 建议在 initialize() 中完成所有硬件初始化,确保后续 configure_streams() 可以快速响应。

3.4 camera_info 填充与静态特性配置

camera_info 和静态特性元数据是 Framework 识别 Camera 能力的关键依据。错误的配置会导致上层应用无法正确使用 Camera 功能。

3.4.1 camera_info 结构

typedef struct camera_info {
    int                 device_version;   // 必须为 CAMERA_DEVICE_API_VERSION_3_5
    const char*         static_camera_characteristics;  // 静态元数据
    int                 resource_cost;    // 资源开销等级 (0-100)
    int                 conflicting_devices_length;     // 冲突设备数量
    const char**        conflicting_devices;            // 冲突设备列表
} camera_info_t;

3.4.2 静态特性元数据构建

静态特性元数据是 HAL3 移植中最繁琐的部分,涉及 200+ 个元数据标签。以下是关键标签的配置示例:

static int build_static_metadata(camera_private_t* priv,
                                 camera_metadata_t** metadata) {
    camera_metadata_t* m = allocate_camera_metadata(
        STATIC_METADATA_ENTRY_COUNT,
        STATIC_METADATA_DATA_SIZE);

    // 1. 基础信息
    int32_t facing = ANDROID_LENS_FACING_BACK;
    add_camera_metadata_entry(m,
        ANDROID_LENS_FACING, &facing, 1);

    // 2. 传感器尺寸
    int32_t sensor_size[] = {3264, 2448};  // 8MP
    add_camera_metadata_entry(m,
        ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
        sensor_size, 2);

    // 3. 支持的输出格式
    int32_t formats[] = {
        HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
        HAL_PIXEL_FORMAT_YCbCr_420_888,
        HAL_PIXEL_FORMAT_BLOB
    };
    add_camera_metadata_entry(m,
        ANDROID_SCALER_AVAILABLE_FORMATS,
        formats, 3);

    // 4. 支持的帧率范围
    int32_t fps_ranges[] = {15, 30, 30, 30};  // [min1,max1,min2,max2]
    add_camera_metadata_entry(m,
        ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
        fps_ranges, 4);

    // 5. 硬件能力级别
    uint8_t hw_level = ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL;
    add_camera_metadata_entry(m,
        ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL,
        &hw_level, 1);

    *metadata = m;
    return 0;
}

3.4.3 get_camera_info() 实现

static int hal3_get_camera_info(int camera_id,
                                struct camera_info* info) {
    if (camera_id < 0 || camera_id >= MAX_CAMERAS)
        return -ENODEV;

    // 1. 填充设备版本
    info->device_version = CAMERA_DEVICE_API_VERSION_3_5;

    // 2. 构建静态特性元数据
    camera_metadata_t* static_meta = NULL;
    if (build_static_metadata(&g_priv[camera_id], &static_meta) != 0)
        return -ENODEV;

    info->static_camera_characteristics =
        (const char*)static_meta;

    // 3. 资源开销(默认值)
    info->resource_cost = 50;

    // 4. 冲突设备(无冲突)
    info->conflicting_devices_length = 0;
    info->conflicting_devices = NULL;

    return 0;
}
关键指标:
  • ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL 决定了 Framework 启用的功能集:LIMITED(基础)、FULL(完整)、LEVEL_3(高级)。
  • resource_cost 影响多 Camera 并发策略,值越高越容易被抢占。
  • 静态元数据一旦构建完成,在整个 HAL 生命周期内不可修改。

3.5 初始化流程架构图

下图展示了 HAL3 初始化流程中三个阶段的调用关系与数据流向:

HAL3 初始化流程架构图 HAL3 初始化流程架构图 Phase 1: open() hw_module_t->open() ① 分配 camera3_device_t ② 填充 ops 函数表 ③ 初始化私有上下文 ④ 初始化硬件资源 ⑤ 返回 device 指针 Phase 2: initialize() camera3_device->ops->initialize() ① 保存 callback_ops 指针 ② 初始化传感器驱动 ③ 初始化 ISP 管线 ④ 创建元数据缓冲区池 ⑤ 返回初始化结果 Phase 3: 静态特性配置 get_camera_info() ① 填充 device_version ② 构建静态特性元数据 ③ 设置 resource_cost ④ 配置冲突设备列表 ⑤ 返回 camera_info 成功 成功 数据流与依赖关系 • open() 输出 camera3_device_t → 作为 initialize() 的输入 • initialize() 注册 callback_ops → 后续 capture 结果通过此回调上报 • get_camera_info() 独立于前两个阶段,但必须在 HAL 加载时完成 错误处理策略 • open() 失败:返回 -ENODEV,Framework 标记 Camera 不可用 • initialize() 失败:返回负值,Framework 调用 close() 释放资源 • 静态特性配置错误:可能导致上层应用崩溃或功能异常

3.6 常见问题与调试技巧

问题现象 可能原因 排查方法
CameraService 无法加载 HAL open() 返回错误或 device_version 不匹配 检查 logcat 中 CameraService 标签的错误日志
initialize() 回调后无响应 callback_ops 指针未正确保存或被覆盖 在 notify() 调用处添加断点验证指针有效性
上层应用无法预览 静态特性中缺少关键格式或分辨率配置 使用 dumpsys media.camera 查看设备能力
多 Camera 并发冲突 conflicting_devices 配置错误 检查 resource_cost 和冲突设备列表
调试建议:
  • 在 open() 和 initialize() 的关键路径添加 ALOGI 日志,便于追踪初始化进度。
  • 使用 adb shell dumpsys media.camera -v 验证静态特性元数据是否正确。
  • 建议在 build_static_metadata() 中增加元数据校验逻辑,确保所有必填标签都已配置。

3.7 初始化流程状态机

HAL3 设备初始化过程可以抽象为有限状态机,每个状态对应特定的操作集合:

HAL3 初始化状态机 HAL3 设备初始化状态机 UNINITIALIZED OPENED INITIALIZED CONFIGURED ERROR open() initialize() configure_streams() 失败 失败 失败 状态转换不可逆:UNINITIALIZED → OPENED → INITIALIZED → CONFIGURED
移植总结: HAL3 初始化流程是 Camera HAL 移植的基石。成功的初始化需要确保:
  • open() 正确创建设备实例并初始化硬件资源
  • initialize() 妥善保存回调指针并完成硬件管线初始化
  • 静态特性元数据完整、准确,覆盖所有 Framework 要求的必填标签
  • 状态机转换严格遵循单向流程,任何阶段的失败都需要妥善清理已分配资源