Revert "Re-enable AAR plugins when an AndroidX failure occurred (#40810)" (#41042)

This reverts commit 96482eeb5ce5a88e260d53cc513a34800c0817de.
diff --git a/dev/bots/test.dart b/dev/bots/test.dart
index e375213..1d2cdc8 100644
--- a/dev/bots/test.dart
+++ b/dev/bots/test.dart
@@ -1022,7 +1022,6 @@
     await _runDevicelabTest('gradle_plugin_fat_apk_test', env: env);
     await _runDevicelabTest('gradle_r8_test', env: env);
     await _runDevicelabTest('gradle_non_android_plugin_test', env: env);
-    await _runDevicelabTest('gradle_jetifier_test', env: env);
   }
   if (subShard == 'gradle2') {
     await _runDevicelabTest('gradle_plugin_bundle_test', env: env);
diff --git a/dev/devicelab/bin/tasks/gradle_jetifier_test.dart b/dev/devicelab/bin/tasks/gradle_jetifier_test.dart
index 86ee0ed..bbabfc2 100644
--- a/dev/devicelab/bin/tasks/gradle_jetifier_test.dart
+++ b/dev/devicelab/bin/tasks/gradle_jetifier_test.dart
@@ -64,7 +64,6 @@
           options: <String>[
             'apk',
             '--target-platform', 'android-arm',
-            '--no-shrink',
             '--verbose',
           ],
         );
@@ -101,9 +100,7 @@
           options: <String>[
             'apk',
             '--target-platform', 'android-arm',
-            '--debug',
-            '--no-shrink',
-            '--verbose',
+            '--debug', '--verbose',
           ],
         );
       });
diff --git a/packages/flutter_tools/gradle/aar_init_script.gradle b/packages/flutter_tools/gradle/aar_init_script.gradle
index 4874aa2..2439da8 100644
--- a/packages/flutter_tools/gradle/aar_init_script.gradle
+++ b/packages/flutter_tools/gradle/aar_init_script.gradle
@@ -7,7 +7,6 @@
 // destination of the local repository.
 // The local repository will contain the AAR and POM files.
 
-import java.nio.file.Paths
 import org.gradle.api.Project
 import org.gradle.api.artifacts.Configuration
 import org.gradle.api.artifacts.maven.MavenDeployer
@@ -40,32 +39,16 @@
             }
         }
     }
-    if (!project.property("is-plugin").toBoolean()) {
-        return
-    }
-    if (project.hasProperty('localEngineOut')) {
-        // TODO(egarciad): Support local engine.
-        // This most likely requires refactoring `flutter.gradle`, so the logic can be reused.
-        throw new GradleException(
-            "Local engine isn't supported when building the plugins as AAR. " +
-            "See: https://github.com/flutter/flutter/issues/40866")
-    }
-
-    // This is a Flutter plugin project. Plugin projects don't apply the Flutter Gradle plugin,
-    // as a result, add the dependency on the embedding.
-    project.repositories {
-        maven {
-            url "http://download.flutter.io"
-        }
-    }
-    String engineVersion = Paths.get(getFlutterRoot(project), "bin", "internal", "engine.version")
-        .toFile().text.trim()
-    project.dependencies {
-        // Add the embedding dependency.
-        compileOnly ("io.flutter:flutter_embedding_release:1.0.0-$engineVersion") {
-            // We only need to expose io.flutter.plugin.*
-            // No need for the embedding transitive dependencies.
-            transitive = false
+    // Check if the project uses the Flutter plugin (defined in flutter.gradle).
+    Boolean usesFlutterPlugin = project.plugins.find { it.class.name == "FlutterPlugin" } != null
+    if (!usesFlutterPlugin) {
+        project.dependencies {
+            // Some plugins don't include `annotations` and they don't set
+            // `android.useAndroidX=true` in `gradle.properties`.
+            compileOnly "androidx.annotation:annotation:+"
+            compileOnly "com.android.support:support-annotations:+"
+            // The Flutter plugin already adds `flutter.jar`.
+            compileOnly project.files("${getFlutterRoot(project)}/bin/cache/artifacts/engine/android-arm-release/flutter.jar")
         }
     }
 }
diff --git a/packages/flutter_tools/gradle/flutter.gradle b/packages/flutter_tools/gradle/flutter.gradle
index 606d3a3..c1067bc 100644
--- a/packages/flutter_tools/gradle/flutter.gradle
+++ b/packages/flutter_tools/gradle/flutter.gradle
@@ -8,8 +8,6 @@
 import com.android.build.OutputFile
 import java.nio.file.Path
 import java.nio.file.Paths
-import java.util.regex.Matcher
-import java.util.regex.Pattern
 import org.apache.tools.ant.taskdefs.condition.Os
 import org.gradle.api.DefaultTask
 import org.gradle.api.GradleException
@@ -258,65 +256,29 @@
      */
     private void configurePlugins() {
         if (!buildPluginAsAar()) {
-            getPluginList().each this.&configurePluginProject
+            getPluginList().each this.&configurePlugin
             return
         }
-        if (useLocalEngine()) {
-            throw new GradleException("Local engine isn't supported when building the plugins as AAR")
-        }
-        List<Project> projects = [project]
-        // Module projects set the `hostProjects` extra property in `include_flutter.groovy`.
-        // This is required to set the local repository in each host app project.
-        if (project.ext.has("hostProjects")) {
-            projects.addAll(project.ext.get("hostProjects"))
-        }
-        // Configure the repository for the plugins.
-        projects.each { hostProject ->
-            hostProject.repositories {
-                maven {
-                    url "${getPluginBuildDir()}/outputs/repo"
-                }
+        addPluginTasks()
+        List<String> tasksToExecute = project.gradle.startParameter.taskNames
+        Set buildTypes = getBuildTypesForTasks(tasksToExecute)
+        if (tasksToExecute.contains("clean")) {
+            // Because the plugins are built during configuration, the task "clean"
+            // cannot run in conjunction with an assembly task.
+            if (!buildTypes.empty) {
+                throw new GradleException("Can't run the clean task along with other assemble tasks")
             }
         }
-        getPluginList().each { pluginName, pluginPath ->
-            configurePluginAar(pluginName, pluginPath, project)
+        // Build plugins when a task "assembly*" will be called later.
+        if (!buildTypes.empty) {
+            // Build the plugin during configuration.
+            // This is required when Jetifier is enabled, otherwise the implementation dependency
+            // cannot be added.
+            buildAarPlugins(buildTypes)
         }
     }
 
-    private static final Pattern GROUP_PATTERN = ~/group\s+\'(.+)\'/
-    private static final Pattern PROJECT_NAME_PATTERN = ~/rootProject\.name\s+=\s+\'(.+)\'/
-
-    // Adds the plugin AAR dependency to the app project.
-    private void configurePluginAar(String pluginName, String pluginPath, Project project) {
-        // Extract the group id from the plugin's build.gradle.
-        // This is `group '<group-id>'`
-        File pluginBuildFile = project.file(Paths.get(pluginPath, "android", "build.gradle"));
-        if (!pluginBuildFile.exists()) {
-            throw new GradleException("Plugin $pluginName doesn't have the required file $pluginBuildFile.")
-        }
-
-        Matcher groupParts = GROUP_PATTERN.matcher(pluginBuildFile.text)
-        assert groupParts.count == 1
-        assert groupParts.hasGroup()
-        String groupId = groupParts[0][1]
-
-        // Extract the artifact name from the plugin's settings.gradle.
-        // This is `rootProject.name = '<artifact-name>'`
-        File pluginSettings = project.file(Paths.get(pluginPath, "android", "settings.gradle"));
-        if (!pluginSettings.exists()) {
-            throw new GradleException("Plugin $pluginName doesn't have the required file $pluginSettings.")
-        }
-        Matcher projectNameParts = PROJECT_NAME_PATTERN.matcher(pluginSettings.text)
-        assert projectNameParts.count == 1
-        assert projectNameParts.hasGroup()
-        String artifactId = "${projectNameParts[0][1]}_release"
-
-        assert !groupId.empty
-        project.dependencies.add("api", "$groupId:$artifactId:+")
-    }
-
-    // Adds the plugin project dependency to the app project .
-    private void configurePluginProject(String name, String _) {
+    private void configurePlugin(String name, String _) {
         Project pluginProject = project.rootProject.findProject(":$name")
         if (pluginProject == null) {
             project.logger.error("Plugin project :$name not found. Please update settings.gradle.")
@@ -381,6 +343,93 @@
         return androidPlugins
     }
 
+    private void addPluginTasks() {
+        Properties plugins = getPluginList()
+        project.android.buildTypes.each { buildType ->
+            plugins.each { name, path ->
+                String buildModeValue = buildType.debuggable ? "debug" : "release"
+                List<String> taskNameParts = ["build", "plugin", buildModeValue]
+                taskNameParts.addAll(name.split("_"))
+                String taskName = toCammelCase(taskNameParts)
+                // Build types can be extended. For example, a build type can extend the `debug` mode.
+                // In such cases, prevent creating the same task.
+                if (project.tasks.findByName(taskName) == null) {
+                    project.tasks.create(name: taskName, type: FlutterPluginTask) {
+                        flutterExecutable this.flutterExecutable
+                        buildMode buildModeValue
+                        verbose isVerbose()
+                        pluginDir project.file(path)
+                        sourceDir project.file(project.flutter.source)
+                        intermediateDir getPluginBuildDir()
+                    }
+                }
+            }
+        }
+    }
+
+    private void buildAarPlugins(Set buildTypes) {
+        List<Project> projects = [project]
+        // Module projects set the `hostProjects` extra property in `include_flutter.groovy`.
+        // This is required to set the local repository in each host app project.
+        if (project.ext.has("hostProjects")) {
+            projects.addAll(project.ext.get("hostProjects"))
+        }
+        projects.each { hostProject ->
+            hostProject.repositories {
+                maven {
+                    url "${getPluginBuildDir()}/outputs/repo"
+                }
+            }
+        }
+        buildTypes.each { buildType ->
+            project.tasks.withType(FlutterPluginTask).all { pluginTask ->
+                String buildMode = buildType.debuggable ? "debug" : "release"
+                if (pluginTask.buildMode != buildMode) {
+                    return
+                }
+                pluginTask.execute()
+                pluginTask.intermediateDir.eachFileRecurse(FILES) { file ->
+                    if (file.name != "maven-metadata.xml") {
+                        return
+                    }
+                    def mavenMetadata = new XmlParser().parse(file)
+                    String groupId = mavenMetadata.groupId.text()
+                    String artifactId = mavenMetadata.artifactId.text()
+
+                    if (!artifactId.endsWith(buildMode)) {
+                        return
+                    }
+                    // Add the plugin dependency based on the Maven metadata.
+                    addApiDependencies(project, buildType.name, "$groupId:$artifactId:+@aar", {
+                        transitive = true
+                    })
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns a set with the build type names that apply to the given list of tasks
+     * required to configure the plugin dependencies.
+     */
+    private Set getBuildTypesForTasks(List<String> tasksToExecute) {
+        Set buildTypes = []
+        tasksToExecute.each { task ->
+            project.android.buildTypes.each { buildType ->
+                if (task == "androidDependencies" || task.endsWith("dependencies")) {
+                    // The tasks to query the dependencies includes all the build types.
+                    buildTypes.add(buildType)
+                } else if (task.endsWith("assemble")) {
+                    // The `assemble` task includes all the build types.
+                    buildTypes.add(buildType)
+                } else if (task.endsWith(buildType.name.capitalize())) {
+                    buildTypes.add(buildType)
+                }
+            }
+        }
+        return buildTypes
+    }
+
     private static String toCammelCase(List<String> parts) {
         if (parts.empty) {
             return ""
@@ -878,3 +927,56 @@
         buildBundle()
     }
 }
+
+class FlutterPluginTask extends DefaultTask {
+    File flutterExecutable
+    @Optional @Input
+    Boolean verbose
+    @Input
+    String buildMode
+    @Input
+    File pluginDir
+    @Input
+    File intermediateDir
+    File sourceDir
+
+    @InputFiles
+    FileCollection getSourceFiles() {
+        return project.fileTree(
+            dir: sourceDir,
+            exclude: ["android", "ios"],
+            include: ["pubspec.yaml"]
+        )
+    }
+
+    @OutputDirectory
+    File getOutputDirectory() {
+        return intermediateDir
+    }
+
+    @TaskAction
+    void build() {
+        intermediateDir.mkdirs()
+        project.exec {
+            executable flutterExecutable.absolutePath
+            workingDir pluginDir
+            args "build", "aar"
+            args "--quiet"
+            args "--suppress-analytics"
+            args "--output-dir", "${intermediateDir}"
+            switch (buildMode) {
+                case 'release':
+                    args "--release"
+                    break
+                case 'debug':
+                    args "--debug"
+                    break
+                default:
+                    assert false
+            }
+            if (verbose) {
+                args "--verbose"
+            }
+        }
+    }
+}
diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart
index dfeca8a..f383329 100644
--- a/packages/flutter_tools/lib/src/android/gradle.dart
+++ b/packages/flutter_tools/lib/src/android/gradle.dart
@@ -22,6 +22,7 @@
 import '../base/version.dart';
 import '../build_info.dart';
 import '../cache.dart';
+import '../features.dart';
 import '../flutter_manifest.dart';
 import '../globals.dart';
 import '../project.dart';
@@ -46,20 +47,18 @@
     return _cachedExecutable;
   }
 
-  final Map<FlutterProject, GradleProject> _cachedAppProject =
-    <FlutterProject, GradleProject>{};
-  /// Gets the [GradleProject] for the [project] if built as an app.
-  Future<GradleProject> getAppProject(FlutterProject project) async {
-    _cachedAppProject[project] ??= await _readGradleProject(project, isLibrary: false);
-    return _cachedAppProject[project];
+  GradleProject _cachedAppProject;
+  /// Gets the [GradleProject] for the current [FlutterProject] if built as an app.
+  Future<GradleProject> get appProject async {
+    _cachedAppProject ??= await _readGradleProject(isLibrary: false);
+    return _cachedAppProject;
   }
 
-  final Map<FlutterProject, GradleProject> _cachedLibraryProject =
-    <FlutterProject, GradleProject>{};
-  /// Gets the [GradleProject] for the [project] if built as a library.
-  Future<GradleProject> getLibraryProject(FlutterProject project) async {
-    _cachedLibraryProject[project] ??= await _readGradleProject(project, isLibrary: true);
-    return _cachedLibraryProject[project];
+  GradleProject _cachedLibraryProject;
+  /// Gets the [GradleProject] for the current [FlutterProject] if built as a library.
+  Future<GradleProject> get libraryProject async {
+    _cachedLibraryProject ??= await _readGradleProject(isLibrary: true);
+    return _cachedLibraryProject;
   }
 }
 
@@ -134,8 +133,7 @@
     case FlutterPluginVersion.managed:
       // Fall through. The managed plugin matches plugin v2 for now.
     case FlutterPluginVersion.v2:
-      final GradleProject gradleProject =
-          await gradleUtils.getAppProject(FlutterProject.current());
+      final GradleProject gradleProject = await gradleUtils.appProject;
       return fs.file(gradleProject.apkDirectory.childFile('app.apk'));
   }
   return null;
@@ -211,10 +209,8 @@
 
 // Note: Dependencies are resolved and possibly downloaded as a side-effect
 // of calculating the app properties using Gradle. This may take minutes.
-Future<GradleProject> _readGradleProject(
-  FlutterProject flutterProject, {
-  bool isLibrary = false,
-}) async {
+Future<GradleProject> _readGradleProject({bool isLibrary = false}) async {
+  final FlutterProject flutterProject = FlutterProject.current();
   final String gradlew = await gradleUtils.getExecutable(flutterProject);
 
   updateLocalProperties(project: flutterProject);
@@ -222,6 +218,10 @@
   final FlutterManifest manifest = flutterProject.manifest;
   final Directory hostAppGradleRoot = flutterProject.android.hostAppGradleRoot;
 
+  if (featureFlags.isPluginAsAarEnabled &&
+      !manifest.isPlugin && !manifest.isModule) {
+    createSettingsAarGradle(hostAppGradleRoot);
+  }
   if (manifest.isPlugin) {
     assert(isLibrary);
     return GradleProject(
@@ -581,9 +581,9 @@
 
   GradleProject gradleProject;
   if (manifest.isModule) {
-    gradleProject = await gradleUtils.getAppProject(project);
+    gradleProject = await gradleUtils.appProject;
   } else if (manifest.isPlugin) {
-    gradleProject = await gradleUtils.getLibraryProject(project);
+    gradleProject = await gradleUtils.libraryProject;
   } else {
     throwToolExit('AARs can only be built for plugin or module projects.');
   }
@@ -612,11 +612,13 @@
     '-Pflutter-root=$flutterRoot',
     '-Poutput-dir=${gradleProject.buildDirectory}',
     '-Pis-plugin=${manifest.isPlugin}',
+    '-Dbuild-plugins-as-aars=true',
   ];
 
   if (target != null && target.isNotEmpty) {
     command.add('-Ptarget=$target');
   }
+
   if (androidBuildInfo.targetArchs.isNotEmpty) {
     final String targetPlatforms = androidBuildInfo.targetArchs
         .map(getPlatformNameForAndroidArch).join(',');
@@ -631,30 +633,34 @@
   command.add(aarTask);
 
   final Stopwatch sw = Stopwatch()..start();
-  RunResult result;
+  int exitCode = 1;
+
   try {
-    result = await processUtils.run(
+    exitCode = await processUtils.stream(
       command,
       workingDirectory: project.android.hostAppGradleRoot.path,
       allowReentrantFlutter: true,
       environment: gradleEnv,
+      mapFunction: (String line) {
+        // Always print the full line in verbose mode.
+        if (logger.isVerbose) {
+          return line;
+        }
+        return null;
+      },
     );
   } finally {
     status.stop();
   }
-  flutterUsage.sendTiming('build', 'gradle-aar', sw.elapsed);
+  flutterUsage.sendTiming('build', 'gradle-aar', Duration(milliseconds: sw.elapsedMilliseconds));
 
-  if (result.exitCode != 0) {
-    printStatus(result.stdout, wrap: false);
-    printError(result.stderr, wrap: false);
-    throwToolExit('Gradle task $aarTask failed with exit code $exitCode.', exitCode: exitCode);
+  if (exitCode != 0) {
+    throwToolExit('Gradle task $aarTask failed with exit code $exitCode', exitCode: exitCode);
   }
 
   final Directory repoDirectory = gradleProject.repoDirectory;
   if (!repoDirectory.existsSync()) {
-    printStatus(result.stdout, wrap: false);
-    printError(result.stderr, wrap: false);
-    throwToolExit('Gradle task $aarTask failed to produce $repoDirectory.', exitCode: exitCode);
+    throwToolExit('Gradle task $aarTask failed to produce $repoDirectory', exitCode: exitCode);
   }
   printStatus('Built ${fs.path.relative(repoDirectory.path)}.', color: TerminalColor.green);
 }
@@ -724,33 +730,21 @@
   FlutterProject flutterProject,
   AndroidBuildInfo androidBuildInfo,
   String target,
-  bool isBuildingBundle, {
-  bool shouldBuildPluginAsAar = false,
-}) async {
+  bool isBuildingBundle,
+) async {
   final String gradlew = await gradleUtils.getExecutable(flutterProject);
-  final GradleProject gradleProject = await gradleUtils.getAppProject(flutterProject);
-
-  if (shouldBuildPluginAsAar) {
-    // Create a settings.gradle that doesn't import the plugins as subprojects.
-    createSettingsAarGradle(flutterProject.android.hostAppGradleRoot);
-    await buildPluginsAsAar(
-      flutterProject,
-      androidBuildInfo,
-      buildDirectory: gradleProject.buildDirectory,
-    );
-  }
-
+  final GradleProject project = await gradleUtils.appProject;
   final BuildInfo buildInfo = androidBuildInfo.buildInfo;
 
   String assembleTask;
 
   if (isBuildingBundle) {
-    assembleTask = gradleProject.bundleTaskFor(buildInfo);
+    assembleTask = project.bundleTaskFor(buildInfo);
   } else {
-    assembleTask = gradleProject.assembleTaskFor(buildInfo);
+    assembleTask = project.assembleTaskFor(buildInfo);
   }
   if (assembleTask == null) {
-    printUndefinedTask(gradleProject, buildInfo);
+    printUndefinedTask(project, buildInfo);
     throwToolExit('Gradle build aborted.');
   }
   final Status status = logger.startProgress(
@@ -797,12 +791,13 @@
         .map(getPlatformNameForAndroidArch).join(',');
     command.add('-Ptarget-platform=$targetPlatforms');
   }
-  if (shouldBuildPluginAsAar) {
+  if (featureFlags.isPluginAsAarEnabled) {
      // Pass a system flag instead of a project flag, so this flag can be
      // read from include_flutter.groovy.
     command.add('-Dbuild-plugins-as-aars=true');
-    // Don't use settings.gradle from the current project since it includes the plugins as subprojects.
-    command.add('--settings-file=settings_aar.gradle');
+    if (!flutterProject.manifest.isModule) {
+      command.add('--settings-file=settings_aar.gradle');
+    }
   }
   command.add(assembleTask);
   bool potentialAndroidXFailure = false;
@@ -849,60 +844,24 @@
       printStatus('To learn more, see: https://developer.android.com/studio/build/shrink-code', indent: 4);
       BuildEvent('r8-failure').send();
     } else if (potentialAndroidXFailure) {
-      final bool hasPlugins = flutterProject.flutterPluginsFile.existsSync();
-      final bool usesAndroidX = isAppUsingAndroidX(flutterProject.android.hostAppGradleRoot);
-      if (!hasPlugins) {
-        // If the app doesn't use any plugin, then it's unclear where the incompatibility is coming from.
-        BuildEvent('android-x-failure', eventError: 'app-not-using-plugins').send();
-      }
-      if (hasPlugins && !usesAndroidX) {
-        // If the app isn't using AndroidX, then the app is likely using a plugin already migrated to AndroidX.
-        printStatus('AndroidX incompatibilities may have caused this build to fail. ');
-        printStatus('Please migrate your app to AndroidX. See https://goo.gl/CP92wY.');
-        BuildEvent('android-x-failure', eventError: 'app-not-using-androidx').send();
-      }
-      if (hasPlugins && usesAndroidX && shouldBuildPluginAsAar) {
-        // This is a dependency conflict instead of an AndroidX failure since by this point
-        // the app is using AndroidX, the plugins are built as AARs, Jetifier translated
-        // Support libraries for AndroidX equivalents.
-        BuildEvent('android-x-failure', eventError: 'using-jetifier').send();
-      }
-      if (hasPlugins && usesAndroidX && !shouldBuildPluginAsAar) {
-        printStatus(
-          'The built failed likely due to AndroidX incompatibilities in a plugin. '
-          'The tool is about to try using Jetfier to solve the incompatibility.'
-        );
-        BuildEvent('android-x-failure', eventError: 'not-using-jetifier').send();
-        // The app is using Androidx, but Jetifier hasn't run yet.
-        // Call the current method again, build the plugins as AAR, so Jetifier can translate
-        // the dependencies.
-        // NOTE: Don't build the plugins as AARs by default since this drastically increases
-        // the build time.
-        await _buildGradleProjectV2(
-          flutterProject,
-          androidBuildInfo,
-          target,
-          isBuildingBundle,
-          shouldBuildPluginAsAar: true,
-        );
-        return;
-      }
+      printStatus('AndroidX incompatibilities may have caused this build to fail. See https://goo.gl/CP92wY.');
+      BuildEvent('android-x-failure').send();
     }
     throwToolExit('Gradle task $assembleTask failed with exit code $exitCode', exitCode: exitCode);
   }
   flutterUsage.sendTiming('build', 'gradle-v2', Duration(milliseconds: sw.elapsedMilliseconds));
 
   if (!isBuildingBundle) {
-    final Iterable<File> apkFiles = findApkFiles(gradleProject, androidBuildInfo);
+    final Iterable<File> apkFiles = findApkFiles(project, androidBuildInfo);
     if (apkFiles.isEmpty) {
       throwToolExit('Gradle build failed to produce an Android package.');
     }
     // Copy the first APK to app.apk, so `flutter run`, `flutter install`, etc. can find it.
     // TODO(blasten): Handle multiple APKs.
-    apkFiles.first.copySync(gradleProject.apkDirectory.childFile('app.apk').path);
+    apkFiles.first.copySync(project.apkDirectory.childFile('app.apk').path);
 
-    printTrace('calculateSha: ${gradleProject.apkDirectory}/app.apk');
-    final File apkShaFile = gradleProject.apkDirectory.childFile('app.apk.sha1');
+    printTrace('calculateSha: ${project.apkDirectory}/app.apk');
+    final File apkShaFile = project.apkDirectory.childFile('app.apk.sha1');
     apkShaFile.writeAsStringSync(_calculateSha(apkFiles.first));
 
     for (File apkFile in apkFiles) {
@@ -916,7 +875,7 @@
           color: TerminalColor.green);
     }
   } else {
-    final File bundleFile = findBundleFile(gradleProject, buildInfo);
+    final File bundleFile = findBundleFile(project, buildInfo);
     if (bundleFile == null) {
       throwToolExit('Gradle build failed to produce an Android bundle package.');
     }
@@ -932,61 +891,6 @@
   }
 }
 
-/// Returns [true] if the current app uses AndroidX.
-// TODO(egarciad): https://github.com/flutter/flutter/issues/40800
-// Remove `FlutterManifest.usesAndroidX` and provide a unified `AndroidProject.usesAndroidX`.
-@visibleForTesting
-bool isAppUsingAndroidX(Directory androidDirectory) {
-  final File properties = androidDirectory.childFile('gradle.properties');
-  if (!properties.existsSync()) {
-    return false;
-  }
-  return properties.readAsStringSync().contains('android.useAndroidX=true');
-}
-
-/// Builds the plugins as AARs.
-@visibleForTesting
-Future<void> buildPluginsAsAar(
-  FlutterProject flutterProject,
-  AndroidBuildInfo androidBuildInfo, {
-  String buildDirectory,
-}) async {
-  final File flutterPluginFile = flutterProject.flutterPluginsFile;
-  if (!flutterPluginFile.existsSync()) {
-    return;
-  }
-  final List<String> plugins = flutterPluginFile.readAsStringSync().split('\n');
-  for (String plugin in plugins) {
-    final List<String> pluginParts = plugin.split('=');
-    if (pluginParts.length != 2) {
-      continue;
-    }
-    final Directory pluginDirectory = fs.directory(pluginParts.last);
-    assert(pluginDirectory.existsSync());
-
-    final String pluginName = pluginParts.first;
-    logger.printStatus('Building plugin $pluginName...');
-    try {
-      await buildGradleAar(
-        project: FlutterProject.fromDirectory(pluginDirectory),
-        androidBuildInfo: const AndroidBuildInfo(
-          BuildInfo(
-            BuildMode.release, // Plugins are built as release.
-            null, // Plugins don't define flavors.
-          ),
-        ),
-        target: '',
-        outputDir: buildDirectory,
-      );
-    } on ToolExit {
-      // Log the entire plugin entry in `.flutter-plugins` since it
-      // includes the plugin name and the version.
-      BuildEvent('plugin-aar-failure', eventError: plugin).send();
-      throwToolExit('The plugin $pluginName could not be built due to the issue above. ');
-    }
-  }
-}
-
 @visibleForTesting
 Iterable<File> findApkFiles(GradleProject project, AndroidBuildInfo androidBuildInfo) {
   final Iterable<String> apkFileNames = project.apkFilesFor(androidBuildInfo);
diff --git a/packages/flutter_tools/lib/src/features.dart b/packages/flutter_tools/lib/src/features.dart
index 1701267..cdb1313 100644
--- a/packages/flutter_tools/lib/src/features.dart
+++ b/packages/flutter_tools/lib/src/features.dart
@@ -36,6 +36,9 @@
   /// Whether flutter desktop for Windows is enabled.
   bool get isWindowsEnabled => _isEnabled(flutterWindowsDesktopFeature);
 
+  /// Whether plugins are built as AARs in app projects.
+  bool get isPluginAsAarEnabled => _isEnabled(flutterBuildPluginAsAarFeature);
+
   // Calculate whether a particular feature is enabled for the current channel.
   static bool _isEnabled(Feature feature) {
     final String currentChannel = FlutterVersion.instance.channel;
diff --git a/packages/flutter_tools/lib/src/reporting/events.dart b/packages/flutter_tools/lib/src/reporting/events.dart
index 99def6b..8a73f51 100644
--- a/packages/flutter_tools/lib/src/reporting/events.dart
+++ b/packages/flutter_tools/lib/src/reporting/events.dart
@@ -125,7 +125,6 @@
   BuildEvent(String parameter, {
     this.command,
     this.settings,
-    this.eventError,
   }) : super(
     'build' +
       (FlutterCommand.current == null ? '' : '-${FlutterCommand.current.name}'),
@@ -133,7 +132,6 @@
 
   final String command;
   final String settings;
-  final String eventError;
 
   @override
   void send() {
@@ -142,8 +140,6 @@
         CustomDimensions.buildEventCommand: command,
       if (settings != null)
         CustomDimensions.buildEventSettings: settings,
-      if (eventError != null)
-        CustomDimensions.buildEventError: eventError,
     });
     flutterUsage.sendEvent(category, parameter, parameters: parameters);
   }
diff --git a/packages/flutter_tools/lib/src/reporting/usage.dart b/packages/flutter_tools/lib/src/reporting/usage.dart
index a3d225d..0f33c97 100644
--- a/packages/flutter_tools/lib/src/reporting/usage.dart
+++ b/packages/flutter_tools/lib/src/reporting/usage.dart
@@ -53,7 +53,6 @@
   commandBuildApkSplitPerAbi, // cd40
   commandBuildAppBundleTargetPlatform, // cd41
   commandBuildAppBundleBuildMode, // cd42
-  buildEventError,  // cd43
 }
 
 String cdKey(CustomDimensions cd) => 'cd${cd.index + 1}';
diff --git a/packages/flutter_tools/test/general.shard/android/gradle_test.dart b/packages/flutter_tools/test/general.shard/android/gradle_test.dart
index 4450e6d..1ab626d 100644
--- a/packages/flutter_tools/test/general.shard/android/gradle_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/gradle_test.dart
@@ -25,6 +25,7 @@
 
 import '../../src/common.dart';
 import '../../src/context.dart';
+import '../../src/mocks.dart';
 import '../../src/pubspec_schema.dart';
 
 void main() {
@@ -1154,153 +1155,6 @@
     });
   });
 
-  group('isAppUsingAndroidX', () {
-    FileSystem fs;
-
-    setUp(() {
-      fs = MemoryFileSystem();
-    });
-
-    testUsingContext('returns true when the project is using AndroidX', () async {
-      final Directory androidDirectory = fs.systemTempDirectory.createTempSync('android.');
-
-      androidDirectory
-        .childFile('gradle.properties')
-        .writeAsStringSync('android.useAndroidX=true');
-
-      expect(isAppUsingAndroidX(androidDirectory), isTrue);
-
-    }, overrides: <Type, Generator>{
-      FileSystem: () => fs,
-    });
-
-    testUsingContext('returns false when the project is not using AndroidX', () async {
-      final Directory androidDirectory = fs.systemTempDirectory.createTempSync('android.');
-
-      androidDirectory
-        .childFile('gradle.properties')
-        .writeAsStringSync('android.useAndroidX=false');
-
-      expect(isAppUsingAndroidX(androidDirectory), isFalse);
-
-    }, overrides: <Type, Generator>{
-      FileSystem: () => fs,
-    });
-
-    testUsingContext('returns false when gradle.properties does not exist', () async {
-      final Directory androidDirectory = fs.systemTempDirectory.createTempSync('android.');
-
-      expect(isAppUsingAndroidX(androidDirectory), isFalse);
-
-    }, overrides: <Type, Generator>{
-      FileSystem: () => fs,
-    });
-  });
-
-  group('buildPluginsAsAar', () {
-    FileSystem fs;
-    MockProcessManager mockProcessManager;
-    MockAndroidSdk mockAndroidSdk;
-
-    setUp(() {
-      fs = MemoryFileSystem();
-
-      mockProcessManager = MockProcessManager();
-      when(mockProcessManager.run(
-        any,
-        workingDirectory: anyNamed('workingDirectory'),
-        environment: anyNamed('environment'),
-      )).thenAnswer((_) async => ProcessResult(1, 0, '', ''));
-
-      mockAndroidSdk = MockAndroidSdk();
-      when(mockAndroidSdk.directory).thenReturn('irrelevant');
-    });
-
-    testUsingContext('calls gradle', () async {
-      final Directory androidDirectory = fs.directory('android.');
-      androidDirectory.createSync();
-      androidDirectory
-        .childFile('pubspec.yaml')
-        .writeAsStringSync('name: irrelevant');
-
-      final Directory plugin1 = fs.directory('plugin1.');
-      plugin1
-        ..createSync()
-        ..childFile('pubspec.yaml')
-        .writeAsStringSync('''
-name: irrelevant
-flutter:
-  plugin:
-    androidPackage: irrelevant
-''');
-      final Directory plugin2 = fs.directory('plugin2.');
-      plugin2
-        ..createSync()
-        ..childFile('pubspec.yaml')
-        .writeAsStringSync('''
-name: irrelevant
-flutter:
-  plugin:
-    androidPackage: irrelevant
-''');
-
-      androidDirectory
-        .childFile('.flutter-plugins')
-        .writeAsStringSync('''
-plugin1=${plugin1.path}
-plugin2=${plugin2.path}
-''');
-      final Directory buildDirectory = androidDirectory.childDirectory('build');
-      buildDirectory
-        .childDirectory('outputs')
-        .childDirectory('repo')
-        .createSync(recursive: true);
-
-      await buildPluginsAsAar(
-        FlutterProject.fromPath(androidDirectory.path),
-        const AndroidBuildInfo(BuildInfo.release),
-        buildDirectory: buildDirectory.path,
-      );
-
-      final String flutterRoot = fs.path.absolute(Cache.flutterRoot);
-      final String initScript = fs.path.join(flutterRoot, 'packages',
-          'flutter_tools', 'gradle', 'aar_init_script.gradle');
-      verify(mockProcessManager.run(
-        <String>[
-          'gradlew',
-          '-I=$initScript',
-          '-Pflutter-root=$flutterRoot',
-          '-Poutput-dir=${buildDirectory.path}',
-          '-Pis-plugin=true',
-          '-Ptarget-platform=android-arm,android-arm64',
-          'assembleAarRelease',
-        ],
-        environment: anyNamed('environment'),
-        workingDirectory: plugin1.childDirectory('android').path),
-      ).called(1);
-
-      verify(mockProcessManager.run(
-        <String>[
-          'gradlew',
-          '-I=$initScript',
-          '-Pflutter-root=$flutterRoot',
-          '-Poutput-dir=${buildDirectory.path}',
-          '-Pis-plugin=true',
-          '-Ptarget-platform=android-arm,android-arm64',
-          'assembleAarRelease',
-        ],
-        environment: anyNamed('environment'),
-        workingDirectory: plugin2.childDirectory('android').path),
-      ).called(1);
-
-    }, overrides: <Type, Generator>{
-      AndroidSdk: () => mockAndroidSdk,
-      FileSystem: () => fs,
-      GradleUtils: () => FakeGradleUtils(),
-      ProcessManager: () => mockProcessManager,
-    });
-  });
-
   group('gradle build', () {
     MockAndroidSdk mockAndroidSdk;
     MockAndroidStudio mockAndroidStudio;
@@ -1381,13 +1235,11 @@
       fs.currentDirectory = 'path/to/project';
 
       // Let any process start. Assert after.
-      when(mockProcessManager.run(
+      when(mockProcessManager.start(
         any,
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory'))
-      ).thenAnswer(
-          (_) async => ProcessResult(1, 0, '', ''),
-      );
+      ).thenAnswer((Invocation invocation) => Future<Process>.value(MockProcess()));
       fs.directory('build/outputs/repo').createSync(recursive: true);
 
       await buildGradleAar(
@@ -1397,11 +1249,11 @@
         target: ''
       );
 
-      final List<String> actualGradlewCall = verify(mockProcessManager.run(
+      final List<String> actualGradlewCall = verify(mockProcessManager.start(
         captureAny,
         environment: anyNamed('environment'),
         workingDirectory: anyNamed('workingDirectory')),
-      ).captured.last;
+      ).captured.single;
 
       expect(actualGradlewCall, contains('/path/to/project/.android/gradlew'));
       expect(actualGradlewCall, contains('-PlocalEngineOut=out/android_arm'));
@@ -1432,14 +1284,6 @@
   return FakePlatform.fromPlatform(const LocalPlatform())..operatingSystem = name;
 }
 
-class FakeGradleUtils extends GradleUtils {
-  @override
-  Future<String> getExecutable(FlutterProject project) async {
-    return 'gradlew';
-  }
-}
-
-class MockAndroidSdk extends Mock implements AndroidSdk {}
 class MockAndroidStudio extends Mock implements AndroidStudio {}
 class MockDirectory extends Mock implements Directory {}
 class MockFile extends Mock implements File {}
diff --git a/packages/flutter_tools/test/general.shard/features_test.dart b/packages/flutter_tools/test/general.shard/features_test.dart
index a7c978e..3594a6e 100644
--- a/packages/flutter_tools/test/general.shard/features_test.dart
+++ b/packages/flutter_tools/test/general.shard/features_test.dart
@@ -432,6 +432,21 @@
 
       expect(featureFlags.isWindowsEnabled, false);
     }));
+
+    /// Plugins as AARS
+    test('plugins built as AARs with config on master', () => testbed.run(() {
+      when(mockFlutterVerion.channel).thenReturn('master');
+      when<bool>(mockFlutterConfig.getValue('enable-build-plugin-as-aar')).thenReturn(false);
+
+      expect(featureFlags.isPluginAsAarEnabled, false);
+    }));
+
+    test('plugins built as AARs with config on dev', () => testbed.run(() {
+      when(mockFlutterVerion.channel).thenReturn('dev');
+      when<bool>(mockFlutterConfig.getValue('enable-build-plugin-as-aar')).thenReturn(false);
+
+      expect(featureFlags.isPluginAsAarEnabled, false);
+    }));
   });
 }
 
diff --git a/packages/flutter_tools/test/src/testbed.dart b/packages/flutter_tools/test/src/testbed.dart
index c73a808..446d111 100644
--- a/packages/flutter_tools/test/src/testbed.dart
+++ b/packages/flutter_tools/test/src/testbed.dart
@@ -693,6 +693,7 @@
     this.isMacOSEnabled = false,
     this.isWebEnabled = false,
     this.isWindowsEnabled = false,
+    this.isPluginAsAarEnabled = false,
 });
 
   @override
@@ -706,4 +707,7 @@
 
   @override
   final bool isWindowsEnabled;
+
+  @override
+  final bool isPluginAsAarEnabled;
 }