Add `.flutter-plugins-dependencies` to the project, which contains the app's plugin dependency graph (#45379)

diff --git a/.gitignore b/.gitignore
index b48f326..c407f64 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,7 @@
 **/doc/api/
 .dart_tool/
 .flutter-plugins
+.flutter-plugins-dependencies
 .packages
 .pub-cache/
 .pub/
diff --git a/dev/integration_tests/android_embedding_v2_smoke_test/.gitignore b/dev/integration_tests/android_embedding_v2_smoke_test/.gitignore
index 437cb45..ae1f183 100644
--- a/dev/integration_tests/android_embedding_v2_smoke_test/.gitignore
+++ b/dev/integration_tests/android_embedding_v2_smoke_test/.gitignore
@@ -24,6 +24,7 @@
 **/doc/api/
 .dart_tool/
 .flutter-plugins
+.flutter-plugins-dependencies
 .packages
 .pub-cache/
 .pub/
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/.gitignore b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/.gitignore
index 05fc69b..2b1f495 100644
--- a/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/.gitignore
+++ b/dev/integration_tests/android_splash_screens/splash_screen_kitchen_sink/.gitignore
@@ -27,6 +27,7 @@
 **/doc/api/
 .dart_tool/
 .flutter-plugins
+.flutter-plugins-dependencies
 .packages
 .pub-cache/
 .pub/
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/.gitignore b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/.gitignore
index 716b5a9..7391168 100644
--- a/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/.gitignore
+++ b/dev/integration_tests/android_splash_screens/splash_screen_load_rotate/.gitignore
@@ -24,6 +24,7 @@
 **/doc/api/
 .dart_tool/
 .flutter-plugins
+.flutter-plugins-dependencies
 .packages
 .pub-cache/
 .pub/
diff --git a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/.gitignore b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/.gitignore
index 716b5a9..7391168 100644
--- a/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/.gitignore
+++ b/dev/integration_tests/android_splash_screens/splash_screen_trans_rotate/.gitignore
@@ -24,6 +24,7 @@
 **/doc/api/
 .dart_tool/
 .flutter-plugins
+.flutter-plugins-dependencies
 .packages
 .pub-cache/
 .pub/
diff --git a/dev/integration_tests/ios_add2app/flutterapp/.gitignore b/dev/integration_tests/ios_add2app/flutterapp/.gitignore
index cdecf14..86f4691 100644
--- a/dev/integration_tests/ios_add2app/flutterapp/.gitignore
+++ b/dev/integration_tests/ios_add2app/flutterapp/.gitignore
@@ -39,3 +39,4 @@
 .android/
 .ios/
 .flutter-plugins
+.flutter-plugins-dependencies
diff --git a/dev/integration_tests/release_smoke_test/.gitignore b/dev/integration_tests/release_smoke_test/.gitignore
index 716b5a9..7391168 100644
--- a/dev/integration_tests/release_smoke_test/.gitignore
+++ b/dev/integration_tests/release_smoke_test/.gitignore
@@ -24,6 +24,7 @@
 **/doc/api/
 .dart_tool/
 .flutter-plugins
+.flutter-plugins-dependencies
 .packages
 .pub-cache/
 .pub/
diff --git a/packages/flutter_tools/gradle/flutter.gradle b/packages/flutter_tools/gradle/flutter.gradle
index 45dc4e3..173ba30 100644
--- a/packages/flutter_tools/gradle/flutter.gradle
+++ b/packages/flutter_tools/gradle/flutter.gradle
@@ -6,6 +6,7 @@
 
 import com.android.builder.model.AndroidProject
 import com.android.build.OutputFile
+import groovy.json.JsonSlurper
 import java.nio.file.Path
 import java.nio.file.Paths
 import java.util.regex.Matcher
@@ -253,6 +254,7 @@
     private void configurePlugins() {
         if (!buildPluginAsAar()) {
             getPluginList().each this.&configurePluginProject
+            getPluginDependencies().each this.&configurePluginDependencies
             return
         }
         project.repositories {
@@ -298,19 +300,15 @@
     }
 
     // Adds the plugin project dependency to the app project .
-    private void configurePluginProject(String name, String _) {
-        Project pluginProject = project.rootProject.findProject(":$name")
+    private void configurePluginProject(String pluginName, String _) {
+        Project pluginProject = project.rootProject.findProject(":$pluginName")
         if (pluginProject == null) {
-            project.logger.error("Plugin project :$name not found. Please update settings.gradle.")
+            project.logger.error("Plugin project :$pluginName not found. Please update settings.gradle.")
             return
         }
         // Add plugin dependency to the app project.
         project.dependencies {
-            if (project.getConfigurations().findByName("implementation")) {
-                implementation pluginProject
-            } else {
-                compile pluginProject
-            }
+            implementation pluginProject
         }
         Closure addEmbeddingCompileOnlyDependency = { buildType ->
             String flutterBuildMode = buildModeFor(buildType)
@@ -337,6 +335,36 @@
         }
     }
 
+    // Add the dependencies on other plugin projects to the plugin project.
+    // A plugin A can depend on plugin B. As a result, this dependency must be surfaced by
+    // making the Gradle plugin project A depend on the Gradle plugin project B.
+    private void configurePluginDependencies(Object dependencyObject) {
+        assert dependencyObject.name instanceof String
+        Project pluginProject = project.rootProject.findProject(":${dependencyObject.name}")
+        if (pluginProject == null) {
+            // Ignore plugins that don't have a project since most likely they don't
+            // have an android/ directory.
+            return
+        }
+        assert dependencyObject.dependencies instanceof List
+        dependencyObject.dependencies.each { pluginDependencyName ->
+            assert pluginDependencyName instanceof String
+            if (pluginDependencyName.empty) {
+                return
+            }
+            Project dependencyProject = project.rootProject.findProject(":$pluginDependencyName")
+            if (dependencyProject == null) {
+                return
+            }
+            // Wait for the Android plugin to load and add the dependency to the plugin project.
+            pluginProject.afterEvaluate {
+                pluginProject.dependencies {
+                    implementation dependencyProject
+                }
+            }
+        }
+    }
+
     private Properties getPluginList() {
         File pluginsFile = new File(project.projectDir.parentFile.parentFile, '.flutter-plugins')
         Properties allPlugins = readPropertiesIfExist(pluginsFile)
@@ -353,6 +381,39 @@
         return androidPlugins
     }
 
+    // Gets the plugins dependencies from `.flutter-plugins-dependencies`.
+    private List getPluginDependencies() {
+        // Consider a `.flutter-plugins-dependencies` file with the following content:
+        // {
+        //     "dependencyGraph": [
+        //       {
+        //         "name": "plugin-a",
+        //         "dependencies": ["plugin-b","plugin-c"]
+        //       },
+        //       {
+        //         "name": "plugin-b",
+        //         "dependencies": ["plugin-c"]
+        //       },
+        //       {
+        //         "name": "plugin-c",
+        //         "dependencies": []'
+        //       }
+        //     ]
+        //  }
+        //
+        // This means, `plugin-a` depends on `plugin-b` and `plugin-c`.
+        // `plugin-b` depends on `plugin-c`.
+        // `plugin-c` doesn't depend on anything.
+        File pluginsDependencyFile = new File(project.projectDir.parentFile.parentFile, '.flutter-plugins-dependencies')
+        if (pluginsDependencyFile.exists()) {
+            def object = new JsonSlurper().parseText(pluginsDependencyFile.text)
+            assert object instanceof Map
+            assert object.dependencyGraph instanceof List
+            return object.dependencyGraph
+        }
+        return []
+    }
+
     private static String toCammelCase(List<String> parts) {
         if (parts.empty) {
             return ""
diff --git a/packages/flutter_tools/lib/src/plugins.dart b/packages/flutter_tools/lib/src/plugins.dart
index 2be328c..7e9b124 100644
--- a/packages/flutter_tools/lib/src/plugins.dart
+++ b/packages/flutter_tools/lib/src/plugins.dart
@@ -4,12 +4,14 @@
 
 import 'dart:async';
 
+import 'package:meta/meta.dart';
 import 'package:mustache/mustache.dart' as mustache;
 import 'package:yaml/yaml.dart';
 
 import 'android/gradle.dart';
 import 'base/common.dart';
 import 'base/file_system.dart';
+import 'convert.dart';
 import 'dart/package_map.dart';
 import 'features.dart';
 import 'globals.dart';
@@ -27,10 +29,14 @@
 
 class Plugin {
   Plugin({
-    this.name,
-    this.path,
-    this.platforms,
-  });
+    @required this.name,
+    @required this.path,
+    @required this.platforms,
+    @required this.dependencies,
+  }) : assert(name != null),
+       assert(path != null),
+       assert(platforms != null),
+       assert(dependencies != null);
 
   /// Parses [Plugin] specification from the provided pluginYaml.
   ///
@@ -60,18 +66,28 @@
   ///            pluginClass: SamplePlugin
   ///          windows:
   ///            pluginClass: SamplePlugin
-  factory Plugin.fromYaml(String name, String path, YamlMap pluginYaml) {
+  factory Plugin.fromYaml(
+    String name,
+    String path,
+    YamlMap pluginYaml,
+    List<String> dependencies,
+  ) {
     final List<String> errors = validatePluginYaml(pluginYaml);
     if (errors.isNotEmpty) {
       throwToolExit('Invalid plugin specification.\n${errors.join('\n')}');
     }
     if (pluginYaml != null && pluginYaml['platforms'] != null) {
-      return Plugin._fromMultiPlatformYaml(name, path, pluginYaml);
+      return Plugin._fromMultiPlatformYaml(name, path, pluginYaml, dependencies);
     }
-    return Plugin._fromLegacyYaml(name, path, pluginYaml);
+    return Plugin._fromLegacyYaml(name, path, pluginYaml, dependencies);
   }
 
-  factory Plugin._fromMultiPlatformYaml(String name, String path, dynamic pluginYaml) {
+  factory Plugin._fromMultiPlatformYaml(
+    String name,
+    String path,
+    dynamic pluginYaml,
+    List<String> dependencies,
+  ) {
     assert (pluginYaml != null && pluginYaml['platforms'] != null,
             'Invalid multi-platform plugin specification.');
     final YamlMap platformsYaml = pluginYaml['platforms'] as YamlMap;
@@ -118,10 +134,16 @@
       name: name,
       path: path,
       platforms: platforms,
+      dependencies: dependencies,
     );
   }
 
-  factory Plugin._fromLegacyYaml(String name, String path, dynamic pluginYaml) {
+  factory Plugin._fromLegacyYaml(
+    String name,
+    String path,
+    dynamic pluginYaml,
+    List<String> dependencies,
+  ) {
     final Map<String, PluginPlatform> platforms = <String, PluginPlatform>{};
     final String pluginClass = pluginYaml['pluginClass'] as String;
     if (pluginYaml != null && pluginClass != null) {
@@ -147,6 +169,7 @@
       name: name,
       path: path,
       platforms: platforms,
+      dependencies: dependencies,
     );
   }
 
@@ -232,6 +255,9 @@
   final String name;
   final String path;
 
+  /// The name of the packages this plugin depends on.
+  final List<String> dependencies;
+
   /// This is a mapping from platform config key to the plugin platform spec.
   final Map<String, PluginPlatform> platforms;
 }
@@ -250,11 +276,13 @@
     return null;
   }
   final String packageRootPath = fs.path.fromUri(packageRoot);
+  final YamlMap dependencies = pubspec['dependencies'];
   printTrace('Found plugin $name at $packageRootPath');
   return Plugin.fromYaml(
     name,
     packageRootPath,
     flutterConfig['plugin'] as YamlMap,
+    dependencies == null ? <String>[] : <String>[...dependencies.keys],
   );
 }
 
@@ -281,29 +309,58 @@
   return plugins;
 }
 
-/// Returns true if .flutter-plugins has changed, otherwise returns false.
+/// Writes the .flutter-plugins and .flutter-plugins-dependencies files based on the list of plugins.
+/// If there aren't any plugins, then the files aren't written to disk.
+///
+/// Finally, returns [true] if .flutter-plugins or .flutter-plugins-dependencies have changed,
+/// otherwise returns [false].
 bool _writeFlutterPluginsList(FlutterProject project, List<Plugin> plugins) {
+  final List<dynamic> directAppDependencies = <dynamic>[];
+  final StringBuffer flutterPluginsBuffer = StringBuffer();
+
+  final Set<String> pluginNames = <String>{};
+  for (Plugin plugin in plugins) {
+    pluginNames.add(plugin.name);
+  }
+  for (Plugin plugin in plugins) {
+    flutterPluginsBuffer.write('${plugin.name}=${escapePath(plugin.path)}\n');
+    directAppDependencies.add(<String, dynamic>{
+      'name': plugin.name,
+      // Extract the plugin dependencies which happen to be plugins.
+      'dependencies': <String>[...plugin.dependencies.where(pluginNames.contains)],
+    });
+  }
   final File pluginsFile = project.flutterPluginsFile;
-  final String oldContents = _readFlutterPluginsList(project);
-  final String pluginManifest =
-      plugins.map<String>((Plugin p) => '${p.name}=${escapePath(p.path)}').join('\n');
-  if (pluginManifest.isNotEmpty) {
-    pluginsFile.writeAsStringSync('$pluginManifest\n', flush: true);
+  final String oldPluginFileContent = _readFileContent(pluginsFile);
+  final String pluginFileContent = flutterPluginsBuffer.toString();
+  if (pluginFileContent.isNotEmpty) {
+    pluginsFile.writeAsStringSync(pluginFileContent, flush: true);
   } else {
     if (pluginsFile.existsSync()) {
       pluginsFile.deleteSync();
     }
   }
-  final String newContents = _readFlutterPluginsList(project);
-  return oldContents != newContents;
+
+  final File dependenciesFile = project.flutterPluginsDependenciesFile;
+  final String oldDependenciesFileContent = _readFileContent(dependenciesFile);
+  final String dependenciesFileContent = json.encode(<String, dynamic>{
+      'dependencyGraph': directAppDependencies,
+    });
+  if (pluginFileContent.isNotEmpty) {
+    dependenciesFile.writeAsStringSync(dependenciesFileContent, flush: true);
+  } else {
+    if (dependenciesFile.existsSync()) {
+      dependenciesFile.deleteSync();
+    }
+  }
+
+  return oldPluginFileContent != _readFileContent(pluginsFile)
+      || oldDependenciesFileContent != _readFileContent(dependenciesFile);
 }
 
-/// Returns the contents of the `.flutter-plugins` file in [project], or
-/// null if that file does not exist.
-String _readFlutterPluginsList(FlutterProject project) {
-  return project.flutterPluginsFile.existsSync()
-      ? project.flutterPluginsFile.readAsStringSync()
-      : null;
+/// Returns the contents of [File] or [null] if that file does not exist.
+String _readFileContent(File file) {
+  return file.existsSync() ? file.readAsStringSync() : null;
 }
 
 const String _androidPluginRegistryTemplateOldEmbedding = '''package io.flutter.plugins;
@@ -782,5 +839,5 @@
 ///
 /// Assumes [refreshPluginsList] has been called since last change to `pubspec.yaml`.
 bool hasPlugins(FlutterProject project) {
-  return _readFlutterPluginsList(project) != null;
+  return _readFileContent(project.flutterPluginsFile) != null;
 }
diff --git a/packages/flutter_tools/lib/src/project.dart b/packages/flutter_tools/lib/src/project.dart
index 6751ab6..2da69f1 100644
--- a/packages/flutter_tools/lib/src/project.dart
+++ b/packages/flutter_tools/lib/src/project.dart
@@ -146,6 +146,10 @@
   /// The `.flutter-plugins` file of this project.
   File get flutterPluginsFile => directory.childFile('.flutter-plugins');
 
+  /// The `.flutter-plugins-dependencies` file of this project,
+  /// which contains the dependencies each plugin depends on.
+  File get flutterPluginsDependenciesFile => directory.childFile('.flutter-plugins-dependencies');
+
   /// The `.dart-tool` directory of this project.
   Directory get dartTool => directory.childDirectory('.dart_tool');
 
diff --git a/packages/flutter_tools/templates/app/.gitignore.tmpl b/packages/flutter_tools/templates/app/.gitignore.tmpl
index 437cb45..ae1f183 100644
--- a/packages/flutter_tools/templates/app/.gitignore.tmpl
+++ b/packages/flutter_tools/templates/app/.gitignore.tmpl
@@ -24,6 +24,7 @@
 **/doc/api/
 .dart_tool/
 .flutter-plugins
+.flutter-plugins-dependencies
 .packages
 .pub-cache/
 .pub/
diff --git a/packages/flutter_tools/templates/module/common/.gitignore.tmpl b/packages/flutter_tools/templates/module/common/.gitignore.tmpl
index cdecf14..86f4691 100644
--- a/packages/flutter_tools/templates/module/common/.gitignore.tmpl
+++ b/packages/flutter_tools/templates/module/common/.gitignore.tmpl
@@ -39,3 +39,4 @@
 .android/
 .ios/
 .flutter-plugins
+.flutter-plugins-dependencies
diff --git a/packages/flutter_tools/templates/package/.gitignore.tmpl b/packages/flutter_tools/templates/package/.gitignore.tmpl
index 6ffedae..bb431f0 100644
--- a/packages/flutter_tools/templates/package/.gitignore.tmpl
+++ b/packages/flutter_tools/templates/package/.gitignore.tmpl
@@ -24,6 +24,7 @@
 **/doc/api/
 .dart_tool/
 .flutter-plugins
+.flutter-plugins-dependencies
 .packages
 .pub-cache/
 .pub/
diff --git a/packages/flutter_tools/test/general.shard/plugin_parsing_test.dart b/packages/flutter_tools/test/general.shard/plugin_parsing_test.dart
index ea91679..8f96ebb 100644
--- a/packages/flutter_tools/test/general.shard/plugin_parsing_test.dart
+++ b/packages/flutter_tools/test/general.shard/plugin_parsing_test.dart
@@ -20,7 +20,7 @@
 
       final dynamic pluginYaml = loadYaml(pluginYamlRaw);
       final Plugin plugin =
-          Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml);
+          Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml, const <String>[]);
 
       final AndroidPlugin androidPlugin =
           plugin.platforms[AndroidPlugin.kConfigKey];
@@ -53,7 +53,7 @@
 
       final dynamic pluginYaml = loadYaml(pluginYamlRaw);
       final Plugin plugin =
-          Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml);
+          Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml, const <String>[]);
 
       final AndroidPlugin androidPlugin =
           plugin.platforms[AndroidPlugin.kConfigKey];
@@ -100,7 +100,7 @@
 
       final dynamic pluginYaml = loadYaml(pluginYamlRaw);
       final Plugin plugin =
-      Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml);
+      Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml, const <String>[]);
 
       final AndroidPlugin androidPlugin =
       plugin.platforms[AndroidPlugin.kConfigKey];
@@ -144,7 +144,7 @@
 
       final dynamic pluginYaml = loadYaml(pluginYamlRaw);
       final Plugin plugin =
-      Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml);
+      Plugin.fromYaml(_kTestPluginName, _kTestPluginPath, pluginYaml, const <String>[]);
 
       expect(plugin.platforms, <String, PluginPlatform> {});
     });
diff --git a/packages/flutter_tools/test/general.shard/plugins_test.dart b/packages/flutter_tools/test/general.shard/plugins_test.dart
index 802d8034..5d35408 100644
--- a/packages/flutter_tools/test/general.shard/plugins_test.dart
+++ b/packages/flutter_tools/test/general.shard/plugins_test.dart
@@ -9,7 +9,7 @@
 import 'package:flutter_tools/src/ios/xcodeproj.dart';
 import 'package:flutter_tools/src/plugins.dart';
 import 'package:flutter_tools/src/project.dart';
-
+import 'package:meta/meta.dart';
 import 'package:mockito/mockito.dart';
 
 import '../src/common.dart';
@@ -32,7 +32,8 @@
       // Add basic properties to the Flutter project and subprojects
       flutterProject = MockFlutterProject();
       when(flutterProject.directory).thenReturn(fs.directory('/'));
-      when(flutterProject.flutterPluginsFile).thenReturn(flutterProject.directory.childFile('.plugins'));
+      when(flutterProject.flutterPluginsFile).thenReturn(flutterProject.directory.childFile('.flutter-plugins'));
+      when(flutterProject.flutterPluginsDependenciesFile).thenReturn(flutterProject.directory.childFile('.flutter-plugins-dependencies'));
       iosProject = MockIosProject();
       when(flutterProject.ios).thenReturn(iosProject);
       when(iosProject.pluginRegistrantHost).thenReturn(flutterProject.directory.childDirectory('Runner'));
@@ -189,6 +190,37 @@
         );
     }
 
+    void createPluginWithDependencies({
+      @required String name,
+      @required List<String> dependencies,
+    }) {
+      assert(name != null);
+      assert(dependencies != null);
+
+      final Directory pluginDirectory = fs.systemTempDirectory.createTempSync('plugin.');
+      pluginDirectory
+        .childFile('pubspec.yaml')
+        .writeAsStringSync('''
+name: $name
+flutter:
+  plugin:
+    androidPackage: plugin2
+    pluginClass: UseNewEmbedding
+dependencies:
+''');
+      for (String dependency in dependencies) {
+        pluginDirectory
+          .childFile('pubspec.yaml')
+          .writeAsStringSync('  $dependency:\n', mode: FileMode.append);
+      }
+      flutterProject.directory
+        .childFile('.packages')
+        .writeAsStringSync(
+          '$name:${pluginDirectory.childDirectory('lib').uri.toString()}\n',
+          mode: FileMode.append,
+        );
+    }
+
     // Creates the files that would indicate that pod install has run for the
     // given project.
     void simulatePodInstallRun(XcodeBasedProject project) {
@@ -199,6 +231,7 @@
       testUsingContext('Refreshing the plugin list is a no-op when the plugins list stays empty', () {
         refreshPluginsList(flutterProject);
         expect(flutterProject.flutterPluginsFile.existsSync(), false);
+        expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), false);
       }, overrides: <Type, Generator>{
         FileSystem: () => fs,
         ProcessManager: () => FakeProcessManager.any(),
@@ -210,6 +243,7 @@
         when(macosProject.existsSync()).thenReturn(false);
         refreshPluginsList(flutterProject);
         expect(flutterProject.flutterPluginsFile.existsSync(), false);
+        expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), false);
       }, overrides: <Type, Generator>{
         FileSystem: () => fs,
         ProcessManager: () => FakeProcessManager.any(),
@@ -221,6 +255,47 @@
         when(macosProject.existsSync()).thenReturn(false);
         refreshPluginsList(flutterProject);
         expect(flutterProject.flutterPluginsFile.existsSync(), true);
+        expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true);
+      }, overrides: <Type, Generator>{
+        FileSystem: () => fs,
+        ProcessManager: () => FakeProcessManager.any(),
+      });
+
+      testUsingContext('Refreshing the plugin list modifies .flutter-plugins and .flutter-plugins-dependencies when there are plugins', () {
+        createPluginWithDependencies(name: 'plugin-a', dependencies: const <String>['plugin-b', 'plugin-c', 'random-package']);
+        createPluginWithDependencies(name: 'plugin-b', dependencies: const <String>['plugin-c']);
+        createPluginWithDependencies(name: 'plugin-c', dependencies: const <String>[]);
+        when(iosProject.existsSync()).thenReturn(false);
+        when(macosProject.existsSync()).thenReturn(false);
+
+        refreshPluginsList(flutterProject);
+
+        expect(flutterProject.flutterPluginsFile.existsSync(), true);
+        expect(flutterProject.flutterPluginsDependenciesFile.existsSync(), true);
+        expect(flutterProject.flutterPluginsFile.readAsStringSync(),
+          'plugin-a=/.tmp_rand0/plugin.rand0/\n'
+          'plugin-b=/.tmp_rand0/plugin.rand1/\n'
+          'plugin-c=/.tmp_rand0/plugin.rand2/\n'
+          ''
+        );
+        expect(flutterProject.flutterPluginsDependenciesFile.readAsStringSync(),
+          '{'
+            '"dependencyGraph":['
+              '{'
+                '"name":"plugin-a",'
+                '"dependencies":["plugin-b","plugin-c"]'
+              '},'
+              '{'
+                '"name":"plugin-b",'
+                '"dependencies":["plugin-c"]'
+              '},'
+              '{'
+                '"name":"plugin-c",'
+                '"dependencies":[]'
+              '}'
+            ']'
+          '}'
+        );
       }, overrides: <Type, Generator>{
         FileSystem: () => fs,
         ProcessManager: () => FakeProcessManager.any(),