[various] Adopt `plugin_platform_interface` (#6332)

diff --git a/packages/google_sign_in/google_sign_in_platform_interface/CHANGELOG.md b/packages/google_sign_in/google_sign_in_platform_interface/CHANGELOG.md
index 591f36e..cc88c07 100644
--- a/packages/google_sign_in/google_sign_in_platform_interface/CHANGELOG.md
+++ b/packages/google_sign_in/google_sign_in_platform_interface/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 2.3.0
+
+* Adopts `plugin_platform_interface`. As a result, `isMock` is deprecated in
+  favor of the now-standard `MockPlatformInterfaceMixin`.
+
 ## 2.2.0
 
 * Adds support for the `serverClientId` parameter.
diff --git a/packages/google_sign_in/google_sign_in_platform_interface/lib/google_sign_in_platform_interface.dart b/packages/google_sign_in/google_sign_in_platform_interface/lib/google_sign_in_platform_interface.dart
index 69d8455..64fc88d 100644
--- a/packages/google_sign_in/google_sign_in_platform_interface/lib/google_sign_in_platform_interface.dart
+++ b/packages/google_sign_in/google_sign_in_platform_interface/lib/google_sign_in_platform_interface.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 
 import 'package:flutter/foundation.dart' show visibleForTesting;
+import 'package:plugin_platform_interface/plugin_platform_interface.dart';
 
 import 'src/method_channel_google_sign_in.dart';
 import 'src/types.dart';
@@ -20,13 +21,19 @@
 /// ensures that the subclass will get the default implementation, while
 /// platform implementations that `implements` this interface will be broken by
 /// newly added [GoogleSignInPlatform] methods.
-abstract class GoogleSignInPlatform {
+abstract class GoogleSignInPlatform extends PlatformInterface {
+  /// Constructs a GoogleSignInPlatform.
+  GoogleSignInPlatform() : super(token: _token);
+
+  static final Object _token = Object();
+
   /// Only mock implementations should set this to `true`.
   ///
   /// Mockito mocks implement this class with `implements` which is forbidden
   /// (see class docs). This property provides a backdoor for mocks to skip the
   /// verification that the class isn't implemented with `implements`.
   @visibleForTesting
+  @Deprecated('Use MockPlatformInterfaceMixin instead')
   bool get isMock => false;
 
   /// The default instance of [GoogleSignInPlatform] to use.
@@ -44,25 +51,11 @@
   // https://github.com/flutter/flutter/issues/43368
   static set instance(GoogleSignInPlatform instance) {
     if (!instance.isMock) {
-      try {
-        instance._verifyProvidesDefaultImplementations();
-      } on NoSuchMethodError catch (_) {
-        throw AssertionError(
-            'Platform interfaces must not be implemented with `implements`');
-      }
+      PlatformInterface.verify(instance, _token);
     }
     _instance = instance;
   }
 
-  /// This method ensures that [GoogleSignInPlatform] isn't implemented with `implements`.
-  ///
-  /// See class docs for more details on why using `implements` to implement
-  /// [GoogleSignInPlatform] is forbidden.
-  ///
-  /// This private method is called by the [instance] setter, which should fail
-  /// if the provided instance is a class implemented with `implements`.
-  void _verifyProvidesDefaultImplementations() {}
-
   /// Initializes the plugin. Deprecated: call [initWithParams] instead.
   ///
   /// The [hostedDomain] argument specifies a hosted domain restriction. By
diff --git a/packages/google_sign_in/google_sign_in_platform_interface/pubspec.yaml b/packages/google_sign_in/google_sign_in_platform_interface/pubspec.yaml
index 9ad3e1c..aa9c8f6 100644
--- a/packages/google_sign_in/google_sign_in_platform_interface/pubspec.yaml
+++ b/packages/google_sign_in/google_sign_in_platform_interface/pubspec.yaml
@@ -4,7 +4,7 @@
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_sign_in%22
 # NOTE: We strongly prefer non-breaking changes, even at the expense of a
 # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes
-version: 2.2.0
+version: 2.3.0
 
 environment:
   sdk: ">=2.12.0 <3.0.0"
@@ -13,6 +13,7 @@
 dependencies:
   flutter:
     sdk: flutter
+  plugin_platform_interface: ^2.1.0
   quiver: ^3.0.0
 
 dev_dependencies:
diff --git a/packages/google_sign_in/google_sign_in_platform_interface/test/google_sign_in_platform_interface_test.dart b/packages/google_sign_in/google_sign_in_platform_interface/test/google_sign_in_platform_interface_test.dart
index 6ffa85f..057f13c 100644
--- a/packages/google_sign_in/google_sign_in_platform_interface/test/google_sign_in_platform_interface_test.dart
+++ b/packages/google_sign_in/google_sign_in_platform_interface/test/google_sign_in_platform_interface_test.dart
@@ -5,6 +5,7 @@
 import 'package:flutter_test/flutter_test.dart';
 import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
 import 'package:mockito/mockito.dart';
+import 'package:plugin_platform_interface/plugin_platform_interface.dart';
 
 void main() {
   // Store the initial instance before any tests change it.
@@ -33,7 +34,11 @@
     });
 
     test('Can be mocked with `implements`', () {
-      GoogleSignInPlatform.instance = ImplementsWithIsMock();
+      GoogleSignInPlatform.instance = ModernMockImplementation();
+    });
+
+    test('still supports legacy isMock', () {
+      GoogleSignInPlatform.instance = LegacyIsMockImplementation();
     });
   });
 
@@ -76,11 +81,18 @@
   });
 }
 
-class ImplementsWithIsMock extends Mock implements GoogleSignInPlatform {
+class LegacyIsMockImplementation extends Mock implements GoogleSignInPlatform {
   @override
   bool get isMock => true;
 }
 
+class ModernMockImplementation extends Mock
+    with MockPlatformInterfaceMixin
+    implements GoogleSignInPlatform {
+  @override
+  bool get isMock => false;
+}
+
 class ImplementsGoogleSignInPlatform extends Mock
     implements GoogleSignInPlatform {}
 
diff --git a/packages/shared_preferences/shared_preferences_platform_interface/CHANGELOG.md b/packages/shared_preferences/shared_preferences_platform_interface/CHANGELOG.md
index 51b5965..12d6132 100644
--- a/packages/shared_preferences/shared_preferences_platform_interface/CHANGELOG.md
+++ b/packages/shared_preferences/shared_preferences_platform_interface/CHANGELOG.md
@@ -1,6 +1,7 @@
-## NEXT
+## 2.1.0
 
-* Fixes newly enabled analyzer options.
+* Adopts `plugin_platform_interface`. As a result, `isMock` is deprecated in
+  favor of the now-standard `MockPlatformInterfaceMixin`.
 
 ## 2.0.0
 
diff --git a/packages/shared_preferences/shared_preferences_platform_interface/lib/shared_preferences_platform_interface.dart b/packages/shared_preferences/shared_preferences_platform_interface/lib/shared_preferences_platform_interface.dart
index 8023c86..ced6aa5 100644
--- a/packages/shared_preferences/shared_preferences_platform_interface/lib/shared_preferences_platform_interface.dart
+++ b/packages/shared_preferences/shared_preferences_platform_interface/lib/shared_preferences_platform_interface.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 
 import 'package:flutter/foundation.dart';
+import 'package:plugin_platform_interface/plugin_platform_interface.dart';
 
 import 'method_channel_shared_preferences.dart';
 
@@ -15,7 +16,12 @@
 /// (using `extends`) ensures that the subclass will get the default implementation, while
 /// platform implementations that `implements` this interface will be broken by newly added
 /// [SharedPreferencesStorePlatform] methods.
-abstract class SharedPreferencesStorePlatform {
+abstract class SharedPreferencesStorePlatform extends PlatformInterface {
+  /// Constructs a SharedPreferencesStorePlatform.
+  SharedPreferencesStorePlatform() : super(token: _token);
+
+  static final Object _token = Object();
+
   /// The default instance of [SharedPreferencesStorePlatform] to use.
   ///
   /// Defaults to [MethodChannelSharedPreferencesStore].
@@ -23,16 +29,11 @@
 
   /// Platform-specific plugins should set this with their own platform-specific
   /// class that extends [SharedPreferencesStorePlatform] when they register themselves.
-  static set instance(SharedPreferencesStorePlatform value) {
-    if (!value.isMock) {
-      try {
-        value._verifyProvidesDefaultImplementations();
-      } on NoSuchMethodError catch (_) {
-        throw AssertionError(
-            'Platform interfaces must not be implemented with `implements`');
-      }
+  static set instance(SharedPreferencesStorePlatform instance) {
+    if (!instance.isMock) {
+      PlatformInterface.verify(instance, _token);
     }
-    _instance = value;
+    _instance = instance;
   }
 
   static SharedPreferencesStorePlatform _instance =
@@ -44,6 +45,7 @@
   /// other than mocks (see class docs). This property provides a backdoor for mockito mocks to
   /// skip the verification that the class isn't implemented with `implements`.
   @visibleForTesting
+  @Deprecated('Use MockPlatformInterfaceMixin instead')
   bool get isMock => false;
 
   /// Removes the value associated with the [key].
@@ -65,14 +67,6 @@
 
   /// Returns all key/value pairs persisted in this store.
   Future<Map<String, Object>> getAll();
-
-  // This method makes sure that SharedPreferencesStorePlatform isn't implemented with `implements`.
-  //
-  // See class doc for more details on why implementing this class is forbidden.
-  //
-  // This private method is called by the instance setter, which fails if the class is
-  // implemented with `implements`.
-  void _verifyProvidesDefaultImplementations() {}
 }
 
 /// Stores data in memory.
diff --git a/packages/shared_preferences/shared_preferences_platform_interface/pubspec.yaml b/packages/shared_preferences/shared_preferences_platform_interface/pubspec.yaml
index 9dce94c..7e4b9f0 100644
--- a/packages/shared_preferences/shared_preferences_platform_interface/pubspec.yaml
+++ b/packages/shared_preferences/shared_preferences_platform_interface/pubspec.yaml
@@ -2,7 +2,7 @@
 description: A common platform interface for the shared_preferences plugin.
 repository: https://github.com/flutter/plugins/tree/main/packages/shared_preferences/shared_preferences_platform_interface
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+shared_preferences%22
-version: 2.0.0
+version: 2.1.0
 
 environment:
   sdk: ">=2.12.0 <3.0.0"
@@ -11,6 +11,7 @@
 dependencies:
   flutter:
     sdk: flutter
+  plugin_platform_interface: ^2.1.0
 
 dev_dependencies:
   flutter_test:
diff --git a/packages/shared_preferences/shared_preferences_platform_interface/test/shared_preferences_platform_interface_test.dart b/packages/shared_preferences/shared_preferences_platform_interface/test/shared_preferences_platform_interface_test.dart
index 8efe885..ed078e8 100644
--- a/packages/shared_preferences/shared_preferences_platform_interface/test/shared_preferences_platform_interface_test.dart
+++ b/packages/shared_preferences/shared_preferences_platform_interface/test/shared_preferences_platform_interface_test.dart
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import 'package:flutter_test/flutter_test.dart';
+import 'package:plugin_platform_interface/plugin_platform_interface.dart';
 import 'package:shared_preferences_platform_interface/shared_preferences_platform_interface.dart';
 
 void main() {
@@ -10,16 +11,30 @@
 
   group(SharedPreferencesStorePlatform, () {
     test('disallows implementing interface', () {
-      expect(
-        () {
-          SharedPreferencesStorePlatform.instance = IllegalImplementation();
-        },
-        throwsAssertionError,
-      );
+      expect(() {
+        SharedPreferencesStorePlatform.instance = IllegalImplementation();
+      },
+          // In versions of `package:plugin_platform_interface` prior to fixing
+          // https://github.com/flutter/flutter/issues/109339, an attempt to
+          // implement a platform interface using `implements` would sometimes
+          // throw a `NoSuchMethodError` and other times throw an
+          // `AssertionError`. After the issue is fixed, an `AssertionError` will
+          // always be thrown. For the purpose of this test, we don't really care
+          // what exception is thrown, so just allow any exception.
+          throwsA(anything));
+    });
+
+    test('supports MockPlatformInterfaceMixin', () {
+      SharedPreferencesStorePlatform.instance = ModernMockImplementation();
+    });
+
+    test('still supports legacy isMock', () {
+      SharedPreferencesStorePlatform.instance = LegacyIsMockImplementation();
     });
   });
 }
 
+/// An implementation using `implements` that isn't a mock, which isn't allowed.
 class IllegalImplementation implements SharedPreferencesStorePlatform {
   // Intentionally declare self as not a mock to trigger the
   // compliance check.
@@ -46,3 +61,55 @@
     throw UnimplementedError();
   }
 }
+
+class LegacyIsMockImplementation implements SharedPreferencesStorePlatform {
+  @override
+  bool get isMock => true;
+
+  @override
+  Future<bool> clear() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<Map<String, Object>> getAll() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<bool> remove(String key) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<bool> setValue(String valueType, String key, Object value) {
+    throw UnimplementedError();
+  }
+}
+
+class ModernMockImplementation
+    with MockPlatformInterfaceMixin
+    implements SharedPreferencesStorePlatform {
+  @override
+  bool get isMock => false;
+
+  @override
+  Future<bool> clear() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<Map<String, Object>> getAll() {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<bool> remove(String key) {
+    throw UnimplementedError();
+  }
+
+  @override
+  Future<bool> setValue(String valueType, String key, Object value) {
+    throw UnimplementedError();
+  }
+}