3. Camera3Device构造函数:参数解析与内部成员变量初始化
Camera3Device 构造函数是整个 HAL 对接流程的起点。它接收来自 CameraService 的调用参数,完成设备句柄的绑定、内部状态机的初始状态设置、以及关键回调接口的注册。本节将深入解析构造函数的参数含义,并逐一说明内部成员变量的初始化逻辑。
3.1 构造函数签名与参数解析
Camera3Device 的构造函数通常定义在 Camera3Device.cpp 中,其典型签名如下:
Camera3Device::Camera3Device(
const std::string& cameraId,
const camera3_device_t* halDevice,
const sp<ICameraDeviceCallbacks>& deviceCallbacks,
const sp<ICameraService>& cameraService,
const std::shared_ptr<CameraProviderManager>& providerManager)
: mCameraId(cameraId),
mHalDevice(halDevice),
mDeviceCallbacks(deviceCallbacks),
mCameraService(cameraService),
mProviderManager(providerManager),
mStatus(CAMERA_DEVICE_STATUS_CLOSED),
mNextRequestId(1),
mStreamList(),
mCallbackOps{},
mFrameNumberCounter(0),
mUseHal3v3(false),
mInitialized(false) {}
下表对每个参数的作用和来源进行详细说明:
| 参数名 | 类型 | 来源 | 作用说明 |
|---|---|---|---|
cameraId |
const std::string& |
CameraService 根据 HAL 上报的摄像头列表分配 | 唯一标识摄像头设备,如 "0"、"1";用于日志、权限校验和 HAL 设备查找 |
halDevice |
const camera3_device_t* |
CameraProviderManager 通过 open() 调用从 HAL 获取 |
指向 HAL 层 camera3_device_t 结构体,包含所有 HAL 操作函数指针 |
deviceCallbacks |
const sp<ICameraDeviceCallbacks>& |
CameraService 创建设备时传入 | 用于 Camera3Device 向 CameraService 上报事件、错误和结果通知 |
cameraService |
const sp<ICameraService>& |
CameraService 自身引用 | 用于跨进程调用 CameraService 的接口,如策略查询、资源管理等 |
providerManager |
const std::shared_ptr<CameraProviderManager>& |
CameraService 全局单例 | 管理 HAL 提供者生命周期,用于后续的流配置、模板查询等操作 |
关键点:
halDevice 参数是构造函数中最重要的输入。它不是一个简单的指针,而是 HAL 实现必须填充完整的 camera3_device_t 结构体,其中 ops 字段指向 camera3_device_ops_t,包含 initialize、configure_streams、process_capture_request 等核心函数指针。
3.2 内部成员变量初始化清单
构造函数初始化列表完成后,还会在函数体内执行一系列关键成员变量的初始化。以下按类别列出所有重要成员变量及其初始值:
3.2.1 状态与标识类
mStatus:初始化为CAMERA_DEVICE_STATUS_CLOSED,表示设备尚未打开或初始化。mInitialized:布尔值,初始false,在initialize()方法成功返回后置为true。mNextRequestId:自增请求 ID 生成器,初始值 1,每次下发 capture request 时递增。mFrameNumberCounter:帧号计数器,初始 0,每收到一个 HAL 结果帧时递增。
3.2.2 HAL 对接类
mHalDevice:直接保存传入的camera3_device_t*指针。mCallbackOps:类型为camera3_callback_ops_t的结构体,初始化为零。在initialize()中填充函数指针后传递给 HAL。mUseHal3v3:布尔值,初始false,在检测到 HAL 版本 >= 3.3 时置为true,用于区分不同版本的 HAL 行为。
3.2.3 流与请求管理类
mStreamList:空列表,类型为std::vector<camera3_stream_t*>,在configure_streams()中被填充。mPendingRequests:空映射表,类型为std::map<uint32_t, CaptureRequest>,用于跟踪已下发但未完成的请求。mResultQueue:空队列,用于缓存从 HAL 返回的结果帧,等待 CameraService 消费。
3.2.4 同步与线程安全类
mLock:Mutex类型,用于保护所有成员变量的并发访问。mResultSignal:Condition类型,用于通知结果处理线程有新结果到达。
设计意图: 构造函数只做轻量级初始化,不执行任何 HAL 调用。真正的 HAL 初始化(调用
halDevice->ops->initialize())延迟到 initialize() 方法中执行,这样可以避免在构造阶段因 HAL 异常导致对象创建失败。
3.3 初始化流程的 SVG 架构图
下图展示了 Camera3Device 构造函数执行过程中,参数传入与内部成员变量初始化的完整数据流:
3.4 回调结构体初始化细节
mCallbackOps 是 Camera3Device 与 HAL 之间的通信桥梁。构造函数中将其清零,然后在 initialize() 方法中填充以下函数指针:
// 在 Camera3Device::initialize() 中
mCallbackOps = {
.notify = [](const camera3_callback_ops_t* ops,
const camera3_notify_msg_t* msg) {
auto* self = static_cast<Camera3Device*>(ops->userData);
self->handleNotify(msg);
},
.process_capture_result = [](const camera3_callback_ops_t* ops,
const camera3_capture_result_t* result) {
auto* self = static_cast<Camera3Device*>(ops->userData);
self->handleCaptureResult(result);
},
.userData = this // 指向 Camera3Device 自身实例
};
常见错误: 如果构造函数中
mCallbackOps 没有清零,或者 userData 未正确设置为 this,HAL 在回调时会导致空指针访问或错误的类型转换,引发进程崩溃。务必在构造函数中执行 memset(&mCallbackOps, 0, sizeof(mCallbackOps)) 或使用零初始化语法。
3.5 初始化顺序与依赖关系
构造函数内部成员变量的初始化顺序遵循严格的依赖关系,下表列出各成员的初始化顺序及其依赖:
| 初始化顺序 | 成员变量 | 依赖项 | 说明 |
|---|---|---|---|
| 1 | mCameraId |
无 | 字符串拷贝,独立初始化 |
| 2 | mHalDevice |
无 | 指针赋值,不进行有效性检查 |
| 3 | mDeviceCallbacks |
无 | sp 智能指针引用计数增加 |
| 4 | mCameraService |
无 | sp 智能指针引用计数增加 |
| 5 | mProviderManager |
无 | shared_ptr 引用计数增加 |
| 6 | mStatus |
无 | 枚举值直接赋值 |
| 7 | mNextRequestId |
无 | 整数直接赋值 |
| 8 | mCallbackOps |
无 | 结构体零初始化 |
| 9 | mStreamList |
无 | 默认构造空 vector |
| 10 | mFrameNumberCounter |
无 | 整数直接赋值 |
设计原则: 所有成员变量的初始化都不依赖其他成员变量的值,因此初始化顺序仅由声明顺序决定。C++ 保证初始化列表按照成员变量在类中声明的顺序执行,而非初始化列表中的书写顺序。务必保持声明顺序与初始化列表顺序一致,避免潜在的未定义行为。
3.6 构造函数执行后的状态检查
构造函数执行完毕后,Camera3Device 对象处于以下状态:
- 设备状态:
CLOSED,尚未与 HAL 建立通信。 - HAL 指针:已保存,但未调用任何 HAL 函数。
- 回调接口:结构体已清零,尚未注册到 HAL。
- 流列表:为空,未配置任何数据流。
- 请求队列:为空,无待处理请求。
此时,Camera3Device 对象已经可以安全地返回给 CameraService,但还不能处理任何捕获请求。后续的 initialize() 调用将完成 HAL 回调注册和设备初始化,使对象进入 OPEN 状态。