From 1d7f43939053c0b891baa23358f4e2abf3f5bafa Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Wed, 11 Jan 2023 11:23:09 -0800 Subject: [PATCH 01/13] Adding availableCameras to camerax camera implementation --- .../camerax/CameraSelectorHostApiImpl.java | 3 -- .../lib/src/android_camera_camerax.dart | 46 ++++++++++++++++++- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraSelectorHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraSelectorHostApiImpl.java index 9c559a72e63c..7d03068ce74f 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraSelectorHostApiImpl.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraSelectorHostApiImpl.java @@ -52,12 +52,9 @@ public List filter(@NonNull Long identifier, @NonNull List cameraInf } List filteredCameraInfos = cameraSelector.filter(cameraInfosForFilter); - final CameraInfoFlutterApiImpl cameraInfoFlutterApiImpl = - new CameraInfoFlutterApiImpl(binaryMessenger, instanceManager); List filteredCameraInfosIds = new ArrayList(); for (CameraInfo cameraInfo : filteredCameraInfos) { - cameraInfoFlutterApiImpl.create(cameraInfo, result -> {}); Long filteredCameraInfoId = instanceManager.getIdentifierForStrongReference(cameraInfo); filteredCameraInfosIds.add(filteredCameraInfoId); } diff --git a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart index f03273861793..4dd04c9d4df5 100644 --- a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart +++ b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart @@ -3,6 +3,9 @@ // found in the LICENSE file. import 'dart:async'; +import 'process_camera_provider.dart'; +import 'camera_info.dart'; +import 'camera_selector.dart'; import 'package:camera_platform_interface/camera_platform_interface.dart'; @@ -16,6 +19,47 @@ class AndroidCameraCameraX extends CameraPlatform { /// Returns list of all available cameras and their descriptions. @override Future> availableCameras() async { - throw UnimplementedError('availableCameras() is not implemented.'); + final List cameraDescriptions = []; + + ProcessCameraProvider processCameraProvider = + await ProcessCameraProvider.getInstance(); + final List cameraInfos = + await processCameraProvider!.getAvailableCameraInfos(); + + final CameraSelector backCameraSelector = + CameraSelector.getDefaultBackCamera(); + final CameraSelector frontCameraSelector = + CameraSelector.getDefaultFrontCamera(); + + CameraLensDirection cameraLensDirection; + int cameraCount = 0; + int cameraSensorOrientation; + String cameraName; + + for (final CameraInfo cameraInfo in cameraInfos) { + // Determine the lens direction by filtering the CameraInfo + // TODO(gmackall): replace this with call to CameraInfo.getLensFacing when changes containing that method are available + if ((await backCameraSelector.filter([cameraInfo])) + .isNotEmpty) { + cameraLensDirection = CameraLensDirection.back; + } else if ((await frontCameraSelector.filter([cameraInfo])) + .isNotEmpty) { + cameraLensDirection = CameraLensDirection.front; + } else { + //Skip this CameraInfo as its lens direction is unknown + continue; + } + + cameraSensorOrientation = await cameraInfo.getSensorRotationDegrees(); + cameraName = 'Camera $cameraCount'; + cameraCount++; + + cameraDescriptions.add(CameraDescription( + name: cameraName, + lensDirection: cameraLensDirection, + sensorOrientation: cameraSensorOrientation)); + } + + return cameraDescriptions; } } From 22fd08a96a6cecadff0bfc38d208408fc6d253ce Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Wed, 18 Jan 2023 15:58:12 -0800 Subject: [PATCH 02/13] Marking loop variables as nullable in availableCameras --- .../lib/src/android_camera_camerax.dart | 6 +++--- .../test/android_camera_camerax_test.dart | 0 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart diff --git a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart index 4dd04c9d4df5..79437837d38a 100644 --- a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart +++ b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart @@ -31,10 +31,10 @@ class AndroidCameraCameraX extends CameraPlatform { final CameraSelector frontCameraSelector = CameraSelector.getDefaultFrontCamera(); - CameraLensDirection cameraLensDirection; + CameraLensDirection? cameraLensDirection; int cameraCount = 0; - int cameraSensorOrientation; - String cameraName; + int? cameraSensorOrientation; + String? cameraName; for (final CameraInfo cameraInfo in cameraInfos) { // Determine the lens direction by filtering the CameraInfo diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart new file mode 100644 index 000000000000..e69de29bb2d1 From 3cc21d97203ac45dfaeef3e624e1c8ed23f8e0de Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Tue, 24 Jan 2023 10:56:35 -0800 Subject: [PATCH 03/13] adding testing for android_camerax availableCameras() --- .../test/android_camera_camerax_test.dart | 119 +++++++++++++ .../android_camera_camerax_test.mocks.dart | 168 ++++++++++++++++++ 2 files changed, 287 insertions(+) create mode 100644 packages/camera/camera_android_camerax/test/android_camera_camerax_test.mocks.dart diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart index e69de29bb2d1..e09980aa1f21 100644 --- a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart +++ b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart @@ -0,0 +1,119 @@ +import 'package:camera_android_camerax/camera_android_camerax.dart'; +import 'package:camera_android_camerax/src/camera_info.dart'; +import 'package:camera_android_camerax/src/camera_selector.dart'; +import 'package:camera_android_camerax/src/instance_manager.dart'; +import 'package:camera_android_camerax/src/java_object.dart'; +import 'package:camera_android_camerax/src/process_camera_provider.dart'; +import 'package:camera_platform_interface/camera_platform_interface.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; + +import 'android_camera_camerax_test.mocks.dart'; + +//import 'process_camera_provider_test.mocks.dart'; +import 'test_camerax_library.pigeon.dart'; + +@GenerateMocks([ + ProcessCameraProvider, + CameraSelector, + CameraInfo, + TestProcessCameraProviderHostApi, + TestCameraSelectorHostApi, + TestCameraInfoHostApi, +]) +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + test('Should fetch CameraDescription instances for available cameras', + () async { + // Arrange + final List returnData = [ + { + 'name': 'Camera 0', + 'lensFacing': 'back', + 'sensorOrientation': 0 + }, + { + 'name': 'Camera 1', + 'lensFacing': 'front', + 'sensorOrientation': 90 + } + ]; + + final MockTestProcessCameraProviderHostApi + mockTestProcessCameraProviderHostApi = + MockTestProcessCameraProviderHostApi(); + TestProcessCameraProviderHostApi.setup( + mockTestProcessCameraProviderHostApi); + + final MockTestCameraSelectorHostApi mockTestCameraSelectorHostApi = + MockTestCameraSelectorHostApi(); + TestCameraSelectorHostApi.setup(mockTestCameraSelectorHostApi); + + MockTestCameraInfoHostApi mockTestCameraInfoHostApi = + MockTestCameraInfoHostApi(); + TestCameraInfoHostApi.setup(mockTestCameraInfoHostApi); + + final InstanceManager instanceManager = JavaObject.globalInstanceManager; + final ProcessCameraProvider processCameraProvider = + ProcessCameraProvider.detached( + instanceManager: instanceManager, + ); + + instanceManager.addHostCreatedInstance( + processCameraProvider, + 0, + onCopy: (_) => ProcessCameraProvider.detached(), + ); + final CameraInfo fakeBackCameraInfo = + CameraInfo.detached(instanceManager: instanceManager); + instanceManager.addHostCreatedInstance( + fakeBackCameraInfo, + 1, + onCopy: (_) => CameraInfo.detached(), + ); + final CameraInfo fakeFrontCameraInfo = + CameraInfo.detached(instanceManager: instanceManager); + instanceManager.addHostCreatedInstance( + fakeFrontCameraInfo, + 2, + onCopy: (_) => CameraInfo.detached(), + ); + + when(mockTestProcessCameraProviderHostApi.getInstance()) + .thenAnswer((_) async => 0); + when(mockTestProcessCameraProviderHostApi.getAvailableCameraInfos(0)) + .thenReturn([1, 2]); + + when(mockTestCameraSelectorHostApi.filter(any, [1])).thenReturn([1]); + final List> responses = >[ + [], + [2] + ]; + when(mockTestCameraSelectorHostApi.filter(any, [2])) + .thenAnswer((_) => responses.removeAt(0)); + + when(mockTestCameraInfoHostApi.getSensorRotationDegrees(1)).thenReturn(0); + when(mockTestCameraInfoHostApi.getSensorRotationDegrees(2)).thenReturn(90); + + AndroidCameraCameraX.registerWith(); + final AndroidCameraCameraX androidCameraCamerax = AndroidCameraCameraX(); + final List cameraDescriptions = + await androidCameraCamerax.availableCameras(); + + expect(cameraDescriptions.length, returnData.length); + for (int i = 0; i < returnData.length; i++) { + final Map typedData = + (returnData[i] as Map).cast(); + final CameraDescription cameraDescription = CameraDescription( + name: typedData['name']! as String, + lensDirection: (typedData['lensFacing']! as String) == 'front' + ? CameraLensDirection.front + : CameraLensDirection.back, + sensorOrientation: typedData['sensorOrientation']! as int, + ); + expect(cameraDescriptions[i], cameraDescription); + } + }); +} diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.mocks.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.mocks.dart new file mode 100644 index 000000000000..c7d373e33a05 --- /dev/null +++ b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.mocks.dart @@ -0,0 +1,168 @@ +// Mocks generated by Mockito 5.3.2 from annotations +// in camera_android_camerax/test/android_camera_camerax_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/camera_info.dart' as _i4; +import 'package:camera_android_camerax/src/camera_selector.dart' as _i5; +import 'package:camera_android_camerax/src/process_camera_provider.dart' as _i2; +import 'package:mockito/mockito.dart' as _i1; + +import 'test_camerax_library.pigeon.dart' as _i6; + +// 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 [ProcessCameraProvider]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockProcessCameraProvider extends _i1.Mock + implements _i2.ProcessCameraProvider { + MockProcessCameraProvider() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Future> getAvailableCameraInfos() => + (super.noSuchMethod( + Invocation.method( + #getAvailableCameraInfos, + [], + ), + returnValue: _i3.Future>.value(<_i4.CameraInfo>[]), + ) as _i3.Future>); +} + +/// A class which mocks [CameraSelector]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockCameraSelector extends _i1.Mock implements _i5.CameraSelector { + MockCameraSelector() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Future> filter(List<_i4.CameraInfo>? cameraInfos) => + (super.noSuchMethod( + Invocation.method( + #filter, + [cameraInfos], + ), + returnValue: _i3.Future>.value(<_i4.CameraInfo>[]), + ) as _i3.Future>); +} + +/// A class which mocks [CameraInfo]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockCameraInfo extends _i1.Mock implements _i4.CameraInfo { + MockCameraInfo() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Future getSensorRotationDegrees() => (super.noSuchMethod( + Invocation.method( + #getSensorRotationDegrees, + [], + ), + returnValue: _i3.Future.value(0), + ) as _i3.Future); +} + +/// A class which mocks [TestProcessCameraProviderHostApi]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockTestProcessCameraProviderHostApi extends _i1.Mock + implements _i6.TestProcessCameraProviderHostApi { + MockTestProcessCameraProviderHostApi() { + _i1.throwOnMissingStub(this); + } + + @override + _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); +} + +/// A class which mocks [TestCameraSelectorHostApi]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockTestCameraSelectorHostApi extends _i1.Mock + implements _i6.TestCameraSelectorHostApi { + MockTestCameraSelectorHostApi() { + _i1.throwOnMissingStub(this); + } + + @override + 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); +} + +/// A class which mocks [TestCameraInfoHostApi]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockTestCameraInfoHostApi extends _i1.Mock + implements _i6.TestCameraInfoHostApi { + MockTestCameraInfoHostApi() { + _i1.throwOnMissingStub(this); + } + + @override + int getSensorRotationDegrees(int? identifier) => (super.noSuchMethod( + Invocation.method( + #getSensorRotationDegrees, + [identifier], + ), + returnValue: 0, + ) as int); +} From 92136adb95df768586626f537a5fcf5d82b1c33a Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Tue, 24 Jan 2023 11:01:45 -0800 Subject: [PATCH 04/13] marking variable final --- .../test/android_camera_camerax_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart index e09980aa1f21..43dbed482978 100644 --- a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart +++ b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart @@ -51,7 +51,7 @@ void main() { MockTestCameraSelectorHostApi(); TestCameraSelectorHostApi.setup(mockTestCameraSelectorHostApi); - MockTestCameraInfoHostApi mockTestCameraInfoHostApi = + final MockTestCameraInfoHostApi mockTestCameraInfoHostApi = MockTestCameraInfoHostApi(); TestCameraInfoHostApi.setup(mockTestCameraInfoHostApi); From eb8a032f62349b09cced71d3f93bc2ad32278996 Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Tue, 24 Jan 2023 11:02:43 -0800 Subject: [PATCH 05/13] removing commented import --- .../test/android_camera_camerax_test.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart index 43dbed482978..539d27017822 100644 --- a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart +++ b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart @@ -10,8 +10,6 @@ import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'android_camera_camerax_test.mocks.dart'; - -//import 'process_camera_provider_test.mocks.dart'; import 'test_camerax_library.pigeon.dart'; @GenerateMocks([ From 04d34c9f6e9840b396494c96087af0e2c830559c Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Mon, 30 Jan 2023 15:35:25 -0800 Subject: [PATCH 06/13] cleaning up tests for availableCamera camerax re-write --- .../lib/src/android_camera_camerax.dart | 43 ++++++--- .../test/android_camera_camerax_test.dart | 87 ++++++------------ .../android_camera_camerax_test.mocks.dart | 89 ------------------- 3 files changed, 58 insertions(+), 161 deletions(-) diff --git a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart index 79437837d38a..a4028644847a 100644 --- a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart +++ b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart @@ -3,11 +3,13 @@ // found in the LICENSE file. import 'dart:async'; -import 'process_camera_provider.dart'; -import 'camera_info.dart'; -import 'camera_selector.dart'; import 'package:camera_platform_interface/camera_platform_interface.dart'; +import 'package:flutter/cupertino.dart'; + +import 'camera_info.dart'; +import 'camera_selector.dart'; +import 'process_camera_provider.dart'; /// The Android implementation of [CameraPlatform] that uses the CameraX library. class AndroidCameraCameraX extends CameraPlatform { @@ -16,20 +18,22 @@ class AndroidCameraCameraX extends CameraPlatform { CameraPlatform.instance = AndroidCameraCameraX(); } + ProcessCameraProvider? processCameraProvider; + CameraSelector? backCameraSelector; + CameraSelector? frontCameraSelector; + + /// Returns list of all available cameras and their descriptions. @override Future> availableCameras() async { final List cameraDescriptions = []; - ProcessCameraProvider processCameraProvider = - await ProcessCameraProvider.getInstance(); + processCameraProvider ??= await ProcessCameraProvider.getInstance(); final List cameraInfos = await processCameraProvider!.getAvailableCameraInfos(); - final CameraSelector backCameraSelector = - CameraSelector.getDefaultBackCamera(); - final CameraSelector frontCameraSelector = - CameraSelector.getDefaultFrontCamera(); + backCameraSelector ??= CameraSelector.getDefaultBackCamera(); + frontCameraSelector ??= CameraSelector.getDefaultFrontCamera(); CameraLensDirection? cameraLensDirection; int cameraCount = 0; @@ -39,10 +43,10 @@ class AndroidCameraCameraX extends CameraPlatform { for (final CameraInfo cameraInfo in cameraInfos) { // Determine the lens direction by filtering the CameraInfo // TODO(gmackall): replace this with call to CameraInfo.getLensFacing when changes containing that method are available - if ((await backCameraSelector.filter([cameraInfo])) + if ((await backCameraSelector!.filter([cameraInfo])) .isNotEmpty) { cameraLensDirection = CameraLensDirection.back; - } else if ((await frontCameraSelector.filter([cameraInfo])) + } else if ((await frontCameraSelector!.filter([cameraInfo])) .isNotEmpty) { cameraLensDirection = CameraLensDirection.front; } else { @@ -62,4 +66,19 @@ class AndroidCameraCameraX extends CameraPlatform { return cameraDescriptions; } -} + + @visibleForTesting + void setDefaultFrontCameraSelector(CameraSelector frontCameraSelector) { + this.frontCameraSelector = frontCameraSelector; + } + + @visibleForTesting + void setDefaultBackCameraSelector(CameraSelector backCameraSelector) { + this.backCameraSelector = backCameraSelector; + } + + @visibleForTesting + void setProcessCameraProvider(ProcessCameraProvider processCameraProvider) { + this.processCameraProvider = processCameraProvider; + } +} \ No newline at end of file diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart index 539d27017822..57948fbd6f9b 100644 --- a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart +++ b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart @@ -1,8 +1,6 @@ import 'package:camera_android_camerax/camera_android_camerax.dart'; import 'package:camera_android_camerax/src/camera_info.dart'; import 'package:camera_android_camerax/src/camera_selector.dart'; -import 'package:camera_android_camerax/src/instance_manager.dart'; -import 'package:camera_android_camerax/src/java_object.dart'; import 'package:camera_android_camerax/src/process_camera_provider.dart'; import 'package:camera_platform_interface/camera_platform_interface.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -10,15 +8,11 @@ import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'android_camera_camerax_test.mocks.dart'; -import 'test_camerax_library.pigeon.dart'; @GenerateMocks([ ProcessCameraProvider, CameraSelector, CameraInfo, - TestProcessCameraProviderHostApi, - TestCameraSelectorHostApi, - TestCameraInfoHostApi, ]) void main() { TestWidgetsFlutterBinding.ensureInitialized(); @@ -39,64 +33,37 @@ void main() { } ]; - final MockTestProcessCameraProviderHostApi - mockTestProcessCameraProviderHostApi = - MockTestProcessCameraProviderHostApi(); - TestProcessCameraProviderHostApi.setup( - mockTestProcessCameraProviderHostApi); - - final MockTestCameraSelectorHostApi mockTestCameraSelectorHostApi = - MockTestCameraSelectorHostApi(); - TestCameraSelectorHostApi.setup(mockTestCameraSelectorHostApi); - - final MockTestCameraInfoHostApi mockTestCameraInfoHostApi = - MockTestCameraInfoHostApi(); - TestCameraInfoHostApi.setup(mockTestCameraInfoHostApi); - - final InstanceManager instanceManager = JavaObject.globalInstanceManager; - final ProcessCameraProvider processCameraProvider = - ProcessCameraProvider.detached( - instanceManager: instanceManager, - ); + //Create mocks to use + final MockProcessCameraProvider mockProcessCameraProvider = + MockProcessCameraProvider(); + final MockCameraSelector mockBackCameraSelector = MockCameraSelector(); + final MockCameraSelector mockFrontCameraSelector = MockCameraSelector(); + final MockCameraInfo mockFrontCameraInfo = MockCameraInfo(); + final MockCameraInfo mockBackCameraInfo = MockCameraInfo(); + AndroidCameraCameraX.registerWith(); - instanceManager.addHostCreatedInstance( - processCameraProvider, - 0, - onCopy: (_) => ProcessCameraProvider.detached(), - ); - final CameraInfo fakeBackCameraInfo = - CameraInfo.detached(instanceManager: instanceManager); - instanceManager.addHostCreatedInstance( - fakeBackCameraInfo, - 1, - onCopy: (_) => CameraInfo.detached(), - ); - final CameraInfo fakeFrontCameraInfo = - CameraInfo.detached(instanceManager: instanceManager); - instanceManager.addHostCreatedInstance( - fakeFrontCameraInfo, - 2, - onCopy: (_) => CameraInfo.detached(), - ); + //Set class level ProcessCameraProvider and camera selectors to created mocks + final AndroidCameraCameraX androidCameraCamerax = AndroidCameraCameraX(); + androidCameraCamerax.setDefaultBackCameraSelector(mockBackCameraSelector); + androidCameraCamerax.setDefaultFrontCameraSelector(mockFrontCameraSelector); + androidCameraCamerax.setProcessCameraProvider(mockProcessCameraProvider); - when(mockTestProcessCameraProviderHostApi.getInstance()) + //Mock calls to native platform + when(mockProcessCameraProvider.getAvailableCameraInfos()) + .thenAnswer((_) async => [mockBackCameraInfo, mockFrontCameraInfo]); + when(mockBackCameraSelector.filter([mockFrontCameraInfo])) + .thenAnswer((_) async => []); + when(mockBackCameraSelector.filter([mockBackCameraInfo])) + .thenAnswer((_) async => [mockBackCameraInfo]); + when(mockFrontCameraSelector.filter([mockBackCameraInfo])) + .thenAnswer((_) async => []); + when(mockFrontCameraSelector.filter([mockFrontCameraInfo])) + .thenAnswer((_) async => [mockFrontCameraInfo]); + when(mockBackCameraInfo.getSensorRotationDegrees()) .thenAnswer((_) async => 0); - when(mockTestProcessCameraProviderHostApi.getAvailableCameraInfos(0)) - .thenReturn([1, 2]); + when(mockFrontCameraInfo.getSensorRotationDegrees()) + .thenAnswer((_) async => 90); - when(mockTestCameraSelectorHostApi.filter(any, [1])).thenReturn([1]); - final List> responses = >[ - [], - [2] - ]; - when(mockTestCameraSelectorHostApi.filter(any, [2])) - .thenAnswer((_) => responses.removeAt(0)); - - when(mockTestCameraInfoHostApi.getSensorRotationDegrees(1)).thenReturn(0); - when(mockTestCameraInfoHostApi.getSensorRotationDegrees(2)).thenReturn(90); - - AndroidCameraCameraX.registerWith(); - final AndroidCameraCameraX androidCameraCamerax = AndroidCameraCameraX(); final List cameraDescriptions = await androidCameraCamerax.availableCameras(); diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.mocks.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.mocks.dart index c7d373e33a05..44171eebda91 100644 --- a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.mocks.dart +++ b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.mocks.dart @@ -10,8 +10,6 @@ import 'package:camera_android_camerax/src/camera_selector.dart' as _i5; import 'package:camera_android_camerax/src/process_camera_provider.dart' as _i2; import 'package:mockito/mockito.dart' as _i1; -import 'test_camerax_library.pigeon.dart' as _i6; - // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values // ignore_for_file: avoid_setters_without_getters @@ -79,90 +77,3 @@ class MockCameraInfo extends _i1.Mock implements _i4.CameraInfo { returnValue: _i3.Future.value(0), ) as _i3.Future); } - -/// A class which mocks [TestProcessCameraProviderHostApi]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockTestProcessCameraProviderHostApi extends _i1.Mock - implements _i6.TestProcessCameraProviderHostApi { - MockTestProcessCameraProviderHostApi() { - _i1.throwOnMissingStub(this); - } - - @override - _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); -} - -/// A class which mocks [TestCameraSelectorHostApi]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockTestCameraSelectorHostApi extends _i1.Mock - implements _i6.TestCameraSelectorHostApi { - MockTestCameraSelectorHostApi() { - _i1.throwOnMissingStub(this); - } - - @override - 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); -} - -/// A class which mocks [TestCameraInfoHostApi]. -/// -/// See the documentation for Mockito's code generation for more information. -class MockTestCameraInfoHostApi extends _i1.Mock - implements _i6.TestCameraInfoHostApi { - MockTestCameraInfoHostApi() { - _i1.throwOnMissingStub(this); - } - - @override - int getSensorRotationDegrees(int? identifier) => (super.noSuchMethod( - Invocation.method( - #getSensorRotationDegrees, - [identifier], - ), - returnValue: 0, - ) as int); -} From 183a8baac0ffc11da8af6242d00f039d1abaee1e Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Mon, 30 Jan 2023 15:38:24 -0800 Subject: [PATCH 07/13] chaning import --- .../camera_android_camerax/lib/src/android_camera_camerax.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart index a4028644847a..e306e868550e 100644 --- a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart +++ b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart @@ -5,7 +5,7 @@ import 'dart:async'; import 'package:camera_platform_interface/camera_platform_interface.dart'; -import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'camera_info.dart'; import 'camera_selector.dart'; From 396b67343a87dc65f031e2f9d06577e670d00c3b Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Tue, 7 Feb 2023 15:49:05 -0800 Subject: [PATCH 08/13] respondingt to review comments --- .../lib/src/android_camera_camerax.dart | 29 ++++++------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart index e306e868550e..26134f0ac347 100644 --- a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart +++ b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart @@ -18,9 +18,11 @@ class AndroidCameraCameraX extends CameraPlatform { CameraPlatform.instance = AndroidCameraCameraX(); } - ProcessCameraProvider? processCameraProvider; - CameraSelector? backCameraSelector; - CameraSelector? frontCameraSelector; + ProcessCameraProvider? _processCameraProvider; + @visibleForTesting + CameraSelector? backCameraSelector = CameraSelector.getDefaultBackCamera(); + @visibleForTesting + CameraSelector? frontCameraSelector = CameraSelector.getDefaultFrontCamera(); /// Returns list of all available cameras and their descriptions. @@ -28,12 +30,9 @@ class AndroidCameraCameraX extends CameraPlatform { Future> availableCameras() async { final List cameraDescriptions = []; - processCameraProvider ??= await ProcessCameraProvider.getInstance(); + setProcessCameraProvider(await ProcessCameraProvider.getInstance()); final List cameraInfos = - await processCameraProvider!.getAvailableCameraInfos(); - - backCameraSelector ??= CameraSelector.getDefaultBackCamera(); - frontCameraSelector ??= CameraSelector.getDefaultFrontCamera(); + await _processCameraProvider!.getAvailableCameraInfos(); CameraLensDirection? cameraLensDirection; int cameraCount = 0; @@ -67,18 +66,8 @@ class AndroidCameraCameraX extends CameraPlatform { return cameraDescriptions; } - @visibleForTesting - void setDefaultFrontCameraSelector(CameraSelector frontCameraSelector) { - this.frontCameraSelector = frontCameraSelector; - } - - @visibleForTesting - void setDefaultBackCameraSelector(CameraSelector backCameraSelector) { - this.backCameraSelector = backCameraSelector; - } - @visibleForTesting void setProcessCameraProvider(ProcessCameraProvider processCameraProvider) { - this.processCameraProvider = processCameraProvider; + this._processCameraProvider ??= processCameraProvider; } -} \ No newline at end of file +} From 43dd546b2f82bd10af264b417aa2a97dd8da6427 Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Tue, 7 Feb 2023 17:00:14 -0800 Subject: [PATCH 09/13] fixing tests --- .../lib/src/android_camera_camerax.dart | 6 +++--- .../test/android_camera_camerax_test.dart | 8 ++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart index 26134f0ac347..627869b4bfef 100644 --- a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart +++ b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart @@ -24,13 +24,13 @@ class AndroidCameraCameraX extends CameraPlatform { @visibleForTesting CameraSelector? frontCameraSelector = CameraSelector.getDefaultFrontCamera(); - /// Returns list of all available cameras and their descriptions. @override Future> availableCameras() async { final List cameraDescriptions = []; - setProcessCameraProvider(await ProcessCameraProvider.getInstance()); + _processCameraProvider ?? + setProcessCameraProvider(await ProcessCameraProvider.getInstance()); final List cameraInfos = await _processCameraProvider!.getAvailableCameraInfos(); @@ -68,6 +68,6 @@ class AndroidCameraCameraX extends CameraPlatform { @visibleForTesting void setProcessCameraProvider(ProcessCameraProvider processCameraProvider) { - this._processCameraProvider ??= processCameraProvider; + this._processCameraProvider = processCameraProvider; } } diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart index 57948fbd6f9b..b25538606b0f 100644 --- a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart +++ b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart @@ -1,3 +1,7 @@ +// 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/camera_android_camerax.dart'; import 'package:camera_android_camerax/src/camera_info.dart'; import 'package:camera_android_camerax/src/camera_selector.dart'; @@ -44,8 +48,8 @@ void main() { //Set class level ProcessCameraProvider and camera selectors to created mocks final AndroidCameraCameraX androidCameraCamerax = AndroidCameraCameraX(); - androidCameraCamerax.setDefaultBackCameraSelector(mockBackCameraSelector); - androidCameraCamerax.setDefaultFrontCameraSelector(mockFrontCameraSelector); + androidCameraCamerax.backCameraSelector = mockBackCameraSelector; + androidCameraCamerax.frontCameraSelector = mockFrontCameraSelector; androidCameraCamerax.setProcessCameraProvider(mockProcessCameraProvider); //Mock calls to native platform From 9c3660dcab3ef4e32e9ebabdbf735930b4b2edfd Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Wed, 8 Feb 2023 12:34:36 -0800 Subject: [PATCH 10/13] fixing presubmit issues --- .../camerax/CameraSelectorHostApiImpl.java | 3 --- .../lib/src/android_camera_camerax.dart | 16 +++++++-------- .../test/android_camera_camerax_test.dart | 20 +++++++++---------- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraSelectorHostApiImpl.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraSelectorHostApiImpl.java index f766ece39dc9..603f7cf78def 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraSelectorHostApiImpl.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraSelectorHostApiImpl.java @@ -58,9 +58,6 @@ public List filter(@NonNull Long identifier, @NonNull List cameraInf List filteredCameraInfosIds = new ArrayList(); for (CameraInfo cameraInfo : filteredCameraInfos) { - if (!instanceManager.containsInstance(cameraInfo)) { - cameraInfoFlutterApiImpl.create(cameraInfo, result -> {}); - } Long filteredCameraInfoId = instanceManager.getIdentifierForStrongReference(cameraInfo); filteredCameraInfosIds.add(filteredCameraInfoId); } diff --git a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart index 627869b4bfef..2da62bc5df24 100644 --- a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart +++ b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart @@ -18,9 +18,13 @@ class AndroidCameraCameraX extends CameraPlatform { CameraPlatform.instance = AndroidCameraCameraX(); } - ProcessCameraProvider? _processCameraProvider; + /// ProcessCameraProvider used to get list of cameras. Visible only for testing. + @visibleForTesting + ProcessCameraProvider? processCameraProvider; + /// Camera selector used to determine which CameraInfos are back cameras. @visibleForTesting CameraSelector? backCameraSelector = CameraSelector.getDefaultBackCamera(); + /// Camera selector used to determine which CameraInfos are back cameras. @visibleForTesting CameraSelector? frontCameraSelector = CameraSelector.getDefaultFrontCamera(); @@ -29,10 +33,9 @@ class AndroidCameraCameraX extends CameraPlatform { Future> availableCameras() async { final List cameraDescriptions = []; - _processCameraProvider ?? - setProcessCameraProvider(await ProcessCameraProvider.getInstance()); + processCameraProvider ??= await ProcessCameraProvider.getInstance(); final List cameraInfos = - await _processCameraProvider!.getAvailableCameraInfos(); + await processCameraProvider!.getAvailableCameraInfos(); CameraLensDirection? cameraLensDirection; int cameraCount = 0; @@ -65,9 +68,4 @@ class AndroidCameraCameraX extends CameraPlatform { return cameraDescriptions; } - - @visibleForTesting - void setProcessCameraProvider(ProcessCameraProvider processCameraProvider) { - this._processCameraProvider = processCameraProvider; - } } diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart index b25538606b0f..f82749b37f57 100644 --- a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart +++ b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart @@ -50,19 +50,19 @@ void main() { final AndroidCameraCameraX androidCameraCamerax = AndroidCameraCameraX(); androidCameraCamerax.backCameraSelector = mockBackCameraSelector; androidCameraCamerax.frontCameraSelector = mockFrontCameraSelector; - androidCameraCamerax.setProcessCameraProvider(mockProcessCameraProvider); + androidCameraCamerax.processCameraProvider = mockProcessCameraProvider; //Mock calls to native platform when(mockProcessCameraProvider.getAvailableCameraInfos()) - .thenAnswer((_) async => [mockBackCameraInfo, mockFrontCameraInfo]); - when(mockBackCameraSelector.filter([mockFrontCameraInfo])) - .thenAnswer((_) async => []); - when(mockBackCameraSelector.filter([mockBackCameraInfo])) - .thenAnswer((_) async => [mockBackCameraInfo]); - when(mockFrontCameraSelector.filter([mockBackCameraInfo])) - .thenAnswer((_) async => []); - when(mockFrontCameraSelector.filter([mockFrontCameraInfo])) - .thenAnswer((_) async => [mockFrontCameraInfo]); + .thenAnswer((_) async => [mockBackCameraInfo, mockFrontCameraInfo]); + when(mockBackCameraSelector.filter([mockFrontCameraInfo])) + .thenAnswer((_) async => []); + when(mockBackCameraSelector.filter([mockBackCameraInfo])) + .thenAnswer((_) async => [mockBackCameraInfo]); + when(mockFrontCameraSelector.filter([mockBackCameraInfo])) + .thenAnswer((_) async => []); + when(mockFrontCameraSelector.filter([mockFrontCameraInfo])) + .thenAnswer((_) async => [mockFrontCameraInfo]); when(mockBackCameraInfo.getSensorRotationDegrees()) .thenAnswer((_) async => 0); when(mockFrontCameraInfo.getSensorRotationDegrees()) From 26562aa30d08c1c249c490a544f927228a733f69 Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Wed, 8 Feb 2023 12:37:38 -0800 Subject: [PATCH 11/13] adding changelog message --- packages/camera/camera_android_camerax/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/camera/camera_android_camerax/CHANGELOG.md b/packages/camera/camera_android_camerax/CHANGELOG.md index 080240a64f42..50fdf586c5e7 100644 --- a/packages/camera/camera_android_camerax/CHANGELOG.md +++ b/packages/camera/camera_android_camerax/CHANGELOG.md @@ -9,3 +9,4 @@ * Bump CameraX version to 1.3.0-alpha03 and Kotlin version to 1.8.0. * Changes instance manager to allow the separate creation of identical objects. * Adds Preview and Surface classes, along with other methods needed to implement camera preview. +* Adds implementation of availableCameras() From 4194464a66c559893797e538c835b4263e97aa78 Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Wed, 8 Feb 2023 12:44:36 -0800 Subject: [PATCH 12/13] formatting changes for presubmit tests --- .../lib/src/android_camera_camerax.dart | 2 ++ .../test/android_camera_camerax_test.dart | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart index 2da62bc5df24..300d6717fb46 100644 --- a/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart +++ b/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart @@ -21,9 +21,11 @@ class AndroidCameraCameraX extends CameraPlatform { /// ProcessCameraProvider used to get list of cameras. Visible only for testing. @visibleForTesting ProcessCameraProvider? processCameraProvider; + /// Camera selector used to determine which CameraInfos are back cameras. @visibleForTesting CameraSelector? backCameraSelector = CameraSelector.getDefaultBackCamera(); + /// Camera selector used to determine which CameraInfos are back cameras. @visibleForTesting CameraSelector? frontCameraSelector = CameraSelector.getDefaultFrontCamera(); diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart index f82749b37f57..1f475300d57f 100644 --- a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart +++ b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart @@ -53,8 +53,8 @@ void main() { androidCameraCamerax.processCameraProvider = mockProcessCameraProvider; //Mock calls to native platform - when(mockProcessCameraProvider.getAvailableCameraInfos()) - .thenAnswer((_) async => [mockBackCameraInfo, mockFrontCameraInfo]); + when(mockProcessCameraProvider.getAvailableCameraInfos()).thenAnswer( + (_) async => [mockBackCameraInfo, mockFrontCameraInfo]); when(mockBackCameraSelector.filter([mockFrontCameraInfo])) .thenAnswer((_) async => []); when(mockBackCameraSelector.filter([mockBackCameraInfo])) From fd6e09bb24bc2c0d72e681c4e50a90e1018b93e9 Mon Sep 17 00:00:00 2001 From: Gray Mackall Date: Wed, 8 Feb 2023 12:47:51 -0800 Subject: [PATCH 13/13] another formatting change for presubmit checks --- .../test/android_camera_camerax_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart index 1f475300d57f..8b16c64c6ede 100644 --- a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart +++ b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart @@ -54,7 +54,7 @@ void main() { //Mock calls to native platform when(mockProcessCameraProvider.getAvailableCameraInfos()).thenAnswer( - (_) async => [mockBackCameraInfo, mockFrontCameraInfo]); + (_) async => [mockBackCameraInfo, mockFrontCameraInfo]); when(mockBackCameraSelector.filter([mockFrontCameraInfo])) .thenAnswer((_) async => []); when(mockBackCameraSelector.filter([mockBackCameraInfo]))