一、CameraProvider 服务:HIDL 服务架构与启动流程
各位同学,今天我们来聊聊 CameraProvider 这个服务。说实话,这个模块在 Android 相机系统里属于「幕后英雄」—— 平时你可能感觉不到它的存在,但一旦出了问题,你才会发现它有多重要。
我个人习惯把 CameraProvider 理解为「硬件抽象层的看门人」。它负责把底层的摄像头硬件能力,通过 HIDL 接口暴露给上层。说白了,它就是 CameraService 和硬件之间的翻译官。
1.1 HIDL 服务架构
先说说 HIDL。HAL Interface Definition Language,这是 Android Treble 项目引入的核心技术。它的目标很明确:把 vendor 实现和 framework 实现彻底解耦。
在 Treble 之前,Camera HAL 是以 .so 库的形式直接加载到 CameraService 进程里的。这意味着什么?意味着你升级一次系统,所有 HAL 都得重新编译。我在项目中遇到过,某厂商的 HAL 库在 Android 8.0 升级时直接崩了,因为接口对不上了。
Treble 之后,HIDL 服务变成了独立的进程。CameraProvider 作为一个 HIDL 服务,跑在单独的进程中,通过 Binder 化的 HIDL 接口与 CameraService 通信。结构大概是这样的:
嗯,这里要注意:HIDL 接口是分版本的。比如 android.hardware.camera.provider@2.4、@2.5、@2.6 等等。每个版本都会增加一些新功能。我记得在 @2.5 版本里,Google 加入了 Torch 模式的支持,当时我们适配的时候还踩了个坑——某些老设备不支持,但接口返回了成功。
1.2 CameraProvider 启动流程
启动流程其实不复杂,但细节很多。我们一步步来看:
- init 进程解析 rc 文件:CameraProvider 的启动脚本通常在
/vendor/etc/init/目录下,比如android.hardware.camera.provider@2.4-service.rc。 - 注册 HIDL 服务:进程启动后,会调用
registerAsService()把自己注册到 HIDL Service Manager 中。 - CameraService 发现服务:CameraService 通过
getService()获取 CameraProvider 的代理。 - 枚举摄像头:CameraService 调用
getCameraIdList()获取所有可用的摄像头 ID。
我曾经在调试一个启动时序问题时发现,如果 CameraProvider 启动慢了,CameraService 会超时重试。默认超时是 5 秒,但某些低端设备启动时间超过 8 秒,导致相机应用打不开。解决方案?在 rc 文件里加了个 class main 和 on boot 的依赖,确保 Provider 先启动。
核心要点:CameraProvider 的启动是异步的。CameraService 不会阻塞等待,而是通过 HIDL 的死亡通知机制来监听 Provider 的状态。如果 Provider 挂了,CameraService 会尝试重新连接。
1.3 CameraService 与 Provider 交互
交互过程说白了就是「一问一答」。CameraService 是客户端,CameraProvider 是服务端。典型的交互流程如下:
| 步骤 | 调用方 | HIDL 接口 | 说明 |
|---|---|---|---|
| 1 | CameraService | getCameraIdList() | 获取摄像头列表 |
| 2 | CameraService | getCameraDeviceInterface() | 获取某个摄像头的设备接口 |
| 3 | CameraService | isTorchModeSupported() | 检查闪光灯模式支持 |
| 4 | CameraService | setCallback() | 注册回调,接收状态变化 |
你想想看,这个交互模型其实很脆弱。如果 Provider 进程挂了,CameraService 手里的所有代理对象都会变成「僵尸」。所以 Google 引入了 ICameraDeviceCallback 机制,让 Provider 可以主动通知 CameraService 状态变化。
个人经验:我在做 CTS 测试时发现,某些厂商的 Provider 实现里,getCameraIdList() 返回的列表顺序是固定的。但 Google 的测试用例期望按逻辑 ID 排序。结果就是测试挂了。解决方案?在 Provider 里加个排序逻辑,或者让 HAL 层保证顺序。
1.4 Treble 化影响
Treble 化对 CameraProvider 的影响,我觉得可以用三个词概括:隔离、标准化、升级友好。
- 隔离:Provider 进程和 CameraService 进程完全隔离。一个 crash 不会影响另一个。我记得以前在 Android 7.0 上,HAL 层一个空指针就能把整个系统相机搞死。现在?Provider 重启一下就恢复了。
- 标准化:HIDL 接口是强制要求的。厂商不能随便改接口。这其实是个双刃剑——好处是兼容性好,坏处是厂商想加私有功能变得困难了。
- 升级友好:Framework 升级不需要重新编译 HAL。只要 HIDL 接口不变,vendor 镜像可以保持不变。这对 OEM 来说是天大的好事。
注意:Treble 化不是万能的。如果 HIDL 接口版本升级了(比如从 @2.4 升到 @2.5),老的 Provider 实现必须同步更新。否则 CameraService 会检测到版本不匹配,直接拒绝连接。我曾经在项目里遇到过,Google 强制要求升级到 @2.6,结果某厂商的 HAL 实现没跟上,导致相机无法启动。
嗯,最后说一句。Treble 化之后,CameraProvider 的调试也变得更复杂了。以前你可以在 CameraService 进程里直接打 log 看 HAL 的行为。现在?你得同时看两个进程的 log。我个人的习惯是,在 Provider 的 log 里加一个唯一的 tag,比如 CamProvider,然后用 logcat -s CamProvider 单独过滤。
好了,这一章的内容就到这里。CameraProvider 虽然看起来只是一个「中间人」,但它的设计思路——HIDL 服务化、进程隔离、接口标准化——其实是整个 Android 系统架构演进的缩影。理解了它,你就理解了 Treble 的精髓。
公众号:蓝海资料掘金营,微信 deep3321