4. Camera3Device初始化入口:initialize()方法的调用时机与整体流程

Camera3Device 的 initialize() 方法是 Camera HAL3 设备初始化的核心入口点。它标志着 CameraService 从框架层正式进入 HAL 层设备初始化的关键阶段。本章将深入分析 initialize() 的调用时机、调用链以及内部执行流程。

4.1 initialize() 的调用时机

initialize() 方法并非在 CameraService 启动时立即调用,而是在应用层通过 CameraManager.openCamera() 成功打开 Camera 设备后,由 CameraService 内部触发。具体调用链路如下:

  1. 应用层调用:CameraManager.openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler)
  2. CameraService 处理:CameraService::connect() 创建 Camera3Device 实例
  3. 设备初始化触发:Camera3Device::initialize() 被调用
  4. HAL 接口对接:内部调用 camera3_device_t->ops->initialize()
关键时序点:initialize() 必须在 configureStreams() 之前调用,且在整个设备生命周期中只调用一次。
initialize() 调用时序图 App / CameraManager CameraService Camera3Device HAL openCamera() connect() initialize() 调用前提 设备已打开(open) 未调用过 initialize()

4.2 initialize() 方法的整体流程

Camera3Device::initialize() 的执行流程可以分为以下 6 个主要阶段:

阶段 执行内容 关键函数/接口
1. 参数校验 检查传入的 callback、camera_info 等参数有效性 checkCallbacks(), validateInfo()
2. HAL 设备初始化 调用 HAL 层的 initialize() 接口 camera3_device_t::ops->initialize()
3. 静态信息获取 从 HAL 获取 camera_metadata_t 静态特征 getCameraCharacteristics()
4. 资源预分配 创建 BufferManager、RequestThread 等内部模块 createBufferManager(), startRequestThread()
5. 状态迁移 设备状态从 UNINITIALIZED 变为 INITIALIZED setState(INITIALIZED)
6. 回调通知 通过 callback 通知 CameraService 初始化完成 onInitialized()
最佳实践:在 HAL 层实现 initialize() 时,应避免执行耗时操作(如打开 sensor、加载固件),这些操作应延迟到 configureStreams() 或第一次 processCaptureRequest() 时执行,以缩短应用启动时间。

4.3 核心代码路径分析

以下是 Camera3Device::initialize() 的核心代码片段,展示了与 HAL 接口对接的关键逻辑:

status_t Camera3Device::initialize(
        const sp<ICameraDeviceCallbacks>& callback,
        const camera_metadata_t* info) {
    // 阶段1: 参数校验
    if (callback == nullptr || info == nullptr) {
        ALOGE("%s: Invalid arguments", __FUNCTION__);
        return BAD_VALUE;
    }

    // 阶段2: 调用 HAL 层 initialize
    camera3_device_t* halDevice = mHalDevice;
    status_t res = halDevice->ops->initialize(halDevice, info);
    if (res != OK) {
        ALOGE("HAL initialize failed: %d", res);
        return res;
    }

    // 阶段3: 获取静态特征
    camera_metadata_t* characteristics = nullptr;
    res = halDevice->ops->get_metadata(halDevice, &characteristics);
    if (res != OK) {
        ALOGE("Failed to get camera characteristics");
        return res;
    }

    // 阶段4: 创建内部模块
    mBufferManager = new Camera3BufferManager();
    mRequestThread = new RequestThread(this);

    // 阶段5: 状态迁移
    mState = STATE_INITIALIZED;

    // 阶段6: 回调通知
    callback->onInitialized();

    return OK;
}

4.4 HAL 接口 initialize() 的契约

HAL 层 initialize() 接口必须遵循以下契约:

  • 调用线程:由 CameraService 的 Binder 线程调用,HAL 实现不应阻塞该线程超过 200ms
  • 参数要求:camera_metadata_t* info 包含应用层传入的初始化参数,HAL 应解析并保存
  • 返回值:成功返回 0,失败返回负的错误码(如 -ENODEV、-EINVAL)
  • 幂等性:不允许重复调用,第二次调用应返回 -EALREADY
  • 资源状态:调用后 HAL 应处于可接收 configureStreams() 的状态
HAL initialize() 接口契约 CameraService HAL Implementation initialize() 接口契约要求: 1. 调用线程:Binder 线程,阻塞时间 < 200ms 2. 参数:camera_metadata_t* info 必须解析并保存 3. 返回值:成功 0,失败 -ENODEV / -EINVAL / -EALREADY 4. 幂等性:不可重复调用,第二次返回 -EALREADY

4.5 常见问题与避坑指南

常见错误 1:HAL initialize() 中执行耗时操作
某些 HAL 实现在 initialize() 中打开 sensor 或加载固件,导致 CameraService 主线程阻塞超过 200ms,引发 ANR。解决方案:将耗时操作延迟到 configureStreams() 中执行。
常见错误 2:未正确处理重复调用
如果 HAL 未检查 initialize() 的重复调用,第二次调用可能导致资源泄漏或状态混乱。必须返回 -EALREADY。
常见错误 3:忽略 camera_metadata_t 的解析
部分 HAL 实现未正确解析 info 参数中的关键字段(如 ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL),导致后续配置失败。建议在 initialize() 中立即解析并缓存所有必要信息。

4.6 初始化流程总结

Camera3Device::initialize() 是 Camera HAL3 设备初始化的核心入口,其调用时机严格位于设备打开之后、流配置之前。整个流程涉及参数校验、HAL 接口调用、静态信息获取、内部模块创建、状态迁移和回调通知六个阶段。HAL 层实现必须严格遵守接口契约,避免在 initialize() 中执行耗时操作,并正确处理幂等性和参数解析。