Advanced AOSP Subsystems
4 min read

Camera2 API

Overview

The Camera2 API, introduced in Android 5.0 (API level 21), represents a paradigm shift in how applications interact with camera hardware. Unlike the deprecated android.hardware.Camera API, which treated the camera as a black box with high-level parameters, Camera2 exposes a granular, per-frame control mechanism. It models the camera subsystem as a pipeline that processes incoming requests and returns corresponding results, enabling advanced computational photography, manual sensor control, and zero-shutter-lag (ZSL) captures.

Core Architectural Components

The Camera2 framework relies on several key classes that orchestrate the flow of data between the application and the underlying Camera Service.

CameraManager

CameraManager is a system service responsible for enumerating, querying, and opening camera devices. It acts as the entry point to the Camera2 API.

CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
String[] cameraIds = manager.getCameraIdList();

for (String id : cameraIds) {
    CameraCharacteristics chars = manager.getCameraCharacteristics(id);
    Integer facing = chars.get(CameraCharacteristics.LENS_FACING);
    if (facing != null && facing == CameraCharacteristics.LENS_FACING_BACK) {
        // Found the back camera
    }
}

CameraDevice

CameraDevice represents a physical or logical camera connected to the Android device. Opening a camera is an asynchronous operation, handled via a CameraDevice.StateCallback.

manager.openCamera(cameraId, new CameraDevice.StateCallback() {
    @Override
    public void onOpened(@NonNull CameraDevice camera) {
        mCameraDevice = camera;
        // Proceed to create a capture session
    }

    @Override
    public void onDisconnected(@NonNull CameraDevice camera) {
        camera.close();
        mCameraDevice = null;
    }

    @Override
    public void onError(@NonNull CameraDevice camera, int error) {
        camera.close();
        mCameraDevice = null;
    }
}, backgroundHandler);

CameraCaptureSession

A CameraCaptureSession manages the active configuration of outputs (Surfaces) and coordinates the submission of requests. It must be created before any image data can be captured. Reconfiguring a session is an expensive operation that typically involves tearing down and rebuilding the underlying HAL streams.

The Request-Result Pipeline

The core philosophy of Camera2 is the request-response model.

CaptureRequest

A CaptureRequest defines the complete configuration for a single frame. This includes routing (which Surfaces receive the output) and settings (exposure time, ISO, autofocus mode). Requests are built using CaptureRequest.Builder, initialized with a specific template (e.g., TEMPLATE_PREVIEW, TEMPLATE_STILL_CAPTURE).

CaptureRequest.Builder requestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
requestBuilder.addTarget(previewSurface);
requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);

CaptureResult

For every CaptureRequest processed by the hardware, the system generates a CaptureResult (or TotalCaptureResult). This object contains the exact metadata used to capture the frame, which may differ from the request if the HAL was running in an auto-exposure or auto-focus mode.

mCaptureSession.setRepeatingRequest(requestBuilder.build(), new CameraCaptureSession.CaptureCallback() {
    @Override
    public void onCaptureCompleted(@NonNull CameraCaptureSession session, 
                                   @NonNull CaptureRequest request, 
                                   @NonNull TotalCaptureResult result) {
        Long exposureTime = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
        Integer iso = result.get(CaptureResult.SENSOR_SENSITIVITY);
        Log.d("Camera2", "Frame captured: Exp=" + exposureTime + "ns, ISO=" + iso);
    }
}, backgroundHandler);

Camera Metadata: Deep Dive

Camera2 relies heavily on metadata tags to communicate state and intent. These tags are defined in C++ (within system/media/camera/include/system/camera_metadata_tags.h) and mapped to Java keys.

Key Metadata Categories:

  • CONTROL: Settings for the 3A routines (Auto-Exposure, Auto-Focus, Auto-White Balance).
  • SENSOR: Direct sensor controls like exposure time, sensitivity (ISO), and frame duration.
  • STATISTICS: Output from the ISP, such as face detection rectangles, histograms, and lens shading maps.
  • LENS: Focus distance, optical stabilization (OIS) state, and aperture.

Example: Manual Exposure Control

To take full control, an application must disable the AE routine and set raw sensor values:

requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
requestBuilder.set(CaptureRequest.SENSOR_EXPOSURE_TIME, 1000000000L / 60); // 1/60th of a second
requestBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, 400); // ISO 400

Output Targets and Surfaces

Camera2 produces data into Surface objects. These surfaces abstract the underlying GraphicBuffer allocation.

ImageReader

ImageReader is the standard way to access image data in CPU memory (e.g., for processing YUV data or saving JPEG files).

ImageReader reader = ImageReader.newInstance(width, height, ImageFormat.JPEG, 2);
reader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
    @Override
    public void onImageAvailable(ImageReader reader) {
        try (Image image = reader.acquireLatestImage()) {
            ByteBuffer buffer = image.getPlanes()[0].getBuffer();
            byte[] bytes = new byte[buffer.remaining()];
            buffer.get(bytes);
            // Save or process JPEG bytes
        }
    }
}, backgroundHandler);

Surface imageReaderSurface = reader.getSurface();

Typical Surface Flow

  • SurfaceView / TextureView: Used for direct-to-screen preview rendering via SurfaceFlinger.
  • MediaCodec: Used for video recording.
  • RenderScript / OpenGL: Used for custom GPU-accelerated processing.

Debugging Camera2 API

When developing with Camera2, the dumpsys command is invaluable for inspecting the state of the Camera Service and connected clients.

# Dump the state of all connected cameras and active sessions
adb shell dumpsys media.camera

Look for the Client sections in the output to see active configurations, stream sizes, and pending request queues. This helps identify issues where the application is requesting formats or sizes unsupported by the hardware.