4. Preview Request 流程详解:从 Framework 下发 CaptureRequest 到 HAL 的完整路径

Preview 流程的起点是 Android Framework 的 Camera 应用层,终点是 HAL 层的硬件处理单元。本章将深入剖析 CaptureRequest 从 Framework 下发到 HAL 的完整路径,并详细解析核心数据结构 camera3_capture_request_t 的每个字段。

4.1 整体流程概览

一个 Preview Request 的生命周期跨越 Framework、Camera Service、Camera Provider 和 HAL 四个层级。下图展示了从应用层调用 capture 到 HAL 接收 process_capture_request 的完整路径。

Preview Request 下发完整路径 Application capture() / setRepeatingRequest() Camera Framework CameraDeviceImpl / CaptureRequest Camera Service Camera3Device / RequestThread Camera Provider CameraProvider / HAL Binder HAL (process_capture_request) 关键数据结构传递链 CaptureRequest.Builder → CaptureRequest → CameraMetadata → camera3_capture_request_t Binder 序列化 CameraMetadata native_handle → Parcel → 跨进程传输 → 反序列化 HAL 层转换 Camera3Device::convertRequestToHAL() → camera3_capture_request_t 填充 Stream 绑定 camera3_stream_buffer_t 数组构建,绑定 output streams 物理 Camera 支持 camera3_physical_camera_settings_t 用于多 Camera 场景

4.2 关键路径步骤详解

从 Framework 到 HAL 的完整路径包含以下关键步骤:

  1. 应用层发起请求:应用通过 CameraCaptureSession.capture() 或 setRepeatingRequest() 提交 CaptureRequest。
  2. Framework 层封装:CameraDeviceImpl 将请求封装为 CaptureRequest 对象,包含 metadata 和 target surfaces。
  3. Camera Service 调度:Camera3Device 的 RequestThread 将请求加入队列,按优先级和帧号调度。
  4. 跨进程传输:通过 Binder 将 CaptureRequest 序列化后传输到 Camera Provider 进程。
  5. HAL 层转换:Camera Provider 调用 convertRequestToHAL() 将 Framework 请求转换为 camera3_capture_request_t。
  6. HAL 回调:调用 process_capture_request() 将请求下发到 HAL 实现。

4.3 核心数据结构:camera3_capture_request_t 字段解析

camera3_capture_request_t 是 HAL 层接收请求的核心数据结构,定义在 hardware/libhardware/include/hardware/camera3.h 中。下表详细解析每个字段的含义和用途:

字段名 类型 描述 Preview 场景典型值
frame_number uint32_t 帧序号,单调递增,用于追踪请求和结果对应关系 0, 1, 2, ...
settings const camera_metadata_t* 请求的 metadata,包含 3A 参数、AE/AF/AWB 设置、输出尺寸等 预览模式的 metadata
input_buffer const camera3_stream_buffer_t* 输入 buffer,用于 reprocessing 场景;Preview 通常为 NULL NULL
num_output_buffers uint32_t 输出 buffer 数量,对应 target surfaces 个数 1(预览 Surface)或 2(预览 + 录像)
output_buffers const camera3_stream_buffer_t* 输出 buffer 数组,每个元素描述一个 output stream 的 buffer 指向预览 stream 的 buffer
num_physcam_settings uint32_t 物理 camera settings 数量,用于多 camera 场景 0(单 camera)
physcam_settings const camera3_physical_camera_settings_t* 物理 camera settings 数组,每个物理 camera 独立设置 NULL

4.4 camera3_stream_buffer_t 结构解析

camera3_stream_buffer_t 是 camera3_capture_request_t 中描述 buffer 的核心子结构:

字段名 类型 描述
stream camera3_stream_t* 指向 stream 的指针,标识该 buffer 属于哪个 stream
buffer buffer_handle_t* 实际 buffer 的 handle,指向 GraphicBuffer
status int buffer 状态,CAMERA3_BUFFER_STATUS_OK 或 ERROR
acquire_fence int acquire fence fd,HAL 等待此 fence 后才能写入 buffer
release_fence int release fence fd,HAL 写入完成后 signal 此 fence
性能提示:Preview 场景中,acquire_fence 通常为 -1(无需等待),因为 SurfaceFlinger 已经准备好 buffer。但录像或高帧率场景中,fence 机制对同步至关重要。

4.5 Framework 到 HAL 的转换流程

以下代码展示了 Camera3Device 如何将 Framework 的 CaptureRequest 转换为 HAL 的 camera3_capture_request_t:

// frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
status_t Camera3Device::convertRequestToHAL(
        const CaptureRequest &frameworkRequest,
        camera3_capture_request_t *halRequest) {
    
    // 1. 填充 frame_number
    halRequest->frame_number = frameworkRequest.mFrameNumber;
    
    // 2. 转换 metadata
    halRequest->settings = frameworkRequest.mSettings.get();
    
    // 3. 处理 input buffer(Preview 通常为 NULL)
    halRequest->input_buffer = nullptr;
    
    // 4. 构建 output buffers 数组
    Vector<camera3_stream_buffer_t> outputBuffers;
    for (auto &surface : frameworkRequest.mSurfaceList) {
        camera3_stream_buffer_t buf;
        buf.stream = getStreamForSurface(surface);
        buf.buffer = getBufferForSurface(surface);
        buf.status = CAMERA3_BUFFER_STATUS_OK;
        buf.acquire_fence = -1;
        buf.release_fence = -1;
        outputBuffers.add(buf);
    }
    halRequest->num_output_buffers = outputBuffers.size();
    halRequest->output_buffers = outputBuffers.array();
    
    // 5. 处理物理 camera settings
    halRequest->num_physcam_settings = 0;
    halRequest->physcam_settings = nullptr;
    
    return OK;
}

4.6 Preview 场景下的字段填充示例

以一个典型的 1080p Preview 请求为例,各字段的实际填充值如下:

字段 示例值 说明
frame_number 42 第 42 帧请求
settings 包含 AE_MODE=ON, AE_TARGET_FPS_RANGE=[30,30], ANDROID_CONTROL_AE_LOCK=false 等 预览模式的标准 metadata
num_output_buffers 1 仅预览 Surface
output_buffers[0].stream 指向 preview stream,格式 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED 分辨率 1920x1080
output_buffers[0].acquire_fence -1 无需等待
output_buffers[0].release_fence -1 HAL 完成后 signal

4.7 性能关键点与优化建议

性能关键点:
  • metadata 序列化开销:每次请求都需序列化 metadata,大量重复 key 会增加 Binder 传输负担。建议使用 CameraMetadata 的缓存机制减少重复设置。
  • buffer 分配策略:Preview 场景建议使用 dequeueBuffer 预分配 buffer 池,避免每帧动态分配。
  • fence 管理:合理使用 acquire/release fence 可以减少 CPU 等待,提升 pipeline 吞吐量。
  • frame_number 连续性:HAL 应保证 frame_number 连续,避免 Framework 侧超时或丢帧检测误判。
常见陷阱:
  • HAL 实现中修改 settings 指向的 metadata 内容会导致未定义行为,应视为只读。
  • output_buffers 数组的生命周期仅持续到 process_capture_request 返回,HAL 需要深拷贝 buffer handles 用于异步处理。
  • 多 camera 场景下,physcam_settings 中的物理 camera ID 必须与 stream 配置一致,否则会导致 HAL 崩溃。

4.8 路径总结

Preview Request 从 Framework 到 HAL 的完整路径可概括为:

  • 应用层:构建 CaptureRequest.Builder,设置 metadata 和 target surfaces。
  • Framework 层:CameraDeviceImpl 封装为 CaptureRequest,通过 Binder 发送到 Camera Service。
  • Service 层:Camera3Device 的 RequestThread 调度请求,调用 convertRequestToHAL() 转换。
  • Provider 层:通过 HAL Binder 接口将 camera3_capture_request_t 传递给 HAL。
  • HAL 层:process_capture_request() 接收请求,解析 settings 和 output_buffers,开始 ISP 处理。