[camera_android] Provides a default exposure point if null. (#3851)
Recently we had problems in our apps (they use the camera a lot), due to the error of [CONTROL_AE_REGIONS] being set to a null value.
It should now return the default exposure point value. Thanks https://github.com/AnggaSP
Fix attempt for https://github.com/flutter/flutter/issues/105200
diff --git a/packages/camera/camera_android/CHANGELOG.md b/packages/camera/camera_android/CHANGELOG.md
index a0a0fd8..426731a 100644
--- a/packages/camera/camera_android/CHANGELOG.md
+++ b/packages/camera/camera_android/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.10.8+5
+
+* Provides a default exposure point if null.
+
## 0.10.8+4
* Adjusts SDK checks for better testability.
diff --git a/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/features/exposurepoint/ExposurePointFeature.java b/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/features/exposurepoint/ExposurePointFeature.java
index 40f28ea..afeed98 100644
--- a/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/features/exposurepoint/ExposurePointFeature.java
+++ b/packages/camera/camera_android/android/src/main/java/io/flutter/plugins/camera/features/exposurepoint/ExposurePointFeature.java
@@ -10,6 +10,7 @@
import android.util.Size;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
import io.flutter.plugins.camera.CameraProperties;
import io.flutter.plugins.camera.CameraRegionUtils;
@@ -24,6 +25,8 @@
@Nullable private Point exposurePoint;
private MeteringRectangle exposureRectangle;
@NonNull private final SensorOrientationFeature sensorOrientationFeature;
+ private boolean defaultRegionsHasBeenSet = false;
+ @VisibleForTesting @Nullable public MeteringRectangle[] defaultRegions;
/**
* Creates a new instance of the {@link ExposurePointFeature}.
@@ -78,9 +81,18 @@
if (!checkIsSupported()) {
return;
}
- requestBuilder.set(
- CaptureRequest.CONTROL_AE_REGIONS,
- exposureRectangle == null ? null : new MeteringRectangle[] {exposureRectangle});
+
+ if (!defaultRegionsHasBeenSet) {
+ defaultRegions = requestBuilder.get(CaptureRequest.CONTROL_AE_REGIONS);
+ defaultRegionsHasBeenSet = true;
+ }
+
+ if (exposureRectangle != null) {
+ requestBuilder.set(
+ CaptureRequest.CONTROL_AE_REGIONS, new MeteringRectangle[] {exposureRectangle});
+ } else {
+ requestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, defaultRegions);
+ }
}
private void buildExposureRectangle() {
diff --git a/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/features/exposurepoint/ExposurePointFeatureTest.java b/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/features/exposurepoint/ExposurePointFeatureTest.java
index 800c3f7..1eaa537 100644
--- a/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/features/exposurepoint/ExposurePointFeatureTest.java
+++ b/packages/camera/camera_android/android/src/test/java/io/flutter/plugins/camera/features/exposurepoint/ExposurePointFeatureTest.java
@@ -9,7 +9,7 @@
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -281,7 +281,7 @@
}
@Test
- public void updateBuilder_shouldNotSetMeteringRectangleWhenNoValidBoundariesAreSupplied() {
+ public void updateBuilder_shoulSetDefaultMeteringRectangleWhenNoValidBoundariesAreSupplied() {
CameraProperties mockCameraProperties = mock(CameraProperties.class);
when(mockCameraProperties.getControlMaxRegionsAutoExposure()).thenReturn(1);
CaptureRequest.Builder mockCaptureRequestBuilder = mock(CaptureRequest.Builder.class);
@@ -290,11 +290,11 @@
exposurePointFeature.updateBuilder(mockCaptureRequestBuilder);
- verify(mockCaptureRequestBuilder, times(1)).set(any(), isNull());
+ verify(mockCaptureRequestBuilder, times(1)).set(any(), any());
}
@Test
- public void updateBuilder_shouldNotSetMeteringRectangleWhenNoValidCoordsAreSupplied() {
+ public void updateBuilder_shouldSetDefaultMeteringRectangleWhenNoValidCoordsAreSupplied() {
CameraProperties mockCameraProperties = mock(CameraProperties.class);
when(mockCameraProperties.getControlMaxRegionsAutoExposure()).thenReturn(1);
CaptureRequest.Builder mockCaptureRequestBuilder = mock(CaptureRequest.Builder.class);
@@ -302,12 +302,40 @@
new ExposurePointFeature(mockCameraProperties, mockSensorOrientationFeature);
exposurePointFeature.setCameraBoundaries(this.mockCameraBoundaries);
+ MeteringRectangle[] defaultRegions =
+ new MeteringRectangle[] {new MeteringRectangle(0, 0, 100, 100, 0)};
+ when(mockCaptureRequestBuilder.get(CaptureRequest.CONTROL_AE_REGIONS))
+ .thenReturn(defaultRegions);
+
exposurePointFeature.setValue(null);
exposurePointFeature.updateBuilder(mockCaptureRequestBuilder);
exposurePointFeature.setValue(new Point(0d, null));
exposurePointFeature.updateBuilder(mockCaptureRequestBuilder);
exposurePointFeature.setValue(new Point(null, 0d));
exposurePointFeature.updateBuilder(mockCaptureRequestBuilder);
- verify(mockCaptureRequestBuilder, times(3)).set(any(), isNull());
+
+ verify(mockCaptureRequestBuilder, times(3)).set(any(), eq(defaultRegions));
+ }
+
+ @Test
+ public void updateBuilder_shouldSetNonNullMeteringRectangleWhenNullValueIsSupplied() {
+ CameraProperties mockCameraProperties = mock(CameraProperties.class);
+ when(mockCameraProperties.getControlMaxRegionsAutoExposure()).thenReturn(1);
+ CaptureRequest.Builder mockCaptureRequestBuilder = mock(CaptureRequest.Builder.class);
+ ExposurePointFeature exposurePointFeature =
+ new ExposurePointFeature(mockCameraProperties, mockSensorOrientationFeature);
+
+ MeteringRectangle[] defaultRegions =
+ new MeteringRectangle[] {new MeteringRectangle(0, 0, 100, 100, 0)};
+ when(mockCaptureRequestBuilder.get(CaptureRequest.CONTROL_AE_REGIONS))
+ .thenReturn(defaultRegions);
+
+ exposurePointFeature.setCameraBoundaries(this.mockCameraBoundaries);
+
+ exposurePointFeature.setValue(null);
+
+ exposurePointFeature.updateBuilder(mockCaptureRequestBuilder);
+
+ verify(mockCaptureRequestBuilder, times(1)).set(any(), eq(exposurePointFeature.defaultRegions));
}
}
diff --git a/packages/camera/camera_android/pubspec.yaml b/packages/camera/camera_android/pubspec.yaml
index 307506a..68e539e 100644
--- a/packages/camera/camera_android/pubspec.yaml
+++ b/packages/camera/camera_android/pubspec.yaml
@@ -3,7 +3,7 @@
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
-version: 0.10.8+4
+version: 0.10.8+5
environment:
sdk: ">=2.18.0 <4.0.0"