Add support for --replace-version to aapt2
Implement --replace-version to match aapt1.
Bug: 79755007
Test: aapt2_tests
Change-Id: Iee2bd9a3981c7d4681509f18b735c6e9e6c1a336
Merged-In: Iee2bd9a3981c7d4681509f18b735c6e9e6c1a336
(cherry picked from commit dcd58c420771af75c625242985bd96ba828aca56)
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 0910040..db42e7c 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -2120,6 +2120,12 @@
.OptionalFlag("--version-name",
"Version name to inject into the AndroidManifest.xml if none is present.",
&options.manifest_fixer_options.version_name_default)
+ .OptionalSwitch("--replace-version",
+ "If --version-code and/or --version-name 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.",
+ &options.manifest_fixer_options.replace_version)
.OptionalFlag("--compile-sdk-version-code",
"Version code (integer) to inject into the AndroidManifest.xml if none is\n"
"present.",
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index bfff148..ee4e702 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -261,6 +261,9 @@
manifest_action.Action(FixCoreAppAttribute);
manifest_action.Action([&](xml::Element* el) -> bool {
if (options_.version_name_default) {
+ if (options_.replace_version) {
+ el->RemoveAttribute(xml::kSchemaAndroid, "versionName");
+ }
if (el->FindAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
el->attributes.push_back(
xml::Attribute{xml::kSchemaAndroid, "versionName",
@@ -269,6 +272,9 @@
}
if (options_.version_code_default) {
+ if (options_.replace_version) {
+ el->RemoveAttribute(xml::kSchemaAndroid, "versionCode");
+ }
if (el->FindAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
el->attributes.push_back(
xml::Attribute{xml::kSchemaAndroid, "versionCode",
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index 7d6fad2..98d06fd 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -44,10 +44,12 @@
// <instrumentation>.
Maybe<std::string> rename_instrumentation_target_package;
- // The version name to set if 'android:versionName' is not defined in <manifest>.
+ // The version name to set if 'android:versionName' is not defined in <manifest> or if
+ // replace_version is set.
Maybe<std::string> version_name_default;
- // The version code to set if 'android:versionCode' is not defined in <manifest>.
+ // The version code to set if 'android:versionCode' is not defined in <manifest> or if
+ // replace_version is set.
Maybe<std::string> version_code_default;
// The version of the framework being compiled against to set for 'android:compileSdkVersion' in
@@ -65,6 +67,9 @@
// Whether to inject the android:debuggable="true" flag into the manifest
bool debug_mode = false;
+
+ // Whether to replace the manifest version with the the command line version
+ bool replace_version = false;
};
// Verifies that the manifest is correctly formed and inserts defaults where specified with
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 5f406e8..5bc004d 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -349,6 +349,136 @@
EXPECT_THAT(attr->value, StrEq("0x10000000"));
}
+TEST_F(ManifestFixerTest, DontUseDefaultVersionNameAndCode) {
+ManifestFixerOptions options;
+options.version_name_default = std::string("Beta");
+options.version_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="0x20000000"
+ android:versionName="Alpha" />)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, "versionName");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("Alpha"));
+
+attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("0x20000000"));
+}
+
+TEST_F(ManifestFixerTest, ReplaceVersionNameAndCode) {
+ManifestFixerOptions options;
+options.replace_version = true;
+options.version_name_default = std::string("Beta");
+options.version_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="0x20000000"
+ android:versionName="Alpha" />)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, "versionName");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("Beta"));
+
+attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("0x10000000"));
+}
+
+TEST_F(ManifestFixerTest, ReplaceVersionName) {
+ManifestFixerOptions options;
+options.replace_version = true;
+options.version_name_default = std::string("Beta");
+
+std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android"
+ android:versionCode="0x20000000"
+ android:versionName="Alpha" />)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, "versionName");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("Beta"));
+
+attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("0x20000000"));
+}
+
+TEST_F(ManifestFixerTest, ReplaceVersionCode) {
+ManifestFixerOptions options;
+options.replace_version = true;
+options.version_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="0x20000000"
+ android:versionName="Alpha" />)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, "versionName");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("Alpha"));
+
+attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("0x10000000"));
+}
+
+TEST_F(ManifestFixerTest, DontReplaceVersionNameOrCode) {
+ManifestFixerOptions options;
+options.replace_version = true;
+
+std::unique_ptr<xml::XmlResource> doc = VerifyWithOptions(R"EOF(
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android"
+ android:versionCode="0x20000000"
+ android:versionName="Alpha" />)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, "versionName");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("Alpha"));
+
+attr = manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode");
+ASSERT_THAT(attr, NotNull());
+EXPECT_THAT(attr->value, StrEq("0x20000000"));
+}
+
TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"hello\" />"), IsNull());
EXPECT_THAT(Verify("<manifest package=\"android\" coreApp=\"1dp\" />"), IsNull());
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index b6cd086..acd07c2 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -423,6 +423,15 @@
return nullptr;
}
+void Element::RemoveAttribute(const StringPiece& ns, const StringPiece& name) {
+ auto new_attr_end = std::remove_if(attributes.begin(), attributes.end(),
+ [&](const Attribute& attr) -> bool {
+ return ns == attr.namespace_uri && name == attr.name;
+ });
+
+ attributes.erase(new_attr_end, attributes.end());
+}
+
Attribute* Element::FindOrCreateAttribute(const StringPiece& ns, const StringPiece& name) {
Attribute* attr = FindAttribute(ns, name);
if (attr == nullptr) {
diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h
index 8f382961..a5b2d10 100644
--- a/tools/aapt2/xml/XmlDom.h
+++ b/tools/aapt2/xml/XmlDom.h
@@ -102,6 +102,8 @@
const android::StringPiece& name) const;
Attribute* FindOrCreateAttribute(const android::StringPiece& ns,
const android::StringPiece& name);
+ void RemoveAttribute(const android::StringPiece& ns,
+ const android::StringPiece& name);
Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name);
const Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name) const;