From e168785f9c32e9862de69edcc2b4788a0709794e Mon Sep 17 00:00:00 2001 From: camsim99 Date: Mon, 9 Jan 2023 15:11:46 -0800 Subject: [PATCH 01/13] Add base code from proof of concept --- .../android/src/main/AndroidManifest.xml | 5 + .../camerax/CameraAndroidCameraxPlugin.java | 20 +- .../camerax/CameraPermissionsManager.java | 118 +++++++ .../camerax/DeviceOrientationManager.java | 330 ++++++++++++++++++ .../camerax/SystemServicesFlutterApiImpl.java | 27 ++ .../camerax/SystemServicesHostApiImpl.java | 62 ++++ ...roid_camera_camerax_flutter_api_impls.dart | 8 + .../lib/src/instance_manager.dart | 1 - .../lib/src/system_services.dart | 134 +++++++ .../pigeons/camerax_library.dart | 16 + .../camera_android_camerax/pubspec.yaml | 1 + 11 files changed, 715 insertions(+), 7 deletions(-) create mode 100644 packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraPermissionsManager.java create mode 100644 packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/DeviceOrientationManager.java create mode 100644 packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesFlutterApiImpl.java create mode 100644 packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java create mode 100644 packages/camera/camera_android_camerax/lib/src/system_services.dart diff --git a/packages/camera/camera_android_camerax/android/src/main/AndroidManifest.xml b/packages/camera/camera_android_camerax/android/src/main/AndroidManifest.xml index ea4275c757cf..52012aaa6915 100644 --- a/packages/camera/camera_android_camerax/android/src/main/AndroidManifest.xml +++ b/packages/camera/camera_android_camerax/android/src/main/AndroidManifest.xml @@ -1,3 +1,8 @@ + + + + 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 b8fbaf539c32..3303601fd552 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 @@ -10,12 +10,14 @@ import io.flutter.embedding.engine.plugins.activity.ActivityAware; import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding; import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.view.TextureRegistry; /** Platform implementation of the camera_plugin implemented with the CameraX library. */ public final class CameraAndroidCameraxPlugin implements FlutterPlugin, ActivityAware { private InstanceManager instanceManager; private FlutterPluginBinding pluginBinding; private ProcessCameraProviderHostApiImpl processCameraProviderHostApi; + public SystemServicesHostApiImpl systemServicesHostApi; /** * Initialize this within the {@code #configureFlutterEngine} of a Flutter activity or fragment. @@ -24,7 +26,7 @@ public final class CameraAndroidCameraxPlugin implements FlutterPlugin, Activity */ public CameraAndroidCameraxPlugin() {} - void setUp(BinaryMessenger binaryMessenger, Context context) { + void setUp(BinaryMessenger binaryMessenger, Context context, TextureRegistry textureRegistry) { // Set up instance manager. instanceManager = InstanceManager.open( @@ -44,15 +46,13 @@ void setUp(BinaryMessenger binaryMessenger, Context context) { new ProcessCameraProviderHostApiImpl(binaryMessenger, instanceManager, context); GeneratedCameraXLibrary.ProcessCameraProviderHostApi.setup( binaryMessenger, processCameraProviderHostApi); + systemServicesHostApi = new SystemServicesHostApiImpl(binaryMessenger, instanceManager); + GeneratedCameraXLibrary.SystemServicesHostApi.setup(binaryMessenger, systemServicesHostApi); } @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) { pluginBinding = flutterPluginBinding; - (new CameraAndroidCameraxPlugin()) - .setUp( - flutterPluginBinding.getBinaryMessenger(), - flutterPluginBinding.getApplicationContext()); } @Override @@ -66,7 +66,15 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { @Override public void onAttachedToActivity(@NonNull ActivityPluginBinding activityPluginBinding) { - updateContext(activityPluginBinding.getActivity()); + CameraAndroidCameraxPlugin plugin = new CameraAndroidCameraxPlugin(); + plugin.setUp( + pluginBinding.getBinaryMessenger(), + pluginBinding.getApplicationContext(), + pluginBinding.getTextureRegistry()); + plugin.updateContext(pluginBinding.getApplicationContext()); + plugin.systemServicesHostApi.setActivity(activityPluginBinding.getActivity()); + plugin.systemServicesHostApi.setPermissionsRegistry( + activityPluginBinding::addRequestPermissionsResultListener); } @Override diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraPermissionsManager.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraPermissionsManager.java new file mode 100644 index 000000000000..230f3fdc4f44 --- /dev/null +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraPermissionsManager.java @@ -0,0 +1,118 @@ +// 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.Manifest; +import android.Manifest.permission; +import android.app.Activity; +import android.content.pm.PackageManager; +import androidx.annotation.VisibleForTesting; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +final class CameraPermissionsManager { + interface PermissionsRegistry { + @SuppressWarnings("deprecation") + void addListener( + io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener handler); + } + + interface ResultCallback { + void onResult(String errorCode, String errorDescription); + } + + /** + * Camera access permission errors handled when camera is created. See {@code MethodChannelCamera} + * in {@code camera/camera_platform_interface} for details. + */ + private static final String CAMERA_PERMISSIONS_REQUEST_ONGOING = + "CameraPermissionsRequestOngoing"; + + private static final String CAMERA_PERMISSIONS_REQUEST_ONGOING_MESSAGE = + "Another request is ongoing and multiple requests cannot be handled at once."; + private static final String CAMERA_ACCESS_DENIED = "CameraAccessDenied"; + private static final String CAMERA_ACCESS_DENIED_MESSAGE = "Camera access permission was denied."; + private static final String AUDIO_ACCESS_DENIED = "AudioAccessDenied"; + private static final String AUDIO_ACCESS_DENIED_MESSAGE = "Audio access permission was denied."; + + private static final int CAMERA_REQUEST_ID = 9796; + @VisibleForTesting boolean ongoing = false; + + void requestPermissions( + Activity activity, + PermissionsRegistry permissionsRegistry, + boolean enableAudio, + ResultCallback callback) { + if (ongoing) { + callback.onResult( + CAMERA_PERMISSIONS_REQUEST_ONGOING, CAMERA_PERMISSIONS_REQUEST_ONGOING_MESSAGE); + return; + } + if (!hasCameraPermission(activity) || (enableAudio && !hasAudioPermission(activity))) { + permissionsRegistry.addListener( + new CameraRequestPermissionsListener( + (String errorCode, String errorDescription) -> { + ongoing = false; + callback.onResult(errorCode, errorDescription); + })); + ongoing = true; + ActivityCompat.requestPermissions( + activity, + enableAudio + ? new String[] {Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO} + : new String[] {Manifest.permission.CAMERA}, + CAMERA_REQUEST_ID); + } else { + // Permissions already exist. Call the callback with success. + callback.onResult(null, null); + } + } + + private boolean hasCameraPermission(Activity activity) { + return ContextCompat.checkSelfPermission(activity, permission.CAMERA) + == PackageManager.PERMISSION_GRANTED; + } + + private boolean hasAudioPermission(Activity activity) { + return ContextCompat.checkSelfPermission(activity, permission.RECORD_AUDIO) + == PackageManager.PERMISSION_GRANTED; + } + + @VisibleForTesting + @SuppressWarnings("deprecation") + static final class CameraRequestPermissionsListener + implements io.flutter.plugin.common.PluginRegistry.RequestPermissionsResultListener { + + // There's no way to unregister permission listeners in the v1 embedding, so we'll be called + // duplicate times in cases where the user denies and then grants a permission. Keep track of if + // we've responded before and bail out of handling the callback manually if this is a repeat + // call. + boolean alreadyCalled = false; + + final ResultCallback callback; + + @VisibleForTesting + CameraRequestPermissionsListener(ResultCallback callback) { + this.callback = callback; + } + + @Override + public boolean onRequestPermissionsResult(int id, String[] permissions, int[] grantResults) { + if (alreadyCalled || id != CAMERA_REQUEST_ID) { + return false; + } + + alreadyCalled = true; + if (grantResults[0] != PackageManager.PERMISSION_GRANTED) { + callback.onResult(CAMERA_ACCESS_DENIED, CAMERA_ACCESS_DENIED_MESSAGE); + } else if (grantResults.length > 1 && grantResults[1] != PackageManager.PERMISSION_GRANTED) { + callback.onResult(AUDIO_ACCESS_DENIED, AUDIO_ACCESS_DENIED_MESSAGE); + } else { + callback.onResult(null, null); + } + return true; + } + } +} diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/DeviceOrientationManager.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/DeviceOrientationManager.java new file mode 100644 index 000000000000..9f85860bb87b --- /dev/null +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/DeviceOrientationManager.java @@ -0,0 +1,330 @@ +// 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.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.res.Configuration; +import android.view.Display; +import android.view.Surface; +import android.view.WindowManager; +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; +import io.flutter.embedding.engine.systemchannels.PlatformChannel; +import io.flutter.embedding.engine.systemchannels.PlatformChannel.DeviceOrientation; + +/** + * Support class to help to determine the media orientation based on the orientation of the device. + */ +public class DeviceOrientationManager { + + interface DeviceOrientationChangeCallback { + void onChange(String newOrientation); + } + + private static final IntentFilter orientationIntentFilter = + new IntentFilter(Intent.ACTION_CONFIGURATION_CHANGED); + + private final Activity activity; + private final boolean isFrontFacing; + private final int sensorOrientation; + private final DeviceOrientationChangeCallback deviceOrientationChangeCallback; + private PlatformChannel.DeviceOrientation lastOrientation; + private BroadcastReceiver broadcastReceiver; + + DeviceOrientationManager( + @NonNull Activity activity, + boolean isFrontFacing, + int sensorOrientation, + DeviceOrientationChangeCallback callback) { + this.activity = activity; + this.isFrontFacing = isFrontFacing; + this.sensorOrientation = sensorOrientation; + this.deviceOrientationChangeCallback = callback; + } + + // TODO(camsim99): Fix docs. + /** + * Starts listening to the device's sensors or UI for orientation updates. + * + *

When orientation information is updated the new orientation is send to the client using the + * {@link DartMessenger}. This latest value can also be retrieved through the {@link + * #getVideoOrientation()} accessor. + * + *

If the device's ACCELEROMETER_ROTATION setting is enabled the {@link + * DeviceOrientationManager} will report orientation updates based on the sensor information. If + * the ACCELEROMETER_ROTATION is disabled the {@link DeviceOrientationManager} will fallback to + * the deliver orientation updates based on the UI orientation. + */ + public void start() { + if (broadcastReceiver != null) { + return; + } + broadcastReceiver = + new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + handleUIOrientationChange(); + } + }; + activity.registerReceiver(broadcastReceiver, orientationIntentFilter); + broadcastReceiver.onReceive(activity, null); + } + + /** Stops listening for orientation updates. */ + public void stop() { + if (broadcastReceiver == null) { + return; + } + activity.unregisterReceiver(broadcastReceiver); + broadcastReceiver = null; + } + + /** + * Returns the device's photo orientation in degrees based on the sensor orientation and the last + * known UI orientation. + * + *

Returns one of 0, 90, 180 or 270. + * + * @return The device's photo orientation in degrees. + */ + public int getPhotoOrientation() { + return this.getPhotoOrientation(this.lastOrientation); + } + + /** + * Returns the device's photo orientation in degrees based on the sensor orientation and the + * supplied {@link PlatformChannel.DeviceOrientation} value. + * + *

Returns one of 0, 90, 180 or 270. + * + * @param orientation The {@link PlatformChannel.DeviceOrientation} value that is to be converted + * into degrees. + * @return The device's photo orientation in degrees. + */ + public int getPhotoOrientation(PlatformChannel.DeviceOrientation orientation) { + int angle = 0; + // Fallback to device orientation when the orientation value is null. + if (orientation == null) { + orientation = getUIOrientation(); + } + + switch (orientation) { + case PORTRAIT_UP: + angle = 90; + break; + case PORTRAIT_DOWN: + angle = 270; + break; + case LANDSCAPE_LEFT: + angle = isFrontFacing ? 180 : 0; + break; + case LANDSCAPE_RIGHT: + angle = isFrontFacing ? 0 : 180; + break; + } + + // Sensor orientation is 90 for most devices, or 270 for some devices (eg. Nexus 5X). + // This has to be taken into account so the JPEG is rotated properly. + // For devices with orientation of 90, this simply returns the mapping from ORIENTATIONS. + // For devices with orientation of 270, the JPEG is rotated 180 degrees instead. + return (angle + sensorOrientation + 270) % 360; + } + + /** + * Returns the device's video orientation in clockwise degrees based on the sensor orientation and + * the last known UI orientation. + * + *

Returns one of 0, 90, 180 or 270. + * + * @return The device's video orientation in clockwise degrees. + */ + public int getVideoOrientation() { + return this.getVideoOrientation(this.lastOrientation); + } + + /** + * Returns the device's video orientation in clockwise degrees based on the sensor orientation and + * the supplied {@link PlatformChannel.DeviceOrientation} value. + * + *

Returns one of 0, 90, 180 or 270. + * + *

More details can be found in the official Android documentation: + * https://developer.android.com/reference/android/media/MediaRecorder#setOrientationHint(int) + * + *

See also: + * https://developer.android.com/training/camera2/camera-preview-large-screens#orientation_calculation + * + * @param orientation The {@link PlatformChannel.DeviceOrientation} value that is to be converted + * into degrees. + * @return The device's video orientation in clockwise degrees. + */ + public int getVideoOrientation(PlatformChannel.DeviceOrientation orientation) { + int angle = 0; + + // Fallback to device orientation when the orientation value is null. + if (orientation == null) { + orientation = getUIOrientation(); + } + + switch (orientation) { + case PORTRAIT_UP: + angle = 0; + break; + case PORTRAIT_DOWN: + angle = 180; + break; + case LANDSCAPE_LEFT: + angle = 270; + break; + case LANDSCAPE_RIGHT: + angle = 90; + break; + } + + if (isFrontFacing) { + angle *= -1; + } + + return (angle + sensorOrientation + 360) % 360; + } + + /** @return the last received UI orientation. */ + public PlatformChannel.DeviceOrientation getLastUIOrientation() { + return this.lastOrientation; + } + + /** + * Handles orientation changes based on change events triggered by the OrientationIntentFilter. + * + *

This method is visible for testing purposes only and should never be used outside this + * class. + */ + @VisibleForTesting + void handleUIOrientationChange() { + PlatformChannel.DeviceOrientation orientation = getUIOrientation(); + handleOrientationChange(orientation, lastOrientation, deviceOrientationChangeCallback); + lastOrientation = orientation; + } + + /** + * Handles orientation changes coming from either the device's sensors or the + * OrientationIntentFilter. + * + *

This method is visible for testing purposes only and should never be used outside this + * class. + */ + @VisibleForTesting + static void handleOrientationChange( + DeviceOrientation newOrientation, + DeviceOrientation previousOrientation, + DeviceOrientationChangeCallback callback) { + if (!newOrientation.equals(previousOrientation)) { + callback.onChange(newOrientation.name()); + } + } + + /** + * Gets the current user interface orientation. + * + *

This method is visible for testing purposes only and should never be used outside this + * class. + * + * @return The current user interface orientation. + */ + @VisibleForTesting + PlatformChannel.DeviceOrientation getUIOrientation() { + final int rotation = getDisplay().getRotation(); + final int orientation = activity.getResources().getConfiguration().orientation; + + switch (orientation) { + case Configuration.ORIENTATION_PORTRAIT: + if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) { + return PlatformChannel.DeviceOrientation.PORTRAIT_UP; + } else { + return PlatformChannel.DeviceOrientation.PORTRAIT_DOWN; + } + case Configuration.ORIENTATION_LANDSCAPE: + if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90) { + return PlatformChannel.DeviceOrientation.LANDSCAPE_LEFT; + } else { + return PlatformChannel.DeviceOrientation.LANDSCAPE_RIGHT; + } + default: + return PlatformChannel.DeviceOrientation.PORTRAIT_UP; + } + } + + /** + * Calculates the sensor orientation based on the supplied angle. + * + *

This method is visible for testing purposes only and should never be used outside this + * class. + * + * @param angle Orientation angle. + * @return The sensor orientation based on the supplied angle. + */ + @VisibleForTesting + PlatformChannel.DeviceOrientation calculateSensorOrientation(int angle) { + final int tolerance = 45; + angle += tolerance; + + // Orientation is 0 in the default orientation mode. This is portrait-mode for phones + // and landscape for tablets. We have to compensate for this by calculating the default + // orientation, and apply an offset accordingly. + int defaultDeviceOrientation = getDeviceDefaultOrientation(); + if (defaultDeviceOrientation == Configuration.ORIENTATION_LANDSCAPE) { + angle += 90; + } + // Determine the orientation + angle = angle % 360; + return new PlatformChannel.DeviceOrientation[] { + PlatformChannel.DeviceOrientation.PORTRAIT_UP, + PlatformChannel.DeviceOrientation.LANDSCAPE_LEFT, + PlatformChannel.DeviceOrientation.PORTRAIT_DOWN, + PlatformChannel.DeviceOrientation.LANDSCAPE_RIGHT, + } + [angle / 90]; + } + + /** + * Gets the default orientation of the device. + * + *

This method is visible for testing purposes only and should never be used outside this + * class. + * + * @return The default orientation of the device. + */ + @VisibleForTesting + int getDeviceDefaultOrientation() { + Configuration config = activity.getResources().getConfiguration(); + int rotation = getDisplay().getRotation(); + if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) + && config.orientation == Configuration.ORIENTATION_LANDSCAPE) + || ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) + && config.orientation == Configuration.ORIENTATION_PORTRAIT)) { + return Configuration.ORIENTATION_LANDSCAPE; + } else { + return Configuration.ORIENTATION_PORTRAIT; + } + } + + /** + * Gets an instance of the Android {@link android.view.Display}. + * + *

This method is visible for testing purposes only and should never be used outside this + * class. + * + * @return An instance of the Android {@link android.view.Display}. + */ + @SuppressWarnings("deprecation") + @VisibleForTesting + Display getDisplay() { + return ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); + } +} \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesFlutterApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesFlutterApiImpl.java new file mode 100644 index 000000000000..06926f1a06ac --- /dev/null +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesFlutterApiImpl.java @@ -0,0 +1,27 @@ +// 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 io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugins.camerax.GeneratedCameraXLibrary.SystemServicesFlutterApi; + +public class SystemServicesFlutterApiImpl extends SystemServicesFlutterApi { + public SystemServicesFlutterApiImpl( + BinaryMessenger binaryMessenger, InstanceManager instanceManager) { + super(binaryMessenger); + this.instanceManager = instanceManager; + } + + private final InstanceManager instanceManager; + + public void onCameraPermissionsRequestResult( + String resultCode, String resultMessage, Reply reply) { + super.onCameraPermissionsRequestResult(resultCode, resultMessage, reply); + } + + public void onDeviceOrientationChanged(String orientation, Reply reply) { + super.onDeviceOrientationChanged(orientation, reply); + } +} diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java new file mode 100644 index 000000000000..ff40e1de84be --- /dev/null +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java @@ -0,0 +1,62 @@ +// 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.app.Activity; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugins.camerax.CameraPermissionsManager.PermissionsRegistry; +import io.flutter.plugins.camerax.GeneratedCameraXLibrary.SystemServicesHostApi; + +public class SystemServicesHostApiImpl implements SystemServicesHostApi { + private final BinaryMessenger binaryMessenger; + private final InstanceManager instanceManager; + + private Activity activity; + private PermissionsRegistry permissionsRegistry; + + public SystemServicesHostApiImpl( + BinaryMessenger binaryMessenger, InstanceManager instanceManager) { + this.binaryMessenger = binaryMessenger; + this.instanceManager = instanceManager; + } + + public void setActivity(Activity activity) { + this.activity = activity; + } + + public void setPermissionsRegistry(PermissionsRegistry permissionsRegistry) { + this.permissionsRegistry = permissionsRegistry; + } + + @Override + public void requestCameraPermissions(Boolean enableAudio) { + CameraPermissionsManager cameraPermissionsManager = new CameraPermissionsManager(); + cameraPermissionsManager.requestPermissions( + activity, + permissionsRegistry, + enableAudio, + (String errCode, String errDesc) -> { + final SystemServicesFlutterApiImpl api = + new SystemServicesFlutterApiImpl(binaryMessenger, instanceManager); + api.onCameraPermissionsRequestResult(errCode, errDesc, reply -> {}); + }); + } + + @Override + public void startListeningForDeviceOrientationChange( + Boolean isFrontFacing, Long sensorOrientation) { + DeviceOrientationManager deviceOrientationManager = + new DeviceOrientationManager( + activity, + isFrontFacing, + sensorOrientation.intValue(), + (String newOrientation) -> { + final SystemServicesFlutterApiImpl api = + new SystemServicesFlutterApiImpl(binaryMessenger, instanceManager); + api.onDeviceOrientationChanged(newOrientation, reply -> {}); + }); + deviceOrientationManager.start(); + } +} \ No newline at end of file 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 9c6564a06c08..c0a784230656 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 @@ -7,6 +7,7 @@ import 'camera_selector.dart'; import 'camerax_library.pigeon.dart'; import 'java_object.dart'; import 'process_camera_provider.dart'; +import 'system_services.dart'; /// Handles initialization of Flutter APIs for the Android CameraX library. class AndroidCameraXCameraFlutterApis { @@ -16,6 +17,7 @@ class AndroidCameraXCameraFlutterApis { CameraInfoFlutterApiImpl? cameraInfoFlutterApi, CameraSelectorFlutterApiImpl? cameraSelectorFlutterApi, ProcessCameraProviderFlutterApiImpl? processCameraProviderFlutterApi, + SystemServicesFlutterApiImpl? systemServicesFlutterApi, }) { this.javaObjectFlutterApi = javaObjectFlutterApi ?? JavaObjectFlutterApiImpl(); @@ -25,6 +27,8 @@ class AndroidCameraXCameraFlutterApis { cameraSelectorFlutterApi ?? CameraSelectorFlutterApiImpl(); this.processCameraProviderFlutterApi = processCameraProviderFlutterApi ?? ProcessCameraProviderFlutterApiImpl(); + this.systemServicesFlutterApi = + systemServicesFlutterApi ?? SystemServicesFlutterApiImpl(); } static bool _haveBeenSetUp = false; @@ -48,6 +52,9 @@ class AndroidCameraXCameraFlutterApis { late final ProcessCameraProviderFlutterApiImpl processCameraProviderFlutterApi; + /// Flutter Api for [SystemServices]. + late final SystemServicesFlutterApiImpl systemServicesFlutterApi; + /// Ensures all the Flutter APIs have been setup to receive calls from native code. void ensureSetUp() { if (!_haveBeenSetUp) { @@ -55,6 +62,7 @@ class AndroidCameraXCameraFlutterApis { CameraInfoFlutterApi.setup(cameraInfoFlutterApi); CameraSelectorFlutterApi.setup(cameraSelectorFlutterApi); ProcessCameraProviderFlutterApi.setup(processCameraProviderFlutterApi); + SystemServicesFlutterApi.setup(systemServicesFlutterApi); _haveBeenSetUp = true; } } diff --git a/packages/camera/camera_android_camerax/lib/src/instance_manager.dart b/packages/camera/camera_android_camerax/lib/src/instance_manager.dart index dd48610c8b56..4e2b615618be 100644 --- a/packages/camera/camera_android_camerax/lib/src/instance_manager.dart +++ b/packages/camera/camera_android_camerax/lib/src/instance_manager.dart @@ -161,7 +161,6 @@ class InstanceManager { int identifier, { required T Function(T original) onCopy, }) { - assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); _addInstanceWithIdentifier(instance, identifier, onCopy: onCopy); diff --git a/packages/camera/camera_android_camerax/lib/src/system_services.dart b/packages/camera/camera_android_camerax/lib/src/system_services.dart new file mode 100644 index 000000000000..4efed521175d --- /dev/null +++ b/packages/camera/camera_android_camerax/lib/src/system_services.dart @@ -0,0 +1,134 @@ +// 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 'dart:async'; + +import 'package:camera_platform_interface/camera_platform_interface.dart' + show DeviceOrientationChangedEvent; +import 'package:flutter/services.dart'; + +import 'android_camera_camerax_flutter_api_impls.dart'; +import 'camerax_library.pigeon.dart'; +import 'instance_manager.dart'; +import 'java_object.dart'; +import 'use_case.dart'; + +class SystemServices { + // TODO(camsim99): Change this to actually handle errors. + static final StreamController cameraPermissionsStreamController = + StreamController.broadcast(); + + static final StreamController + deviceOrientationChangedStreamController = + StreamController.broadcast(); + + static Future requestCameraPermissions(bool enableAudio, + {BinaryMessenger? binaryMessenger, InstanceManager? instanceManager}) { + AndroidCameraXCameraFlutterApis.instance.ensureSetUp(); + SystemServicesHostApiImpl api = SystemServicesHostApiImpl( + binaryMessenger: binaryMessenger, instanceManager: instanceManager); + + return api.requestCameraPermissionsFromInstance(enableAudio); + } + + static void startListeningForDeviceOrientationChange( + bool isFrontFacing, int sensorOrientation, + {BinaryMessenger? binaryMessenger, InstanceManager? instanceManager}) { + AndroidCameraXCameraFlutterApis.instance.ensureSetUp(); + SystemServicesHostApi api = + SystemServicesHostApi(binaryMessenger: binaryMessenger); + + api.startListeningForDeviceOrientationChange( + isFrontFacing, sensorOrientation); + } +} + +/// Host API implementation of [SystemServices]. +class SystemServicesHostApiImpl extends SystemServicesHostApi { + /// Creates a [SystemServicesHostApiImpl]. + SystemServicesHostApiImpl( + {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; + + Future requestCameraPermissionsFromInstance(bool enableAudio) async { + requestCameraPermissions(enableAudio); + + try { + await for (final bool result + in SystemServices.cameraPermissionsStreamController.stream) { + return result; + } + } catch (e) { + // TODO(camsim99): Actually throw error here + return false; + } + return false; + } +} + +/// Flutter API implementation of [SystemServices]. +class SystemServicesFlutterApiImpl implements SystemServicesFlutterApi { + /// Constructs a [SystemServicesFlutterApiImpl]. + SystemServicesFlutterApiImpl({ + this.binaryMessenger, + InstanceManager? instanceManager, + }) : 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. + final InstanceManager instanceManager; + + @override + void onCameraPermissionsRequestResult( + String? errorCode, String? errorMessage) { + // TODO(camsim99): Expand on this to throw appropriate error. + bool result = false; + if (errorCode == null) { + result = true; + } + + SystemServices.cameraPermissionsStreamController.add(result); + } + + @override + void onDeviceOrientationChanged(String orientation) { + DeviceOrientation? deviceOrientation = getDeviceOrientation(orientation); + if (deviceOrientation == null) { + return; + } + SystemServices.deviceOrientationChangedStreamController + .add(DeviceOrientationChangedEvent(deviceOrientation!)); + } + + DeviceOrientation? getDeviceOrientation(String orientation) { + switch (orientation) { + case 'LANDSCAPE_LEFT': + return DeviceOrientation.landscapeLeft; + case 'LANDSCAPE_RIGHT': + return DeviceOrientation.landscapeRight; + case 'PORTRAIT_DOWN': + return DeviceOrientation.portraitDown; + case 'PORTRAIT_UP': + return DeviceOrientation.portraitUp; + default: + return null; + } + } +} diff --git a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart index 4d7d96910246..90eb8ea49fc7 100644 --- a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart +++ b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart @@ -70,3 +70,19 @@ abstract class ProcessCameraProviderHostApi { abstract class ProcessCameraProviderFlutterApi { void create(int identifier); } + +@HostApi(dartHostTestHandler: 'TestSystemServicesHostApi') +abstract class SystemServicesHostApi { + void requestCameraPermissions(bool enableAudio); + + void startListeningForDeviceOrientationChange( + bool isFrontFacing, int sensorOrientation); +} + +@FlutterApi() +abstract class SystemServicesFlutterApi { + void onCameraPermissionsRequestResult( + String? errorCode, String? errorMessage); + + void onDeviceOrientationChanged(String orientation); +} diff --git a/packages/camera/camera_android_camerax/pubspec.yaml b/packages/camera/camera_android_camerax/pubspec.yaml index 9873db1a0121..7f81ecbd4f71 100644 --- a/packages/camera/camera_android_camerax/pubspec.yaml +++ b/packages/camera/camera_android_camerax/pubspec.yaml @@ -21,6 +21,7 @@ dependencies: camera_platform_interface: ^2.2.0 flutter: sdk: flutter + stream_transform: ^2.1.0 dev_dependencies: build_runner: ^2.1.4 From b923bc22729980b4bb67973df284a07c784a3203 Mon Sep 17 00:00:00 2001 From: camsim99 Date: Mon, 9 Jan 2023 16:24:42 -0800 Subject: [PATCH 02/13] Add pigeon types --- .../camerax/SystemServicesHostApiImpl.java | 4 ++-- .../lib/src/instance_manager.dart | 2 +- .../pigeons/camerax_library.dart | 21 ++++++++++++++++--- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java index ff40e1de84be..6035ceef7a12 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java @@ -37,10 +37,10 @@ public void requestCameraPermissions(Boolean enableAudio) { activity, permissionsRegistry, enableAudio, - (String errCode, String errDesc) -> { + (String errorCode, String errDescription) -> { final SystemServicesFlutterApiImpl api = new SystemServicesFlutterApiImpl(binaryMessenger, instanceManager); - api.onCameraPermissionsRequestResult(errCode, errDesc, reply -> {}); + api.onCameraPermissionsRequestResult(errorCode, errDescription, reply -> {}); }); } diff --git a/packages/camera/camera_android_camerax/lib/src/instance_manager.dart b/packages/camera/camera_android_camerax/lib/src/instance_manager.dart index 4e2b615618be..0eddd64cbc13 100644 --- a/packages/camera/camera_android_camerax/lib/src/instance_manager.dart +++ b/packages/camera/camera_android_camerax/lib/src/instance_manager.dart @@ -152,7 +152,7 @@ class InstanceManager { /// In other words, the host platform wants to add a new instance that /// represents an object on the host platform. Stored with [identifier]. /// - /// Throws assertion error if the instance or its identifier has already been + /// Throws assertion error if the instance has already been /// added. /// /// Returns unique identifier of the [instance] added. diff --git a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart index 90eb8ea49fc7..458bb671b3c0 100644 --- a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart +++ b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart @@ -26,6 +26,22 @@ import 'package:pigeon/pigeon.dart'; ), ), ) + +// TODO(camsim99): delete test comment +class CameraPermissionsErrorData { + CameraPermissionsErrorData(this.errorCode, this.description); + + String? errorCode; + String? description; +} + +enum DeviceOrientation { + landscapeLeft, + landscapeRight, + portraitDown, + portraitUp, +} + @HostApi(dartHostTestHandler: 'TestJavaObjectHostApi') abstract class JavaObjectHostApi { void dispose(int identifier); @@ -81,8 +97,7 @@ abstract class SystemServicesHostApi { @FlutterApi() abstract class SystemServicesFlutterApi { - void onCameraPermissionsRequestResult( - String? errorCode, String? errorMessage); + void onCameraPermissionsRequestResult(CameraPermissionsErrorData? error); - void onDeviceOrientationChanged(String orientation); + void onDeviceOrientationChanged(DeviceOrientation orientation); } From ec1b618e745ae6d577a02e2f60f3b4a62889e163 Mon Sep 17 00:00:00 2001 From: camsim99 Date: Wed, 11 Jan 2023 10:51:00 -0800 Subject: [PATCH 03/13] Make corrections, add Dart tests --- .../camerax/DeviceOrientationManager.java | 6 +- .../camerax/GeneratedCameraXLibrary.java | 231 ++++++++++++++++++ .../camerax/SystemServicesFlutterApiImpl.java | 5 - .../camerax/SystemServicesHostApiImpl.java | 32 ++- .../plugins/camerax/SystemServicesTest.java | 1 + .../lib/src/camerax_library.pigeon.dart | 147 +++++++++++ .../lib/src/system_services.dart | 70 ++---- .../pigeons/camerax_library.dart | 25 +- .../test/camera_info_test.mocks.dart | 10 +- .../test/camera_selector_test.mocks.dart | 36 ++- .../process_camera_provider_test.mocks.dart | 20 +- .../test/system_services_test.dart | 101 ++++++++ .../test/system_services_test.mocks.dart | 58 +++++ .../test/test_camerax_library.pigeon.dart | 81 ++++++ 14 files changed, 727 insertions(+), 96 deletions(-) create mode 100644 packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/SystemServicesTest.java create mode 100644 packages/camera/camera_android_camerax/test/system_services_test.dart create mode 100644 packages/camera/camera_android_camerax/test/system_services_test.mocks.dart diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/DeviceOrientationManager.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/DeviceOrientationManager.java index 9f85860bb87b..752b802e66db 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/DeviceOrientationManager.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/DeviceOrientationManager.java @@ -24,7 +24,7 @@ public class DeviceOrientationManager { interface DeviceOrientationChangeCallback { - void onChange(String newOrientation); + void onChange(DeviceOrientation newOrientation); } private static final IntentFilter orientationIntentFilter = @@ -225,7 +225,7 @@ static void handleOrientationChange( DeviceOrientation previousOrientation, DeviceOrientationChangeCallback callback) { if (!newOrientation.equals(previousOrientation)) { - callback.onChange(newOrientation.name()); + callback.onChange(newOrientation); } } @@ -327,4 +327,4 @@ int getDeviceDefaultOrientation() { Display getDisplay() { return ((WindowManager) activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); } -} \ No newline at end of file +} 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 041564c3bfcb..73fcf3ae78f0 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 @@ -13,6 +13,8 @@ import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MessageCodec; import io.flutter.plugin.common.StandardMessageCodec; +import java.io.ByteArrayOutputStream; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -23,6 +25,78 @@ @SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression"}) public class GeneratedCameraXLibrary { + /** Generated class from Pigeon that represents data sent in messages. */ + public static class CameraPermissionsErrorData { + private @NonNull String errorCode; + + public @NonNull String getErrorCode() { + return errorCode; + } + + public void setErrorCode(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"errorCode\" is null."); + } + this.errorCode = setterArg; + } + + private @NonNull String description; + + public @NonNull String getDescription() { + return description; + } + + public void setDescription(@NonNull String setterArg) { + if (setterArg == null) { + throw new IllegalStateException("Nonnull field \"description\" is null."); + } + this.description = setterArg; + } + + /** Constructor is private to enforce null safety; use Builder. */ + private CameraPermissionsErrorData() {} + + public static final class Builder { + private @Nullable String errorCode; + + public @NonNull Builder setErrorCode(@NonNull String setterArg) { + this.errorCode = setterArg; + return this; + } + + private @Nullable String description; + + public @NonNull Builder setDescription(@NonNull String setterArg) { + this.description = setterArg; + return this; + } + + public @NonNull CameraPermissionsErrorData build() { + CameraPermissionsErrorData pigeonReturn = new CameraPermissionsErrorData(); + pigeonReturn.setErrorCode(errorCode); + pigeonReturn.setDescription(description); + return pigeonReturn; + } + } + + @NonNull + Map toMap() { + Map toMapResult = new HashMap<>(); + toMapResult.put("errorCode", errorCode); + toMapResult.put("description", description); + return toMapResult; + } + + static @NonNull CameraPermissionsErrorData fromMap(@NonNull Map map) { + CameraPermissionsErrorData pigeonResult = new CameraPermissionsErrorData(); + Object errorCode = map.get("errorCode"); + pigeonResult.setErrorCode((String) errorCode); + Object description = map.get("description"); + pigeonResult.setDescription((String) description); + return pigeonResult; + } + } + public interface Result { void success(T result); @@ -445,6 +519,163 @@ public void create(@NonNull Long identifierArg, Reply callback) { } } + private static class SystemServicesHostApiCodec extends StandardMessageCodec { + public static final SystemServicesHostApiCodec INSTANCE = new SystemServicesHostApiCodec(); + + private SystemServicesHostApiCodec() {} + + @Override + protected Object readValueOfType(byte type, ByteBuffer buffer) { + switch (type) { + case (byte) 128: + return CameraPermissionsErrorData.fromMap((Map) readValue(buffer)); + + default: + return super.readValueOfType(type, buffer); + } + } + + @Override + protected void writeValue(ByteArrayOutputStream stream, Object value) { + if (value instanceof CameraPermissionsErrorData) { + stream.write(128); + writeValue(stream, ((CameraPermissionsErrorData) value).toMap()); + } else { + super.writeValue(stream, value); + } + } + } + + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ + public interface SystemServicesHostApi { + void requestCameraPermissions( + @NonNull Boolean enableAudio, Result result); + + void startListeningForDeviceOrientationChange( + @NonNull Boolean isFrontFacing, @NonNull Long sensorOrientation); + + /** The codec used by SystemServicesHostApi. */ + static MessageCodec getCodec() { + return SystemServicesHostApiCodec.INSTANCE; + } + + /** + * Sets up an instance of `SystemServicesHostApi` to handle messages through the + * `binaryMessenger`. + */ + static void setup(BinaryMessenger binaryMessenger, SystemServicesHostApi api) { + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Boolean enableAudioArg = (Boolean) args.get(0); + if (enableAudioArg == null) { + throw new NullPointerException("enableAudioArg unexpectedly null."); + } + Result resultCallback = + new Result() { + public void success(CameraPermissionsErrorData result) { + wrapped.put("result", result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + wrapped.put("error", wrapError(error)); + reply.reply(wrapped); + } + }; + + api.requestCameraPermissions(enableAudioArg, resultCallback); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + reply.reply(wrapped); + } + }); + } else { + channel.setMessageHandler(null); + } + } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Boolean isFrontFacingArg = (Boolean) args.get(0); + if (isFrontFacingArg == null) { + throw new NullPointerException("isFrontFacingArg unexpectedly null."); + } + Number sensorOrientationArg = (Number) args.get(1); + if (sensorOrientationArg == null) { + throw new NullPointerException("sensorOrientationArg unexpectedly null."); + } + api.startListeningForDeviceOrientationChange( + isFrontFacingArg, + (sensorOrientationArg == null) ? null : sensorOrientationArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } + } + } + + private static class SystemServicesFlutterApiCodec extends StandardMessageCodec { + public static final SystemServicesFlutterApiCodec INSTANCE = + new SystemServicesFlutterApiCodec(); + + private SystemServicesFlutterApiCodec() {} + } + + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ + public static class SystemServicesFlutterApi { + private final BinaryMessenger binaryMessenger; + + public SystemServicesFlutterApi(BinaryMessenger argBinaryMessenger) { + this.binaryMessenger = argBinaryMessenger; + } + + public interface Reply { + void reply(T reply); + } + + static MessageCodec getCodec() { + return SystemServicesFlutterApiCodec.INSTANCE; + } + + public void onDeviceOrientationChanged(@NonNull String orientationArg, Reply callback) { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.SystemServicesFlutterApi.onDeviceOrientationChanged", + getCodec()); + channel.send( + new ArrayList(Arrays.asList(orientationArg)), + channelReply -> { + callback.reply(null); + }); + } + } + private static Map wrapError(Throwable exception) { Map errorMap = new HashMap<>(); errorMap.put("message", exception.toString()); diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesFlutterApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesFlutterApiImpl.java index 06926f1a06ac..1e9f33b092bb 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesFlutterApiImpl.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesFlutterApiImpl.java @@ -16,11 +16,6 @@ public SystemServicesFlutterApiImpl( private final InstanceManager instanceManager; - public void onCameraPermissionsRequestResult( - String resultCode, String resultMessage, Reply reply) { - super.onCameraPermissionsRequestResult(resultCode, resultMessage, reply); - } - public void onDeviceOrientationChanged(String orientation, Reply reply) { super.onDeviceOrientationChanged(orientation, reply); } diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java index 6035ceef7a12..aa610a98ef18 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java @@ -5,8 +5,11 @@ package io.flutter.plugins.camerax; import android.app.Activity; +import io.flutter.embedding.engine.systemchannels.PlatformChannel.DeviceOrientation; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugins.camerax.CameraPermissionsManager.PermissionsRegistry; +import io.flutter.plugins.camerax.GeneratedCameraXLibrary.CameraPermissionsErrorData; +import io.flutter.plugins.camerax.GeneratedCameraXLibrary.Result; import io.flutter.plugins.camerax.GeneratedCameraXLibrary.SystemServicesHostApi; public class SystemServicesHostApiImpl implements SystemServicesHostApi { @@ -31,16 +34,24 @@ public void setPermissionsRegistry(PermissionsRegistry permissionsRegistry) { } @Override - public void requestCameraPermissions(Boolean enableAudio) { + public void requestCameraPermissions( + Boolean enableAudio, Result result) { CameraPermissionsManager cameraPermissionsManager = new CameraPermissionsManager(); cameraPermissionsManager.requestPermissions( activity, permissionsRegistry, enableAudio, - (String errorCode, String errDescription) -> { - final SystemServicesFlutterApiImpl api = - new SystemServicesFlutterApiImpl(binaryMessenger, instanceManager); - api.onCameraPermissionsRequestResult(errorCode, errDescription, reply -> {}); + (String errorCode, String description) -> { + if (errorCode == null) { + result.success(null); + } + // If permissions are ongoing or denied, error data will be sent to be handled. + CameraPermissionsErrorData errorData = + new CameraPermissionsErrorData.Builder() + .setErrorCode(errorCode) + .setDescription(description) + .build(); + result.success(errorData); }); } @@ -52,11 +63,16 @@ public void startListeningForDeviceOrientationChange( activity, isFrontFacing, sensorOrientation.intValue(), - (String newOrientation) -> { + (DeviceOrientation newOrientation) -> { final SystemServicesFlutterApiImpl api = new SystemServicesFlutterApiImpl(binaryMessenger, instanceManager); - api.onDeviceOrientationChanged(newOrientation, reply -> {}); + api.onDeviceOrientationChanged( + serializeDeviceOrientation(newOrientation), reply -> {}); }); deviceOrientationManager.start(); } -} \ No newline at end of file + + String serializeDeviceOrientation(DeviceOrientation orientation) { + return orientation.name(); + } +} diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/SystemServicesTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/SystemServicesTest.java new file mode 100644 index 000000000000..dc85387d5c2f --- /dev/null +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/SystemServicesTest.java @@ -0,0 +1 @@ +public class SystemServicesTest {} diff --git a/packages/camera/camera_android_camerax/lib/src/camerax_library.pigeon.dart b/packages/camera/camera_android_camerax/lib/src/camerax_library.pigeon.dart index c0b052378def..8f4c60e02b36 100644 --- a/packages/camera/camera_android_camerax/lib/src/camerax_library.pigeon.dart +++ b/packages/camera/camera_android_camerax/lib/src/camerax_library.pigeon.dart @@ -10,6 +10,31 @@ import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; import 'package:flutter/services.dart'; +class CameraPermissionsErrorData { + CameraPermissionsErrorData({ + required this.errorCode, + required this.description, + }); + + String errorCode; + String description; + + Object encode() { + final Map pigeonMap = {}; + pigeonMap['errorCode'] = errorCode; + pigeonMap['description'] = description; + return pigeonMap; + } + + static CameraPermissionsErrorData decode(Object message) { + final Map pigeonMap = message as Map; + return CameraPermissionsErrorData( + errorCode: pigeonMap['errorCode']! as String, + description: pigeonMap['description']! as String, + ); + } +} + class _JavaObjectHostApiCodec extends StandardMessageCodec { const _JavaObjectHostApiCodec(); } @@ -372,3 +397,125 @@ abstract class ProcessCameraProviderFlutterApi { } } } + +class _SystemServicesHostApiCodec extends StandardMessageCodec { + const _SystemServicesHostApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is CameraPermissionsErrorData) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return CameraPermissionsErrorData.decode(readValue(buffer)!); + + default: + return super.readValueOfType(type, buffer); + } + } +} + +class SystemServicesHostApi { + /// Constructor for [SystemServicesHostApi]. 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. + SystemServicesHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _SystemServicesHostApiCodec(); + + Future requestCameraPermissions( + bool arg_enableAudio) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_enableAudio]) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as CameraPermissionsErrorData?); + } + } + + Future startListeningForDeviceOrientationChange( + bool arg_isFrontFacing, int arg_sensorOrientation) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send([arg_isFrontFacing, arg_sensorOrientation]) + as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } +} + +class _SystemServicesFlutterApiCodec extends StandardMessageCodec { + const _SystemServicesFlutterApiCodec(); +} + +abstract class SystemServicesFlutterApi { + static const MessageCodec codec = _SystemServicesFlutterApiCodec(); + + void onDeviceOrientationChanged(String orientation); + static void setup(SystemServicesFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.SystemServicesFlutterApi.onDeviceOrientationChanged', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.SystemServicesFlutterApi.onDeviceOrientationChanged was null.'); + final List args = (message as List?)!; + final String? arg_orientation = (args[0] as String?); + assert(arg_orientation != null, + 'Argument for dev.flutter.pigeon.SystemServicesFlutterApi.onDeviceOrientationChanged was null, expected non-null String.'); + api.onDeviceOrientationChanged(arg_orientation!); + return; + }); + } + } + } +} diff --git a/packages/camera/camera_android_camerax/lib/src/system_services.dart b/packages/camera/camera_android_camerax/lib/src/system_services.dart index 4efed521175d..03f88da9c520 100644 --- a/packages/camera/camera_android_camerax/lib/src/system_services.dart +++ b/packages/camera/camera_android_camerax/lib/src/system_services.dart @@ -5,17 +5,15 @@ import 'dart:async'; import 'package:camera_platform_interface/camera_platform_interface.dart' - show DeviceOrientationChangedEvent; + show CameraException, DeviceOrientationChangedEvent; import 'package:flutter/services.dart'; import 'android_camera_camerax_flutter_api_impls.dart'; import 'camerax_library.pigeon.dart'; import 'instance_manager.dart'; import 'java_object.dart'; -import 'use_case.dart'; class SystemServices { - // TODO(camsim99): Change this to actually handle errors. static final StreamController cameraPermissionsStreamController = StreamController.broadcast(); @@ -23,18 +21,17 @@ class SystemServices { deviceOrientationChangedStreamController = StreamController.broadcast(); - static Future requestCameraPermissions(bool enableAudio, - {BinaryMessenger? binaryMessenger, InstanceManager? instanceManager}) { - AndroidCameraXCameraFlutterApis.instance.ensureSetUp(); - SystemServicesHostApiImpl api = SystemServicesHostApiImpl( - binaryMessenger: binaryMessenger, instanceManager: instanceManager); + static Future requestCameraPermissions(bool enableAudio, + {BinaryMessenger? binaryMessenger}) { + SystemServicesHostApiImpl api = + SystemServicesHostApiImpl(binaryMessenger: binaryMessenger); return api.requestCameraPermissionsFromInstance(enableAudio); } static void startListeningForDeviceOrientationChange( bool isFrontFacing, int sensorOrientation, - {BinaryMessenger? binaryMessenger, InstanceManager? instanceManager}) { + {BinaryMessenger? binaryMessenger}) { AndroidCameraXCameraFlutterApis.instance.ensureSetUp(); SystemServicesHostApi api = SystemServicesHostApi(binaryMessenger: binaryMessenger); @@ -47,11 +44,8 @@ class SystemServices { /// Host API implementation of [SystemServices]. class SystemServicesHostApiImpl extends SystemServicesHostApi { /// Creates a [SystemServicesHostApiImpl]. - SystemServicesHostApiImpl( - {this.binaryMessenger, InstanceManager? instanceManager}) - : super(binaryMessenger: binaryMessenger) { - this.instanceManager = instanceManager ?? JavaObject.globalInstanceManager; - } + SystemServicesHostApiImpl({this.binaryMessenger}) + : super(binaryMessenger: binaryMessenger) {} /// Receives binary data across the Flutter platform barrier. /// @@ -59,22 +53,16 @@ class SystemServicesHostApiImpl extends SystemServicesHostApi { /// the host platform. final BinaryMessenger? binaryMessenger; - /// Maintains instances stored to communicate with native language objects. - late final InstanceManager instanceManager; - - Future requestCameraPermissionsFromInstance(bool enableAudio) async { - requestCameraPermissions(enableAudio); + Future requestCameraPermissionsFromInstance(bool enableAudio) async { + CameraPermissionsErrorData? error = + await requestCameraPermissions(enableAudio); - try { - await for (final bool result - in SystemServices.cameraPermissionsStreamController.stream) { - return result; - } - } catch (e) { - // TODO(camsim99): Actually throw error here - return false; + if (error != null) { + throw CameraException( + error.errorCode, + error.description, + ); } - return false; } } @@ -83,8 +71,7 @@ class SystemServicesFlutterApiImpl implements SystemServicesFlutterApi { /// Constructs a [SystemServicesFlutterApiImpl]. SystemServicesFlutterApiImpl({ this.binaryMessenger, - InstanceManager? instanceManager, - }) : instanceManager = instanceManager ?? JavaObject.globalInstanceManager; + }); /// Receives binary data across the Flutter platform barrier. /// @@ -92,24 +79,10 @@ class SystemServicesFlutterApiImpl implements SystemServicesFlutterApi { /// the host platform. final BinaryMessenger? binaryMessenger; - /// Maintains instances stored to communicate with native language objects. - final InstanceManager instanceManager; - - @override - void onCameraPermissionsRequestResult( - String? errorCode, String? errorMessage) { - // TODO(camsim99): Expand on this to throw appropriate error. - bool result = false; - if (errorCode == null) { - result = true; - } - - SystemServices.cameraPermissionsStreamController.add(result); - } - @override void onDeviceOrientationChanged(String orientation) { - DeviceOrientation? deviceOrientation = getDeviceOrientation(orientation); + DeviceOrientation deviceOrientation = + deserializeDeviceOrientation(orientation); if (deviceOrientation == null) { return; } @@ -117,7 +90,7 @@ class SystemServicesFlutterApiImpl implements SystemServicesFlutterApi { .add(DeviceOrientationChangedEvent(deviceOrientation!)); } - DeviceOrientation? getDeviceOrientation(String orientation) { + DeviceOrientation deserializeDeviceOrientation(String orientation) { switch (orientation) { case 'LANDSCAPE_LEFT': return DeviceOrientation.landscapeLeft; @@ -128,7 +101,8 @@ class SystemServicesFlutterApiImpl implements SystemServicesFlutterApi { case 'PORTRAIT_UP': return DeviceOrientation.portraitUp; default: - return null; + throw ArgumentError( + '"$orientation" is not a valid DeviceOrientation value'); } } } diff --git a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart index 458bb671b3c0..3096ea1f0a8b 100644 --- a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart +++ b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart @@ -26,20 +26,14 @@ import 'package:pigeon/pigeon.dart'; ), ), ) - -// TODO(camsim99): delete test comment class CameraPermissionsErrorData { - CameraPermissionsErrorData(this.errorCode, this.description); - - String? errorCode; - String? description; -} + CameraPermissionsErrorData({ + required this.errorCode, + required this.description, + }); -enum DeviceOrientation { - landscapeLeft, - landscapeRight, - portraitDown, - portraitUp, + String errorCode; + String description; } @HostApi(dartHostTestHandler: 'TestJavaObjectHostApi') @@ -89,7 +83,8 @@ abstract class ProcessCameraProviderFlutterApi { @HostApi(dartHostTestHandler: 'TestSystemServicesHostApi') abstract class SystemServicesHostApi { - void requestCameraPermissions(bool enableAudio); + @async + CameraPermissionsErrorData? requestCameraPermissions(bool enableAudio); void startListeningForDeviceOrientationChange( bool isFrontFacing, int sensorOrientation); @@ -97,7 +92,5 @@ abstract class SystemServicesHostApi { @FlutterApi() abstract class SystemServicesFlutterApi { - void onCameraPermissionsRequestResult(CameraPermissionsErrorData? error); - - void onDeviceOrientationChanged(DeviceOrientation orientation); + void onDeviceOrientationChanged(String orientation); } diff --git a/packages/camera/camera_android_camerax/test/camera_info_test.mocks.dart b/packages/camera/camera_android_camerax/test/camera_info_test.mocks.dart index e1f1e3ca9e9b..63ec03c30083 100644 --- a/packages/camera/camera_android_camerax/test/camera_info_test.mocks.dart +++ b/packages/camera/camera_android_camerax/test/camera_info_test.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.3.0 from annotations +// Mocks generated by Mockito 5.3.2 from annotations // in camera_android_camerax/test/camera_info_test.dart. // Do not manually edit this file. @@ -29,6 +29,10 @@ class MockTestCameraInfoHostApi extends _i1.Mock @override int getSensorRotationDegrees(int? identifier) => (super.noSuchMethod( - Invocation.method(#getSensorRotationDegrees, [identifier]), - returnValue: 0) as int); + Invocation.method( + #getSensorRotationDegrees, + [identifier], + ), + returnValue: 0, + ) as int); } diff --git a/packages/camera/camera_android_camerax/test/camera_selector_test.mocks.dart b/packages/camera/camera_android_camerax/test/camera_selector_test.mocks.dart index 456db1eaf822..bb08c82514a5 100644 --- a/packages/camera/camera_android_camerax/test/camera_selector_test.mocks.dart +++ b/packages/camera/camera_android_camerax/test/camera_selector_test.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.3.0 from annotations +// Mocks generated by Mockito 5.3.2 from annotations // in camera_android_camerax/test/camera_selector_test.dart. // Do not manually edit this file. @@ -28,11 +28,33 @@ class MockTestCameraSelectorHostApi extends _i1.Mock } @override - void create(int? identifier, int? lensFacing) => - super.noSuchMethod(Invocation.method(#create, [identifier, lensFacing]), - returnValueForMissingStub: null); + void create( + int? identifier, + int? lensFacing, + ) => + super.noSuchMethod( + Invocation.method( + #create, + [ + identifier, + lensFacing, + ], + ), + returnValueForMissingStub: null, + ); @override - List filter(int? identifier, List? cameraInfoIds) => (super - .noSuchMethod(Invocation.method(#filter, [identifier, cameraInfoIds]), - returnValue: []) as List); + List filter( + int? identifier, + List? cameraInfoIds, + ) => + (super.noSuchMethod( + Invocation.method( + #filter, + [ + identifier, + cameraInfoIds, + ], + ), + returnValue: [], + ) as List); } diff --git a/packages/camera/camera_android_camerax/test/process_camera_provider_test.mocks.dart b/packages/camera/camera_android_camerax/test/process_camera_provider_test.mocks.dart index 9fcfe690c062..5e886b232775 100644 --- a/packages/camera/camera_android_camerax/test/process_camera_provider_test.mocks.dart +++ b/packages/camera/camera_android_camerax/test/process_camera_provider_test.mocks.dart @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.3.0 from annotations +// Mocks generated by Mockito 5.3.2 from annotations // in camera_android_camerax/test/process_camera_provider_test.dart. // Do not manually edit this file. @@ -30,11 +30,19 @@ class MockTestProcessCameraProviderHostApi extends _i1.Mock } @override - _i3.Future getInstance() => - (super.noSuchMethod(Invocation.method(#getInstance, []), - returnValue: _i3.Future.value(0)) as _i3.Future); + _i3.Future getInstance() => (super.noSuchMethod( + Invocation.method( + #getInstance, + [], + ), + returnValue: _i3.Future.value(0), + ) as _i3.Future); @override List getAvailableCameraInfos(int? identifier) => (super.noSuchMethod( - Invocation.method(#getAvailableCameraInfos, [identifier]), - returnValue: []) as List); + Invocation.method( + #getAvailableCameraInfos, + [identifier], + ), + returnValue: [], + ) as List); } diff --git a/packages/camera/camera_android_camerax/test/system_services_test.dart b/packages/camera/camera_android_camerax/test/system_services_test.dart new file mode 100644 index 000000000000..eae462f619cb --- /dev/null +++ b/packages/camera/camera_android_camerax/test/system_services_test.dart @@ -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. + +import 'package:camera_android_camerax/src/camerax_library.pigeon.dart' + show CameraPermissionsErrorData; +import 'package:camera_android_camerax/src/system_services.dart'; +import 'package:camera_platform_interface/camera_platform_interface.dart' + show CameraException, DeviceOrientationChangedEvent; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'system_services_test.mocks.dart'; +import 'test_camerax_library.pigeon.dart'; + +@GenerateMocks([TestSystemServicesHostApi]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + group('SystemServices', () { + tearDown(() => TestProcessCameraProviderHostApi.setup(null)); + + test( + 'requestCameraPermissionsFromInstance completes normally without errors test', + () async { + final MockTestSystemServicesHostApi mockApi = + MockTestSystemServicesHostApi(); + TestSystemServicesHostApi.setup(mockApi); + const bool enableAudio = true; + + when(mockApi.requestCameraPermissions(enableAudio)) + .thenAnswer((_) async => null); + + await SystemServices.requestCameraPermissions(enableAudio); + verify(mockApi.requestCameraPermissions(enableAudio)); + }); + + test( + 'requestCameraPermissionsFromInstance throws CameraException if there was a request error', + () { + final MockTestSystemServicesHostApi mockApi = + MockTestSystemServicesHostApi(); + TestSystemServicesHostApi.setup(mockApi); + const bool enableAudio = true; + final CameraPermissionsErrorData error = CameraPermissionsErrorData( + errorCode: 'Test error code', + description: 'Test error description', + ); + + when(mockApi.requestCameraPermissions(enableAudio)) + .thenAnswer((_) async => error); + + expect( + () async => SystemServices.requestCameraPermissions(enableAudio), + throwsA(isA() + .having((CameraException e) => e.code, 'code', 'Test error code') + .having((CameraException e) => e.description, 'description', + 'Test error description'))); + verify(mockApi.requestCameraPermissions(enableAudio)); + }); + + test('startListeningForDeviceOrientationChangeTest', () async { + final MockTestSystemServicesHostApi mockApi = + MockTestSystemServicesHostApi(); + TestSystemServicesHostApi.setup(mockApi); + const bool isFrontFacing = true; + const int sensorOrientation = 90; + + SystemServices.startListeningForDeviceOrientationChange( + isFrontFacing, sensorOrientation); + verify(mockApi.startListeningForDeviceOrientationChange( + isFrontFacing, sensorOrientation)); + }); + + test('onDeviceOrientationChanged adds new orientation to stream', () { + const String orientation = 'LANDSCAPE_LEFT'; + + SystemServices.deviceOrientationChangedStreamController.stream + .listen((DeviceOrientationChangedEvent event) { + expect(event.orientation, equals(DeviceOrientation.landscapeLeft)); + }); + SystemServicesFlutterApiImpl().onDeviceOrientationChanged(orientation); + }); + + test( + 'onDeviceOrientationChanged throws error if new orientation is invalid', + () { + const String orientation = 'FAKE_ORIENTATION'; + + expect( + () => SystemServicesFlutterApiImpl() + .onDeviceOrientationChanged(orientation), + throwsA(isA().having( + (ArgumentError e) => e.message, + 'message', + '"FAKE_ORIENTATION" is not a valid DeviceOrientation value'))); + }); + }); +} diff --git a/packages/camera/camera_android_camerax/test/system_services_test.mocks.dart b/packages/camera/camera_android_camerax/test/system_services_test.mocks.dart new file mode 100644 index 000000000000..429fde1f8bc1 --- /dev/null +++ b/packages/camera/camera_android_camerax/test/system_services_test.mocks.dart @@ -0,0 +1,58 @@ +// Mocks generated by Mockito 5.3.2 from annotations +// in camera_android_camerax/test/system_services_test.dart. +// Do not manually edit this file. + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; + +import 'package:camera_android_camerax/src/camerax_library.pigeon.dart' as _i4; +import 'package:mockito/mockito.dart' as _i1; + +import 'test_camerax_library.pigeon.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 [TestSystemServicesHostApi]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockTestSystemServicesHostApi extends _i1.Mock + implements _i2.TestSystemServicesHostApi { + MockTestSystemServicesHostApi() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Future<_i4.CameraPermissionsErrorData?> requestCameraPermissions( + bool? enableAudio) => + (super.noSuchMethod( + Invocation.method( + #requestCameraPermissions, + [enableAudio], + ), + returnValue: _i3.Future<_i4.CameraPermissionsErrorData?>.value(), + ) as _i3.Future<_i4.CameraPermissionsErrorData?>); + @override + void startListeningForDeviceOrientationChange( + bool? isFrontFacing, + int? sensorOrientation, + ) => + super.noSuchMethod( + Invocation.method( + #startListeningForDeviceOrientationChange, + [ + isFrontFacing, + sensorOrientation, + ], + ), + returnValueForMissingStub: null, + ); +} diff --git a/packages/camera/camera_android_camerax/test/test_camerax_library.pigeon.dart b/packages/camera/camera_android_camerax/test/test_camerax_library.pigeon.dart index 2196b73d7fdb..3f137f6e440e 100644 --- a/packages/camera/camera_android_camerax/test/test_camerax_library.pigeon.dart +++ b/packages/camera/camera_android_camerax/test/test_camerax_library.pigeon.dart @@ -185,3 +185,84 @@ abstract class TestProcessCameraProviderHostApi { } } } + +class _TestSystemServicesHostApiCodec extends StandardMessageCodec { + const _TestSystemServicesHostApiCodec(); + @override + void writeValue(WriteBuffer buffer, Object? value) { + if (value is CameraPermissionsErrorData) { + buffer.putUint8(128); + writeValue(buffer, value.encode()); + } else { + super.writeValue(buffer, value); + } + } + + @override + Object? readValueOfType(int type, ReadBuffer buffer) { + switch (type) { + case 128: + return CameraPermissionsErrorData.decode(readValue(buffer)!); + + default: + return super.readValueOfType(type, buffer); + } + } +} + +abstract class TestSystemServicesHostApi { + static const MessageCodec codec = _TestSystemServicesHostApiCodec(); + + Future requestCameraPermissions( + bool enableAudio); + void startListeningForDeviceOrientationChange( + bool isFrontFacing, int sensorOrientation); + static void setup(TestSystemServicesHostApi? api, + {BinaryMessenger? binaryMessenger}) { + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions was null.'); + final List args = (message as List?)!; + final bool? arg_enableAudio = (args[0] as bool?); + assert(arg_enableAudio != null, + 'Argument for dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions was null, expected non-null bool.'); + final CameraPermissionsErrorData? output = + await api.requestCameraPermissions(arg_enableAudio!); + return {'result': output}; + }); + } + } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange was null.'); + final List args = (message as List?)!; + final bool? arg_isFrontFacing = (args[0] as bool?); + assert(arg_isFrontFacing != null, + 'Argument for dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange was null, expected non-null bool.'); + final int? arg_sensorOrientation = (args[1] as int?); + assert(arg_sensorOrientation != null, + 'Argument for dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange was null, expected non-null int.'); + api.startListeningForDeviceOrientationChange( + arg_isFrontFacing!, arg_sensorOrientation!); + return {}; + }); + } + } + } +} From e552ef42d6f9297d916ca9c2808bc22697848f9c Mon Sep 17 00:00:00 2001 From: camsim99 Date: Tue, 17 Jan 2023 10:36:10 -0800 Subject: [PATCH 04/13] Add test files --- .../camerax/CameraPermissionsManagerTest.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraPermissionsManagerTest.java diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraPermissionsManagerTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraPermissionsManagerTest.java new file mode 100644 index 000000000000..bd3eb0fa70a8 --- /dev/null +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraPermissionsManagerTest.java @@ -0,0 +1,89 @@ +// 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 junit.framework.TestCase.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import android.content.pm.PackageManager; +import io.flutter.plugins.camerax.CameraPermissions.CameraRequestPermissionsListener; +import io.flutter.plugins.camerax.CameraPermissions.ResultCallback; +import org.junit.Test; + +public class CameraPermissionsTest { + @Test + public void listener_respondsOnce() { + final int[] calledCounter = {0}; + CameraRequestPermissionsListener permissionsListener = + new CameraRequestPermissionsListener((String code, String desc) -> calledCounter[0]++); + + permissionsListener.onRequestPermissionsResult( + 9796, null, new int[] {PackageManager.PERMISSION_DENIED}); + permissionsListener.onRequestPermissionsResult( + 9796, null, new int[] {PackageManager.PERMISSION_GRANTED}); + + assertEquals(1, calledCounter[0]); + } + + @Test + public void callback_respondsWithCameraAccessDenied() { + ResultCallback fakeResultCallback = mock(ResultCallback.class); + CameraRequestPermissionsListener permissionsListener = + new CameraRequestPermissionsListener(fakeResultCallback); + + permissionsListener.onRequestPermissionsResult( + 9796, null, new int[] {PackageManager.PERMISSION_DENIED}); + + verify(fakeResultCallback) + .onResult("CameraAccessDenied", "Camera access permission was denied."); + } + + @Test + public void callback_respondsWithAudioAccessDenied() { + ResultCallback fakeResultCallback = mock(ResultCallback.class); + CameraRequestPermissionsListener permissionsListener = + new CameraRequestPermissionsListener(fakeResultCallback); + + permissionsListener.onRequestPermissionsResult( + 9796, + null, + new int[] {PackageManager.PERMISSION_GRANTED, PackageManager.PERMISSION_DENIED}); + + verify(fakeResultCallback).onResult("AudioAccessDenied", "Audio access permission was denied."); + } + + @Test + public void callback_doesNotRespond() { + ResultCallback fakeResultCallback = mock(ResultCallback.class); + CameraRequestPermissionsListener permissionsListener = + new CameraRequestPermissionsListener(fakeResultCallback); + + permissionsListener.onRequestPermissionsResult( + 9796, + null, + new int[] {PackageManager.PERMISSION_GRANTED, PackageManager.PERMISSION_GRANTED}); + + verify(fakeResultCallback, never()) + .onResult("CameraAccessDenied", "Camera access permission was denied."); + verify(fakeResultCallback, never()) + .onResult("AudioAccessDenied", "Audio access permission was denied."); + } + + @Test + public void callback_respondsWithCameraAccessDeniedWhenEmptyResult() { + // Handles the case where the grantResults array is empty + + ResultCallback fakeResultCallback = mock(ResultCallback.class); + CameraRequestPermissionsListener permissionsListener = + new CameraRequestPermissionsListener(fakeResultCallback); + + permissionsListener.onRequestPermissionsResult(9796, null, new int[] {}); + + verify(fakeResultCallback) + .onResult("CameraAccessDenied", "Camera access permission was denied."); + } +} From b1e00b1b2763a3d73b84f57064de40bb46e298a5 Mon Sep 17 00:00:00 2001 From: camsim99 Date: Tue, 17 Jan 2023 14:53:00 -0800 Subject: [PATCH 05/13] Add java tests --- .../camerax/CameraPermissionsManager.java | 4 +- .../flutter/plugins/camerax/CameraXProxy.java | 13 + .../camerax/SystemServicesHostApiImpl.java | 36 +- .../camerax/CameraPermissionsManagerTest.java | 6 +- .../camerax/DeviceOrientationManagerTest.java | 313 ++++++++++++++++++ .../plugins/camerax/SystemServicesTest.java | 138 +++++++- 6 files changed, 492 insertions(+), 18 deletions(-) create mode 100644 packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/DeviceOrientationManagerTest.java diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraPermissionsManager.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraPermissionsManager.java index 230f3fdc4f44..19b1ee569a9b 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraPermissionsManager.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraPermissionsManager.java @@ -105,7 +105,9 @@ public boolean onRequestPermissionsResult(int id, String[] permissions, int[] gr } alreadyCalled = true; - if (grantResults[0] != PackageManager.PERMISSION_GRANTED) { + // grantResults could be empty if the permissions request with the user is interrupted + // https://developer.android.com/reference/android/app/Activity#onRequestPermissionsResult(int,%20java.lang.String[],%20int[]) + if (grantResults.length == 0 || grantResults[0] != PackageManager.PERMISSION_GRANTED) { callback.onResult(CAMERA_ACCESS_DENIED, CAMERA_ACCESS_DENIED_MESSAGE); } else if (grantResults.length > 1 && grantResults[1] != PackageManager.PERMISSION_GRANTED) { callback.onResult(AUDIO_ACCESS_DENIED, AUDIO_ACCESS_DENIED_MESSAGE); diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraXProxy.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraXProxy.java index 8063866d2fc6..83c43a9d55d4 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraXProxy.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraXProxy.java @@ -4,10 +4,23 @@ package io.flutter.plugins.camerax; +import android.app.Activity; import androidx.camera.core.CameraSelector; public class CameraXProxy { public CameraSelector.Builder createCameraSelectorBuilder() { return new CameraSelector.Builder(); } + + public CameraPermissionsManager createCameraPermissionsManager() { + return new CameraPermissionsManager(); + } + + public DeviceOrientationManager createDeviceOrientationManager( + Activity activity, + Boolean isFrontFacing, + int sensorOrientation, + DeviceOrientationManager.DeviceOrientationChangeCallback callback) { + return new DeviceOrientationManager(activity, isFrontFacing, sensorOrientation, callback); + } } diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java index aa610a98ef18..2240a7b4fd20 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java @@ -5,6 +5,7 @@ package io.flutter.plugins.camerax; import android.app.Activity; +import androidx.annotation.VisibleForTesting; import io.flutter.embedding.engine.systemchannels.PlatformChannel.DeviceOrientation; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugins.camerax.CameraPermissionsManager.PermissionsRegistry; @@ -16,6 +17,9 @@ public class SystemServicesHostApiImpl implements SystemServicesHostApi { private final BinaryMessenger binaryMessenger; private final InstanceManager instanceManager; + @VisibleForTesting public CameraXProxy cameraXProxy = new CameraXProxy(); + @VisibleForTesting public SystemServicesFlutterApiImpl systemServicesFlutterApi; + private Activity activity; private PermissionsRegistry permissionsRegistry; @@ -23,6 +27,8 @@ public SystemServicesHostApiImpl( BinaryMessenger binaryMessenger, InstanceManager instanceManager) { this.binaryMessenger = binaryMessenger; this.instanceManager = instanceManager; + this.systemServicesFlutterApi = + new SystemServicesFlutterApiImpl(binaryMessenger, instanceManager); } public void setActivity(Activity activity) { @@ -36,7 +42,8 @@ public void setPermissionsRegistry(PermissionsRegistry permissionsRegistry) { @Override public void requestCameraPermissions( Boolean enableAudio, Result result) { - CameraPermissionsManager cameraPermissionsManager = new CameraPermissionsManager(); + CameraPermissionsManager cameraPermissionsManager = + cameraXProxy.createCameraPermissionsManager(); cameraPermissionsManager.requestPermissions( activity, permissionsRegistry, @@ -44,14 +51,15 @@ public void requestCameraPermissions( (String errorCode, String description) -> { if (errorCode == null) { result.success(null); + } else { + // If permissions are ongoing or denied, error data will be sent to be handled. + CameraPermissionsErrorData errorData = + new CameraPermissionsErrorData.Builder() + .setErrorCode(errorCode) + .setDescription(description) + .build(); + result.success(errorData); } - // If permissions are ongoing or denied, error data will be sent to be handled. - CameraPermissionsErrorData errorData = - new CameraPermissionsErrorData.Builder() - .setErrorCode(errorCode) - .setDescription(description) - .build(); - result.success(errorData); }); } @@ -59,20 +67,22 @@ public void requestCameraPermissions( public void startListeningForDeviceOrientationChange( Boolean isFrontFacing, Long sensorOrientation) { DeviceOrientationManager deviceOrientationManager = - new DeviceOrientationManager( + cameraXProxy.createDeviceOrientationManager( activity, isFrontFacing, sensorOrientation.intValue(), (DeviceOrientation newOrientation) -> { - final SystemServicesFlutterApiImpl api = - new SystemServicesFlutterApiImpl(binaryMessenger, instanceManager); - api.onDeviceOrientationChanged( + systemServicesFlutterApi.onDeviceOrientationChanged( serializeDeviceOrientation(newOrientation), reply -> {}); }); deviceOrientationManager.start(); } + /** + * Helper method for serializing a {@code DeviceOrientation} into a String that the Dart side is + * able to recognize. + */ String serializeDeviceOrientation(DeviceOrientation orientation) { - return orientation.name(); + return orientation.toString(); } } diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraPermissionsManagerTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraPermissionsManagerTest.java index bd3eb0fa70a8..d90bde953306 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraPermissionsManagerTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/CameraPermissionsManagerTest.java @@ -10,11 +10,11 @@ import static org.mockito.Mockito.verify; import android.content.pm.PackageManager; -import io.flutter.plugins.camerax.CameraPermissions.CameraRequestPermissionsListener; -import io.flutter.plugins.camerax.CameraPermissions.ResultCallback; +import io.flutter.plugins.camerax.CameraPermissionsManager.CameraRequestPermissionsListener; +import io.flutter.plugins.camerax.CameraPermissionsManager.ResultCallback; import org.junit.Test; -public class CameraPermissionsTest { +public class CameraPermissionsManagerTest { @Test public void listener_respondsOnce() { final int[] calledCounter = {0}; diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/DeviceOrientationManagerTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/DeviceOrientationManagerTest.java new file mode 100644 index 000000000000..1e2bfba714c7 --- /dev/null +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/DeviceOrientationManagerTest.java @@ -0,0 +1,313 @@ +// 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.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Configuration; +import android.content.res.Resources; +import android.provider.Settings; +import android.view.Display; +import android.view.Surface; +import android.view.WindowManager; +import io.flutter.embedding.engine.systemchannels.PlatformChannel.DeviceOrientation; +import io.flutter.plugins.camerax.DeviceOrientationManager.DeviceOrientationChangeCallback; +import org.junit.Before; +import org.junit.Test; +import org.mockito.MockedStatic; + +public class DeviceOrientationManagerTest { + private Activity mockActivity; + private DeviceOrientationChangeCallback mockDeviceOrientationChangeCallback; + private WindowManager mockWindowManager; + private Display mockDisplay; + private DeviceOrientationManager deviceOrientationManager; + + @Before + @SuppressWarnings("deprecation") + public void before() { + mockActivity = mock(Activity.class); + mockDisplay = mock(Display.class); + mockWindowManager = mock(WindowManager.class); + mockDeviceOrientationChangeCallback = mock(DeviceOrientationChangeCallback.class); + + when(mockActivity.getSystemService(Context.WINDOW_SERVICE)).thenReturn(mockWindowManager); + when(mockWindowManager.getDefaultDisplay()).thenReturn(mockDisplay); + + deviceOrientationManager = + new DeviceOrientationManager(mockActivity, false, 0, mockDeviceOrientationChangeCallback); + } + + @Test + public void getVideoOrientation_whenNaturalScreenOrientationEqualsPortraitUp() { + int degreesPortraitUp = + deviceOrientationManager.getVideoOrientation(DeviceOrientation.PORTRAIT_UP); + int degreesPortraitDown = + deviceOrientationManager.getVideoOrientation(DeviceOrientation.PORTRAIT_DOWN); + int degreesLandscapeLeft = + deviceOrientationManager.getVideoOrientation(DeviceOrientation.LANDSCAPE_LEFT); + int degreesLandscapeRight = + deviceOrientationManager.getVideoOrientation(DeviceOrientation.LANDSCAPE_RIGHT); + + assertEquals(0, degreesPortraitUp); + assertEquals(270, degreesLandscapeLeft); + assertEquals(180, degreesPortraitDown); + assertEquals(90, degreesLandscapeRight); + } + + @Test + public void getVideoOrientation_whenNaturalScreenOrientationEqualsLandscapeLeft() { + DeviceOrientationManager orientationManager = + new DeviceOrientationManager(mockActivity, false, 90, mockDeviceOrientationChangeCallback); + + int degreesPortraitUp = orientationManager.getVideoOrientation(DeviceOrientation.PORTRAIT_UP); + int degreesPortraitDown = + orientationManager.getVideoOrientation(DeviceOrientation.PORTRAIT_DOWN); + int degreesLandscapeLeft = + orientationManager.getVideoOrientation(DeviceOrientation.LANDSCAPE_LEFT); + int degreesLandscapeRight = + orientationManager.getVideoOrientation(DeviceOrientation.LANDSCAPE_RIGHT); + + assertEquals(90, degreesPortraitUp); + assertEquals(0, degreesLandscapeLeft); + assertEquals(270, degreesPortraitDown); + assertEquals(180, degreesLandscapeRight); + } + + @Test + public void getVideoOrientation_fallbackToPortraitSensorOrientationWhenOrientationIsNull() { + setUpUIOrientationMocks(Configuration.ORIENTATION_PORTRAIT, Surface.ROTATION_0); + + int degrees = deviceOrientationManager.getVideoOrientation(null); + + assertEquals(0, degrees); + } + + @Test + public void getVideoOrientation_fallbackToLandscapeSensorOrientationWhenOrientationIsNull() { + setUpUIOrientationMocks(Configuration.ORIENTATION_LANDSCAPE, Surface.ROTATION_0); + + DeviceOrientationManager orientationManager = + new DeviceOrientationManager(mockActivity, false, 90, mockDeviceOrientationChangeCallback); + + int degrees = orientationManager.getVideoOrientation(null); + + assertEquals(0, degrees); + } + + @Test + public void getPhotoOrientation_whenNaturalScreenOrientationEqualsPortraitUp() { + int degreesPortraitUp = + deviceOrientationManager.getPhotoOrientation(DeviceOrientation.PORTRAIT_UP); + int degreesPortraitDown = + deviceOrientationManager.getPhotoOrientation(DeviceOrientation.PORTRAIT_DOWN); + int degreesLandscapeLeft = + deviceOrientationManager.getPhotoOrientation(DeviceOrientation.LANDSCAPE_LEFT); + int degreesLandscapeRight = + deviceOrientationManager.getPhotoOrientation(DeviceOrientation.LANDSCAPE_RIGHT); + + assertEquals(0, degreesPortraitUp); + assertEquals(90, degreesLandscapeRight); + assertEquals(180, degreesPortraitDown); + assertEquals(270, degreesLandscapeLeft); + } + + @Test + public void getPhotoOrientation_whenNaturalScreenOrientationEqualsLandscapeLeft() { + DeviceOrientationManager orientationManager = + new DeviceOrientationManager(mockActivity, false, 90, mockDeviceOrientationChangeCallback); + + int degreesPortraitUp = orientationManager.getPhotoOrientation(DeviceOrientation.PORTRAIT_UP); + int degreesPortraitDown = + orientationManager.getPhotoOrientation(DeviceOrientation.PORTRAIT_DOWN); + int degreesLandscapeLeft = + orientationManager.getPhotoOrientation(DeviceOrientation.LANDSCAPE_LEFT); + int degreesLandscapeRight = + orientationManager.getPhotoOrientation(DeviceOrientation.LANDSCAPE_RIGHT); + + assertEquals(90, degreesPortraitUp); + assertEquals(180, degreesLandscapeRight); + assertEquals(270, degreesPortraitDown); + assertEquals(0, degreesLandscapeLeft); + } + + @Test + public void getPhotoOrientation_shouldFallbackToCurrentOrientationWhenOrientationIsNull() { + setUpUIOrientationMocks(Configuration.ORIENTATION_LANDSCAPE, Surface.ROTATION_0); + + int degrees = deviceOrientationManager.getPhotoOrientation(null); + + assertEquals(270, degrees); + } + + @Test + public void handleUIOrientationChange_shouldSendMessageWhenSensorAccessIsAllowed() { + try (MockedStatic mockedSystem = mockStatic(Settings.System.class)) { + mockedSystem + .when( + () -> + Settings.System.getInt(any(), eq(Settings.System.ACCELEROMETER_ROTATION), eq(0))) + .thenReturn(0); + setUpUIOrientationMocks(Configuration.ORIENTATION_LANDSCAPE, Surface.ROTATION_0); + + deviceOrientationManager.handleUIOrientationChange(); + } + + verify(mockDeviceOrientationChangeCallback, times(1)) + .onChange(DeviceOrientation.LANDSCAPE_LEFT); + } + + @Test + public void handleOrientationChange_shouldSendMessageWhenOrientationIsUpdated() { + DeviceOrientation previousOrientation = DeviceOrientation.PORTRAIT_UP; + DeviceOrientation newOrientation = DeviceOrientation.LANDSCAPE_LEFT; + + DeviceOrientationManager.handleOrientationChange( + newOrientation, previousOrientation, mockDeviceOrientationChangeCallback); + + verify(mockDeviceOrientationChangeCallback, times(1)).onChange(newOrientation); + } + + @Test + public void handleOrientationChange_shouldNotSendMessageWhenOrientationIsNotUpdated() { + DeviceOrientation previousOrientation = DeviceOrientation.PORTRAIT_UP; + DeviceOrientation newOrientation = DeviceOrientation.PORTRAIT_UP; + + DeviceOrientationManager.handleOrientationChange( + newOrientation, previousOrientation, mockDeviceOrientationChangeCallback); + + verify(mockDeviceOrientationChangeCallback, never()).onChange(any()); + } + + @Test + public void getUIOrientation() { + // Orientation portrait and rotation of 0 should translate to "PORTRAIT_UP". + setUpUIOrientationMocks(Configuration.ORIENTATION_PORTRAIT, Surface.ROTATION_0); + DeviceOrientation uiOrientation = deviceOrientationManager.getUIOrientation(); + assertEquals(DeviceOrientation.PORTRAIT_UP, uiOrientation); + + // Orientation portrait and rotation of 90 should translate to "PORTRAIT_UP". + setUpUIOrientationMocks(Configuration.ORIENTATION_PORTRAIT, Surface.ROTATION_90); + uiOrientation = deviceOrientationManager.getUIOrientation(); + assertEquals(DeviceOrientation.PORTRAIT_UP, uiOrientation); + + // Orientation portrait and rotation of 180 should translate to "PORTRAIT_DOWN". + setUpUIOrientationMocks(Configuration.ORIENTATION_PORTRAIT, Surface.ROTATION_180); + uiOrientation = deviceOrientationManager.getUIOrientation(); + assertEquals(DeviceOrientation.PORTRAIT_DOWN, uiOrientation); + + // Orientation portrait and rotation of 270 should translate to "PORTRAIT_DOWN". + setUpUIOrientationMocks(Configuration.ORIENTATION_PORTRAIT, Surface.ROTATION_270); + uiOrientation = deviceOrientationManager.getUIOrientation(); + assertEquals(DeviceOrientation.PORTRAIT_DOWN, uiOrientation); + + // Orientation landscape and rotation of 0 should translate to "LANDSCAPE_LEFT". + setUpUIOrientationMocks(Configuration.ORIENTATION_LANDSCAPE, Surface.ROTATION_0); + uiOrientation = deviceOrientationManager.getUIOrientation(); + assertEquals(DeviceOrientation.LANDSCAPE_LEFT, uiOrientation); + + // Orientation landscape and rotation of 90 should translate to "LANDSCAPE_LEFT". + setUpUIOrientationMocks(Configuration.ORIENTATION_LANDSCAPE, Surface.ROTATION_90); + uiOrientation = deviceOrientationManager.getUIOrientation(); + assertEquals(DeviceOrientation.LANDSCAPE_LEFT, uiOrientation); + + // Orientation landscape and rotation of 180 should translate to "LANDSCAPE_RIGHT". + setUpUIOrientationMocks(Configuration.ORIENTATION_LANDSCAPE, Surface.ROTATION_180); + uiOrientation = deviceOrientationManager.getUIOrientation(); + assertEquals(DeviceOrientation.LANDSCAPE_RIGHT, uiOrientation); + + // Orientation landscape and rotation of 270 should translate to "LANDSCAPE_RIGHT". + setUpUIOrientationMocks(Configuration.ORIENTATION_LANDSCAPE, Surface.ROTATION_270); + uiOrientation = deviceOrientationManager.getUIOrientation(); + assertEquals(DeviceOrientation.LANDSCAPE_RIGHT, uiOrientation); + + // Orientation undefined should default to "PORTRAIT_UP". + setUpUIOrientationMocks(Configuration.ORIENTATION_UNDEFINED, Surface.ROTATION_0); + uiOrientation = deviceOrientationManager.getUIOrientation(); + assertEquals(DeviceOrientation.PORTRAIT_UP, uiOrientation); + } + + @Test + public void getDeviceDefaultOrientation() { + setUpUIOrientationMocks(Configuration.ORIENTATION_PORTRAIT, Surface.ROTATION_0); + int orientation = deviceOrientationManager.getDeviceDefaultOrientation(); + assertEquals(Configuration.ORIENTATION_PORTRAIT, orientation); + + setUpUIOrientationMocks(Configuration.ORIENTATION_PORTRAIT, Surface.ROTATION_180); + orientation = deviceOrientationManager.getDeviceDefaultOrientation(); + assertEquals(Configuration.ORIENTATION_PORTRAIT, orientation); + + setUpUIOrientationMocks(Configuration.ORIENTATION_PORTRAIT, Surface.ROTATION_90); + orientation = deviceOrientationManager.getDeviceDefaultOrientation(); + assertEquals(Configuration.ORIENTATION_LANDSCAPE, orientation); + + setUpUIOrientationMocks(Configuration.ORIENTATION_PORTRAIT, Surface.ROTATION_270); + orientation = deviceOrientationManager.getDeviceDefaultOrientation(); + assertEquals(Configuration.ORIENTATION_LANDSCAPE, orientation); + + setUpUIOrientationMocks(Configuration.ORIENTATION_LANDSCAPE, Surface.ROTATION_0); + orientation = deviceOrientationManager.getDeviceDefaultOrientation(); + assertEquals(Configuration.ORIENTATION_LANDSCAPE, orientation); + + setUpUIOrientationMocks(Configuration.ORIENTATION_LANDSCAPE, Surface.ROTATION_180); + orientation = deviceOrientationManager.getDeviceDefaultOrientation(); + assertEquals(Configuration.ORIENTATION_LANDSCAPE, orientation); + + setUpUIOrientationMocks(Configuration.ORIENTATION_LANDSCAPE, Surface.ROTATION_90); + orientation = deviceOrientationManager.getDeviceDefaultOrientation(); + assertEquals(Configuration.ORIENTATION_PORTRAIT, orientation); + + setUpUIOrientationMocks(Configuration.ORIENTATION_LANDSCAPE, Surface.ROTATION_270); + orientation = deviceOrientationManager.getDeviceDefaultOrientation(); + assertEquals(Configuration.ORIENTATION_PORTRAIT, orientation); + } + + @Test + public void calculateSensorOrientation() { + setUpUIOrientationMocks(Configuration.ORIENTATION_PORTRAIT, Surface.ROTATION_0); + DeviceOrientation orientation = deviceOrientationManager.calculateSensorOrientation(0); + assertEquals(DeviceOrientation.PORTRAIT_UP, orientation); + + setUpUIOrientationMocks(Configuration.ORIENTATION_PORTRAIT, Surface.ROTATION_0); + orientation = deviceOrientationManager.calculateSensorOrientation(90); + assertEquals(DeviceOrientation.LANDSCAPE_LEFT, orientation); + + setUpUIOrientationMocks(Configuration.ORIENTATION_PORTRAIT, Surface.ROTATION_0); + orientation = deviceOrientationManager.calculateSensorOrientation(180); + assertEquals(DeviceOrientation.PORTRAIT_DOWN, orientation); + + setUpUIOrientationMocks(Configuration.ORIENTATION_PORTRAIT, Surface.ROTATION_0); + orientation = deviceOrientationManager.calculateSensorOrientation(270); + assertEquals(DeviceOrientation.LANDSCAPE_RIGHT, orientation); + } + + private void setUpUIOrientationMocks(int orientation, int rotation) { + Resources mockResources = mock(Resources.class); + Configuration mockConfiguration = mock(Configuration.class); + + when(mockDisplay.getRotation()).thenReturn(rotation); + + mockConfiguration.orientation = orientation; + when(mockActivity.getResources()).thenReturn(mockResources); + when(mockResources.getConfiguration()).thenReturn(mockConfiguration); + } + + @Test + public void getDisplayTest() { + Display display = deviceOrientationManager.getDisplay(); + + assertEquals(mockDisplay, display); + } +} diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/SystemServicesTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/SystemServicesTest.java index dc85387d5c2f..d90c2633271c 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/SystemServicesTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/SystemServicesTest.java @@ -1 +1,137 @@ -public class SystemServicesTest {} +// 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.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.Activity; +import io.flutter.embedding.engine.systemchannels.PlatformChannel.DeviceOrientation; +import io.flutter.plugin.common.BinaryMessenger; +import io.flutter.plugins.camerax.CameraPermissionsManager.PermissionsRegistry; +import io.flutter.plugins.camerax.CameraPermissionsManager.ResultCallback; +import io.flutter.plugins.camerax.DeviceOrientationManager.DeviceOrientationChangeCallback; +import io.flutter.plugins.camerax.GeneratedCameraXLibrary.CameraPermissionsErrorData; +import io.flutter.plugins.camerax.GeneratedCameraXLibrary.Result; +import io.flutter.plugins.camerax.GeneratedCameraXLibrary.SystemServicesFlutterApi.Reply; +import org.junit.Rule; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; + +public class SystemServicesTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + + @Mock public BinaryMessenger mockBinaryMessenger; + @Mock public InstanceManager mockInstanceManager; + + @Test + public void requestCameraPermissionsTest() { + final SystemServicesHostApiImpl systemServicesHostApi = + new SystemServicesHostApiImpl(mockBinaryMessenger, mockInstanceManager); + final CameraXProxy mockCameraXProxy = mock(CameraXProxy.class); + final CameraPermissionsManager mockCameraPermissionsManager = + mock(CameraPermissionsManager.class); + final Activity mockActivity = mock(Activity.class); + final PermissionsRegistry mockPermissionsRegistry = mock(PermissionsRegistry.class); + final Result mockResult = mock(Result.class); + final Boolean enableAudio = false; + + systemServicesHostApi.cameraXProxy = mockCameraXProxy; + systemServicesHostApi.setActivity(mockActivity); + systemServicesHostApi.setPermissionsRegistry(mockPermissionsRegistry); + when(mockCameraXProxy.createCameraPermissionsManager()) + .thenReturn(mockCameraPermissionsManager); + + final ArgumentCaptor resultCallbackCaptor = + ArgumentCaptor.forClass(ResultCallback.class); + + systemServicesHostApi.requestCameraPermissions(enableAudio, mockResult); + + // Test camera permissions are requested. + verify(mockCameraPermissionsManager) + .requestPermissions( + eq(mockActivity), + eq(mockPermissionsRegistry), + eq(enableAudio), + resultCallbackCaptor.capture()); + + ResultCallback resultCallback = (ResultCallback) resultCallbackCaptor.getValue(); + + // Test no error data is sent upon permissions request success. + resultCallback.onResult(null, null); + verify(mockResult).success(null); + + // Test expected error data is sent upon permissions request failure. + final String testErrorCode = "TestErrorCode"; + final String testErrorDescription = "Test error description."; + + final ArgumentCaptor cameraPermissionsErrorDataCaptor = + ArgumentCaptor.forClass(CameraPermissionsErrorData.class); + + resultCallback.onResult(testErrorCode, testErrorDescription); + verify(mockResult, times(2)).success(cameraPermissionsErrorDataCaptor.capture()); + + CameraPermissionsErrorData cameraPermissionsErrorData = + cameraPermissionsErrorDataCaptor.getValue(); + assertEquals(cameraPermissionsErrorData.getErrorCode(), testErrorCode); + assertEquals(cameraPermissionsErrorData.getDescription(), testErrorDescription); + } + + @Test + public void deviceOrientationChangeTest() { + final SystemServicesHostApiImpl systemServicesHostApi = + new SystemServicesHostApiImpl(mockBinaryMessenger, mockInstanceManager); + final CameraXProxy mockCameraXProxy = mock(CameraXProxy.class); + final Activity mockActivity = mock(Activity.class); + final DeviceOrientationManager mockDeviceOrientationManager = + mock(DeviceOrientationManager.class); + final Boolean isFrontFacing = true; + final int sensorOrientation = 90; + + SystemServicesFlutterApiImpl systemServicesFlutterApi = + mock(SystemServicesFlutterApiImpl.class); + systemServicesHostApi.systemServicesFlutterApi = systemServicesFlutterApi; + + systemServicesHostApi.cameraXProxy = mockCameraXProxy; + systemServicesHostApi.setActivity(mockActivity); + when(mockCameraXProxy.createDeviceOrientationManager( + eq(mockActivity), + eq(isFrontFacing), + eq(sensorOrientation), + any(DeviceOrientationChangeCallback.class))) + .thenReturn(mockDeviceOrientationManager); + + final ArgumentCaptor deviceOrientationChangeCallbackCaptor = + ArgumentCaptor.forClass(DeviceOrientationChangeCallback.class); + + systemServicesHostApi.startListeningForDeviceOrientationChange( + isFrontFacing, Long.valueOf(sensorOrientation)); + + // Test callback method defined in Flutter API is called when device orientation changes. + verify(mockCameraXProxy) + .createDeviceOrientationManager( + eq(mockActivity), + eq(isFrontFacing), + eq(sensorOrientation), + deviceOrientationChangeCallbackCaptor.capture()); + DeviceOrientationChangeCallback deviceOrientationChangeCallback = + deviceOrientationChangeCallbackCaptor.getValue(); + + deviceOrientationChangeCallback.onChange(DeviceOrientation.PORTRAIT_DOWN); + verify(systemServicesFlutterApi) + .onDeviceOrientationChanged(eq("PORTRAIT_DOWN"), any(Reply.class)); + + // Test that the DeviceOrientationManager starts listening for device orientation changes. + verify(mockDeviceOrientationManager).start(); + } +} From 15914af111c9b0058f3b4d32630d48cc871f5bee Mon Sep 17 00:00:00 2001 From: camsim99 Date: Tue, 17 Jan 2023 15:19:48 -0800 Subject: [PATCH 06/13] Add docs --- .../camerax/DeviceOrientationManager.java | 7 +++--- .../camerax/SystemServicesHostApiImpl.java | 13 +++++++++++ .../lib/src/instance_manager.dart | 23 +++++++++++-------- .../lib/src/system_services.dart | 20 ++++++++++++---- 4 files changed, 45 insertions(+), 18 deletions(-) diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/DeviceOrientationManager.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/DeviceOrientationManager.java index 752b802e66db..ebcb86433f65 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/DeviceOrientationManager.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/DeviceOrientationManager.java @@ -48,13 +48,12 @@ interface DeviceOrientationChangeCallback { this.deviceOrientationChangeCallback = callback; } - // TODO(camsim99): Fix docs. /** * Starts listening to the device's sensors or UI for orientation updates. * - *

When orientation information is updated the new orientation is send to the client using the - * {@link DartMessenger}. This latest value can also be retrieved through the {@link - * #getVideoOrientation()} accessor. + *

When orientation information is updated, the callback method of the {@link + * DeviceOrientationChangeCallback} is called with the new orientation. This latest value can also + * be retrieved through the {@link #getVideoOrientation()} accessor. * *

If the device's ACCELEROMETER_ROTATION setting is enabled the {@link * DeviceOrientationManager} will report orientation updates based on the sensor information. If diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java index 2240a7b4fd20..47883aa2fc57 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java @@ -39,6 +39,12 @@ public void setPermissionsRegistry(PermissionsRegistry permissionsRegistry) { this.permissionsRegistry = permissionsRegistry; } + /** + * Requests camera permissions using an instance of a {@link CameraPermissionsManager}. + * + *

Will result with {@code null} if permissions were approved or there were no errors; + * otherwise, it will result with the error data explaining what went wrong. + */ @Override public void requestCameraPermissions( Boolean enableAudio, Result result) { @@ -63,6 +69,13 @@ public void requestCameraPermissions( }); } + /** + * Starts listening for device orientation changes using an instace of a {@link + * DeviceOrientationManager}. + * + *

Whenever a change in device orientation is detected by the {@code DeviceOrientationManager}, + * the {@link SystemServicesFlutterApi} will be used to notify the Dart side. + */ @Override public void startListeningForDeviceOrientationChange( Boolean isFrontFacing, Long sensorOrientation) { diff --git a/packages/camera/camera_android_camerax/lib/src/instance_manager.dart b/packages/camera/camera_android_camerax/lib/src/instance_manager.dart index 0eddd64cbc13..8c6081c855ba 100644 --- a/packages/camera/camera_android_camerax/lib/src/instance_manager.dart +++ b/packages/camera/camera_android_camerax/lib/src/instance_manager.dart @@ -124,22 +124,26 @@ class InstanceManager { /// This method also expects the host `InstanceManager` to have a strong /// reference to the instance the identifier is associated with. T? getInstanceWithWeakReference(int identifier) { - final Object? weakInstance = _weakInstances[identifier]?.target; + final T? weakInstance = _weakInstances[identifier]?.target as T?; if (weakInstance == null) { - final Object? strongInstance = _strongInstances[identifier]; + final T? strongInstance = _strongInstances[identifier] as T?; if (strongInstance != null) { - final Object copy = - _copyCallbacks[identifier]!(strongInstance)! as Object; + // This cast is safe since it matches the argument type for + // _addInstanceWithIdentifier, which is the only place _copyCallbacks + // is populated. + final T Function(T) copyCallback = + _copyCallbacks[identifier]! as T Function(T); + final T copy = copyCallback(strongInstance); _identifiers[copy] = identifier; - _weakInstances[identifier] = WeakReference(copy); + _weakInstances[identifier] = WeakReference(copy); _finalizer.attach(copy, identifier, detach: copy); - return copy as T; + return copy; } - return strongInstance as T?; + return strongInstance; } - return weakInstance as T; + return weakInstance; } /// Retrieves the identifier associated with instance. @@ -152,7 +156,7 @@ class InstanceManager { /// In other words, the host platform wants to add a new instance that /// represents an object on the host platform. Stored with [identifier]. /// - /// Throws assertion error if the instance has already been + /// Throws assertion error if the instance or its identifier has already been /// added. /// /// Returns unique identifier of the [instance] added. @@ -161,6 +165,7 @@ class InstanceManager { int identifier, { required T Function(T original) onCopy, }) { + assert(!containsIdentifier(identifier)); assert(getIdentifier(instance) == null); assert(identifier >= 0); _addInstanceWithIdentifier(instance, identifier, onCopy: onCopy); diff --git a/packages/camera/camera_android_camerax/lib/src/system_services.dart b/packages/camera/camera_android_camerax/lib/src/system_services.dart index 03f88da9c520..a45948117fd2 100644 --- a/packages/camera/camera_android_camerax/lib/src/system_services.dart +++ b/packages/camera/camera_android_camerax/lib/src/system_services.dart @@ -13,22 +13,28 @@ import 'camerax_library.pigeon.dart'; import 'instance_manager.dart'; import 'java_object.dart'; +/// Utility class that offers access to Android system services needed for +/// camera usage. class SystemServices { - static final StreamController cameraPermissionsStreamController = - StreamController.broadcast(); - + /// Stream that emits the device orientation whenever it is changed/ + /// + /// Values may start being added to the stream once + /// `startListeningForDeviceOrientationChange(...)` is called. static final StreamController deviceOrientationChangedStreamController = StreamController.broadcast(); + /// Requests permission to access the camera and audio if specified. static Future requestCameraPermissions(bool enableAudio, {BinaryMessenger? binaryMessenger}) { SystemServicesHostApiImpl api = SystemServicesHostApiImpl(binaryMessenger: binaryMessenger); - return api.requestCameraPermissionsFromInstance(enableAudio); + return api.requestCameraPermissions(enableAudio); } + /// Requests that [deviceOrientationChangedStreamController] start + /// emitting values for any change in device orientation. static void startListeningForDeviceOrientationChange( bool isFrontFacing, int sensorOrientation, {BinaryMessenger? binaryMessenger}) { @@ -53,7 +59,11 @@ class SystemServicesHostApiImpl extends SystemServicesHostApi { /// the host platform. final BinaryMessenger? binaryMessenger; - Future requestCameraPermissionsFromInstance(bool enableAudio) async { + /// Requests permission to access the camera and audio if specified. + /// + /// Will complete normally if permissions are successfully granted; otherwise, + /// will throw a [CameraException]. + Future requestCameraPermissions(bool enableAudio) async { CameraPermissionsErrorData? error = await requestCameraPermissions(enableAudio); From 077a044b7cb9b443eea3df3f42a90379576d8c10 Mon Sep 17 00:00:00 2001 From: camsim99 Date: Tue, 17 Jan 2023 16:13:14 -0800 Subject: [PATCH 07/13] Add stop, docs, fix analyze --- .../camerax/GeneratedCameraXLibrary.java | 24 ++++++++++++ .../camerax/SystemServicesHostApiImpl.java | 21 ++++++++--- .../lib/src/camerax_library.pigeon.dart | 25 +++++++++++++ .../lib/src/system_services.dart | 37 ++++++++++++++----- .../pigeons/camerax_library.dart | 2 + .../test/system_services_test.dart | 9 +++++ .../test/system_services_test.mocks.dart | 8 ++++ .../test/test_camerax_library.pigeon.dart | 16 ++++++++ 8 files changed, 127 insertions(+), 15 deletions(-) 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 73fcf3ae78f0..331091675cba 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 @@ -554,6 +554,8 @@ void requestCameraPermissions( void startListeningForDeviceOrientationChange( @NonNull Boolean isFrontFacing, @NonNull Long sensorOrientation); + void stopListeningForDeviceOrientationChange(); + /** The codec used by SystemServicesHostApi. */ static MessageCodec getCodec() { return SystemServicesHostApiCodec.INSTANCE; @@ -636,6 +638,28 @@ public void error(Throwable error) { channel.setMessageHandler(null); } } + { + BasicMessageChannel channel = + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.SystemServicesHostApi.stopListeningForDeviceOrientationChange", + getCodec()); + if (api != null) { + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + api.stopListeningForDeviceOrientationChange(); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); + } else { + channel.setMessageHandler(null); + } + } } } diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java index 47883aa2fc57..e8eb715a7b3a 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/SystemServicesHostApiImpl.java @@ -18,6 +18,7 @@ public class SystemServicesHostApiImpl implements SystemServicesHostApi { private final InstanceManager instanceManager; @VisibleForTesting public CameraXProxy cameraXProxy = new CameraXProxy(); + @VisibleForTesting public DeviceOrientationManager deviceOrientationManager; @VisibleForTesting public SystemServicesFlutterApiImpl systemServicesFlutterApi; private Activity activity; @@ -79,7 +80,7 @@ public void requestCameraPermissions( @Override public void startListeningForDeviceOrientationChange( Boolean isFrontFacing, Long sensorOrientation) { - DeviceOrientationManager deviceOrientationManager = + deviceOrientationManager = cameraXProxy.createDeviceOrientationManager( activity, isFrontFacing, @@ -91,11 +92,21 @@ public void startListeningForDeviceOrientationChange( deviceOrientationManager.start(); } - /** - * Helper method for serializing a {@code DeviceOrientation} into a String that the Dart side is - * able to recognize. - */ + /** Serializes {@code DeviceOrientation} into a String that the Dart side is able to recognize. */ String serializeDeviceOrientation(DeviceOrientation orientation) { return orientation.toString(); } + + /** + * Tells the {@code deviceOrientationManager} to stop listening for orientation updates. + * + *

Has no effect if the {@code deviceOrientationManager} was never created to listen for device + * orientation updates. + */ + @Override + public void stopListeningForDeviceOrientationChange() { + if (deviceOrientationManager != null) { + deviceOrientationManager.stop(); + } + } } diff --git a/packages/camera/camera_android_camerax/lib/src/camerax_library.pigeon.dart b/packages/camera/camera_android_camerax/lib/src/camerax_library.pigeon.dart index 8f4c60e02b36..890f65d18830 100644 --- a/packages/camera/camera_android_camerax/lib/src/camerax_library.pigeon.dart +++ b/packages/camera/camera_android_camerax/lib/src/camerax_library.pigeon.dart @@ -485,6 +485,31 @@ class SystemServicesHostApi { return; } } + + Future stopListeningForDeviceOrientationChange() async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.SystemServicesHostApi.stopListeningForDeviceOrientationChange', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send(null) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return; + } + } } class _SystemServicesFlutterApiCodec extends StandardMessageCodec { diff --git a/packages/camera/camera_android_camerax/lib/src/system_services.dart b/packages/camera/camera_android_camerax/lib/src/system_services.dart index a45948117fd2..53d027559d87 100644 --- a/packages/camera/camera_android_camerax/lib/src/system_services.dart +++ b/packages/camera/camera_android_camerax/lib/src/system_services.dart @@ -10,8 +10,8 @@ import 'package:flutter/services.dart'; import 'android_camera_camerax_flutter_api_impls.dart'; import 'camerax_library.pigeon.dart'; -import 'instance_manager.dart'; -import 'java_object.dart'; + +// ignore_for_file: avoid_classes_with_only_static_members /// Utility class that offers access to Android system services needed for /// camera usage. @@ -27,10 +27,10 @@ class SystemServices { /// Requests permission to access the camera and audio if specified. static Future requestCameraPermissions(bool enableAudio, {BinaryMessenger? binaryMessenger}) { - SystemServicesHostApiImpl api = + final SystemServicesHostApiImpl api = SystemServicesHostApiImpl(binaryMessenger: binaryMessenger); - return api.requestCameraPermissions(enableAudio); + return api.sendCameraPermissionsRequest(enableAudio); } /// Requests that [deviceOrientationChangedStreamController] start @@ -39,19 +39,29 @@ class SystemServices { bool isFrontFacing, int sensorOrientation, {BinaryMessenger? binaryMessenger}) { AndroidCameraXCameraFlutterApis.instance.ensureSetUp(); - SystemServicesHostApi api = + final SystemServicesHostApi api = SystemServicesHostApi(binaryMessenger: binaryMessenger); api.startListeningForDeviceOrientationChange( isFrontFacing, sensorOrientation); } + + /// Stops the [deviceOrientationChangedStreamController] from emitting values + /// for changes in device orientation. + static void stopListeningForDeviceOrientationChange( + {BinaryMessenger? binaryMessenger}) { + final SystemServicesHostApi api = + SystemServicesHostApi(binaryMessenger: binaryMessenger); + + api.stopListeningForDeviceOrientationChange(); + } } /// Host API implementation of [SystemServices]. class SystemServicesHostApiImpl extends SystemServicesHostApi { /// Creates a [SystemServicesHostApiImpl]. SystemServicesHostApiImpl({this.binaryMessenger}) - : super(binaryMessenger: binaryMessenger) {} + : super(binaryMessenger: binaryMessenger); /// Receives binary data across the Flutter platform barrier. /// @@ -63,8 +73,8 @@ class SystemServicesHostApiImpl extends SystemServicesHostApi { /// /// Will complete normally if permissions are successfully granted; otherwise, /// will throw a [CameraException]. - Future requestCameraPermissions(bool enableAudio) async { - CameraPermissionsErrorData? error = + Future sendCameraPermissionsRequest(bool enableAudio) async { + final CameraPermissionsErrorData? error = await requestCameraPermissions(enableAudio); if (error != null) { @@ -89,17 +99,24 @@ class SystemServicesFlutterApiImpl implements SystemServicesFlutterApi { /// the host platform. final BinaryMessenger? binaryMessenger; + /// Callback method for any changes in device orientation. + /// + /// Will only be called if + /// `SystemServices.startListeningForDeviceOrientationChange(...)` was called + /// to start listening for device orientation updates. @override void onDeviceOrientationChanged(String orientation) { - DeviceOrientation deviceOrientation = + final DeviceOrientation deviceOrientation = deserializeDeviceOrientation(orientation); if (deviceOrientation == null) { return; } SystemServices.deviceOrientationChangedStreamController - .add(DeviceOrientationChangedEvent(deviceOrientation!)); + .add(DeviceOrientationChangedEvent(deviceOrientation)); } + /// Deserializes device orientation in [String] format into a + /// [DeviceOrientation]. DeviceOrientation deserializeDeviceOrientation(String orientation) { switch (orientation) { case 'LANDSCAPE_LEFT': diff --git a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart index 3096ea1f0a8b..37abec32e944 100644 --- a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart +++ b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart @@ -88,6 +88,8 @@ abstract class SystemServicesHostApi { void startListeningForDeviceOrientationChange( bool isFrontFacing, int sensorOrientation); + + void stopListeningForDeviceOrientationChange(); } @FlutterApi() diff --git a/packages/camera/camera_android_camerax/test/system_services_test.dart b/packages/camera/camera_android_camerax/test/system_services_test.dart index eae462f619cb..d4304fd2c182 100644 --- a/packages/camera/camera_android_camerax/test/system_services_test.dart +++ b/packages/camera/camera_android_camerax/test/system_services_test.dart @@ -74,6 +74,15 @@ void main() { isFrontFacing, sensorOrientation)); }); + test('stopListeningForDeviceOrientationChangeTest', () async { + final MockTestSystemServicesHostApi mockApi = + MockTestSystemServicesHostApi(); + TestSystemServicesHostApi.setup(mockApi); + + SystemServices.stopListeningForDeviceOrientationChange(); + verify(mockApi.stopListeningForDeviceOrientationChange()); + }); + test('onDeviceOrientationChanged adds new orientation to stream', () { const String orientation = 'LANDSCAPE_LEFT'; diff --git a/packages/camera/camera_android_camerax/test/system_services_test.mocks.dart b/packages/camera/camera_android_camerax/test/system_services_test.mocks.dart index 429fde1f8bc1..2698d2d52307 100644 --- a/packages/camera/camera_android_camerax/test/system_services_test.mocks.dart +++ b/packages/camera/camera_android_camerax/test/system_services_test.mocks.dart @@ -55,4 +55,12 @@ class MockTestSystemServicesHostApi extends _i1.Mock ), returnValueForMissingStub: null, ); + @override + void stopListeningForDeviceOrientationChange() => super.noSuchMethod( + Invocation.method( + #stopListeningForDeviceOrientationChange, + [], + ), + returnValueForMissingStub: null, + ); } diff --git a/packages/camera/camera_android_camerax/test/test_camerax_library.pigeon.dart b/packages/camera/camera_android_camerax/test/test_camerax_library.pigeon.dart index 3f137f6e440e..5e2aa78f79a5 100644 --- a/packages/camera/camera_android_camerax/test/test_camerax_library.pigeon.dart +++ b/packages/camera/camera_android_camerax/test/test_camerax_library.pigeon.dart @@ -217,6 +217,7 @@ abstract class TestSystemServicesHostApi { bool enableAudio); void startListeningForDeviceOrientationChange( bool isFrontFacing, int sensorOrientation); + void stopListeningForDeviceOrientationChange(); static void setup(TestSystemServicesHostApi? api, {BinaryMessenger? binaryMessenger}) { { @@ -264,5 +265,20 @@ abstract class TestSystemServicesHostApi { }); } } + { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.SystemServicesHostApi.stopListeningForDeviceOrientationChange', + codec, + binaryMessenger: binaryMessenger); + if (api == null) { + channel.setMockMessageHandler(null); + } else { + channel.setMockMessageHandler((Object? message) async { + // ignore message + api.stopListeningForDeviceOrientationChange(); + return {}; + }); + } + } } } From 0c47f13279d5dca32ee6575d03076058fa76af1a Mon Sep 17 00:00:00 2001 From: camsim99 Date: Wed, 18 Jan 2023 13:34:50 -0800 Subject: [PATCH 08/13] Fix comment --- .../camera/camera_android_camerax/lib/src/system_services.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_android_camerax/lib/src/system_services.dart b/packages/camera/camera_android_camerax/lib/src/system_services.dart index 53d027559d87..b0a6db2fa58b 100644 --- a/packages/camera/camera_android_camerax/lib/src/system_services.dart +++ b/packages/camera/camera_android_camerax/lib/src/system_services.dart @@ -16,7 +16,7 @@ import 'camerax_library.pigeon.dart'; /// Utility class that offers access to Android system services needed for /// camera usage. class SystemServices { - /// Stream that emits the device orientation whenever it is changed/ + /// Stream that emits the device orientation whenever it is changed. /// /// Values may start being added to the stream once /// `startListeningForDeviceOrientationChange(...)` is called. From 7a9f1f11a4975feee6d0c6d7a78c881961ada38f Mon Sep 17 00:00:00 2001 From: camsim99 Date: Wed, 25 Jan 2023 14:18:54 -0800 Subject: [PATCH 09/13] Add comment and remove literals --- .../lib/src/system_services.dart | 2 ++ .../test/system_services_test.dart | 28 +++++++------------ 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/packages/camera/camera_android_camerax/lib/src/system_services.dart b/packages/camera/camera_android_camerax/lib/src/system_services.dart index b0a6db2fa58b..d5fbe5a92c91 100644 --- a/packages/camera/camera_android_camerax/lib/src/system_services.dart +++ b/packages/camera/camera_android_camerax/lib/src/system_services.dart @@ -11,6 +11,8 @@ import 'package:flutter/services.dart'; import 'android_camera_camerax_flutter_api_impls.dart'; import 'camerax_library.pigeon.dart'; +// Ignoring lint indicating this class only contains static members +// as this class is a wrapper for various Android system services. // ignore_for_file: avoid_classes_with_only_static_members /// Utility class that offers access to Android system services needed for diff --git a/packages/camera/camera_android_camerax/test/system_services_test.dart b/packages/camera/camera_android_camerax/test/system_services_test.dart index d4304fd2c182..571f1923e367 100644 --- a/packages/camera/camera_android_camerax/test/system_services_test.dart +++ b/packages/camera/camera_android_camerax/test/system_services_test.dart @@ -28,13 +28,12 @@ void main() { final MockTestSystemServicesHostApi mockApi = MockTestSystemServicesHostApi(); TestSystemServicesHostApi.setup(mockApi); - const bool enableAudio = true; - when(mockApi.requestCameraPermissions(enableAudio)) + when(mockApi.requestCameraPermissions(true)) .thenAnswer((_) async => null); - await SystemServices.requestCameraPermissions(enableAudio); - verify(mockApi.requestCameraPermissions(enableAudio)); + await SystemServices.requestCameraPermissions(true); + verify(mockApi.requestCameraPermissions(true)); }); test( @@ -43,35 +42,32 @@ void main() { final MockTestSystemServicesHostApi mockApi = MockTestSystemServicesHostApi(); TestSystemServicesHostApi.setup(mockApi); - const bool enableAudio = true; final CameraPermissionsErrorData error = CameraPermissionsErrorData( errorCode: 'Test error code', description: 'Test error description', ); - when(mockApi.requestCameraPermissions(enableAudio)) + when(mockApi.requestCameraPermissions(true)) .thenAnswer((_) async => error); expect( - () async => SystemServices.requestCameraPermissions(enableAudio), + () async => SystemServices.requestCameraPermissions(true), throwsA(isA() .having((CameraException e) => e.code, 'code', 'Test error code') .having((CameraException e) => e.description, 'description', 'Test error description'))); - verify(mockApi.requestCameraPermissions(enableAudio)); + verify(mockApi.requestCameraPermissions(true)); }); test('startListeningForDeviceOrientationChangeTest', () async { final MockTestSystemServicesHostApi mockApi = MockTestSystemServicesHostApi(); TestSystemServicesHostApi.setup(mockApi); - const bool isFrontFacing = true; - const int sensorOrientation = 90; SystemServices.startListeningForDeviceOrientationChange( - isFrontFacing, sensorOrientation); + true, 90); verify(mockApi.startListeningForDeviceOrientationChange( - isFrontFacing, sensorOrientation)); + true, 90)); }); test('stopListeningForDeviceOrientationChangeTest', () async { @@ -84,23 +80,19 @@ void main() { }); test('onDeviceOrientationChanged adds new orientation to stream', () { - const String orientation = 'LANDSCAPE_LEFT'; - SystemServices.deviceOrientationChangedStreamController.stream .listen((DeviceOrientationChangedEvent event) { expect(event.orientation, equals(DeviceOrientation.landscapeLeft)); }); - SystemServicesFlutterApiImpl().onDeviceOrientationChanged(orientation); + SystemServicesFlutterApiImpl().onDeviceOrientationChanged('LANDSCAPE_LEFT'); }); test( 'onDeviceOrientationChanged throws error if new orientation is invalid', () { - const String orientation = 'FAKE_ORIENTATION'; - expect( () => SystemServicesFlutterApiImpl() - .onDeviceOrientationChanged(orientation), + .onDeviceOrientationChanged('FAKE_ORIENTATION'), throwsA(isA().having( (ArgumentError e) => e.message, 'message', From 2b086684795825a04bf25fedbf4f3b5945dbd6ba Mon Sep 17 00:00:00 2001 From: camsim99 Date: Wed, 25 Jan 2023 14:29:02 -0800 Subject: [PATCH 10/13] Formatting --- .../camerax/GeneratedCameraXLibrary.java | 775 +++++++++++------- .../lib/src/camerax_library.pigeon.dart | 220 +++-- .../test/system_services_test.dart | 9 +- .../test/test_camerax_library.pigeon.dart | 184 +++-- 4 files changed, 748 insertions(+), 440 deletions(-) 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 3982826f56dd..528870cc749c 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 @@ -15,11 +15,11 @@ import io.flutter.plugin.common.StandardMessageCodec; import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; -import java.util.Arrays; import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.HashMap; /** Generated class from Pigeon. */ @SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression"}) @@ -28,7 +28,11 @@ public class GeneratedCameraXLibrary { /** Generated class from Pigeon that represents data sent in messages. */ public static class CameraPermissionsErrorData { private @NonNull String errorCode; - public @NonNull String getErrorCode() { return errorCode; } + + public @NonNull String getErrorCode() { + return errorCode; + } + public void setErrorCode(@NonNull String setterArg) { if (setterArg == null) { throw new IllegalStateException("Nonnull field \"errorCode\" is null."); @@ -37,7 +41,11 @@ public void setErrorCode(@NonNull String setterArg) { } private @NonNull String description; - public @NonNull String getDescription() { return description; } + + public @NonNull String getDescription() { + return description; + } + public void setDescription(@NonNull String setterArg) { if (setterArg == null) { throw new IllegalStateException("Nonnull field \"description\" is null."); @@ -47,17 +55,22 @@ public void setDescription(@NonNull String setterArg) { /** Constructor is private to enforce null safety; use Builder. */ private CameraPermissionsErrorData() {} + public static final class Builder { private @Nullable String errorCode; + public @NonNull Builder setErrorCode(@NonNull String setterArg) { this.errorCode = setterArg; return this; } + private @Nullable String description; + public @NonNull Builder setDescription(@NonNull String setterArg) { this.description = setterArg; return this; } + public @NonNull CameraPermissionsErrorData build() { CameraPermissionsErrorData pigeonReturn = new CameraPermissionsErrorData(); pigeonReturn.setErrorCode(errorCode); @@ -65,32 +78,38 @@ public static final class Builder { return pigeonReturn; } } - @NonNull Map toMap() { + + @NonNull + Map toMap() { Map toMapResult = new HashMap<>(); toMapResult.put("errorCode", errorCode); toMapResult.put("description", description); return toMapResult; } + static @NonNull CameraPermissionsErrorData fromMap(@NonNull Map map) { CameraPermissionsErrorData pigeonResult = new CameraPermissionsErrorData(); Object errorCode = map.get("errorCode"); - pigeonResult.setErrorCode((String)errorCode); + pigeonResult.setErrorCode((String) errorCode); Object description = map.get("description"); - pigeonResult.setDescription((String)description); + pigeonResult.setDescription((String) description); return pigeonResult; } } public interface Result { void success(T result); + void error(Throwable error); } + private static class JavaObjectHostApiCodec extends StandardMessageCodec { public static final JavaObjectHostApiCodec INSTANCE = new JavaObjectHostApiCodec(); + private JavaObjectHostApiCodec() {} } - /** Generated interface from Pigeon that represents a handler of messages from Flutter.*/ + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface JavaObjectHostApi { void dispose(@NonNull Long identifier); @@ -99,237 +118,302 @@ static MessageCodec getCodec() { return JavaObjectHostApiCodec.INSTANCE; } - /** Sets up an instance of `JavaObjectHostApi` to handle messages through the `binaryMessenger`. */ + /** + * Sets up an instance of `JavaObjectHostApi` to handle messages through the `binaryMessenger`. + */ static void setup(BinaryMessenger binaryMessenger, JavaObjectHostApi api) { { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.JavaObjectHostApi.dispose", getCodec()); + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.JavaObjectHostApi.dispose", getCodec()); if (api != null) { - channel.setMessageHandler((message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList)message; - Number identifierArg = (Number)args.get(0); - if (identifierArg == null) { - throw new NullPointerException("identifierArg unexpectedly null."); - } - api.dispose((identifierArg == null) ? null : identifierArg.longValue()); - wrapped.put("result", null); - } - catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - } - reply.reply(wrapped); - }); + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number identifierArg = (Number) args.get(0); + if (identifierArg == null) { + throw new NullPointerException("identifierArg unexpectedly null."); + } + api.dispose((identifierArg == null) ? null : identifierArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); } else { channel.setMessageHandler(null); } } } } + private static class JavaObjectFlutterApiCodec extends StandardMessageCodec { public static final JavaObjectFlutterApiCodec INSTANCE = new JavaObjectFlutterApiCodec(); + private JavaObjectFlutterApiCodec() {} } - /** Generated class from Pigeon that represents Flutter messages that can be called from Java.*/ + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ public static class JavaObjectFlutterApi { private final BinaryMessenger binaryMessenger; - public JavaObjectFlutterApi(BinaryMessenger argBinaryMessenger){ + + public JavaObjectFlutterApi(BinaryMessenger argBinaryMessenger) { this.binaryMessenger = argBinaryMessenger; } + public interface Reply { void reply(T reply); } + static MessageCodec getCodec() { return JavaObjectFlutterApiCodec.INSTANCE; } public void dispose(@NonNull Long identifierArg, Reply callback) { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.JavaObjectFlutterApi.dispose", getCodec()); - channel.send(new ArrayList(Arrays.asList(identifierArg)), channelReply -> { - callback.reply(null); - }); + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.JavaObjectFlutterApi.dispose", getCodec()); + channel.send( + new ArrayList(Arrays.asList(identifierArg)), + channelReply -> { + callback.reply(null); + }); } } + private static class CameraInfoHostApiCodec extends StandardMessageCodec { public static final CameraInfoHostApiCodec INSTANCE = new CameraInfoHostApiCodec(); + private CameraInfoHostApiCodec() {} } - /** Generated interface from Pigeon that represents a handler of messages from Flutter.*/ + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface CameraInfoHostApi { - @NonNull Long getSensorRotationDegrees(@NonNull Long identifier); + @NonNull + Long getSensorRotationDegrees(@NonNull Long identifier); /** The codec used by CameraInfoHostApi. */ static MessageCodec getCodec() { return CameraInfoHostApiCodec.INSTANCE; } - /** Sets up an instance of `CameraInfoHostApi` to handle messages through the `binaryMessenger`. */ + /** + * Sets up an instance of `CameraInfoHostApi` to handle messages through the `binaryMessenger`. + */ static void setup(BinaryMessenger binaryMessenger, CameraInfoHostApi api) { { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.CameraInfoHostApi.getSensorRotationDegrees", getCodec()); + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.CameraInfoHostApi.getSensorRotationDegrees", + getCodec()); if (api != null) { - channel.setMessageHandler((message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList)message; - Number identifierArg = (Number)args.get(0); - if (identifierArg == null) { - throw new NullPointerException("identifierArg unexpectedly null."); - } - Long output = api.getSensorRotationDegrees((identifierArg == null) ? null : identifierArg.longValue()); - wrapped.put("result", output); - } - catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - } - reply.reply(wrapped); - }); + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number identifierArg = (Number) args.get(0); + if (identifierArg == null) { + throw new NullPointerException("identifierArg unexpectedly null."); + } + Long output = + api.getSensorRotationDegrees( + (identifierArg == null) ? null : identifierArg.longValue()); + wrapped.put("result", output); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); } else { channel.setMessageHandler(null); } } } } + private static class CameraInfoFlutterApiCodec extends StandardMessageCodec { public static final CameraInfoFlutterApiCodec INSTANCE = new CameraInfoFlutterApiCodec(); + private CameraInfoFlutterApiCodec() {} } - /** Generated class from Pigeon that represents Flutter messages that can be called from Java.*/ + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ public static class CameraInfoFlutterApi { private final BinaryMessenger binaryMessenger; - public CameraInfoFlutterApi(BinaryMessenger argBinaryMessenger){ + + public CameraInfoFlutterApi(BinaryMessenger argBinaryMessenger) { this.binaryMessenger = argBinaryMessenger; } + public interface Reply { void reply(T reply); } + static MessageCodec getCodec() { return CameraInfoFlutterApiCodec.INSTANCE; } public void create(@NonNull Long identifierArg, Reply callback) { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.CameraInfoFlutterApi.create", getCodec()); - channel.send(new ArrayList(Arrays.asList(identifierArg)), channelReply -> { - callback.reply(null); - }); + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.CameraInfoFlutterApi.create", getCodec()); + channel.send( + new ArrayList(Arrays.asList(identifierArg)), + channelReply -> { + callback.reply(null); + }); } } + private static class CameraSelectorHostApiCodec extends StandardMessageCodec { public static final CameraSelectorHostApiCodec INSTANCE = new CameraSelectorHostApiCodec(); + private CameraSelectorHostApiCodec() {} } - /** Generated interface from Pigeon that represents a handler of messages from Flutter.*/ + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface CameraSelectorHostApi { void create(@NonNull Long identifier, @Nullable Long lensFacing); - @NonNull List filter(@NonNull Long identifier, @NonNull List cameraInfoIds); + + @NonNull + List filter(@NonNull Long identifier, @NonNull List cameraInfoIds); /** The codec used by CameraSelectorHostApi. */ static MessageCodec getCodec() { return CameraSelectorHostApiCodec.INSTANCE; } - /** Sets up an instance of `CameraSelectorHostApi` to handle messages through the `binaryMessenger`. */ + /** + * Sets up an instance of `CameraSelectorHostApi` to handle messages through the + * `binaryMessenger`. + */ static void setup(BinaryMessenger binaryMessenger, CameraSelectorHostApi api) { { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.CameraSelectorHostApi.create", getCodec()); + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.CameraSelectorHostApi.create", getCodec()); if (api != null) { - channel.setMessageHandler((message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList)message; - Number identifierArg = (Number)args.get(0); - if (identifierArg == null) { - throw new NullPointerException("identifierArg unexpectedly null."); - } - Number lensFacingArg = (Number)args.get(1); - api.create((identifierArg == null) ? null : identifierArg.longValue(), (lensFacingArg == null) ? null : lensFacingArg.longValue()); - wrapped.put("result", null); - } - catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - } - reply.reply(wrapped); - }); + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number identifierArg = (Number) args.get(0); + if (identifierArg == null) { + throw new NullPointerException("identifierArg unexpectedly null."); + } + Number lensFacingArg = (Number) args.get(1); + api.create( + (identifierArg == null) ? null : identifierArg.longValue(), + (lensFacingArg == null) ? null : lensFacingArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); } else { channel.setMessageHandler(null); } } { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.CameraSelectorHostApi.filter", getCodec()); + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.CameraSelectorHostApi.filter", getCodec()); if (api != null) { - channel.setMessageHandler((message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList)message; - Number identifierArg = (Number)args.get(0); - if (identifierArg == null) { - throw new NullPointerException("identifierArg unexpectedly null."); - } - List cameraInfoIdsArg = (List)args.get(1); - if (cameraInfoIdsArg == null) { - throw new NullPointerException("cameraInfoIdsArg unexpectedly null."); - } - List output = api.filter((identifierArg == null) ? null : identifierArg.longValue(), cameraInfoIdsArg); - wrapped.put("result", output); - } - catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - } - reply.reply(wrapped); - }); + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number identifierArg = (Number) args.get(0); + if (identifierArg == null) { + throw new NullPointerException("identifierArg unexpectedly null."); + } + List cameraInfoIdsArg = (List) args.get(1); + if (cameraInfoIdsArg == null) { + throw new NullPointerException("cameraInfoIdsArg unexpectedly null."); + } + List output = + api.filter( + (identifierArg == null) ? null : identifierArg.longValue(), + cameraInfoIdsArg); + wrapped.put("result", output); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); } else { channel.setMessageHandler(null); } } } } + private static class CameraSelectorFlutterApiCodec extends StandardMessageCodec { - public static final CameraSelectorFlutterApiCodec INSTANCE = new CameraSelectorFlutterApiCodec(); + public static final CameraSelectorFlutterApiCodec INSTANCE = + new CameraSelectorFlutterApiCodec(); + private CameraSelectorFlutterApiCodec() {} } - /** Generated class from Pigeon that represents Flutter messages that can be called from Java.*/ + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ public static class CameraSelectorFlutterApi { private final BinaryMessenger binaryMessenger; - public CameraSelectorFlutterApi(BinaryMessenger argBinaryMessenger){ + + public CameraSelectorFlutterApi(BinaryMessenger argBinaryMessenger) { this.binaryMessenger = argBinaryMessenger; } + public interface Reply { void reply(T reply); } + static MessageCodec getCodec() { return CameraSelectorFlutterApiCodec.INSTANCE; } - public void create(@NonNull Long identifierArg, @Nullable Long lensFacingArg, Reply callback) { + public void create( + @NonNull Long identifierArg, @Nullable Long lensFacingArg, Reply callback) { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.CameraSelectorFlutterApi.create", getCodec()); - channel.send(new ArrayList(Arrays.asList(identifierArg, lensFacingArg)), channelReply -> { - callback.reply(null); - }); + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.CameraSelectorFlutterApi.create", getCodec()); + channel.send( + new ArrayList(Arrays.asList(identifierArg, lensFacingArg)), + channelReply -> { + callback.reply(null); + }); } } + private static class ProcessCameraProviderHostApiCodec extends StandardMessageCodec { - public static final ProcessCameraProviderHostApiCodec INSTANCE = new ProcessCameraProviderHostApiCodec(); + public static final ProcessCameraProviderHostApiCodec INSTANCE = + new ProcessCameraProviderHostApiCodec(); + private ProcessCameraProviderHostApiCodec() {} } - /** Generated interface from Pigeon that represents a handler of messages from Flutter.*/ + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface ProcessCameraProviderHostApi { void getInstance(Result result); - @NonNull List getAvailableCameraInfos(@NonNull Long identifier); - @NonNull Long bindToLifecycle(@NonNull Long identifier, @NonNull Long cameraSelectorIdentifier, @NonNull List useCaseIds); + + @NonNull + List getAvailableCameraInfos(@NonNull Long identifier); + + @NonNull + Long bindToLifecycle( + @NonNull Long identifier, + @NonNull Long cameraSelectorIdentifier, + @NonNull List useCaseIds); + void unbind(@NonNull Long identifier, @NonNull List useCaseIds); + void unbindAll(@NonNull Long identifier); /** The codec used by ProcessCameraProviderHostApi. */ @@ -337,229 +421,284 @@ static MessageCodec getCodec() { return ProcessCameraProviderHostApiCodec.INSTANCE; } - /** Sets up an instance of `ProcessCameraProviderHostApi` to handle messages through the `binaryMessenger`. */ + /** + * Sets up an instance of `ProcessCameraProviderHostApi` to handle messages through the + * `binaryMessenger`. + */ static void setup(BinaryMessenger binaryMessenger, ProcessCameraProviderHostApi api) { { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.ProcessCameraProviderHostApi.getInstance", getCodec()); + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.ProcessCameraProviderHostApi.getInstance", + getCodec()); if (api != null) { - channel.setMessageHandler((message, reply) -> { - Map wrapped = new HashMap<>(); - try { - Result resultCallback = new Result() { - public void success(Long result) { - wrapped.put("result", result); + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + Result resultCallback = + new Result() { + public void success(Long result) { + wrapped.put("result", result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + wrapped.put("error", wrapError(error)); + reply.reply(wrapped); + } + }; + + api.getInstance(resultCallback); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); reply.reply(wrapped); } - public void error(Throwable error) { - wrapped.put("error", wrapError(error)); - reply.reply(wrapped); - } - }; - - api.getInstance(resultCallback); - } - catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - reply.reply(wrapped); - } - }); + }); } else { channel.setMessageHandler(null); } } { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.ProcessCameraProviderHostApi.getAvailableCameraInfos", getCodec()); + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.ProcessCameraProviderHostApi.getAvailableCameraInfos", + getCodec()); if (api != null) { - channel.setMessageHandler((message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList)message; - Number identifierArg = (Number)args.get(0); - if (identifierArg == null) { - throw new NullPointerException("identifierArg unexpectedly null."); - } - List output = api.getAvailableCameraInfos((identifierArg == null) ? null : identifierArg.longValue()); - wrapped.put("result", output); - } - catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - } - reply.reply(wrapped); - }); + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number identifierArg = (Number) args.get(0); + if (identifierArg == null) { + throw new NullPointerException("identifierArg unexpectedly null."); + } + List output = + api.getAvailableCameraInfos( + (identifierArg == null) ? null : identifierArg.longValue()); + wrapped.put("result", output); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); } else { channel.setMessageHandler(null); } } { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle", getCodec()); + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle", + getCodec()); if (api != null) { - channel.setMessageHandler((message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList)message; - Number identifierArg = (Number)args.get(0); - if (identifierArg == null) { - throw new NullPointerException("identifierArg unexpectedly null."); - } - Number cameraSelectorIdentifierArg = (Number)args.get(1); - if (cameraSelectorIdentifierArg == null) { - throw new NullPointerException("cameraSelectorIdentifierArg unexpectedly null."); - } - List useCaseIdsArg = (List)args.get(2); - if (useCaseIdsArg == null) { - throw new NullPointerException("useCaseIdsArg unexpectedly null."); - } - Long output = api.bindToLifecycle((identifierArg == null) ? null : identifierArg.longValue(), (cameraSelectorIdentifierArg == null) ? null : cameraSelectorIdentifierArg.longValue(), useCaseIdsArg); - wrapped.put("result", output); - } - catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - } - reply.reply(wrapped); - }); + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number identifierArg = (Number) args.get(0); + if (identifierArg == null) { + throw new NullPointerException("identifierArg unexpectedly null."); + } + Number cameraSelectorIdentifierArg = (Number) args.get(1); + if (cameraSelectorIdentifierArg == null) { + throw new NullPointerException( + "cameraSelectorIdentifierArg unexpectedly null."); + } + List useCaseIdsArg = (List) args.get(2); + if (useCaseIdsArg == null) { + throw new NullPointerException("useCaseIdsArg unexpectedly null."); + } + Long output = + api.bindToLifecycle( + (identifierArg == null) ? null : identifierArg.longValue(), + (cameraSelectorIdentifierArg == null) + ? null + : cameraSelectorIdentifierArg.longValue(), + useCaseIdsArg); + wrapped.put("result", output); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); } else { channel.setMessageHandler(null); } } { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.ProcessCameraProviderHostApi.unbind", getCodec()); + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.ProcessCameraProviderHostApi.unbind", + getCodec()); if (api != null) { - channel.setMessageHandler((message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList)message; - Number identifierArg = (Number)args.get(0); - if (identifierArg == null) { - throw new NullPointerException("identifierArg unexpectedly null."); - } - List useCaseIdsArg = (List)args.get(1); - if (useCaseIdsArg == null) { - throw new NullPointerException("useCaseIdsArg unexpectedly null."); - } - api.unbind((identifierArg == null) ? null : identifierArg.longValue(), useCaseIdsArg); - wrapped.put("result", null); - } - catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - } - reply.reply(wrapped); - }); + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number identifierArg = (Number) args.get(0); + if (identifierArg == null) { + throw new NullPointerException("identifierArg unexpectedly null."); + } + List useCaseIdsArg = (List) args.get(1); + if (useCaseIdsArg == null) { + throw new NullPointerException("useCaseIdsArg unexpectedly null."); + } + api.unbind( + (identifierArg == null) ? null : identifierArg.longValue(), useCaseIdsArg); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); } else { channel.setMessageHandler(null); } } { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.ProcessCameraProviderHostApi.unbindAll", getCodec()); + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.ProcessCameraProviderHostApi.unbindAll", + getCodec()); if (api != null) { - channel.setMessageHandler((message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList)message; - Number identifierArg = (Number)args.get(0); - if (identifierArg == null) { - throw new NullPointerException("identifierArg unexpectedly null."); - } - api.unbindAll((identifierArg == null) ? null : identifierArg.longValue()); - wrapped.put("result", null); - } - catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - } - reply.reply(wrapped); - }); + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Number identifierArg = (Number) args.get(0); + if (identifierArg == null) { + throw new NullPointerException("identifierArg unexpectedly null."); + } + api.unbindAll((identifierArg == null) ? null : identifierArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); } else { channel.setMessageHandler(null); } } } } + private static class ProcessCameraProviderFlutterApiCodec extends StandardMessageCodec { - public static final ProcessCameraProviderFlutterApiCodec INSTANCE = new ProcessCameraProviderFlutterApiCodec(); + public static final ProcessCameraProviderFlutterApiCodec INSTANCE = + new ProcessCameraProviderFlutterApiCodec(); + private ProcessCameraProviderFlutterApiCodec() {} } - /** Generated class from Pigeon that represents Flutter messages that can be called from Java.*/ + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ public static class ProcessCameraProviderFlutterApi { private final BinaryMessenger binaryMessenger; - public ProcessCameraProviderFlutterApi(BinaryMessenger argBinaryMessenger){ + + public ProcessCameraProviderFlutterApi(BinaryMessenger argBinaryMessenger) { this.binaryMessenger = argBinaryMessenger; } + public interface Reply { void reply(T reply); } + static MessageCodec getCodec() { return ProcessCameraProviderFlutterApiCodec.INSTANCE; } public void create(@NonNull Long identifierArg, Reply callback) { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.ProcessCameraProviderFlutterApi.create", getCodec()); - channel.send(new ArrayList(Arrays.asList(identifierArg)), channelReply -> { - callback.reply(null); - }); + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.ProcessCameraProviderFlutterApi.create", + getCodec()); + channel.send( + new ArrayList(Arrays.asList(identifierArg)), + channelReply -> { + callback.reply(null); + }); } } + private static class CameraFlutterApiCodec extends StandardMessageCodec { public static final CameraFlutterApiCodec INSTANCE = new CameraFlutterApiCodec(); + private CameraFlutterApiCodec() {} } - /** Generated class from Pigeon that represents Flutter messages that can be called from Java.*/ + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ public static class CameraFlutterApi { private final BinaryMessenger binaryMessenger; - public CameraFlutterApi(BinaryMessenger argBinaryMessenger){ + + public CameraFlutterApi(BinaryMessenger argBinaryMessenger) { this.binaryMessenger = argBinaryMessenger; } + public interface Reply { void reply(T reply); } + static MessageCodec getCodec() { return CameraFlutterApiCodec.INSTANCE; } public void create(@NonNull Long identifierArg, Reply callback) { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.CameraFlutterApi.create", getCodec()); - channel.send(new ArrayList(Arrays.asList(identifierArg)), channelReply -> { - callback.reply(null); - }); + new BasicMessageChannel<>( + binaryMessenger, "dev.flutter.pigeon.CameraFlutterApi.create", getCodec()); + channel.send( + new ArrayList(Arrays.asList(identifierArg)), + channelReply -> { + callback.reply(null); + }); } } + private static class SystemServicesHostApiCodec extends StandardMessageCodec { public static final SystemServicesHostApiCodec INSTANCE = new SystemServicesHostApiCodec(); + private SystemServicesHostApiCodec() {} + @Override protected Object readValueOfType(byte type, ByteBuffer buffer) { switch (type) { - case (byte)128: + case (byte) 128: return CameraPermissionsErrorData.fromMap((Map) readValue(buffer)); - - default: + + default: return super.readValueOfType(type, buffer); - } } + @Override - protected void writeValue(ByteArrayOutputStream stream, Object value) { + protected void writeValue(ByteArrayOutputStream stream, Object value) { if (value instanceof CameraPermissionsErrorData) { stream.write(128); writeValue(stream, ((CameraPermissionsErrorData) value).toMap()); - } else -{ + } else { super.writeValue(stream, value); } } } - /** Generated interface from Pigeon that represents a handler of messages from Flutter.*/ + /** Generated interface from Pigeon that represents a handler of messages from Flutter. */ public interface SystemServicesHostApi { - void requestCameraPermissions(@NonNull Boolean enableAudio, Result result); - void startListeningForDeviceOrientationChange(@NonNull Boolean isFrontFacing, @NonNull Long sensorOrientation); + void requestCameraPermissions( + @NonNull Boolean enableAudio, Result result); + + void startListeningForDeviceOrientationChange( + @NonNull Boolean isFrontFacing, @NonNull Long sensorOrientation); + void stopListeningForDeviceOrientationChange(); /** The codec used by SystemServicesHostApi. */ @@ -567,122 +706,152 @@ static MessageCodec getCodec() { return SystemServicesHostApiCodec.INSTANCE; } - /** Sets up an instance of `SystemServicesHostApi` to handle messages through the `binaryMessenger`. */ + /** + * Sets up an instance of `SystemServicesHostApi` to handle messages through the + * `binaryMessenger`. + */ static void setup(BinaryMessenger binaryMessenger, SystemServicesHostApi api) { { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions", getCodec()); + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions", + getCodec()); if (api != null) { - channel.setMessageHandler((message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList)message; - Boolean enableAudioArg = (Boolean)args.get(0); - if (enableAudioArg == null) { - throw new NullPointerException("enableAudioArg unexpectedly null."); - } - Result resultCallback = new Result() { - public void success(CameraPermissionsErrorData result) { - wrapped.put("result", result); - reply.reply(wrapped); - } - public void error(Throwable error) { - wrapped.put("error", wrapError(error)); + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Boolean enableAudioArg = (Boolean) args.get(0); + if (enableAudioArg == null) { + throw new NullPointerException("enableAudioArg unexpectedly null."); + } + Result resultCallback = + new Result() { + public void success(CameraPermissionsErrorData result) { + wrapped.put("result", result); + reply.reply(wrapped); + } + + public void error(Throwable error) { + wrapped.put("error", wrapError(error)); + reply.reply(wrapped); + } + }; + + api.requestCameraPermissions(enableAudioArg, resultCallback); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); reply.reply(wrapped); } - }; - - api.requestCameraPermissions(enableAudioArg, resultCallback); - } - catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - reply.reply(wrapped); - } - }); + }); } else { channel.setMessageHandler(null); } } { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange", getCodec()); + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange", + getCodec()); if (api != null) { - channel.setMessageHandler((message, reply) -> { - Map wrapped = new HashMap<>(); - try { - ArrayList args = (ArrayList)message; - Boolean isFrontFacingArg = (Boolean)args.get(0); - if (isFrontFacingArg == null) { - throw new NullPointerException("isFrontFacingArg unexpectedly null."); - } - Number sensorOrientationArg = (Number)args.get(1); - if (sensorOrientationArg == null) { - throw new NullPointerException("sensorOrientationArg unexpectedly null."); - } - api.startListeningForDeviceOrientationChange(isFrontFacingArg, (sensorOrientationArg == null) ? null : sensorOrientationArg.longValue()); - wrapped.put("result", null); - } - catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - } - reply.reply(wrapped); - }); + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + ArrayList args = (ArrayList) message; + Boolean isFrontFacingArg = (Boolean) args.get(0); + if (isFrontFacingArg == null) { + throw new NullPointerException("isFrontFacingArg unexpectedly null."); + } + Number sensorOrientationArg = (Number) args.get(1); + if (sensorOrientationArg == null) { + throw new NullPointerException("sensorOrientationArg unexpectedly null."); + } + api.startListeningForDeviceOrientationChange( + isFrontFacingArg, + (sensorOrientationArg == null) ? null : sensorOrientationArg.longValue()); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); } else { channel.setMessageHandler(null); } } { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.SystemServicesHostApi.stopListeningForDeviceOrientationChange", getCodec()); + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.SystemServicesHostApi.stopListeningForDeviceOrientationChange", + getCodec()); if (api != null) { - channel.setMessageHandler((message, reply) -> { - Map wrapped = new HashMap<>(); - try { - api.stopListeningForDeviceOrientationChange(); - wrapped.put("result", null); - } - catch (Error | RuntimeException exception) { - wrapped.put("error", wrapError(exception)); - } - reply.reply(wrapped); - }); + channel.setMessageHandler( + (message, reply) -> { + Map wrapped = new HashMap<>(); + try { + api.stopListeningForDeviceOrientationChange(); + wrapped.put("result", null); + } catch (Error | RuntimeException exception) { + wrapped.put("error", wrapError(exception)); + } + reply.reply(wrapped); + }); } else { channel.setMessageHandler(null); } } } } + private static class SystemServicesFlutterApiCodec extends StandardMessageCodec { - public static final SystemServicesFlutterApiCodec INSTANCE = new SystemServicesFlutterApiCodec(); + public static final SystemServicesFlutterApiCodec INSTANCE = + new SystemServicesFlutterApiCodec(); + private SystemServicesFlutterApiCodec() {} } - /** Generated class from Pigeon that represents Flutter messages that can be called from Java.*/ + /** Generated class from Pigeon that represents Flutter messages that can be called from Java. */ public static class SystemServicesFlutterApi { private final BinaryMessenger binaryMessenger; - public SystemServicesFlutterApi(BinaryMessenger argBinaryMessenger){ + + public SystemServicesFlutterApi(BinaryMessenger argBinaryMessenger) { this.binaryMessenger = argBinaryMessenger; } + public interface Reply { void reply(T reply); } + static MessageCodec getCodec() { return SystemServicesFlutterApiCodec.INSTANCE; } public void onDeviceOrientationChanged(@NonNull String orientationArg, Reply callback) { BasicMessageChannel channel = - new BasicMessageChannel<>(binaryMessenger, "dev.flutter.pigeon.SystemServicesFlutterApi.onDeviceOrientationChanged", getCodec()); - channel.send(new ArrayList(Arrays.asList(orientationArg)), channelReply -> { - callback.reply(null); - }); + new BasicMessageChannel<>( + binaryMessenger, + "dev.flutter.pigeon.SystemServicesFlutterApi.onDeviceOrientationChanged", + getCodec()); + channel.send( + new ArrayList(Arrays.asList(orientationArg)), + channelReply -> { + callback.reply(null); + }); } } + private static Map wrapError(Throwable exception) { Map errorMap = new HashMap<>(); errorMap.put("message", exception.toString()); errorMap.put("code", exception.getClass().getSimpleName()); - errorMap.put("details", "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); + errorMap.put( + "details", + "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception)); return errorMap; } } diff --git a/packages/camera/camera_android_camerax/lib/src/camerax_library.pigeon.dart b/packages/camera/camera_android_camerax/lib/src/camerax_library.pigeon.dart index 7468d66ad49e..6d8869968f41 100644 --- a/packages/camera/camera_android_camerax/lib/src/camerax_library.pigeon.dart +++ b/packages/camera/camera_android_camerax/lib/src/camerax_library.pigeon.dart @@ -43,7 +43,8 @@ class JavaObjectHostApi { /// Constructor for [JavaObjectHostApi]. 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. - JavaObjectHostApi({BinaryMessenger? binaryMessenger}) : _binaryMessenger = binaryMessenger; + JavaObjectHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; final BinaryMessenger? _binaryMessenger; @@ -51,7 +52,8 @@ class JavaObjectHostApi { Future dispose(int arg_identifier) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.JavaObjectHostApi.dispose', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.JavaObjectHostApi.dispose', codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send([arg_identifier]) as Map?; if (replyMap == null) { @@ -60,7 +62,8 @@ class JavaObjectHostApi { message: 'Unable to establish connection on channel.', ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -75,22 +78,27 @@ class JavaObjectHostApi { class _JavaObjectFlutterApiCodec extends StandardMessageCodec { const _JavaObjectFlutterApiCodec(); } + abstract class JavaObjectFlutterApi { static const MessageCodec codec = _JavaObjectFlutterApiCodec(); void dispose(int identifier); - static void setup(JavaObjectFlutterApi? api, {BinaryMessenger? binaryMessenger}) { + static void setup(JavaObjectFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.JavaObjectFlutterApi.dispose', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.JavaObjectFlutterApi.dispose', codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.JavaObjectFlutterApi.dispose was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.JavaObjectFlutterApi.dispose was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, 'Argument for dev.flutter.pigeon.JavaObjectFlutterApi.dispose was null, expected non-null int.'); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.JavaObjectFlutterApi.dispose was null, expected non-null int.'); api.dispose(arg_identifier!); return; }); @@ -107,7 +115,8 @@ class CameraInfoHostApi { /// Constructor for [CameraInfoHostApi]. 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. - CameraInfoHostApi({BinaryMessenger? binaryMessenger}) : _binaryMessenger = binaryMessenger; + CameraInfoHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; final BinaryMessenger? _binaryMessenger; @@ -115,7 +124,8 @@ class CameraInfoHostApi { Future getSensorRotationDegrees(int arg_identifier) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CameraInfoHostApi.getSensorRotationDegrees', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.CameraInfoHostApi.getSensorRotationDegrees', codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send([arg_identifier]) as Map?; if (replyMap == null) { @@ -124,7 +134,8 @@ class CameraInfoHostApi { message: 'Unable to establish connection on channel.', ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -144,22 +155,27 @@ class CameraInfoHostApi { class _CameraInfoFlutterApiCodec extends StandardMessageCodec { const _CameraInfoFlutterApiCodec(); } + abstract class CameraInfoFlutterApi { static const MessageCodec codec = _CameraInfoFlutterApiCodec(); void create(int identifier); - static void setup(CameraInfoFlutterApi? api, {BinaryMessenger? binaryMessenger}) { + static void setup(CameraInfoFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CameraInfoFlutterApi.create', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.CameraInfoFlutterApi.create', codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.CameraInfoFlutterApi.create was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.CameraInfoFlutterApi.create was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, 'Argument for dev.flutter.pigeon.CameraInfoFlutterApi.create was null, expected non-null int.'); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.CameraInfoFlutterApi.create was null, expected non-null int.'); api.create(arg_identifier!); return; }); @@ -176,7 +192,8 @@ class CameraSelectorHostApi { /// Constructor for [CameraSelectorHostApi]. 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. - CameraSelectorHostApi({BinaryMessenger? binaryMessenger}) : _binaryMessenger = binaryMessenger; + CameraSelectorHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; final BinaryMessenger? _binaryMessenger; @@ -184,16 +201,19 @@ class CameraSelectorHostApi { Future create(int arg_identifier, int? arg_lensFacing) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CameraSelectorHostApi.create', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.CameraSelectorHostApi.create', codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = - await channel.send([arg_identifier, arg_lensFacing]) as Map?; + await channel.send([arg_identifier, arg_lensFacing]) + as Map?; if (replyMap == null) { throw PlatformException( code: 'channel-error', message: 'Unable to establish connection on channel.', ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -204,18 +224,22 @@ class CameraSelectorHostApi { } } - Future> filter(int arg_identifier, List arg_cameraInfoIds) async { + Future> filter( + int arg_identifier, List arg_cameraInfoIds) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CameraSelectorHostApi.filter', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.CameraSelectorHostApi.filter', codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = - await channel.send([arg_identifier, arg_cameraInfoIds]) as Map?; + await channel.send([arg_identifier, arg_cameraInfoIds]) + as Map?; if (replyMap == null) { throw PlatformException( code: 'channel-error', message: 'Unable to establish connection on channel.', ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -235,22 +259,27 @@ class CameraSelectorHostApi { class _CameraSelectorFlutterApiCodec extends StandardMessageCodec { const _CameraSelectorFlutterApiCodec(); } + abstract class CameraSelectorFlutterApi { static const MessageCodec codec = _CameraSelectorFlutterApiCodec(); void create(int identifier, int? lensFacing); - static void setup(CameraSelectorFlutterApi? api, {BinaryMessenger? binaryMessenger}) { + static void setup(CameraSelectorFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CameraSelectorFlutterApi.create', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.CameraSelectorFlutterApi.create', codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.CameraSelectorFlutterApi.create was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.CameraSelectorFlutterApi.create was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, 'Argument for dev.flutter.pigeon.CameraSelectorFlutterApi.create was null, expected non-null int.'); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.CameraSelectorFlutterApi.create was null, expected non-null int.'); final int? arg_lensFacing = (args[1] as int?); api.create(arg_identifier!, arg_lensFacing); return; @@ -268,15 +297,18 @@ class ProcessCameraProviderHostApi { /// Constructor for [ProcessCameraProviderHostApi]. 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. - ProcessCameraProviderHostApi({BinaryMessenger? binaryMessenger}) : _binaryMessenger = binaryMessenger; + ProcessCameraProviderHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; final BinaryMessenger? _binaryMessenger; - static const MessageCodec codec = _ProcessCameraProviderHostApiCodec(); + static const MessageCodec codec = + _ProcessCameraProviderHostApiCodec(); Future getInstance() async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.ProcessCameraProviderHostApi.getInstance', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.ProcessCameraProviderHostApi.getInstance', codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send(null) as Map?; if (replyMap == null) { @@ -285,7 +317,8 @@ class ProcessCameraProviderHostApi { message: 'Unable to establish connection on channel.', ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -303,7 +336,9 @@ class ProcessCameraProviderHostApi { Future> getAvailableCameraInfos(int arg_identifier) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.ProcessCameraProviderHostApi.getAvailableCameraInfos', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.ProcessCameraProviderHostApi.getAvailableCameraInfos', + codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send([arg_identifier]) as Map?; if (replyMap == null) { @@ -312,7 +347,8 @@ class ProcessCameraProviderHostApi { message: 'Unable to establish connection on channel.', ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -328,18 +364,25 @@ class ProcessCameraProviderHostApi { } } - Future bindToLifecycle(int arg_identifier, int arg_cameraSelectorIdentifier, List arg_useCaseIds) async { + Future bindToLifecycle(int arg_identifier, + int arg_cameraSelectorIdentifier, List arg_useCaseIds) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle', codec, binaryMessenger: _binaryMessenger); - final Map? replyMap = - await channel.send([arg_identifier, arg_cameraSelectorIdentifier, arg_useCaseIds]) as Map?; + 'dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel.send([ + arg_identifier, + arg_cameraSelectorIdentifier, + arg_useCaseIds + ]) as Map?; if (replyMap == null) { throw PlatformException( code: 'channel-error', message: 'Unable to establish connection on channel.', ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -357,16 +400,19 @@ class ProcessCameraProviderHostApi { Future unbind(int arg_identifier, List arg_useCaseIds) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.ProcessCameraProviderHostApi.unbind', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.ProcessCameraProviderHostApi.unbind', codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = - await channel.send([arg_identifier, arg_useCaseIds]) as Map?; + await channel.send([arg_identifier, arg_useCaseIds]) + as Map?; if (replyMap == null) { throw PlatformException( code: 'channel-error', message: 'Unable to establish connection on channel.', ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -379,7 +425,8 @@ class ProcessCameraProviderHostApi { Future unbindAll(int arg_identifier) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.ProcessCameraProviderHostApi.unbindAll', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.ProcessCameraProviderHostApi.unbindAll', codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send([arg_identifier]) as Map?; if (replyMap == null) { @@ -388,7 +435,8 @@ class ProcessCameraProviderHostApi { message: 'Unable to establish connection on channel.', ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -403,22 +451,28 @@ class ProcessCameraProviderHostApi { class _ProcessCameraProviderFlutterApiCodec extends StandardMessageCodec { const _ProcessCameraProviderFlutterApiCodec(); } + abstract class ProcessCameraProviderFlutterApi { - static const MessageCodec codec = _ProcessCameraProviderFlutterApiCodec(); + static const MessageCodec codec = + _ProcessCameraProviderFlutterApiCodec(); void create(int identifier); - static void setup(ProcessCameraProviderFlutterApi? api, {BinaryMessenger? binaryMessenger}) { + static void setup(ProcessCameraProviderFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.ProcessCameraProviderFlutterApi.create', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.ProcessCameraProviderFlutterApi.create', codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.ProcessCameraProviderFlutterApi.create was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.ProcessCameraProviderFlutterApi.create was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, 'Argument for dev.flutter.pigeon.ProcessCameraProviderFlutterApi.create was null, expected non-null int.'); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.ProcessCameraProviderFlutterApi.create was null, expected non-null int.'); api.create(arg_identifier!); return; }); @@ -430,6 +484,7 @@ abstract class ProcessCameraProviderFlutterApi { class _CameraFlutterApiCodec extends StandardMessageCodec { const _CameraFlutterApiCodec(); } + abstract class CameraFlutterApi { static const MessageCodec codec = _CameraFlutterApiCodec(); @@ -437,15 +492,18 @@ abstract class CameraFlutterApi { static void setup(CameraFlutterApi? api, {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CameraFlutterApi.create', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.CameraFlutterApi.create', codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.CameraFlutterApi.create was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.CameraFlutterApi.create was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, 'Argument for dev.flutter.pigeon.CameraFlutterApi.create was null, expected non-null int.'); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.CameraFlutterApi.create was null, expected non-null int.'); api.create(arg_identifier!); return; }); @@ -461,20 +519,19 @@ class _SystemServicesHostApiCodec extends StandardMessageCodec { if (value is CameraPermissionsErrorData) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else -{ + } else { super.writeValue(buffer, value); } } + @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: + case 128: return CameraPermissionsErrorData.decode(readValue(buffer)!); - - default: + + default: return super.readValueOfType(type, buffer); - } } } @@ -483,24 +540,29 @@ class SystemServicesHostApi { /// Constructor for [SystemServicesHostApi]. 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. - SystemServicesHostApi({BinaryMessenger? binaryMessenger}) : _binaryMessenger = binaryMessenger; + SystemServicesHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; final BinaryMessenger? _binaryMessenger; static const MessageCodec codec = _SystemServicesHostApiCodec(); - Future requestCameraPermissions(bool arg_enableAudio) async { + Future requestCameraPermissions( + bool arg_enableAudio) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions', codec, binaryMessenger: _binaryMessenger); - final Map? replyMap = - await channel.send([arg_enableAudio]) as Map?; + 'dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions', + codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = await channel + .send([arg_enableAudio]) as Map?; if (replyMap == null) { throw PlatformException( code: 'channel-error', message: 'Unable to establish connection on channel.', ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -511,18 +573,23 @@ class SystemServicesHostApi { } } - Future startListeningForDeviceOrientationChange(bool arg_isFrontFacing, int arg_sensorOrientation) async { + Future startListeningForDeviceOrientationChange( + bool arg_isFrontFacing, int arg_sensorOrientation) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange', + codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = - await channel.send([arg_isFrontFacing, arg_sensorOrientation]) as Map?; + await channel.send([arg_isFrontFacing, arg_sensorOrientation]) + as Map?; if (replyMap == null) { throw PlatformException( code: 'channel-error', message: 'Unable to establish connection on channel.', ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -535,7 +602,9 @@ class SystemServicesHostApi { Future stopListeningForDeviceOrientationChange() async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.SystemServicesHostApi.stopListeningForDeviceOrientationChange', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.SystemServicesHostApi.stopListeningForDeviceOrientationChange', + codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send(null) as Map?; if (replyMap == null) { @@ -544,7 +613,8 @@ class SystemServicesHostApi { message: 'Unable to establish connection on channel.', ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -559,22 +629,28 @@ class SystemServicesHostApi { class _SystemServicesFlutterApiCodec extends StandardMessageCodec { const _SystemServicesFlutterApiCodec(); } + abstract class SystemServicesFlutterApi { static const MessageCodec codec = _SystemServicesFlutterApiCodec(); void onDeviceOrientationChanged(String orientation); - static void setup(SystemServicesFlutterApi? api, {BinaryMessenger? binaryMessenger}) { + static void setup(SystemServicesFlutterApi? api, + {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.SystemServicesFlutterApi.onDeviceOrientationChanged', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.SystemServicesFlutterApi.onDeviceOrientationChanged', + codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.SystemServicesFlutterApi.onDeviceOrientationChanged was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.SystemServicesFlutterApi.onDeviceOrientationChanged was null.'); final List args = (message as List?)!; final String? arg_orientation = (args[0] as String?); - assert(arg_orientation != null, 'Argument for dev.flutter.pigeon.SystemServicesFlutterApi.onDeviceOrientationChanged was null, expected non-null String.'); + assert(arg_orientation != null, + 'Argument for dev.flutter.pigeon.SystemServicesFlutterApi.onDeviceOrientationChanged was null, expected non-null String.'); api.onDeviceOrientationChanged(arg_orientation!); return; }); diff --git a/packages/camera/camera_android_camerax/test/system_services_test.dart b/packages/camera/camera_android_camerax/test/system_services_test.dart index 571f1923e367..c8a2721ecc2d 100644 --- a/packages/camera/camera_android_camerax/test/system_services_test.dart +++ b/packages/camera/camera_android_camerax/test/system_services_test.dart @@ -64,10 +64,8 @@ void main() { MockTestSystemServicesHostApi(); TestSystemServicesHostApi.setup(mockApi); - SystemServices.startListeningForDeviceOrientationChange( - true, 90); - verify(mockApi.startListeningForDeviceOrientationChange( - true, 90)); + SystemServices.startListeningForDeviceOrientationChange(true, 90); + verify(mockApi.startListeningForDeviceOrientationChange(true, 90)); }); test('stopListeningForDeviceOrientationChangeTest', () async { @@ -84,7 +82,8 @@ void main() { .listen((DeviceOrientationChangedEvent event) { expect(event.orientation, equals(DeviceOrientation.landscapeLeft)); }); - SystemServicesFlutterApiImpl().onDeviceOrientationChanged('LANDSCAPE_LEFT'); + SystemServicesFlutterApiImpl() + .onDeviceOrientationChanged('LANDSCAPE_LEFT'); }); test( diff --git a/packages/camera/camera_android_camerax/test/test_camerax_library.pigeon.dart b/packages/camera/camera_android_camerax/test/test_camerax_library.pigeon.dart index 44ed76c3e386..349004c7e6de 100644 --- a/packages/camera/camera_android_camerax/test/test_camerax_library.pigeon.dart +++ b/packages/camera/camera_android_camerax/test/test_camerax_library.pigeon.dart @@ -16,22 +16,27 @@ import 'package:camera_android_camerax/src/camerax_library.pigeon.dart'; class _TestJavaObjectHostApiCodec extends StandardMessageCodec { const _TestJavaObjectHostApiCodec(); } + abstract class TestJavaObjectHostApi { static const MessageCodec codec = _TestJavaObjectHostApiCodec(); void dispose(int identifier); - static void setup(TestJavaObjectHostApi? api, {BinaryMessenger? binaryMessenger}) { + static void setup(TestJavaObjectHostApi? api, + {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.JavaObjectHostApi.dispose', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.JavaObjectHostApi.dispose', codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.JavaObjectHostApi.dispose was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.JavaObjectHostApi.dispose was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, 'Argument for dev.flutter.pigeon.JavaObjectHostApi.dispose was null, expected non-null int.'); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.JavaObjectHostApi.dispose was null, expected non-null int.'); api.dispose(arg_identifier!); return {}; }); @@ -43,22 +48,28 @@ abstract class TestJavaObjectHostApi { class _TestCameraInfoHostApiCodec extends StandardMessageCodec { const _TestCameraInfoHostApiCodec(); } + abstract class TestCameraInfoHostApi { static const MessageCodec codec = _TestCameraInfoHostApiCodec(); int getSensorRotationDegrees(int identifier); - static void setup(TestCameraInfoHostApi? api, {BinaryMessenger? binaryMessenger}) { + static void setup(TestCameraInfoHostApi? api, + {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CameraInfoHostApi.getSensorRotationDegrees', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.CameraInfoHostApi.getSensorRotationDegrees', + codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.CameraInfoHostApi.getSensorRotationDegrees was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.CameraInfoHostApi.getSensorRotationDegrees was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, 'Argument for dev.flutter.pigeon.CameraInfoHostApi.getSensorRotationDegrees was null, expected non-null int.'); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.CameraInfoHostApi.getSensorRotationDegrees was null, expected non-null int.'); final int output = api.getSensorRotationDegrees(arg_identifier!); return {'result': output}; }); @@ -70,23 +81,28 @@ abstract class TestCameraInfoHostApi { class _TestCameraSelectorHostApiCodec extends StandardMessageCodec { const _TestCameraSelectorHostApiCodec(); } + abstract class TestCameraSelectorHostApi { static const MessageCodec codec = _TestCameraSelectorHostApiCodec(); void create(int identifier, int? lensFacing); List filter(int identifier, List cameraInfoIds); - static void setup(TestCameraSelectorHostApi? api, {BinaryMessenger? binaryMessenger}) { + static void setup(TestCameraSelectorHostApi? api, + {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CameraSelectorHostApi.create', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.CameraSelectorHostApi.create', codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.CameraSelectorHostApi.create was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.CameraSelectorHostApi.create was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, 'Argument for dev.flutter.pigeon.CameraSelectorHostApi.create was null, expected non-null int.'); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.CameraSelectorHostApi.create was null, expected non-null int.'); final int? arg_lensFacing = (args[1] as int?); api.create(arg_identifier!, arg_lensFacing); return {}; @@ -95,18 +111,24 @@ abstract class TestCameraSelectorHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.CameraSelectorHostApi.filter', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.CameraSelectorHostApi.filter', codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.CameraSelectorHostApi.filter was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.CameraSelectorHostApi.filter was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, 'Argument for dev.flutter.pigeon.CameraSelectorHostApi.filter was null, expected non-null int.'); - final List? arg_cameraInfoIds = (args[1] as List?)?.cast(); - assert(arg_cameraInfoIds != null, 'Argument for dev.flutter.pigeon.CameraSelectorHostApi.filter was null, expected non-null List.'); - final List output = api.filter(arg_identifier!, arg_cameraInfoIds!); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.CameraSelectorHostApi.filter was null, expected non-null int.'); + final List? arg_cameraInfoIds = + (args[1] as List?)?.cast(); + assert(arg_cameraInfoIds != null, + 'Argument for dev.flutter.pigeon.CameraSelectorHostApi.filter was null, expected non-null List.'); + final List output = + api.filter(arg_identifier!, arg_cameraInfoIds!); return {'result': output}; }); } @@ -117,18 +139,23 @@ abstract class TestCameraSelectorHostApi { class _TestProcessCameraProviderHostApiCodec extends StandardMessageCodec { const _TestProcessCameraProviderHostApiCodec(); } + abstract class TestProcessCameraProviderHostApi { - static const MessageCodec codec = _TestProcessCameraProviderHostApiCodec(); + static const MessageCodec codec = + _TestProcessCameraProviderHostApiCodec(); Future getInstance(); List getAvailableCameraInfos(int identifier); - int bindToLifecycle(int identifier, int cameraSelectorIdentifier, List useCaseIds); + int bindToLifecycle( + int identifier, int cameraSelectorIdentifier, List useCaseIds); void unbind(int identifier, List useCaseIds); void unbindAll(int identifier); - static void setup(TestProcessCameraProviderHostApi? api, {BinaryMessenger? binaryMessenger}) { + static void setup(TestProcessCameraProviderHostApi? api, + {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.ProcessCameraProviderHostApi.getInstance', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.ProcessCameraProviderHostApi.getInstance', codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMockMessageHandler(null); } else { @@ -141,53 +168,71 @@ abstract class TestProcessCameraProviderHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.ProcessCameraProviderHostApi.getAvailableCameraInfos', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.ProcessCameraProviderHostApi.getAvailableCameraInfos', + codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.getAvailableCameraInfos was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.getAvailableCameraInfos was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.getAvailableCameraInfos was null, expected non-null int.'); - final List output = api.getAvailableCameraInfos(arg_identifier!); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.getAvailableCameraInfos was null, expected non-null int.'); + final List output = + api.getAvailableCameraInfos(arg_identifier!); return {'result': output}; }); } } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle', + codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle was null, expected non-null int.'); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle was null, expected non-null int.'); final int? arg_cameraSelectorIdentifier = (args[1] as int?); - assert(arg_cameraSelectorIdentifier != null, 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle was null, expected non-null int.'); - final List? arg_useCaseIds = (args[2] as List?)?.cast(); - assert(arg_useCaseIds != null, 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle was null, expected non-null List.'); - final int output = api.bindToLifecycle(arg_identifier!, arg_cameraSelectorIdentifier!, arg_useCaseIds!); + assert(arg_cameraSelectorIdentifier != null, + 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle was null, expected non-null int.'); + final List? arg_useCaseIds = + (args[2] as List?)?.cast(); + assert(arg_useCaseIds != null, + 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.bindToLifecycle was null, expected non-null List.'); + final int output = api.bindToLifecycle( + arg_identifier!, arg_cameraSelectorIdentifier!, arg_useCaseIds!); return {'result': output}; }); } } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.ProcessCameraProviderHostApi.unbind', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.ProcessCameraProviderHostApi.unbind', codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.unbind was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.unbind was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.unbind was null, expected non-null int.'); - final List? arg_useCaseIds = (args[1] as List?)?.cast(); - assert(arg_useCaseIds != null, 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.unbind was null, expected non-null List.'); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.unbind was null, expected non-null int.'); + final List? arg_useCaseIds = + (args[1] as List?)?.cast(); + assert(arg_useCaseIds != null, + 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.unbind was null, expected non-null List.'); api.unbind(arg_identifier!, arg_useCaseIds!); return {}; }); @@ -195,15 +240,18 @@ abstract class TestProcessCameraProviderHostApi { } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.ProcessCameraProviderHostApi.unbindAll', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.ProcessCameraProviderHostApi.unbindAll', codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.unbindAll was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.unbindAll was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); - assert(arg_identifier != null, 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.unbindAll was null, expected non-null int.'); + assert(arg_identifier != null, + 'Argument for dev.flutter.pigeon.ProcessCameraProviderHostApi.unbindAll was null, expected non-null int.'); api.unbindAll(arg_identifier!); return {}; }); @@ -219,67 +267,83 @@ class _TestSystemServicesHostApiCodec extends StandardMessageCodec { if (value is CameraPermissionsErrorData) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else -{ + } else { super.writeValue(buffer, value); } } + @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: + case 128: return CameraPermissionsErrorData.decode(readValue(buffer)!); - - default: + + default: return super.readValueOfType(type, buffer); - } } } + abstract class TestSystemServicesHostApi { static const MessageCodec codec = _TestSystemServicesHostApiCodec(); - Future requestCameraPermissions(bool enableAudio); - void startListeningForDeviceOrientationChange(bool isFrontFacing, int sensorOrientation); + Future requestCameraPermissions( + bool enableAudio); + void startListeningForDeviceOrientationChange( + bool isFrontFacing, int sensorOrientation); void stopListeningForDeviceOrientationChange(); - static void setup(TestSystemServicesHostApi? api, {BinaryMessenger? binaryMessenger}) { + static void setup(TestSystemServicesHostApi? api, + {BinaryMessenger? binaryMessenger}) { { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions', + codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions was null.'); final List args = (message as List?)!; final bool? arg_enableAudio = (args[0] as bool?); - assert(arg_enableAudio != null, 'Argument for dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions was null, expected non-null bool.'); - final CameraPermissionsErrorData? output = await api.requestCameraPermissions(arg_enableAudio!); + assert(arg_enableAudio != null, + 'Argument for dev.flutter.pigeon.SystemServicesHostApi.requestCameraPermissions was null, expected non-null bool.'); + final CameraPermissionsErrorData? output = + await api.requestCameraPermissions(arg_enableAudio!); return {'result': output}; }); } } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange', + codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMockMessageHandler(null); } else { channel.setMockMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange was null.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange was null.'); final List args = (message as List?)!; final bool? arg_isFrontFacing = (args[0] as bool?); - assert(arg_isFrontFacing != null, 'Argument for dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange was null, expected non-null bool.'); + assert(arg_isFrontFacing != null, + 'Argument for dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange was null, expected non-null bool.'); final int? arg_sensorOrientation = (args[1] as int?); - assert(arg_sensorOrientation != null, 'Argument for dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange was null, expected non-null int.'); - api.startListeningForDeviceOrientationChange(arg_isFrontFacing!, arg_sensorOrientation!); + assert(arg_sensorOrientation != null, + 'Argument for dev.flutter.pigeon.SystemServicesHostApi.startListeningForDeviceOrientationChange was null, expected non-null int.'); + api.startListeningForDeviceOrientationChange( + arg_isFrontFacing!, arg_sensorOrientation!); return {}; }); } } { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.SystemServicesHostApi.stopListeningForDeviceOrientationChange', codec, binaryMessenger: binaryMessenger); + 'dev.flutter.pigeon.SystemServicesHostApi.stopListeningForDeviceOrientationChange', + codec, + binaryMessenger: binaryMessenger); if (api == null) { channel.setMockMessageHandler(null); } else { From 02a939a0ecf221cc99678540d6bd934045c68a56 Mon Sep 17 00:00:00 2001 From: camsim99 Date: Wed, 25 Jan 2023 15:35:54 -0800 Subject: [PATCH 11/13] Remove merge conflict reside --- .../io/flutter/plugins/camerax/CameraAndroidCameraxPlugin.java | 3 --- 1 file changed, 3 deletions(-) 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 f00476940f2a..64eb0742c385 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 @@ -67,9 +67,6 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { @Override public void onAttachedToActivity(@NonNull ActivityPluginBinding activityPluginBinding) { - plugin.systemServicesHostApi.setActivity(activityPluginBinding.getActivity()); - plugin.systemServicesHostApi.setPermissionsRegistry( - activityPluginBinding::addRequestPermissionsResultListener); setUp(pluginBinding.getBinaryMessenger(), pluginBinding.getApplicationContext()); updateContext(pluginBinding.getApplicationContext()); processCameraProviderHostApi.setLifecycleOwner( From fe7a6ca82be03785b08aa12bb68b4473cd34e15a Mon Sep 17 00:00:00 2001 From: camsim99 Date: Wed, 25 Jan 2023 15:55:22 -0800 Subject: [PATCH 12/13] Fix test --- .../flutter/plugins/camerax/CameraAndroidCameraxPlugin.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 64eb0742c385..5d1dc1eea1a9 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 @@ -38,7 +38,9 @@ void setUp(BinaryMessenger binaryMessenger, Context context, TextureRegistry tex // Set up Host APIs. GeneratedCameraXLibrary.CameraInfoHostApi.setup( - binaryMessenger, new CameraInfoHostApiImpl(instanceManager)); + binaryMessenger, + new CameraInfoHostApiImpl(instanceManager), + pluginBinding.getTextureRegistry()); GeneratedCameraXLibrary.CameraSelectorHostApi.setup( binaryMessenger, new CameraSelectorHostApiImpl(binaryMessenger, instanceManager)); GeneratedCameraXLibrary.JavaObjectHostApi.setup( From 7811444a059f90d642889ec0061082bbdea585b7 Mon Sep 17 00:00:00 2001 From: camsim99 Date: Wed, 25 Jan 2023 16:05:29 -0800 Subject: [PATCH 13/13] Fix bad pasting job --- .../plugins/camerax/CameraAndroidCameraxPlugin.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) 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 5d1dc1eea1a9..c35394f01d82 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 @@ -38,9 +38,7 @@ void setUp(BinaryMessenger binaryMessenger, Context context, TextureRegistry tex // Set up Host APIs. GeneratedCameraXLibrary.CameraInfoHostApi.setup( - binaryMessenger, - new CameraInfoHostApiImpl(instanceManager), - pluginBinding.getTextureRegistry()); + binaryMessenger, new CameraInfoHostApiImpl(instanceManager)); GeneratedCameraXLibrary.CameraSelectorHostApi.setup( binaryMessenger, new CameraSelectorHostApiImpl(binaryMessenger, instanceManager)); GeneratedCameraXLibrary.JavaObjectHostApi.setup( @@ -69,7 +67,10 @@ public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) { @Override public void onAttachedToActivity(@NonNull ActivityPluginBinding activityPluginBinding) { - setUp(pluginBinding.getBinaryMessenger(), pluginBinding.getApplicationContext()); + setUp( + pluginBinding.getBinaryMessenger(), + pluginBinding.getApplicationContext(), + pluginBinding.getTextureRegistry()); updateContext(pluginBinding.getApplicationContext()); processCameraProviderHostApi.setLifecycleOwner( (LifecycleOwner) activityPluginBinding.getActivity());