4. Camera Provider进程

各位同学,今天我们来聊聊Camera HAL层最核心的一个话题——Camera Provider进程。说实话,这个知识点我当年刚接触时也绕了不少弯路。你想想看,Framework层怎么找到HAL层的?它们之间怎么通信的?这一切都离不开Camera Provider这个“中间人”。

1.1 从Treble架构说起

Android 8.0引入Treble架构,说白了就是把Framework和HAL彻底解耦。以前HAL是以.so的形式直接加载到系统进程里,现在不行了——HAL必须跑在独立的进程中。

为什么要这么干?我遇到过最典型的场景:某厂商的Camera HAL有内存泄漏,如果是旧架构,整个系统都得重启。现在呢?Provider进程挂了,Framework还能优雅地重新拉起它。这就是隔离的好处。

核心变化:HAL从“共享库”变成了“独立服务”

1.2 Camera Provider进程长什么样

Camera Provider其实是一个独立的Native进程,它的注册名是android.hardware.camera.provider@2.4-service或@2.5-service。这个进程启动后,会向HwServiceManager注册自己。

我们来看一下它的启动入口,通常在device/xxx/init.rc里定义:

service camera-provider-2-4 /vendor/bin/hw/android.hardware.camera.provider@2.4-service
    class hal
    user cameraserver
    group audio camera input drmrpc
    capabilities SYS_NICE
    task_profiles CameraServiceCapacity

嗯,这里要注意user cameraserver这一行。我曾经踩过一个坑——权限配置不对,Provider进程死活起不来,最后发现是SELinux策略没加。所以大家做移植时,一定要检查file_contexts和te文件。

1.3 HIDL服务注册流程

进程启动后,会调用defaultPassthroughServiceImplementation()或者手动注册。我们以2.4版本为例,核心代码在CameraProvider.cpp里:

int main() {
    ALOGI("Camera provider service starting...");
    
    // 创建CameraProvider实例
    sp<ICameraProvider> provider = new CameraProvider();
    
    // 注册到HwServiceManager
    status_t status = provider->registerAsService("legacy/0");
    
    if (status != OK) {
        ALOGE("Failed to register camera provider: %d", status);
        return 1;
    }
    
    ALOGI("Camera provider service is ready");
    
    // 进入事件循环
    joinRpcThreadpool();
    return 0;
}

流程其实很清晰:

  1. 创建Provider对象——这里会初始化底层Camera设备
  2. 调用registerAsService——向HwServiceManager注册
  3. 进入RPC线程池——等待Framework调用

个人经验:我建议在registerAsService之前加一些健康检查。比如确认底层硬件是否正常,否则注册成功了但后面调用失败,排查起来更麻烦。

1.4 Framework与HAL的通信机制

通信机制说白了就是Binder的变种——HwBinder。Framework进程通过HwServiceManager拿到Provider的代理,然后直接调用HIDL接口。

整个调用链路是这样的:

App进程 → CameraService(Framework) → HwBinder → CameraProvider(HAL) → 底层驱动

这里有个关键点:HwBinder和普通Binder有什么区别?

特性 普通Binder HwBinder
服务注册 ServiceManager HwServiceManager
接口定义 AIDL HIDL
进程隔离 支持 强制隔离
稳定性 一般 高(版本化接口)

我个人觉得HwBinder最大的优势是接口版本化。比如CameraProvider@2.4和@2.5可以共存,Framework可以根据需要选择。这在系统升级时特别有用——老设备用2.4,新设备用2.5,互不干扰。

1.5 服务发现过程

Framework怎么找到Provider的?我们来看CameraService的代码:

sp<ICameraProvider> provider = ICameraProvider::getService("legacy/0");
if (provider == nullptr) {
    ALOGE("Cannot get camera provider service");
    return;
}

这行代码背后发生了什么?

  • 首先,getService会通过HwServiceManager查找
  • 如果没找到,它会等待(默认5秒)
  • 如果超时,返回nullptr

避坑指南:我曾经遇到一个情况——Provider进程启动太慢,Framework超时了。后来我们在init.rc里加了on property:init.svc.camera-provider-2-4=running的触发条件,确保Provider完全启动后再启动CameraService。

1.6 2.4 vs 2.5 版本差异

很多同学问:2.4和2.5到底差在哪?我简单总结一下:

  • 2.4:基础功能,支持单摄像头、基本配置
  • 2.5:增加了isStreamCombinationSupported接口,支持更灵活的流组合查询

说白了,2.5就是2.4的增强版。如果你的设备需要复杂的多摄像头场景,建议用2.5。但要注意,2.5不是2.4的替代品,它们是并存的。

1.7 整体架构图

下面我用一张图来总结Camera Provider在整个系统中的位置:

Framework层(System Server进程) CameraService HwServiceManager 查找Provider HIDL 接口层(@2.4 / @2.5) HwBinder调用 HAL层(Camera Provider进程) CameraProvider@2.4 CameraProvider@2.5 内核层(Kernel) Camera驱动 / V4L2 / ISP 图1:Camera Provider架构图 - 进程隔离与HwBinder通信

从这张图可以看得很清楚:CameraService在Framework层,CameraProvider在HAL层,中间通过HIDL接口和HwBinder通信。两层完全隔离,互不依赖对方的实现细节。

1.8 小结

这一章我们主要讲了Camera Provider进程的启动流程和通信机制。核心就三点:

  • Provider是一个独立进程,通过init.rc启动
  • 它向HwServiceManager注册HIDL服务
  • Framework通过HwBinder远程调用HAL接口