From 61b2ecdfef232bcff3b748f24513167926ebbeb6 Mon Sep 17 00:00:00 2001 From: q2a3z <57368238+q2a3z@users.noreply.github.com> Date: Mon, 23 Mar 2026 22:34:32 +0900 Subject: [PATCH 1/3] [camera_android] Reset AE and AF triggers to idle after capture --- .../src/main/java/io/flutter/plugins/camera/Camera.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java index b4f89adef9a3..2cf7ca3e6b64 100644 --- a/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -677,6 +677,11 @@ private void runPrecaptureSequence() { captureSession.capture( previewRequestBuilder.build(), cameraCaptureCallback, backgroundHandler); + // Reset the trigger to idle again. + previewRequestBuilder.set( + CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, + CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE); + } catch (CameraAccessException e) { e.printStackTrace(); } @@ -796,6 +801,9 @@ private void lockAutoFocus() { : e.getMessage(); dartMessenger.sendCameraErrorEvent(message); } + // Reset the trigger to idle again. + previewRequestBuilder.set( + CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE); } /** Cancel and reset auto focus state and refresh the preview session. */ From 07abc0f9dca448b4da642b3540a7c10ce398903e Mon Sep 17 00:00:00 2001 From: q2a3z <57368238+q2a3z@users.noreply.github.com> Date: Sat, 28 Mar 2026 02:27:07 +0900 Subject: [PATCH 2/3] [camera_android] Implement trigger reset callback for AE and AF capture events --- .../io/flutter/plugins/camera/Camera.java | 35 +++++++++++- .../io/flutter/plugins/camera/CameraTest.java | 56 +++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) diff --git a/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java index 2cf7ca3e6b64..f3b291856bdb 100644 --- a/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -12,6 +12,7 @@ import android.graphics.SurfaceTexture; import android.hardware.camera2.CameraAccessException; import android.hardware.camera2.CameraCaptureSession; +import android.hardware.camera2.CaptureFailure; import android.hardware.camera2.CameraDevice; import android.hardware.camera2.CameraManager; import android.hardware.camera2.CameraMetadata; @@ -675,7 +676,11 @@ private void runPrecaptureSequence() { // Trigger one capture to start AE sequence. captureSession.capture( - previewRequestBuilder.build(), cameraCaptureCallback, backgroundHandler); + previewRequestBuilder.build(), + createTriggerResetCallback( + CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, + CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE), + backgroundHandler); // Reset the trigger to idle again. previewRequestBuilder.set( @@ -687,6 +692,28 @@ private void runPrecaptureSequence() { } } + @VisibleForTesting + CameraCaptureSession.CaptureCallback createTriggerResetCallback( + final CaptureRequest.Key triggerKey, final int triggerIdleValue) { + return new CameraCaptureSession.CaptureCallback() { + @Override + public void onCaptureCompleted( + @NonNull CameraCaptureSession session, + @NonNull CaptureRequest request, + @NonNull TotalCaptureResult result) { + previewRequestBuilder.set(triggerKey, triggerIdleValue); + } + + @Override + public void onCaptureFailed( + @NonNull CameraCaptureSession session, + @NonNull CaptureRequest request, + @NonNull CaptureFailure failure) { + previewRequestBuilder.set(triggerKey, triggerIdleValue); + } + }; + } + /** * Capture a still picture. This method should be called when a response is received {@link * #cameraCaptureCallback} from both lockFocus(). @@ -793,7 +820,11 @@ private void lockAutoFocus() { CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START); try { - captureSession.capture(previewRequestBuilder.build(), null, backgroundHandler); + captureSession.capture( + previewRequestBuilder.build(), + createTriggerResetCallback( + CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_IDLE), + backgroundHandler); } catch (CameraAccessException e) { String message = (e.getMessage() == null) diff --git a/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/CameraTest.java b/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/CameraTest.java index 9b2b4ffeec81..0a73e0a29752 100644 --- a/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/CameraTest.java +++ b/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/CameraTest.java @@ -976,6 +976,62 @@ public void setFocusMode_shouldSendErrorEventOnLockAutoFocusCameraAccessExceptio verify(mockDartMessenger, times(1)).sendCameraErrorEvent(any()); } + @Test + public void createTriggerResetCallback_shouldResetTriggerOnCaptureCompleted() { + CaptureRequest.Key triggerKey = CaptureRequest.CONTROL_AF_TRIGGER; + int idleValue = CameraMetadata.CONTROL_AF_TRIGGER_IDLE; + + CameraCaptureSession.CaptureCallback callback = + camera.createTriggerResetCallback(triggerKey, idleValue); + + callback.onCaptureCompleted( + mock(CameraCaptureSession.class), mock(CaptureRequest.class), mock(TotalCaptureResult.class)); + + verify(mockPreviewRequestBuilder, times(1)).set(triggerKey, idleValue); + } + + @Test + public void createTriggerResetCallback_shouldResetTriggerOnCaptureFailed() { + CaptureRequest.Key triggerKey = CaptureRequest.CONTROL_AF_TRIGGER; + int idleValue = CameraMetadata.CONTROL_AF_TRIGGER_IDLE; + + CameraCaptureSession.CaptureCallback callback = + camera.createTriggerResetCallback(triggerKey, idleValue); + + callback.onCaptureFailed( + mock(CameraCaptureSession.class), mock(CaptureRequest.class), mock(CaptureFailure.class)); + + verify(mockPreviewRequestBuilder, times(1)).set(triggerKey, idleValue); + } + + @Test + public void createTriggerResetCallback_shouldResetAEPrecaptureTriggerOnCaptureCompleted() { + CaptureRequest.Key triggerKey = CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER; + int idleValue = CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE; + + CameraCaptureSession.CaptureCallback callback = + camera.createTriggerResetCallback(triggerKey, idleValue); + + callback.onCaptureCompleted( + mock(CameraCaptureSession.class), mock(CaptureRequest.class), mock(TotalCaptureResult.class)); + + verify(mockPreviewRequestBuilder, times(1)).set(triggerKey, idleValue); + } + + @Test + public void createTriggerResetCallback_shouldResetAEPrecaptureTriggerOnCaptureFailed() { + CaptureRequest.Key triggerKey = CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER; + int idleValue = CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE; + + CameraCaptureSession.CaptureCallback callback = + camera.createTriggerResetCallback(triggerKey, idleValue); + + callback.onCaptureFailed( + mock(CameraCaptureSession.class), mock(CaptureRequest.class), mock(CaptureFailure.class)); + + verify(mockPreviewRequestBuilder, times(1)).set(triggerKey, idleValue); + } + @Test public void setFocusMode_shouldCallErrorOnResultOnCameraAccessException() throws CameraAccessException { From daa1d076585598262aa027075fbab43aa9d3ebb7 Mon Sep 17 00:00:00 2001 From: q2a3z <57368238+q2a3z@users.noreply.github.com> Date: Sat, 28 Mar 2026 02:53:08 +0900 Subject: [PATCH 3/3] Revert "[camera_android] Reset AE and AF triggers to idle after capture" This reverts commit 61b2ecdfef232bcff3b748f24513167926ebbeb6. --- .../src/main/java/io/flutter/plugins/camera/Camera.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java index f3b291856bdb..f76a1cde5eac 100644 --- a/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java +++ b/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/Camera.java @@ -682,11 +682,6 @@ private void runPrecaptureSequence() { CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE), backgroundHandler); - // Reset the trigger to idle again. - previewRequestBuilder.set( - CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, - CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE); - } catch (CameraAccessException e) { e.printStackTrace(); } @@ -832,9 +827,6 @@ private void lockAutoFocus() { : e.getMessage(); dartMessenger.sendCameraErrorEvent(message); } - // Reset the trigger to idle again. - previewRequestBuilder.set( - CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE); } /** Cancel and reset auto focus state and refresh the preview session. */