2. Camera HAL 架构解析:HAL3 Pipeline 模型、Camera Device Session、Request/Result 机制详解

Android Camera HAL3 架构的核心设计目标是 高吞吐、低延迟、可重入。与 HAL1 的同步、单线程模型不同,HAL3 引入了一套基于 Pipeline(流水线) 的异步处理框架,将拍照、预览、视频录制等操作抽象为统一的 Request/Result 交互模型。本章将深入剖析 HAL3 的三大核心概念:Pipeline 模型、Camera Device Session 生命周期以及 Request/Result 机制。

2.1 HAL3 Pipeline 模型

HAL3 的 Pipeline 模型将 Camera 硬件抽象为一条可配置的 处理流水线。每一帧图像从 Sensor 曝光到最终输出给 Framework,需要经过多个硬件模块(ISP、TNR、JPEG Encoder 等)的串行或并行处理。Pipeline 模型的核心优势在于:多帧并行处理 和 模块解耦。

关键设计原则: Pipeline 中的每个处理阶段(Stage)都是独立的“黑盒”,HAL 厂商可以自由替换或优化某个阶段,而不影响其他模块。Framework 通过配置不同的 Stream(流)来定义 Pipeline 的输出格式和分辨率。
HAL3 Pipeline 模型架构图 HAL3 Pipeline 模型架构 Sensor Bayer RAW ISP 处理 TNR 降噪 Output Pipeline 支持多 Stream 并行:预览流(YUV)、拍照流(JPEG)、视频流(HEVC)可同时处理 Pipeline 关键特性: • 多帧并行:Sensor 曝光第 N+2 帧时,ISP 正在处理第 N+1 帧,Output 正在输出第 N 帧。 • 模块可插拔:厂商可替换 TNR 算法模块,只需保证输入/输出格式一致。 • 延迟可控:每个 Stage 有独立的超时阈值,避免单点故障阻塞整条流水线。

2.2 Camera Device Session 生命周期

Session 是 HAL3 中 连接 Framework 与 Camera 硬件 的会话对象。一个 Camera Device 在同一时刻只能有一个活跃的 Session,但 Session 内部可以包含多个 Stream(数据流) 和 Request(请求)。Session 的生命周期管理直接决定了 Camera 的启动速度和资源占用。

Session 状态 触发动作 关键行为 常见问题
Idle Device 打开后 等待 Framework 创建 Session 资源未分配,功耗低
Configuring configure_streams() 调用 分配 Pipeline 资源、配置 Sensor 输出格式 Stream 配置冲突(如分辨率超出 Sensor 最大输出)
Active process_capture_request() 开始 Pipeline 全速运行,处理 Request/Result Request 超时、Buffer 饥饿
Flushing flush() 调用 丢弃所有待处理 Request,等待硬件空闲 Flush 未完成时收到新 Request
Closed close() 调用 释放所有硬件资源、销毁 Pipeline 资源泄漏(DMA Buffer 未释放)
移植适配要点: 在 configure_streams() 阶段,HAL 厂商必须根据 Sensor 的 实际输出能力 校验 Framework 请求的 Stream 组合。例如,若 Sensor 最大输出为 4000x3000,而 Framework 请求 4096x2160 的 YUV 流,HAL 应返回 -EINVAL 并建议降级。

2.3 Request/Result 机制详解

HAL3 使用 异步 Request/Result 模型替代了 HAL1 的同步操作。Framework 向 HAL 提交一个 CaptureRequest,HAL 在处理完成后通过回调返回 CaptureResult。这种机制允许 Framework 同时提交多个 Request,实现“流水线级”的并行处理。

2.3.1 Request 结构

一个标准的 CaptureRequest 包含以下核心字段:

// 伪代码:CaptureRequest 核心结构
struct CaptureRequest {
    uint32_t frame_number;          // 帧序号,单调递增
    camera_metadata_t *settings;    // 3A 参数、AE/AF/AWB 设置
    buffer_handle_t *output_buffers; // 输出 Buffer 数组(对应 Stream)
    uint32_t num_output_buffers;    // Buffer 数量
    int32_t sensor_timestamp;       // 可选:指定 Sensor 曝光时间戳
};

2.3.2 Result 回调流程

HAL 在处理完一帧后,通过以下三个回调将结果返回给 Framework:

  1. notify():发送错误事件(如 Sensor 故障、Buffer 丢失)或快门事件(Shutter)。
  2. process_capture_result():返回处理完成的 CaptureResult,包含最终 3A 参数、输出 Buffer 和元数据。
  3. process_capture_result() 中的 partial_result:支持部分结果返回,Framework 可提前获取部分元数据(如 AE 收敛状态)。
Request/Result 交互时序图 Request/Result 异步交互时序 Framework HAL3 CaptureRequest (frame=100) notify() → SHUTTER process_capture_result() → partial=1 process_capture_result() → final (frame=100) 注意:HAL 必须在 notify(SHUTTER) 之后才能返回 process_capture_result(),且 frame_number 必须严格递增。

2.4 关键数据结构对比

数据结构 方向 包含内容 生命周期
CaptureRequest Framework → HAL settings、output_buffers、input_buffer(ZSL) 提交后由 HAL 持有,直到 Result 返回
CaptureResult HAL → Framework metadata、output_buffers、partial_result 标志 HAL 分配,Framework 释放 Buffer
Stream 配置阶段 format、resolution、usage flags、max_buffers Session 生命周期内有效
Buffer 双向 handle、stride、size、timestamp 由 Gralloc 分配,Framework 和 HAL 共享
常见移植陷阱: 在 HAL3 实现中,process_capture_request() 必须是非阻塞的。如果 HAL 在该函数中执行了硬件等待(如等待 Sensor 曝光完成),会导致 Framework 的 Request 队列阻塞,进而引发 ANR(应用无响应)。正确的做法是:将 Request 放入内部队列,立即返回,由工作线程异步处理。

2.5 实战要点总结

  • Pipeline 深度: 根据硬件能力配置合理的 Pipeline 深度(通常为 3~6 帧),过深会增加延迟,过浅会导致 Buffer 饥饿。
  • Session 复用: 避免频繁创建/销毁 Session,建议在 Camera 打开时创建,关闭时销毁。切换 Stream 配置时使用 configure_streams() 而非重建 Session。
  • Request 超时: 为每个 Request 设置硬件超时(如 500ms),超时后调用 notify(ERROR_REQUEST) 并丢弃该帧。
  • Partial Result: 善用 partial_result 提前返回 AE/AWB 状态,Framework 可以利用这些信息提前更新 UI 预览效果。