Camera Service核心:启动、架构与Client管理
Camera Service,说白了就是整个相机框架的“大管家”。
我刚开始接触Android相机时,总觉得它就是个黑盒子——上层调个openCamera,底层就自动干活了。后来啃了半年源码才发现,CameraService才是真正承上启下的关键节点。今天咱们就把它拆开看看。
一、CameraService的启动流程
CameraService是在系统启动时,由init进程拉起来的。它注册为系统服务,等待客户端来调用。
具体启动路径是这样的:
- init进程解析init.rc,启动cameraserver进程
- cameraserver的main函数里,实例化CameraService
- 调用CameraService::instantiate(),注册到ServiceManager
- ServiceManager将其加入服务列表,供其他进程查询
嗯,这里要注意:CameraService是跑在独立的cameraserver进程里的,不是system_server。为什么这么设计?
我个人理解,是为了隔离。相机处理涉及大量内存和硬件操作,万一崩了不能拖垮整个系统。我在项目中就遇到过相机进程OOM,但系统其他功能完全不受影响——这就是独立进程的好处。
核心要点:CameraService的启动是系统级服务注册,它通过Binder与上层通信,通过HAL与底层硬件交互。
二、CameraService的架构设计
CameraService的架构,我习惯把它分成三层:
| 层级 | 组件 | 职责 |
|---|---|---|
| 接口层 | ICameraService | 定义Binder接口,供APP调用 |
| 核心层 | CameraService | 管理Client、处理权限、协调资源 |
| 设备层 | CameraDevice/Camera3Device | 封装HAL调用,管理流和请求 |
你想想看,上层APP调用connect()时,实际上走的是Binder跨进程调用。CameraService收到请求后,会做几件事:
- 检查调用方权限(有没有CAMERA权限)
- 检查设备是否可用(有没有被其他进程占用)
- 创建CameraClient实例
- 返回Binder代理给APP
我记得有一次排查问题,发现某个第三方应用一直拿不到相机。查了半天,原来是它没在manifest里声明CAMERA权限。CameraService在权限校验这步就直接拒绝了,连HAL都没碰——这种设计很合理,避免无效的硬件操作。
避坑指南:我曾经在调试多摄像头时,发现CameraService内部维护了一个mCameraMap,key是摄像头ID,value是Client实例。如果某个摄像头被占用了,其他进程再打开就会返回-EBUSY。所以上层一定要做好异常处理。
三、CameraClient管理
CameraClient是CameraService与上层APP之间的桥梁。每个打开的摄像头,都对应一个CameraClient实例。
Client的生命周期是这样的:
- 创建:APP调用connect(),CameraService创建CameraClient
- 初始化:Client内部创建CameraDevice,打开HAL
- 运行:处理上层发来的请求(拍照、预览等)
- 销毁:APP调用disconnect(),或者进程死亡,Client被清理
这里有个关键点:CameraService怎么管理多个Client?
说白了,就是用一个map来存。CameraService内部维护了:
// 伪代码,展示核心逻辑
sp<CameraClient> mClient;
status_t CameraService::connect(...) {
// 检查是否已有Client
if (mClient != nullptr) {
// 如果是同一个APP,可以重新连接
// 如果是不同APP,返回错误
return -EBUSY;
}
// 创建新Client
mClient = new CameraClient(this, cameraId, ...);
return OK;
}
嗯,这里要注意:Android 9之后引入了并发相机(concurrent camera)的支持。多个APP可以同时打开不同的摄像头。但同一个摄像头,同一时刻只能被一个APP使用。这个限制是硬件层面的,CameraService只是做了调度。
重要提醒:Client销毁时,一定要释放HAL资源。我曾经遇到一个bug,APP闪退后Client没有正确清理,导致下次打开相机时HAL还处于占用状态。后来在CameraService的binderDied()回调里加了强制清理逻辑才解决。
四、Client与HAL的交互
CameraClient不直接操作硬件,它通过CameraDevice来调用HAL。这个设计很巧妙——Client只关心业务逻辑,设备管理交给下层。
交互流程大致是:
- APP下发拍照请求 → CameraClient处理 → CameraDevice封装 → HAL执行
- HAL返回数据 → CameraDevice解析 → CameraClient回调 → APP收到结果
我个人习惯把CameraClient看作一个“状态机”。它有这些状态:
| 状态 | 含义 | 常见操作 |
|---|---|---|
| INITIAL | 刚创建,未打开设备 | initialize() |
| ACTIVE | 设备已打开,可以处理请求 | startPreview(), takePicture() |
| STOPPED | 停止流,但设备未关闭 | stopPreview() |
| DESTROYED | 已断开,等待回收 | disconnect() |
你想想看,如果APP在ACTIVE状态下突然调用disconnect(),Client会先停止所有流,再关闭设备,最后把自己从CameraService的map里移除。这个顺序不能乱,否则容易出问题。
总结一下:CameraService是相机框架的中枢神经。它负责启动、注册、权限校验、Client管理。而CameraClient是每个相机会话的代言人,管理着从打开到关闭的完整生命周期。理解了这两层,你就掌握了Android相机框架的核心脉络。
下一章我们会深入CameraDevice和HAL的交互细节,看看底层到底是怎么处理每一帧数据的。到时候再聊。