Advanced AOSP Subsystems
4 min read

End-to-End Camera Request Flow

Overview

Understanding the end-to-end camera request flow is essential for debugging performance issues, latency, and synchronization problems in the Android camera stack. This flow traces the journey of a single frame from the moment an application requests it until the pixels are rendered on the screen or saved to disk. It highlights the intricate choreography between the Java API, native services, hardware abstractions, and kernel drivers.

1. Application Submits CaptureRequest

The journey begins in the application process. Once a CameraCaptureSession is configured with target Surface objects, the app builds a CaptureRequest.

  1. Building the Request: The app uses CaptureRequest.Builder to define the metadata parameters (e.g., EV compensation, flash mode) and attaches the target Surfaces (e.g., a SurfaceView for preview).
  2. Submission: The app calls setRepeatingRequest() or capture() on the session.
  3. Binder IPC: The framework serializes the request and sends it via Binder IPC to the CameraService running in a separate system process.
// App side: Submitting the request
CaptureRequest request = requestBuilder.build();
mSession.setRepeatingRequest(request, mCaptureCallback, mBackgroundHandler);

2. CameraService Processing

The CameraService acts as the orchestrator.

  1. Request Validation: The CameraDeviceClient receives the request, validates the metadata, and ensures the target Streams are part of the active configuration.
  2. Buffer Acquisition: For each target Surface in the request, the CameraService dequeues a free GraphicBuffer from the corresponding BufferQueue. This buffer represents physical memory allocated by gralloc.
  3. Translation: The Java CaptureRequest is translated into a native camera3_capture_request_t structure. This structure includes the metadata and handles to the dequeued buffers.
  4. Dispatch to HAL: The CameraService calls processCaptureRequest on the HAL interface via HIDL or AIDL.

3. HAL Programs ISP and Sensor

The Camera HAL (Hardware Abstraction Layer) takes over execution.

  1. Queueing: The HAL places the request into an internal pipeline queue. Because hardware pipelines are deep, the HAL typically manages requests several frames ahead of actual sensor capture.
  2. Parameter Resolution: The HAL merges the requested metadata with its internal 3A states (Auto-Exposure, Auto-Focus, Auto-White Balance) and tuning data to calculate the exact hardware registers needed.
  3. Hardware Programming: The HAL interacts with kernel drivers (e.g., via V4L2) to program the sensor (exposure time, gain) and the Image Signal Processor (ISP) blocks (lens shading, noise reduction, scaling).
  4. Buffer Mapping: The HAL ensures the hardware DMA engines are configured to write the processed image data directly into the gralloc buffers provided in the request.

4. Hardware Capture and HAL Callback

The physical capture occurs.

  1. Exposure: The sensor exposes light and reads out raw data.
  2. ISP Processing: The raw data streams through the ISP pipeline, undergoing demosaicing, color correction, and formatting.
  3. Hardware Interrupt: Once the ISP completes writing to the destination buffer, it triggers a hardware interrupt. The kernel driver handles the interrupt and signals the HAL.
  4. processCaptureResult: The HAL constructs a camera3_capture_result_t structure containing the actual applied metadata (the CaptureResult) and the filled buffers. It sends this back to the CameraService via the processCaptureResult callback.
// HAL side: Sending result back
camera3_capture_result_t result = {};
result.frame_number = request->frame_number;
result.result = final_metadata;
result.num_output_buffers = 1;
result.output_buffers = &filled_buffer;

callback->process_capture_result(callback, &result);

5. Buffer Flow and Application Consumption

The CameraService receives the result and routes data back to the consumer.

  1. Buffer Enqueueing: The CameraService takes the filled GraphicBuffer and enqueues it back into the target BufferQueue.
  2. Metadata Dispatch: The metadata is serialized and sent via Binder back to the application, triggering the onCaptureCompleted callback.
  3. Consumer Notification: The BufferQueue notifies its consumer that a new buffer is available.
    • If the consumer is a SurfaceView, SurfaceFlinger acquires the buffer and composites it onto the screen.
    • If the consumer is an ImageReader, the onImageAvailable callback is fired in the app.
    • If the consumer is MediaCodec, the video encoder begins processing the frame.
// App side: Receiving metadata
@Override
public void onCaptureCompleted(@NonNull CameraCaptureSession session,
                               @NonNull CaptureRequest request,
                               @NonNull TotalCaptureResult result) {
    // Process result metadata (e.g., read actual exposure time)
}

Analyzing the Pipeline with Systrace

This complex sequence is heavily dependent on precise timing. Developers use systrace (or Perfetto) to analyze the request flow.

When tracing a camera session, you can observe:

  • App Thread: Submitting requests.
  • CameraService Threads: Handling IPC and dequeuing buffers.
  • HAL Threads: Processing requests and waiting on hardware interrupts.
  • SurfaceFlinger / App Threads: Consuming the rendered buffers.

Bottlenecks at any stage (e.g., slow metadata processing in the app, ISP overload, or SurfaceFlinger composition delays) can result in dropped frames or visible stutter in the camera preview.