diff --git a/packages/camera/camera_android_camerax/CHANGELOG.md b/packages/camera/camera_android_camerax/CHANGELOG.md index 2818f35b8c8..ffb540b6587 100644 --- a/packages/camera/camera_android_camerax/CHANGELOG.md +++ b/packages/camera/camera_android_camerax/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.6.18 + +* Adds support for the `MediaSettings.enableAudio` setting, which determines whether or not audio is + recorded during video recording. + ## 0.6.17+1 * Replaces deprecated `onSurfaceDestroyed` with `onSurfaceCleanup`. diff --git a/packages/camera/camera_android_camerax/android/build.gradle b/packages/camera/camera_android_camerax/android/build.gradle index 7c387331a74..4ed1e856598 100644 --- a/packages/camera/camera_android_camerax/android/build.gradle +++ b/packages/camera/camera_android_camerax/android/build.gradle @@ -9,7 +9,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.0' + classpath 'com.android.tools.build:gradle:8.6.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -57,16 +57,17 @@ android { } } - lintOptions { + lint { checkAllWarnings true warningsAsErrors true disable 'AndroidGradlePluginVersion', 'GradleDependency', 'InvalidPackage', 'NewerVersionAvailable' + baseline = file("lint-baseline.xml") } } dependencies { // CameraX core library using the camera2 implementation must use same version number. - def camerax_version = "1.4.1" + def camerax_version = "1.5.0-beta01" implementation "androidx.camera:camera-core:${camerax_version}" implementation "androidx.camera:camera-camera2:${camerax_version}" implementation "androidx.camera:camera-lifecycle:${camerax_version}" diff --git a/packages/camera/camera_android_camerax/android/lint-baseline.xml b/packages/camera/camera_android_camerax/android/lint-baseline.xml new file mode 100644 index 00000000000..7a4999067f3 --- /dev/null +++ b/packages/camera/camera_android_camerax/android/lint-baseline.xml @@ -0,0 +1,268 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraXLibrary.g.kt b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraXLibrary.g.kt index 3841b8beb2a..58f599dee23 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraXLibrary.g.kt +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraXLibrary.g.kt @@ -3,7 +3,7 @@ // found in the LICENSE file. // Autogenerated from Pigeon (v25.3.1), do not edit directly. // See also: https://pub.dev/packages/pigeon -@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass", "UnsafeOptInUsageError") +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") package io.flutter.plugins.camerax @@ -3643,6 +3643,12 @@ abstract class PigeonApiVideoRecordEventListener( abstract class PigeonApiPendingRecording( open val pigeonRegistrar: CameraXLibraryPigeonProxyApiRegistrar ) { + /** Enables audio to be recorded for this recording. */ + abstract fun withAudioEnabled( + pigeon_instance: androidx.camera.video.PendingRecording, + initialMuted: Boolean + ): androidx.camera.video.PendingRecording + /** Starts the recording, making it an active recording. */ abstract fun start( pigeon_instance: androidx.camera.video.PendingRecording, @@ -3653,6 +3659,29 @@ abstract class PigeonApiPendingRecording( @Suppress("LocalVariableName") fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiPendingRecording?) { val codec = api?.pigeonRegistrar?.codec ?: CameraXLibraryPigeonCodec() + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.camera_android_camerax.PendingRecording.withAudioEnabled", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as androidx.camera.video.PendingRecording + val initialMutedArg = args[1] as Boolean + val wrapped: List = + try { + listOf(api.withAudioEnabled(pigeon_instanceArg, initialMutedArg)) + } catch (exception: Throwable) { + CameraXLibraryPigeonUtils.wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } run { val channel = BasicMessageChannel( diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PendingRecordingProxyApi.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PendingRecordingProxyApi.java index c7f294a0f59..14fef1b0ef9 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PendingRecordingProxyApi.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/PendingRecordingProxyApi.java @@ -4,6 +4,8 @@ package io.flutter.plugins.camerax; +import android.Manifest; +import android.content.pm.PackageManager; import androidx.annotation.NonNull; import androidx.camera.video.PendingRecording; import androidx.camera.video.Recording; @@ -25,6 +27,19 @@ public ProxyApiRegistrar getPigeonRegistrar() { return (ProxyApiRegistrar) super.getPigeonRegistrar(); } + @NonNull + @Override + public PendingRecording withAudioEnabled(PendingRecording pigeonInstance, boolean initialMuted) { + if (!initialMuted + && ContextCompat.checkSelfPermission( + getPigeonRegistrar().getContext(), Manifest.permission.RECORD_AUDIO) + == PackageManager.PERMISSION_GRANTED) { + return pigeonInstance.withAudioEnabled(false); + } + + return pigeonInstance.withAudioEnabled(true); + } + @NonNull @Override public Recording start( diff --git a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/RecorderProxyApi.java b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/RecorderProxyApi.java index 4aa83f9e66e..0f326281b9a 100644 --- a/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/RecorderProxyApi.java +++ b/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/RecorderProxyApi.java @@ -4,15 +4,12 @@ package io.flutter.plugins.camerax; -import android.Manifest; -import android.content.pm.PackageManager; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.camera.video.FileOutputOptions; import androidx.camera.video.PendingRecording; import androidx.camera.video.QualitySelector; import androidx.camera.video.Recorder; -import androidx.core.content.ContextCompat; import java.io.File; /** @@ -69,11 +66,6 @@ public PendingRecording prepareRecording(Recorder pigeonInstance, @NonNull Strin final PendingRecording pendingRecording = pigeonInstance.prepareRecording(getPigeonRegistrar().getContext(), fileOutputOptions); - if (ContextCompat.checkSelfPermission( - getPigeonRegistrar().getContext(), Manifest.permission.RECORD_AUDIO) - == PackageManager.PERMISSION_GRANTED) { - pendingRecording.withAudioEnabled(); - } return pendingRecording; } diff --git a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PendingRecordingTest.java b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PendingRecordingTest.java index 23e8279a7a4..ad606cb5082 100644 --- a/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PendingRecordingTest.java +++ b/packages/camera/camera_android_camerax/android/src/test/java/io/flutter/plugins/camerax/PendingRecordingTest.java @@ -5,10 +5,15 @@ package io.flutter.plugins.camerax; import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.Manifest; +import android.content.Context; +import android.content.pm.PackageManager; import androidx.camera.video.PendingRecording; import androidx.camera.video.Recording; import androidx.core.content.ContextCompat; @@ -19,6 +24,65 @@ import org.mockito.stubbing.Answer; public class PendingRecordingTest { + @Test + public void withAudioEnabled_enablesAudioWhenRequestedAndPermissionGranted() { + final PigeonApiPendingRecording api = + new TestProxyApiRegistrar().getPigeonApiPendingRecording(); + final PendingRecording instance = mock(PendingRecording.class); + final PendingRecording newInstance = mock(PendingRecording.class); + + try (MockedStatic mockedContextCompat = + Mockito.mockStatic(ContextCompat.class)) { + mockedContextCompat + .when( + () -> + ContextCompat.checkSelfPermission( + any(Context.class), eq(Manifest.permission.RECORD_AUDIO))) + .thenAnswer((Answer) invocation -> PackageManager.PERMISSION_GRANTED); + + when(instance.withAudioEnabled(false)).thenReturn(newInstance); + + assertEquals(api.withAudioEnabled(instance, false), newInstance); + verify(instance).withAudioEnabled(false); + } + } + + @Test + public void withAudioEnabled_doesNotEnableAudioWhenRequestedAndPermissionNotGranted() { + final PigeonApiPendingRecording api = + new TestProxyApiRegistrar().getPigeonApiPendingRecording(); + final PendingRecording instance = mock(PendingRecording.class); + final PendingRecording newInstance = mock(PendingRecording.class); + + try (MockedStatic mockedContextCompat = + Mockito.mockStatic(ContextCompat.class)) { + mockedContextCompat + .when( + () -> + ContextCompat.checkSelfPermission( + any(Context.class), eq(Manifest.permission.RECORD_AUDIO))) + .thenAnswer((Answer) invocation -> PackageManager.PERMISSION_DENIED); + + when(instance.withAudioEnabled(true)).thenReturn(newInstance); + + assertEquals(api.withAudioEnabled(instance, false), newInstance); + verify(instance).withAudioEnabled(true); + } + } + + @Test + public void withAudioEnabled_doesNotEnableAudioWhenAudioNotRequested() { + final PigeonApiPendingRecording api = + new TestProxyApiRegistrar().getPigeonApiPendingRecording(); + final PendingRecording instance = mock(PendingRecording.class); + final PendingRecording newInstance = mock(PendingRecording.class); + + when(instance.withAudioEnabled(true)).thenReturn(newInstance); + + assertEquals(api.withAudioEnabled(instance, true), newInstance); + verify(instance).withAudioEnabled(true); + } + @Test public void start_callsStartOnInstance() { final PigeonApiPendingRecording api = diff --git a/packages/camera/camera_android_camerax/example/lib/main.dart b/packages/camera/camera_android_camerax/example/lib/main.dart index 07043549441..359f584fd76 100644 --- a/packages/camera/camera_android_camerax/example/lib/main.dart +++ b/packages/camera/camera_android_camerax/example/lib/main.dart @@ -661,11 +661,12 @@ class _CameraExampleHomeState extends State final CameraController cameraController = CameraController( cameraDescription, - mediaSettings: const MediaSettings( + mediaSettings: MediaSettings( resolutionPreset: ResolutionPreset.low, fps: 15, videoBitrate: 200000, audioBitrate: 32000, + enableAudio: enableAudio, ), imageFormatGroup: ImageFormatGroup.jpeg, ); 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 fdb83feddb7..795a8747227 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 @@ -261,6 +261,11 @@ class AndroidCameraCameraX extends CameraPlatform { /// This is expressed in terms of one of the [Surface] rotation constant. late int _initialDefaultDisplayRotation; + /// Whether or not audio should be enabled for recording video if permission is + /// granted. + @visibleForTesting + late bool enableRecordingAudio; + /// Returns list of all available cameras and their descriptions. @override Future> availableCameras() async { @@ -345,8 +350,9 @@ class AndroidCameraCameraX extends CameraPlatform { CameraDescription cameraDescription, MediaSettings? mediaSettings, ) async { + enableRecordingAudio = mediaSettings?.enableAudio ?? false; final CameraPermissionsError? error = await systemServicesManager - .requestCameraPermissions(mediaSettings?.enableAudio ?? false); + .requestCameraPermissions(enableRecordingAudio); if (error != null) { throw CameraException(error.errorCode, error.description); @@ -1109,6 +1115,13 @@ class AndroidCameraCameraX extends CameraPlatform { ); pendingRecording = await recorder!.prepareRecording(videoOutputPath!); + // Enable/disable recording audio as requested. If enabling audio is requested + // and permission was not granted when the camera was created, then recording + // audio will be disabled to respect the denied permission. + pendingRecording = await pendingRecording!.withAudioEnabled( + /* initialMuted */ !enableRecordingAudio, + ); + recording = await pendingRecording!.start(_videoRecordingEventListener); if (streamCallback != null) { diff --git a/packages/camera/camera_android_camerax/lib/src/camerax_library.g.dart b/packages/camera/camera_android_camerax/lib/src/camerax_library.g.dart index 1df922788e6..ba337d81f32 100644 --- a/packages/camera/camera_android_camerax/lib/src/camerax_library.g.dart +++ b/packages/camera/camera_android_camerax/lib/src/camerax_library.g.dart @@ -4359,6 +4359,42 @@ class PendingRecording extends PigeonInternalProxyApiBaseClass { } } + /// Enables audio to be recorded for this recording. + Future withAudioEnabled(bool initialMuted) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecPendingRecording; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.camera_android_camerax.PendingRecording.withAudioEnabled'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = pigeonVar_channel.send( + [this, initialMuted], + ); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else if (pigeonVar_replyList[0] == null) { + throw PlatformException( + code: 'null-error', + message: 'Host platform returned null value for non-null return value.', + ); + } else { + return (pigeonVar_replyList[0] as PendingRecording?)!; + } + } + /// Starts the recording, making it an active recording. Future start(VideoRecordEventListener listener) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = diff --git a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart index 4f7377af93d..80253e11dd9 100644 --- a/packages/camera/camera_android_camerax/pigeons/camerax_library.dart +++ b/packages/camera/camera_android_camerax/pigeons/camerax_library.dart @@ -517,6 +517,9 @@ abstract class VideoRecordEventListener { ), ) abstract class PendingRecording { + /// Enables/disables audio to be recorded for this recording. + PendingRecording withAudioEnabled(bool initialMuted); + /// Starts the recording, making it an active recording. Recording start(VideoRecordEventListener listener); } diff --git a/packages/camera/camera_android_camerax/pubspec.yaml b/packages/camera/camera_android_camerax/pubspec.yaml index 329913bd16a..1299af343e3 100644 --- a/packages/camera/camera_android_camerax/pubspec.yaml +++ b/packages/camera/camera_android_camerax/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_android_camerax description: Android implementation of the camera plugin using the CameraX library. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.6.17+1 +version: 0.6.18 environment: sdk: ^3.7.0 diff --git a/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart b/packages/camera/camera_android_camerax/test/android_camera_camerax_test.dart index 1524758960c..6618e45f26f 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 @@ -1867,7 +1867,7 @@ void main() { ); test( - 'createCamera sets sensor orientation, handlesCropAndRotation, initialDeviceOrientation as expected', + 'createCamera sets sensorOrientationDegrees and enableRecordingAudio as expected', () async { final AndroidCameraCameraX camera = AndroidCameraCameraX(); const CameraLensDirection testLensDirection = CameraLensDirection.back; @@ -1925,6 +1925,7 @@ void main() { ); expect(camera.sensorOrientationDegrees, testSensorOrientation); + expect(camera.enableRecordingAudio, isTrue); }, ); @@ -2556,12 +2557,14 @@ void main() { group('video recording', () { test( - 'startVideoCapturing binds video capture use case, updates saved camera instance and its properties, and starts the recording', + 'startVideoCapturing binds video capture use case, updates saved camera instance and its properties, and starts the recording with audio enabled as desired', () async { // Set up mocks and constants. final AndroidCameraCameraX camera = AndroidCameraCameraX(); final MockPendingRecording mockPendingRecording = MockPendingRecording(); + final MockPendingRecording mockPendingRecordingWithAudio = + MockPendingRecording(); final MockRecording mockRecording = MockRecording(); final MockCamera mockCamera = MockCamera(); final MockCamera newMockCamera = MockCamera(); @@ -2572,6 +2575,7 @@ void main() { MockLiveCameraState(); final MockCamera2CameraInfo mockCamera2CameraInfo = MockCamera2CameraInfo(); + const bool enableAudio = true; // Set directly for test versus calling createCamera. camera.processCameraProvider = MockProcessCameraProvider(); @@ -2582,6 +2586,7 @@ void main() { camera.liveCameraState = mockLiveCameraState; camera.cameraInfo = MockCameraInfo(); camera.imageAnalysis = MockImageAnalysis(); + camera.enableRecordingAudio = enableAudio; // Ignore setting target rotation for this test; tested separately. camera.captureOrientationLocked = true; @@ -2655,7 +2660,10 @@ void main() { camera.recorder!.prepareRecording(outputPath), ).thenAnswer((_) async => mockPendingRecording); when( - mockPendingRecording.start(any), + mockPendingRecording.withAudioEnabled(!enableAudio), + ).thenAnswer((_) async => mockPendingRecordingWithAudio); + when( + mockPendingRecordingWithAudio.start(any), ).thenAnswer((_) async => mockRecording); when( camera.processCameraProvider!.isBound(camera.videoCapture!), @@ -2711,7 +2719,7 @@ void main() { ); // Verify recording is started. - expect(camera.pendingRecording, equals(mockPendingRecording)); + expect(camera.pendingRecording, equals(mockPendingRecordingWithAudio)); expect(camera.recording, mockRecording); }, ); @@ -2737,6 +2745,7 @@ void main() { camera.cameraSelector = MockCameraSelector(); camera.cameraInfo = MockCameraInfo(); camera.imageAnalysis = MockImageAnalysis(); + camera.enableRecordingAudio = false; // Ignore setting target rotation for this test; tested seprately. camera.captureOrientationLocked = true; @@ -2809,6 +2818,9 @@ void main() { when( camera.recorder!.prepareRecording(outputPath), ).thenAnswer((_) async => mockPendingRecording); + when( + mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio), + ).thenAnswer((_) async => mockPendingRecording); when( mockPendingRecording.start(any), ).thenAnswer((_) async => mockRecording); @@ -2863,6 +2875,7 @@ void main() { verify(camera.recorder!.prepareRecording(outputPath)).called(1); verifyNoMoreInteractions(camera.recorder); verify(mockPendingRecording.start(any)).called(1); + verify(mockPendingRecording.withAudioEnabled(any)).called(1); verifyNoMoreInteractions(mockPendingRecording); }, ); @@ -2891,6 +2904,7 @@ void main() { camera.recorder = mockRecorder; camera.cameraInfo = initialCameraInfo; camera.imageCapture = MockImageCapture(); + camera.enableRecordingAudio = true; // Ignore setting target rotation for this test; tested seprately. camera.captureOrientationLocked = true; @@ -2986,6 +3000,9 @@ void main() { when( camera.recorder!.prepareRecording(outputPath), ).thenAnswer((_) async => mockPendingRecording); + when( + mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio), + ).thenAnswer((_) async => mockPendingRecording); when( mockProcessCameraProvider.bindToLifecycle(any, any), ).thenAnswer((_) => Future.value(camera.camera)); @@ -3037,6 +3054,7 @@ void main() { camera.cameraSelector = MockCameraSelector(); camera.imageAnalysis = MockImageAnalysis(); camera.cameraInfo = initialCameraInfo; + camera.enableRecordingAudio = false; // Tell plugin to mock call to get current video orientation and mock Camera2CameraInfo retrieval. const String outputPath = '/temp/REC123.temp'; @@ -3124,6 +3142,9 @@ void main() { when( camera.recorder!.prepareRecording(outputPath), ).thenAnswer((_) async => mockPendingRecording); + when( + mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio), + ).thenAnswer((_) async => mockPendingRecording); when( mockPendingRecording.start(any), ).thenAnswer((_) async => mockRecording); @@ -6066,6 +6087,7 @@ void main() { camera.cameraSelector = MockCameraSelector(); camera.cameraInfo = MockCameraInfo(); camera.imageAnalysis = MockImageAnalysis(); + camera.enableRecordingAudio = false; // Ignore setting target rotation for this test; tested seprately. camera.captureOrientationLocked = true; @@ -6138,6 +6160,9 @@ void main() { when( camera.recorder!.prepareRecording(outputPath), ).thenAnswer((_) async => mockPendingRecording); + when( + mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio), + ).thenAnswer((_) async => mockPendingRecording); when( mockPendingRecording.start(any), ).thenAnswer((_) async => mockRecording); @@ -6199,6 +6224,7 @@ void main() { camera.cameraSelector = MockCameraSelector(); camera.cameraInfo = MockCameraInfo(); camera.imageAnalysis = MockImageAnalysis(); + camera.enableRecordingAudio = true; // Ignore setting target rotation for this test; tested seprately. camera.captureOrientationLocked = true; @@ -6271,6 +6297,9 @@ void main() { when( camera.recorder!.prepareRecording(outputPath), ).thenAnswer((_) async => mockPendingRecording); + when( + mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio), + ).thenAnswer((_) async => mockPendingRecording); when( mockPendingRecording.start(any), ).thenAnswer((_) async => mockRecording); @@ -6332,6 +6361,7 @@ void main() { camera.cameraSelector = MockCameraSelector(); camera.cameraInfo = MockCameraInfo(); camera.imageAnalysis = MockImageAnalysis(); + camera.enableRecordingAudio = false; // Ignore setting target rotation for this test; tested seprately. camera.captureOrientationLocked = true; @@ -6404,6 +6434,9 @@ void main() { when( camera.recorder!.prepareRecording(outputPath), ).thenAnswer((_) async => mockPendingRecording); + when( + mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio), + ).thenAnswer((_) async => mockPendingRecording); when( mockPendingRecording.start(any), ).thenAnswer((_) async => mockRecording); @@ -6470,6 +6503,7 @@ void main() { camera.cameraInfo = MockCameraInfo(); camera.imageAnalysis = MockImageAnalysis(); camera.imageCapture = MockImageCapture(); + camera.enableRecordingAudio = true; // Ignore setting target rotation for this test; tested seprately. camera.captureOrientationLocked = true; @@ -6556,6 +6590,9 @@ void main() { when( camera.recorder!.prepareRecording(outputPath), ).thenAnswer((_) async => mockPendingRecording); + when( + mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio), + ).thenAnswer((_) async => mockPendingRecording); when( mockPendingRecording.start(any), ).thenAnswer((_) async => mockRecording); @@ -6626,6 +6663,7 @@ void main() { camera.imageAnalysis = MockImageAnalysis(); camera.imageCapture = MockImageCapture(); camera.preview = MockPreview(); + camera.enableRecordingAudio = false; // Ignore setting target rotation for this test; tested seprately. camera.captureOrientationLocked = true; @@ -6712,6 +6750,9 @@ void main() { when( camera.recorder!.prepareRecording(outputPath), ).thenAnswer((_) async => mockPendingRecording); + when( + mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio), + ).thenAnswer((_) async => mockPendingRecording); when( mockPendingRecording.start(any), ).thenAnswer((_) async => mockRecording); @@ -6774,6 +6815,7 @@ void main() { camera.imageAnalysis = MockImageAnalysis(); camera.imageCapture = MockImageCapture(); camera.preview = MockPreview(); + camera.enableRecordingAudio = true; // Ignore setting target rotation for this test; tested seprately. camera.captureOrientationLocked = true; @@ -6860,6 +6902,9 @@ void main() { when( camera.recorder!.prepareRecording(outputPath), ).thenAnswer((_) async => mockPendingRecording); + when( + mockPendingRecording.withAudioEnabled(!camera.enableRecordingAudio), + ).thenAnswer((_) async => mockPendingRecording); when( mockPendingRecording.start(any), ).thenAnswer((_) async => mockRecording); 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 d88b2feba4f..8a709e6beff 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 @@ -1,4 +1,4 @@ -// Mocks generated by Mockito 5.4.5 from annotations +// Mocks generated by Mockito 5.4.6 from annotations // in camera_android_camerax/test/android_camera_camerax_test.dart. // Do not manually edit this file. @@ -249,14 +249,14 @@ class _FakeImageProxy_38 extends _i1.SmartFake implements _i2.ImageProxy { : super(parent, parentInvocation); } -class _FakeRecording_39 extends _i1.SmartFake implements _i2.Recording { - _FakeRecording_39(Object parent, Invocation parentInvocation) +class _FakePendingRecording_39 extends _i1.SmartFake + implements _i2.PendingRecording { + _FakePendingRecording_39(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } -class _FakePendingRecording_40 extends _i1.SmartFake - implements _i2.PendingRecording { - _FakePendingRecording_40(Object parent, Invocation parentInvocation) +class _FakeRecording_40 extends _i1.SmartFake implements _i2.Recording { + _FakeRecording_40(Object parent, Invocation parentInvocation) : super(parent, parentInvocation); } @@ -1818,23 +1818,6 @@ class MockCameraXProxy extends _i1.Mock implements _i7.CameraXProxy { _i2.PigeonInstanceManager? pigeon_instanceManager, })); - @override - set withModeFocusMeteringActionBuilder( - _i2.FocusMeteringActionBuilder Function({ - required _i2.MeteringMode mode, - required _i2.MeteringPoint point, - _i8.BinaryMessenger? pigeon_binaryMessenger, - _i2.PigeonInstanceManager? pigeon_instanceManager, - })? - _withModeFocusMeteringActionBuilder, - ) => super.noSuchMethod( - Invocation.setter( - #withModeFocusMeteringActionBuilder, - _withModeFocusMeteringActionBuilder, - ), - returnValueForMissingStub: null, - ); - @override _i2.CaptureRequestOptions Function({ required Map<_i2.CaptureRequestKey, Object?> options, @@ -1869,19 +1852,6 @@ class MockCameraXProxy extends _i1.Mock implements _i7.CameraXProxy { _i2.PigeonInstanceManager? pigeon_instanceManager, })); - @override - set newCaptureRequestOptions( - _i2.CaptureRequestOptions Function({ - required Map<_i2.CaptureRequestKey, Object?> options, - _i8.BinaryMessenger? pigeon_binaryMessenger, - _i2.PigeonInstanceManager? pigeon_instanceManager, - })? - _newCaptureRequestOptions, - ) => super.noSuchMethod( - Invocation.setter(#newCaptureRequestOptions, _newCaptureRequestOptions), - returnValueForMissingStub: null, - ); - @override _i2.Camera2CameraControl Function({ required _i2.CameraControl cameraControl, @@ -1916,19 +1886,6 @@ class MockCameraXProxy extends _i1.Mock implements _i7.CameraXProxy { _i2.PigeonInstanceManager? pigeon_instanceManager, })); - @override - set fromCamera2CameraControl( - _i2.Camera2CameraControl Function({ - required _i2.CameraControl cameraControl, - _i8.BinaryMessenger? pigeon_binaryMessenger, - _i2.PigeonInstanceManager? pigeon_instanceManager, - })? - _fromCamera2CameraControl, - ) => super.noSuchMethod( - Invocation.setter(#fromCamera2CameraControl, _fromCamera2CameraControl), - returnValueForMissingStub: null, - ); - @override _i2.ResolutionFilter Function({ required _i2.CameraSize preferredSize, @@ -2043,24 +2000,6 @@ class MockCameraXProxy extends _i1.Mock implements _i7.CameraXProxy { _i2.PigeonInstanceManager? pigeon_instanceManager, })); - @override - set newDisplayOrientedMeteringPointFactory( - _i2.DisplayOrientedMeteringPointFactory Function({ - required _i3.CameraInfo cameraInfo, - required double height, - required double width, - _i8.BinaryMessenger? pigeon_binaryMessenger, - _i2.PigeonInstanceManager? pigeon_instanceManager, - })? - _newDisplayOrientedMeteringPointFactory, - ) => super.noSuchMethod( - Invocation.setter( - #newDisplayOrientedMeteringPointFactory, - _newDisplayOrientedMeteringPointFactory, - ), - returnValueForMissingStub: null, - ); - @override _i5.Future<_i2.ProcessCameraProvider> Function({ _i8.BinaryMessenger? pigeon_binaryMessenger, @@ -2248,17 +2187,6 @@ class MockCameraXProxy extends _i1.Mock implements _i7.CameraXProxy { ) as _i2.CaptureRequestKey Function()); - @override - set controlAELockCaptureRequest( - _i2.CaptureRequestKey Function()? _controlAELockCaptureRequest, - ) => super.noSuchMethod( - Invocation.setter( - #controlAELockCaptureRequest, - _controlAELockCaptureRequest, - ), - returnValueForMissingStub: null, - ); - @override _i2.CameraCharacteristicsKey Function() get infoSupportedHardwareLevelCameraCharacteristics => @@ -2298,6 +2226,78 @@ class MockCameraXProxy extends _i1.Mock implements _i7.CameraXProxy { ), ) as _i2.CameraCharacteristicsKey Function()); + + @override + set withModeFocusMeteringActionBuilder( + _i2.FocusMeteringActionBuilder Function({ + required _i2.MeteringMode mode, + required _i2.MeteringPoint point, + _i8.BinaryMessenger? pigeon_binaryMessenger, + _i2.PigeonInstanceManager? pigeon_instanceManager, + })? + _withModeFocusMeteringActionBuilder, + ) => super.noSuchMethod( + Invocation.setter( + #withModeFocusMeteringActionBuilder, + _withModeFocusMeteringActionBuilder, + ), + returnValueForMissingStub: null, + ); + + @override + set newCaptureRequestOptions( + _i2.CaptureRequestOptions Function({ + required Map<_i2.CaptureRequestKey, Object?> options, + _i8.BinaryMessenger? pigeon_binaryMessenger, + _i2.PigeonInstanceManager? pigeon_instanceManager, + })? + _newCaptureRequestOptions, + ) => super.noSuchMethod( + Invocation.setter(#newCaptureRequestOptions, _newCaptureRequestOptions), + returnValueForMissingStub: null, + ); + + @override + set fromCamera2CameraControl( + _i2.Camera2CameraControl Function({ + required _i2.CameraControl cameraControl, + _i8.BinaryMessenger? pigeon_binaryMessenger, + _i2.PigeonInstanceManager? pigeon_instanceManager, + })? + _fromCamera2CameraControl, + ) => super.noSuchMethod( + Invocation.setter(#fromCamera2CameraControl, _fromCamera2CameraControl), + returnValueForMissingStub: null, + ); + + @override + set newDisplayOrientedMeteringPointFactory( + _i2.DisplayOrientedMeteringPointFactory Function({ + required _i3.CameraInfo cameraInfo, + required double height, + required double width, + _i8.BinaryMessenger? pigeon_binaryMessenger, + _i2.PigeonInstanceManager? pigeon_instanceManager, + })? + _newDisplayOrientedMeteringPointFactory, + ) => super.noSuchMethod( + Invocation.setter( + #newDisplayOrientedMeteringPointFactory, + _newDisplayOrientedMeteringPointFactory, + ), + returnValueForMissingStub: null, + ); + + @override + set controlAELockCaptureRequest( + _i2.CaptureRequestKey Function()? _controlAELockCaptureRequest, + ) => super.noSuchMethod( + Invocation.setter( + #controlAELockCaptureRequest, + _controlAELockCaptureRequest, + ), + returnValueForMissingStub: null, + ); } /// A class which mocks [CaptureRequestOptions]. @@ -3022,15 +3022,34 @@ class MockPendingRecording extends _i1.Mock implements _i2.PendingRecording { ) as _i2.PigeonInstanceManager); + @override + _i5.Future<_i2.PendingRecording> withAudioEnabled(bool? initialMuted) => + (super.noSuchMethod( + Invocation.method(#withAudioEnabled, [initialMuted]), + returnValue: _i5.Future<_i2.PendingRecording>.value( + _FakePendingRecording_39( + this, + Invocation.method(#withAudioEnabled, [initialMuted]), + ), + ), + returnValueForMissingStub: _i5.Future<_i2.PendingRecording>.value( + _FakePendingRecording_39( + this, + Invocation.method(#withAudioEnabled, [initialMuted]), + ), + ), + ) + as _i5.Future<_i2.PendingRecording>); + @override _i5.Future<_i2.Recording> start(_i2.VideoRecordEventListener? listener) => (super.noSuchMethod( Invocation.method(#start, [listener]), returnValue: _i5.Future<_i2.Recording>.value( - _FakeRecording_39(this, Invocation.method(#start, [listener])), + _FakeRecording_40(this, Invocation.method(#start, [listener])), ), returnValueForMissingStub: _i5.Future<_i2.Recording>.value( - _FakeRecording_39(this, Invocation.method(#start, [listener])), + _FakeRecording_40(this, Invocation.method(#start, [listener])), ), ) as _i5.Future<_i2.Recording>); @@ -3039,11 +3058,11 @@ class MockPendingRecording extends _i1.Mock implements _i2.PendingRecording { _i2.PendingRecording pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakePendingRecording_40( + returnValue: _FakePendingRecording_39( this, Invocation.method(#pigeon_copy, []), ), - returnValueForMissingStub: _FakePendingRecording_40( + returnValueForMissingStub: _FakePendingRecording_39( this, Invocation.method(#pigeon_copy, []), ), @@ -3389,13 +3408,13 @@ class MockRecorder extends _i1.Mock implements _i2.Recorder { (super.noSuchMethod( Invocation.method(#prepareRecording, [path]), returnValue: _i5.Future<_i2.PendingRecording>.value( - _FakePendingRecording_40( + _FakePendingRecording_39( this, Invocation.method(#prepareRecording, [path]), ), ), returnValueForMissingStub: _i5.Future<_i2.PendingRecording>.value( - _FakePendingRecording_40( + _FakePendingRecording_39( this, Invocation.method(#prepareRecording, [path]), ), @@ -3628,11 +3647,11 @@ class MockRecording extends _i1.Mock implements _i2.Recording { _i2.Recording pigeon_copy() => (super.noSuchMethod( Invocation.method(#pigeon_copy, []), - returnValue: _FakeRecording_39( + returnValue: _FakeRecording_40( this, Invocation.method(#pigeon_copy, []), ), - returnValueForMissingStub: _FakeRecording_39( + returnValueForMissingStub: _FakeRecording_40( this, Invocation.method(#pigeon_copy, []), ),