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 进行同步处理。

HAL1 核心特征:
  • 单线程同步模型:所有 Camera 操作(setParameters、startPreview、takePicture)在同一个线程中串行执行,任一操作阻塞会导致整个 Camera 卡死。
  • 参数通过字符串传递:使用 setParameters(String) 和 getParameters() 传递键值对,参数类型需手动序列化/反序列化,极易出错。
  • 预览与拍照耦合:拍照时必须停止预览流,重新配置后再恢复,导致拍照黑屏或卡顿。
  • 无 Buffer 管理权:HAL 不参与 Buffer 分配,完全依赖 CameraService 提供的 Surface。
避坑提示:HAL1 的 setParameters 调用是同步且昂贵的,频繁调用(如每帧调整曝光)会导致预览帧率骤降。在 HAL1 时代,很多厂商通过“参数缓存 + 批量提交”来缓解此问题,但这增加了代码复杂度。

下图展示了 HAL1 的典型调用流程,注意预览与拍照之间的串行依赖关系:

HAL1 架构调用流程 HAL1 架构:预览与拍照串行流程 App 请求预览 CameraService HAL1 预览 显示/编码 App 请求拍照 停止预览 拍照处理 返回 JPEG 恢复预览 关键瓶颈:拍照必须停止预览 → 重新配置 → 恢复预览,导致拍照黑屏(通常 200~500ms)

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)和物理摄像头映射
迁移注意事项:HAL3 虽然功能强大,但对 HAL 实现方的要求也更高:必须正确处理 flush() 超时、Buffer 生命周期管理、Metadata 完整性校验。很多早期 HAL3 移植项目因未处理好 ERROR_REQUEST 和 ERROR_BUFFER 回调导致 CTS 测试失败。

HAL3 的 Request/Result 管道模型如下图所示,注意每个 Request 可以独立指定输出目标(Surface)和参数(Metadata):

HAL3 Request/Result 管道模型 HAL3 异步管道:Request/Result 模型 App CameraService Request 队列 HAL3 实现 Result 回调(异步) 每帧独立控制示例:连续 3 帧 Request 携带不同参数 Frame 1: AE=auto, AF=auto Frame 2: AE=lock, AF=macro Frame 3: AE=-1EV, AF=inf 每个 Request 独立包含 Metadata,HAL3 按序处理并返回对应 Result

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),每个设备对应一个物理或逻辑摄像头。

Provider 进程模型关键点:
  • 独立进程: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 系统中的位置和进程边界:

Camera Provider 进程架构 Camera Provider 服务进程架构 Framework 进程 (cameraserver) CameraService ICameraProvider 客户端 HwBinder / AIDL 通信 Vendor 进程 (Provider) CameraProvider@X.Y-service ICameraDevice (HAL3 实现) Provider 管理的 Camera 设备 Camera 0: 后置主摄 (IMX586) Camera 1: 前置摄像头 (OV32B) Camera 2: 超广角 (IMX350) Camera 3: 深度摄像头 (ToF) 每个设备通过 getCameraDeviceInterface() 暴露

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 12+,请优先使用 AIDL Camera Provider。AIDL 支持更简洁的接口定义、自动生成的 Java/C++ 绑定,并且与 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”方式不再可行,所有数据必须显式序列化。
性能陷阱:在独立进程 HAL 中,如果每帧都传递大尺寸的 Vendor Tag 数据(如自定义的 ISP 统计信息),Binder 序列化时间可能超过 5ms,直接吃掉帧预算。解决方案是使用 hidl_memory 或 NativeHandle 共享内存,避免数据拷贝。

下图展示了跨进程参数传递的完整路径,注意 Metadata 的序列化/反序列化环节:

跨进程 Metadata 传递路径 跨进程 CameraMetadata 传递路径 CameraService 构造 Request Metadata Binder 序列化 Metadata → Parcel IPC 传输 HwBinder Binder 反序列化 Parcel → Metadata 性能关键点:序列化/反序列化是跨进程调用的主要开销 • 小 Metadata(< 1KB):序列化时间约 0.1ms,可忽略 • 大 Metadata(> 10KB):序列化时间可达 2~5ms,需优化 • 超大 Metadata(> 100KB):建议使用共享内存(hidl_memory)绕过 Binder 限制

1.4 本章小结

本章从三个维度梳理了 Camera HAL 的基础架构:

  • HAL1 → HAL3 演进:从同步串行的预览模型到异步并发的 Request/Result 管道模型,参数传递方式从字符串键值对升级为结构化 Metadata,每帧独立控制成为可能。
  • Camera Provider 服务:Treble 项目将 HAL 封装为独立进程的 Provider 服务,通过 HIDL/AIDL 与 Framework 通信,实现了进程隔离和生命周期解耦。
  • 进程模型与参数传递:独立进程模型带来了内存隔离和稳定性提升,但也引入了 Binder 序列化开销和内存限制,这对 Metadata 扩展配置的设计提出了新的要求。