1、Camera Framework 概述:Android相机架构全景

说实话,Android相机框架是我在系统开发中遇到过最复杂的模块之一。它不像你写个普通App,调个API就完事了。相机这东西,涉及硬件、驱动、服务层、应用层,层层嵌套。我刚开始接触时,也被这庞大的架构搞得晕头转向。

但别怕,咱们一步步拆解。今天这一章,就是整个课程的地基。地基打牢了,后面30章你才能站得稳。

Android相机架构全景

先给你画个全景图。Android相机系统,说白了就是一条流水线:

  • 最底层:摄像头硬件传感器(CMOS、ISP)
  • 中间层:HAL层(硬件抽象层)+ CameraProvider
  • 核心层:CameraService(系统服务)
  • 上层:CameraDevice + CameraManager(给App用的API)
  • 最顶层:你的App或者系统相机应用

嗯,这里要注意:每一层都有自己独立的进程空间。为什么?因为相机数据量大,而且涉及权限和安全。分层隔离,是Android设计者的智慧。

核心观点:Camera Framework不是单指某个服务,而是从硬件到应用的一整套通信协议和组件集合。你写的App调用的每一个capture(),背后都经历了至少4个进程的协作。

我个人习惯把相机架构比作一个「管道系统」。App是水龙头,CameraService是阀门,CameraProvider是水泵,硬件就是水源。任何一个环节堵了,水就出不来。

Android Camera Framework 全景架构图 应用层 (App / Camera2 API) Framework层 (CameraManager / CameraDevice) CameraService (系统服务 / 核心调度) CameraProvider (HAL层 / 硬件抽象) 硬件层 (Camera Sensor / ISP) 进程边界

Camera Framework 在系统中的位置

你想想看,Android系统里跑着几十个系统服务。ActivityManager管界面,WindowManager管窗口,那CameraService管什么?

说白了,CameraService就是相机世界的「交通警察」。它负责:

  • 管理所有摄像头设备的生命周期
  • 协调多个App同时访问相机的冲突
  • 转发App的请求到HAL层
  • 把硬件产生的数据流回传给App

我记得有一次排查线上问题,发现某个App打开相机后一直黑屏。查了半天,原来是CameraService在初始化时,和Provider之间的Binder通信超时了。这种问题,如果你不了解Framework的位置,根本无从下手。

避坑指南:我曾经在调试时发现,CameraService运行在system_server进程里。这意味着如果相机模块崩溃,整个系统服务都会受影响。所以,千万别在CameraService里做耗时操作。

核心组件介绍

1. CameraService

CameraService是Android相机系统的「大脑」。它运行在system_server进程中,以系统服务的形式存在。它的主要职责包括:

  • 设备管理:枚举所有摄像头,管理它们的打开/关闭状态
  • 权限控制:检查App是否有相机权限
  • 会话管理:创建和管理CameraDeviceSession
  • 数据分发:把HAL层返回的帧数据分发给对应的App

代码层面,CameraService的核心实现在 frameworks/av/services/camera/libcameraservice/ 目录下。你如果去看源码,会发现它主要继承自 BnCameraService,通过Binder与客户端通信。

// CameraService 的核心接口(简化)
class CameraService : public BnCameraService {
public:
    // 打开一个摄像头设备
    status_t connect(const sp<ICameraClient>& client, 
                     int cameraId, 
                     /* 输出 */ sp<ICameraDevice>& device);
    
    // 获取摄像头信息列表
    status_t getCameraInfo(int cameraId, 
                           struct CameraInfo* cameraInfo);
    
    // 添加/移除摄像头(热插拔)
    status_t addCamera(const String16& cameraId);
    status_t removeCamera(const String16& cameraId);
};

嗯,这里要注意:CameraService并不直接操作硬件。它只是调度者。真正干活的,是下面的CameraProvider。

2. CameraProvider

CameraProvider是Android 8.0之后引入的组件。它把HAL层独立成了一个单独的进程。为什么这么做?

原因很简单:HAL层是厂商实现的,质量参差不齐。如果HAL崩溃了,不能让它把整个系统服务拖下水。独立进程,意味着HAL挂了,CameraService还能活着。

CameraProvider的核心职责:

  • 加载厂商提供的HAL库(如 camera.provider.so
  • 实现ICameraProvider接口,暴露给CameraService调用
  • 管理底层CameraDevice的创建和销毁
  • 处理硬件事件(如闪光灯、对焦、变焦)

注意:CameraProvider和CameraService之间通过HIDL(Android 8~10)或AIDL(Android 11+)通信。如果你在开发中遇到「Service not registered」的错误,多半是Provider进程没启动或者挂了。

我遇到过最坑的一次,是某款手机在低电量时,CameraProvider进程被LMK(Low Memory Killer)给杀了。结果相机App打开后一直卡在「正在启动相机」界面。后来我们在Provider进程里加了前台服务的优先级,才算解决。

3. CameraDevice

CameraDevice是App直接打交道的对象。在Camera2 API中,你通过 CameraManager.openCamera() 获取的就是一个 CameraDevice 实例。

它代表了一个物理或逻辑摄像头。每个CameraDevice可以创建多个 CaptureSession,用来发送拍照或录像请求。

CameraDevice的核心状态机:

状态 说明 常见触发
UNINITIALIZED 未初始化 刚创建时
OPENED 已打开,但未创建会话 openCamera() 成功后
CONFIGURED 已配置,可发送请求 createCaptureSession() 成功后
ERROR 错误状态 硬件异常或断开连接
CLOSED 已关闭 close() 调用后

你想想看,为什么CameraDevice要设计这么多状态?因为相机硬件是独占资源。如果不做状态管理,两个App同时打开同一个摄像头,那不乱套了?

我个人习惯在调试时,先检查CameraDevice的状态。很多「拍照黑屏」的问题,其实是因为设备处于ERROR状态,但App没有正确处理回调。

// CameraDevice 典型使用流程
CameraManager manager = (CameraManager) getSystemService(CAMERA_SERVICE);
String cameraId = manager.getCameraIdList()[0];

// 打开设备
manager.openCamera(cameraId, new CameraDevice.StateCallback() {
    @Override
    public void onOpened(@NonNull CameraDevice device) {
        // 设备已打开,可以创建会话了
        device.createCaptureSession(...);
    }
    
    @Override
    public void onDisconnected(@NonNull CameraDevice device) {
        // 设备断开连接,需要释放资源
        device.close();
    }
    
    @Override
    public void onError(@NonNull CameraDevice device, int error) {
        // 出错了!检查 error code
        Log.e("Camera", "Error: " + error);
    }
}, null);

总结一下:CameraService是调度中心,CameraProvider是硬件代理,CameraDevice是App的接口。三者通过Binder/HIDL串联起来,构成了Android相机框架的骨架。

这一章的内容,说白了就是让你对整个相机架构有个「上帝视角」。后面每一章,我们都会深入其中一个组件,把代码一行行拆开看。但今天,你只要记住这三者的关系和位置就够了。

嗯,我建议你打开Android源码,找到 frameworks/av/services/camera/ 目录,先浏览一下文件结构。不用看懂代码,先感受一下模块的划分。这对后续学习非常有帮助。


公众号:蓝海资料掘金营,微信deep3321