[camerax] Implements torch mode (#4903)
Implements the torch flash mode. Also wraps classes necessary for the implementation (a method in `Camera`, `CameraControl`).
Fixes https://github.com/flutter/flutter/issues/120715.
Fixes https://github.com/flutter/flutter/issues/115846.
Part of https://github.com/flutter/flutter/issues/115847.
diff --git a/packages/camera/camera_android_camerax/CHANGELOG.md b/packages/camera/camera_android_camerax/CHANGELOG.md
index 6db9956..995e917 100644
--- a/packages/camera/camera_android_camerax/CHANGELOG.md
+++ b/packages/camera/camera_android_camerax/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.5.0+19
+
+* Implements torch flash mode.
+
## 0.5.0+18
* Implements `startVideoCapturing`.
diff --git a/packages/camera/camera_android_camerax/README.md b/packages/camera/camera_android_camerax/README.md
index 63c0bf5..a9a3ddc 100644
--- a/packages/camera/camera_android_camerax/README.md
+++ b/packages/camera/camera_android_camerax/README.md
@@ -35,10 +35,6 @@
`lockCaptureOrientation` & `unLockCaptureOrientation` are unimplemented.
-### Torch mode \[[Issue #120715][120715]\]
-
-Calling `setFlashMode` with mode `FlashMode.torch` currently does nothing.
-
### Exposure mode, point, & offset configuration \[[Issue #120468][120468]\]
`setExposureMode`, `setExposurePoint`, & `setExposureOffset` are unimplemented.
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java
index d2a9c27..eeb3c02 100644
--- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java
@@ -25,6 +25,7 @@
private VideoCaptureHostApiImpl videoCaptureHostApiImpl;
private ImageAnalysisHostApiImpl imageAnalysisHostApiImpl;
private ImageCaptureHostApiImpl imageCaptureHostApiImpl;
+ private CameraControlHostApiImpl cameraControlHostApiImpl;
public @Nullable SystemServicesHostApiImpl systemServicesHostApiImpl;
@VisibleForTesting
@@ -81,7 +82,8 @@
GeneratedCameraXLibrary.LiveDataHostApi.setup(binaryMessenger, liveDataHostApiImpl);
GeneratedCameraXLibrary.ObserverHostApi.setup(
binaryMessenger, new ObserverHostApiImpl(binaryMessenger, instanceManager));
- imageAnalysisHostApiImpl = new ImageAnalysisHostApiImpl(binaryMessenger, instanceManager);
+ imageAnalysisHostApiImpl =
+ new ImageAnalysisHostApiImpl(binaryMessenger, instanceManager, context);
GeneratedCameraXLibrary.ImageAnalysisHostApi.setup(binaryMessenger, imageAnalysisHostApiImpl);
GeneratedCameraXLibrary.AnalyzerHostApi.setup(
binaryMessenger, new AnalyzerHostApiImpl(binaryMessenger, instanceManager));
@@ -107,6 +109,8 @@
binaryMessenger, new FallbackStrategyHostApiImpl(instanceManager));
GeneratedCameraXLibrary.QualitySelectorHostApi.setup(
binaryMessenger, new QualitySelectorHostApiImpl(instanceManager));
+ cameraControlHostApiImpl = new CameraControlHostApiImpl(instanceManager, context);
+ GeneratedCameraXLibrary.CameraControlHostApi.setup(binaryMessenger, cameraControlHostApiImpl);
}
@Override
@@ -128,7 +132,6 @@
Activity activity = activityPluginBinding.getActivity();
setUp(pluginBinding.getBinaryMessenger(), activity, pluginBinding.getTextureRegistry());
- updateContext(activity);
if (activity instanceof LifecycleOwner) {
processCameraProviderHostApiImpl.setLifecycleOwner((LifecycleOwner) activity);
@@ -183,5 +186,8 @@
if (imageAnalysisHostApiImpl != null) {
imageAnalysisHostApiImpl.setContext(context);
}
+ if (cameraControlHostApiImpl != null) {
+ cameraControlHostApiImpl.setContext(context);
+ }
}
}
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraControlFlutterApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraControlFlutterApiImpl.java
new file mode 100644
index 0000000..1b61618
--- /dev/null
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraControlFlutterApiImpl.java
@@ -0,0 +1,29 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.camerax;
+
+import androidx.annotation.NonNull;
+import androidx.camera.core.CameraControl;
+import io.flutter.plugin.common.BinaryMessenger;
+import io.flutter.plugins.camerax.GeneratedCameraXLibrary.CameraControlFlutterApi;
+
+public class CameraControlFlutterApiImpl extends CameraControlFlutterApi {
+ private final @NonNull InstanceManager instanceManager;
+
+ public CameraControlFlutterApiImpl(
+ @NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager) {
+ super(binaryMessenger);
+ this.instanceManager = instanceManager;
+ }
+
+ /**
+ * Creates a {@link CameraControl} instance in Dart. {@code reply} is not used so it can be empty.
+ */
+ void create(CameraControl cameraControl, Reply<Void> reply) {
+ if (!instanceManager.containsInstance(cameraControl)) {
+ create(instanceManager.addHostCreatedInstance(cameraControl), reply);
+ }
+ }
+}
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraControlHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraControlHostApiImpl.java
new file mode 100644
index 0000000..8241fda
--- /dev/null
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraControlHostApiImpl.java
@@ -0,0 +1,101 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.camerax;
+
+import android.content.Context;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+import androidx.camera.core.CameraControl;
+import androidx.core.content.ContextCompat;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import io.flutter.plugins.camerax.GeneratedCameraXLibrary.CameraControlHostApi;
+import java.util.Objects;
+
+/**
+ * Host API implementation for {@link CameraControl}.
+ *
+ * <p>This class handles instantiating and adding native object instances that are attached to a
+ * Dart instance or handle method calls on the associated native class or an instance of the class.
+ */
+public class CameraControlHostApiImpl implements CameraControlHostApi {
+ private final InstanceManager instanceManager;
+ private final CameraControlProxy proxy;
+
+ /** Proxy for constructors and static method of {@link CameraControl}. */
+ @VisibleForTesting
+ public static class CameraControlProxy {
+ Context context;
+
+ /** Enables or disables the torch of the specified {@link CameraControl} instance. */
+ @NonNull
+ public void enableTorch(
+ @NonNull CameraControl cameraControl,
+ @NonNull Boolean torch,
+ @NonNull GeneratedCameraXLibrary.Result<Void> result) {
+ ListenableFuture<Void> enableTorchFuture = cameraControl.enableTorch(torch);
+
+ Futures.addCallback(
+ enableTorchFuture,
+ new FutureCallback<Void>() {
+ public void onSuccess(Void voidResult) {
+ result.success(null);
+ }
+
+ public void onFailure(Throwable t) {
+ result.error(t);
+ }
+ },
+ ContextCompat.getMainExecutor(context));
+ }
+ }
+
+ /**
+ * Constructs an {@link CameraControlHostApiImpl}.
+ *
+ * @param instanceManager maintains instances stored to communicate with attached Dart objects
+ */
+ public CameraControlHostApiImpl(
+ @NonNull InstanceManager instanceManager, @NonNull Context context) {
+ this(instanceManager, new CameraControlProxy(), context);
+ }
+
+ /**
+ * Constructs an {@link CameraControlHostApiImpl}.
+ *
+ * @param instanceManager maintains instances stored to communicate with attached Dart objects
+ * @param proxy proxy for constructors and static method of {@link CameraControl}
+ * @param context {@link Context} used to retrieve {@code Executor} used to enable torch mode
+ */
+ @VisibleForTesting
+ CameraControlHostApiImpl(
+ @NonNull InstanceManager instanceManager,
+ @NonNull CameraControlProxy proxy,
+ @NonNull Context context) {
+ this.instanceManager = instanceManager;
+ this.proxy = proxy;
+ proxy.context = context;
+ }
+
+ /**
+ * Sets the context that the {@code ProcessCameraProvider} will use to enable/disable torch mode.
+ *
+ * <p>If using the camera plugin in an add-to-app context, ensure that a new instance of the
+ * {@code CameraControl} is fetched via {@code #enableTorch} anytime the context changes.
+ */
+ public void setContext(@NonNull Context context) {
+ this.proxy.context = context;
+ }
+
+ @Override
+ public void enableTorch(
+ @NonNull Long identifier,
+ @NonNull Boolean torch,
+ @NonNull GeneratedCameraXLibrary.Result<Void> result) {
+ proxy.enableTorch(
+ Objects.requireNonNull(instanceManager.getInstance(identifier)), torch, result);
+ }
+}
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraHostApiImpl.java
index 98f5f74..603cc62 100644
--- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraHostApiImpl.java
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraHostApiImpl.java
@@ -6,6 +6,7 @@
import androidx.annotation.NonNull;
import androidx.camera.core.Camera;
+import androidx.camera.core.CameraControl;
import androidx.camera.core.CameraInfo;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.CameraHostApi;
@@ -28,14 +29,33 @@
@Override
@NonNull
public Long getCameraInfo(@NonNull Long identifier) {
- Camera camera = (Camera) Objects.requireNonNull(instanceManager.getInstance(identifier));
+ Camera camera = getCameraInstance(identifier);
CameraInfo cameraInfo = camera.getCameraInfo();
- if (!instanceManager.containsInstance(cameraInfo)) {
- CameraInfoFlutterApiImpl cameraInfoFlutterApiImpl =
- new CameraInfoFlutterApiImpl(binaryMessenger, instanceManager);
- cameraInfoFlutterApiImpl.create(cameraInfo, reply -> {});
- }
+ CameraInfoFlutterApiImpl cameraInfoFlutterApiImpl =
+ new CameraInfoFlutterApiImpl(binaryMessenger, instanceManager);
+ cameraInfoFlutterApiImpl.create(cameraInfo, reply -> {});
return instanceManager.getIdentifierForStrongReference(cameraInfo);
}
+
+ /**
+ * Retrieves the {@link CameraControl} instance that provides access to asynchronous operations
+ * like zoom and focus & metering on the {@link Camera} instance with the specified identifier.
+ */
+ @Override
+ @NonNull
+ public Long getCameraControl(@NonNull Long identifier) {
+ Camera camera = getCameraInstance(identifier);
+ CameraControl cameraControl = camera.getCameraControl();
+
+ CameraControlFlutterApiImpl cameraControlFlutterApiImpl =
+ new CameraControlFlutterApiImpl(binaryMessenger, instanceManager);
+ cameraControlFlutterApiImpl.create(cameraControl, reply -> {});
+ return instanceManager.getIdentifierForStrongReference(cameraControl);
+ }
+
+ /** Retrieives the {@link Camera} instance associated with the specified {@code identifier}. */
+ private Camera getCameraInstance(@NonNull Long identifier) {
+ return (Camera) Objects.requireNonNull(instanceManager.getInstance(identifier));
+ }
}
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/GeneratedCameraXLibrary.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/GeneratedCameraXLibrary.java
index fe9a935..224ba11 100644
--- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/GeneratedCameraXLibrary.java
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/GeneratedCameraXLibrary.java
@@ -1136,6 +1136,9 @@
@NonNull
Long getCameraInfo(@NonNull Long identifier);
+ @NonNull
+ Long getCameraControl(@NonNull Long identifier);
+
/** The codec used by CameraHostApi. */
static @NonNull MessageCodec<Object> getCodec() {
return new StandardMessageCodec();
@@ -1166,6 +1169,31 @@
channel.setMessageHandler(null);
}
}
+ {
+ BasicMessageChannel<Object> channel =
+ new BasicMessageChannel<>(
+ binaryMessenger, "dev.flutter.pigeon.CameraHostApi.getCameraControl", getCodec());
+ if (api != null) {
+ channel.setMessageHandler(
+ (message, reply) -> {
+ ArrayList<Object> wrapped = new ArrayList<Object>();
+ ArrayList<Object> args = (ArrayList<Object>) message;
+ Number identifierArg = (Number) args.get(0);
+ try {
+ Long output =
+ api.getCameraControl(
+ (identifierArg == null) ? null : identifierArg.longValue());
+ wrapped.add(0, output);
+ } catch (Throwable exception) {
+ ArrayList<Object> wrappedError = wrapError(exception);
+ wrapped = wrappedError;
+ }
+ reply.reply(wrapped);
+ });
+ } else {
+ channel.setMessageHandler(null);
+ }
+ }
}
}
/** Generated class from Pigeon that represents Flutter messages that can be called from Java. */
@@ -3203,4 +3231,82 @@
}
}
}
+ /** Generated interface from Pigeon that represents a handler of messages from Flutter. */
+ public interface CameraControlHostApi {
+
+ void enableTorch(
+ @NonNull Long identifier, @NonNull Boolean torch, @NonNull Result<Void> result);
+
+ /** The codec used by CameraControlHostApi. */
+ static @NonNull MessageCodec<Object> getCodec() {
+ return new StandardMessageCodec();
+ }
+ /**
+ * Sets up an instance of `CameraControlHostApi` to handle messages through the
+ * `binaryMessenger`.
+ */
+ static void setup(
+ @NonNull BinaryMessenger binaryMessenger, @Nullable CameraControlHostApi api) {
+ {
+ BasicMessageChannel<Object> channel =
+ new BasicMessageChannel<>(
+ binaryMessenger, "dev.flutter.pigeon.CameraControlHostApi.enableTorch", getCodec());
+ if (api != null) {
+ channel.setMessageHandler(
+ (message, reply) -> {
+ ArrayList<Object> wrapped = new ArrayList<Object>();
+ ArrayList<Object> args = (ArrayList<Object>) message;
+ Number identifierArg = (Number) args.get(0);
+ Boolean torchArg = (Boolean) args.get(1);
+ Result<Void> resultCallback =
+ new Result<Void>() {
+ public void success(Void result) {
+ wrapped.add(0, null);
+ reply.reply(wrapped);
+ }
+
+ public void error(Throwable error) {
+ ArrayList<Object> wrappedError = wrapError(error);
+ reply.reply(wrappedError);
+ }
+ };
+
+ api.enableTorch(
+ (identifierArg == null) ? null : identifierArg.longValue(),
+ torchArg,
+ resultCallback);
+ });
+ } else {
+ channel.setMessageHandler(null);
+ }
+ }
+ }
+ }
+ /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */
+ public static class CameraControlFlutterApi {
+ private final @NonNull BinaryMessenger binaryMessenger;
+
+ public CameraControlFlutterApi(@NonNull BinaryMessenger argBinaryMessenger) {
+ this.binaryMessenger = argBinaryMessenger;
+ }
+
+ /** Public interface for sending reply. */
+ @SuppressWarnings("UnknownNullness")
+ public interface Reply<T> {
+ void reply(T reply);
+ }
+ /** The codec used by CameraControlFlutterApi. */
+ static @NonNull MessageCodec<Object> getCodec() {
+ return new StandardMessageCodec();
+ }
+
+ public void create(@NonNull Long identifierArg, @NonNull Reply<Void> callback) {
+ BasicMessageChannel<Object> channel =
+ new BasicMessageChannel<>(
+ binaryMessenger, "dev.flutter.pigeon.CameraControlFlutterApi.create", getCodec());
+ channel.send(
+ new ArrayList<Object>(Collections.singletonList(identifierArg)),
+ channelReply -> callback.reply(null));
+ }
+ }
}
diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageAnalysisHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageAnalysisHostApiImpl.java
index 5849147..00bceb7 100644
--- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageAnalysisHostApiImpl.java
+++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/ImageAnalysisHostApiImpl.java
@@ -24,9 +24,12 @@
@VisibleForTesting @NonNull public CameraXProxy cameraXProxy = new CameraXProxy();
public ImageAnalysisHostApiImpl(
- @NonNull BinaryMessenger binaryMessenger, @NonNull InstanceManager instanceManager) {
+ @NonNull BinaryMessenger binaryMessenger,
+ @NonNull InstanceManager instanceManager,
+ @NonNull Context context) {
this.binaryMessenger = binaryMessenger;
this.instanceManager = instanceManager;
+ this.context = context;
}
/**
diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraControlTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraControlTest.java
new file mode 100644
index 0000000..5e17f64
--- /dev/null
+++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraControlTest.java
@@ -0,0 +1,111 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package io.flutter.plugins.camerax;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import androidx.camera.core.CameraControl;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import io.flutter.plugin.common.BinaryMessenger;
+import java.util.Objects;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+public class CameraControlTest {
+ @Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
+
+ @Mock public BinaryMessenger mockBinaryMessenger;
+ @Mock public CameraControl cameraControl;
+
+ InstanceManager testInstanceManager;
+
+ @Before
+ public void setUp() {
+ testInstanceManager = InstanceManager.create(identifier -> {});
+ }
+
+ @After
+ public void tearDown() {
+ testInstanceManager.stopFinalizationListener();
+ }
+
+ @Test
+ public void enableTorch_turnsTorchModeOnAndOffAsExpected() {
+ try (MockedStatic<Futures> mockedFutures = Mockito.mockStatic(Futures.class)) {
+ final CameraControlHostApiImpl cameraControlHostApiImpl =
+ new CameraControlHostApiImpl(testInstanceManager, mock(Context.class));
+ final Long cameraControlIdentifier = 88L;
+ final boolean enableTorch = true;
+
+ @SuppressWarnings("unchecked")
+ final ListenableFuture<Void> enableTorchFuture = mock(ListenableFuture.class);
+
+ testInstanceManager.addDartCreatedInstance(cameraControl, cameraControlIdentifier);
+
+ when(cameraControl.enableTorch(true)).thenReturn(enableTorchFuture);
+
+ @SuppressWarnings("unchecked")
+ final ArgumentCaptor<FutureCallback<Void>> futureCallbackCaptor =
+ ArgumentCaptor.forClass(FutureCallback.class);
+
+ // Test turning on torch mode.
+ @SuppressWarnings("unchecked")
+ final GeneratedCameraXLibrary.Result<Void> successfulMockResult =
+ mock(GeneratedCameraXLibrary.Result.class);
+ cameraControlHostApiImpl.enableTorch(
+ cameraControlIdentifier, enableTorch, successfulMockResult);
+ mockedFutures.verify(
+ () -> Futures.addCallback(eq(enableTorchFuture), futureCallbackCaptor.capture(), any()));
+ mockedFutures.clearInvocations();
+
+ FutureCallback<Void> successfulEnableTorchCallback = futureCallbackCaptor.getValue();
+
+ successfulEnableTorchCallback.onSuccess(mock(Void.class));
+ verify(successfulMockResult).success(null);
+
+ // Test turning off torch mode.
+ @SuppressWarnings("unchecked")
+ final GeneratedCameraXLibrary.Result<Void> failedMockResult =
+ mock(GeneratedCameraXLibrary.Result.class);
+ final Throwable testThrowable = new Throwable();
+ cameraControlHostApiImpl.enableTorch(cameraControlIdentifier, enableTorch, failedMockResult);
+ mockedFutures.verify(
+ () -> Futures.addCallback(eq(enableTorchFuture), futureCallbackCaptor.capture(), any()));
+
+ FutureCallback<Void> failedEnableTorchCallback = futureCallbackCaptor.getValue();
+
+ failedEnableTorchCallback.onFailure(testThrowable);
+ verify(failedMockResult).error(testThrowable);
+ }
+ }
+
+ @Test
+ public void flutterApiCreate_makesCallToCreateInstanceOnDartSide() {
+ final CameraControlFlutterApiImpl spyFlutterApi =
+ spy(new CameraControlFlutterApiImpl(mockBinaryMessenger, testInstanceManager));
+
+ spyFlutterApi.create(cameraControl, reply -> {});
+
+ final long cameraControlIdentifier =
+ Objects.requireNonNull(testInstanceManager.getIdentifierForStrongReference(cameraControl));
+ verify(spyFlutterApi).create(eq(cameraControlIdentifier), any());
+ }
+}
diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraTest.java
index fb6b0b3..590529c 100644
--- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraTest.java
+++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraTest.java
@@ -13,6 +13,7 @@
import static org.mockito.Mockito.when;
import androidx.camera.core.Camera;
+import androidx.camera.core.CameraControl;
import androidx.camera.core.CameraInfo;
import io.flutter.plugin.common.BinaryMessenger;
import java.util.Objects;
@@ -60,6 +61,23 @@
}
@Test
+ public void getCameraControl_retrievesExpectedCameraControlInstance() {
+ final CameraHostApiImpl cameraHostApiImpl =
+ new CameraHostApiImpl(mockBinaryMessenger, testInstanceManager);
+ final CameraControl mockCameraControl = mock(CameraControl.class);
+ final Long cameraIdentifier = 43L;
+ final Long mockCameraControlIdentifier = 79L;
+
+ testInstanceManager.addDartCreatedInstance(camera, cameraIdentifier);
+ testInstanceManager.addDartCreatedInstance(mockCameraControl, mockCameraControlIdentifier);
+
+ when(camera.getCameraControl()).thenReturn(mockCameraControl);
+
+ assertEquals(cameraHostApiImpl.getCameraControl(cameraIdentifier), mockCameraControlIdentifier);
+ verify(camera).getCameraControl();
+ }
+
+ @Test
public void flutterApiCreate_makesCallToCreateInstanceOnDartSide() {
final CameraFlutterApiImpl spyFlutterApi =
spy(new CameraFlutterApiImpl(mockBinaryMessenger, testInstanceManager));
diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageAnalysisTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageAnalysisTest.java
index b9a6d29..08a9f80 100644
--- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageAnalysisTest.java
+++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/ImageAnalysisTest.java
@@ -50,7 +50,7 @@
@Test
public void hostApiCreate_createsExpectedImageAnalysisInstanceWithExpectedIdentifier() {
final ImageAnalysisHostApiImpl hostApi =
- new ImageAnalysisHostApiImpl(mockBinaryMessenger, instanceManager);
+ new ImageAnalysisHostApiImpl(mockBinaryMessenger, instanceManager, context);
final CameraXProxy mockCameraXProxy = mock(CameraXProxy.class);
final ImageAnalysis.Builder mockImageAnalysisBuilder = mock(ImageAnalysis.Builder.class);
final ResolutionSelector mockResolutionSelector = mock(ResolutionSelector.class);
@@ -72,8 +72,7 @@
@Test
public void setAnalyzer_makesCallToSetAnalyzerOnExpectedImageAnalysisInstance() {
final ImageAnalysisHostApiImpl hostApi =
- new ImageAnalysisHostApiImpl(mockBinaryMessenger, instanceManager);
- hostApi.setContext(context);
+ new ImageAnalysisHostApiImpl(mockBinaryMessenger, instanceManager, context);
final ImageAnalysis.Analyzer mockAnalyzer = mock(ImageAnalysis.Analyzer.class);
final long analyzerIdentifier = 10;
@@ -90,7 +89,7 @@
@Test
public void clearAnalyzer_makesCallToClearAnalyzerOnExpectedImageAnalysisInstance() {
final ImageAnalysisHostApiImpl hostApi =
- new ImageAnalysisHostApiImpl(mockBinaryMessenger, instanceManager);
+ new ImageAnalysisHostApiImpl(mockBinaryMessenger, instanceManager, context);
final long instanceIdentifier = 22;
instanceManager.addDartCreatedInstance(mockImageAnalysis, instanceIdentifier);
diff --git a/packages/camera/camera_android_camerax/example/lib/main.dart b/packages/camera/camera_android_camerax/example/lib/main.dart
index 5dbfffa..ec6fb51 100644
--- a/packages/camera/camera_android_camerax/example/lib/main.dart
+++ b/packages/camera/camera_android_camerax/example/lib/main.dart
@@ -274,7 +274,7 @@
IconButton(
icon: const Icon(Icons.flash_on),
color: Colors.blue,
- onPressed: () {}, // TODO(camsim99): Add functionality back here.
+ onPressed: controller != null ? onFlashModeButtonPressed : null,
),
// The exposure and focus mode are currently not supported on the web.
...!kIsWeb
@@ -326,28 +326,36 @@
color: controller?.value.flashMode == FlashMode.off
? Colors.orange
: Colors.blue,
- onPressed: () {}, // TODO(camsim99): Add functionality back here.
+ onPressed: controller != null
+ ? () => onSetFlashModeButtonPressed(FlashMode.off)
+ : null,
),
IconButton(
icon: const Icon(Icons.flash_auto),
color: controller?.value.flashMode == FlashMode.auto
? Colors.orange
: Colors.blue,
- onPressed: () {}, // TODO(camsim99): Add functionality back here.
+ onPressed: controller != null
+ ? () => onSetFlashModeButtonPressed(FlashMode.auto)
+ : null,
),
IconButton(
icon: const Icon(Icons.flash_on),
color: controller?.value.flashMode == FlashMode.always
? Colors.orange
: Colors.blue,
- onPressed: () {}, // TODO(camsim99): Add functionality back here.
+ onPressed: controller != null
+ ? () => onSetFlashModeButtonPressed(FlashMode.always)
+ : null,
),
IconButton(
icon: const Icon(Icons.highlight),
color: controller?.value.flashMode == FlashMode.torch
? Colors.orange
: Colors.blue,
- onPressed: () {}, // TODO(camsim99): Add functionality back here.
+ onPressed: controller != null
+ ? () => onSetFlashModeButtonPressed(FlashMode.torch)
+ : null,
),
],
),
diff --git a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart
index c915961..8b06bf6 100644
--- a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart
+++ b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart
@@ -11,6 +11,7 @@
import 'analyzer.dart';
import 'camera.dart';
+import 'camera_control.dart';
import 'camera_info.dart';
import 'camera_selector.dart';
import 'camera_state.dart';
@@ -111,6 +112,10 @@
/// The flash mode currently configured for [imageCapture].
int? _currentFlashMode;
+ /// Whether or not torch flash mode has been enabled for the [camera].
+ @visibleForTesting
+ bool torchEnabled = false;
+
/// The [ImageAnalysis] instance that can be configured to analyze individual
/// frames.
ImageAnalysis? imageAnalysis;
@@ -483,14 +488,37 @@
Future<XFile> takePicture(int cameraId) async {
if (_currentFlashMode != null) {
await imageCapture!.setFlashMode(_currentFlashMode!);
+ } else if (torchEnabled) {
+ // Ensure any previously set flash modes are unset when torch mode has
+ // been enabled.
+ await imageCapture!.setFlashMode(ImageCapture.flashModeOff);
}
final String picturePath = await imageCapture!.takePicture();
return XFile(picturePath);
}
/// Sets the flash mode for the selected camera.
+ ///
+ /// When the [FlashMode.torch] is enabled, any previously set [FlashMode] with
+ /// this method will be disabled, just as with any other [FlashMode]; while
+ /// this is not default native Android behavior as defined by the CameraX API,
+ /// this behavior is compliant with the plugin platform interface.
+ ///
+ /// This method combines the notion of setting the flash mode of the
+ /// [imageCapture] UseCase and enabling the camera torch, as described
+ /// by https://developer.android.com/reference/androidx/camera/core/ImageCapture
+ /// and https://developer.android.com/reference/androidx/camera/core/CameraControl#enableTorch(boolean),
+ /// respectively.
@override
Future<void> setFlashMode(int cameraId, FlashMode mode) async {
+ CameraControl? cameraControl;
+ // Turn off torch mode if it is enabled and not being redundantly set.
+ if (mode != FlashMode.torch && torchEnabled) {
+ cameraControl = await camera!.getCameraControl();
+ await cameraControl.enableTorch(false);
+ torchEnabled = false;
+ }
+
switch (mode) {
case FlashMode.off:
_currentFlashMode = ImageCapture.flashModeOff;
@@ -502,7 +530,14 @@
_currentFlashMode = ImageCapture.flashModeOn;
break;
case FlashMode.torch:
- // TODO(camsim99): Implement torch mode when CameraControl is wrapped.
+ _currentFlashMode = null;
+ if (torchEnabled) {
+ // Torch mode enabled already.
+ return;
+ }
+ cameraControl = await camera!.getCameraControl();
+ await cameraControl.enableTorch(true);
+ torchEnabled = true;
break;
}
}
diff --git a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax_flutter_api_impls.dart b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax_flutter_api_impls.dart
index b268323..b59e0df 100644
--- a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax_flutter_api_impls.dart
+++ b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax_flutter_api_impls.dart
@@ -4,6 +4,7 @@
import 'analyzer.dart';
import 'camera.dart';
+import 'camera_control.dart';
import 'camera_info.dart';
import 'camera_selector.dart';
import 'camera_state.dart';
@@ -26,27 +27,27 @@
/// Handles initialization of Flutter APIs for the Android CameraX library.
class AndroidCameraXCameraFlutterApis {
/// Creates a [AndroidCameraXCameraFlutterApis].
- AndroidCameraXCameraFlutterApis({
- JavaObjectFlutterApiImpl? javaObjectFlutterApiImpl,
- CameraFlutterApiImpl? cameraFlutterApiImpl,
- CameraInfoFlutterApiImpl? cameraInfoFlutterApiImpl,
- CameraSelectorFlutterApiImpl? cameraSelectorFlutterApiImpl,
- ProcessCameraProviderFlutterApiImpl? processCameraProviderFlutterApiImpl,
- SystemServicesFlutterApiImpl? systemServicesFlutterApiImpl,
- CameraStateErrorFlutterApiImpl? cameraStateErrorFlutterApiImpl,
- CameraStateFlutterApiImpl? cameraStateFlutterApiImpl,
- PendingRecordingFlutterApiImpl? pendingRecordingFlutterApiImpl,
- RecordingFlutterApiImpl? recordingFlutterApiImpl,
- RecorderFlutterApiImpl? recorderFlutterApiImpl,
- VideoCaptureFlutterApiImpl? videoCaptureFlutterApiImpl,
- ExposureStateFlutterApiImpl? exposureStateFlutterApiImpl,
- ZoomStateFlutterApiImpl? zoomStateFlutterApiImpl,
- LiveDataFlutterApiImpl? liveDataFlutterApiImpl,
- ObserverFlutterApiImpl? observerFlutterApiImpl,
- ImageProxyFlutterApiImpl? imageProxyFlutterApiImpl,
- PlaneProxyFlutterApiImpl? planeProxyFlutterApiImpl,
- AnalyzerFlutterApiImpl? analyzerFlutterApiImpl,
- }) {
+ AndroidCameraXCameraFlutterApis(
+ {JavaObjectFlutterApiImpl? javaObjectFlutterApiImpl,
+ CameraFlutterApiImpl? cameraFlutterApiImpl,
+ CameraInfoFlutterApiImpl? cameraInfoFlutterApiImpl,
+ CameraSelectorFlutterApiImpl? cameraSelectorFlutterApiImpl,
+ ProcessCameraProviderFlutterApiImpl? processCameraProviderFlutterApiImpl,
+ SystemServicesFlutterApiImpl? systemServicesFlutterApiImpl,
+ CameraStateErrorFlutterApiImpl? cameraStateErrorFlutterApiImpl,
+ CameraStateFlutterApiImpl? cameraStateFlutterApiImpl,
+ PendingRecordingFlutterApiImpl? pendingRecordingFlutterApiImpl,
+ RecordingFlutterApiImpl? recordingFlutterApiImpl,
+ RecorderFlutterApiImpl? recorderFlutterApiImpl,
+ VideoCaptureFlutterApiImpl? videoCaptureFlutterApiImpl,
+ ExposureStateFlutterApiImpl? exposureStateFlutterApiImpl,
+ ZoomStateFlutterApiImpl? zoomStateFlutterApiImpl,
+ LiveDataFlutterApiImpl? liveDataFlutterApiImpl,
+ ObserverFlutterApiImpl? observerFlutterApiImpl,
+ ImageProxyFlutterApiImpl? imageProxyFlutterApiImpl,
+ PlaneProxyFlutterApiImpl? planeProxyFlutterApiImpl,
+ AnalyzerFlutterApiImpl? analyzerFlutterApiImpl,
+ CameraControlFlutterApiImpl? cameraControlFlutterApiImpl}) {
this.javaObjectFlutterApiImpl =
javaObjectFlutterApiImpl ?? JavaObjectFlutterApiImpl();
this.cameraInfoFlutterApiImpl =
@@ -85,6 +86,8 @@
imageProxyFlutterApiImpl ?? ImageProxyFlutterApiImpl();
this.planeProxyFlutterApiImpl =
planeProxyFlutterApiImpl ?? PlaneProxyFlutterApiImpl();
+ this.cameraControlFlutterApiImpl =
+ cameraControlFlutterApiImpl ?? CameraControlFlutterApiImpl();
}
static bool _haveBeenSetUp = false;
@@ -153,6 +156,9 @@
/// Flutter Api implementation for [PlaneProxy].
late final PlaneProxyFlutterApiImpl planeProxyFlutterApiImpl;
+ /// Flutter Api implementation for [CameraControl].
+ late final CameraControlFlutterApiImpl cameraControlFlutterApiImpl;
+
/// Ensures all the Flutter APIs have been setup to receive calls from native code.
void ensureSetUp() {
if (!_haveBeenSetUp) {
@@ -176,6 +182,7 @@
PlaneProxyFlutterApi.setup(planeProxyFlutterApiImpl);
LiveDataFlutterApi.setup(liveDataFlutterApiImpl);
ObserverFlutterApi.setup(observerFlutterApiImpl);
+ CameraControlFlutterApi.setup(cameraControlFlutterApiImpl);
_haveBeenSetUp = true;
}
}
diff --git a/packages/camera/camera_android_camerax/lib/src/camera.dart b/packages/camera/camera_android_camerax/lib/src/camera.dart
index 8bc1dbf..1001450 100644
--- a/packages/camera/camera_android_camerax/lib/src/camera.dart
+++ b/packages/camera/camera_android_camerax/lib/src/camera.dart
@@ -6,6 +6,7 @@
import 'package:meta/meta.dart' show immutable;
import 'android_camera_camerax_flutter_api_impls.dart';
+import 'camera_control.dart';
import 'camera_info.dart';
import 'camerax_library.g.dart';
import 'instance_manager.dart';
@@ -23,27 +24,33 @@
: super.detached(
binaryMessenger: binaryMessenger,
instanceManager: instanceManager) {
- _api = CameraHostApiImpl(
+ _api = _CameraHostApiImpl(
binaryMessenger: binaryMessenger, instanceManager: instanceManager);
AndroidCameraXCameraFlutterApis.instance.ensureSetUp();
}
- late final CameraHostApiImpl _api;
+ late final _CameraHostApiImpl _api;
- /// Retrieve the [CameraInfo] instance that contains information about this
+ /// Retrieves the [CameraInfo] instance that contains information about this
/// instance.
Future<CameraInfo> getCameraInfo() async {
return _api.getCameraInfoFromInstance(this);
}
+
+ /// Retrieves the [CameraControl] instance that provides asynchronous
+ /// operations like zoom and focus & metering for this instance.
+ Future<CameraControl> getCameraControl() async {
+ return _api.getCameraControlFromInstance(this);
+ }
}
/// Host API implementation of [Camera].
-class CameraHostApiImpl extends CameraHostApi {
- /// Constructs a [CameraHostApiImpl].
+class _CameraHostApiImpl extends CameraHostApi {
+ /// Constructs a [_CameraHostApiImpl].
///
/// An [instanceManager] is typically passed when a copy of an instance
/// contained by an [InstanceManager] is being created.
- CameraHostApiImpl({this.binaryMessenger, InstanceManager? instanceManager})
+ _CameraHostApiImpl({this.binaryMessenger, InstanceManager? instanceManager})
: super(binaryMessenger: binaryMessenger) {
this.instanceManager = instanceManager ?? JavaObject.globalInstanceManager;
}
@@ -57,7 +64,7 @@
/// Maintains instances stored to communicate with native language objects.
late final InstanceManager instanceManager;
- /// Gets the [CameraInfo] associated with the specified instance of [Camera].
+ /// Gets the [CameraInfo] associated with the specified [Camera] instance.
Future<CameraInfo> getCameraInfoFromInstance(Camera instance) async {
final int identifier = instanceManager.getIdentifier(instance)!;
final int cameraInfoId = await getCameraInfo(identifier);
@@ -65,6 +72,15 @@
return instanceManager
.getInstanceWithWeakReference<CameraInfo>(cameraInfoId)!;
}
+
+ /// Gets the [CameraControl] associated with the specified [Camera] instance.
+ Future<CameraControl> getCameraControlFromInstance(Camera instance) async {
+ final int identifier = instanceManager.getIdentifier(instance)!;
+ final int cameraControlId = await getCameraControl(identifier);
+
+ return instanceManager
+ .getInstanceWithWeakReference<CameraControl>(cameraControlId)!;
+ }
}
/// Flutter API implementation of [Camera].
diff --git a/packages/camera/camera_android_camerax/lib/src/camera_control.dart b/packages/camera/camera_android_camerax/lib/src/camera_control.dart
new file mode 100644
index 0000000..b30195c
--- /dev/null
+++ b/packages/camera/camera_android_camerax/lib/src/camera_control.dart
@@ -0,0 +1,109 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/services.dart' show BinaryMessenger, PlatformException;
+import 'package:meta/meta.dart' show immutable;
+
+import 'android_camera_camerax_flutter_api_impls.dart';
+import 'camerax_library.g.dart';
+import 'instance_manager.dart';
+import 'java_object.dart';
+import 'system_services.dart';
+
+/// The interface that provides asynchronous operations like zoom and focus &
+/// metering, which affects output of all [UseCase]s currently bound to the
+/// corresponding [Camera] instance.
+///
+/// See https://developer.android.com/reference/androidx/camera/core/CameraControl.
+@immutable
+class CameraControl extends JavaObject {
+ /// Constructs a [CameraControl] that is not automatically attached to a native object.
+ CameraControl.detached(
+ {BinaryMessenger? binaryMessenger, InstanceManager? instanceManager})
+ : super.detached(
+ binaryMessenger: binaryMessenger,
+ instanceManager: instanceManager) {
+ _api = _CameraControlHostApiImpl(
+ binaryMessenger: binaryMessenger, instanceManager: instanceManager);
+ AndroidCameraXCameraFlutterApis.instance.ensureSetUp();
+ }
+
+ late final _CameraControlHostApiImpl _api;
+
+ /// Enables or disables the torch of related [Camera] instance.
+ Future<void> enableTorch(bool torch) async {
+ return _api.enableTorchFromInstance(this, torch);
+ }
+}
+
+/// Host API implementation of [CameraControl].
+class _CameraControlHostApiImpl extends CameraControlHostApi {
+ /// Constructs a [_CameraControlHostApiImpl].
+ ///
+ /// An [instanceManager] is typically passed when a copy of an instance
+ /// contained by an [InstanceManager] is being created.
+ _CameraControlHostApiImpl(
+ {this.binaryMessenger, InstanceManager? instanceManager})
+ : super(binaryMessenger: binaryMessenger) {
+ this.instanceManager = instanceManager ?? JavaObject.globalInstanceManager;
+ }
+
+ /// Receives binary data across the Flutter platform barrier.
+ ///
+ /// If it is null, the default BinaryMessenger will be used which routes to
+ /// the host platform.
+ final BinaryMessenger? binaryMessenger;
+
+ /// Maintains instances stored to communicate with native language objects.
+ late final InstanceManager instanceManager;
+
+ /// Enables or disables the torch for the specified [CameraControl] instance.
+ Future<void> enableTorchFromInstance(
+ CameraControl instance, bool torch) async {
+ final int identifier = instanceManager.getIdentifier(instance)!;
+ try {
+ await enableTorch(identifier, torch);
+ } on PlatformException catch (e) {
+ SystemServices.cameraErrorStreamController
+ .add(e.message ?? 'The camera was unable to change torch modes.');
+ }
+ }
+}
+
+/// Flutter API implementation of [CameraControl].
+class CameraControlFlutterApiImpl extends CameraControlFlutterApi {
+ /// Constructs a [CameraControlFlutterApiImpl].
+ ///
+ /// If [binaryMessenger] is null, the default [BinaryMessenger] will be used,
+ /// which routes to the host platform.
+ ///
+ /// An [instanceManager] is typically passed when a copy of an instance
+ /// contained by an [InstanceManager] is being created. If left null, it
+ /// will default to the global instance defined in [JavaObject].
+ CameraControlFlutterApiImpl({
+ BinaryMessenger? binaryMessenger,
+ InstanceManager? instanceManager,
+ }) : _binaryMessenger = binaryMessenger,
+ _instanceManager = instanceManager ?? JavaObject.globalInstanceManager;
+
+ /// Receives binary data across the Flutter platform barrier.
+ final BinaryMessenger? _binaryMessenger;
+
+ /// Maintains instances stored to communicate with native language objects.
+ final InstanceManager _instanceManager;
+
+ @override
+ void create(int identifier) {
+ _instanceManager.addHostCreatedInstance(
+ CameraControl.detached(
+ binaryMessenger: _binaryMessenger, instanceManager: _instanceManager),
+ identifier,
+ onCopy: (CameraControl original) {
+ return CameraControl.detached(
+ binaryMessenger: _binaryMessenger,
+ instanceManager: _instanceManager);
+ },
+ );
+ }
+}
diff --git a/packages/camera/camera_android_camerax/lib/src/camerax_library.g.dart b/packages/camera/camera_android_camerax/lib/src/camerax_library.g.dart
index dda3a81..4fc4d15 100644
--- a/packages/camera/camera_android_camerax/lib/src/camerax_library.g.dart
+++ b/packages/camera/camera_android_camerax/lib/src/camerax_library.g.dart
@@ -780,6 +780,33 @@
return (replyList[0] as int?)!;
}
}
+
+ Future<int> getCameraControl(int arg_identifier) async {
+ final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+ 'dev.flutter.pigeon.CameraHostApi.getCameraControl', codec,
+ binaryMessenger: _binaryMessenger);
+ final List<Object?>? replyList =
+ await channel.send(<Object?>[arg_identifier]) as List<Object?>?;
+ if (replyList == null) {
+ throw PlatformException(
+ code: 'channel-error',
+ message: 'Unable to establish connection on channel.',
+ );
+ } else if (replyList.length > 1) {
+ throw PlatformException(
+ code: replyList[0]! as String,
+ message: replyList[1] as String?,
+ details: replyList[2],
+ );
+ } else if (replyList[0] == null) {
+ throw PlatformException(
+ code: 'null-error',
+ message: 'Host platform returned null value for non-null return value.',
+ );
+ } else {
+ return (replyList[0] as int?)!;
+ }
+ }
}
abstract class CameraFlutterApi {
@@ -2626,3 +2653,65 @@
}
}
}
+
+class CameraControlHostApi {
+ /// Constructor for [CameraControlHostApi]. The [binaryMessenger] named argument is
+ /// available for dependency injection. If it is left null, the default
+ /// BinaryMessenger will be used which routes to the host platform.
+ CameraControlHostApi({BinaryMessenger? binaryMessenger})
+ : _binaryMessenger = binaryMessenger;
+ final BinaryMessenger? _binaryMessenger;
+
+ static const MessageCodec<Object?> codec = StandardMessageCodec();
+
+ Future<void> enableTorch(int arg_identifier, bool arg_torch) async {
+ final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+ 'dev.flutter.pigeon.CameraControlHostApi.enableTorch', codec,
+ binaryMessenger: _binaryMessenger);
+ final List<Object?>? replyList = await channel
+ .send(<Object?>[arg_identifier, arg_torch]) as List<Object?>?;
+ if (replyList == null) {
+ throw PlatformException(
+ code: 'channel-error',
+ message: 'Unable to establish connection on channel.',
+ );
+ } else if (replyList.length > 1) {
+ throw PlatformException(
+ code: replyList[0]! as String,
+ message: replyList[1] as String?,
+ details: replyList[2],
+ );
+ } else {
+ return;
+ }
+ }
+}
+
+abstract class CameraControlFlutterApi {
+ static const MessageCodec<Object?> codec = StandardMessageCodec();
+
+ void create(int identifier);
+
+ static void setup(CameraControlFlutterApi? api,
+ {BinaryMessenger? binaryMessenger}) {
+ {
+ final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+ 'dev.flutter.pigeon.CameraControlFlutterApi.create', codec,
+ binaryMessenger: binaryMessenger);
+ if (api == null) {
+ channel.setMessageHandler(null);
+ } else {
+ channel.setMessageHandler((Object? message) async {
+ assert(message != null,
+ 'Argument for dev.flutter.pigeon.CameraControlFlutterApi.create was null.');
+ final List<Object?> args = (message as List<Object?>?)!;
+ final int? arg_identifier = (args[0] as int?);
+ assert(arg_identifier != null,
+ 'Argument for dev.flutter.pigeon.CameraControlFlutterApi.create was null, expected non-null int.');
+ api.create(arg_identifier!);
+ return;
+ });
+ }
+ }
+ }
+}
diff --git a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart
index 9ebf34b..2c5b9c2 100644
--- a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart
+++ b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart
@@ -197,6 +197,8 @@
@HostApi(dartHostTestHandler: 'TestCameraHostApi')
abstract class CameraHostApi {
int getCameraInfo(int identifier);
+
+ int getCameraControl(int identifier);
}
@FlutterApi()
@@ -417,3 +419,14 @@
void create(int identifier, VideoQuality quality,
VideoResolutionFallbackRule fallbackRule);
}
+
+@HostApi(dartHostTestHandler: 'TestCameraControlHostApi')
+abstract class CameraControlHostApi {
+ @async
+ void enableTorch(int identifier, bool torch);
+}
+
+@FlutterApi()
+abstract class CameraControlFlutterApi {
+ void create(int identifier);
+}
diff --git a/packages/camera/camera_android_camerax/pubspec.yaml b/packages/camera/camera_android_camerax/pubspec.yaml
index 75b3c03..238d94c 100644
--- a/packages/camera/camera_android_camerax/pubspec.yaml
+++ b/packages/camera/camera_android_camerax/pubspec.yaml
@@ -2,7 +2,7 @@
description: Android implementation of the camera plugin using the CameraX library.
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
-version: 0.5.0+18
+version: 0.5.0+19
environment:
sdk: ">=2.19.0 <4.0.0"
diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart
index b90aabd..10c8e5b 100644
--- a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart
+++ b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart
@@ -8,6 +8,7 @@
import 'package:camera_android_camerax/camera_android_camerax.dart';
import 'package:camera_android_camerax/src/analyzer.dart';
import 'package:camera_android_camerax/src/camera.dart';
+import 'package:camera_android_camerax/src/camera_control.dart';
import 'package:camera_android_camerax/src/camera_info.dart';
import 'package:camera_android_camerax/src/camera_selector.dart';
import 'package:camera_android_camerax/src/camera_state.dart';
@@ -46,6 +47,7 @@
@GenerateNiceMocks(<MockSpec<Object>>[
MockSpec<Camera>(),
MockSpec<CameraInfo>(),
+ MockSpec<CameraControl>(),
MockSpec<CameraImageData>(),
MockSpec<CameraSelector>(),
MockSpec<ExposureState>(),
@@ -1025,12 +1027,35 @@
expect(imageFile.path, equals(testPicturePath));
});
- test('setFlashMode configures ImageCapture with expected flash mode',
+ test('takePicture turns non-torch flash mode off when torch mode enabled',
+ () async {
+ final AndroidCameraCameraX camera = AndroidCameraCameraX();
+ const int cameraId = 77;
+ final MockCameraControl mockCameraControl = MockCameraControl();
+
+ camera.imageCapture = MockImageCapture();
+ camera.camera = MockCamera();
+
+ when(camera.camera!.getCameraControl())
+ .thenAnswer((_) async => mockCameraControl);
+
+ await camera.setFlashMode(cameraId, FlashMode.torch);
+ await camera.takePicture(cameraId);
+ verify(camera.imageCapture!.setFlashMode(ImageCapture.flashModeOff));
+ });
+
+ test(
+ 'setFlashMode configures ImageCapture with expected non-torch flash mode',
() async {
final AndroidCameraCameraX camera = AndroidCameraCameraX();
const int cameraId = 22;
+ final MockCameraControl mockCameraControl = MockCameraControl();
camera.imageCapture = MockImageCapture();
+ camera.camera = MockCamera();
+
+ when(camera.camera!.getCameraControl())
+ .thenAnswer((_) async => mockCameraControl);
for (final FlashMode flashMode in FlashMode.values) {
await camera.setFlashMode(cameraId, flashMode);
@@ -1047,19 +1072,68 @@
expectedFlashMode = ImageCapture.flashModeOn;
break;
case FlashMode.torch:
- // TODO(camsim99): Test torch mode when implemented.
+ expectedFlashMode = null;
break;
}
if (expectedFlashMode == null) {
+ // Torch mode enabled and won't be used for configuring image capture.
continue;
}
+ verifyNever(mockCameraControl.enableTorch(true));
+ expect(camera.torchEnabled, isFalse);
await camera.takePicture(cameraId);
verify(camera.imageCapture!.setFlashMode(expectedFlashMode));
}
});
+ test('setFlashMode turns on torch mode as expected', () async {
+ final AndroidCameraCameraX camera = AndroidCameraCameraX();
+ const int cameraId = 44;
+ final MockCameraControl mockCameraControl = MockCameraControl();
+
+ camera.camera = MockCamera();
+
+ when(camera.camera!.getCameraControl())
+ .thenAnswer((_) async => mockCameraControl);
+
+ await camera.setFlashMode(cameraId, FlashMode.torch);
+
+ verify(mockCameraControl.enableTorch(true));
+ expect(camera.torchEnabled, isTrue);
+ });
+
+ test('setFlashMode turns off torch mode when non-torch flash modes set',
+ () async {
+ final AndroidCameraCameraX camera = AndroidCameraCameraX();
+ const int cameraId = 33;
+ final MockCameraControl mockCameraControl = MockCameraControl();
+
+ camera.camera = MockCamera();
+
+ when(camera.camera!.getCameraControl())
+ .thenAnswer((_) async => mockCameraControl);
+
+ for (final FlashMode flashMode in FlashMode.values) {
+ camera.torchEnabled = true;
+ await camera.setFlashMode(cameraId, flashMode);
+
+ switch (flashMode) {
+ case FlashMode.off:
+ case FlashMode.auto:
+ case FlashMode.always:
+ verify(mockCameraControl.enableTorch(false));
+ expect(camera.torchEnabled, isFalse);
+ break;
+ case FlashMode.torch:
+ verifyNever(mockCameraControl.enableTorch(true));
+ expect(camera.torchEnabled, true);
+ break;
+ }
+ }
+ });
+
test('getMinExposureOffset returns expected exposure offset', () async {
final AndroidCameraCameraX camera = AndroidCameraCameraX();
final MockCameraInfo mockCameraInfo = MockCameraInfo();
diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.mocks.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.mocks.dart
index 1d3d636..f275ea7 100644
--- a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.mocks.dart
+++ b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.mocks.dart
@@ -5,39 +5,40 @@
// @dart=2.19
// ignore_for_file: no_leading_underscores_for_library_prefixes
-import 'dart:async' as _i14;
-import 'dart:typed_data' as _i23;
+import 'dart:async' as _i15;
+import 'dart:typed_data' as _i24;
-import 'package:camera_android_camerax/src/analyzer.dart' as _i19;
-import 'package:camera_android_camerax/src/camera.dart' as _i7;
+import 'package:camera_android_camerax/src/analyzer.dart' as _i20;
+import 'package:camera_android_camerax/src/camera.dart' as _i8;
+import 'package:camera_android_camerax/src/camera_control.dart' as _i3;
import 'package:camera_android_camerax/src/camera_info.dart' as _i2;
-import 'package:camera_android_camerax/src/camera_selector.dart' as _i17;
-import 'package:camera_android_camerax/src/camera_state.dart' as _i15;
-import 'package:camera_android_camerax/src/camerax_library.g.dart' as _i6;
-import 'package:camera_android_camerax/src/exposure_state.dart' as _i4;
-import 'package:camera_android_camerax/src/image_analysis.dart' as _i18;
-import 'package:camera_android_camerax/src/image_capture.dart' as _i20;
-import 'package:camera_android_camerax/src/image_proxy.dart' as _i21;
-import 'package:camera_android_camerax/src/live_data.dart' as _i3;
-import 'package:camera_android_camerax/src/observer.dart' as _i29;
-import 'package:camera_android_camerax/src/pending_recording.dart' as _i8;
-import 'package:camera_android_camerax/src/plane_proxy.dart' as _i22;
-import 'package:camera_android_camerax/src/preview.dart' as _i24;
+import 'package:camera_android_camerax/src/camera_selector.dart' as _i18;
+import 'package:camera_android_camerax/src/camera_state.dart' as _i16;
+import 'package:camera_android_camerax/src/camerax_library.g.dart' as _i7;
+import 'package:camera_android_camerax/src/exposure_state.dart' as _i5;
+import 'package:camera_android_camerax/src/image_analysis.dart' as _i19;
+import 'package:camera_android_camerax/src/image_capture.dart' as _i21;
+import 'package:camera_android_camerax/src/image_proxy.dart' as _i22;
+import 'package:camera_android_camerax/src/live_data.dart' as _i4;
+import 'package:camera_android_camerax/src/observer.dart' as _i30;
+import 'package:camera_android_camerax/src/pending_recording.dart' as _i9;
+import 'package:camera_android_camerax/src/plane_proxy.dart' as _i23;
+import 'package:camera_android_camerax/src/preview.dart' as _i25;
import 'package:camera_android_camerax/src/process_camera_provider.dart'
- as _i25;
-import 'package:camera_android_camerax/src/recorder.dart' as _i10;
-import 'package:camera_android_camerax/src/recording.dart' as _i9;
-import 'package:camera_android_camerax/src/use_case.dart' as _i26;
-import 'package:camera_android_camerax/src/video_capture.dart' as _i27;
-import 'package:camera_android_camerax/src/zoom_state.dart' as _i16;
+ as _i26;
+import 'package:camera_android_camerax/src/recorder.dart' as _i11;
+import 'package:camera_android_camerax/src/recording.dart' as _i10;
+import 'package:camera_android_camerax/src/use_case.dart' as _i27;
+import 'package:camera_android_camerax/src/video_capture.dart' as _i28;
+import 'package:camera_android_camerax/src/zoom_state.dart' as _i17;
import 'package:camera_platform_interface/camera_platform_interface.dart'
- as _i5;
-import 'package:flutter/foundation.dart' as _i13;
-import 'package:flutter/services.dart' as _i12;
-import 'package:flutter/widgets.dart' as _i11;
+ as _i6;
+import 'package:flutter/foundation.dart' as _i14;
+import 'package:flutter/services.dart' as _i13;
+import 'package:flutter/widgets.dart' as _i12;
import 'package:mockito/mockito.dart' as _i1;
-import 'test_camerax_library.g.dart' as _i28;
+import 'test_camerax_library.g.dart' as _i29;
// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
@@ -60,9 +61,8 @@
);
}
-class _FakeLiveData_1<T extends Object> extends _i1.SmartFake
- implements _i3.LiveData<T> {
- _FakeLiveData_1(
+class _FakeCameraControl_1 extends _i1.SmartFake implements _i3.CameraControl {
+ _FakeCameraControl_1(
Object parent,
Invocation parentInvocation,
) : super(
@@ -71,8 +71,9 @@
);
}
-class _FakeExposureState_2 extends _i1.SmartFake implements _i4.ExposureState {
- _FakeExposureState_2(
+class _FakeLiveData_2<T extends Object> extends _i1.SmartFake
+ implements _i4.LiveData<T> {
+ _FakeLiveData_2(
Object parent,
Invocation parentInvocation,
) : super(
@@ -81,9 +82,8 @@
);
}
-class _FakeCameraImageFormat_3 extends _i1.SmartFake
- implements _i5.CameraImageFormat {
- _FakeCameraImageFormat_3(
+class _FakeExposureState_3 extends _i1.SmartFake implements _i5.ExposureState {
+ _FakeExposureState_3(
Object parent,
Invocation parentInvocation,
) : super(
@@ -92,9 +92,9 @@
);
}
-class _FakeExposureCompensationRange_4 extends _i1.SmartFake
- implements _i6.ExposureCompensationRange {
- _FakeExposureCompensationRange_4(
+class _FakeCameraImageFormat_4 extends _i1.SmartFake
+ implements _i6.CameraImageFormat {
+ _FakeCameraImageFormat_4(
Object parent,
Invocation parentInvocation,
) : super(
@@ -103,9 +103,9 @@
);
}
-class _FakeResolutionInfo_5 extends _i1.SmartFake
- implements _i6.ResolutionInfo {
- _FakeResolutionInfo_5(
+class _FakeExposureCompensationRange_5 extends _i1.SmartFake
+ implements _i7.ExposureCompensationRange {
+ _FakeExposureCompensationRange_5(
Object parent,
Invocation parentInvocation,
) : super(
@@ -114,8 +114,9 @@
);
}
-class _FakeCamera_6 extends _i1.SmartFake implements _i7.Camera {
- _FakeCamera_6(
+class _FakeResolutionInfo_6 extends _i1.SmartFake
+ implements _i7.ResolutionInfo {
+ _FakeResolutionInfo_6(
Object parent,
Invocation parentInvocation,
) : super(
@@ -124,9 +125,8 @@
);
}
-class _FakePendingRecording_7 extends _i1.SmartFake
- implements _i8.PendingRecording {
- _FakePendingRecording_7(
+class _FakeCamera_7 extends _i1.SmartFake implements _i8.Camera {
+ _FakeCamera_7(
Object parent,
Invocation parentInvocation,
) : super(
@@ -135,8 +135,9 @@
);
}
-class _FakeRecording_8 extends _i1.SmartFake implements _i9.Recording {
- _FakeRecording_8(
+class _FakePendingRecording_8 extends _i1.SmartFake
+ implements _i9.PendingRecording {
+ _FakePendingRecording_8(
Object parent,
Invocation parentInvocation,
) : super(
@@ -145,8 +146,8 @@
);
}
-class _FakeRecorder_9 extends _i1.SmartFake implements _i10.Recorder {
- _FakeRecorder_9(
+class _FakeRecording_9 extends _i1.SmartFake implements _i10.Recording {
+ _FakeRecording_9(
Object parent,
Invocation parentInvocation,
) : super(
@@ -155,8 +156,18 @@
);
}
-class _FakeWidget_10 extends _i1.SmartFake implements _i11.Widget {
- _FakeWidget_10(
+class _FakeRecorder_10 extends _i1.SmartFake implements _i11.Recorder {
+ _FakeRecorder_10(
+ Object parent,
+ Invocation parentInvocation,
+ ) : super(
+ parent,
+ parentInvocation,
+ );
+}
+
+class _FakeWidget_11 extends _i1.SmartFake implements _i12.Widget {
+ _FakeWidget_11(
Object parent,
Invocation parentInvocation,
) : super(
@@ -166,13 +177,13 @@
@override
String toString(
- {_i12.DiagnosticLevel? minLevel = _i12.DiagnosticLevel.info}) =>
+ {_i13.DiagnosticLevel? minLevel = _i13.DiagnosticLevel.info}) =>
super.toString();
}
-class _FakeInheritedWidget_11 extends _i1.SmartFake
- implements _i11.InheritedWidget {
- _FakeInheritedWidget_11(
+class _FakeInheritedWidget_12 extends _i1.SmartFake
+ implements _i12.InheritedWidget {
+ _FakeInheritedWidget_12(
Object parent,
Invocation parentInvocation,
) : super(
@@ -182,13 +193,13 @@
@override
String toString(
- {_i12.DiagnosticLevel? minLevel = _i12.DiagnosticLevel.info}) =>
+ {_i13.DiagnosticLevel? minLevel = _i13.DiagnosticLevel.info}) =>
super.toString();
}
-class _FakeDiagnosticsNode_12 extends _i1.SmartFake
- implements _i13.DiagnosticsNode {
- _FakeDiagnosticsNode_12(
+class _FakeDiagnosticsNode_13 extends _i1.SmartFake
+ implements _i14.DiagnosticsNode {
+ _FakeDiagnosticsNode_13(
Object parent,
Invocation parentInvocation,
) : super(
@@ -198,8 +209,8 @@
@override
String toString({
- _i13.TextTreeConfiguration? parentConfiguration,
- _i12.DiagnosticLevel? minLevel = _i12.DiagnosticLevel.info,
+ _i14.TextTreeConfiguration? parentConfiguration,
+ _i13.DiagnosticLevel? minLevel = _i13.DiagnosticLevel.info,
}) =>
super.toString();
}
@@ -208,14 +219,14 @@
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockCamera extends _i1.Mock implements _i7.Camera {
+class MockCamera extends _i1.Mock implements _i8.Camera {
@override
- _i14.Future<_i2.CameraInfo> getCameraInfo() => (super.noSuchMethod(
+ _i15.Future<_i2.CameraInfo> getCameraInfo() => (super.noSuchMethod(
Invocation.method(
#getCameraInfo,
[],
),
- returnValue: _i14.Future<_i2.CameraInfo>.value(_FakeCameraInfo_0(
+ returnValue: _i15.Future<_i2.CameraInfo>.value(_FakeCameraInfo_0(
this,
Invocation.method(
#getCameraInfo,
@@ -223,14 +234,36 @@
),
)),
returnValueForMissingStub:
- _i14.Future<_i2.CameraInfo>.value(_FakeCameraInfo_0(
+ _i15.Future<_i2.CameraInfo>.value(_FakeCameraInfo_0(
this,
Invocation.method(
#getCameraInfo,
[],
),
)),
- ) as _i14.Future<_i2.CameraInfo>);
+ ) as _i15.Future<_i2.CameraInfo>);
+ @override
+ _i15.Future<_i3.CameraControl> getCameraControl() => (super.noSuchMethod(
+ Invocation.method(
+ #getCameraControl,
+ [],
+ ),
+ returnValue: _i15.Future<_i3.CameraControl>.value(_FakeCameraControl_1(
+ this,
+ Invocation.method(
+ #getCameraControl,
+ [],
+ ),
+ )),
+ returnValueForMissingStub:
+ _i15.Future<_i3.CameraControl>.value(_FakeCameraControl_1(
+ this,
+ Invocation.method(
+ #getCameraControl,
+ [],
+ ),
+ )),
+ ) as _i15.Future<_i3.CameraControl>);
}
/// A class which mocks [CameraInfo].
@@ -239,23 +272,23 @@
// ignore: must_be_immutable
class MockCameraInfo extends _i1.Mock implements _i2.CameraInfo {
@override
- _i14.Future<int> getSensorRotationDegrees() => (super.noSuchMethod(
+ _i15.Future<int> getSensorRotationDegrees() => (super.noSuchMethod(
Invocation.method(
#getSensorRotationDegrees,
[],
),
- returnValue: _i14.Future<int>.value(0),
- returnValueForMissingStub: _i14.Future<int>.value(0),
- ) as _i14.Future<int>);
+ returnValue: _i15.Future<int>.value(0),
+ returnValueForMissingStub: _i15.Future<int>.value(0),
+ ) as _i15.Future<int>);
@override
- _i14.Future<_i3.LiveData<_i15.CameraState>> getCameraState() =>
+ _i15.Future<_i4.LiveData<_i16.CameraState>> getCameraState() =>
(super.noSuchMethod(
Invocation.method(
#getCameraState,
[],
),
- returnValue: _i14.Future<_i3.LiveData<_i15.CameraState>>.value(
- _FakeLiveData_1<_i15.CameraState>(
+ returnValue: _i15.Future<_i4.LiveData<_i16.CameraState>>.value(
+ _FakeLiveData_2<_i16.CameraState>(
this,
Invocation.method(
#getCameraState,
@@ -263,22 +296,22 @@
),
)),
returnValueForMissingStub:
- _i14.Future<_i3.LiveData<_i15.CameraState>>.value(
- _FakeLiveData_1<_i15.CameraState>(
+ _i15.Future<_i4.LiveData<_i16.CameraState>>.value(
+ _FakeLiveData_2<_i16.CameraState>(
this,
Invocation.method(
#getCameraState,
[],
),
)),
- ) as _i14.Future<_i3.LiveData<_i15.CameraState>>);
+ ) as _i15.Future<_i4.LiveData<_i16.CameraState>>);
@override
- _i14.Future<_i4.ExposureState> getExposureState() => (super.noSuchMethod(
+ _i15.Future<_i5.ExposureState> getExposureState() => (super.noSuchMethod(
Invocation.method(
#getExposureState,
[],
),
- returnValue: _i14.Future<_i4.ExposureState>.value(_FakeExposureState_2(
+ returnValue: _i15.Future<_i5.ExposureState>.value(_FakeExposureState_3(
this,
Invocation.method(
#getExposureState,
@@ -286,23 +319,23 @@
),
)),
returnValueForMissingStub:
- _i14.Future<_i4.ExposureState>.value(_FakeExposureState_2(
+ _i15.Future<_i5.ExposureState>.value(_FakeExposureState_3(
this,
Invocation.method(
#getExposureState,
[],
),
)),
- ) as _i14.Future<_i4.ExposureState>);
+ ) as _i15.Future<_i5.ExposureState>);
@override
- _i14.Future<_i3.LiveData<_i16.ZoomState>> getZoomState() =>
+ _i15.Future<_i4.LiveData<_i17.ZoomState>> getZoomState() =>
(super.noSuchMethod(
Invocation.method(
#getZoomState,
[],
),
- returnValue: _i14.Future<_i3.LiveData<_i16.ZoomState>>.value(
- _FakeLiveData_1<_i16.ZoomState>(
+ returnValue: _i15.Future<_i4.LiveData<_i17.ZoomState>>.value(
+ _FakeLiveData_2<_i17.ZoomState>(
this,
Invocation.method(
#getZoomState,
@@ -310,34 +343,50 @@
),
)),
returnValueForMissingStub:
- _i14.Future<_i3.LiveData<_i16.ZoomState>>.value(
- _FakeLiveData_1<_i16.ZoomState>(
+ _i15.Future<_i4.LiveData<_i17.ZoomState>>.value(
+ _FakeLiveData_2<_i17.ZoomState>(
this,
Invocation.method(
#getZoomState,
[],
),
)),
- ) as _i14.Future<_i3.LiveData<_i16.ZoomState>>);
+ ) as _i15.Future<_i4.LiveData<_i17.ZoomState>>);
+}
+
+/// A class which mocks [CameraControl].
+///
+/// See the documentation for Mockito's code generation for more information.
+// ignore: must_be_immutable
+class MockCameraControl extends _i1.Mock implements _i3.CameraControl {
+ @override
+ _i15.Future<void> enableTorch(bool? torch) => (super.noSuchMethod(
+ Invocation.method(
+ #enableTorch,
+ [torch],
+ ),
+ returnValue: _i15.Future<void>.value(),
+ returnValueForMissingStub: _i15.Future<void>.value(),
+ ) as _i15.Future<void>);
}
/// A class which mocks [CameraImageData].
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockCameraImageData extends _i1.Mock implements _i5.CameraImageData {
+class MockCameraImageData extends _i1.Mock implements _i6.CameraImageData {
@override
- _i5.CameraImageFormat get format => (super.noSuchMethod(
+ _i6.CameraImageFormat get format => (super.noSuchMethod(
Invocation.getter(#format),
- returnValue: _FakeCameraImageFormat_3(
+ returnValue: _FakeCameraImageFormat_4(
this,
Invocation.getter(#format),
),
- returnValueForMissingStub: _FakeCameraImageFormat_3(
+ returnValueForMissingStub: _FakeCameraImageFormat_4(
this,
Invocation.getter(#format),
),
- ) as _i5.CameraImageFormat);
+ ) as _i6.CameraImageFormat);
@override
int get height => (super.noSuchMethod(
Invocation.getter(#height),
@@ -351,50 +400,50 @@
returnValueForMissingStub: 0,
) as int);
@override
- List<_i5.CameraImagePlane> get planes => (super.noSuchMethod(
+ List<_i6.CameraImagePlane> get planes => (super.noSuchMethod(
Invocation.getter(#planes),
- returnValue: <_i5.CameraImagePlane>[],
- returnValueForMissingStub: <_i5.CameraImagePlane>[],
- ) as List<_i5.CameraImagePlane>);
+ returnValue: <_i6.CameraImagePlane>[],
+ returnValueForMissingStub: <_i6.CameraImagePlane>[],
+ ) as List<_i6.CameraImagePlane>);
}
/// A class which mocks [CameraSelector].
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockCameraSelector extends _i1.Mock implements _i17.CameraSelector {
+class MockCameraSelector extends _i1.Mock implements _i18.CameraSelector {
@override
- _i14.Future<List<_i2.CameraInfo>> filter(List<_i2.CameraInfo>? cameraInfos) =>
+ _i15.Future<List<_i2.CameraInfo>> filter(List<_i2.CameraInfo>? cameraInfos) =>
(super.noSuchMethod(
Invocation.method(
#filter,
[cameraInfos],
),
returnValue:
- _i14.Future<List<_i2.CameraInfo>>.value(<_i2.CameraInfo>[]),
+ _i15.Future<List<_i2.CameraInfo>>.value(<_i2.CameraInfo>[]),
returnValueForMissingStub:
- _i14.Future<List<_i2.CameraInfo>>.value(<_i2.CameraInfo>[]),
- ) as _i14.Future<List<_i2.CameraInfo>>);
+ _i15.Future<List<_i2.CameraInfo>>.value(<_i2.CameraInfo>[]),
+ ) as _i15.Future<List<_i2.CameraInfo>>);
}
/// A class which mocks [ExposureState].
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockExposureState extends _i1.Mock implements _i4.ExposureState {
+class MockExposureState extends _i1.Mock implements _i5.ExposureState {
@override
- _i6.ExposureCompensationRange get exposureCompensationRange =>
+ _i7.ExposureCompensationRange get exposureCompensationRange =>
(super.noSuchMethod(
Invocation.getter(#exposureCompensationRange),
- returnValue: _FakeExposureCompensationRange_4(
+ returnValue: _FakeExposureCompensationRange_5(
this,
Invocation.getter(#exposureCompensationRange),
),
- returnValueForMissingStub: _FakeExposureCompensationRange_4(
+ returnValueForMissingStub: _FakeExposureCompensationRange_5(
this,
Invocation.getter(#exposureCompensationRange),
),
- ) as _i6.ExposureCompensationRange);
+ ) as _i7.ExposureCompensationRange);
@override
double get exposureCompensationStep => (super.noSuchMethod(
Invocation.getter(#exposureCompensationStep),
@@ -407,57 +456,57 @@
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockImageAnalysis extends _i1.Mock implements _i18.ImageAnalysis {
+class MockImageAnalysis extends _i1.Mock implements _i19.ImageAnalysis {
@override
- _i14.Future<void> setAnalyzer(_i19.Analyzer? analyzer) => (super.noSuchMethod(
+ _i15.Future<void> setAnalyzer(_i20.Analyzer? analyzer) => (super.noSuchMethod(
Invocation.method(
#setAnalyzer,
[analyzer],
),
- returnValue: _i14.Future<void>.value(),
- returnValueForMissingStub: _i14.Future<void>.value(),
- ) as _i14.Future<void>);
+ returnValue: _i15.Future<void>.value(),
+ returnValueForMissingStub: _i15.Future<void>.value(),
+ ) as _i15.Future<void>);
@override
- _i14.Future<void> clearAnalyzer() => (super.noSuchMethod(
+ _i15.Future<void> clearAnalyzer() => (super.noSuchMethod(
Invocation.method(
#clearAnalyzer,
[],
),
- returnValue: _i14.Future<void>.value(),
- returnValueForMissingStub: _i14.Future<void>.value(),
- ) as _i14.Future<void>);
+ returnValue: _i15.Future<void>.value(),
+ returnValueForMissingStub: _i15.Future<void>.value(),
+ ) as _i15.Future<void>);
}
/// A class which mocks [ImageCapture].
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockImageCapture extends _i1.Mock implements _i20.ImageCapture {
+class MockImageCapture extends _i1.Mock implements _i21.ImageCapture {
@override
- _i14.Future<void> setFlashMode(int? newFlashMode) => (super.noSuchMethod(
+ _i15.Future<void> setFlashMode(int? newFlashMode) => (super.noSuchMethod(
Invocation.method(
#setFlashMode,
[newFlashMode],
),
- returnValue: _i14.Future<void>.value(),
- returnValueForMissingStub: _i14.Future<void>.value(),
- ) as _i14.Future<void>);
+ returnValue: _i15.Future<void>.value(),
+ returnValueForMissingStub: _i15.Future<void>.value(),
+ ) as _i15.Future<void>);
@override
- _i14.Future<String> takePicture() => (super.noSuchMethod(
+ _i15.Future<String> takePicture() => (super.noSuchMethod(
Invocation.method(
#takePicture,
[],
),
- returnValue: _i14.Future<String>.value(''),
- returnValueForMissingStub: _i14.Future<String>.value(''),
- ) as _i14.Future<String>);
+ returnValue: _i15.Future<String>.value(''),
+ returnValueForMissingStub: _i15.Future<String>.value(''),
+ ) as _i15.Future<String>);
}
/// A class which mocks [ImageProxy].
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockImageProxy extends _i1.Mock implements _i21.ImageProxy {
+class MockImageProxy extends _i1.Mock implements _i22.ImageProxy {
@override
int get format => (super.noSuchMethod(
Invocation.getter(#format),
@@ -477,38 +526,38 @@
returnValueForMissingStub: 0,
) as int);
@override
- _i14.Future<List<_i22.PlaneProxy>> getPlanes() => (super.noSuchMethod(
+ _i15.Future<List<_i23.PlaneProxy>> getPlanes() => (super.noSuchMethod(
Invocation.method(
#getPlanes,
[],
),
returnValue:
- _i14.Future<List<_i22.PlaneProxy>>.value(<_i22.PlaneProxy>[]),
+ _i15.Future<List<_i23.PlaneProxy>>.value(<_i23.PlaneProxy>[]),
returnValueForMissingStub:
- _i14.Future<List<_i22.PlaneProxy>>.value(<_i22.PlaneProxy>[]),
- ) as _i14.Future<List<_i22.PlaneProxy>>);
+ _i15.Future<List<_i23.PlaneProxy>>.value(<_i23.PlaneProxy>[]),
+ ) as _i15.Future<List<_i23.PlaneProxy>>);
@override
- _i14.Future<void> close() => (super.noSuchMethod(
+ _i15.Future<void> close() => (super.noSuchMethod(
Invocation.method(
#close,
[],
),
- returnValue: _i14.Future<void>.value(),
- returnValueForMissingStub: _i14.Future<void>.value(),
- ) as _i14.Future<void>);
+ returnValue: _i15.Future<void>.value(),
+ returnValueForMissingStub: _i15.Future<void>.value(),
+ ) as _i15.Future<void>);
}
/// A class which mocks [PlaneProxy].
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockPlaneProxy extends _i1.Mock implements _i22.PlaneProxy {
+class MockPlaneProxy extends _i1.Mock implements _i23.PlaneProxy {
@override
- _i23.Uint8List get buffer => (super.noSuchMethod(
+ _i24.Uint8List get buffer => (super.noSuchMethod(
Invocation.getter(#buffer),
- returnValue: _i23.Uint8List(0),
- returnValueForMissingStub: _i23.Uint8List(0),
- ) as _i23.Uint8List);
+ returnValue: _i24.Uint8List(0),
+ returnValueForMissingStub: _i24.Uint8List(0),
+ ) as _i24.Uint8List);
@override
int get pixelStride => (super.noSuchMethod(
Invocation.getter(#pixelStride),
@@ -527,16 +576,16 @@
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockPreview extends _i1.Mock implements _i24.Preview {
+class MockPreview extends _i1.Mock implements _i25.Preview {
@override
- _i14.Future<int> setSurfaceProvider() => (super.noSuchMethod(
+ _i15.Future<int> setSurfaceProvider() => (super.noSuchMethod(
Invocation.method(
#setSurfaceProvider,
[],
),
- returnValue: _i14.Future<int>.value(0),
- returnValueForMissingStub: _i14.Future<int>.value(0),
- ) as _i14.Future<int>);
+ returnValue: _i15.Future<int>.value(0),
+ returnValueForMissingStub: _i15.Future<int>.value(0),
+ ) as _i15.Future<int>);
@override
void releaseFlutterSurfaceTexture() => super.noSuchMethod(
Invocation.method(
@@ -546,13 +595,13 @@
returnValueForMissingStub: null,
);
@override
- _i14.Future<_i6.ResolutionInfo> getResolutionInfo() => (super.noSuchMethod(
+ _i15.Future<_i7.ResolutionInfo> getResolutionInfo() => (super.noSuchMethod(
Invocation.method(
#getResolutionInfo,
[],
),
returnValue:
- _i14.Future<_i6.ResolutionInfo>.value(_FakeResolutionInfo_5(
+ _i15.Future<_i7.ResolutionInfo>.value(_FakeResolutionInfo_6(
this,
Invocation.method(
#getResolutionInfo,
@@ -560,14 +609,14 @@
),
)),
returnValueForMissingStub:
- _i14.Future<_i6.ResolutionInfo>.value(_FakeResolutionInfo_5(
+ _i15.Future<_i7.ResolutionInfo>.value(_FakeResolutionInfo_6(
this,
Invocation.method(
#getResolutionInfo,
[],
),
)),
- ) as _i14.Future<_i6.ResolutionInfo>);
+ ) as _i15.Future<_i7.ResolutionInfo>);
}
/// A class which mocks [ProcessCameraProvider].
@@ -575,23 +624,23 @@
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
class MockProcessCameraProvider extends _i1.Mock
- implements _i25.ProcessCameraProvider {
+ implements _i26.ProcessCameraProvider {
@override
- _i14.Future<List<_i2.CameraInfo>> getAvailableCameraInfos() =>
+ _i15.Future<List<_i2.CameraInfo>> getAvailableCameraInfos() =>
(super.noSuchMethod(
Invocation.method(
#getAvailableCameraInfos,
[],
),
returnValue:
- _i14.Future<List<_i2.CameraInfo>>.value(<_i2.CameraInfo>[]),
+ _i15.Future<List<_i2.CameraInfo>>.value(<_i2.CameraInfo>[]),
returnValueForMissingStub:
- _i14.Future<List<_i2.CameraInfo>>.value(<_i2.CameraInfo>[]),
- ) as _i14.Future<List<_i2.CameraInfo>>);
+ _i15.Future<List<_i2.CameraInfo>>.value(<_i2.CameraInfo>[]),
+ ) as _i15.Future<List<_i2.CameraInfo>>);
@override
- _i14.Future<_i7.Camera> bindToLifecycle(
- _i17.CameraSelector? cameraSelector,
- List<_i26.UseCase>? useCases,
+ _i15.Future<_i8.Camera> bindToLifecycle(
+ _i18.CameraSelector? cameraSelector,
+ List<_i27.UseCase>? useCases,
) =>
(super.noSuchMethod(
Invocation.method(
@@ -601,7 +650,7 @@
useCases,
],
),
- returnValue: _i14.Future<_i7.Camera>.value(_FakeCamera_6(
+ returnValue: _i15.Future<_i8.Camera>.value(_FakeCamera_7(
this,
Invocation.method(
#bindToLifecycle,
@@ -611,7 +660,7 @@
],
),
)),
- returnValueForMissingStub: _i14.Future<_i7.Camera>.value(_FakeCamera_6(
+ returnValueForMissingStub: _i15.Future<_i8.Camera>.value(_FakeCamera_7(
this,
Invocation.method(
#bindToLifecycle,
@@ -621,18 +670,18 @@
],
),
)),
- ) as _i14.Future<_i7.Camera>);
+ ) as _i15.Future<_i8.Camera>);
@override
- _i14.Future<bool> isBound(_i26.UseCase? useCase) => (super.noSuchMethod(
+ _i15.Future<bool> isBound(_i27.UseCase? useCase) => (super.noSuchMethod(
Invocation.method(
#isBound,
[useCase],
),
- returnValue: _i14.Future<bool>.value(false),
- returnValueForMissingStub: _i14.Future<bool>.value(false),
- ) as _i14.Future<bool>);
+ returnValue: _i15.Future<bool>.value(false),
+ returnValueForMissingStub: _i15.Future<bool>.value(false),
+ ) as _i15.Future<bool>);
@override
- void unbind(List<_i26.UseCase>? useCases) => super.noSuchMethod(
+ void unbind(List<_i27.UseCase>? useCases) => super.noSuchMethod(
Invocation.method(
#unbind,
[useCases],
@@ -653,16 +702,16 @@
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockRecorder extends _i1.Mock implements _i10.Recorder {
+class MockRecorder extends _i1.Mock implements _i11.Recorder {
@override
- _i14.Future<_i8.PendingRecording> prepareRecording(String? path) =>
+ _i15.Future<_i9.PendingRecording> prepareRecording(String? path) =>
(super.noSuchMethod(
Invocation.method(
#prepareRecording,
[path],
),
returnValue:
- _i14.Future<_i8.PendingRecording>.value(_FakePendingRecording_7(
+ _i15.Future<_i9.PendingRecording>.value(_FakePendingRecording_8(
this,
Invocation.method(
#prepareRecording,
@@ -670,28 +719,28 @@
),
)),
returnValueForMissingStub:
- _i14.Future<_i8.PendingRecording>.value(_FakePendingRecording_7(
+ _i15.Future<_i9.PendingRecording>.value(_FakePendingRecording_8(
this,
Invocation.method(
#prepareRecording,
[path],
),
)),
- ) as _i14.Future<_i8.PendingRecording>);
+ ) as _i15.Future<_i9.PendingRecording>);
}
/// A class which mocks [PendingRecording].
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockPendingRecording extends _i1.Mock implements _i8.PendingRecording {
+class MockPendingRecording extends _i1.Mock implements _i9.PendingRecording {
@override
- _i14.Future<_i9.Recording> start() => (super.noSuchMethod(
+ _i15.Future<_i10.Recording> start() => (super.noSuchMethod(
Invocation.method(
#start,
[],
),
- returnValue: _i14.Future<_i9.Recording>.value(_FakeRecording_8(
+ returnValue: _i15.Future<_i10.Recording>.value(_FakeRecording_9(
this,
Invocation.method(
#start,
@@ -699,71 +748,71 @@
),
)),
returnValueForMissingStub:
- _i14.Future<_i9.Recording>.value(_FakeRecording_8(
+ _i15.Future<_i10.Recording>.value(_FakeRecording_9(
this,
Invocation.method(
#start,
[],
),
)),
- ) as _i14.Future<_i9.Recording>);
+ ) as _i15.Future<_i10.Recording>);
}
/// A class which mocks [Recording].
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockRecording extends _i1.Mock implements _i9.Recording {
+class MockRecording extends _i1.Mock implements _i10.Recording {
@override
- _i14.Future<void> close() => (super.noSuchMethod(
+ _i15.Future<void> close() => (super.noSuchMethod(
Invocation.method(
#close,
[],
),
- returnValue: _i14.Future<void>.value(),
- returnValueForMissingStub: _i14.Future<void>.value(),
- ) as _i14.Future<void>);
+ returnValue: _i15.Future<void>.value(),
+ returnValueForMissingStub: _i15.Future<void>.value(),
+ ) as _i15.Future<void>);
@override
- _i14.Future<void> pause() => (super.noSuchMethod(
+ _i15.Future<void> pause() => (super.noSuchMethod(
Invocation.method(
#pause,
[],
),
- returnValue: _i14.Future<void>.value(),
- returnValueForMissingStub: _i14.Future<void>.value(),
- ) as _i14.Future<void>);
+ returnValue: _i15.Future<void>.value(),
+ returnValueForMissingStub: _i15.Future<void>.value(),
+ ) as _i15.Future<void>);
@override
- _i14.Future<void> resume() => (super.noSuchMethod(
+ _i15.Future<void> resume() => (super.noSuchMethod(
Invocation.method(
#resume,
[],
),
- returnValue: _i14.Future<void>.value(),
- returnValueForMissingStub: _i14.Future<void>.value(),
- ) as _i14.Future<void>);
+ returnValue: _i15.Future<void>.value(),
+ returnValueForMissingStub: _i15.Future<void>.value(),
+ ) as _i15.Future<void>);
@override
- _i14.Future<void> stop() => (super.noSuchMethod(
+ _i15.Future<void> stop() => (super.noSuchMethod(
Invocation.method(
#stop,
[],
),
- returnValue: _i14.Future<void>.value(),
- returnValueForMissingStub: _i14.Future<void>.value(),
- ) as _i14.Future<void>);
+ returnValue: _i15.Future<void>.value(),
+ returnValueForMissingStub: _i15.Future<void>.value(),
+ ) as _i15.Future<void>);
}
/// A class which mocks [VideoCapture].
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockVideoCapture extends _i1.Mock implements _i27.VideoCapture {
+class MockVideoCapture extends _i1.Mock implements _i28.VideoCapture {
@override
- _i14.Future<_i10.Recorder> getOutput() => (super.noSuchMethod(
+ _i15.Future<_i11.Recorder> getOutput() => (super.noSuchMethod(
Invocation.method(
#getOutput,
[],
),
- returnValue: _i14.Future<_i10.Recorder>.value(_FakeRecorder_9(
+ returnValue: _i15.Future<_i11.Recorder>.value(_FakeRecorder_10(
this,
Invocation.method(
#getOutput,
@@ -771,32 +820,32 @@
),
)),
returnValueForMissingStub:
- _i14.Future<_i10.Recorder>.value(_FakeRecorder_9(
+ _i15.Future<_i11.Recorder>.value(_FakeRecorder_10(
this,
Invocation.method(
#getOutput,
[],
),
)),
- ) as _i14.Future<_i10.Recorder>);
+ ) as _i15.Future<_i11.Recorder>);
}
/// A class which mocks [BuildContext].
///
/// See the documentation for Mockito's code generation for more information.
-class MockBuildContext extends _i1.Mock implements _i11.BuildContext {
+class MockBuildContext extends _i1.Mock implements _i12.BuildContext {
@override
- _i11.Widget get widget => (super.noSuchMethod(
+ _i12.Widget get widget => (super.noSuchMethod(
Invocation.getter(#widget),
- returnValue: _FakeWidget_10(
+ returnValue: _FakeWidget_11(
this,
Invocation.getter(#widget),
),
- returnValueForMissingStub: _FakeWidget_10(
+ returnValueForMissingStub: _FakeWidget_11(
this,
Invocation.getter(#widget),
),
- ) as _i11.Widget);
+ ) as _i12.Widget);
@override
bool get mounted => (super.noSuchMethod(
Invocation.getter(#mounted),
@@ -810,8 +859,8 @@
returnValueForMissingStub: false,
) as bool);
@override
- _i11.InheritedWidget dependOnInheritedElement(
- _i11.InheritedElement? ancestor, {
+ _i12.InheritedWidget dependOnInheritedElement(
+ _i12.InheritedElement? ancestor, {
Object? aspect,
}) =>
(super.noSuchMethod(
@@ -820,7 +869,7 @@
[ancestor],
{#aspect: aspect},
),
- returnValue: _FakeInheritedWidget_11(
+ returnValue: _FakeInheritedWidget_12(
this,
Invocation.method(
#dependOnInheritedElement,
@@ -828,7 +877,7 @@
{#aspect: aspect},
),
),
- returnValueForMissingStub: _FakeInheritedWidget_11(
+ returnValueForMissingStub: _FakeInheritedWidget_12(
this,
Invocation.method(
#dependOnInheritedElement,
@@ -836,9 +885,9 @@
{#aspect: aspect},
),
),
- ) as _i11.InheritedWidget);
+ ) as _i12.InheritedWidget);
@override
- void visitAncestorElements(_i11.ConditionalElementVisitor? visitor) =>
+ void visitAncestorElements(_i12.ConditionalElementVisitor? visitor) =>
super.noSuchMethod(
Invocation.method(
#visitAncestorElements,
@@ -847,7 +896,7 @@
returnValueForMissingStub: null,
);
@override
- void visitChildElements(_i11.ElementVisitor? visitor) => super.noSuchMethod(
+ void visitChildElements(_i12.ElementVisitor? visitor) => super.noSuchMethod(
Invocation.method(
#visitChildElements,
[visitor],
@@ -855,7 +904,7 @@
returnValueForMissingStub: null,
);
@override
- void dispatchNotification(_i11.Notification? notification) =>
+ void dispatchNotification(_i12.Notification? notification) =>
super.noSuchMethod(
Invocation.method(
#dispatchNotification,
@@ -864,9 +913,9 @@
returnValueForMissingStub: null,
);
@override
- _i13.DiagnosticsNode describeElement(
+ _i14.DiagnosticsNode describeElement(
String? name, {
- _i13.DiagnosticsTreeStyle? style = _i13.DiagnosticsTreeStyle.errorProperty,
+ _i14.DiagnosticsTreeStyle? style = _i14.DiagnosticsTreeStyle.errorProperty,
}) =>
(super.noSuchMethod(
Invocation.method(
@@ -874,7 +923,7 @@
[name],
{#style: style},
),
- returnValue: _FakeDiagnosticsNode_12(
+ returnValue: _FakeDiagnosticsNode_13(
this,
Invocation.method(
#describeElement,
@@ -882,7 +931,7 @@
{#style: style},
),
),
- returnValueForMissingStub: _FakeDiagnosticsNode_12(
+ returnValueForMissingStub: _FakeDiagnosticsNode_13(
this,
Invocation.method(
#describeElement,
@@ -890,11 +939,11 @@
{#style: style},
),
),
- ) as _i13.DiagnosticsNode);
+ ) as _i14.DiagnosticsNode);
@override
- _i13.DiagnosticsNode describeWidget(
+ _i14.DiagnosticsNode describeWidget(
String? name, {
- _i13.DiagnosticsTreeStyle? style = _i13.DiagnosticsTreeStyle.errorProperty,
+ _i14.DiagnosticsTreeStyle? style = _i14.DiagnosticsTreeStyle.errorProperty,
}) =>
(super.noSuchMethod(
Invocation.method(
@@ -902,7 +951,7 @@
[name],
{#style: style},
),
- returnValue: _FakeDiagnosticsNode_12(
+ returnValue: _FakeDiagnosticsNode_13(
this,
Invocation.method(
#describeWidget,
@@ -910,7 +959,7 @@
{#style: style},
),
),
- returnValueForMissingStub: _FakeDiagnosticsNode_12(
+ returnValueForMissingStub: _FakeDiagnosticsNode_13(
this,
Invocation.method(
#describeWidget,
@@ -918,9 +967,9 @@
{#style: style},
),
),
- ) as _i13.DiagnosticsNode);
+ ) as _i14.DiagnosticsNode);
@override
- List<_i13.DiagnosticsNode> describeMissingAncestor(
+ List<_i14.DiagnosticsNode> describeMissingAncestor(
{required Type? expectedAncestorType}) =>
(super.noSuchMethod(
Invocation.method(
@@ -928,38 +977,38 @@
[],
{#expectedAncestorType: expectedAncestorType},
),
- returnValue: <_i13.DiagnosticsNode>[],
- returnValueForMissingStub: <_i13.DiagnosticsNode>[],
- ) as List<_i13.DiagnosticsNode>);
+ returnValue: <_i14.DiagnosticsNode>[],
+ returnValueForMissingStub: <_i14.DiagnosticsNode>[],
+ ) as List<_i14.DiagnosticsNode>);
@override
- _i13.DiagnosticsNode describeOwnershipChain(String? name) =>
+ _i14.DiagnosticsNode describeOwnershipChain(String? name) =>
(super.noSuchMethod(
Invocation.method(
#describeOwnershipChain,
[name],
),
- returnValue: _FakeDiagnosticsNode_12(
+ returnValue: _FakeDiagnosticsNode_13(
this,
Invocation.method(
#describeOwnershipChain,
[name],
),
),
- returnValueForMissingStub: _FakeDiagnosticsNode_12(
+ returnValueForMissingStub: _FakeDiagnosticsNode_13(
this,
Invocation.method(
#describeOwnershipChain,
[name],
),
),
- ) as _i13.DiagnosticsNode);
+ ) as _i14.DiagnosticsNode);
}
/// A class which mocks [TestInstanceManagerHostApi].
///
/// See the documentation for Mockito's code generation for more information.
class MockTestInstanceManagerHostApi extends _i1.Mock
- implements _i28.TestInstanceManagerHostApi {
+ implements _i29.TestInstanceManagerHostApi {
@override
void clear() => super.noSuchMethod(
Invocation.method(
@@ -974,19 +1023,19 @@
///
/// See the documentation for Mockito's code generation for more information.
class MockTestSystemServicesHostApi extends _i1.Mock
- implements _i28.TestSystemServicesHostApi {
+ implements _i29.TestSystemServicesHostApi {
@override
- _i14.Future<_i6.CameraPermissionsErrorData?> requestCameraPermissions(
+ _i15.Future<_i7.CameraPermissionsErrorData?> requestCameraPermissions(
bool? enableAudio) =>
(super.noSuchMethod(
Invocation.method(
#requestCameraPermissions,
[enableAudio],
),
- returnValue: _i14.Future<_i6.CameraPermissionsErrorData?>.value(),
+ returnValue: _i15.Future<_i7.CameraPermissionsErrorData?>.value(),
returnValueForMissingStub:
- _i14.Future<_i6.CameraPermissionsErrorData?>.value(),
- ) as _i14.Future<_i6.CameraPermissionsErrorData?>);
+ _i15.Future<_i7.CameraPermissionsErrorData?>.value(),
+ ) as _i15.Future<_i7.CameraPermissionsErrorData?>);
@override
void startListeningForDeviceOrientationChange(
bool? isFrontFacing,
@@ -1032,7 +1081,7 @@
///
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
-class MockZoomState extends _i1.Mock implements _i16.ZoomState {
+class MockZoomState extends _i1.Mock implements _i17.ZoomState {
@override
double get minZoomRatio => (super.noSuchMethod(
Invocation.getter(#minZoomRatio),
@@ -1052,30 +1101,30 @@
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
class MockLiveCameraState extends _i1.Mock
- implements _i3.LiveData<_i15.CameraState> {
+ implements _i4.LiveData<_i16.CameraState> {
MockLiveCameraState() {
_i1.throwOnMissingStub(this);
}
@override
- _i14.Future<void> observe(_i29.Observer<_i15.CameraState>? observer) =>
+ _i15.Future<void> observe(_i30.Observer<_i16.CameraState>? observer) =>
(super.noSuchMethod(
Invocation.method(
#observe,
[observer],
),
- returnValue: _i14.Future<void>.value(),
- returnValueForMissingStub: _i14.Future<void>.value(),
- ) as _i14.Future<void>);
+ returnValue: _i15.Future<void>.value(),
+ returnValueForMissingStub: _i15.Future<void>.value(),
+ ) as _i15.Future<void>);
@override
- _i14.Future<void> removeObservers() => (super.noSuchMethod(
+ _i15.Future<void> removeObservers() => (super.noSuchMethod(
Invocation.method(
#removeObservers,
[],
),
- returnValue: _i14.Future<void>.value(),
- returnValueForMissingStub: _i14.Future<void>.value(),
- ) as _i14.Future<void>);
+ returnValue: _i15.Future<void>.value(),
+ returnValueForMissingStub: _i15.Future<void>.value(),
+ ) as _i15.Future<void>);
}
/// A class which mocks [LiveData].
@@ -1083,28 +1132,28 @@
/// See the documentation for Mockito's code generation for more information.
// ignore: must_be_immutable
class MockLiveZoomState extends _i1.Mock
- implements _i3.LiveData<_i16.ZoomState> {
+ implements _i4.LiveData<_i17.ZoomState> {
MockLiveZoomState() {
_i1.throwOnMissingStub(this);
}
@override
- _i14.Future<void> observe(_i29.Observer<_i16.ZoomState>? observer) =>
+ _i15.Future<void> observe(_i30.Observer<_i17.ZoomState>? observer) =>
(super.noSuchMethod(
Invocation.method(
#observe,
[observer],
),
- returnValue: _i14.Future<void>.value(),
- returnValueForMissingStub: _i14.Future<void>.value(),
- ) as _i14.Future<void>);
+ returnValue: _i15.Future<void>.value(),
+ returnValueForMissingStub: _i15.Future<void>.value(),
+ ) as _i15.Future<void>);
@override
- _i14.Future<void> removeObservers() => (super.noSuchMethod(
+ _i15.Future<void> removeObservers() => (super.noSuchMethod(
Invocation.method(
#removeObservers,
[],
),
- returnValue: _i14.Future<void>.value(),
- returnValueForMissingStub: _i14.Future<void>.value(),
- ) as _i14.Future<void>);
+ returnValue: _i15.Future<void>.value(),
+ returnValueForMissingStub: _i15.Future<void>.value(),
+ ) as _i15.Future<void>);
}
diff --git a/packages/camera/camera_android_camerax/test/camera_control_test.dart b/packages/camera/camera_android_camerax/test/camera_control_test.dart
new file mode 100644
index 0000000..99acc94
--- /dev/null
+++ b/packages/camera/camera_android_camerax/test/camera_control_test.dart
@@ -0,0 +1,67 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:camera_android_camerax/src/camera_control.dart';
+import 'package:camera_android_camerax/src/instance_manager.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:mockito/annotations.dart';
+import 'package:mockito/mockito.dart';
+
+import 'camera_control_test.mocks.dart';
+import 'test_camerax_library.g.dart';
+
+@GenerateMocks(<Type>[TestCameraControlHostApi, TestInstanceManagerHostApi])
+void main() {
+ TestWidgetsFlutterBinding.ensureInitialized();
+
+ // Mocks the call to clear the native InstanceManager.
+ TestInstanceManagerHostApi.setup(MockTestInstanceManagerHostApi());
+
+ group('CameraControl', () {
+ tearDown(() => TestCameraHostApi.setup(null));
+
+ test('enableTorch makes call on Java side to enable torch', () async {
+ final MockTestCameraControlHostApi mockApi =
+ MockTestCameraControlHostApi();
+ TestCameraControlHostApi.setup(mockApi);
+
+ final InstanceManager instanceManager = InstanceManager(
+ onWeakReferenceRemoved: (_) {},
+ );
+
+ final CameraControl cameraControl = CameraControl.detached(
+ instanceManager: instanceManager,
+ );
+ const int cameraControlIdentifier = 22;
+
+ instanceManager.addHostCreatedInstance(
+ cameraControl,
+ cameraControlIdentifier,
+ onCopy: (_) => CameraControl.detached(instanceManager: instanceManager),
+ );
+
+ const bool enableTorch = true;
+ await cameraControl.enableTorch(enableTorch);
+
+ verify(mockApi.enableTorch(cameraControlIdentifier, enableTorch));
+ });
+
+ test('flutterApiCreate makes call to add instance to instance manager', () {
+ final InstanceManager instanceManager = InstanceManager(
+ onWeakReferenceRemoved: (_) {},
+ );
+ final CameraControlFlutterApiImpl flutterApi =
+ CameraControlFlutterApiImpl(
+ instanceManager: instanceManager,
+ );
+ const int cameraControlIdentifier = 67;
+
+ flutterApi.create(cameraControlIdentifier);
+
+ expect(
+ instanceManager.getInstanceWithWeakReference(cameraControlIdentifier),
+ isA<CameraControl>());
+ });
+ });
+}
diff --git a/packages/camera/camera_android_camerax/test/camera_control_test.mocks.dart b/packages/camera/camera_android_camerax/test/camera_control_test.mocks.dart
new file mode 100644
index 0000000..0f43f0c
--- /dev/null
+++ b/packages/camera/camera_android_camerax/test/camera_control_test.mocks.dart
@@ -0,0 +1,69 @@
+// Mocks generated by Mockito 5.4.1 from annotations
+// in camera_android_camerax/test/camera_control_test.dart.
+// Do not manually edit this file.
+
+// @dart=2.19
+
+// ignore_for_file: no_leading_underscores_for_library_prefixes
+import 'dart:async' as _i3;
+
+import 'package:mockito/mockito.dart' as _i1;
+
+import 'test_camerax_library.g.dart' as _i2;
+
+// ignore_for_file: type=lint
+// ignore_for_file: avoid_redundant_argument_values
+// ignore_for_file: avoid_setters_without_getters
+// ignore_for_file: comment_references
+// ignore_for_file: implementation_imports
+// ignore_for_file: invalid_use_of_visible_for_testing_member
+// ignore_for_file: prefer_const_constructors
+// ignore_for_file: unnecessary_parenthesis
+// ignore_for_file: camel_case_types
+// ignore_for_file: subtype_of_sealed_class
+
+/// A class which mocks [TestCameraControlHostApi].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockTestCameraControlHostApi extends _i1.Mock
+ implements _i2.TestCameraControlHostApi {
+ MockTestCameraControlHostApi() {
+ _i1.throwOnMissingStub(this);
+ }
+
+ @override
+ _i3.Future<void> enableTorch(
+ int? identifier,
+ bool? torch,
+ ) =>
+ (super.noSuchMethod(
+ Invocation.method(
+ #enableTorch,
+ [
+ identifier,
+ torch,
+ ],
+ ),
+ returnValue: _i3.Future<void>.value(),
+ returnValueForMissingStub: _i3.Future<void>.value(),
+ ) as _i3.Future<void>);
+}
+
+/// A class which mocks [TestInstanceManagerHostApi].
+///
+/// See the documentation for Mockito's code generation for more information.
+class MockTestInstanceManagerHostApi extends _i1.Mock
+ implements _i2.TestInstanceManagerHostApi {
+ MockTestInstanceManagerHostApi() {
+ _i1.throwOnMissingStub(this);
+ }
+
+ @override
+ void clear() => super.noSuchMethod(
+ Invocation.method(
+ #clear,
+ [],
+ ),
+ returnValueForMissingStub: null,
+ );
+}
diff --git a/packages/camera/camera_android_camerax/test/camera_test.dart b/packages/camera/camera_android_camerax/test/camera_test.dart
index 05f5fe7..22d9dab 100644
--- a/packages/camera/camera_android_camerax/test/camera_test.dart
+++ b/packages/camera/camera_android_camerax/test/camera_test.dart
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'package:camera_android_camerax/src/camera.dart';
+import 'package:camera_android_camerax/src/camera_control.dart';
import 'package:camera_android_camerax/src/camera_info.dart';
import 'package:camera_android_camerax/src/instance_manager.dart';
import 'package:flutter_test/flutter_test.dart';
@@ -54,6 +55,39 @@
verify(mockApi.getCameraInfo(cameraIdentifier));
});
+ test('getCameraControl makes call to retrieve expected CameraControl',
+ () async {
+ final MockTestCameraHostApi mockApi = MockTestCameraHostApi();
+ TestCameraHostApi.setup(mockApi);
+
+ final InstanceManager instanceManager = InstanceManager(
+ onWeakReferenceRemoved: (_) {},
+ );
+
+ final Camera camera = Camera.detached(
+ instanceManager: instanceManager,
+ );
+ const int cameraIdentifier = 42;
+ final CameraControl cameraControl = CameraControl.detached();
+ const int cameraControlIdentifier = 8;
+ instanceManager.addHostCreatedInstance(
+ camera,
+ cameraIdentifier,
+ onCopy: (_) => Camera.detached(instanceManager: instanceManager),
+ );
+ instanceManager.addHostCreatedInstance(
+ cameraControl,
+ cameraControlIdentifier,
+ onCopy: (_) => CameraControl.detached(instanceManager: instanceManager),
+ );
+
+ when(mockApi.getCameraControl(cameraIdentifier))
+ .thenAnswer((_) => cameraControlIdentifier);
+
+ expect(await camera.getCameraControl(), equals(cameraControl));
+ verify(mockApi.getCameraControl(cameraIdentifier));
+ });
+
test('flutterApiCreate makes call to add instance to instance manager', () {
final InstanceManager instanceManager = InstanceManager(
onWeakReferenceRemoved: (_) {},
diff --git a/packages/camera/camera_android_camerax/test/camera_test.mocks.dart b/packages/camera/camera_android_camerax/test/camera_test.mocks.dart
index 47a15ae..7bae865 100644
--- a/packages/camera/camera_android_camerax/test/camera_test.mocks.dart
+++ b/packages/camera/camera_android_camerax/test/camera_test.mocks.dart
@@ -36,6 +36,14 @@
),
returnValue: 0,
) as int);
+ @override
+ int getCameraControl(int? identifier) => (super.noSuchMethod(
+ Invocation.method(
+ #getCameraControl,
+ [identifier],
+ ),
+ returnValue: 0,
+ ) as int);
}
/// A class which mocks [TestInstanceManagerHostApi].
diff --git a/packages/camera/camera_android_camerax/test/test_camerax_library.g.dart b/packages/camera/camera_android_camerax/test/test_camerax_library.g.dart
index c649a73..88e44ae 100644
--- a/packages/camera/camera_android_camerax/test/test_camerax_library.g.dart
+++ b/packages/camera/camera_android_camerax/test/test_camerax_library.g.dart
@@ -426,6 +426,8 @@
int getCameraInfo(int identifier);
+ int getCameraControl(int identifier);
+
static void setup(TestCameraHostApi? api,
{BinaryMessenger? binaryMessenger}) {
{
@@ -450,6 +452,28 @@
});
}
}
+ {
+ final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+ 'dev.flutter.pigeon.CameraHostApi.getCameraControl', codec,
+ binaryMessenger: binaryMessenger);
+ if (api == null) {
+ _testBinaryMessengerBinding!.defaultBinaryMessenger
+ .setMockDecodedMessageHandler<Object?>(channel, null);
+ } else {
+ _testBinaryMessengerBinding!.defaultBinaryMessenger
+ .setMockDecodedMessageHandler<Object?>(channel,
+ (Object? message) async {
+ assert(message != null,
+ 'Argument for dev.flutter.pigeon.CameraHostApi.getCameraControl was null.');
+ final List<Object?> args = (message as List<Object?>?)!;
+ final int? arg_identifier = (args[0] as int?);
+ assert(arg_identifier != null,
+ 'Argument for dev.flutter.pigeon.CameraHostApi.getCameraControl was null, expected non-null int.');
+ final int output = api.getCameraControl(arg_identifier!);
+ return <Object?>[output];
+ });
+ }
+ }
}
}
@@ -1721,3 +1745,40 @@
}
}
}
+
+abstract class TestCameraControlHostApi {
+ static TestDefaultBinaryMessengerBinding? get _testBinaryMessengerBinding =>
+ TestDefaultBinaryMessengerBinding.instance;
+ static const MessageCodec<Object?> codec = StandardMessageCodec();
+
+ Future<void> enableTorch(int identifier, bool torch);
+
+ static void setup(TestCameraControlHostApi? api,
+ {BinaryMessenger? binaryMessenger}) {
+ {
+ final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+ 'dev.flutter.pigeon.CameraControlHostApi.enableTorch', codec,
+ binaryMessenger: binaryMessenger);
+ if (api == null) {
+ _testBinaryMessengerBinding!.defaultBinaryMessenger
+ .setMockDecodedMessageHandler<Object?>(channel, null);
+ } else {
+ _testBinaryMessengerBinding!.defaultBinaryMessenger
+ .setMockDecodedMessageHandler<Object?>(channel,
+ (Object? message) async {
+ assert(message != null,
+ 'Argument for dev.flutter.pigeon.CameraControlHostApi.enableTorch was null.');
+ final List<Object?> args = (message as List<Object?>?)!;
+ final int? arg_identifier = (args[0] as int?);
+ assert(arg_identifier != null,
+ 'Argument for dev.flutter.pigeon.CameraControlHostApi.enableTorch was null, expected non-null int.');
+ final bool? arg_torch = (args[1] as bool?);
+ assert(arg_torch != null,
+ 'Argument for dev.flutter.pigeon.CameraControlHostApi.enableTorch was null, expected non-null bool.');
+ await api.enableTorch(arg_identifier!, arg_torch!);
+ return <Object?>[];
+ });
+ }
+ }
+ }
+}