Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a10b8082 authored by Andrei Onea's avatar Andrei Onea
Browse files

Add support for adding fingerprint prefix install constraints

Since more install constraints could be added in the future, add a new
option for inserting just fingerprint prefixes.

Bug: 270562509
Test: atest aapt2_tests
Change-Id: If357c6df09491fa1bec5fe1a00a682d634af69b7
parent 7f9d899a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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_);
+30 −1
Original line number Diff line number Diff line
@@ -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>},
+17 −0
Original line number Diff line number Diff line
@@ -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;
+4 −2
Original line number Diff line number Diff line
@@ -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.
+57 −0
Original line number Diff line number Diff line
@@ -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"