第1章:Camera Provider进程:HIDL服务启动流程
各位同学,今天我们来聊聊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;
}
流程其实很清晰:
- 创建Provider对象——这里会初始化底层Camera设备
- 调用registerAsService——向HwServiceManager注册
- 进入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在整个系统中的位置:
从这张图可以看得很清楚:CameraService在Framework层,CameraProvider在HAL层,中间通过HIDL接口和HwBinder通信。两层完全隔离,互不依赖对方的实现细节。
1.8 小结
这一章我们主要讲了Camera Provider进程的启动流程和通信机制。核心就三点:
- Provider是一个独立进程,通过init.rc启动
- 它向HwServiceManager注册HIDL服务
- Framework通过HwBinder远程调用HAL接口
嗯,这些概念理解了,后面讲Camera HAL的具体实现就会顺畅很多。下一章我们深入CameraProvider的内部实现,看看它怎么管理Camera设备的。