3. CaptureResult 与 CaptureRequest 的对应关系:result metadata、partial result、shutter callback、buffer status

在 Android Camera HAL3 架构中,每一个 CaptureRequest 的提交都会触发一个或多个 CaptureResult 的回调。理解这两者之间的对应关系,是定位 HAL 链路异常、校验参数传递正确性的核心基础。本章将深入剖析 result metadata、partial result、shutter callback 以及 buffer status 四个关键概念,并阐明它们如何共同构成一次完整的 capture 生命周期。

3.1 核心对应关系总览

一个 CaptureRequest 从提交到完成,HAL 会按顺序产生以下三类回调:

  • shutter callback:通知框架曝光开始的时间戳。
  • partial result:中间状态的 metadata 片段,允许框架提前处理部分数据。
  • final result:包含完整 metadata 和所有 buffer 的最终结果。

下表总结了每个回调与原始 Request 的对应关系:

回调类型 触发时机 包含内容 与 Request 的对应关系
shutter callback 传感器开始曝光时 曝光开始时间戳 (timestamp) 一对一,每个 Request 最多一次
partial result HAL 处理过程中 部分 metadata keys(如 sensor 状态、3A 结果) 零到多次,按 partial result count 配置
final result 所有处理完成时 完整 metadata + 所有 buffer 状态 一对一,每个 Request 最终一次
关键原则: 框架通过 requestId 将 result 与原始 request 绑定。在调试时,务必检查 result 中的 android.request.id 是否与预期一致。

3.2 result metadata:从 Request 到 Result 的传递链

CaptureResult 中的 metadata 是 HAL 对 CaptureRequest 中参数的响应。并非所有 request 中的 key 都会出现在 result 中,只有 HAL 实际使用的 key 才会被回传。下图展示了 metadata 的传递与校验链路:

CaptureRequest → CaptureResult Metadata 传递链路 CaptureRequest HAL 处理 CaptureResult 关键校验点: 1. Request 中的 android.control.aeMode 是否在 Result 的 android.control.aeState 中体现? 2. Request 中的 android.sensor.sensitivity 是否被 HAL 正确应用? 3. Result 中是否出现了 Request 中未定义的 key?(可能为 HAL 内部状态泄漏) 4. 所有 mandatory keys 是否都已出现在 final result 中?

3.3 partial result:中间状态的分段交付

HAL3 允许通过 android.request.partialResultCount 配置 partial result 的数量。每个 partial result 包含一部分 metadata,框架可以在收到所有 partial result 之前就开始处理某些数据(如预览帧的 3A 状态)。

调试要点: 如果 HAL 返回的 partial result 数量少于 partialResultCount,框架会一直等待,导致 result timeout。这是常见的 HAL 实现 bug。

partial result 的典型使用场景:

  • 第 1 个 partial result:通常包含 sensor 时间戳、曝光参数。
  • 第 2 个 partial result:包含 3A 状态(AE/AWB/AF)。
  • 第 3 个 partial result:包含统计信息或后处理参数。
  • final result:包含所有 metadata + buffer 状态。

3.4 shutter callback:曝光时间戳的精确锚点

shutter callback 是 HAL 通知框架传感器开始曝光的关键事件。它携带一个 timestamp,该时间戳必须与 result metadata 中的 android.sensor.timestamp 一致。

属性 说明 常见异常
触发时机 传感器开始积分(曝光)时 HAL 在曝光前或曝光后很久才调用
时间戳来源 通常来自 sensor 的硬件时间戳 使用系统时间而非硬件时间,导致同步偏差
与 result 的关系 必须早于 final result 的 timestamp shutter 时间戳晚于 result 时间戳(时序颠倒)
多帧场景 每个 request 独立触发一次 漏触发或重复触发
严重异常: 如果 shutter callback 的时间戳与 result 中的 android.sensor.timestamp 不一致,会导致 AE/AF 收敛算法 和 视频稳像 出现不可预测的偏差。务必在 HAL 实现中保证两者使用同一个时钟源。

3.5 buffer status:输出图像的交付状态

每个 CaptureRequest 可以包含多个输出 buffer(如 preview、still capture、video)。HAL 通过 CaptureResult 中的 android.request.outputStreams 和对应的 bufferStatus 来报告每个 buffer 的处理结果。

buffer status 的常见取值:

  • OK (0):buffer 已成功填充数据。
  • ERROR (1):buffer 处理失败,数据无效。
  • ERROR_REQUEST (2):整个 request 失败,所有 buffer 均无效。

下图展示了 buffer 从 request 到 result 的完整生命周期:

Buffer 生命周期与状态传递 Request 提交 HAL 填充 状态判定 Result 回调 OK (0) ERROR (1) ERROR_REQUEST (2)

3.6 异常定位实战:result 与 request 不匹配的典型场景

在实际调试中,以下问题最为常见:

  1. result 中缺少 request 中设置的 key:HAL 未实现该 key 的处理,或未在 result 中回传。
  2. partial result 数量不足:HAL 返回的 partial result 少于 partialResultCount,导致框架超时。
  3. shutter callback 时间戳与 result 不一致:时钟源不同或时间戳传递错误。
  4. buffer status 为 ERROR 但 metadata 正常:HAL 在填充 buffer 时发生错误,但未正确上报。
  5. final result 中 buffer 数量与 request 中 output streams 数量不匹配:HAL 漏处理了某个 stream。
调试命令示例: 使用 dumpsys 检查 pending request 和 result 的对应关系:
adb shell dumpsys media.camera | grep -A 20 "CaptureRequest"
adb shell dumpsys media.camera | grep -A 20 "CaptureResult"
通过对比 requestId 和 timestamp,可以快速定位丢失的 result。

3.7 总结:对应关系检查清单

在 HAL 实现或调试过程中,请逐项核对以下清单:

检查项 预期行为 异常后果
shutter callback 触发次数 每个 request 一次 框架等待超时
partial result 数量 等于 partialResultCount result 不完整或超时
final result 中的 metadata 包含所有 mandatory keys 上层应用获取不到必要参数
buffer status 所有 buffer 为 OK 图像数据丢失或黑帧
时间戳一致性 shutter < partial < final 3A 算法异常