camera HAL参数传递与metadata扩展配置 - 第1节
1.1 Camera HAL 架构演进:从 HAL1 到 HAL3
Android Camera HAL(硬件抽象层)是 Framework 与底层 Camera 硬件驱动之间的中间层,其核心职责是屏蔽不同 SoC 和 Sensor 厂商的硬件差异,向上提供统一的操作接口。HAL 的架构设计直接决定了 Camera 系统的性能上限、功能丰富度以及可维护性。
1.1.1 HAL1 架构:基于预览流的同步模型
HAL1 是 Android 早期(2.x ~ 4.x)采用的 Camera HAL 架构,其设计围绕“预览流”展开,所有操作(预览、拍照、录像)都基于一个固定的预览 Surface 进行同步处理。
- 单线程同步模型:所有 Camera 操作(setParameters、startPreview、takePicture)在同一个线程中串行执行,任一操作阻塞会导致整个 Camera 卡死。
- 参数通过字符串传递:使用
setParameters(String)和getParameters()传递键值对,参数类型需手动序列化/反序列化,极易出错。 - 预览与拍照耦合:拍照时必须停止预览流,重新配置后再恢复,导致拍照黑屏或卡顿。
- 无 Buffer 管理权:HAL 不参与 Buffer 分配,完全依赖 CameraService 提供的 Surface。
setParameters 调用是同步且昂贵的,频繁调用(如每帧调整曝光)会导致预览帧率骤降。在 HAL1 时代,很多厂商通过“参数缓存 + 批量提交”来缓解此问题,但这增加了代码复杂度。
下图展示了 HAL1 的典型调用流程,注意预览与拍照之间的串行依赖关系:
1.1.2 HAL3 架构:基于 Request/Result 的异步管道模型
HAL3 从 Android 5.0 开始引入,彻底重构了 Camera 架构。其核心思想是“一次 Capture Request 对应一次 Capture Result”,将 Camera 抽象为一个可配置的异步处理管道,支持每帧独立的参数控制和高吞吐并发。
| 对比维度 | HAL1 | HAL3 |
|---|---|---|
| 参数传递方式 | setParameters(String) 字符串键值对 |
CameraMetadata 结构化 Metadata(ACameraMetadata) |
| 操作模型 | 同步串行,预览/拍照/录像互斥 | 异步管道,支持多路并发 Request |
| Buffer 管理 | 由 Framework 分配 Surface | HAL 通过 processCaptureRequest 管理输入/输出 Buffer |
| 每帧控制 | 全局参数,无法逐帧差异化 | 每个 Request 携带独立 Metadata,支持逐帧 AE/AWB/AF 控制 |
| 拍照黑屏 | 必须停止预览,存在黑屏 | 预览与拍照使用独立 Stream,无需停止 |
| 多摄像头支持 | 每个 Camera 独立 HAL 实例 | 支持逻辑摄像头(Multi-Camera)和物理摄像头映射 |
flush() 超时、Buffer 生命周期管理、Metadata 完整性校验。很多早期 HAL3 移植项目因未处理好 ERROR_REQUEST 和 ERROR_BUFFER 回调导致 CTS 测试失败。
HAL3 的 Request/Result 管道模型如下图所示,注意每个 Request 可以独立指定输出目标(Surface)和参数(Metadata):
1.2 Camera Provider 服务架构
从 Android 8.0(Treble 项目)开始,Camera HAL 被封装为独立的 Camera Provider 服务,运行在独立的进程空间中,通过 HIDL(Android 8~10)或 AIDL(Android 11+)与 CameraService 通信。这一变化彻底解耦了 Framework 和 HAL 的生命周期。
1.2.1 Provider 进程模型
Camera Provider 服务通常由 cameraserver 进程(CameraService 所在进程)通过 ICameraProvider 接口调用。Provider 内部可以管理多个 Camera 设备(ICameraDevice),每个设备对应一个物理或逻辑摄像头。
- 独立进程:Camera Provider 运行在
/vendor/bin/hw/android.hardware.camera.provider@X.Y-service进程中,与cameraserver隔离。 - 服务注册:Provider 启动后通过 HwBinder 注册到 ServiceManager,CameraService 通过 ServiceManager 发现并绑定 Provider。
- 设备管理:一个 Provider 可以暴露多个 Camera 设备(如 back_camera、front_camera、depth_camera),每个设备通过
getCameraDeviceInterface()获取。 - 生命周期隔离:Provider 进程崩溃不会导致 Framework 重启,CameraService 会检测到死亡通知并尝试重新连接。
下图展示了 Camera Provider 在 Android 系统中的位置和进程边界:
1.2.2 HIDL 与 AIDL 接口演进
| 接口类型 | Android 版本 | 关键特性 | 迁移原因 |
|---|---|---|---|
| HIDL | 8.0 ~ 10 | 稳定 ABI,支持 @1.0/@1.1/@2.0 版本化 | Treble 项目引入,分离 Framework 与 Vendor |
| AIDL | 11+ | 统一使用 AIDL,支持稳定 AIDL(Stable AIDL) | 减少接口碎片化,与系统服务接口统一 |
android.hardware.camera.provider 命名空间完全兼容。HIDL 版本将在未来 Android 版本中逐步废弃。
1.3 HAL 进程模型与内存隔离
Camera HAL 的进程模型经历了从“同进程”到“跨进程”的演变,这一变化对参数传递和 Metadata 配置产生了深远影响。
1.3.1 进程模型对比
| 模型 | Android 版本 | 进程布局 | 参数传递方式 | 优势 | 劣势 |
|---|---|---|---|---|---|
| 同进程 HAL | ≤ 7.x | HAL 作为 shared library 加载到 cameraserver | 直接函数调用,指针传递 | 延迟低,无 IPC 开销 | HAL 崩溃导致 cameraserver 崩溃;内存无隔离 |
| 独立进程 HAL | 8.0+ | HAL 运行在独立 Vendor 进程 | HwBinder/AIDL 序列化传递 | 进程隔离,崩溃不影响 Framework | IPC 开销,Metadata 需序列化/反序列化 |
1.3.2 跨进程参数传递的挑战
独立进程模型下,CameraMetadata 必须通过 Binder 序列化在进程间传递。这带来了几个关键挑战:
- 序列化开销:每个 Capture Request 中的 Metadata 需要从 Vendor 进程的地址空间复制到 cameraserver 进程,大尺寸 Metadata(如 3A 统计数据、人脸检测结果)会增加延迟。
- 内存限制:Binder 事务缓冲区默认限制为 1MB,如果 Metadata 包含大量动态数据(如多帧 HDR 的 LSC 表),可能超出限制导致事务失败。
- 指针失效:HAL1 时代常用的“指针传递 Buffer”方式不再可行,所有数据必须显式序列化。
hidl_memory 或 NativeHandle 共享内存,避免数据拷贝。
下图展示了跨进程参数传递的完整路径,注意 Metadata 的序列化/反序列化环节:
1.4 本章小结
本章从三个维度梳理了 Camera HAL 的基础架构:
- HAL1 → HAL3 演进:从同步串行的预览模型到异步并发的 Request/Result 管道模型,参数传递方式从字符串键值对升级为结构化 Metadata,每帧独立控制成为可能。
- Camera Provider 服务:Treble 项目将 HAL 封装为独立进程的 Provider 服务,通过 HIDL/AIDL 与 Framework 通信,实现了进程隔离和生命周期解耦。
- 进程模型与参数传递:独立进程模型带来了内存隔离和稳定性提升,但也引入了 Binder 序列化开销和内存限制,这对 Metadata 扩展配置的设计提出了新的要求。