Skip to content

Fix: CameraDevice race condition crash on Android rotation (IllegalStateException)#80

Draft
Copilot wants to merge 2 commits into
masterfrom
copilot/fix-camera-crash-on-rotation
Draft

Fix: CameraDevice race condition crash on Android rotation (IllegalStateException)#80
Copilot wants to merge 2 commits into
masterfrom
copilot/fix-camera-crash-on-rotation

Conversation

Copilot AI commented Apr 21, 2026

Copy link
Copy Markdown

Rapid stop/start cycles during device rotation cause a stale OnConfigured() callback to fire after a new CameraDevice has already opened. The callback overwrites previewSession with an old session tied to the already-closed device, then calls SetRepeatingRequest() on it → IllegalStateException: CameraDevice was already closed.

Changes

  • Session generation counterpreviewSessionGeneration (atomically incremented via Interlocked) is added to MauiCameraView; each StartPreview() invocation captures its own generation value before any await.

  • Stale callback detection in OnConfigured()PreviewCaptureStateCallback now stores the generation at construction time and guards against two stale conditions before touching previewSession:

    if (cameraView.cameraDevice == null ||
        generation != Volatile.Read(ref cameraView.previewSessionGeneration))
    {
        try { session.Close(); } catch (Java.Lang.Exception ex) { DebugOut.WriteLine(ex.ToString()); }
        return;
    }
  • Early exit in StartPreview() — after the await Task.Delay loop, bails out if the camera was stopped or a newer StartPreview() ran in the meantime.

  • Defensive catch in UpdatePreview() — adds Java.Lang.IllegalStateException alongside the existing CameraAccessException catch as a last-resort safety net.

Add a previewSessionGeneration counter to MauiCameraView so that stale
OnConfigured() callbacks—fired after the camera was closed and
re-opened during rapid stop/start cycles (e.g. device rotation)—can
detect they are obsolete and close their stale session instead of
calling SetRepeatingRequest() on a CameraDevice that has already been
closed.

Race condition that was occurring:
1. Camera A opens → OnOpened sets cameraDevice=cam_A → StartPreview
   calls cam_A.CreateCaptureSession() (async)
2. StopCamera() (rotation) → cam_A.Close(), cameraDevice=null
3. Camera B opens → OnOpened sets cameraDevice=cam_B → StartPreview
   calls cam_B.CreateCaptureSession() (async)
4. *Old* OnConfigured(session_A) fires → overwrites previewSession with
   session_A → UpdatePreview sees cameraDevice=cam_B (not null!) →
   SetRepeatingRequest() on session_A (cam_A is closed) → CRASH

Fix:
- previewSessionGeneration atomically incremented at the start of each
  StartPreview() call; the captured value is passed to
  PreviewCaptureStateCallback
- OnConfigured() checks that (a) cameraDevice != null and (b) its
  generation still matches the current counter; stale callbacks close
  the session and return without modifying previewSession
- StartPreview() also bails out early after its await loop if the
  camera was stopped/restarted in the meantime
- UpdatePreview() now also catches Java.Lang.IllegalStateException as a
  defensive safety net

Agent-Logs-Url: https://github.com/janusw/CameraMaui/sessions/1a42b9b4-c323-4138-8b53-3540a3fcba5c

Co-authored-by: janusw <484108+janusw@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix camera crash on device rotation in Android 15+ Fix: CameraDevice race condition crash on Android rotation (IllegalStateException) Apr 21, 2026
Copilot AI requested a review from janusw April 21, 2026 19:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Camera crash when rotating device on Android 15+ (CameraDevice was already closed)

2 participants