Reland "[null-safety] reland: migrate app side flutter driver to null-safety" (#67570)

diff --git a/packages/flutter/analysis_options.yaml b/packages/flutter/analysis_options.yaml
index 00d1a5a..a368eea 100644
--- a/packages/flutter/analysis_options.yaml
+++ b/packages/flutter/analysis_options.yaml
@@ -10,4 +10,4 @@
     type_init_formals: false # https://github.com/dart-lang/linter/issues/2192
     unrelated_type_equality_checks: false # https://github.com/dart-lang/linter/issues/2196
     void_checks: false # https://github.com/dart-lang/linter/issues/2185
-    unnecessary_null_comparison: false # https://github.com/dart-lang/language/issues/1018 , turned off until https://github.com/flutter/flutter/issues/61042
+    unnecessary_null_comparison: false # Turned off until null-safe rollout is complete.
diff --git a/packages/flutter_driver/analysis_options.yaml b/packages/flutter_driver/analysis_options.yaml
new file mode 100644
index 0000000..a368eea
--- /dev/null
+++ b/packages/flutter_driver/analysis_options.yaml
@@ -0,0 +1,13 @@
+# Use the parent analysis options settings and enable null-experiment.
+
+include: ../analysis_options.yaml
+
+analyzer:
+  enable-experiment:
+    - non-nullable
+  errors:
+    always_require_non_null_named_parameters: false # not needed with nnbd
+    type_init_formals: false # https://github.com/dart-lang/linter/issues/2192
+    unrelated_type_equality_checks: false # https://github.com/dart-lang/linter/issues/2196
+    void_checks: false # https://github.com/dart-lang/linter/issues/2185
+    unnecessary_null_comparison: false # Turned off until null-safe rollout is complete.
diff --git a/packages/flutter_driver/lib/flutter_driver.dart b/packages/flutter_driver/lib/flutter_driver.dart
index 7077074..46ebb8c 100644
--- a/packages/flutter_driver/lib/flutter_driver.dart
+++ b/packages/flutter_driver/lib/flutter_driver.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.
 
+// @dart = 2.8
+
 /// Provides API to test Flutter applications that run on real
 /// devices and emulators.
 ///
diff --git a/packages/flutter_driver/lib/src/common/diagnostics_tree.dart b/packages/flutter_driver/lib/src/common/diagnostics_tree.dart
index 496bce5..ec4b53d 100644
--- a/packages/flutter_driver/lib/src/common/diagnostics_tree.dart
+++ b/packages/flutter_driver/lib/src/common/diagnostics_tree.dart
@@ -27,16 +27,16 @@
   GetDiagnosticsTree(SerializableFinder finder, this.diagnosticsType, {
     this.subtreeDepth = 0,
     this.includeProperties = true,
-    Duration timeout,
+    Duration? timeout,
   }) : assert(subtreeDepth != null),
        assert(includeProperties != null),
        super(finder, timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   GetDiagnosticsTree.deserialize(Map<String, String> json, DeserializeFinderFactory finderFactory)
-      : subtreeDepth = int.parse(json['subtreeDepth']),
+      : subtreeDepth = int.parse(json['subtreeDepth']!),
         includeProperties = json['includeProperties'] == 'true',
-        diagnosticsType = _diagnosticsTypeIndex.lookupBySimpleName(json['diagnosticsType']),
+        diagnosticsType = _diagnosticsTypeIndex.lookupBySimpleName(json['diagnosticsType']!),
         super.deserialize(json, finderFactory);
 
   /// How many levels of children to include in the JSON result.
@@ -69,7 +69,7 @@
 
   /// The JSON encoded [DiagnosticsNode] tree requested by the
   /// [GetDiagnosticsTree] command.
-  final Map<String, Object> json;
+  final Map<String, dynamic> json;
 
   @override
   Map<String, dynamic> toJson() => json;
diff --git a/packages/flutter_driver/lib/src/common/enum_util.dart b/packages/flutter_driver/lib/src/common/enum_util.dart
index 3af7803..0f54221 100644
--- a/packages/flutter_driver/lib/src/common/enum_util.dart
+++ b/packages/flutter_driver/lib/src/common/enum_util.dart
@@ -31,10 +31,10 @@
   final Map<E, String> _valueToName;
 
   /// Given a [simpleName] finds the corresponding enum value.
-  E lookupBySimpleName(String simpleName) => _nameToValue[simpleName];
+  E lookupBySimpleName(String simpleName) => _nameToValue[simpleName]!;
 
   /// Returns the simple name for [enumValue].
-  String toSimpleName(E enumValue) => _valueToName[enumValue];
+  String toSimpleName(E enumValue) => _valueToName[enumValue]!;
 }
 
 String _getSimpleName(dynamic enumValue) {
diff --git a/packages/flutter_driver/lib/src/common/find.dart b/packages/flutter_driver/lib/src/common/find.dart
index 3de4862..bdb6ac2 100644
--- a/packages/flutter_driver/lib/src/common/find.dart
+++ b/packages/flutter_driver/lib/src/common/find.dart
@@ -13,7 +13,7 @@
 mixin DeserializeFinderFactory {
   /// Deserializes the finder from JSON generated by [SerializableFinder.serialize].
   SerializableFinder deserializeFinder(Map<String, String> json) {
-    final String finderType = json['finderType'];
+    final String? finderType = json['finderType'];
     switch (finderType) {
       case 'ByType': return ByType.deserialize(json);
       case 'ByValueKey': return ByValueKey.deserialize(json);
@@ -41,7 +41,7 @@
 /// and add more keys to the returned map.
 abstract class CommandWithTarget extends Command {
   /// Constructs this command given a [finder].
-  CommandWithTarget(this.finder, {Duration timeout}) : super(timeout: timeout) {
+  CommandWithTarget(this.finder, {Duration? timeout}) : super(timeout: timeout) {
     assert(finder != null, '$runtimeType target cannot be null');
   }
 
@@ -72,7 +72,7 @@
   /// appear within the [timeout] amount of time.
   ///
   /// If [timeout] is not specified, the command defaults to no timeout.
-  WaitFor(SerializableFinder finder, {Duration timeout})
+  WaitFor(SerializableFinder finder, {Duration? timeout})
     : super(finder, timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
@@ -102,7 +102,7 @@
   /// disappear within the [timeout] amount of time.
   ///
   /// If [timeout] is not specified, the command defaults to no timeout.
-  WaitForAbsent(SerializableFinder finder, {Duration timeout})
+  WaitForAbsent(SerializableFinder finder, {Duration? timeout})
     : super(finder, timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
@@ -164,7 +164,7 @@
 
   /// Deserializes the finder from JSON generated by [serialize].
   static ByTooltipMessage deserialize(Map<String, String> json) {
-    return ByTooltipMessage(json['text']);
+    return ByTooltipMessage(json['text']!);
   }
 }
 
@@ -202,7 +202,7 @@
   /// Deserializes the finder from JSON generated by [serialize].
   static BySemanticsLabel deserialize(Map<String, String> json) {
     final bool isRegExp = json['isRegExp'] == 'true';
-    return BySemanticsLabel(isRegExp ? RegExp(json['label']) : json['label']);
+    return BySemanticsLabel(isRegExp ? RegExp(json['label']!) : json['label']!);
   }
 }
 
@@ -225,7 +225,7 @@
 
   /// Deserializes the finder from JSON generated by [serialize].
   static ByText deserialize(Map<String, String> json) {
-    return ByText(json['text']);
+    return ByText(json['text']!);
   }
 }
 
@@ -261,8 +261,8 @@
 
   /// Deserializes the finder from JSON generated by [serialize].
   static ByValueKey deserialize(Map<String, String> json) {
-    final String keyValueString = json['keyValueString'];
-    final String keyValueType = json['keyValueType'];
+    final String keyValueString = json['keyValueString']!;
+    final String keyValueType = json['keyValueType']!;
     switch (keyValueType) {
       case 'int':
         return ByValueKey(int.parse(keyValueString));
@@ -292,7 +292,7 @@
 
   /// Deserializes the finder from JSON generated by [serialize].
   static ByType deserialize(Map<String, String> json) {
-    return ByType(json['type']);
+    return ByType(json['type']!);
   }
 }
 
@@ -318,8 +318,8 @@
 class Descendant extends SerializableFinder {
   /// Creates a descendant finder.
   const Descendant({
-    @required this.of,
-    @required this.matching,
+    required this.of,
+    required this.matching,
     this.matchRoot = false,
     this.firstMatchOnly = false,
   });
@@ -353,9 +353,9 @@
   /// Deserializes the finder from JSON generated by [serialize].
   static Descendant deserialize(Map<String, String> json, DeserializeFinderFactory finderFactory) {
     final Map<String, String> jsonOfMatcher =
-        Map<String, String>.from(jsonDecode(json['of']) as Map<String, dynamic>);
+        Map<String, String>.from(jsonDecode(json['of']!) as Map<String, dynamic>);
     final Map<String, String> jsonMatchingMatcher =
-        Map<String, String>.from(jsonDecode(json['matching']) as Map<String, dynamic>);
+        Map<String, String>.from(jsonDecode(json['matching']!) as Map<String, dynamic>);
     return Descendant(
       of: finderFactory.deserializeFinder(jsonOfMatcher),
       matching: finderFactory.deserializeFinder(jsonMatchingMatcher),
@@ -373,8 +373,8 @@
 class Ancestor extends SerializableFinder {
   /// Creates an ancestor finder.
   const Ancestor({
-    @required this.of,
-    @required this.matching,
+    required this.of,
+    required this.matching,
     this.matchRoot = false,
     this.firstMatchOnly = false,
   });
@@ -408,9 +408,9 @@
   /// Deserializes the finder from JSON generated by [serialize].
   static Ancestor deserialize(Map<String, String> json, DeserializeFinderFactory finderFactory) {
     final Map<String, String> jsonOfMatcher =
-        Map<String, String>.from(jsonDecode(json['of']) as Map<String, dynamic>);
+        Map<String, String>.from(jsonDecode(json['of']!) as Map<String, dynamic>);
     final Map<String, String> jsonMatchingMatcher =
-        Map<String, String>.from(jsonDecode(json['matching']) as Map<String, dynamic>);
+        Map<String, String>.from(jsonDecode(json['matching']!) as Map<String, dynamic>);
     return Ancestor(
       of: finderFactory.deserializeFinder(jsonOfMatcher),
       matching: finderFactory.deserializeFinder(jsonMatchingMatcher),
@@ -435,7 +435,7 @@
 class GetSemanticsId extends CommandWithTarget {
 
   /// Creates a command which finds a Widget and then looks up the semantic id.
-  GetSemanticsId(SerializableFinder finder, {Duration timeout}) : super(finder, timeout: timeout);
+  GetSemanticsId(SerializableFinder finder, {Duration? timeout}) : super(finder, timeout: timeout);
 
   /// Creates a command from a JSON map.
   GetSemanticsId.deserialize(Map<String, String> json, DeserializeFinderFactory finderFactory)
diff --git a/packages/flutter_driver/lib/src/common/frame_sync.dart b/packages/flutter_driver/lib/src/common/frame_sync.dart
index e19e3c4..a9fd347 100644
--- a/packages/flutter_driver/lib/src/common/frame_sync.dart
+++ b/packages/flutter_driver/lib/src/common/frame_sync.dart
@@ -7,11 +7,11 @@
 /// A Flutter Driver command that enables or disables the FrameSync mechanism.
 class SetFrameSync extends Command {
   /// Creates a command to toggle the FrameSync mechanism.
-  const SetFrameSync(this.enabled, { Duration timeout }) : super(timeout: timeout);
+  const SetFrameSync(this.enabled, { Duration? timeout }) : super(timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   SetFrameSync.deserialize(Map<String, String> params)
-    : enabled = params['enabled'].toLowerCase() == 'true',
+    : enabled = params['enabled']!.toLowerCase() == 'true',
       super.deserialize(params);
 
   /// Whether frameSync should be enabled or disabled.
diff --git a/packages/flutter_driver/lib/src/common/fuchsia_compat.dart b/packages/flutter_driver/lib/src/common/fuchsia_compat.dart
index 13847d1..a92cacd 100644
--- a/packages/flutter_driver/lib/src/common/fuchsia_compat.dart
+++ b/packages/flutter_driver/lib/src/common/fuchsia_compat.dart
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// @dart = 2.8
+
 /// Convenience methods for Flutter application driving on Fuchsia. Can
 /// be run on either a host machine (making a remote connection to a Fuchsia
 /// device), or on the target Fuchsia machine.
-import 'dart:core';
 import 'dart:io';
 
 import 'package:fuchsia_remote_debug_protocol/fuchsia_remote_debug_protocol.dart';
diff --git a/packages/flutter_driver/lib/src/common/geometry.dart b/packages/flutter_driver/lib/src/common/geometry.dart
index 3aea6f1..c8e4a32 100644
--- a/packages/flutter_driver/lib/src/common/geometry.dart
+++ b/packages/flutter_driver/lib/src/common/geometry.dart
@@ -33,11 +33,11 @@
 /// to device pixels via [Window.devicePixelRatio].
 class GetOffset extends CommandWithTarget {
   /// The `finder` looks for an element to get its rect.
-  GetOffset(SerializableFinder finder,  this.offsetType, { Duration timeout }) : super(finder, timeout: timeout);
+  GetOffset(SerializableFinder finder,  this.offsetType, { Duration? timeout }) : super(finder, timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   GetOffset.deserialize(Map<String, String> json, DeserializeFinderFactory finderFactory)
-      : offsetType = _offsetTypeIndex.lookupBySimpleName(json['offsetType']),
+      : offsetType = _offsetTypeIndex.lookupBySimpleName(json['offsetType']!),
         super.deserialize(json, finderFactory);
 
   @override
diff --git a/packages/flutter_driver/lib/src/common/gesture.dart b/packages/flutter_driver/lib/src/common/gesture.dart
index 8d652c3..5a66767 100644
--- a/packages/flutter_driver/lib/src/common/gesture.dart
+++ b/packages/flutter_driver/lib/src/common/gesture.dart
@@ -8,7 +8,7 @@
 /// A Flutter Driver command that taps on a target widget located by [finder].
 class Tap extends CommandWithTarget {
   /// Creates a tap command to tap on a widget located by [finder].
-  Tap(SerializableFinder finder, { Duration timeout }) : super(finder, timeout: timeout);
+  Tap(SerializableFinder finder, { Duration? timeout }) : super(finder, timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   Tap.deserialize(Map<String, String> json, DeserializeFinderFactory finderFactory) : super.deserialize(json, finderFactory);
@@ -42,15 +42,15 @@
     this.dy,
     this.duration,
     this.frequency, {
-    Duration timeout,
+    Duration? timeout,
   }) : super(finder, timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   Scroll.deserialize(Map<String, String> json, DeserializeFinderFactory finderFactory)
-    : dx = double.parse(json['dx']),
-      dy = double.parse(json['dy']),
-      duration = Duration(microseconds: int.parse(json['duration'])),
-      frequency = int.parse(json['frequency']),
+    : dx = double.parse(json['dx']!),
+      dy = double.parse(json['dy']!),
+      duration = Duration(microseconds: int.parse(json['duration']!)),
+      frequency = int.parse(json['frequency']!),
       super.deserialize(json, finderFactory);
 
   /// Delta X offset per move event.
@@ -96,11 +96,11 @@
 class ScrollIntoView extends CommandWithTarget {
   /// Creates this command given a [finder] used to locate the widget to be
   /// scrolled into view.
-  ScrollIntoView(SerializableFinder finder, { this.alignment = 0.0, Duration timeout }) : super(finder, timeout: timeout);
+  ScrollIntoView(SerializableFinder finder, { this.alignment = 0.0, Duration? timeout }) : super(finder, timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   ScrollIntoView.deserialize(Map<String, String> json, DeserializeFinderFactory finderFactory)
-    : alignment = double.parse(json['alignment']),
+    : alignment = double.parse(json['alignment']!),
       super.deserialize(json, finderFactory);
 
   /// How the widget should be aligned.
diff --git a/packages/flutter_driver/lib/src/common/health.dart b/packages/flutter_driver/lib/src/common/health.dart
index 34a7879..a67ac6c 100644
--- a/packages/flutter_driver/lib/src/common/health.dart
+++ b/packages/flutter_driver/lib/src/common/health.dart
@@ -8,7 +8,7 @@
 /// A Flutter Driver command that requests an application health check.
 class GetHealth extends Command {
   /// Create a health check command.
-  const GetHealth({ Duration timeout }) : super(timeout: timeout);
+  const GetHealth({ Duration? timeout }) : super(timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   GetHealth.deserialize(Map<String, String> json) : super.deserialize(json);
diff --git a/packages/flutter_driver/lib/src/common/layer_tree.dart b/packages/flutter_driver/lib/src/common/layer_tree.dart
index 647903c..9129ee7 100644
--- a/packages/flutter_driver/lib/src/common/layer_tree.dart
+++ b/packages/flutter_driver/lib/src/common/layer_tree.dart
@@ -7,7 +7,7 @@
 /// A Flutter Driver command that requests a string representation of the layer tree.
 class GetLayerTree extends Command {
   /// Create a command to request a string representation of the layer tree.
-  const GetLayerTree({ Duration timeout }) : super(timeout: timeout);
+  const GetLayerTree({ Duration? timeout }) : super(timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   GetLayerTree.deserialize(Map<String, String> json) : super.deserialize(json);
@@ -23,7 +23,7 @@
   const LayerTree(this.tree);
 
   /// String representation of the layer tree.
-  final String tree;
+  final String? tree;
 
   /// Deserializes the result from JSON.
   static LayerTree fromJson(Map<String, dynamic> json) {
diff --git a/packages/flutter_driver/lib/src/common/message.dart b/packages/flutter_driver/lib/src/common/message.dart
index 88782bd..893af07 100644
--- a/packages/flutter_driver/lib/src/common/message.dart
+++ b/packages/flutter_driver/lib/src/common/message.dart
@@ -15,8 +15,8 @@
   Command.deserialize(Map<String, String> json)
     : timeout = _parseTimeout(json);
 
-  static Duration _parseTimeout(Map<String, String> json) {
-    final String timeout = json['timeout'];
+  static Duration? _parseTimeout(Map<String, String> json) {
+    final String? timeout = json['timeout'];
     if (timeout == null)
       return null;
     return Duration(milliseconds: int.parse(timeout));
@@ -27,7 +27,7 @@
   /// Defaults to no timeout, because it is common for operations to take oddly
   /// long in test environments (e.g. because the test host is overloaded), and
   /// having timeouts essentially means having race conditions.
-  final Duration timeout;
+  final Duration? timeout;
 
   /// Identifies the type of the command object and of the handler.
   String get kind;
@@ -53,7 +53,7 @@
       'command': kind,
     };
     if (timeout != null)
-      result['timeout'] = '${timeout.inMilliseconds}';
+      result['timeout'] = '${timeout!.inMilliseconds}';
     return result;
   }
 }
diff --git a/packages/flutter_driver/lib/src/common/render_tree.dart b/packages/flutter_driver/lib/src/common/render_tree.dart
index a0884cc..7e4eafe 100644
--- a/packages/flutter_driver/lib/src/common/render_tree.dart
+++ b/packages/flutter_driver/lib/src/common/render_tree.dart
@@ -7,7 +7,7 @@
 /// A Flutter Driver command that requests a string representation of the render tree.
 class GetRenderTree extends Command {
   /// Create a command to request a string representation of the render tree.
-  const GetRenderTree({ Duration timeout }) : super(timeout: timeout);
+  const GetRenderTree({ Duration? timeout }) : super(timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   GetRenderTree.deserialize(Map<String, String> json) : super.deserialize(json);
@@ -23,7 +23,7 @@
   const RenderTree(this.tree);
 
   /// String representation of the render tree.
-  final String tree;
+  final String? tree;
 
   /// Deserializes the result from JSON.
   static RenderTree fromJson(Map<String, dynamic> json) {
diff --git a/packages/flutter_driver/lib/src/common/request_data.dart b/packages/flutter_driver/lib/src/common/request_data.dart
index c1ac123..bc53743 100644
--- a/packages/flutter_driver/lib/src/common/request_data.dart
+++ b/packages/flutter_driver/lib/src/common/request_data.dart
@@ -8,7 +8,7 @@
 /// string response.
 class RequestData extends Command {
   /// Create a command that sends a message.
-  const RequestData(this.message, { Duration timeout }) : super(timeout: timeout);
+  const RequestData(this.message, { Duration? timeout }) : super(timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   RequestData.deserialize(Map<String, String> params)
@@ -16,7 +16,7 @@
       super.deserialize(params);
 
   /// The message being sent from the test to the application.
-  final String message;
+  final String? message;
 
   @override
   String get kind => 'request_data';
@@ -26,7 +26,8 @@
 
   @override
   Map<String, String> serialize() => super.serialize()..addAll(<String, String>{
-    'message': message,
+    if (message != null)
+      'message': message!,
   });
 }
 
diff --git a/packages/flutter_driver/lib/src/common/semantics.dart b/packages/flutter_driver/lib/src/common/semantics.dart
index 400072f..7c56825 100644
--- a/packages/flutter_driver/lib/src/common/semantics.dart
+++ b/packages/flutter_driver/lib/src/common/semantics.dart
@@ -7,11 +7,11 @@
 /// A Flutter Driver command that enables or disables semantics.
 class SetSemantics extends Command {
   /// Creates a command that enables or disables semantics.
-  const SetSemantics(this.enabled, { Duration timeout }) : super(timeout: timeout);
+  const SetSemantics(this.enabled, { Duration? timeout }) : super(timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   SetSemantics.deserialize(Map<String, String> params)
-    : enabled = params['enabled'].toLowerCase() == 'true',
+    : enabled = params['enabled']!.toLowerCase() == 'true',
       super.deserialize(params);
 
   /// Whether semantics should be enabled (true) or disabled (false).
diff --git a/packages/flutter_driver/lib/src/common/text.dart b/packages/flutter_driver/lib/src/common/text.dart
index 7d60139..6ccaf84 100644
--- a/packages/flutter_driver/lib/src/common/text.dart
+++ b/packages/flutter_driver/lib/src/common/text.dart
@@ -8,7 +8,7 @@
 /// A Flutter Driver command that reads the text from a given element.
 class GetText extends CommandWithTarget {
   /// [finder] looks for an element that contains a piece of text.
-  GetText(SerializableFinder finder, { Duration timeout }) : super(finder, timeout: timeout);
+  GetText(SerializableFinder finder, { Duration? timeout }) : super(finder, timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   GetText.deserialize(Map<String, String> json, DeserializeFinderFactory finderFactory) : super.deserialize(json, finderFactory);
@@ -39,11 +39,11 @@
 /// A Flutter Driver command that enters text into the currently focused widget.
 class EnterText extends Command {
   /// Creates a command that enters text into the currently focused widget.
-  const EnterText(this.text, { Duration timeout }) : super(timeout: timeout);
+  const EnterText(this.text, { Duration? timeout }) : super(timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   EnterText.deserialize(Map<String, String> json)
-    : text = json['text'],
+    : text = json['text']!,
       super.deserialize(json);
 
   /// The text extracted by the [GetText] command.
@@ -75,7 +75,7 @@
 /// A Flutter Driver command that enables and disables text entry emulation.
 class SetTextEntryEmulation extends Command {
   /// Creates a command that enables and disables text entry emulation.
-  const SetTextEntryEmulation(this.enabled, { Duration timeout }) : super(timeout: timeout);
+  const SetTextEntryEmulation(this.enabled, { Duration? timeout }) : super(timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   SetTextEntryEmulation.deserialize(Map<String, String> json)
diff --git a/packages/flutter_driver/lib/src/common/wait.dart b/packages/flutter_driver/lib/src/common/wait.dart
index a3243a5..7f8db7b 100644
--- a/packages/flutter_driver/lib/src/common/wait.dart
+++ b/packages/flutter_driver/lib/src/common/wait.dart
@@ -11,7 +11,7 @@
   /// Creates a command that waits for the given [condition] is met.
   ///
   /// The [condition] argument must not be null.
-  const WaitForCondition(this.condition, {Duration timeout})
+  const WaitForCondition(this.condition, {Duration? timeout})
       : assert(condition != null),
         super(timeout: timeout);
 
@@ -51,7 +51,7 @@
 )
 class WaitUntilNoTransientCallbacks extends Command {
   /// Creates a command that waits for there to be no transient callbacks.
-  const WaitUntilNoTransientCallbacks({ Duration timeout }) : super(timeout: timeout);
+  const WaitUntilNoTransientCallbacks({ Duration? timeout }) : super(timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   WaitUntilNoTransientCallbacks.deserialize(Map<String, String> json)
@@ -76,7 +76,7 @@
 )
 class WaitUntilNoPendingFrame extends Command {
   /// Creates a command that waits until there's no pending frame scheduled.
-  const WaitUntilNoPendingFrame({ Duration timeout }) : super(timeout: timeout);
+  const WaitUntilNoPendingFrame({ Duration? timeout }) : super(timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   WaitUntilNoPendingFrame.deserialize(Map<String, String> json)
@@ -108,7 +108,7 @@
 )
 class WaitUntilFirstFrameRasterized extends Command {
   /// Creates this command.
-  const WaitUntilFirstFrameRasterized({ Duration timeout }) : super(timeout: timeout);
+  const WaitUntilFirstFrameRasterized({ Duration? timeout }) : super(timeout: timeout);
 
   /// Deserializes this command from the value generated by [serialize].
   WaitUntilFirstFrameRasterized.deserialize(Map<String, String> json)
@@ -124,7 +124,7 @@
   const SerializationException([this.message]);
 
   /// The error message, possibly null.
-  final String message;
+  final String? message;
 
   @override
   String toString() => 'SerializationException($message)';
@@ -271,7 +271,7 @@
     }
 
     final List<SerializableWaitCondition> conditions = <SerializableWaitCondition>[];
-    for (final Map<String, dynamic> condition in (json.decode(jsonMap['conditions']) as List<dynamic>).cast<Map<String, dynamic>>()) {
+    for (final Map<String, dynamic> condition in (json.decode(jsonMap['conditions']!) as List<dynamic>).cast<Map<String, dynamic>>()) {
       conditions.add(_deserialize(condition.cast<String, String>()));
     }
     return CombinedCondition(conditions);
@@ -301,7 +301,7 @@
 /// The [json] argument must not be null.
 SerializableWaitCondition _deserialize(Map<String, String> json) {
   assert(json != null);
-  final String conditionName = json['conditionName'];
+  final String conditionName = json['conditionName']!;
   switch (conditionName) {
     case 'NoTransientCallbacksCondition':
       return NoTransientCallbacks.deserialize(json);
diff --git a/packages/flutter_driver/lib/src/driver/common.dart b/packages/flutter_driver/lib/src/driver/common.dart
index 7ad0f4b..61b38c7 100644
--- a/packages/flutter_driver/lib/src/driver/common.dart
+++ b/packages/flutter_driver/lib/src/driver/common.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.
 
+// @dart = 2.8
+
 import 'dart:io' show Platform;
 
 import 'package:file/file.dart';
diff --git a/packages/flutter_driver/lib/src/driver/driver.dart b/packages/flutter_driver/lib/src/driver/driver.dart
index 8b9aded..8b379ec 100644
--- a/packages/flutter_driver/lib/src/driver/driver.dart
+++ b/packages/flutter_driver/lib/src/driver/driver.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.
 
+// @dart = 2.8
+
 import 'dart:io';
 
 import 'package:json_rpc_2/json_rpc_2.dart' as rpc;
diff --git a/packages/flutter_driver/lib/src/driver/percentile_utils.dart b/packages/flutter_driver/lib/src/driver/percentile_utils.dart
index bec7bd7..7b2b225 100644
--- a/packages/flutter_driver/lib/src/driver/percentile_utils.dart
+++ b/packages/flutter_driver/lib/src/driver/percentile_utils.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.
 
+// @dart = 2.8
+
 /// Returns the [p]-th percentile element from the [doubles].
 /// `List<doubles>` will be sorted.
 double findPercentile(List<double> doubles, double p) {
diff --git a/packages/flutter_driver/lib/src/driver/profiling_summarizer.dart b/packages/flutter_driver/lib/src/driver/profiling_summarizer.dart
index 8e6833d..32254ab 100644
--- a/packages/flutter_driver/lib/src/driver/profiling_summarizer.dart
+++ b/packages/flutter_driver/lib/src/driver/profiling_summarizer.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.
 
+// @dart = 2.8
+
 import 'percentile_utils.dart';
 import 'timeline.dart';
 
diff --git a/packages/flutter_driver/lib/src/driver/scene_display_lag_summarizer.dart b/packages/flutter_driver/lib/src/driver/scene_display_lag_summarizer.dart
index 5819bea..200ce05 100644
--- a/packages/flutter_driver/lib/src/driver/scene_display_lag_summarizer.dart
+++ b/packages/flutter_driver/lib/src/driver/scene_display_lag_summarizer.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.
 
+// @dart = 2.8
+
 import 'percentile_utils.dart';
 import 'timeline.dart';
 
diff --git a/packages/flutter_driver/lib/src/driver/timeline.dart b/packages/flutter_driver/lib/src/driver/timeline.dart
index 7ab9600..595879c 100644
--- a/packages/flutter_driver/lib/src/driver/timeline.dart
+++ b/packages/flutter_driver/lib/src/driver/timeline.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.
 
+// @dart = 2.8
+
 /// Timeline data recorded by the Flutter runtime.
 class Timeline {
   /// Creates a timeline given JSON-encoded timeline data.
diff --git a/packages/flutter_driver/lib/src/driver/timeline_summary.dart b/packages/flutter_driver/lib/src/driver/timeline_summary.dart
index 1fc8dbb..6146612 100644
--- a/packages/flutter_driver/lib/src/driver/timeline_summary.dart
+++ b/packages/flutter_driver/lib/src/driver/timeline_summary.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.
 
+// @dart = 2.8
+
 import 'dart:convert' show json, JsonEncoder;
 import 'dart:math' as math;
 
diff --git a/packages/flutter_driver/lib/src/driver/vmservice_driver.dart b/packages/flutter_driver/lib/src/driver/vmservice_driver.dart
index cd3e411..44d9fdb 100644
--- a/packages/flutter_driver/lib/src/driver/vmservice_driver.dart
+++ b/packages/flutter_driver/lib/src/driver/vmservice_driver.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.
 
+// @dart = 2.8
+
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
@@ -12,13 +14,12 @@
 import 'package:meta/meta.dart';
 import 'package:path/path.dart' as p;
 import 'package:vm_service_client/vm_service_client.dart';
-import 'package:webdriver/async_io.dart' as async_io;
 import 'package:web_socket_channel/io.dart';
+import 'package:webdriver/async_io.dart' as async_io;
 
 import '../../flutter_driver.dart';
 import '../common/error.dart';
 import '../common/frame_sync.dart';
-import '../common/fuchsia_compat.dart';
 import '../common/health.dart';
 import '../common/message.dart';
 import 'common.dart';
diff --git a/packages/flutter_driver/lib/src/driver/web_driver.dart b/packages/flutter_driver/lib/src/driver/web_driver.dart
index 018a03e..961cb17 100644
--- a/packages/flutter_driver/lib/src/driver/web_driver.dart
+++ b/packages/flutter_driver/lib/src/driver/web_driver.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.
 
+// @dart = 2.8
+
 import 'dart:convert';
 import 'dart:io';
 
diff --git a/packages/flutter_driver/lib/src/extension/extension.dart b/packages/flutter_driver/lib/src/extension/extension.dart
index 84b7573..9614d52 100644
--- a/packages/flutter_driver/lib/src/extension/extension.dart
+++ b/packages/flutter_driver/lib/src/extension/extension.dart
@@ -40,19 +40,19 @@
 ///
 /// Messages are described in string form and should return a [Future] which
 /// eventually completes to a string response.
-typedef DataHandler = Future<String> Function(String message);
+typedef DataHandler = Future<String> Function(String? message);
 
 class _DriverBinding extends BindingBase with SchedulerBinding, ServicesBinding, GestureBinding, PaintingBinding, SemanticsBinding, RendererBinding, WidgetsBinding {
   _DriverBinding(this._handler, this._silenceErrors, this.finders);
 
-  final DataHandler _handler;
+  final DataHandler? _handler;
   final bool _silenceErrors;
-  final List<FinderExtension> finders;
+  final List<FinderExtension>? finders;
 
   @override
   void initServiceExtensions() {
     super.initServiceExtensions();
-    final FlutterDriverExtension extension = FlutterDriverExtension(_handler, _silenceErrors, finders: finders);
+    final FlutterDriverExtension extension = FlutterDriverExtension(_handler, _silenceErrors, finders: finders ?? const <FinderExtension>[]);
     registerServiceExtension(
       name: _extensionMethodName,
       callback: extension.call,
@@ -137,14 +137,14 @@
 /// }
 /// ```
 ///
-void enableFlutterDriverExtension({ DataHandler handler, bool silenceErrors = false, List<FinderExtension> finders}) {
+void enableFlutterDriverExtension({ DataHandler? handler, bool silenceErrors = false, List<FinderExtension>? finders}) {
   assert(WidgetsBinding.instance == null);
   _DriverBinding(handler, silenceErrors, finders ?? <FinderExtension>[]);
   assert(WidgetsBinding.instance is _DriverBinding);
 }
 
 /// Signature for functions that handle a command and return a result.
-typedef CommandHandlerCallback = Future<Result> Function(Command c);
+typedef CommandHandlerCallback = Future<Result?> Function(Command c);
 
 /// Signature for functions that deserialize a JSON map to a command object.
 typedef CommandDeserializerCallback = Command Function(Map<String, String> params);
@@ -233,14 +233,14 @@
 
   final TestTextInput _testTextInput = TestTextInput();
 
-  final DataHandler _requestDataHandler;
+  final DataHandler? _requestDataHandler;
   final bool _silenceErrors;
 
   void _log(String message) {
     driverLog('FlutterDriverExtension', message);
   }
 
-  final WidgetController _prober = LiveWidgetController(WidgetsBinding.instance);
+  final WidgetController _prober = LiveWidgetController(WidgetsBinding.instance!);
   final Map<String, CommandHandlerCallback> _commandHandlers = <String, CommandHandlerCallback>{};
   final Map<String, CommandDeserializerCallback> _commandDeserializers = <String, CommandDeserializerCallback>{};
   final Map<String, FinderExtension> _finderExtensions = <String, FinderExtension>{};
@@ -261,20 +261,20 @@
   /// the result into a subclass of [Result], but that's not strictly required.
   @visibleForTesting
   Future<Map<String, dynamic>> call(Map<String, String> params) async {
-    final String commandKind = params['command'];
+    final String commandKind = params['command']!;
     try {
-      final CommandHandlerCallback commandHandler = _commandHandlers[commandKind];
+      final CommandHandlerCallback commandHandler = _commandHandlers[commandKind]!;
       final CommandDeserializerCallback commandDeserializer =
-          _commandDeserializers[commandKind];
+          _commandDeserializers[commandKind]!;
       if (commandHandler == null || commandDeserializer == null)
         throw 'Extension $_extensionMethod does not support command $commandKind';
       final Command command = commandDeserializer(params);
-      assert(WidgetsBinding.instance.isRootWidgetAttached || !command.requiresRootWidgetAttached,
+      assert(WidgetsBinding.instance!.isRootWidgetAttached || !command.requiresRootWidgetAttached,
           'No root widget is attached; have you remembered to call runApp()?');
-      Future<Result> responseFuture = commandHandler(command);
+      Future<Result?> responseFuture = commandHandler(command);
       if (command.timeout != null)
-        responseFuture = responseFuture.timeout(command.timeout);
-      final Result response = await responseFuture;
+        responseFuture = responseFuture.timeout(command.timeout ?? Duration.zero);
+      final Result? response = await responseFuture;
       return _makeResponse(response?.toJson());
     } on TimeoutException catch (error, stackTrace) {
       final String message = 'Timeout while executing $commandKind: $error\n$stackTrace';
@@ -298,11 +298,11 @@
   Future<Health> _getHealth(Command command) async => const Health(HealthStatus.ok);
 
   Future<LayerTree> _getLayerTree(Command command) async {
-    return LayerTree(RendererBinding.instance?.renderView?.debugLayer?.toStringDeep());
+    return LayerTree(RendererBinding.instance?.renderView.debugLayer?.toStringDeep());
   }
 
   Future<RenderTree> _getRenderTree(Command command) async {
-    return RenderTree(RendererBinding.instance?.renderView?.toStringDeep());
+    return RenderTree(RendererBinding.instance?.renderView.toStringDeep());
   }
 
   // This can be used to wait for the first frame being rasterized during app launch.
@@ -310,16 +310,16 @@
     'This method has been deprecated in favor of _waitForCondition. '
     'This feature was deprecated after v1.9.3.'
   )
-  Future<Result> _waitUntilFirstFrameRasterized(Command command) async {
-    await WidgetsBinding.instance.waitUntilFirstFrameRasterized;
+  Future<Result?> _waitUntilFirstFrameRasterized(Command command) async {
+    await WidgetsBinding.instance!.waitUntilFirstFrameRasterized;
     return null;
   }
 
   // Waits until at the end of a frame the provided [condition] is [true].
-  Future<void> _waitUntilFrame(bool condition(), [ Completer<void> completer ]) {
+  Future<void> _waitUntilFrame(bool condition(), [ Completer<void>? completer ]) {
     completer ??= Completer<void>();
     if (!condition()) {
-      SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
+      SchedulerBinding.instance!.addPostFrameCallback((Duration timestamp) {
         _waitUntilFrame(condition, completer);
       });
     } else {
@@ -331,12 +331,12 @@
   /// Runs `finder` repeatedly until it finds one or more [Element]s.
   Future<Finder> _waitForElement(Finder finder) async {
     if (_frameSync)
-      await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0);
+      await _waitUntilFrame(() => SchedulerBinding.instance!.transientCallbackCount == 0);
 
     await _waitUntilFrame(() => finder.evaluate().isNotEmpty);
 
     if (_frameSync)
-      await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0);
+      await _waitUntilFrame(() => SchedulerBinding.instance!.transientCallbackCount == 0);
 
     return finder;
   }
@@ -344,12 +344,12 @@
   /// Runs `finder` repeatedly until it finds zero [Element]s.
   Future<Finder> _waitForAbsentElement(Finder finder) async {
     if (_frameSync)
-      await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0);
+      await _waitUntilFrame(() => SchedulerBinding.instance!.transientCallbackCount == 0);
 
     await _waitUntilFrame(() => finder.evaluate().isEmpty);
 
     if (_frameSync)
-      await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0);
+      await _waitUntilFrame(() => SchedulerBinding.instance!.transientCallbackCount == 0);
 
     return finder;
   }
@@ -372,7 +372,7 @@
       if (element is! RenderObjectElement) {
         return false;
       }
-      final String semanticsLabel = element.renderObject?.debugSemantics?.label;
+      final String? semanticsLabel = element.renderObject.debugSemantics?.label;
       if (semanticsLabel == null) {
         return false;
       }
@@ -449,7 +449,7 @@
         return _createDescendantFinder(finder as Descendant);
       default:
         if (_finderExtensions.containsKey(finder.finderType)) {
-          return _finderExtensions[finder.finderType].createFinder(finder);
+          return _finderExtensions[finder.finderType]!.createFinder(finder);
         } else {
           throw 'Unsupported finder type: ${finder.finderType}';
         }
@@ -477,7 +477,7 @@
     return const WaitForAbsentResult();
   }
 
-  Future<Result> _waitForCondition(Command command) async {
+  Future<Result?> _waitForCondition(Command command) async {
     assert(command != null);
     final WaitForCondition waitForConditionCommand = command as WaitForCondition;
     final WaitCondition condition = deserializeCondition(waitForConditionCommand.condition);
@@ -489,9 +489,9 @@
     'This method has been deprecated in favor of _waitForCondition. '
     'This feature was deprecated after v1.9.3.'
   )
-  Future<Result> _waitUntilNoTransientCallbacks(Command command) async {
-    if (SchedulerBinding.instance.transientCallbackCount != 0)
-      await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0);
+  Future<Result?> _waitUntilNoTransientCallbacks(Command command) async {
+    if (SchedulerBinding.instance!.transientCallbackCount != 0)
+      await _waitUntilFrame(() => SchedulerBinding.instance!.transientCallbackCount == 0);
     return null;
   }
 
@@ -518,10 +518,10 @@
     'This method has been deprecated in favor of _waitForCondition. '
     'This feature was deprecated after v1.9.3.'
   )
-  Future<Result> _waitUntilNoPendingFrame(Command command) async {
+  Future<Result?> _waitUntilNoPendingFrame(Command command) async {
     await _waitUntilFrame(() {
-      return SchedulerBinding.instance.transientCallbackCount == 0
-          && !SchedulerBinding.instance.hasScheduledFrame;
+      return SchedulerBinding.instance!.transientCallbackCount == 0
+          && !SchedulerBinding.instance!.hasScheduledFrame;
     });
     return null;
   }
@@ -534,11 +534,11 @@
       throw StateError('Found more than one element with the same ID: $elements');
     }
     final Element element = elements.single;
-    RenderObject renderObject = element.renderObject;
-    SemanticsNode node;
+    RenderObject? renderObject = element.renderObject;
+    SemanticsNode? node;
     while (renderObject != null && node == null) {
       node = renderObject.debugSemantics;
-      renderObject = renderObject.parent as RenderObject;
+      renderObject = renderObject.parent as RenderObject?;
     }
     if (node == null)
       throw StateError('No semantics data found');
@@ -549,7 +549,7 @@
     final GetOffset getOffsetCommand = command as GetOffset;
     final Finder finder = await _waitForElement(_createFinder(getOffsetCommand.finder));
     final Element element = finder.evaluate().single;
-    final RenderBox box = element.renderObject as RenderBox;
+    final RenderBox box = (element.renderObject as RenderBox?)!;
     Offset localPoint;
     switch (getOffsetCommand.offsetType) {
       case OffsetType.topLeft:
@@ -579,7 +579,7 @@
     DiagnosticsNode diagnosticsNode;
     switch (diagnosticsCommand.diagnosticsType) {
       case DiagnosticsType.renderObject:
-        diagnosticsNode = element.renderObject.toDiagnosticsNode();
+        diagnosticsNode = element.renderObject!.toDiagnosticsNode();
         break;
       case DiagnosticsType.widget:
         diagnosticsNode = element.toDiagnosticsNode();
@@ -615,7 +615,11 @@
   Future<ScrollResult> _scrollIntoView(Command command) async {
     final ScrollIntoView scrollIntoViewCommand = command as ScrollIntoView;
     final Finder target = await _waitForElement(_createFinder(scrollIntoViewCommand.finder));
-    await Scrollable.ensureVisible(target.evaluate().single, duration: const Duration(milliseconds: 100), alignment: scrollIntoViewCommand.alignment ?? 0.0);
+    await Scrollable.ensureVisible(
+      target.evaluate().single,
+      duration: const Duration(milliseconds: 100),
+      alignment: scrollIntoViewCommand.alignment,
+    );
     return const ScrollResult();
   }
 
@@ -624,7 +628,7 @@
     final Finder target = await _waitForElement(_createFinder(getTextCommand.finder));
 
     final Widget widget = target.evaluate().single.widget;
-    String text;
+    String? text;
 
     if (widget.runtimeType == Text) {
       text = (widget as Text).data;
@@ -634,9 +638,9 @@
         text = (richText.text as TextSpan).text;
       }
     } else if (widget.runtimeType == TextField) {
-      text = (widget as TextField).controller.text;
+      text = (widget as TextField).controller?.text;
     } else if (widget.runtimeType == TextFormField) {
-      text = (widget as TextFormField).controller.text;
+      text = (widget as TextFormField).controller?.text;
     } else if (widget.runtimeType == EditableText) {
       text = (widget as EditableText).controller.text;
     }
@@ -670,7 +674,9 @@
 
   Future<RequestDataResult> _requestData(Command command) async {
     final RequestData requestDataCommand = command as RequestData;
-    return RequestDataResult(_requestDataHandler == null ? 'No requestData Extension registered' : await _requestDataHandler(requestDataCommand.message));
+    return RequestDataResult(_requestDataHandler == null
+      ? 'No requestData Extension registered'
+      : await _requestDataHandler!(requestDataCommand.message));
   }
 
   Future<SetFrameSyncResult> _setFrameSync(Command command) async {
@@ -679,24 +685,24 @@
     return const SetFrameSyncResult();
   }
 
-  SemanticsHandle _semantics;
-  bool get _semanticsIsEnabled => RendererBinding.instance.pipelineOwner.semanticsOwner != null;
+  SemanticsHandle? _semantics;
+  bool get _semanticsIsEnabled => RendererBinding.instance!.pipelineOwner.semanticsOwner != null;
 
   Future<SetSemanticsResult> _setSemantics(Command command) async {
     final SetSemantics setSemanticsCommand = command as SetSemantics;
     final bool semanticsWasEnabled = _semanticsIsEnabled;
     if (setSemanticsCommand.enabled && _semantics == null) {
-      _semantics = RendererBinding.instance.pipelineOwner.ensureSemantics();
+      _semantics = RendererBinding.instance!.pipelineOwner.ensureSemantics();
       if (!semanticsWasEnabled) {
         // wait for the first frame where semantics is enabled.
         final Completer<void> completer = Completer<void>();
-        SchedulerBinding.instance.addPostFrameCallback((Duration d) {
+        SchedulerBinding.instance!.addPostFrameCallback((Duration d) {
           completer.complete();
         });
         await completer.future;
       }
     } else if (!setSemanticsCommand.enabled && _semantics != null) {
-      _semantics.dispose();
+      _semantics!.dispose();
       _semantics = null;
     }
     return SetSemanticsResult(semanticsWasEnabled != _semanticsIsEnabled);
diff --git a/packages/flutter_driver/lib/src/extension/wait_conditions.dart b/packages/flutter_driver/lib/src/extension/wait_conditions.dart
index 8b1e131..c5c6e69 100644
--- a/packages/flutter_driver/lib/src/extension/wait_conditions.dart
+++ b/packages/flutter_driver/lib/src/extension/wait_conditions.dart
@@ -49,12 +49,12 @@
   }
 
   @override
-  bool get condition => SchedulerBinding.instance.transientCallbackCount == 0;
+  bool get condition => SchedulerBinding.instance!.transientCallbackCount == 0;
 
   @override
   Future<void> wait() async {
     while (!condition) {
-      await SchedulerBinding.instance.endOfFrame;
+      await SchedulerBinding.instance!.endOfFrame;
     }
     assert(condition);
   }
@@ -77,12 +77,12 @@
   }
 
   @override
-  bool get condition => !SchedulerBinding.instance.hasScheduledFrame;
+  bool get condition => !SchedulerBinding.instance!.hasScheduledFrame;
 
   @override
   Future<void> wait() async {
     while (!condition) {
-      await SchedulerBinding.instance.endOfFrame;
+      await SchedulerBinding.instance!.endOfFrame;
     }
     assert(condition);
   }
@@ -105,11 +105,11 @@
   }
 
   @override
-  bool get condition => WidgetsBinding.instance.firstFrameRasterized;
+  bool get condition => WidgetsBinding.instance!.firstFrameRasterized;
 
   @override
   Future<void> wait() async {
-    await WidgetsBinding.instance.waitUntilFirstFrameRasterized;
+    await WidgetsBinding.instance!.waitUntilFirstFrameRasterized;
     assert(condition);
   }
 }
@@ -132,13 +132,13 @@
 
   @override
   bool get condition {
-    final TestDefaultBinaryMessenger binaryMessenger = ServicesBinding.instance.defaultBinaryMessenger as TestDefaultBinaryMessenger;
+    final TestDefaultBinaryMessenger binaryMessenger = ServicesBinding.instance!.defaultBinaryMessenger as TestDefaultBinaryMessenger;
     return binaryMessenger.pendingMessageCount == 0;
   }
 
   @override
   Future<void> wait() async {
-    final TestDefaultBinaryMessenger binaryMessenger = ServicesBinding.instance.defaultBinaryMessenger as TestDefaultBinaryMessenger;
+    final TestDefaultBinaryMessenger binaryMessenger = ServicesBinding.instance!.defaultBinaryMessenger as TestDefaultBinaryMessenger;
     while (!condition) {
       await binaryMessenger.platformMessagesFinished;
     }
diff --git a/packages/flutter_driver/pubspec.yaml b/packages/flutter_driver/pubspec.yaml
index 6657abc..1b09165 100644
--- a/packages/flutter_driver/pubspec.yaml
+++ b/packages/flutter_driver/pubspec.yaml
@@ -5,7 +5,7 @@
 
 environment:
   # The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite.
-  sdk: ">=2.2.2 <3.0.0"
+  sdk: ">=2.10.0-0.0.dev <3.0.0"
 
 dependencies:
   file: 6.0.0-nullsafety.2
diff --git a/packages/flutter_driver/test/src/real_tests/extension_test.dart b/packages/flutter_driver/test/src/real_tests/extension_test.dart
index b00abea..968cb93 100644
--- a/packages/flutter_driver/test/src/real_tests/extension_test.dart
+++ b/packages/flutter_driver/test/src/real_tests/extension_test.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.
 
+// @dart = 2.8
+
 import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/rendering.dart';
diff --git a/packages/flutter_driver/test/src/real_tests/find_test.dart b/packages/flutter_driver/test/src/real_tests/find_test.dart
index f50a32b..df41576 100644
--- a/packages/flutter_driver/test/src/real_tests/find_test.dart
+++ b/packages/flutter_driver/test/src/real_tests/find_test.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.
 
+// @dart = 2.8
+
 import 'package:flutter_driver/flutter_driver.dart';
 import 'package:flutter_driver/src/common/find.dart';
 import 'package:mockito/mockito.dart';
diff --git a/packages/flutter_driver/test/src/real_tests/io_extension_test.dart b/packages/flutter_driver/test/src/real_tests/io_extension_test.dart
index 3644bcf..5d5743b 100644
--- a/packages/flutter_driver/test/src/real_tests/io_extension_test.dart
+++ b/packages/flutter_driver/test/src/real_tests/io_extension_test.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.
 
+// @dart = 2.8
+
 import 'package:flutter_driver/src/extension/_extension_io.dart';
 
 import '../../common.dart';
diff --git a/packages/flutter_driver/test/src/real_tests/request_data_test.dart b/packages/flutter_driver/test/src/real_tests/request_data_test.dart
new file mode 100644
index 0000000..7bb289b
--- /dev/null
+++ b/packages/flutter_driver/test/src/real_tests/request_data_test.dart
@@ -0,0 +1,17 @@
+// Copyright 2014 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.
+
+// @dart = 2.8
+
+import 'package:flutter_driver/flutter_driver.dart';
+
+import '../../common.dart';
+
+void main() {
+  test('RequestData does not insert "null" string when no message is provided', () {
+    const RequestData data = RequestData(null);
+
+    expect(data.serialize(), <String, String>{'command': 'request_data'});
+  });
+}
diff --git a/packages/flutter_driver/test/src/real_tests/timeline_summary_test.dart b/packages/flutter_driver/test/src/real_tests/timeline_summary_test.dart
index 27f0eb3..be02433 100644
--- a/packages/flutter_driver/test/src/real_tests/timeline_summary_test.dart
+++ b/packages/flutter_driver/test/src/real_tests/timeline_summary_test.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.
 
+// @dart = 2.8
+
 import 'dart:convert' show json;
 
 import 'package:file/file.dart';
diff --git a/packages/flutter_driver/test/src/real_tests/timeline_test.dart b/packages/flutter_driver/test/src/real_tests/timeline_test.dart
index 9e39b93..40f7cd9 100644
--- a/packages/flutter_driver/test/src/real_tests/timeline_test.dart
+++ b/packages/flutter_driver/test/src/real_tests/timeline_test.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.
 
+// @dart = 2.8
+
 import 'package:flutter_driver/src/driver/timeline.dart';
 
 import '../../common.dart';
diff --git a/packages/flutter_driver/test/src/real_tests/wait_test.dart b/packages/flutter_driver/test/src/real_tests/wait_test.dart
index adf99a4..5526b86 100644
--- a/packages/flutter_driver/test/src/real_tests/wait_test.dart
+++ b/packages/flutter_driver/test/src/real_tests/wait_test.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.
 
+// @dart = 2.8
+
 import 'package:flutter_driver/src/common/wait.dart';
 
 import '../../common.dart';
diff --git a/packages/flutter_test/analysis_options.yaml b/packages/flutter_test/analysis_options.yaml
index 4907497..9adc519 100644
--- a/packages/flutter_test/analysis_options.yaml
+++ b/packages/flutter_test/analysis_options.yaml
@@ -9,4 +9,4 @@
     always_require_non_null_named_parameters: false # not needed with nnbd
     unrelated_type_equality_checks: false # https://github.com/dart-lang/linter/issues/2196
     void_checks: false # https://github.com/dart-lang/linter/issues/2185
-    unnecessary_null_comparison: false # https://github.com/dart-lang/language/issues/1018
+    unnecessary_null_comparison: false # Turned off until null-safe rollout is complete.