2. Result回调基础概念

2.1 什么是Result回调

在Camera HAL3架构中,Result回调是HAL层向Camera Framework上报拍摄结果的核心异步通信机制。当HAL完成一个Capture Request的处理后,通过process_capture_result函数将结果数据推送给Framework,而不是由Framework主动轮询。

Result回调的本质是一个异步通知通道,它携带了以下三类关键信息:

  • 元数据(Metadata):包含3A状态、传感器时间戳、曝光参数等控制结果。
  • 输出缓冲区(Output Buffers):经过ISP处理后的图像数据,如YUV、JPEG或RAW图。
  • 部分结果(Partial Result):允许HAL分批次上报,Framework可提前处理已就绪的数据。
关键设计意图:Result回调将HAL从同步阻塞模型中解放出来。HAL可以按自己的节奏处理流水线,Framework则通过回调及时获取进展,两者通过异步机制解耦。

2.2 Result与Request的对应关系

Result与Request之间遵循严格的1:N映射模型,但并非简单的“一个Request对应一个Result”。实际对应关系如下表所示:

概念 说明 示例
Request Framework下发的拍摄请求,包含帧号(frame_number)、设置(settings)、输出缓冲区列表 frame_number=42, settings={AE, AWB, AF}, buffers=[stream1, stream2]
Result(完整) HAL完成所有处理后一次性上报,包含完整metadata和所有buffer frame_number=42, result_metadata={...}, buffers=[stream1_ready, stream2_ready]
Partial Result HAL分多次上报,每次携带部分metadata或部分buffer,最后通过partial_result计数标识完成 frame_number=42, partial_result=1/3 → 2/3 → 3/3(最终)
Buffer Result HAL单独上报某个stream的buffer状态,不携带metadata frame_number=42, buffer=stream1, status=OK

对应关系的核心规则:

  • 每个Request必须最终产生一个完整的Result(或错误状态)。
  • Partial Result可以多次上报,但partial_result计数器必须递增至总次数。
  • Buffer Result允许提前释放已处理的输出缓冲区,减少Framework端的内存压力。
  • Framework通过frame_number将Result与原始Request关联,确保时序一致性。
实践要点:在HAL实现中,务必保证同一个frame_number的Result回调按顺序上报。如果HAL乱序上报(例如frame 42的Result在frame 41之前到达),Framework会触发错误处理,可能导致相机服务重启。

2.3 Result数据流的基本路径

Result数据从HAL产生到Framework消费,经历了清晰的层级传递。下图展示了完整的Result数据流路径:

Result数据流基本路径 Camera HAL process_capture_result() Camera Service 结果分发与校验 Camera Framework onResultReceived() HIDL/AIDL 内部回调 Result回调携带的数据内容 • 帧号(frame_number):唯一标识对应的Request • 结果元数据(result_metadata):3A状态、曝光参数、传感器时间戳等 • 输出缓冲区(output_buffers):每个stream的填充状态、时间戳、Fence • 部分结果计数(partial_result):标识当前是第几次部分上报 典型时序:Partial Result分步上报 T1: HAL上报 Partial Result 1/3 → 携带AE/AWB元数据,无buffer T2: HAL上报 Partial Result 2/3 → 携带AF元数据 + preview buffer T3: HAL上报 Partial Result 3/3 → 携带完整元数据 + JPEG buffer(最终完成) Framework在T1即可开始处理AE/AWB数据,无需等待T3

Result数据流的基本路径可以概括为以下步骤:

  1. HAL产生结果:HAL完成某个Request的处理后,构造camera3_capture_result_t结构体,填充帧号、元数据、缓冲区列表和部分结果计数。
  2. 跨进程传递:通过HIDL或AIDL接口,将Result数据从HAL进程传递到Camera Service进程。此过程涉及序列化/反序列化,对性能敏感。
  3. Service校验与分发:Camera Service检查Result的合法性(帧号连续性、缓冲区状态等),然后通过内部回调机制分发给Framework层的CameraDevice实例。
  4. Framework消费:Framework的CameraCaptureSession将Result转换为应用层可识别的CaptureResult对象,触发onCaptureCompleted或onCapturePartial回调。
常见陷阱:HAL在Partial Result中上报的metadata必须与最终完整Result中的对应字段一致。如果Partial Result中上报了AE状态为CONVERGED,但最终Result中变为SEARCHING,Framework会认为HAL行为不一致,可能触发异常。

2.4 关键数据结构

Result回调在HAL层对应的核心数据结构是camera3_capture_result_t,其关键字段如下:

typedef struct camera3_capture_result {
    uint32_t                frame_number;           // 对应Request的帧号
    const camera3_stream_buffer_t *output_buffers;  // 输出缓冲区数组
    uint32_t                num_output_buffers;     // 输出缓冲区数量
    const camera3_capture_result_metadata_t *result;// 结果元数据
    uint32_t                partial_result;         // 部分结果计数(0表示完整结果)
    int32_t                 error_stream;           // 错误流标识
    // ... 其他扩展字段
} camera3_capture_result_t;

其中partial_result字段是理解Result回调机制的关键:

  • 值为0:表示这是该Request的最终完整Result,之后HAL不会再为该帧上报任何结果。
  • 值为1~N:表示这是第几次部分结果上报,HAL必须保证从1开始递增,最终上报一次partial_result=0的完整结果。
  • 值为-1:表示该Result仅包含缓冲区状态更新,不携带任何metadata。
性能优化建议:对于高帧率预览场景(如30fps),建议HAL使用Partial Result机制,先上报预览buffer让Framework显示,再上报完整metadata。这样可以将显示延迟降低1~2帧,显著改善取景体验。