[extension_google_sign_in_as_googleapis_auth] Move from flutter/plugins. (#301)
diff --git a/.cirrus.yml b/.cirrus.yml
index 91a71f1..d88484c 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -1,5 +1,6 @@
+use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
+
 task:
-  use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true' && $CIRRUS_PR == ''
   container:
     dockerfile: .ci/Dockerfile
     cpu: 4
@@ -7,8 +8,6 @@
   upgrade_script:
     - flutter channel master
     - flutter upgrade
-    # TODO(goderbauer): Remove next two lines when https://github.com/flutter/flutter/issues/74772 is resolved.
-    - rm -rf /home/cirrus/sdks/flutter/bin/cache
     - flutter doctor
     - git fetch origin master
   activate_script: pub global activate flutter_plugin_tools
@@ -46,41 +45,34 @@
         - dart testing/web_benchmarks_test.dart
 
 task:
-  use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
   name: build-ipas
   osx_instance:
-    image: high-sierra-xcode-9.4.1
+    image: big-sur-xcode-12.4
   env:
     PATH: $PATH:/usr/local/bin
     matrix:
       BUILD_SHARDING: "--shardIndex 0 --shardCount 2"
       BUILD_SHARDING: "--shardIndex 1 --shardCount 2"
   setup_script:
-    - pod repo update
-    - git clone https://github.com/flutter/flutter.git
-    - git fetch origin master
-    - export PATH=`pwd`/flutter/bin:`pwd`/flutter/bin/cache/dart-sdk/bin:$PATH
+    - flutter channel master
+    - flutter upgrade
     - flutter doctor
+    - git fetch origin master
     - pub global activate flutter_plugin_tools
   build_script:
-    - export PATH=`pwd`/flutter/bin:`pwd`/flutter/bin/cache/dart-sdk/bin:$PATH
     - ./script/incremental_build.sh build-examples --ipa
 
 task:
-  use_compute_credits: $CIRRUS_USER_COLLABORATOR == 'true'
   name: local_tests
   osx_instance:
-    image: catalina-flutter
+    image: big-sur-xcode-12.4
   env:
     PATH: $PATH:/usr/local/bin
     matrix:
       CHANNEL: "master"
       CHANNEL: "stable"
   setup_script:
-    - pod repo update
-    - git clone https://github.com/flutter/flutter.git
     - git fetch origin master
-    - export PATH=`pwd`/flutter/bin:`pwd`/flutter/bin/cache/dart-sdk/bin:$PATH
     - pub global activate flutter_plugin_tools
     - brew install clang-format
   upgrade_script:
diff --git a/README.md b/README.md
index 36b2f0c..8430ac8 100644
--- a/README.md
+++ b/README.md
@@ -38,4 +38,5 @@
 | [multicast_dns](./packages/multicast_dns/) | [![pub package](https://img.shields.io/pub/v/multicast_dns.svg)](https://pub.dev/packages/multicast_dns) |
 | [palette_generator](./packages/palette_generator/) | [![pub package](https://img.shields.io/pub/v/palette_generator.svg)](https://pub.dartlang.org/packages/palette_generator) |
 | [pigeon](./packages/pigeon/) | [![pub package](https://img.shields.io/pub/v/pigeon.svg)](https://pub.dev/packages/pigeon) |
+| [pointer_interceptor](./packages/pointer_interceptor/) | [![pub package](https://img.shields.io/pub/v/pointer_interceptor.svg)](https://pub.dev/packages/pointer_interceptor) |
 | [xdg_directories](./packages/xdg_directories/) | [![pub package](https://img.shields.io/pub/v/xdg_directories.svg)](https://pub.dev/packages/xdg_directories) |
diff --git a/packages/animations/CHANGELOG.md b/packages/animations/CHANGELOG.md
index 70ec9b4..0ab0f79 100644
--- a/packages/animations/CHANGELOG.md
+++ b/packages/animations/CHANGELOG.md
@@ -1,20 +1,17 @@
-# Changelog
-
-All notable changes to this project will be documented in this file.
-
-## [2.0.0-nullsafety.0] - November 16, 2020
+## 2.0.0
 
 * Migrates to null safety.
+* Add `routeSettings` and `filter` option to `showModal`.
 
-## [1.1.2] - July 28, 2020
+## 1.1.2
 
 * Fixes for upcoming changes to the flutter framework.
 
-## [1.1.1] - June 19, 2020
+## 1.1.1
 
 * Hide implementation of `DualTransitionBuilder` as the widget has been implemented in the Flutter framework.
 
-## [1.1.0] - June 2, 2020
+## 1.1.0
 
 * Introduce usage of `DualTransitionBuilder` for all transition widgets, preventing ongoing animations at the start of the transition animation from resetting at the end of the transition animations.
 * Fix `FadeScaleTransition` example's `FloatingActionButton` being accessible
@@ -28,12 +25,12 @@
 * Fixes a bug with OpenContainer where a crash occurs when the container is dismissed after the container widget itself is removed.
 
 
-## [1.0.0+5] - February 21, 2020
+## 1.0.0+5
 
 * Fix override analyzer ignore placement.
 
 
-## [1.0.0+4] - February 21, 2020
+## 1.0.0+4
 
 * Fix a typo in the changelog dates
 * Revert use of modern Material text style nomenclature in the example app
@@ -43,21 +40,21 @@
   https://github.com/flutter/flutter/pull/48274.
 
 
-## [1.0.0+3] - February 18, 2020
+## 1.0.0+3
 
 * Update README.md to better describe Material motion
 
 
-## [1.0.0+2] - February 18, 2020
+## 1.0.0+2
 
 * Fixes to pubspec.yaml
 
 
-## [1.0.0+1] - February 18, 2020
+## 1.0.0+1
 
 * Fixes to pubspec.yaml
 
 
-## [1.0.0] - February 18, 2020
+## 1.0.0
 
 * Initial release
diff --git a/packages/animations/example/pubspec.yaml b/packages/animations/example/pubspec.yaml
index 68a79d1..ecee1e8 100644
--- a/packages/animations/example/pubspec.yaml
+++ b/packages/animations/example/pubspec.yaml
@@ -6,12 +6,12 @@
 version: 0.0.1
 
 environment:
-  sdk: ">=2.12.0-0 <3.0.0"
+  sdk: ">=2.12.0-259.9.beta <3.0.0"
 
 dependencies:
   animations:
     path: ../../animations
-  cupertino_icons: ^0.1.2
+  cupertino_icons: ^1.0.2
   flutter:
     sdk: flutter
 
diff --git a/packages/animations/lib/src/modal.dart b/packages/animations/lib/src/modal.dart
index 120d51f..65b6f60 100644
--- a/packages/animations/lib/src/modal.dart
+++ b/packages/animations/lib/src/modal.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 'dart:ui' as ui;
+
 import 'package:flutter/material.dart';
 
 import 'fade_scale_transition.dart';
@@ -51,6 +53,8 @@
   ModalConfiguration configuration = const FadeScaleTransitionConfiguration(),
   bool useRootNavigator = true,
   required WidgetBuilder builder,
+  RouteSettings? routeSettings,
+  ui.ImageFilter? filter,
 }) {
   String? barrierLabel = configuration.barrierLabel;
   // Avoid looking up [MaterialLocalizations.of(context).modalBarrierDismissLabel]
@@ -68,6 +72,8 @@
       transitionDuration: configuration.transitionDuration,
       reverseTransitionDuration: configuration.reverseTransitionDuration,
       builder: builder,
+      routeSettings: routeSettings,
+      filter: filter,
     ),
   );
 }
@@ -91,8 +97,11 @@
     required this.reverseTransitionDuration,
     required _ModalTransitionBuilder transitionBuilder,
     required this.builder,
-  })   : assert(!barrierDismissible || barrierLabel != null),
-        _transitionBuilder = transitionBuilder;
+    RouteSettings? routeSettings,
+    ui.ImageFilter? filter,
+  })  : assert(!barrierDismissible || barrierLabel != null),
+        _transitionBuilder = transitionBuilder,
+        super(filter: filter, settings: routeSettings);
 
   @override
   final Color? barrierColor;
diff --git a/packages/animations/pubspec.yaml b/packages/animations/pubspec.yaml
index 8417e19..81150b1 100644
--- a/packages/animations/pubspec.yaml
+++ b/packages/animations/pubspec.yaml
@@ -1,10 +1,10 @@
 name: animations
 description: Fancy pre-built animations that can easily be integrated into any Flutter application.
-version: 2.0.0-nullsafety.0
+version: 2.0.0
 homepage: https://github.com/flutter/packages/tree/master/packages/animations
 
 environment:
-  sdk: '>=2.12.0-0 <3.0.0'
+  sdk: '>=2.12.0-259.9.beta <3.0.0'
 
 dependencies:
   flutter:
@@ -13,4 +13,4 @@
 dev_dependencies:
   flutter_test:
     sdk: flutter
-  vector_math: ">=2.1.0-nullsafety.5 <3.0.0"
+  vector_math: ^2.1.0
diff --git a/packages/animations/test/modal_test.dart b/packages/animations/test/modal_test.dart
index fdaf10c..7d9c463 100644
--- a/packages/animations/test/modal_test.dart
+++ b/packages/animations/test/modal_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.
 
+import 'dart:ui' as ui;
+
 import 'package:animations/src/modal.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
@@ -456,8 +458,90 @@
       expect(find.byKey(topKey), findsNothing);
     },
   );
+
+  testWidgets(
+    'showModal builds a new route with specified route settings',
+    (WidgetTester tester) async {
+      const RouteSettings routeSettings = RouteSettings(
+        name: 'route-name',
+        arguments: 'arguments',
+      );
+
+      final Widget button = Builder(builder: (BuildContext context) {
+        return Center(
+          child: ElevatedButton(
+            onPressed: () {
+              showModal<void>(
+                context: context,
+                configuration: _TestModalConfiguration(),
+                routeSettings: routeSettings,
+                builder: (BuildContext context) {
+                  return const _FlutterLogoModal();
+                },
+              );
+            },
+            child: const Icon(Icons.add),
+          ),
+        );
+      });
+
+      await tester.pumpWidget(_boilerplate(button));
+      await tester.tap(find.byType(ElevatedButton));
+      await tester.pumpAndSettle();
+
+      // New route containing _FlutterLogoModal is present.
+      expect(find.byType(_FlutterLogoModal), findsOneWidget);
+
+      // Expect the last route pushed to the navigator to contain RouteSettings
+      // equal to the RouteSettings passed to showModal
+      final ModalRoute<dynamic> modalRoute = ModalRoute.of(
+        tester.element(find.byType(_FlutterLogoModal)),
+      )!;
+      expect(modalRoute.settings, routeSettings);
+    },
+  );
+
+  testWidgets(
+    'showModal builds a new route with specified image filter',
+    (WidgetTester tester) async {
+      final ui.ImageFilter filter = ui.ImageFilter.blur(sigmaX: 1, sigmaY: 1);
+
+      final Widget button = Builder(builder: (BuildContext context) {
+        return Center(
+          child: ElevatedButton(
+            onPressed: () {
+              showModal<void>(
+                context: context,
+                configuration: _TestModalConfiguration(),
+                filter: filter,
+                builder: (BuildContext context) {
+                  return const _FlutterLogoModal();
+                },
+              );
+            },
+            child: const Icon(Icons.add),
+          ),
+        );
+      });
+
+      await tester.pumpWidget(_boilerplate(button));
+      await tester.tap(find.byType(ElevatedButton));
+      await tester.pumpAndSettle();
+
+      // New route containing _FlutterLogoModal is present.
+      expect(find.byType(_FlutterLogoModal), findsOneWidget);
+      final BackdropFilter backdropFilter = tester.widget<BackdropFilter>(
+        find.byType(BackdropFilter),
+      );
+
+      // Verify new route's backdrop filter has been applied
+      expect(backdropFilter.filter, filter);
+    },
+  );
 }
 
+Widget _boilerplate(Widget child) => MaterialApp(home: Scaffold(body: child));
+
 double _getOpacity(GlobalKey key, WidgetTester tester) {
   final Finder finder = find.ancestor(
     of: find.byKey(key),
diff --git a/packages/animations/test/open_container_test.dart b/packages/animations/test/open_container_test.dart
index afc0eb2..10ae379 100644
--- a/packages/animations/test/open_container_test.dart
+++ b/packages/animations/test/open_container_test.dart
@@ -774,10 +774,7 @@
             return const Text('Closed');
           },
           openBuilder: (BuildContext context, VoidCallback action) {
-            return Switch(
-              value: true,
-              onChanged: (bool v) {},
-            );
+            return const DummyStatefulWidget();
           },
         ),
       ),
@@ -786,12 +783,12 @@
     await tester.tap(find.text('Closed'));
     await tester.pump(const Duration(milliseconds: 200));
 
-    final State stateOpening = tester.state(find.byType(Switch));
+    final State stateOpening = tester.state(find.byType(DummyStatefulWidget));
     expect(stateOpening, isNotNull);
 
     await tester.pumpAndSettle();
     expect(find.text('Closed'), findsNothing);
-    final State stateOpen = tester.state(find.byType(Switch));
+    final State stateOpen = tester.state(find.byType(DummyStatefulWidget));
     expect(stateOpen, isNotNull);
     expect(stateOpen, same(stateOpening));
 
@@ -799,7 +796,7 @@
     navigator.pop();
     await tester.pump(const Duration(milliseconds: 200));
     expect(find.text('Closed'), findsOneWidget);
-    final State stateClosing = tester.state(find.byType(Switch));
+    final State stateClosing = tester.state(find.byType(DummyStatefulWidget));
     expect(stateClosing, isNotNull);
     expect(stateClosing, same(stateOpen));
   });
@@ -811,10 +808,7 @@
         child: OpenContainer(
           closedBuilder: (BuildContext context, VoidCallback action) {
             open = action;
-            return Switch(
-              value: true,
-              onChanged: (bool v) {},
-            );
+            return const DummyStatefulWidget();
           },
           openBuilder: (BuildContext context, VoidCallback action) {
             return const Text('Open');
@@ -823,21 +817,21 @@
       ),
     ));
 
-    final State stateClosed = tester.state(find.byType(Switch));
+    final State stateClosed = tester.state(find.byType(DummyStatefulWidget));
     expect(stateClosed, isNotNull);
 
     open();
     await tester.pump(const Duration(milliseconds: 200));
     expect(find.text('Open'), findsOneWidget);
 
-    final State stateOpening = tester.state(find.byType(Switch));
+    final State stateOpening = tester.state(find.byType(DummyStatefulWidget));
     expect(stateOpening, same(stateClosed));
 
     await tester.pumpAndSettle();
-    expect(find.byType(Switch), findsNothing);
+    expect(find.byType(DummyStatefulWidget), findsNothing);
     expect(find.text('Open'), findsOneWidget);
     final State stateOpen = tester.state(find.byType(
-      Switch,
+      DummyStatefulWidget,
       skipOffstage: false,
     ));
     expect(stateOpen, same(stateOpening));
@@ -846,12 +840,13 @@
     navigator.pop();
     await tester.pump(const Duration(milliseconds: 200));
     expect(find.text('Open'), findsOneWidget);
-    final State stateClosing = tester.state(find.byType(Switch));
+    final State stateClosing = tester.state(find.byType(DummyStatefulWidget));
     expect(stateClosing, same(stateOpen));
 
     await tester.pumpAndSettle();
     expect(find.text('Open'), findsNothing);
-    final State stateClosedAgain = tester.state(find.byType(Switch));
+    final State stateClosedAgain =
+        tester.state(find.byType(DummyStatefulWidget));
     expect(stateClosedAgain, same(stateClosing));
   });
 
@@ -1966,3 +1961,15 @@
           );
   }
 }
+
+class DummyStatefulWidget extends StatefulWidget {
+  const DummyStatefulWidget({Key? key}) : super(key: key);
+
+  @override
+  State<StatefulWidget> createState() => DummyState();
+}
+
+class DummyState extends State<DummyStatefulWidget> {
+  @override
+  Widget build(BuildContext context) => const SizedBox.expand();
+}
diff --git a/packages/multicast_dns/CHANGELOG.md b/packages/multicast_dns/CHANGELOG.md
index 267e730..fa64e26 100644
--- a/packages/multicast_dns/CHANGELOG.md
+++ b/packages/multicast_dns/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.3.0
+
+* Migrate package to null safety.
+
 ## 0.2.2
 * Fixes parsing of TXT records. Continues parsing on non-utf8 strings.
 
diff --git a/packages/multicast_dns/lib/multicast_dns.dart b/packages/multicast_dns/lib/multicast_dns.dart
index 3b8fa47..148a4b0 100644
--- a/packages/multicast_dns/lib/multicast_dns.dart
+++ b/packages/multicast_dns/lib/multicast_dns.dart
@@ -48,14 +48,13 @@
 
   bool _starting = false;
   bool _started = false;
-  RawDatagramSocket _incoming;
   final List<RawDatagramSocket> _sockets = <RawDatagramSocket>[];
   final LookupResolver _resolver = LookupResolver();
   final ResourceRecordCache _cache = ResourceRecordCache();
   final RawDatagramSocketFactory _rawDatagramSocketFactory;
 
-  InternetAddress _mDnsAddress;
-  int _mDnsPort;
+  InternetAddress? _mDnsAddress;
+  int? _mDnsPort;
 
   /// Find all network interfaces with an the [InternetAddressType] specified.
   static NetworkInterfacesFactory allInterfacesFactory =
@@ -82,14 +81,14 @@
   /// for the mDNS query. If not provided, defaults to either `224.0.0.251` or
   /// or `FF02::FB`.
   Future<void> start({
-    InternetAddress listenAddress,
-    NetworkInterfacesFactory interfacesFactory,
+    InternetAddress? listenAddress,
+    NetworkInterfacesFactory? interfacesFactory,
     int mDnsPort = mDnsPort,
-    InternetAddress mDnsAddress,
+    InternetAddress? mDnsAddress,
   }) async {
     listenAddress ??= InternetAddress.anyIPv4;
     interfacesFactory ??= allInterfacesFactory;
-    _mDnsPort = mDnsPort;
+    final int selectedMDnsPort = _mDnsPort = mDnsPort;
     _mDnsAddress = mDnsAddress;
 
     assert(listenAddress.address == InternetAddress.anyIPv4.address ||
@@ -101,32 +100,32 @@
     _starting = true;
 
     // Listen on all addresses.
-    _incoming = await _rawDatagramSocketFactory(
+    final RawDatagramSocket incoming = await _rawDatagramSocketFactory(
       listenAddress.address,
-      _mDnsPort,
+      selectedMDnsPort,
       reuseAddress: true,
       reusePort: true,
       ttl: 255,
     );
 
     // Can't send to IPv6 any address.
-    if (_incoming.address != InternetAddress.anyIPv6) {
-      _sockets.add(_incoming);
+    if (incoming.address != InternetAddress.anyIPv6) {
+      _sockets.add(incoming);
     }
 
-    _mDnsAddress ??= _incoming.address.type == InternetAddressType.IPv4
+    _mDnsAddress ??= incoming.address.type == InternetAddressType.IPv4
         ? mDnsAddressIPv4
         : mDnsAddressIPv6;
 
     final List<NetworkInterface> interfaces =
-        await interfacesFactory(listenAddress.type);
+        (await interfacesFactory(listenAddress.type)).toList();
 
     for (NetworkInterface interface in interfaces) {
       // Create a socket for sending on each adapter.
       final InternetAddress targetAddress = interface.addresses[0];
       final RawDatagramSocket socket = await _rawDatagramSocketFactory(
         targetAddress,
-        _mDnsPort,
+        selectedMDnsPort,
         reuseAddress: true,
         reusePort: true,
         ttl: 255,
@@ -147,9 +146,9 @@
         ));
       }
       // Join multicast on this interface.
-      _incoming.joinMulticast(_mDnsAddress, interface);
+      incoming.joinMulticast(_mDnsAddress!, interface);
     }
-    _incoming.listen(_handleIncoming);
+    incoming.listen((RawSocketEvent event) => _handleIncoming(event, incoming));
     _started = true;
     _starting = false;
   }
@@ -186,7 +185,8 @@
     ResourceRecordQuery query, {
     Duration timeout = const Duration(seconds: 5),
   }) {
-    if (!_started) {
+    final int? selectedMDnsPort = _mDnsPort;
+    if (!_started || selectedMDnsPort == null) {
       throw StateError('mDNS client must be started before calling lookup.');
     }
     // Look for entries in the cache.
@@ -207,18 +207,21 @@
     // Send the request on all interfaces.
     final List<int> packet = query.encode();
     for (RawDatagramSocket socket in _sockets) {
-      socket.send(packet, _mDnsAddress, _mDnsPort);
+      socket.send(packet, _mDnsAddress!, selectedMDnsPort);
     }
     return results;
   }
 
   // Process incoming datagrams.
-  void _handleIncoming(RawSocketEvent event) {
+  void _handleIncoming(RawSocketEvent event, RawDatagramSocket incoming) {
     if (event == RawSocketEvent.read) {
-      final Datagram datagram = _incoming.receive();
+      final Datagram? datagram = incoming.receive();
+      if (datagram == null) {
+        return;
+      }
 
       // Check for published responses.
-      final List<ResourceRecord> response = decodeMDnsResponse(datagram.data);
+      final List<ResourceRecord>? response = decodeMDnsResponse(datagram.data);
       if (response != null) {
         _cache.updateRecords(response);
         _resolver.handleResponse(response);
diff --git a/packages/multicast_dns/lib/src/constants.dart b/packages/multicast_dns/lib/src/constants.dart
index 2a22264..061329d 100644
--- a/packages/multicast_dns/lib/src/constants.dart
+++ b/packages/multicast_dns/lib/src/constants.dart
@@ -14,20 +14,20 @@
 const int mDnsPort = 5353;
 
 /// Enumeration of supported resource record class types.
-class ResourceRecordClass {
+abstract class ResourceRecordClass {
   // This class is intended to be used as a namespace, and should not be
   // extended directly.
-  factory ResourceRecordClass._() => null;
+  ResourceRecordClass._();
 
   /// Internet address class ("IN").
   static const int internet = 1;
 }
 
 /// Enumeration of DNS question types.
-class QuestionType {
+abstract class QuestionType {
   // This class is intended to be used as a namespace, and should not be
   // extended directly.
-  factory QuestionType._() => null;
+  QuestionType._();
 
   /// "QU" Question.
   static const int unicast = 0x8000;
diff --git a/packages/multicast_dns/lib/src/lookup_resolver.dart b/packages/multicast_dns/lib/src/lookup_resolver.dart
index b374e9f..40cc86b 100644
--- a/packages/multicast_dns/lib/src/lookup_resolver.dart
+++ b/packages/multicast_dns/lib/src/lookup_resolver.dart
@@ -25,7 +25,7 @@
   final StreamController<ResourceRecord> controller;
 
   /// The timer for the request.
-  Timer timer;
+  Timer? timer;
 }
 
 /// Class for keeping track of pending lookups and processing incoming
@@ -89,7 +89,7 @@
     while (_pendingRequests.isNotEmpty) {
       final PendingRequest request = _pendingRequests.first;
       request.unlink();
-      request.timer.cancel();
+      request.timer?.cancel();
       request.controller.close();
     }
   }
diff --git a/packages/multicast_dns/lib/src/native_protocol_client.dart b/packages/multicast_dns/lib/src/native_protocol_client.dart
index 553d564..734412b 100644
--- a/packages/multicast_dns/lib/src/native_protocol_client.dart
+++ b/packages/multicast_dns/lib/src/native_protocol_client.dart
@@ -29,7 +29,7 @@
     for (final SplayTreeMap<String, List<ResourceRecord>> map
         in _cache.values) {
       for (final List<ResourceRecord> records in map.values) {
-        count += records?.length;
+        count += records.length;
       }
     }
     return count;
@@ -45,14 +45,15 @@
       // TODO(dnfield): Update this to use set literal syntax when we're able to bump the SDK constraint.
       seenRecordTypes[record.resourceRecordType] ??=
           Set<String>(); // ignore: prefer_collection_literals
-      if (seenRecordTypes[record.resourceRecordType].add(record.name)) {
+      if (seenRecordTypes[record.resourceRecordType]!.add(record.name)) {
         _cache[record.resourceRecordType] ??=
             SplayTreeMap<String, List<ResourceRecord>>();
 
-        _cache[record.resourceRecordType]
-            [record.name] = <ResourceRecord>[record];
+        _cache[record.resourceRecordType]![record.name] = <ResourceRecord>[
+          record
+        ];
       } else {
-        _cache[record.resourceRecordType][record.name].add(record);
+        _cache[record.resourceRecordType]![record.name]!.add(record);
       }
     }
   }
@@ -62,12 +63,12 @@
       String name, int type, List<T> results) {
     assert(ResourceRecordType.debugAssertValid(type));
     final int time = DateTime.now().millisecondsSinceEpoch;
-    final SplayTreeMap<String, List<ResourceRecord>> candidates = _cache[type];
+    final SplayTreeMap<String, List<ResourceRecord>>? candidates = _cache[type];
     if (candidates == null) {
       return;
     }
 
-    final List<ResourceRecord> candidateRecords = candidates[name];
+    final List<ResourceRecord>? candidateRecords = candidates[name];
     if (candidateRecords == null) {
       return;
     }
diff --git a/packages/multicast_dns/lib/src/packet.dart b/packages/multicast_dns/lib/src/packet.dart
index 2dae398..9905689 100644
--- a/packages/multicast_dns/lib/src/packet.dart
+++ b/packages/multicast_dns/lib/src/packet.dart
@@ -23,7 +23,6 @@
 /// Will attempt to append 'local' if the name is something like '_http._tcp',
 /// and '._tcp.local' if name is something like '_http'.
 List<String> processDnsNameParts(String name) {
-  assert(name != null);
   final List<String> parts = name.split('.');
   if (parts.length == 1) {
     return <String>[parts[0], '_tcp', 'local'];
@@ -47,9 +46,7 @@
   int type = ResourceRecordType.addressIPv4,
   bool multicast = true,
 }) {
-  assert(name != null);
   assert(ResourceRecordType.debugAssertValid(type));
-  assert(multicast != null);
 
   final List<String> nameParts = processDnsNameParts(name);
   final List<List<int>> rawNameParts =
@@ -179,7 +176,7 @@
 /// If decoding fails (e.g. due to an invalid packet), `null` is returned.
 ///
 /// See https://tools.ietf.org/html/rfc1035 for format.
-ResourceRecordQuery decodeMDnsQuery(List<int> packet) {
+ResourceRecordQuery? decodeMDnsQuery(List<int> packet) {
   final int length = packet.length;
   if (length < _kHeaderSize) {
     return null;
@@ -214,7 +211,7 @@
 /// If decoding fails (e.g. due to an invalid packet) `null` is returned.
 ///
 /// See https://tools.ietf.org/html/rfc1035 for the format.
-List<ResourceRecord> decodeMDnsResponse(List<int> packet) {
+List<ResourceRecord>? decodeMDnsResponse(List<int> packet) {
   final int length = packet.length;
   if (length < _kHeaderSize) {
     return null;
@@ -242,7 +239,7 @@
     }
   }
 
-  ResourceRecord readResourceRecord() {
+  ResourceRecord? readResourceRecord() {
     // First read the FQDN.
     final _FQDNReadResult result = _readFQDN(data, packetBytes, offset, length);
     final String fqdn = result.fqdn;
@@ -319,7 +316,6 @@
           priority: priority,
           weight: weight,
         );
-        break;
       case ResourceRecordType.serverPointer:
         checkLength(offset + readDataLength);
         final _FQDNReadResult result =
@@ -373,7 +369,7 @@
       offset += 4;
     }
     for (int i = 0; i < remainingCount; i++) {
-      final ResourceRecord record = readResourceRecord();
+      final ResourceRecord? record = readResourceRecord();
       if (record != null) {
         result.add(record);
       }
@@ -391,7 +387,7 @@
   /// specified [offset].
   ///
   /// The [offset] parameter should not be null.
-  const MDnsDecodeException(this.offset) : assert(offset != null);
+  const MDnsDecodeException(this.offset);
 
   /// The offset in the packet at which the exception occurred.
   final int offset;
diff --git a/packages/multicast_dns/lib/src/resource_record.dart b/packages/multicast_dns/lib/src/resource_record.dart
index e4be5f3..eae21bf 100644
--- a/packages/multicast_dns/lib/src/resource_record.dart
+++ b/packages/multicast_dns/lib/src/resource_record.dart
@@ -6,7 +6,6 @@
 import 'dart:io';
 import 'dart:typed_data';
 
-import 'package:meta/meta.dart';
 import 'package:multicast_dns/src/constants.dart';
 import 'package:multicast_dns/src/packet.dart';
 
@@ -19,7 +18,6 @@
     (current & _multipleHashPrime) ^ hash;
 
 int _hashValues(List<int> values) {
-  assert(values != null);
   assert(values.isNotEmpty);
 
   return values.fold(
@@ -29,10 +27,10 @@
 }
 
 /// Enumeration of support resource record types.
-class ResourceRecordType {
+abstract class ResourceRecordType {
   // This class is intended to be used as a namespace, and should not be
   // extended directly.
-  factory ResourceRecordType._() => null;
+  ResourceRecordType._();
 
   /// An IPv4 Address record, also known as an "A" record. It has a value of 1.
   static const int addressIPv4 = 1;
@@ -94,8 +92,7 @@
     this.resourceRecordType,
     this.fullyQualifiedName,
     this.questionType,
-  )   : assert(fullyQualifiedName != null),
-        assert(ResourceRecordType.debugAssertValid(resourceRecordType));
+  ) : assert(ResourceRecordType.debugAssertValid(resourceRecordType));
 
   /// An A (IPv4) query.
   ResourceRecordQuery.addressIPv4(
@@ -191,8 +188,7 @@
 /// Base implementation of DNS resource records (RRs).
 abstract class ResourceRecord {
   /// Creates a new ResourceRecord.
-  const ResourceRecord(this.resourceRecordType, this.name, this.validUntil)
-      : assert(name != null);
+  const ResourceRecord(this.resourceRecordType, this.name, this.validUntil);
 
   /// The FQDN for this record.
   final String name;
@@ -207,14 +203,13 @@
 
   @override
   String toString() =>
-      '$runtimeType{$name, validUntil: ${DateTime.fromMillisecondsSinceEpoch(validUntil ?? 0)}, $_additionalInfo}';
+      '$runtimeType{$name, validUntil: ${DateTime.fromMillisecondsSinceEpoch(validUntil)}, $_additionalInfo}';
 
   @override
   bool operator ==(Object other) {
-    return other.runtimeType == runtimeType && _equals(other);
+    return other is ResourceRecord && _equals(other);
   }
 
-  @protected
   bool _equals(ResourceRecord other) {
     return other.name == name &&
         other.validUntil == validUntil &&
@@ -233,7 +228,6 @@
 
   // Subclasses of this class should use _hashValues to create a hash code
   // that will then get hashed in with the common values on this class.
-  @protected
   int get _hashCode;
 
   /// Low level method for encoding this record into an mDNS packet.
@@ -250,9 +244,8 @@
   PtrResourceRecord(
     String name,
     int validUntil, {
-    @required this.domainName,
-  })  : assert(domainName != null),
-        super(ResourceRecordType.serverPointer, name, validUntil);
+    required this.domainName,
+  }) : super(ResourceRecordType.serverPointer, name, validUntil);
 
   /// The FQDN for this record.
   final String domainName;
@@ -282,7 +275,7 @@
   IPAddressResourceRecord(
     String name,
     int validUntil, {
-    @required this.address,
+    required this.address,
   }) : super(
             address.type == InternetAddressType.IPv4
                 ? ResourceRecordType.addressIPv4
@@ -316,15 +309,11 @@
   SrvResourceRecord(
     String name,
     int validUntil, {
-    @required this.target,
-    @required this.port,
-    @required this.priority,
-    @required this.weight,
-  })  : assert(target != null),
-        assert(port != null),
-        assert(priority != null),
-        assert(weight != null),
-        super(ResourceRecordType.service, name, validUntil);
+    required this.target,
+    required this.port,
+    required this.priority,
+    required this.weight,
+  }) : super(ResourceRecordType.service, name, validUntil);
 
   /// The hostname for this record.
   final String target;
@@ -378,9 +367,8 @@
   TxtResourceRecord(
     String name,
     int validUntil, {
-    @required this.text,
-  })  : assert(text != null),
-        super(ResourceRecordType.text, name, validUntil);
+    required this.text,
+  }) : super(ResourceRecordType.text, name, validUntil);
 
   /// The raw text from this record.
   final String text;
diff --git a/packages/multicast_dns/pubspec.yaml b/packages/multicast_dns/pubspec.yaml
index 98c75ae..d59445f 100644
--- a/packages/multicast_dns/pubspec.yaml
+++ b/packages/multicast_dns/pubspec.yaml
@@ -1,14 +1,10 @@
 name: multicast_dns
 description: Dart package for mDNS queries (e.g. Bonjour, Avahi).
 homepage: https://github.com/flutter/packages/tree/master/packages/multicast_dns
-version: 0.2.2
-
-dependencies:
-  meta: ^1.1.6
+version: 0.3.0
 
 dev_dependencies:
-  mockito: "^4.1.0"
-  test: "^1.3.4"
+  test: "^1.16.5"
 
 environment:
-  sdk: ">=2.2.0 <3.0.0"
+  sdk: ">=2.12.0-0 <3.0.0"
diff --git a/packages/multicast_dns/test/client_test.dart b/packages/multicast_dns/test/client_test.dart
index f327c20..85ab0b1 100644
--- a/packages/multicast_dns/test/client_test.dart
+++ b/packages/multicast_dns/test/client_test.dart
@@ -2,23 +2,25 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:async';
 import 'dart:io';
 
 import 'package:multicast_dns/multicast_dns.dart';
-import 'package:mockito/mockito.dart';
+import 'package:test/fake.dart';
 import 'package:test/test.dart';
 
 void main() {
   test('Can inject datagram socket factory and configure mdns port', () async {
-    int lastPort;
-    final MockRawDatagramSocket mockRawDatagramSocket = MockRawDatagramSocket();
+    late int lastPort;
+    final FakeRawDatagramSocket datagramSocket = FakeRawDatagramSocket();
     final MDnsClient client = MDnsClient(rawDatagramSocketFactory:
         (dynamic host, int port,
-            {bool reuseAddress, bool reusePort, int ttl = 1}) async {
+            {bool reuseAddress = true,
+            bool reusePort = true,
+            int ttl = 1}) async {
       lastPort = port;
-      return mockRawDatagramSocket;
+      return datagramSocket;
     });
-    when(mockRawDatagramSocket.address).thenReturn(InternetAddress.anyIPv4);
 
     await client.start(
         mDnsPort: 1234,
@@ -29,4 +31,17 @@
   });
 }
 
-class MockRawDatagramSocket extends Mock implements RawDatagramSocket {}
+class FakeRawDatagramSocket extends Fake implements RawDatagramSocket {
+  @override
+  InternetAddress get address => InternetAddress.anyIPv4;
+
+  @override
+  StreamSubscription<RawSocketEvent> listen(
+      void Function(RawSocketEvent event)? onData,
+      {Function? onError,
+      void Function()? onDone,
+      bool? cancelOnError}) {
+    return const Stream<RawSocketEvent>.empty().listen(onData,
+        onError: onError, cancelOnError: cancelOnError, onDone: onDone);
+  }
+}
diff --git a/packages/multicast_dns/test/decode_test.dart b/packages/multicast_dns/test/decode_test.dart
index f11f4d9..e8c1afa 100644
--- a/packages/multicast_dns/test/decode_test.dart
+++ b/packages/multicast_dns/test/decode_test.dart
@@ -21,23 +21,23 @@
 
 void testValidPackages() {
   test('Can decode valid packets', () {
-    List<ResourceRecord> result = decodeMDnsResponse(package1);
+    List<ResourceRecord> result = decodeMDnsResponse(package1)!;
     expect(result, isNotNull);
     expect(result.length, 1);
-    IPAddressResourceRecord ipResult = result[0];
+    IPAddressResourceRecord ipResult = result[0] as IPAddressResourceRecord;
     expect(ipResult.name, 'raspberrypi.local');
     expect(ipResult.address.address, '192.168.1.191');
 
-    result = decodeMDnsResponse(package2);
+    result = decodeMDnsResponse(package2)!;
     expect(result.length, 2);
-    ipResult = result[0];
+    ipResult = result[0] as IPAddressResourceRecord;
     expect(ipResult.name, 'raspberrypi.local');
     expect(ipResult.address.address, '192.168.1.191');
-    ipResult = result[1];
+    ipResult = result[1] as IPAddressResourceRecord;
     expect(ipResult.name, 'raspberrypi.local');
     expect(ipResult.address.address, '169.254.95.83');
 
-    result = decodeMDnsResponse(package3);
+    result = decodeMDnsResponse(package3)!;
     expect(result.length, 8);
     expect(result, <ResourceRecord>[
       TxtResourceRecord(
@@ -85,7 +85,7 @@
       ),
     ]);
 
-    result = decodeMDnsResponse(packagePtrResponse);
+    result = decodeMDnsResponse(packagePtrResponse)!;
     expect(6, result.length);
     expect(result, <ResourceRecord>[
       PtrResourceRecord(
@@ -127,7 +127,7 @@
   // Fixes https://github.com/flutter/flutter/issues/31854
   test('Can decode packages with question, answer and additional', () {
     final List<ResourceRecord> result =
-        decodeMDnsResponse(packetWithQuestionAnArCount);
+        decodeMDnsResponse(packetWithQuestionAnArCount)!;
     expect(result, isNotNull);
     expect(result.length, 2);
     expect(result, <ResourceRecord>[
@@ -148,7 +148,7 @@
   test('Can decode packages without question and with answer and additional',
       () {
     final List<ResourceRecord> result =
-        decodeMDnsResponse(packetWithoutQuestionWithAnArCount);
+        decodeMDnsResponse(packetWithoutQuestionWithAnArCount)!;
     expect(result, isNotNull);
     expect(result.length, 2);
     expect(result, <ResourceRecord>[
@@ -166,7 +166,7 @@
   });
 
   test('Can decode packages with a long text resource', () {
-    final List<ResourceRecord> result = decodeMDnsResponse(packetWithLongTxt);
+    final List<ResourceRecord> result = decodeMDnsResponse(packetWithLongTxt)!;
     expect(result, isNotNull);
     expect(result.length, 2);
     expect(result, <ResourceRecord>[
@@ -210,10 +210,10 @@
 
 void testNonUtf8DomainName() {
   test('Returns non-null for non-utf8 domain name', () {
-    final List<ResourceRecord> result = decodeMDnsResponse(nonUtf8Package);
+    final List<ResourceRecord> result = decodeMDnsResponse(nonUtf8Package)!;
     expect(result, isNotNull);
     expect(result[0] is TxtResourceRecord, isTrue);
-    final TxtResourceRecord txt = result[0];
+    final TxtResourceRecord txt = result[0] as TxtResourceRecord;
     expect(txt.name, contains('�'));
   });
 }
diff --git a/packages/multicast_dns/test/lookup_resolver_test.dart b/packages/multicast_dns/test/lookup_resolver_test.dart
index 6a311fd..3423a68 100644
--- a/packages/multicast_dns/test/lookup_resolver_test.dart
+++ b/packages/multicast_dns/test/lookup_resolver_test.dart
@@ -40,7 +40,8 @@
     final ResourceRecord response =
         ip4Result('xxx.local', InternetAddress('1.2.3.4'));
     resolver.handleResponse(<ResourceRecord>[response]);
-    final IPAddressResourceRecord result = await futureResult.first;
+    final IPAddressResourceRecord result =
+        await futureResult.first as IPAddressResourceRecord;
     expect('1.2.3.4', result.address.address);
     resolver.clearPendingRequests();
   });
@@ -59,8 +60,10 @@
     final ResourceRecord response2 =
         ip4Result('yyy.local', InternetAddress('2.3.4.5'));
     resolver.handleResponse(<ResourceRecord>[response2, response1]);
-    final IPAddressResourceRecord result1 = await futureResult1.first;
-    final IPAddressResourceRecord result2 = await futureResult2.first;
+    final IPAddressResourceRecord result1 =
+        await futureResult1.first as IPAddressResourceRecord;
+    final IPAddressResourceRecord result2 =
+        await futureResult2.first as IPAddressResourceRecord;
     expect('1.2.3.4', result1.address.address);
     expect('2.3.4.5', result2.address.address);
     resolver.clearPendingRequests();
@@ -88,8 +91,10 @@
     resolver.handleResponse(<ResourceRecord>[response0]);
     resolver.handleResponse(<ResourceRecord>[response2, response1]);
     resolver.handleResponse(<ResourceRecord>[response0]);
-    final IPAddressResourceRecord result1 = await futureResult1.first;
-    final IPAddressResourceRecord result2 = await futureResult2.first;
+    final IPAddressResourceRecord result1 =
+        await futureResult1.first as IPAddressResourceRecord;
+    final IPAddressResourceRecord result2 =
+        await futureResult2.first as IPAddressResourceRecord;
     expect('1.2.3.4', result1.address.address);
     expect('2.3.4.5', result2.address.address);
     resolver.clearPendingRequests();
diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md
index 2c96dc7..0e5faee 100644
--- a/packages/pigeon/CHANGELOG.md
+++ b/packages/pigeon/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.1.21
+
+* Fixed decode method on generated Flutter classes that use null-safety and have
+  null values.
+
 ## 0.1.20
 
 * Implemented `@async` HostApi's for iOS.
diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart
index 6cf834d..ca94c97 100644
--- a/packages/pigeon/lib/dart_generator.dart
+++ b/packages/pigeon/lib/dart_generator.dart
@@ -178,11 +178,11 @@
 String _addGenericTypes(String dataType, String nullTag) {
   switch (dataType) {
     case 'List':
-      return 'List<Object$nullTag>';
+      return 'List<Object$nullTag>$nullTag';
     case 'Map':
-      return 'Map<Object$nullTag, Object$nullTag>';
+      return 'Map<Object$nullTag, Object$nullTag>$nullTag';
     default:
-      return dataType;
+      return '$dataType$nullTag';
   }
 }
 
@@ -211,8 +211,7 @@
     sink.write('class ${klass.name} ');
     indent.scoped('{', '}', () {
       for (Field field in klass.fields) {
-        final String datatype =
-            '${_addGenericTypes(field.dataType, nullTag)}$nullTag';
+        final String datatype = '${_addGenericTypes(field.dataType, nullTag)}';
         indent.writeln('$datatype ${field.name};');
       }
       if (klass.fields.isNotEmpty) {
diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart
index 996e794..d196e26 100644
--- a/packages/pigeon/lib/generator_tools.dart
+++ b/packages/pigeon/lib/generator_tools.dart
@@ -8,7 +8,7 @@
 import 'ast.dart';
 
 /// The current version of pigeon. This must match the version in pubspec.yaml.
-const String pigeonVersion = '0.1.20';
+const String pigeonVersion = '0.1.21';
 
 /// Read all the content from [stdin] to a String.
 String readStdin() {
diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart
index 68f61f6..c79a18e 100644
--- a/packages/pigeon/lib/java_generator.dart
+++ b/packages/pigeon/lib/java_generator.dart
@@ -14,8 +14,8 @@
   'Int32List': 'int[]',
   'Int64List': 'long[]',
   'Float64List': 'double[]',
-  'List': 'ArrayList',
-  'Map': 'HashMap',
+  'List': 'List<Object>',
+  'Map': 'Map<String, Object>',
 };
 
 /// Options that control how Java code will be generated.
@@ -77,15 +77,14 @@
             indent.scoped('{', '});', () {
               final String argType = method.argType;
               final String returnType = method.returnType;
-              indent.writeln(
-                  'HashMap<String, HashMap> wrapped = new HashMap<>();');
+              indent.writeln('Map<String, Object> wrapped = new HashMap<>();');
               indent.write('try ');
               indent.scoped('{', '}', () {
                 final List<String> methodArgument = <String>[];
                 if (argType != 'void') {
                   indent.writeln('@SuppressWarnings("ConstantConditions")');
                   indent.writeln(
-                      '$argType input = $argType.fromMap((HashMap)message);');
+                      '$argType input = $argType.fromMap((Map<String, Object>)message);');
                   methodArgument.add('input');
                 }
                 if (method.isAsynchronous) {
@@ -168,20 +167,40 @@
         indent.dec();
         indent.dec();
         if (func.argType != 'void') {
-          indent.writeln('HashMap inputMap = argInput.toMap();');
+          indent.writeln('Map<String, Object> inputMap = argInput.toMap();');
         }
-        indent.write('channel.send($sendArgument, channelReply -> ');
-        indent.scoped('{', '});', () {
-          if (func.returnType == 'void') {
-            indent.writeln('callback.reply(null);');
-          } else {
-            indent.writeln('HashMap outputMap = (HashMap)channelReply;');
-            indent.writeln('@SuppressWarnings("ConstantConditions")');
-            indent.writeln(
-                '${func.returnType} output = ${func.returnType}.fromMap(outputMap);');
-            indent.writeln('callback.reply(output);');
-          }
+        indent.write('if (callback != null)');
+        indent.scoped('{', '}', () {
+          indent.write('channel.send($sendArgument, channelReply -> ');
+          indent.scoped('{', '});', () {
+            if (func.returnType == 'void') {
+              indent.writeln('callback.reply(null);');
+            } else {
+              indent.writeln('Map outputMap = (Map)channelReply;');
+              indent.writeln('@SuppressWarnings("ConstantConditions")');
+              indent.writeln(
+                  '${func.returnType} output = ${func.returnType}.fromMap(outputMap);');
+              indent.writeln('callback.reply(output);');
+            }
+          });
         });
+        indent.write(' else ');
+        indent.scoped('{', '}', () {
+          indent.writeln('channel.send($sendArgument, null);');
+        });
+      });
+
+      if (func.argType == 'void') {
+        indent.write('public void ${func.name}() ');
+      } else {
+        indent.write('public void ${func.name}(${func.argType} argInput) ');
+      }
+      indent.scoped('{', '}', () {
+        if (func.argType == 'void') {
+          indent.writeln('${func.name}(null);');
+        } else {
+          indent.writeln('${func.name}(argInput, null);');
+        }
       });
     }
   });
@@ -210,7 +229,7 @@
     return '($varName == null) ? null : (($varName instanceof Integer) ? (Integer)$varName : (${hostDatatype.datatype})$varName)';
   } else if (!hostDatatype.isBuiltin &&
       classes.map((Class x) => x.name).contains(field.dataType)) {
-    return '${hostDatatype.datatype}.fromMap((HashMap)$varName)';
+    return '${hostDatatype.datatype}.fromMap((Map)$varName)';
   } else {
     return '(${hostDatatype.datatype})$varName';
   }
@@ -232,13 +251,15 @@
   indent.writeln('import io.flutter.plugin.common.BasicMessageChannel;');
   indent.writeln('import io.flutter.plugin.common.BinaryMessenger;');
   indent.writeln('import io.flutter.plugin.common.StandardMessageCodec;');
-  indent.writeln('import java.util.ArrayList;');
+  indent.writeln('import java.util.List;');
+  indent.writeln('import java.util.Map;');
   indent.writeln('import java.util.HashMap;');
 
   indent.addln('');
   assert(options.className != null);
   indent.writeln('/** Generated class from Pigeon. */');
-  indent.writeln('@SuppressWarnings("unused")');
+  indent.writeln(
+      '@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression"})');
   indent.write('public class ${options.className} ');
   indent.scoped('{', '}', () {
     for (Class klass in root.classes) {
@@ -257,10 +278,9 @@
               'public void ${_makeSetter(field)}(${hostDatatype.datatype} setterArg) { this.${field.name} = setterArg; }');
           indent.addln('');
         }
-        indent.write('HashMap toMap() ');
+        indent.write('Map<String, Object> toMap() ');
         indent.scoped('{', '}', () {
-          indent.writeln(
-              'HashMap<String, Object> toMapResult = new HashMap<>();');
+          indent.writeln('Map<String, Object> toMapResult = new HashMap<>();');
           for (Field field in klass.fields) {
             final HostDatatype hostDatatype =
                 getHostDatatype(field, root.classes, _javaTypeForDartType);
@@ -275,7 +295,7 @@
           }
           indent.writeln('return toMapResult;');
         });
-        indent.write('static ${klass.name} fromMap(HashMap map) ');
+        indent.write('static ${klass.name} fromMap(Map<String, Object> map) ');
         indent.scoped('{', '}', () {
           indent.writeln('${klass.name} fromMapResult = new ${klass.name}();');
           for (Field field in klass.fields) {
@@ -297,8 +317,9 @@
       }
     }
 
-    indent.format('''private static HashMap wrapError(Exception exception) {
-\tHashMap<String, Object> errorMap = new HashMap<>();
+    indent.format(
+        '''private static Map<String, Object> wrapError(Exception exception) {
+\tMap<String, Object> errorMap = new HashMap<>();
 \terrorMap.put("${Keys.errorMessage}", exception.toString());
 \terrorMap.put("${Keys.errorCode}", exception.getClass().getSimpleName());
 \terrorMap.put("${Keys.errorDetails}", null);
diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/.gitignore b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/.gitignore
new file mode 100644
index 0000000..0fa6b67
--- /dev/null
+++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/.gitignore
@@ -0,0 +1,46 @@
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+lib/generated_plugin_registrant.dart
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/.metadata b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/.metadata
new file mode 100644
index 0000000..5db57c1
--- /dev/null
+++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/.metadata
@@ -0,0 +1,10 @@
+# This file tracks properties of this Flutter project.
+# Used by Flutter tool to assess capabilities and perform upgrades etc.
+#
+# This file should be version controlled and should not be manually edited.
+
+version:
+  revision: 6db3d61ed4a58ba89140d7fe1fd294b598cc29c5
+  channel: master
+
+project_type: app
diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/README.md b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/README.md
new file mode 100644
index 0000000..3c52fc9
--- /dev/null
+++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/README.md
@@ -0,0 +1,3 @@
+# flutter_unit_tests
+
+Unit test scaffold for null safe Flutter projects.
diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/null_safe_pigeon.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/null_safe_pigeon.dart
new file mode 100644
index 0000000..455058d
--- /dev/null
+++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/null_safe_pigeon.dart
@@ -0,0 +1,166 @@
+// Autogenerated from Pigeon (v0.1.21), do not edit directly.
+// See also: https://pub.dev/packages/pigeon
+// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import
+// @dart = 2.12
+import 'dart:async';
+import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List;
+
+import 'package:flutter/services.dart';
+
+class SearchReply {
+  String? result;
+  String? error;
+
+  Object encode() {
+    final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
+    pigeonMap['result'] = result;
+    pigeonMap['error'] = error;
+    return pigeonMap;
+  }
+
+  static SearchReply decode(Object message) {
+    final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
+    return SearchReply()
+      ..result = pigeonMap['result'] as String?
+      ..error = pigeonMap['error'] as String?;
+  }
+}
+
+class SearchRequest {
+  String? query;
+  int? anInt;
+  bool? aBool;
+
+  Object encode() {
+    final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
+    pigeonMap['query'] = query;
+    pigeonMap['anInt'] = anInt;
+    pigeonMap['aBool'] = aBool;
+    return pigeonMap;
+  }
+
+  static SearchRequest decode(Object message) {
+    final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
+    return SearchRequest()
+      ..query = pigeonMap['query'] as String?
+      ..anInt = pigeonMap['anInt'] as int?
+      ..aBool = pigeonMap['aBool'] as bool?;
+  }
+}
+
+class Nested {
+  SearchRequest? request;
+
+  Object encode() {
+    final Map<Object?, Object?> pigeonMap = <Object?, Object?>{};
+    pigeonMap['request'] = request == null ? null : request!.encode();
+    return pigeonMap;
+  }
+
+  static Nested decode(Object message) {
+    final Map<Object?, Object?> pigeonMap = message as Map<Object?, Object?>;
+    return Nested()
+      ..request = pigeonMap['request'] != null
+          ? SearchRequest.decode(pigeonMap['request']!)
+          : null;
+  }
+}
+
+abstract class FlutterSearchApi {
+  SearchReply search(SearchRequest arg);
+  static void setup(FlutterSearchApi? api) {
+    {
+      const BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+          'dev.flutter.pigeon.FlutterSearchApi.search', StandardMessageCodec());
+      if (api == null) {
+        channel.setMessageHandler(null);
+      } else {
+        channel.setMessageHandler((Object? message) async {
+          assert(message != null,
+              'Argument for dev.flutter.pigeon.FlutterSearchApi.search was null. Expected SearchRequest.');
+          final SearchRequest input = SearchRequest.decode(message!);
+          final SearchReply output = api.search(input);
+          return output.encode();
+        });
+      }
+    }
+  }
+}
+
+class NestedApi {
+  Future<SearchReply> search(Nested arg) async {
+    final Object encoded = arg.encode();
+    const BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+        'dev.flutter.pigeon.NestedApi.search', StandardMessageCodec());
+    final Map<Object?, Object?>? replyMap =
+        await channel.send(encoded) as Map<Object?, Object?>?;
+    if (replyMap == null) {
+      throw PlatformException(
+        code: 'channel-error',
+        message: 'Unable to establish connection on channel.',
+        details: null,
+      );
+    } else if (replyMap['error'] != null) {
+      final Map<Object?, Object?> error =
+          replyMap['error'] as Map<Object?, Object?>;
+      throw PlatformException(
+        code: error['code'] as String,
+        message: error['message'] as String?,
+        details: error['details'],
+      );
+    } else {
+      return SearchReply.decode(replyMap['result']!);
+    }
+  }
+}
+
+class Api {
+  Future<void> initialize() async {
+    const BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+        'dev.flutter.pigeon.Api.initialize', StandardMessageCodec());
+    final Map<Object?, Object?>? replyMap =
+        await channel.send(null) as Map<Object?, Object?>?;
+    if (replyMap == null) {
+      throw PlatformException(
+        code: 'channel-error',
+        message: 'Unable to establish connection on channel.',
+        details: null,
+      );
+    } else if (replyMap['error'] != null) {
+      final Map<Object?, Object?> error =
+          replyMap['error'] as Map<Object?, Object?>;
+      throw PlatformException(
+        code: error['code'] as String,
+        message: error['message'] as String?,
+        details: error['details'],
+      );
+    } else {
+      // noop
+    }
+  }
+
+  Future<SearchReply> search(SearchRequest arg) async {
+    final Object encoded = arg.encode();
+    const BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
+        'dev.flutter.pigeon.Api.search', StandardMessageCodec());
+    final Map<Object?, Object?>? replyMap =
+        await channel.send(encoded) as Map<Object?, Object?>?;
+    if (replyMap == null) {
+      throw PlatformException(
+        code: 'channel-error',
+        message: 'Unable to establish connection on channel.',
+        details: null,
+      );
+    } else if (replyMap['error'] != null) {
+      final Map<Object?, Object?> error =
+          replyMap['error'] as Map<Object?, Object?>;
+      throw PlatformException(
+        code: error['code'] as String,
+        message: error['message'] as String?,
+        details: error['details'],
+      );
+    } else {
+      return SearchReply.decode(replyMap['result']!);
+    }
+  }
+}
diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/pubspec.yaml b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/pubspec.yaml
new file mode 100644
index 0000000..32058de
--- /dev/null
+++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/pubspec.yaml
@@ -0,0 +1,17 @@
+name: flutter_unit_tests
+description: Unit test scaffold for null safe Flutter projects.
+publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+version: 1.0.0+1
+environment:
+  sdk: ">=2.12.0 <3.0.0"
+
+dependencies:
+  flutter:
+    sdk: flutter
+
+dev_dependencies:
+  flutter_test:
+    sdk: flutter
+
+flutter:
+  uses-material-design: true
diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_safe_test.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_safe_test.dart
new file mode 100644
index 0000000..523127a
--- /dev/null
+++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_safe_test.dart
@@ -0,0 +1,28 @@
+// Copyright 2020 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter_unit_tests/null_safe_pigeon.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+  test('with values filled', () {
+    final SearchReply reply = SearchReply()
+      ..result = 'foo'
+      ..error = 'bar';
+    final Object encoded = reply.encode();
+    final SearchReply decoded = SearchReply.decode(encoded);
+    expect(reply.result, decoded.result);
+    expect(reply.error, decoded.error);
+  });
+
+  test('with null value', () {
+    final SearchReply reply = SearchReply()
+      ..result = 'foo'
+      ..error = null;
+    final Object encoded = reply.encode();
+    final SearchReply decoded = SearchReply.decode(encoded);
+    expect(reply.result, decoded.result);
+    expect(reply.error, decoded.error);
+  });
+}
diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml
index 408779e..e534e2d 100644
--- a/packages/pigeon/pubspec.yaml
+++ b/packages/pigeon/pubspec.yaml
@@ -1,5 +1,5 @@
 name: pigeon
-version: 0.1.20 # This must match the version in lib/generator_tools.dart
+version: 0.1.21 # This must match the version in lib/generator_tools.dart
 description: Code generator tool to make communication between Flutter and the host platform type-safe and easier.
 homepage: https://github.com/flutter/packages/tree/master/packages/pigeon
 dependencies:
diff --git a/packages/pigeon/run_tests.sh b/packages/pigeon/run_tests.sh
index c6b5b20..ae5aa1e 100755
--- a/packages/pigeon/run_tests.sh
+++ b/packages/pigeon/run_tests.sh
@@ -111,6 +111,19 @@
 pub run pigeon 1> /dev/null
 
 ###############################################################################
+# Run unit tests on generated Dart code.
+###############################################################################
+pushd $PWD
+pub run pigeon \
+    --input pigeons/message.dart \
+    --dart_null_safety \
+    --dart_out platform_tests/flutter_null_safe_unit_tests/lib/null_safe_pigeon.dart
+cd platform_tests/flutter_null_safe_unit_tests
+flutter pub get
+flutter test test/null_safe_test.dart 
+popd
+
+###############################################################################
 # Mock handler flutter tests.
 ###############################################################################
 pushd $PWD
diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart
index 0334de6..c453231 100644
--- a/packages/pigeon/test/java_generator_test.dart
+++ b/packages/pigeon/test/java_generator_test.dart
@@ -46,7 +46,7 @@
     generateJava(javaOptions, root, sink);
     final String code = sink.toString();
     expect(code, contains('package com.google.foobar;'));
-    expect(code, contains('HashMap toMap()'));
+    expect(code, contains('Map<String, Object> toMap()'));
   });
 
   test('gen one host api', () {
@@ -242,7 +242,7 @@
     generateJava(javaOptions, root, sink);
     final String code = sink.toString();
     expect(code, contains('public static class Foobar'));
-    expect(code, contains('private ArrayList field1;'));
+    expect(code, contains('private List<Object> field1;'));
   });
 
   test('gen map', () {
@@ -257,7 +257,7 @@
     generateJava(javaOptions, root, sink);
     final String code = sink.toString();
     expect(code, contains('public static class Foobar'));
-    expect(code, contains('private HashMap field1;'));
+    expect(code, contains('private Map<String, Object> field1;'));
   });
 
   test('gen nested', () {
@@ -287,7 +287,7 @@
     expect(code, contains('public static class Outer'));
     expect(code, contains('public static class Nested'));
     expect(code, contains('private Nested nested;'));
-    expect(code, contains('Nested.fromMap((HashMap)nested);'));
+    expect(code, contains('Nested.fromMap((Map)nested);'));
     expect(code, contains('put("nested", nested.toMap());'));
   });
 
diff --git a/packages/pointer_interceptor/CHANGELOG.md b/packages/pointer_interceptor/CHANGELOG.md
index a11d080..06e0c6e 100644
--- a/packages/pointer_interceptor/CHANGELOG.md
+++ b/packages/pointer_interceptor/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.9.0
+
+* Migrates to null safety.
+
 ## 0.8.0+2
 
 * Use `ElevatedButton` instead of the deprecated `RaisedButton` in example and docs.
diff --git a/packages/pointer_interceptor/example/README.md b/packages/pointer_interceptor/example/README.md
index d4973fd..9fddf8c 100644
--- a/packages/pointer_interceptor/example/README.md
+++ b/packages/pointer_interceptor/example/README.md
@@ -8,7 +8,7 @@
 
 ## Running tests
 
-`flutter drive --target integration_test/widget_test.dart --driver test_driver/integration_test.dart --show-web-server-device -d web-server`
+`flutter drive --target integration_test/widget_test.dart --driver test_driver/integration_test.dart --show-web-server-device -d web-server --web-renderer=html`
 
 The command above will run the integration tests for this package.
 
diff --git a/packages/pointer_interceptor/example/integration_test/widget_test.dart b/packages/pointer_interceptor/example/integration_test/widget_test.dart
index 59ca9a6..72b02ad 100644
--- a/packages/pointer_interceptor/example/integration_test/widget_test.dart
+++ b/packages/pointer_interceptor/example/integration_test/widget_test.dart
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @dart = 2.9
 import 'dart:html' as html;
 
 // Imports the Flutter Driver API.
@@ -27,12 +26,12 @@
       app.main();
       await tester.pumpAndSettle();
 
-      final html.Element element =
+      final html.Element? element =
           _getHtmlElementFromFinder(clickableButtonFinder, tester);
-      expect(element.tagName.toLowerCase(), 'flt-platform-view');
+      expect(element?.tagName.toLowerCase(), 'flt-platform-view');
 
-      final html.Element platformViewRoot =
-          element.shadowRoot.getElementById('background-html-view');
+      final html.Element? platformViewRoot =
+          element?.shadowRoot?.getElementById('background-html-view');
       expect(platformViewRoot, isNull);
     });
 
@@ -42,12 +41,12 @@
       app.main();
       await tester.pumpAndSettle();
 
-      final html.Element element =
+      final html.Element? element =
           _getHtmlElementFromFinder(nonClickableButtonFinder, tester);
-      expect(element.tagName.toLowerCase(), 'flt-platform-view');
+      expect(element?.tagName.toLowerCase(), 'flt-platform-view');
 
-      final html.Element platformViewRoot =
-          element.shadowRoot.getElementById('background-html-view');
+      final html.Element? platformViewRoot =
+          element?.shadowRoot?.getElementById('background-html-view');
       expect(platformViewRoot, isNotNull);
     });
   });
@@ -56,7 +55,7 @@
 // This functions locates a widget from a Finder, and asks the browser what's the
 // DOM element in the center of the coordinates of the widget. (Returns *which*
 // DOM element will handle Mouse interactions first at those coordinates.)
-html.Element _getHtmlElementFromFinder(Finder finder, WidgetTester tester) {
+html.Element? _getHtmlElementFromFinder(Finder finder, WidgetTester tester) {
   final Offset point = tester.getCenter(finder);
   return html.document.elementFromPoint(point.dx.toInt(), point.dy.toInt());
 }
diff --git a/packages/pointer_interceptor/example/lib/main.dart b/packages/pointer_interceptor/example/lib/main.dart
index 4421e79..fd2b539 100644
--- a/packages/pointer_interceptor/example/lib/main.dart
+++ b/packages/pointer_interceptor/example/lib/main.dart
@@ -186,7 +186,7 @@
 /// Initialize the videoPlayer, then render the corresponding view...
 class HtmlElement extends StatelessWidget {
   /// Constructor
-  const HtmlElement({this.onClick});
+  const HtmlElement({required this.onClick});
 
   /// A function to run when the element is clicked
   final Function onClick;
diff --git a/packages/pointer_interceptor/example/lib/src/shim/dart_ui_fake.dart b/packages/pointer_interceptor/example/lib/src/shim/dart_ui_fake.dart
index d8456c0..787e349 100644
--- a/packages/pointer_interceptor/example/lib/src/shim/dart_ui_fake.dart
+++ b/packages/pointer_interceptor/example/lib/src/shim/dart_ui_fake.dart
@@ -22,7 +22,7 @@
   /// Shim for getAssetUrl.
   /// https://github.com/flutter/engine/blob/master/lib/web_ui/lib/src/engine/assets.dart#L45
   static String getAssetUrl(String asset) {
-    return null;
+    return '';
   }
 }
 
diff --git a/packages/pointer_interceptor/example/pubspec.yaml b/packages/pointer_interceptor/example/pubspec.yaml
index dbb4f7a..2ed4117 100644
--- a/packages/pointer_interceptor/example/pubspec.yaml
+++ b/packages/pointer_interceptor/example/pubspec.yaml
@@ -4,7 +4,8 @@
 version: 1.0.0
 
 environment:
-  sdk: ">=2.7.0 <3.0.0"
+  sdk: ">=2.12.0-0 <3.0.0"
+  flutter: ">=1.26.0-0" # For integration_test from sdk
 
 dependencies:
   flutter:
diff --git a/packages/pointer_interceptor/lib/src/mobile.dart b/packages/pointer_interceptor/lib/src/mobile.dart
index ef4ef6a..1f561ac 100644
--- a/packages/pointer_interceptor/lib/src/mobile.dart
+++ b/packages/pointer_interceptor/lib/src/mobile.dart
@@ -8,9 +8,9 @@
 class PointerInterceptor extends StatelessWidget {
   /// Create a `PointerInterceptor` wrapping a `child`.
   const PointerInterceptor({
-    @required this.child,
+    required this.child,
     this.debug = false,
-    Key key,
+    Key? key,
   }) : super(key: key);
 
   /// The `Widget` that is being wrapped by this `PointerInterceptor`.
diff --git a/packages/pointer_interceptor/lib/src/shim/dart_ui_fake.dart b/packages/pointer_interceptor/lib/src/shim/dart_ui_fake.dart
index d8456c0..787e349 100644
--- a/packages/pointer_interceptor/lib/src/shim/dart_ui_fake.dart
+++ b/packages/pointer_interceptor/lib/src/shim/dart_ui_fake.dart
@@ -22,7 +22,7 @@
   /// Shim for getAssetUrl.
   /// https://github.com/flutter/engine/blob/master/lib/web_ui/lib/src/engine/assets.dart#L45
   static String getAssetUrl(String asset) {
-    return null;
+    return '';
   }
 }
 
diff --git a/packages/pointer_interceptor/lib/src/web.dart b/packages/pointer_interceptor/lib/src/web.dart
index e2e86e8..f59c4a3 100644
--- a/packages/pointer_interceptor/lib/src/web.dart
+++ b/packages/pointer_interceptor/lib/src/web.dart
@@ -40,9 +40,9 @@
 class PointerInterceptor extends StatelessWidget {
   /// Creates a PointerInterceptor for the web.
   PointerInterceptor({
-    @required this.child,
+    required this.child,
     this.debug = false,
-    Key key,
+    Key? key,
   }) : super(key: key) {
     if (!_registered) {
       _register();
diff --git a/packages/pointer_interceptor/pubspec.yaml b/packages/pointer_interceptor/pubspec.yaml
index 5bf127d..5bea65f 100644
--- a/packages/pointer_interceptor/pubspec.yaml
+++ b/packages/pointer_interceptor/pubspec.yaml
@@ -1,10 +1,10 @@
 name: pointer_interceptor
 description: A widget to prevent clicks from being swallowed by underlying HtmlElementViews on the web.
-version: 0.8.0+2
 repository: https://github.com/flutter/packages
+version: 0.9.0
 
 environment:
-  sdk: ">=2.7.0 <3.0.0"
+  sdk: ">=2.12.0-0 <3.0.0"
   flutter: ">=1.17.0"
 
 dependencies:
diff --git a/packages/xdg_directories/CHANGELOG.md b/packages/xdg_directories/CHANGELOG.md
index ce6349a..1a525f0 100644
--- a/packages/xdg_directories/CHANGELOG.md
+++ b/packages/xdg_directories/CHANGELOG.md
@@ -1,20 +1,15 @@
-## [0.2.0-nullsafety.1] - Fix getUserDirectory
-
-* Fixes a regression due to the stdoutEncoding change
-  in the null-safety migration.
-
-## [0.2.0-nullsafety.0] - Migrated to null safety
+## 0.2.0
 
 * Migrated to null safety.
 
-## [0.1.2] - Reduce dependencies on external libraries.
+## 0.1.2
 
 * Broaden dependencies to allow nullsafety version of process, meta, and path to be OK.
 
-## [0.1.1] - Reduce dependencies on external libraries.
+## 0.1.1
 
 * Remove flutter, flutter_test from pubspec dependencies.
 
-## [0.1.0] - Initial Release
+## 0.1.0
 
 * Initial release includes all the features described in the README.md
diff --git a/packages/xdg_directories/pubspec.yaml b/packages/xdg_directories/pubspec.yaml
index 95054e3..197813e 100644
--- a/packages/xdg_directories/pubspec.yaml
+++ b/packages/xdg_directories/pubspec.yaml
@@ -1,16 +1,15 @@
 name: xdg_directories
 description: A Dart package for reading XDG directory configuration information on Linux.
-version: 0.2.0-nullsafety.1
+version: 0.2.0
 homepage: https://github.com/flutter/packages/tree/master/packages/xdg_directories
 
 environment:
   sdk: ">=2.12.0-0 <3.0.0"
 
 dependencies:
-  meta: ^1.3.0-nullsafety.6
-  path: ^1.8.0-nullsafety.3
-  process: ^4.0.0-nullsafety.4
+  meta: ^1.3.0
+  path: ^1.8.0
+  process: ^4.0.0
 
 dev_dependencies:
-  mockito: ^5.0.0-nullsafety.1
-  test: ^1.16.0-nullsafety.13
+  test: ^1.16.0
diff --git a/packages/xdg_directories/test/xdg_directories_test.dart b/packages/xdg_directories/test/xdg_directories_test.dart
index 255a69e..c082726 100644
--- a/packages/xdg_directories/test/xdg_directories_test.dart
+++ b/packages/xdg_directories/test/xdg_directories_test.dart
@@ -5,9 +5,9 @@
 import 'dart:convert';
 import 'dart:io';
 
+import 'package:test/fake.dart';
 import 'package:test/test.dart';
 import 'package:path/path.dart' as path;
-import 'package:mockito/mockito.dart' show Fake;
 import 'package:process/process.dart';
 
 import 'package:xdg_directories/xdg_directories.dart' as xdg;