aapt2: Add a new flag '--revision-code'

A new flag to inject revisionCode into the manifest for cts splits tests.

Bug: 174338944
Test: atest aapt2_tests
Change-Id: If5a089f37233f53af3012ca5eab17fab21eafd9c
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index 852b1244..768b4b2 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -190,8 +190,11 @@
     AddOptionalFlag("--version-name",
         "Version name to inject into the AndroidManifest.xml if none is present.",
         &options_.manifest_fixer_options.version_name_default);
+    AddOptionalFlag("--revision-code",
+        "Revision code (integer) to inject into the AndroidManifest.xml if none is\n"
+            "present.", &options_.manifest_fixer_options.revision_code_default);
     AddOptionalSwitch("--replace-version",
-        "If --version-code and/or --version-name are specified, these\n"
+        "If --version-code, --version-name, and/or --revision-code are specified, these\n"
             "values will replace any value already in the manifest. By\n"
             "default, nothing is changed if the manifest already defines\n"
             "these attributes.",
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index c03661c..8abd9de 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -367,6 +367,16 @@
       }
     }
 
+    if (options_.revision_code_default) {
+      if (options_.replace_version) {
+        el->RemoveAttribute(xml::kSchemaAndroid, "revisionCode");
+      }
+      if (el->FindAttribute(xml::kSchemaAndroid, "revisionCode") == nullptr) {
+        el->attributes.push_back(xml::Attribute{xml::kSchemaAndroid, "revisionCode",
+                                                options_.revision_code_default.value()});
+      }
+    }
+
     return true;
   });
 
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index ec4367b..34ad8d5 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -60,6 +60,10 @@
   // replace_version is set.
   Maybe<std::string> version_code_major_default;
 
+  // The revision code to set if 'android:revisionCode' is not defined in <manifest> or if
+  // replace_version is set.
+  Maybe<std::string> revision_code_default;
+
   // The version of the framework being compiled against to set for 'android:compileSdkVersion' in
   // the <manifest> tag.
   Maybe<std::string> compile_sdk_version;
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 781ff7b..432f10b 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -445,6 +445,66 @@
   EXPECT_THAT(attr->value, StrEq("0x20000000"));
 }
 
+TEST_F(ManifestFixerTest, UseDefaultRevisionCode) {
+  ManifestFixerOptions options;
+  options.revision_code_default = std::string("0x10000000");
+
+  std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+      <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+                package="android"
+                android:versionCode="0x00000001" />)EOF",
+                                                            options);
+  ASSERT_THAT(doc, NotNull());
+
+  xml::Element* manifest_el = doc->root.get();
+  ASSERT_THAT(manifest_el, NotNull());
+
+  xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x10000000"));
+}
+
+TEST_F(ManifestFixerTest, DontUseDefaultRevisionCode) {
+  ManifestFixerOptions options;
+  options.revision_code_default = std::string("0x10000000");
+
+  std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+                  package="android"
+                  android:versionCode="0x00000001"
+                  android:revisionCode="0x00000002" />)EOF",
+                                                            options);
+  ASSERT_THAT(doc, NotNull());
+
+  xml::Element* manifest_el = doc->root.get();
+  ASSERT_THAT(manifest_el, NotNull());
+
+  xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x00000002"));
+}
+
+TEST_F(ManifestFixerTest, ReplaceRevisionCode) {
+  ManifestFixerOptions options;
+  options.replace_version = true;
+  options.revision_code_default = std::string("0x10000000");
+
+  std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+                  package="android"
+                  android:versionCode="0x00000001"
+                  android:revisionCode="0x00000002" />)EOF",
+                                                            options);
+  ASSERT_THAT(doc, NotNull());
+
+  xml::Element* manifest_el = doc->root.get();
+  ASSERT_THAT(manifest_el, NotNull());
+
+  xml::Attribute* attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode");
+  ASSERT_THAT(attr, NotNull());
+  EXPECT_THAT(attr->value, StrEq("0x10000000"));
+}
+
 TEST_F(ManifestFixerTest, ReplaceVersionName) {
   ManifestFixerOptions options;
   options.replace_version = true;