Zygote
Media, audio & cameraintermediate

Camera

Camera2 is hard for a reason: it exposes the actual hardware pipeline. CameraX exists to wrap the common cases without hiding that pipeline completely.

12 minAPI 1–37 · 17interactivequizverified 2026-10-27

The camera is the most complex peripheral on a phone, and Android's camera API reflects that. Camera1 pretended the camera was a point-and-shoot. Camera2 exposes the pipeline. CameraX tries to give you the useful parts of Camera2 without making you reimplement autofocus.

TL;DR#

  • Camera1 was a simple, synchronous API. It is deprecated.
  • Camera2 (API 21) models capture as requests and results: you describe what you want, the hardware does it, and it tells you what actually happened.
  • The camera HAL is where device capabilities live. Two phones on the same Android version can expose different features entirely.
  • CameraX is a Jetpack library that provides use cases (preview, capture, analysis) with device compatibility handled for you.
  • The permission is CAMERA, dangerous since API 23; the camera indicator and global toggle arrived in the API 31 privacy wave.

Mental model#

Think of a professional camera with a director and a technician.

Camera1 is asking the technician to "take a photo" and hoping. Camera2 is handing the technician a shot list: exposure, focus mode, flash, which outputs to fill. The technician executes it and returns a report saying what settings were actually used — because the camera may have decided differently.

CameraX is a production company that turns your intent ("show a preview and let the user take a photo") into a shot list for whichever technician is on set.

Where the analogy breaks#

A shot list is executed once. Camera2 is a continuous loop: a repeating request keeps the preview alive, and each iteration returns a result. The API is a stream of requests and results, not a single transaction.

The big picture#

Loading diagram…
Text description of this diagram

A six-stage loop. The app builds a CaptureRequest naming the target surfaces and settings. The camera service brokers access and enforces permissions. The vendor camera HAL turns the request into register writes for this sensor and ISP. The sensor integrates light and the ISP processes the image into several scaled outputs. Each output is a Surface backed by a BufferQueue: preview, still capture and video can all be targets of one request. The HAL returns a CaptureResult describing the settings and state actually achieved, which is how autofocus and auto-exposure are converged.

The loop is the important part. Camera2 does not have a takePicture() that returns a bitmap. It has a request queue and a result stream, and you drive it.

Deep dive#

Camera1: the synchronous era#

android.hardware.Camera gave you setPreviewDisplay, startPreview, takePicture. It was easy to use and impossible to use well: no control over per-frame settings, no way to get several outputs at once, and a preview that was a separate, lower-quality path from the still capture.

It is deprecated and should not be used for new code. It survives because a lot of old code exists.

Camera2: requests and results#

A CaptureRequest describes one capture:

  • the target surfaces (preview, still, video, analysis),
  • the sensor settings (exposure time, sensitivity),
  • the control modes (autofocus, auto-exposure, auto-white-balance),
  • the output settings (format, size).

A CaptureResult describes what the hardware did: the actual exposure, the focus state, the timestamp, the applied settings. Reading results is how you implement "tap to focus" — you set a focus region, then wait for the result to report focus locked.

There are three request modes:

  • Single request for a still capture.
  • Repeating request for a preview, replaced when settings change.
  • Burst for a sequence.

The HAL is the real API#

The camera HAL defines more than a dozen interfaces: the device, the capture request, the result, the metadata, the stream configuration. A device's capability set is reported through CameraCharacteristics — but the values come from the HAL, so they are only as complete as the vendor made them.1

This is why two phones on the same Android version can behave differently:

  • One supports 4K video from the front camera, another does not.
  • One exposes logical multi-camera, another exposes each lens separately.
  • One supports RAW capture, another reports the capability but produces corrupt files.

The platform defines the contract; the vendor implements it; the CDD sets a floor. Everything above the floor is optional.

CameraX: use cases instead of pipelines#

CameraX rephrases the problem in terms of use cases:

  • Preview: show the viewfinder.
  • ImageCapture: take a photo.
  • ImageAnalysis: get frames for processing (barcode scanning, ML).
  • VideoCapture: record video.

You bind use cases to a lifecycle, and CameraX negotiates the stream combination, handles rotation, and applies device-specific quirks. That is the value: the quirks are the hard part, and they are maintained in the library rather than in every app.2

The trade-off is control. CameraX exposes extensions and some manual controls, but if you need per-frame sensor settings you will drop to Camera2.

Extensions and multi-camera#

Two features deserve a mention because they are where modern camera quality lives:

Camera extensions expose OEM image processing — night mode, bokeh, HDR — through a standard API. The OEM implements the extension in its HAL; the app asks for it by mode. This is how a third-party camera app can use the same night-mode processing as the built-in one, at least in principle.

Logical multi-camera lets one camera device represent several physical lenses, so the app can request a zoom level and let the device choose which lens to use. Without it, an app would have to switch cameras itself and handle the exposure jump.

Both are capability-dependent. An app must query and fall back.

Permissions, indicators and the privacy toggle#

CAMERA is a dangerous permission, required since API 23 at runtime. Beyond the permission:

  • API 30 added a global camera toggle and restricted background access.
  • API 31 added the camera indicator — a system-drawn dot or icon whenever the camera is in use.
  • API 34 requires foreground service types when a service uses the camera.

The pattern is the same as location and microphone: holding the permission is necessary but not sufficient, and the user can always see that the hardware is active.

Why Camera2 is "harder" — and whether that is a flaw#

Camera2 is harder because it is honest. It exposes:

  • the fact that capture is asynchronous,
  • the fact that settings are requests, not commands,
  • the fact that outputs are buffers with backpressure,
  • the fact that hardware capabilities vary.

Camera1 hid all four and produced apps that worked on one device and not another. Camera2 makes the device differences visible, which is unpleasant but correct. CameraX is the pragmatic middle: it hides the differences that can be hidden and exposes the ones that cannot.

A request that converges: tap-to-focus#

The request/result loop is easiest to understand through a feature every camera app has.

A tap produces a metering rectangle, mapped from screen coordinates to sensor coordinates. The app builds a request with CONTROL_AF_MODE_AUTO and the new CONTROL_AF_REGIONS, and submits it as a repeating request. Then it waits — not for the image, but for the result — until CONTROL_AF_STATE reports a locked state.

That loop is the pattern for every manual control:

  1. express the desired state in a request,
  2. keep the request repeating,
  3. read the result to learn the achieved state,
  4. update the UI from the result, not from the request.

An app that draws a "focused" indicator as soon as it sends the request is lying to the user for somewhere between 100 and 800 milliseconds.

Sessions, and sharing the camera#

On Android 10 and later, a camera can be opened by more than one app through a camera session configuration: one app is the primary client and others can share a stream in limited ways. The practical rules are still simple:

  • Camera access is exclusive by default, and the second app gets an error or a reduced stream.
  • The system enforces the camera-in-use policy, so a background app cannot silently hold the device.
  • The indicator tells the user something is using it, which is the visible half of the same rule.

The design is a compromise between "one app owns the camera" — which is simple and matches the hardware — and "video calls and camera apps should coexist" — which requires sharing.

How it evolved#

Architecture changes29 releases
APIVersionWhat changed
11.0
  • Initial AOSP platform: Linux kernel, Dalvik VM, core libraries
  • The first zygote-based app spawning model
41.6 Donut
  • Support for different screen densities via resource qualifiers
52.0 Eclair
  • First multi-core-friendly scheduling and graphics work
82.2 Froyo
  • Trace-based JIT compiler added to Dalvik
  • Support for x86 and ARMv7 optimisations
92.3 Gingerbread
  • Concurrent garbage collector added to Dalvik (GC pause reduction)
113.0 Honeycomb
  • Hardware acceleration for the View system (opt-in per app)
133.2 Honeycomb
  • New screen-size resource qualifiers for compatibility scaling
144.0 Ice Cream Sandwich
  • One system image for phones and tablets
  • Hardware acceleration on by default
164.1 Jelly Bean
  • Project Butter: vsync, triple buffering, Choreographer
  • RenderThread architecture begins
174.2 Jelly Bean
  • Multi-user support on tablets
  • SELinux enforcement begins in the kernel (behind the scenes)
184.3 Jelly Bean
  • SELinux enforcement rolled out more broadly
  • Binder changes for restricted profiles
194.4 KitKat
  • Android Runtime (ART) appears as an experimental runtime
  • Kernel moved under a tighter vendor control
204.4W KitKat (Wear)
  • First time the platform shipped for a new form factor
215.0 Lollipop
  • ART becomes the only runtime: ahead-of-time compilation at install
  • 64-bit ARM and x86 support
  • RenderThread and OpenGL ES 3.1
  • Project Volta and JobScheduler
  • SELinux fully enforcing
225.1 Lollipop
  • Device protection ties verified boot to Google accounts
236.0 Marshmallow
  • Runtime permission model changes how every app asks for access
  • Doze batches background work
  • Fingerprint HAL
  • Adoptable storage
247.0 Nougat
  • Project Treble groundwork
  • A/B seamless updates
  • Hybrid JIT + AOT compilation in ART
  • MediaServer split into sandboxed processes
268.0 Oreo
  • Project Treble: the vendor interface separates vendor and system code
  • Background execution limits
  • Broadcast and service restrictions
  • HIDL for HALs
278.1 Oreo
  • Android Go: a lighter configuration of the same platform
289 Pie
  • App Standby Buckets
  • Mainline groundwork
  • Non-SDK interface restrictions (greylists) begin
  • BiometricPrompt
2910
  • Project Mainline: APEX and updatable system modules
  • Scoped storage
  • Bubbles
  • Project Mainline starts shipping through Play
3011
  • GKI: the Generic Kernel Image splits the kernel into core + vendor modules
  • App hibernation
  • Package visibility filtering
  • Incremental app installs
3112
  • Bluetooth permissions split into the nearby-devices family
  • Exact alarm permissions
  • Foreground service launch restrictions
3212L
  • Window size classes and activity embedding
3313 Tiramisu
  • Granular media permissions replace READ_EXTERNAL_STORAGE
  • The notification permission becomes a runtime permission
  • Predictive back gesture
3414 Upside Down Cake
  • Foreground service types are mandatory
  • Selected photos access via READ_MEDIA_VISUAL_USER_SELECTED
3515 Vanilla Ice Cream
  • 16 KB page size support for native libraries
  • Edge-to-edge is enforced when targeting 35
3616 Baklava
  • The release moves to Q2 (June) with a Q4 feature drop
  • Two SDK releases per year starting with 36
  • Desktop windowing arrives in developer options then stable
3717 Cinnamon Bun
  • Strict per-device app memory limits are enforced by the system
  • Generational garbage collection is added to ART's Concurrent Mark-Compact collector
  • A lock-free MessageQueue for apps targeting API 37
  • Compose-first: new platform and Jetpack APIs target Compose only; View libraries enter maintenance mode
  • Hybrid APK signing (v3.2) combines classical and ML-DSA post-quantum signatures
  • Native library dynamic code loading must be read-only
2008–2014Camera1Simple, synchronous, limited control.API 1
2014 →Camera2 + HAL3Requests and results, multiple outputs, per-frame control.API 21
2018 →ExtensionsOEM processing exposed through a standard API.API 28
2019 →CameraXUse cases and device compatibility as a library.API 29
2021 →Privacy togglesCamera indicator and global disable.API 31

Under the hood#

Curiosity corner#

  • A "48 MP" camera rarely produces 48 MP photos. It bins pixels to improve low light and outputs a smaller image by default; the full-resolution mode is a separate, slower capture.
  • The front camera is often the same sensor as the rear ultrawide. Logical multi-camera can expose one physical sensor through two logical devices.
  • Camera2's CaptureResult is the only honest source of truth. Reading back the request you sent tells you what you asked for, not what the hardware did.

Try it#

List camera capabilities

adb shell dumpsys media.camera | head -60 adb shell cmd media.camera get-num-cameras adb shell dumpsys media.camera -h

Example output
Camera 0:
Facing: BACK
Supported hardware level: LEVEL_3
Stream combinations: 3
Max JPEG size: 4000x3000
Camera 1:
Facing: FRONT
Supported hardware level: LIMITED

The hardware level in that output is the single most useful capability: LEGACY means Camera1 semantics, LIMITED and FULL mean increasing Camera2 support, and LEVEL_3 adds advanced features.

Check yourself#

Check yourself

1 / 12

What are the four stages the media framework separates?

0 answered · 0 correct

Sources#

Sources

Every version number, API level, class name and date on this page is traced to one of these. Pages are re-verified against them; last_verified above says when.

  1. docsCamera overviewsource.android.comaccessed 2026-10-27↩
  2. docsCameraX overviewdeveloper.android.comaccessed 2026-10-27↩
  3. docsManifest.permission | API referencedeveloper.android.comaccessed 2026-10-27↩
  4. docsBehavior changes: Apps targeting Android 12developer.android.comaccessed 2026-10-27↩
  5. docsBehavior changes: Apps targeting Android 13 or higherdeveloper.android.comaccessed 2026-10-27↩