HAL3 与 HAL2 架构对比:设计哲学、Pipeline 模型与 Stream 配置差异

Android Camera HAL 从 HAL2 演进到 HAL3,不仅仅是 API 版本的升级,更是对移动端相机工作流的根本性重构。HAL2 诞生于早期 Android 设备,设计上偏向“黑盒”与“固定管线”;而 HAL3 则引入了“灵活请求”与“分阶段处理”的哲学,为计算摄影、多帧融合和零延迟取景提供了底层支撑。理解这两者的差异,是掌握 Buffer 队列管理与帧同步优化的前提。

核心观点:HAL2 是“设备驱动”模型,HAL3 是“请求驱动”模型。HAL3 将控制权从 HAL 层转移到了 Camera Service 和 App 层,从而实现了更精细的帧级控制。

3.1 设计哲学:黑盒 vs 白盒

HAL2 的设计哲学可以概括为“一次配置,持续运行”。App 通过 Camera API 设置好预览尺寸、帧率和格式后,HAL 内部维护一个固定的处理管线,Sensor 持续输出帧,ISP 持续处理,Display 持续显示。这种模式简单、延迟低,但灵活性极差——任何参数变更(如切换分辨率、开启 HDR)都需要停止流、重新配置、再启动流,耗时可达数百毫秒。

HAL3 则采用了“请求-响应”模型。每一帧的采集和处理都由一个独立的 CaptureRequest 驱动。App 或 Camera Service 可以为每一帧指定不同的参数(曝光、增益、裁剪区域、输出目标等),HAL 根据请求动态调整 Sensor 和 ISP 的行为。这种设计使得多帧 HDR、人像虚化、超级夜景等需要逐帧参数变化的场景成为可能。

对比维度 HAL2 HAL3
控制粒度 流级别(Stream-level) 帧级别(Frame-level)
参数变更 需停止流 → 重配 → 启动流 逐帧下发 CaptureRequest
HAL 职责 维护固定管线状态 解析请求、调度硬件、返回结果
App 控制力 弱(仅能设置初始参数) 强(每帧可独立控制)
典型场景 基础拍照、固定帧率录像 计算摄影、多帧融合、零延迟
工程启示:HAL3 的“逐帧请求”模式虽然灵活,但对 Buffer 队列的吞吐能力和帧同步精度提出了极高要求。每一帧的 Request 必须与对应的 Result 和 Buffer 严格匹配,否则会导致“帧错位”或“Buffer 饥饿”。

3.2 Pipeline 模型:固定管线 vs 分阶段处理

HAL2 的 Pipeline 是一个“黑盒”顺序流水线。Sensor 输出 RAW 数据后,经过 ISP 处理、统计信息生成、编码/显示输出,所有步骤在 HAL 内部串联完成,外部无法干预中间结果。这种模型下,帧同步由 HAL 内部硬件同步信号(VSYNC)驱动,Buffer 队列管理相对简单——生产者(Sensor)和消费者(Display/Encoder)通过固定深度的环形 Buffer 交互。

HAL3 引入了“分阶段处理”模型,将 Pipeline 拆解为三个逻辑阶段:Sensor 阶段(曝光、RAW 输出)、ISP 阶段(YUV/JPEG 处理)、Post-processing 阶段(人脸检测、HDR 融合等)。每个阶段都可以独立配置输出目标,并且允许 App 通过 CaptureRequest 中的 android.control.* 参数控制每个阶段的行为。

HAL3 分阶段 Pipeline 模型 Sensor 阶段 曝光 · RAW 输出 ISP 阶段 YUV/JPEG 处理 Post-processing HDR · 人脸检测 RAW Buffer YUV/Display Buffer JPEG/Encoded Buffer 每个阶段可独立配置输出目标,App 通过 CaptureRequest 控制各阶段参数。 Buffer 队列在阶段间传递,帧同步需保证 Request ID 与 Buffer 一一对应。
常见陷阱:在 HAL3 分阶段模型中,如果 Sensor 阶段和 ISP 阶段的 Buffer 队列深度不匹配,或者帧同步信号(FrameNumber)传递丢失,会导致“帧撕裂”或“Buffer 死锁”。这是 HAL3 调试中最常见的问题之一。

3.3 Stream 配置差异:固定集合 vs 灵活组合

HAL2 的 Stream 配置是“静态集合”。App 在打开 Camera 时指定一组固定的 Stream(如预览流、拍照流、录像流),HAL 内部为每个 Stream 分配固定的 Buffer 队列和硬件资源。一旦配置完成,Stream 的数量、格式、尺寸都不能动态变更。如果需要切换分辨率,必须关闭所有 Stream 并重新配置。

HAL3 引入了 StreamConfigurationMap 和 SessionConfiguration 机制,允许 App 在创建 Session 时灵活组合多个 Stream,并且支持 dynamic resolution switching(动态分辨率切换)。关键差异包括:

  • Stream 类型:HAL3 定义了 INPUT(输入流,用于 reprocessing)和 OUTPUT(输出流)两种类型,HAL2 只有输出流。
  • Buffer 格式:HAL3 支持更丰富的格式组合(如 RAW10、YUV420、NV21、HEIC),且允许同一 Session 内不同 Stream 使用不同格式。
  • Stream 复用:HAL3 允许一个 Stream 被多个 Consumer 共享(如预览和录像共用同一 YUV 流),通过 Buffer 队列的“引用计数”机制实现。
  • 配置延迟:HAL2 的配置延迟通常为 200-500ms(停止流 + 重配 + 启动流),HAL3 的 configureStreams 调用延迟可优化至 50ms 以内。
配置维度 HAL2 HAL3
配置时机 Camera 打开时一次性配置 Session 创建时配置,支持动态更新
Stream 数量 固定(通常 2-3 个) 灵活(最多可达 8-10 个)
输入流支持 不支持 支持(用于 reprocessing)
格式灵活性 低(通常固定 YUV+JPEG) 高(RAW/YUV/JPEG/HEIC 混搭)
分辨率切换 需停止所有流 支持动态切换(需 HAL 实现)
Buffer 队列管理 每个 Stream 独立队列 支持跨 Stream Buffer 共享
HAL3 Stream 配置与 Buffer 队列关系 Camera Service Session Stream 1: Preview YUV 1920x1080 Stream 2: Capture JPEG 4000x3000 Stream 3: RAW RAW10 4000x3000 Buffer Queue (depth=4) Buffer Queue (depth=2) Buffer Queue (depth=1)
性能优化建议:在 HAL3 中,预览流(YUV)的 Buffer 队列深度通常设置为 4-6 帧,以容忍短暂的 ISP 处理抖动;拍照流(JPEG)的队列深度设置为 2 帧即可,因为 JPEG 编码是异步的;RAW 流通常设置为 1 帧,因为 RAW 数据量大且不需要高吞吐。合理配置队列深度可以显著降低内存占用和延迟。

3.4 帧同步机制对比

HAL2 的帧同步依赖硬件 VSYNC 信号。Sensor 在 VSYNC 上升沿开始曝光,曝光完成后触发 ISP 处理,ISP 处理完成后通知 Display/Encoder 消费。整个流程是“推模式”(Push Model),HAL 内部维护一个单调递增的帧计数器,Buffer 按顺序消费,无需显式的帧号匹配。

HAL3 的帧同步则采用“拉模式”(Pull Model)结合显式帧号。每一帧的流程如下:

  1. App 下发 CaptureRequest,携带唯一的 FrameNumber。
  2. HAL 的 processCaptureRequest 接收请求,将 FrameNumber 传递给 Sensor 和 ISP 硬件。
  3. Sensor 曝光完成后,HAL 通过 notify() 回调 SHUTTER 事件,携带 FrameNumber。
  4. ISP 处理完成后,HAL 通过 processCaptureResult 返回 CaptureResult,其中包含 FrameNumber 和对应的 Buffer。
  5. Camera Service 根据 FrameNumber 将 Request、Result 和 Buffer 进行匹配,确保帧级一致性。
关键差异:HAL2 的帧同步是“隐式”的(依赖硬件顺序),HAL3 的帧同步是“显式”的(依赖 FrameNumber 匹配)。HAL3 的显式机制虽然增加了复杂度,但允许乱序返回结果——例如,第 5 帧的 Result 可以在第 6 帧的 Result 之后返回,只要 FrameNumber 正确匹配即可。

这种显式帧同步机制对 Buffer 队列管理提出了新要求:

  • Buffer 必须携带 FrameNumber 标签:每个 Buffer 在队列中必须关联其所属的 FrameNumber,以便在乱序返回时正确匹配。
  • 队列必须支持“按帧号查找”:当 HAL 返回 Result 时,Camera Service 需要根据 FrameNumber 在队列中查找对应的 Request 和 Buffer。
  • 超时处理:如果某个 FrameNumber 的 Result 长时间未返回(超过 1-2 秒),Camera Service 会触发“帧超时”错误,并尝试恢复或关闭 Session。
帧同步维度 HAL2 HAL3
驱动模式 硬件 VSYNC 推模式 请求拉模式 + 显式帧号
帧号管理 HAL 内部维护 App/Camera Service 下发
乱序返回 不支持(严格顺序) 支持(按 FrameNumber 匹配)
Buffer 匹配 按队列顺序匹配 按 FrameNumber 显式匹配
超时处理 无(硬件保证顺序) 有(1-2 秒超时阈值)
调试要点:在 HAL3 开发中,最常见的帧同步 Bug 是“FrameNumber 不连续”或“Buffer 与 FrameNumber 错位”。建议在 HAL 实现中增加日志,打印每个 Request 的 FrameNumber 和对应的 Buffer 地址,以便快速定位问题。