diff options
| -rw-r--r-- | tools/aapt2/cmd/Link.cpp | 6 | ||||
| -rw-r--r-- | tools/aapt2/link/ManifestFixer.cpp | 6 | ||||
| -rw-r--r-- | tools/aapt2/link/ManifestFixer.h | 9 | ||||
| -rw-r--r-- | tools/aapt2/link/ManifestFixer_test.cpp | 131 | ||||
| -rw-r--r-- | tools/aapt2/xml/XmlDom.cpp | 9 | ||||
| -rw-r--r-- | tools/aapt2/xml/XmlDom.h | 3 |
6 files changed, 164 insertions, 0 deletions
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp index 036bf5d86f32..3a312b07d15d 100644 --- a/tools/aapt2/cmd/Link.cpp +++ b/tools/aapt2/cmd/Link.cpp @@ -1923,6 +1923,12 @@ int Link(const std::vector<StringPiece>& args, IDiagnostics* diagnostics) { .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) .OptionalSwitch("--shared-lib", "Generates a shared Android runtime library.", &shared_lib) .OptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib) diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index e6271eb12c05..ca7b6530a264 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -237,6 +237,9 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor, 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", @@ -245,6 +248,9 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor, } 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 dbabab179cad..d7a5931eef1f 100644 --- a/tools/aapt2/link/ManifestFixer.h +++ b/tools/aapt2/link/ManifestFixer.h @@ -33,13 +33,22 @@ struct ManifestFixerOptions { Maybe<std::string> target_sdk_version_default; Maybe<std::string> rename_manifest_package; Maybe<std::string> rename_instrumentation_target_package; + + // 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> or if + // replace_version is set. Maybe<std::string> version_code_default; // Wether validation errors should be treated only as warnings. If this is 'true', then an // incorrect node will not result in an error, but only as a warning, and the parsing will // continue. bool warn_validation = false; + + // Whether to replace the manifest version with the the command line version + bool replace_version = false; }; /** diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp index 84e367d842c8..e6410c971c44 100644 --- a/tools/aapt2/link/ManifestFixer_test.cpp +++ b/tools/aapt2/link/ManifestFixer_test.cpp @@ -21,6 +21,7 @@ using ::android::StringPiece; using ::testing::IsNull; using ::testing::NotNull; +using ::testing::StrEq; namespace aapt { @@ -339,6 +340,136 @@ TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) { EXPECT_EQ(std::string("0x10000000"), attr->value); } +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_EQ(nullptr, Verify("<manifest package=\"android\" coreApp=\"hello\" />")); diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp index 1d122db9990f..22767781b9b5 100644 --- a/tools/aapt2/xml/XmlDom.cpp +++ b/tools/aapt2/xml/XmlDom.cpp @@ -394,6 +394,15 @@ const Attribute* Element::FindAttribute(const StringPiece& ns, const StringPiece 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()); +} + Element* Element::FindChild(const StringPiece& ns, const StringPiece& name) { return FindChildWithAttribute(ns, name, {}, {}, {}); } diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h index 154224381626..995cdb24a3f0 100644 --- a/tools/aapt2/xml/XmlDom.h +++ b/tools/aapt2/xml/XmlDom.h @@ -98,6 +98,9 @@ class Element : public Node { Attribute* FindAttribute(const android::StringPiece& ns, const android::StringPiece& name); const Attribute* FindAttribute(const android::StringPiece& ns, const android::StringPiece& name) const; + void RemoveAttribute(const android::StringPiece& ns, + const android::StringPiece& name); + Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name); Element* FindChildWithAttribute(const android::StringPiece& ns, const android::StringPiece& name, const android::StringPiece& attr_ns, |