4. Camera3Device初始化入口:initialize()方法的调用时机与整体流程
Camera3Device 的 initialize() 方法是 Camera HAL3 设备初始化的核心入口点。它标志着 CameraService 从框架层正式进入 HAL 层设备初始化的关键阶段。本章将深入分析 initialize() 的调用时机、调用链以及内部执行流程。
4.1 initialize() 的调用时机
initialize() 方法并非在 CameraService 启动时立即调用,而是在应用层通过 CameraManager.openCamera() 成功打开 Camera 设备后,由 CameraService 内部触发。具体调用链路如下:
- 应用层调用:
CameraManager.openCamera(String cameraId, CameraDevice.StateCallback callback, Handler handler) - CameraService 处理:
CameraService::connect()创建Camera3Device实例 - 设备初始化触发:
Camera3Device::initialize()被调用 - HAL 接口对接:内部调用
camera3_device_t->ops->initialize()
关键时序点:
initialize() 必须在 configureStreams() 之前调用,且在整个设备生命周期中只调用一次。
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()的状态
4.5 常见问题与避坑指南
常见错误 1:HAL initialize() 中执行耗时操作
某些 HAL 实现在
某些 HAL 实现在
initialize() 中打开 sensor 或加载固件,导致 CameraService 主线程阻塞超过 200ms,引发 ANR。解决方案:将耗时操作延迟到 configureStreams() 中执行。
常见错误 2:未正确处理重复调用
如果 HAL 未检查
如果 HAL 未检查
initialize() 的重复调用,第二次调用可能导致资源泄漏或状态混乱。必须返回 -EALREADY。
常见错误 3:忽略 camera_metadata_t 的解析
部分 HAL 实现未正确解析
部分 HAL 实现未正确解析
info 参数中的关键字段(如 ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL),导致后续配置失败。建议在 initialize() 中立即解析并缓存所有必要信息。
4.6 初始化流程总结
Camera3Device::initialize() 是 Camera HAL3 设备初始化的核心入口,其调用时机严格位于设备打开之后、流配置之前。整个流程涉及参数校验、HAL 接口调用、静态信息获取、内部模块创建、状态迁移和回调通知六个阶段。HAL 层实现必须严格遵守接口契约,避免在 initialize() 中执行耗时操作,并正确处理幂等性和参数解析。