4. CameraService构造函数:服务注册、监听器初始化、HAL设备枚举准备
CameraService 的构造函数是整个相机框架启动的核心入口。它不仅要完成自身状态的初始化,还需要完成三个关键任务:向 ServiceManager 注册服务、初始化内部监听器、以及为后续 HAL 设备枚举做好准备。本章将深入分析构造函数中每一行关键代码的执行逻辑与调试要点。
4.1 构造函数整体流程
CameraService 构造函数位于 frameworks/av/services/camera/libcameraservice/CameraService.cpp,其核心执行顺序如下表所示:
| 步骤 | 执行函数/操作 | 关键作用 | 调试关注点 |
|---|---|---|---|
| 1 | CameraService() 入口 |
初始化成员变量、mutex、condition | 检查是否重复构造 |
| 2 | registerService() |
将 CameraService 注册到 ServiceManager | 确认服务名 "media.camera" 是否注册成功 |
| 3 | initializeListener() |
创建并启动内部监听线程 | 监听线程是否正常轮询 |
| 4 | enumerateHALDevices() 准备 |
初始化 HAL 客户端、准备设备枚举 | HAL 服务是否可达 |
onFirstRef() 中增加日志标记,确认构造是否完整执行。
4.2 服务注册:向 ServiceManager 注册 CameraService
CameraService 继承自 BnCameraService,通过 defaultServiceManager()->addService() 将自身注册到 ServiceManager。注册成功后,其他进程(如 Camera2 应用)可以通过 getService("media.camera") 获取代理。
// CameraService.cpp 关键代码片段
void CameraService::onFirstRef() {
ALOGI("CameraService started (pid=%d)", getpid());
// 注册服务
status_t err = defaultServiceManager()->addService(
String16("media.camera"), this, false);
if (err != OK) {
ALOGE("Failed to register camera service: %d", err);
return;
}
ALOGI("CameraService registered successfully");
// ... 后续初始化
}
服务注册的流程可以用下面的 SVG 图表示:
adb shell dumpsys media.camera 可以验证 CameraService 是否已注册。如果返回 "Service not found",说明注册失败,需要检查 SELinux 权限或 ServiceManager 是否正常。
4.3 监听器初始化:内部事件监听线程
CameraService 内部维护了一个 CameraServiceListener,用于监听系统事件(如设备热插拔、权限变化等)。监听器在构造函数中通过 initializeListener() 初始化,并启动一个独立的 ListenerThread 进行事件轮询。
// CameraService.cpp 监听器初始化
status_t CameraService::initializeListener() {
mListener = new CameraServiceListener(this);
mListenerThread = new ListenerThread("CameraListener", mListener);
status_t err = mListenerThread->run("CameraListener");
if (err != OK) {
ALOGE("Failed to start listener thread: %d", err);
return err;
}
ALOGI("Camera listener thread started");
return OK;
}
监听器线程的工作模式如下:
- 事件源: 来自 HAL 层的设备状态变化通知、系统广播(如屏幕状态变化)。
- 处理方式: 线程内部维护一个
Looper,通过MessageQueue异步处理事件。 - 关键回调:
onDeviceStatusChanged()、onTorchStatusChanged()。
adb shell ps -A | grep camera 查看线程是否存活。
4.4 HAL 设备枚举准备:初始化 HAL 客户端
在构造函数末尾,CameraService 会为 HAL 设备枚举做准备。这包括创建 CameraProviderManager 实例,并注册 CameraServiceProxy 用于与 HAL 服务通信。
// CameraService.cpp 枚举准备
void CameraService::enumerateHALDevices() {
// 创建 CameraProviderManager
mProviderManager = new CameraProviderManager();
mProviderManager->initialize(this);
// 注册 HAL 服务监听
mProviderManager->setCameraServiceListener(mListener);
// 准备枚举所有 HAL 设备
status_t err = mProviderManager->enumerateProviders();
if (err != OK) {
ALOGE("Failed to enumerate HAL providers: %d", err);
}
}
枚举准备阶段的核心数据结构如下表所示:
| 组件 | 类型 | 作用 | 初始化状态 |
|---|---|---|---|
CameraProviderManager |
核心管理类 | 管理所有 HAL Provider 的注册与枚举 | 创建后立即初始化 |
CameraServiceProxy |
Binder 代理 | 与 HAL 服务进程通信 | 延迟初始化(首次枚举时) |
HALDeviceInfo |
设备信息结构体 | 存储每个 HAL 设备的元数据 | 枚举完成后填充 |
下面的 SVG 图展示了枚举准备阶段的组件关系:
4.5 构造函数执行时序总结
CameraService 构造函数的完整执行时序可以归纳为以下步骤:
- 成员初始化: 设置默认值、初始化 mutex 和 condition 变量。
- 服务注册: 调用
addService("media.camera"),使 CameraService 对外可见。 - 监听器启动: 创建
CameraServiceListener并启动监听线程。 - HAL 枚举准备: 初始化
CameraProviderManager,注册代理,准备枚举。
- 确认 logcat 中是否输出 "CameraService started" 和 "CameraService registered successfully"。
- 检查监听器线程是否正常启动,无 "Failed to start listener thread" 错误。
- 确认 HAL 枚举准备阶段没有 "Failed to enumerate HAL providers" 日志。
- 使用
adb shell dumpsys media.camera验证服务是否可用。
构造函数执行完毕后,CameraService 进入就绪状态,等待来自应用层的绑定请求和来自 HAL 层的设备状态通知。下一阶段将进入实际的 HAL 设备枚举流程。