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 模型的核心优势在于:多帧并行处理 和 模块解耦。
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 未释放) |
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:
- notify():发送错误事件(如 Sensor 故障、Buffer 丢失)或快门事件(Shutter)。
- process_capture_result():返回处理完成的
CaptureResult,包含最终 3A 参数、输出 Buffer 和元数据。 - process_capture_result() 中的 partial_result:支持部分结果返回,Framework 可提前获取部分元数据(如 AE 收敛状态)。
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 共享 |
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 预览效果。