[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);
+  });
+}