diff options
| -rw-r--r-- | tools/aapt2/cmd/Link.h | 2 | ||||
| -rw-r--r-- | tools/aapt2/dump/DumpManifest.cpp | 31 | ||||
| -rw-r--r-- | tools/aapt2/link/ManifestFixer.cpp | 17 | ||||
| -rw-r--r-- | tools/aapt2/link/ManifestFixer.h | 6 | ||||
| -rw-r--r-- | tools/aapt2/link/ManifestFixer_test.cpp | 57 |
5 files changed, 110 insertions, 3 deletions
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h index 5fdfb66bdf4e..2ce2167c1bf3 100644 --- a/tools/aapt2/cmd/Link.h +++ b/tools/aapt2/cmd/Link.h @@ -209,6 +209,8 @@ class LinkCommand : public Command { AddOptionalFlag("--compile-sdk-version-name", "Version name to inject into the AndroidManifest.xml if none is present.", &options_.manifest_fixer_options.compile_sdk_version_codename); + AddOptionalFlagList("--fingerprint-prefix", "Fingerprint prefix to add to install constraints.", + &options_.manifest_fixer_options.fingerprint_prefixes); AddOptionalSwitch("--shared-lib", "Generates a shared Android runtime library.", &shared_lib_); AddOptionalSwitch("--static-lib", "Generate a static Android library.", &static_lib_); diff --git a/tools/aapt2/dump/DumpManifest.cpp b/tools/aapt2/dump/DumpManifest.cpp index c66f4e5b7c30..a43bf1b60f42 100644 --- a/tools/aapt2/dump/DumpManifest.cpp +++ b/tools/aapt2/dump/DumpManifest.cpp @@ -2120,6 +2120,33 @@ class InputType : public ManifestExtractor::Element { } }; +/** Represents <install-constraints> elements. **/ +class InstallConstraints : public ManifestExtractor::Element { + public: + InstallConstraints() = default; + std::vector<std::string> fingerprint_prefixes; + + void Extract(xml::Element* element) override { + for (xml::Element* child : element->GetChildElements()) { + if (child->name == "fingerprint-prefix") { + xml::Attribute* attr = child->FindAttribute(kAndroidNamespace, "value"); + if (attr) { + fingerprint_prefixes.push_back(attr->value); + } + } + } + } + + void Print(text::Printer* printer) override { + if (!fingerprint_prefixes.empty()) { + printer->Print(StringPrintf("install-constraints:\n")); + for (const auto& prefix : fingerprint_prefixes) { + printer->Print(StringPrintf(" fingerprint-prefix='%s'\n", prefix.c_str())); + } + } + } +}; + /** Represents <original-package> elements. **/ class OriginalPackage : public ManifestExtractor::Element { public: @@ -2869,7 +2896,7 @@ template <typename T> constexpr const char* GetExpectedTagForType() { // This array does not appear at runtime, as GetExpectedTagForType function is used by compiler // to inject proper 'expected_tag' into ElementCast. - std::array<std::pair<const char*, bool>, 37> tags = { + std::array<std::pair<const char*, bool>, 38> tags = { std::make_pair("action", std::is_same<Action, T>::value), std::make_pair("activity", std::is_same<Activity, T>::value), std::make_pair("additional-certificate", std::is_same<AdditionalCertificate, T>::value), @@ -2878,6 +2905,7 @@ constexpr const char* GetExpectedTagForType() { std::make_pair("compatible-screens", std::is_same<CompatibleScreens, T>::value), std::make_pair("feature-group", std::is_same<FeatureGroup, T>::value), std::make_pair("input-type", std::is_same<InputType, T>::value), + std::make_pair("install-constraints", std::is_same<InstallConstraints, T>::value), std::make_pair("intent-filter", std::is_same<IntentFilter, T>::value), std::make_pair("meta-data", std::is_same<MetaData, T>::value), std::make_pair("manifest", std::is_same<Manifest, T>::value), @@ -2948,6 +2976,7 @@ std::unique_ptr<ManifestExtractor::Element> ManifestExtractor::Element::Inflate( {"compatible-screens", &CreateType<CompatibleScreens>}, {"feature-group", &CreateType<FeatureGroup>}, {"input-type", &CreateType<InputType>}, + {"install-constraints", &CreateType<InstallConstraints>}, {"intent-filter", &CreateType<IntentFilter>}, {"manifest", &CreateType<Manifest>}, {"meta-data", &CreateType<MetaData>}, diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp index 56d90758ee73..53f0abee1cf2 100644 --- a/tools/aapt2/link/ManifestFixer.cpp +++ b/tools/aapt2/link/ManifestFixer.cpp @@ -749,6 +749,23 @@ bool ManifestFixer::Consume(IAaptContext* context, xml::XmlResource* doc) { attr->value = options_.compile_sdk_version_codename.value(); } + if (!options_.fingerprint_prefixes.empty()) { + xml::Element* install_constraints_el = root->FindChild({}, "install-constraints"); + if (install_constraints_el == nullptr) { + std::unique_ptr<xml::Element> install_constraints = std::make_unique<xml::Element>(); + install_constraints->name = "install-constraints"; + install_constraints_el = install_constraints.get(); + root->AppendChild(std::move(install_constraints)); + } + for (const std::string& prefix : options_.fingerprint_prefixes) { + std::unique_ptr<xml::Element> prefix_el = std::make_unique<xml::Element>(); + prefix_el->name = "fingerprint-prefix"; + xml::Attribute* attr = prefix_el->FindOrCreateAttribute(xml::kSchemaAndroid, "value"); + attr->value = prefix; + install_constraints_el->AppendChild(std::move(prefix_el)); + } + } + xml::XmlActionExecutor executor; if (!BuildRules(&executor, context->GetDiagnostics())) { return false; diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h index 90f5177e752e..175ab6f1cd7b 100644 --- a/tools/aapt2/link/ManifestFixer.h +++ b/tools/aapt2/link/ManifestFixer.h @@ -18,11 +18,10 @@ #define AAPT_LINK_MANIFESTFIXER_H #include <string> +#include <vector> #include "android-base/macros.h" - #include "process/IResourceTableConsumer.h" - #include "xml/XmlActionExecutor.h" #include "xml/XmlDom.h" @@ -75,6 +74,9 @@ struct ManifestFixerOptions { // 'android:compileSdkVersionCodename' in the <manifest> tag. std::optional<std::string> compile_sdk_version_codename; + // The fingerprint prefixes to be added to the <install-constraints> tag. + std::vector<std::string> fingerprint_prefixes; + // Whether 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. diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp index 7180ae6b8bc7..1b8f05b957a7 100644 --- a/tools/aapt2/link/ManifestFixer_test.cpp +++ b/tools/aapt2/link/ManifestFixer_test.cpp @@ -965,6 +965,63 @@ TEST_F(ManifestFixerTest, UnexpectedElementsInManifest) { ASSERT_THAT(manifest, IsNull()); } +TEST_F(ManifestFixerTest, InsertFingerprintPrefixIfNotExist) { + std::string input = R"( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="android"> + </manifest>)"; + ManifestFixerOptions options; + options.fingerprint_prefixes = {"foo", "bar"}; + + std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options); + ASSERT_THAT(manifest, NotNull()); + xml::Element* install_constraints = manifest->root.get()->FindChild({}, "install-constraints"); + ASSERT_THAT(install_constraints, NotNull()); + std::vector<xml::Element*> fingerprint_prefixes = install_constraints->GetChildElements(); + EXPECT_EQ(fingerprint_prefixes.size(), 2); + xml::Attribute* attr; + EXPECT_THAT(fingerprint_prefixes[0]->name, StrEq("fingerprint-prefix")); + attr = fingerprint_prefixes[0]->FindAttribute(xml::kSchemaAndroid, "value"); + ASSERT_THAT(attr, NotNull()); + EXPECT_THAT(attr->value, StrEq("foo")); + EXPECT_THAT(fingerprint_prefixes[1]->name, StrEq("fingerprint-prefix")); + attr = fingerprint_prefixes[1]->FindAttribute(xml::kSchemaAndroid, "value"); + ASSERT_THAT(attr, NotNull()); + EXPECT_THAT(attr->value, StrEq("bar")); +} + +TEST_F(ManifestFixerTest, AppendFingerprintPrefixIfExists) { + std::string input = R"( + <manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="android"> + <install-constraints> + <fingerprint-prefix android:value="foo" /> + </install-constraints> + </manifest>)"; + ManifestFixerOptions options; + options.fingerprint_prefixes = {"bar", "baz"}; + + std::unique_ptr<xml::XmlResource> manifest = VerifyWithOptions(input, options); + ASSERT_THAT(manifest, NotNull()); + xml::Element* install_constraints = manifest->root.get()->FindChild({}, "install-constraints"); + ASSERT_THAT(install_constraints, NotNull()); + std::vector<xml::Element*> fingerprint_prefixes = install_constraints->GetChildElements(); + EXPECT_EQ(fingerprint_prefixes.size(), 3); + xml::Attribute* attr; + EXPECT_THAT(fingerprint_prefixes[0]->name, StrEq("fingerprint-prefix")); + attr = fingerprint_prefixes[0]->FindAttribute(xml::kSchemaAndroid, "value"); + ASSERT_THAT(attr, NotNull()); + EXPECT_THAT(attr->value, StrEq("foo")); + EXPECT_THAT(fingerprint_prefixes[1]->name, StrEq("fingerprint-prefix")); + attr = fingerprint_prefixes[1]->FindAttribute(xml::kSchemaAndroid, "value"); + ASSERT_THAT(attr, NotNull()); + EXPECT_THAT(attr->value, StrEq("bar")); + EXPECT_THAT(fingerprint_prefixes[2]->name, StrEq("fingerprint-prefix")); + attr = fingerprint_prefixes[2]->FindAttribute(xml::kSchemaAndroid, "value"); + ASSERT_THAT(attr, NotNull()); + EXPECT_THAT(attr->value, StrEq("baz")); +} + TEST_F(ManifestFixerTest, UsesLibraryMustHaveNonEmptyName) { std::string input = R"( <manifest xmlns:android="http://schemas.android.com/apk/res/android" |