[camera_platform_interface] Add platform interface methods for setting auto exposure. (#3345)
* Added platform interface methods for setting auto exposure.
* Added platform interface methods for setting auto exposure.
* Remove workspace files
diff --git a/packages/camera/camera_platform_interface/CHANGELOG.md b/packages/camera/camera_platform_interface/CHANGELOG.md
index d117e1c..8e31605 100644
--- a/packages/camera/camera_platform_interface/CHANGELOG.md
+++ b/packages/camera/camera_platform_interface/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.2.0
+
+- Added interface to support automatic exposure.
+
## 1.1.0
- Added an optional `maxVideoDuration` parameter to the `startVideoRecording` method, which allows implementations to limit the duration of a video recording.
diff --git a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart
index ab3d455..590713d 100644
--- a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart
+++ b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import '../../camera_platform_interface.dart';
+
/// Generic Event coming from the native side of Camera.
///
/// All [CameraEvent]s contain the `cameraId` that originated the event. This
@@ -45,6 +47,12 @@
/// The height of the preview in pixels.
final double previewHeight;
+ /// The default exposure mode
+ final ExposureMode exposureMode;
+
+ /// Whether setting exposure points is supported.
+ final bool exposurePointSupported;
+
/// Build a CameraInitialized event triggered from the camera represented by
/// `cameraId`.
///
@@ -54,6 +62,8 @@
int cameraId,
this.previewWidth,
this.previewHeight,
+ this.exposureMode,
+ this.exposurePointSupported,
) : super(cameraId);
/// Converts the supplied [Map] to an instance of the [CameraInitializedEvent]
@@ -61,6 +71,8 @@
CameraInitializedEvent.fromJson(Map<String, dynamic> json)
: previewWidth = json['previewWidth'],
previewHeight = json['previewHeight'],
+ exposureMode = deserializeExposureMode(json['exposureMode']),
+ exposurePointSupported = json['exposurePointSupported'],
super(json['cameraId']);
/// Converts the [CameraInitializedEvent] instance into a [Map] instance that
@@ -69,6 +81,8 @@
'cameraId': cameraId,
'previewWidth': previewWidth,
'previewHeight': previewHeight,
+ 'exposureMode': serializeExposureMode(exposureMode),
+ 'exposurePointSupported': exposurePointSupported,
};
@override
@@ -78,11 +92,17 @@
other is CameraInitializedEvent &&
runtimeType == other.runtimeType &&
previewWidth == other.previewWidth &&
- previewHeight == other.previewHeight;
+ previewHeight == other.previewHeight &&
+ exposureMode == other.exposureMode &&
+ exposurePointSupported == other.exposurePointSupported;
@override
int get hashCode =>
- super.hashCode ^ previewWidth.hashCode ^ previewHeight.hashCode;
+ super.hashCode ^
+ previewWidth.hashCode ^
+ previewHeight.hashCode ^
+ exposureMode.hashCode ^
+ exposurePointSupported.hashCode;
}
/// An event fired when the resolution preset of the camera has changed.
diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart
index bf2b3d3..6a73031 100644
--- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart
+++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'dart:async';
+import 'dart:math';
import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:camera_platform_interface/src/utils/utils.dart';
@@ -190,6 +191,62 @@
);
@override
+ Future<void> setExposureMode(int cameraId, ExposureMode mode) =>
+ _channel.invokeMethod<void>(
+ 'setExposureMode',
+ <String, dynamic>{
+ 'cameraId': cameraId,
+ 'mode': serializeExposureMode(mode),
+ },
+ );
+
+ @override
+ Future<void> setExposurePoint(int cameraId, Point<double> point) {
+ assert(point == null || point.x >= 0 && point.x <= 1);
+ assert(point == null || point.y >= 0 && point.y <= 1);
+ return _channel.invokeMethod<void>(
+ 'setExposurePoint',
+ <String, dynamic>{
+ 'cameraId': cameraId,
+ 'reset': point == null,
+ 'x': point?.x,
+ 'y': point?.y,
+ },
+ );
+ }
+
+ @override
+ Future<double> getMinExposureOffset(int cameraId) =>
+ _channel.invokeMethod<double>(
+ 'getMinExposureOffset',
+ <String, dynamic>{'cameraId': cameraId},
+ );
+
+ @override
+ Future<double> getMaxExposureOffset(int cameraId) =>
+ _channel.invokeMethod<double>(
+ 'getMaxExposureOffset',
+ <String, dynamic>{'cameraId': cameraId},
+ );
+
+ @override
+ Future<double> getExposureOffsetStepSize(int cameraId) =>
+ _channel.invokeMethod<double>(
+ 'getExposureOffsetStepSize',
+ <String, dynamic>{'cameraId': cameraId},
+ );
+
+ @override
+ Future<double> setExposureOffset(int cameraId, double offset) =>
+ _channel.invokeMethod<double>(
+ 'setExposureOffset',
+ <String, dynamic>{
+ 'cameraId': cameraId,
+ 'offset': offset,
+ },
+ );
+
+ @override
Future<double> getMaxZoomLevel(int cameraId) => _channel.invokeMethod<double>(
'getMaxZoomLevel',
<String, dynamic>{'cameraId': cameraId},
@@ -269,6 +326,8 @@
cameraId,
call.arguments['previewWidth'],
call.arguments['previewHeight'],
+ deserializeExposureMode(call.arguments['exposureMode']),
+ call.arguments['exposurePointSupported'],
));
break;
case 'resolution_changed':
diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart
index 6c8e200..c7a6032 100644
--- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart
+++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart
@@ -3,9 +3,11 @@
// found in the LICENSE file.
import 'dart:async';
+import 'dart:math';
import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:camera_platform_interface/src/method_channel/method_channel_camera.dart';
+import 'package:camera_platform_interface/src/types/exposure_mode.dart';
import 'package:cross_file/cross_file.dart';
import 'package:flutter/widgets.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
@@ -116,6 +118,48 @@
throw UnimplementedError('setFlashMode() is not implemented.');
}
+ /// Sets the exposure mode for taking pictures.
+ Future<void> setExposureMode(int cameraId, ExposureMode mode) {
+ throw UnimplementedError('setExposureMode() is not implemented.');
+ }
+
+ /// Sets the exposure point for automatically determining the exposure value.
+ Future<void> setExposurePoint(int cameraId, Point<double> point) {
+ throw UnimplementedError('setExposurePoint() is not implemented.');
+ }
+
+ /// Gets the minimum supported exposure offset for the selected camera in EV units.
+ Future<double> getMinExposureOffset(int cameraId) {
+ throw UnimplementedError('getMinExposureOffset() is not implemented.');
+ }
+
+ /// Gets the maximum supported exposure offset for the selected camera in EV units.
+ Future<double> getMaxExposureOffset(int cameraId) {
+ throw UnimplementedError('getMaxExposureOffset() is not implemented.');
+ }
+
+ /// Gets the supported step size for exposure offset for the selected camera in EV units.
+ ///
+ /// Returns 0 when the camera supports using a free value without stepping.
+ Future<double> getExposureOffsetStepSize(int cameraId) {
+ throw UnimplementedError('getMinExposureOffset() is not implemented.');
+ }
+
+ /// Sets the exposure offset for the selected camera.
+ ///
+ /// The supplied [offset] value should be in EV units. 1 EV unit represents a
+ /// doubling in brightness. It should be between the minimum and maximum offsets
+ /// obtained through `getMinExposureOffset` and `getMaxExposureOffset` respectively.
+ /// Throws a `CameraException` when an illegal offset is supplied.
+ ///
+ /// When the supplied [offset] value does not align with the step size obtained
+ /// through `getExposureStepSize`, it will automatically be rounded to the nearest step.
+ ///
+ /// Returns the (rounded) offset value that was set.
+ Future<double> setExposureOffset(int cameraId, double offset) {
+ throw UnimplementedError('setExposureOffset() is not implemented.');
+ }
+
/// Gets the maximum supported zoom level for the selected camera.
Future<double> getMaxZoomLevel(int cameraId) {
throw UnimplementedError('getMaxZoomLevel() is not implemented.');
@@ -129,7 +173,7 @@
/// Set the zoom level for the selected camera.
///
/// The supplied [zoom] value should be between 1.0 and the maximum supported
- /// zoom level returned by the `getMaxZoomLevel`. Throws an `CameraException`
+ /// zoom level returned by the `getMaxZoomLevel`. Throws a `CameraException`
/// when an illegal zoom level is supplied.
Future<void> setZoomLevel(int cameraId, double zoom) {
throw UnimplementedError('setZoomLevel() is not implemented.');
diff --git a/packages/camera/camera_platform_interface/lib/src/types/exposure_mode.dart b/packages/camera/camera_platform_interface/lib/src/types/exposure_mode.dart
new file mode 100644
index 0000000..836f538
--- /dev/null
+++ b/packages/camera/camera_platform_interface/lib/src/types/exposure_mode.dart
@@ -0,0 +1,36 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/// The possible exposure modes that can be set for a camera.
+enum ExposureMode {
+ /// Automatically determine exposure settings.
+ auto,
+
+ /// Lock the currently determined exposure settings.
+ locked,
+}
+
+/// Returns the exposure mode as a String.
+String serializeExposureMode(ExposureMode exposureMode) {
+ switch (exposureMode) {
+ case ExposureMode.locked:
+ return 'locked';
+ case ExposureMode.auto:
+ return 'auto';
+ default:
+ throw ArgumentError('Unknown ExposureMode value');
+ }
+}
+
+/// Returns the exposure mode for a given String.
+ExposureMode deserializeExposureMode(String str) {
+ switch (str) {
+ case "locked":
+ return ExposureMode.locked;
+ case "auto":
+ return ExposureMode.auto;
+ default:
+ throw ArgumentError('"$str" is not a valid ExposureMode value');
+ }
+}
diff --git a/packages/camera/camera_platform_interface/lib/src/types/types.dart b/packages/camera/camera_platform_interface/lib/src/types/types.dart
index 3a89a10..bab430e 100644
--- a/packages/camera/camera_platform_interface/lib/src/types/types.dart
+++ b/packages/camera/camera_platform_interface/lib/src/types/types.dart
@@ -6,3 +6,4 @@
export 'resolution_preset.dart';
export 'camera_exception.dart';
export 'flash_mode.dart';
+export 'exposure_mode.dart';
diff --git a/packages/camera/camera_platform_interface/pubspec.yaml b/packages/camera/camera_platform_interface/pubspec.yaml
index b693331..b8301d2 100644
--- a/packages/camera/camera_platform_interface/pubspec.yaml
+++ b/packages/camera/camera_platform_interface/pubspec.yaml
@@ -3,7 +3,7 @@
homepage: https://github.com/flutter/plugins/tree/master/packages/camera/camera_platform_interface
# NOTE: We strongly prefer non-breaking changes, even at the expense of a
# less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
-version: 1.1.0
+version: 1.2.0
dependencies:
flutter:
diff --git a/packages/camera/camera_platform_interface/test/camera_platform_interface_test.dart b/packages/camera/camera_platform_interface/test/camera_platform_interface_test.dart
index 7a6fc34..574fa45 100644
--- a/packages/camera/camera_platform_interface/test/camera_platform_interface_test.dart
+++ b/packages/camera/camera_platform_interface/test/camera_platform_interface_test.dart
@@ -187,6 +187,84 @@
});
test(
+ 'Default implementation of setExposureMode() should throw unimplemented error',
+ () {
+ // Arrange
+ final cameraPlatform = ExtendsCameraPlatform();
+
+ // Act & Assert
+ expect(
+ () => cameraPlatform.setExposureMode(1, null),
+ throwsUnimplementedError,
+ );
+ });
+
+ test(
+ 'Default implementation of setExposurePoint() should throw unimplemented error',
+ () {
+ // Arrange
+ final cameraPlatform = ExtendsCameraPlatform();
+
+ // Act & Assert
+ expect(
+ () => cameraPlatform.setExposurePoint(1, null),
+ throwsUnimplementedError,
+ );
+ });
+
+ test(
+ 'Default implementation of getMinExposureOffset() should throw unimplemented error',
+ () {
+ // Arrange
+ final cameraPlatform = ExtendsCameraPlatform();
+
+ // Act & Assert
+ expect(
+ () => cameraPlatform.getMinExposureOffset(1),
+ throwsUnimplementedError,
+ );
+ });
+
+ test(
+ 'Default implementation of getMaxExposureOffset() should throw unimplemented error',
+ () {
+ // Arrange
+ final cameraPlatform = ExtendsCameraPlatform();
+
+ // Act & Assert
+ expect(
+ () => cameraPlatform.getMaxExposureOffset(1),
+ throwsUnimplementedError,
+ );
+ });
+
+ test(
+ 'Default implementation of getExposureOffsetStepSize() should throw unimplemented error',
+ () {
+ // Arrange
+ final cameraPlatform = ExtendsCameraPlatform();
+
+ // Act & Assert
+ expect(
+ () => cameraPlatform.getExposureOffsetStepSize(1),
+ throwsUnimplementedError,
+ );
+ });
+
+ test(
+ 'Default implementation of setExposureOffset() should throw unimplemented error',
+ () {
+ // Arrange
+ final cameraPlatform = ExtendsCameraPlatform();
+
+ // Act & Assert
+ expect(
+ () => cameraPlatform.setExposureOffset(1, null),
+ throwsUnimplementedError,
+ );
+ });
+
+ test(
'Default implementation of startVideoRecording() should throw unimplemented error',
() {
// Arrange
diff --git a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart
index 01b03b8..1e28fa6 100644
--- a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart
+++ b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'package:camera_platform_interface/camera_platform_interface.dart';
+import 'package:camera_platform_interface/src/types/exposure_mode.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
@@ -10,11 +11,14 @@
group('CameraInitializedEvent tests', () {
test('Constructor should initialize all properties', () {
- final event = CameraInitializedEvent(1, 1024, 640);
+ final event =
+ CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true);
expect(event.cameraId, 1);
expect(event.previewWidth, 1024);
expect(event.previewHeight, 640);
+ expect(event.exposureMode, ExposureMode.auto);
+ expect(event.exposurePointSupported, true);
});
test('fromJson should initialize all properties', () {
@@ -22,57 +26,92 @@
'cameraId': 1,
'previewWidth': 1024.0,
'previewHeight': 640.0,
+ 'exposureMode': 'auto'
});
expect(event.cameraId, 1);
expect(event.previewWidth, 1024);
expect(event.previewHeight, 640);
+ expect(event.exposureMode, ExposureMode.auto);
});
test('toJson should return a map with all fields', () {
- final event = CameraInitializedEvent(1, 1024, 640);
+ final event =
+ CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true);
final jsonMap = event.toJson();
- expect(jsonMap.length, 3);
+ expect(jsonMap.length, 5);
expect(jsonMap['cameraId'], 1);
expect(jsonMap['previewWidth'], 1024);
expect(jsonMap['previewHeight'], 640);
+ expect(jsonMap['exposureMode'], 'auto');
+ expect(jsonMap['exposurePointSupported'], true);
});
test('equals should return true if objects are the same', () {
- final firstEvent = CameraInitializedEvent(1, 1024, 640);
- final secondEvent = CameraInitializedEvent(1, 1024, 640);
+ final firstEvent =
+ CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true);
+ final secondEvent =
+ CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true);
expect(firstEvent == secondEvent, true);
});
test('equals should return false if cameraId is different', () {
- final firstEvent = CameraInitializedEvent(1, 1024, 640);
- final secondEvent = CameraInitializedEvent(2, 1024, 640);
+ final firstEvent =
+ CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true);
+ final secondEvent =
+ CameraInitializedEvent(2, 1024, 640, ExposureMode.auto, true);
expect(firstEvent == secondEvent, false);
});
test('equals should return false if previewWidth is different', () {
- final firstEvent = CameraInitializedEvent(1, 1024, 640);
- final secondEvent = CameraInitializedEvent(1, 2048, 640);
+ final firstEvent =
+ CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true);
+ final secondEvent =
+ CameraInitializedEvent(1, 2048, 640, ExposureMode.auto, true);
expect(firstEvent == secondEvent, false);
});
test('equals should return false if previewHeight is different', () {
- final firstEvent = CameraInitializedEvent(1, 1024, 640);
- final secondEvent = CameraInitializedEvent(1, 1024, 980);
+ final firstEvent =
+ CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true);
+ final secondEvent =
+ CameraInitializedEvent(1, 1024, 980, ExposureMode.auto, true);
+
+ expect(firstEvent == secondEvent, false);
+ });
+
+ test('equals should return false if exposureMode is different', () {
+ final firstEvent =
+ CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true);
+ final secondEvent =
+ CameraInitializedEvent(1, 1024, 640, ExposureMode.locked, true);
+
+ expect(firstEvent == secondEvent, false);
+ });
+
+ test('equals should return false if exposurePointSupported is different',
+ () {
+ final firstEvent =
+ CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true);
+ final secondEvent =
+ CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, false);
expect(firstEvent == secondEvent, false);
});
test('hashCode should match hashCode of all properties', () {
- final event = CameraInitializedEvent(1, 1024, 640);
- final expectedHashCode = event.cameraId.hashCode ^
+ final event =
+ CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true);
+ final expectedHashCode = event.cameraId ^
event.previewWidth.hashCode ^
- event.previewHeight.hashCode;
+ event.previewHeight.hashCode ^
+ event.exposureMode.hashCode ^
+ event.exposurePointSupported.hashCode;
expect(event.hashCode, expectedHashCode);
});
diff --git a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart
index 12f5d6e..b916513 100644
--- a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart
+++ b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart
@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'dart:async';
+import 'dart:math';
import 'package:async/async.dart';
import 'package:camera_platform_interface/camera_platform_interface.dart';
@@ -118,8 +119,13 @@
// Act
Future<void> initializeFuture = camera.initializeCamera(cameraId);
- camera.cameraEventStreamController
- .add(CameraInitializedEvent(cameraId, 1920, 1080));
+ camera.cameraEventStreamController.add(CameraInitializedEvent(
+ cameraId,
+ 1920,
+ 1080,
+ ExposureMode.auto,
+ true,
+ ));
await initializeFuture;
// Assert
@@ -151,8 +157,13 @@
ResolutionPreset.high,
);
Future<void> initializeFuture = camera.initializeCamera(cameraId);
- camera.cameraEventStreamController
- .add(CameraInitializedEvent(cameraId, 1920, 1080));
+ camera.cameraEventStreamController.add(CameraInitializedEvent(
+ cameraId,
+ 1920,
+ 1080,
+ ExposureMode.auto,
+ true,
+ ));
await initializeFuture;
// Act
@@ -188,8 +199,13 @@
ResolutionPreset.high,
);
Future<void> initializeFuture = camera.initializeCamera(cameraId);
- camera.cameraEventStreamController
- .add(CameraInitializedEvent(cameraId, 1920, 1080));
+ camera.cameraEventStreamController.add(CameraInitializedEvent(
+ cameraId,
+ 1920,
+ 1080,
+ ExposureMode.auto,
+ true,
+ ));
await initializeFuture;
});
@@ -200,7 +216,13 @@
final streamQueue = StreamQueue(eventStream);
// Emit test events
- final event = CameraInitializedEvent(cameraId, 3840, 2160);
+ final event = CameraInitializedEvent(
+ cameraId,
+ 3840,
+ 2160,
+ ExposureMode.auto,
+ true,
+ );
await camera.handleMethodCall(
MethodCall('initialized', event.toJson()), cameraId);
@@ -304,8 +326,15 @@
ResolutionPreset.high,
);
Future<void> initializeFuture = camera.initializeCamera(cameraId);
- camera.cameraEventStreamController
- .add(CameraInitializedEvent(cameraId, 1920, 1080));
+ camera.cameraEventStreamController.add(
+ CameraInitializedEvent(
+ cameraId,
+ 1920,
+ 1080,
+ ExposureMode.auto,
+ true,
+ ),
+ );
await initializeFuture;
});
@@ -518,6 +547,131 @@
]);
});
+ test('Should set the exposure mode', () async {
+ // Arrange
+ MethodChannelMock channel = MethodChannelMock(
+ channelName: 'plugins.flutter.io/camera',
+ methods: {'setExposureMode': null},
+ );
+
+ // Act
+ await camera.setExposureMode(cameraId, ExposureMode.auto);
+ await camera.setExposureMode(cameraId, ExposureMode.locked);
+
+ // Assert
+ expect(channel.log, <Matcher>[
+ isMethodCall('setExposureMode',
+ arguments: {'cameraId': cameraId, 'mode': 'auto'}),
+ isMethodCall('setExposureMode',
+ arguments: {'cameraId': cameraId, 'mode': 'locked'}),
+ ]);
+ });
+
+ test('Should set the exposure point', () async {
+ // Arrange
+ MethodChannelMock channel = MethodChannelMock(
+ channelName: 'plugins.flutter.io/camera',
+ methods: {'setExposurePoint': null},
+ );
+
+ // Act
+ await camera.setExposurePoint(cameraId, Point<double>(0.5, 0.5));
+ await camera.setExposurePoint(cameraId, null);
+
+ // Assert
+ expect(channel.log, <Matcher>[
+ isMethodCall('setExposurePoint', arguments: {
+ 'cameraId': cameraId,
+ 'x': 0.5,
+ 'y': 0.5,
+ 'reset': false
+ }),
+ isMethodCall('setExposurePoint', arguments: {
+ 'cameraId': cameraId,
+ 'x': null,
+ 'y': null,
+ 'reset': true
+ }),
+ ]);
+ });
+
+ test('Should get the min exposure offset', () async {
+ // Arrange
+ MethodChannelMock channel = MethodChannelMock(
+ channelName: 'plugins.flutter.io/camera',
+ methods: {'getMinExposureOffset': 2.0},
+ );
+
+ // Act
+ final minExposureOffset = await camera.getMinExposureOffset(cameraId);
+
+ // Assert
+ expect(minExposureOffset, 2.0);
+ expect(channel.log, <Matcher>[
+ isMethodCall('getMinExposureOffset', arguments: {
+ 'cameraId': cameraId,
+ }),
+ ]);
+ });
+
+ test('Should get the max exposure offset', () async {
+ // Arrange
+ MethodChannelMock channel = MethodChannelMock(
+ channelName: 'plugins.flutter.io/camera',
+ methods: {'getMaxExposureOffset': 2.0},
+ );
+
+ // Act
+ final maxExposureOffset = await camera.getMaxExposureOffset(cameraId);
+
+ // Assert
+ expect(maxExposureOffset, 2.0);
+ expect(channel.log, <Matcher>[
+ isMethodCall('getMaxExposureOffset', arguments: {
+ 'cameraId': cameraId,
+ }),
+ ]);
+ });
+
+ test('Should get the exposure offset step size', () async {
+ // Arrange
+ MethodChannelMock channel = MethodChannelMock(
+ channelName: 'plugins.flutter.io/camera',
+ methods: {'getExposureOffsetStepSize': 0.25},
+ );
+
+ // Act
+ final stepSize = await camera.getExposureOffsetStepSize(cameraId);
+
+ // Assert
+ expect(stepSize, 0.25);
+ expect(channel.log, <Matcher>[
+ isMethodCall('getExposureOffsetStepSize', arguments: {
+ 'cameraId': cameraId,
+ }),
+ ]);
+ });
+
+ test('Should set the exposure offset', () async {
+ // Arrange
+ MethodChannelMock channel = MethodChannelMock(
+ channelName: 'plugins.flutter.io/camera',
+ methods: {'setExposureOffset': 0.6},
+ );
+
+ // Act
+ final actualOffset = await camera.setExposureOffset(cameraId, 0.5);
+
+ // Assert
+ expect(actualOffset, 0.6);
+ expect(channel.log, <Matcher>[
+ isMethodCall('setExposureOffset', arguments: {
+ 'cameraId': cameraId,
+ 'offset': 0.5,
+ }),
+ ]);
+ });
+
test('Should build a texture widget as preview widget', () async {
// Act
Widget widget = camera.buildPreview(cameraId);
diff --git a/packages/camera/camera_platform_interface/test/types/exposure_mode_test.dart b/packages/camera/camera_platform_interface/test/types/exposure_mode_test.dart
new file mode 100644
index 0000000..c34c1d7
--- /dev/null
+++ b/packages/camera/camera_platform_interface/test/types/exposure_mode_test.dart
@@ -0,0 +1,32 @@
+// Copyright 2019 The Chromium 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_platform_interface/camera_platform_interface.dart';
+import 'package:camera_platform_interface/src/types/exposure_mode.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ test('ExposureMode should contain 2 options', () {
+ final values = ExposureMode.values;
+
+ expect(values.length, 2);
+ });
+
+ test("ExposureMode enum should have items in correct index", () {
+ final values = ExposureMode.values;
+
+ expect(values[0], ExposureMode.auto);
+ expect(values[1], ExposureMode.locked);
+ });
+
+ test("serializeExposureMode() should serialize correctly", () {
+ expect(serializeExposureMode(ExposureMode.auto), "auto");
+ expect(serializeExposureMode(ExposureMode.locked), "locked");
+ });
+
+ test("deserializeExposureMode() should deserialize correctly", () {
+ expect(deserializeExposureMode('auto'), ExposureMode.auto);
+ expect(deserializeExposureMode('locked'), ExposureMode.locked);
+ });
+}