Add buildNumber param to "flutter build aar" command (#46291)

diff --git a/packages/flutter_tools/gradle/aar_init_script.gradle b/packages/flutter_tools/gradle/aar_init_script.gradle
index 01aea1f..2e9a341 100644
--- a/packages/flutter_tools/gradle/aar_init_script.gradle
+++ b/packages/flutter_tools/gradle/aar_init_script.gradle
@@ -20,15 +20,20 @@
 
     project.apply plugin: "maven"
 
-    project.android.libraryVariants.all { variant ->
-        addAarTask(project, variant)
-    }
     // Snapshot versions include the timestamp in the artifact name.
     // Therefore, remove the snapshot part, so new runs of `flutter build aar` overrides existing artifacts.
     // This version isn't relevant in Flutter since the pub version is used
     // to resolve dependencies.
     project.version = project.version.replace("-SNAPSHOT", "")
 
+    if (project.hasProperty("buildNumber")) {
+        project.version = project.property("buildNumber")
+    }
+
+    project.android.libraryVariants.all { variant ->
+        addAarTask(project, variant)
+    }
+    
     project.uploadArchives {
         repositories {
             mavenDeployer {
@@ -39,6 +44,7 @@
     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.
diff --git a/packages/flutter_tools/lib/src/android/android_builder.dart b/packages/flutter_tools/lib/src/android/android_builder.dart
index ed061aa..50e2f1b 100644
--- a/packages/flutter_tools/lib/src/android/android_builder.dart
+++ b/packages/flutter_tools/lib/src/android/android_builder.dart
@@ -29,6 +29,7 @@
     @required Set<AndroidBuildInfo> androidBuildInfo,
     @required String target,
     @required String outputDirectoryPath,
+    @required String buildNumber,
   });
 
   /// Builds an APK artifact.
@@ -57,6 +58,7 @@
     @required Set<AndroidBuildInfo> androidBuildInfo,
     @required String target,
     @required String outputDirectoryPath,
+    @required String buildNumber,
   }) async {
     try {
       Directory outputDirectory =
@@ -71,6 +73,7 @@
           androidBuildInfo: androidBuildInfo,
           target: target,
           outputDirectory: outputDirectory,
+          buildNumber: buildNumber,
         );
       }
       printHowToConsumeAar(
@@ -80,6 +83,7 @@
           }).toSet(),
         androidPackage: project.manifest.androidPackage,
         repoDirectory: getRepoDirectory(outputDirectory),
+        buildNumber: buildNumber,
       );
     } finally {
       androidSdk.reinitialize();
diff --git a/packages/flutter_tools/lib/src/android/gradle.dart b/packages/flutter_tools/lib/src/android/gradle.dart
index 4440d98..649c5ea 100644
--- a/packages/flutter_tools/lib/src/android/gradle.dart
+++ b/packages/flutter_tools/lib/src/android/gradle.dart
@@ -477,11 +477,13 @@
 /// * [project] is typically [FlutterProject.current()].
 /// * [androidBuildInfo] is the build configuration.
 /// * [outputDir] is the destination of the artifacts,
+/// * [buildNumber] is the build number of the output aar,
 Future<void> buildGradleAar({
   @required FlutterProject project,
   @required AndroidBuildInfo androidBuildInfo,
   @required String target,
   @required Directory outputDirectory,
+  @required String buildNumber,
 }) async {
   assert(project != null);
   assert(target != null);
@@ -491,6 +493,7 @@
   if (androidSdk == null) {
     exitWithNoSdkMessage();
   }
+
   final FlutterManifest manifest = project.manifest;
   if (!manifest.isModule && !manifest.isPlugin) {
     throwToolExit('AARs can only be built for plugin or module projects.');
@@ -517,6 +520,7 @@
     '-Pflutter-root=$flutterRoot',
     '-Poutput-dir=${outputDirectory.path}',
     '-Pis-plugin=${manifest.isPlugin}',
+    '-PbuildNumber=$buildNumber'
   ];
 
   if (target != null && target.isNotEmpty) {
@@ -587,10 +591,12 @@
   @required Set<String> buildModes,
   @required String androidPackage,
   @required Directory repoDirectory,
+  String buildNumber,
 }) {
   assert(buildModes != null && buildModes.isNotEmpty);
   assert(androidPackage != null);
   assert(repoDirectory != null);
+  buildNumber ??= '1.0';
 
   printStatus('''
 
@@ -613,7 +619,7 @@
 
   for (String buildMode in buildModes) {
     printStatus('''
-      ${buildMode}Implementation '$androidPackage:flutter_$buildMode:1.0''');
+      ${buildMode}Implementation '$androidPackage:flutter_$buildMode:$buildNumber''');
   }
 
 printStatus('''
@@ -721,6 +727,7 @@
         ),
         target: '',
         outputDirectory: buildDirectory,
+        buildNumber: '1.0'
       );
     } on ToolExit {
       // Log the entire plugin entry in `.flutter-plugins` since it
diff --git a/packages/flutter_tools/lib/src/commands/build_aar.dart b/packages/flutter_tools/lib/src/commands/build_aar.dart
index 1394504..96c7c1c 100644
--- a/packages/flutter_tools/lib/src/commands/build_aar.dart
+++ b/packages/flutter_tools/lib/src/commands/build_aar.dart
@@ -33,6 +33,7 @@
         help: 'Build a release version of the current project.',
       );
     usesFlavorOption();
+    usesBuildNumberOption();
     usesPubOption();
     argParser
       ..addMultiOption(
@@ -85,17 +86,22 @@
   @override
   Future<FlutterCommandResult> runCommand() async {
     final Set<AndroidBuildInfo> androidBuildInfo = <AndroidBuildInfo>{};
-    final Iterable<AndroidArch> targetArchitectures = stringsArg('target-platform')
-      .map<AndroidArch>(getAndroidArchForName);
+
+    final Iterable<AndroidArch> targetArchitectures =
+        stringsArg('target-platform').map<AndroidArch>(getAndroidArchForName);
+
+    final String buildNumber = argParser.options.containsKey('build-number')
+      && stringArg('build-number') != null
+      && stringArg('build-number').isNotEmpty
+      ? stringArg('build-number')
+      : '1.0';
 
     for (String buildMode in const <String>['debug', 'profile', 'release']) {
       if (boolArg(buildMode)) {
-        androidBuildInfo.add(
-          AndroidBuildInfo(
-            BuildInfo(BuildMode.fromName(buildMode), stringArg('flavor')),
-            targetArchs: targetArchitectures,
-          )
-        );
+        androidBuildInfo.add(AndroidBuildInfo(
+          BuildInfo(BuildMode.fromName(buildMode), stringArg('flavor')),
+          targetArchs: targetArchitectures,
+        ));
       }
     }
     if (androidBuildInfo.isEmpty) {
@@ -106,6 +112,7 @@
       target: '', // Not needed because this command only builds Android's code.
       androidBuildInfo: androidBuildInfo,
       outputDirectoryPath: stringArg('output-dir'),
+      buildNumber: buildNumber,
     );
     return null;
   }
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 8317c06..1df1a2c 100644
--- a/packages/flutter_tools/test/general.shard/android/gradle_test.dart
+++ b/packages/flutter_tools/test/general.shard/android/gradle_test.dart
@@ -936,6 +936,7 @@
           '-Pflutter-root=$flutterRoot',
           '-Poutput-dir=${buildDirectory.path}',
           '-Pis-plugin=true',
+          '-PbuildNumber=1.0',
           '-Ptarget-platform=android-arm,android-arm64,android-x64',
           'assembleAarRelease',
         ],
@@ -950,6 +951,7 @@
           '-Pflutter-root=$flutterRoot',
           '-Poutput-dir=${buildDirectory.path}',
           '-Pis-plugin=true',
+          '-PbuildNumber=1.0',
           '-Ptarget-platform=android-arm,android-arm64,android-x64',
           'assembleAarRelease',
         ],
@@ -1548,6 +1550,7 @@
         project: FlutterProject.current(),
         outputDirectory: fs.directory('build/'),
         target: '',
+        buildNumber: '1.0',
       );
 
       expect(
@@ -1710,6 +1713,7 @@
         project: FlutterProject.current(),
         outputDirectory: fs.directory('build/'),
         target: '',
+        buildNumber: '2.0',
       );
 
       final List<String> actualGradlewCall = verify(
@@ -1724,6 +1728,7 @@
       expect(actualGradlewCall, contains('-Plocal-engine-out=out/android_arm'));
       expect(actualGradlewCall, contains('-Plocal-engine-repo=/.tmp_rand0/flutter_tool_local_engine_repo.rand0'));
       expect(actualGradlewCall, contains('-Plocal-engine-build-mode=release'));
+      expect(actualGradlewCall, contains('-PbuildNumber=2.0'));
 
     }, overrides: <Type, Generator>{
       AndroidSdk: () => mockAndroidSdk,
@@ -1742,6 +1747,7 @@
         buildModes: const <String>{'release', 'debug', 'profile'},
         androidPackage: 'com.mycompany',
         repoDirectory: fs.directory('build/'),
+        buildNumber: '2.2',
       );
 
       expect(
@@ -1764,9 +1770,9 @@
           '  3. Make the host app depend on the Flutter module:\n'
           '\n'
           '    dependencies {\n'
-          '      releaseImplementation \'com.mycompany:flutter_release:1.0\n'
-          '      debugImplementation \'com.mycompany:flutter_debug:1.0\n'
-          '      profileImplementation \'com.mycompany:flutter_profile:1.0\n'
+          '      releaseImplementation \'com.mycompany:flutter_release:2.2\n'
+          '      debugImplementation \'com.mycompany:flutter_debug:2.2\n'
+          '      profileImplementation \'com.mycompany:flutter_profile:2.2\n'
           '    }\n'
           '\n'
           '\n'
@@ -1872,6 +1878,7 @@
         buildModes: const <String>{'profile'},
         androidPackage: 'com.mycompany',
         repoDirectory: fs.directory('build/'),
+        buildNumber: '1.0',
       );
 
       expect(
diff --git a/packages/flutter_tools/test/src/android_common.dart b/packages/flutter_tools/test/src/android_common.dart
index e7d4220..c156d5a 100644
--- a/packages/flutter_tools/test/src/android_common.dart
+++ b/packages/flutter_tools/test/src/android_common.dart
@@ -16,6 +16,7 @@
     @required Set<AndroidBuildInfo> androidBuildInfo,
     @required String target,
     @required String outputDirectoryPath,
+    @required String buildNumber,
   }) async {}
 
   @override