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

Commit 813d7503 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Implement issue #112113117: Ad library dependency declaration in manifest

You can now do a new form of <uses-package> that allows you to
specify a type of package along with required cert digests (like
uses-static-library).

This defines the new attribute needed for this and XML tag, and
updates aapt2 to actually allow uses-library in the manifest and
output this data with "dump badging".

While doing this I realized that "dump badging" was not printing
the data for uses-static-library or uses-library, so do those too.

Bug: 112113117
Test: manual
Change-Id: I5d02010aad9cb44675504a317df9cced421be8a1
parent 1d3ebe25
Loading
Loading
Loading
Loading
+10 −9
Original line number Diff line number Diff line
@@ -280,7 +280,7 @@ package android {
    field public static final int allowBackup = 16843392; // 0x1010280
    field public static final int allowClearUserData = 16842757; // 0x1010005
    field public static final int allowEmbedded = 16843765; // 0x10103f5
    field public static final int allowForceDark = 16844171; // 0x101058b
    field public static final int allowForceDark = 16844172; // 0x101058c
    field public static final int allowParallelSyncs = 16843570; // 0x1010332
    field public static final int allowSingleTap = 16843353; // 0x1010259
    field public static final int allowTaskReparenting = 16843268; // 0x1010204
@@ -774,11 +774,11 @@ package android {
    field public static final int isFeatureSplit = 16844123; // 0x101055b
    field public static final int isGame = 16843764; // 0x10103f4
    field public static final int isIndicator = 16843079; // 0x1010147
    field public static final int isLightTheme = 16844175; // 0x101058f
    field public static final int isLightTheme = 16844176; // 0x1010590
    field public static final int isModifier = 16843334; // 0x1010246
    field public static final int isRepeatable = 16843336; // 0x1010248
    field public static final int isScrollContainer = 16843342; // 0x101024e
    field public static final int isSplitRequired = 16844176; // 0x1010590
    field public static final int isSplitRequired = 16844177; // 0x1010591
    field public static final int isStatic = 16844122; // 0x101055a
    field public static final int isSticky = 16843335; // 0x1010247
    field public static final int isolatedProcess = 16843689; // 0x10103a9
@@ -938,7 +938,7 @@ package android {
    field public static final int minSdkVersion = 16843276; // 0x101020c
    field public static final int minWidth = 16843071; // 0x101013f
    field public static final int minimumHorizontalAngle = 16843901; // 0x101047d
    field public static final int minimumUiTimeout = 16844174; // 0x101058e
    field public static final int minimumUiTimeout = 16844175; // 0x101058f
    field public static final int minimumVerticalAngle = 16843902; // 0x101047e
    field public static final int mipMap = 16843725; // 0x10103cd
    field public static final int mirrorForRtl = 16843726; // 0x10103ce
@@ -978,10 +978,10 @@ package android {
    field public static final int onClick = 16843375; // 0x101026f
    field public static final int oneshot = 16843159; // 0x1010197
    field public static final int opacity = 16843550; // 0x101031e
    field public static final int opticalInsetBottom = 16844170; // 0x101058a
    field public static final int opticalInsetLeft = 16844167; // 0x1010587
    field public static final int opticalInsetRight = 16844169; // 0x1010589
    field public static final int opticalInsetTop = 16844168; // 0x1010588
    field public static final int opticalInsetBottom = 16844171; // 0x101058b
    field public static final int opticalInsetLeft = 16844168; // 0x1010588
    field public static final int opticalInsetRight = 16844170; // 0x101058a
    field public static final int opticalInsetTop = 16844169; // 0x1010589
    field public static final int order = 16843242; // 0x10101ea
    field public static final int orderInCategory = 16843231; // 0x10101df
    field public static final int ordering = 16843490; // 0x10102e2
@@ -997,6 +997,7 @@ package android {
    field public static final int overlapAnchor = 16843874; // 0x1010462
    field public static final int overridesImplicitlyEnabledSubtype = 16843682; // 0x10103a2
    field public static final int packageNames = 16843649; // 0x1010381
    field public static final int packageType = 16844167; // 0x1010587
    field public static final int padding = 16842965; // 0x10100d5
    field public static final int paddingBottom = 16842969; // 0x10100d9
    field public static final int paddingEnd = 16843700; // 0x10103b4
@@ -1306,7 +1307,7 @@ package android {
    field public static final int summaryColumn = 16843426; // 0x10102a2
    field public static final int summaryOff = 16843248; // 0x10101f0
    field public static final int summaryOn = 16843247; // 0x10101ef
    field public static final int supportsAmbientMode = 16844172; // 0x101058c
    field public static final int supportsAmbientMode = 16844173; // 0x101058d
    field public static final int supportsAssist = 16844016; // 0x10104f0
    field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
    field public static final int supportsLocalInteraction = 16844047; // 0x101050f
+29 −3
Original line number Diff line number Diff line
@@ -1442,8 +1442,11 @@
         {@link #AndroidManifestService service},
         {@link #AndroidManifestReceiver receiver},
         {@link #AndroidManifestActivity activity},
         {@link #AndroidManifestActivityAlias activity-alias}, and
         {@link #AndroidManifestUsesLibrary uses-library}.  The application tag
         {@link #AndroidManifestActivityAlias activity-alias},
         {@link #AndroidManifestUsesLibrary uses-library},
         {@link #AndroidManifestUsesStaticLibrary uses-static-library}, and
         {@link #AndroidManifestUsesPackage uses-package}.
         The application tag
         appears as a child of the root {@link #AndroidManifest manifest} tag in
         an application's manifest file. -->
    <declare-styleable name="AndroidManifestApplication" parent="AndroidManifest">
@@ -1877,12 +1880,35 @@
         library is singed with more than one certificate.

         <p>This appears as a child tag of the
         {@link #AndroidManifestUsesStaticLibrary uses-static-library} tag. -->
         {@link #AndroidManifestUsesStaticLibrary uses-static-library} or
         {@link #AndroidManifestUsesPackage uses-package} tag. -->
    <declare-styleable name="AndroidManifestAdditionalCertificate" parent="AndroidManifestUsesStaticLibrary">
        <!-- The SHA-256 digest of the library signing certificate. -->
        <attr name="certDigest" />
    </declare-styleable>

    <!-- The <code>uses-package</code> specifies some kind of dependency on another
         package.  It does not have any impact on the app's execution on the device,
         but provides information about dependencies it has on other packages that need
         to  be satisfied for it to run correctly.  That is, this is primarily for
         installers to know what other apps need to be installed along with this one.

         <p>This appears as a child tag of the
         {@link #AndroidManifestApplication application} tag. -->
    <declare-styleable name="AndroidManifestUsesPackage" parent="AndroidManifestApplication">
        <!-- Required type of association with the package, for example "android.package.ad_service"
             if it provides an advertising service. -->
        <attr name="packageType" format="string" />
        <!-- Required name of the package you use. -->
        <attr name="name" />
        <!-- Optional minimum version of the package that satisfies the dependency. -->
        <attr name="version" />
        <!-- Optional minimum major version of the package that satisfies the dependency. -->
        <attr name="versionMajor" format="integer" />
        <!-- Optional SHA-256 digest of the package signing certificate. -->
        <attr name="certDigest" format="string" />
    </declare-styleable>

    <!-- The <code>supports-screens</code> specifies the screen dimensions an
         application supports.  By default a modern application supports all
         screen sizes and must explicitly disable certain screen sizes here;
+1 −0
Original line number Diff line number Diff line
@@ -2903,6 +2903,7 @@
  <eat-comment />

    <public-group type="attr" first-id="0x01010587">
        <public name="packageType" />
        <public name="opticalInsetLeft" />
        <public name="opticalInsetTop" />
        <public name="opticalInsetRight" />
+128 −2
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

#include "DumpManifest.h"

#include <algorithm>

#include "LoadedApk.h"
#include "SdkConstants.h"
#include "ValueVisitor.h"
@@ -70,10 +72,14 @@ enum {
  CATEGORY_ATTR = 0x010103e8,
  BANNER_ATTR = 0x10103f2,
  ISGAME_ATTR = 0x10103f4,
  VERSION_ATTR = 0x01010519,
  CERT_DIGEST_ATTR = 0x01010548,
  REQUIRED_FEATURE_ATTR = 0x1010557,
  REQUIRED_NOT_FEATURE_ATTR = 0x1010558,
  COMPILE_SDK_VERSION_ATTR = 0x01010572,
  COMPILE_SDK_VERSION_CODENAME_ATTR = 0x01010573,
  VERSION_MAJOR_ATTR = 0x01010577,
  PACKAGE_TYPE_ATTR = 0x01010587,
};

const std::string& kAndroidNamespace = "http://schemas.android.com/apk/res/android";
@@ -1318,6 +1324,70 @@ class UsesLibrary : public ManifestExtractor::Element {
  }
};

/** Represents <static-library> elements. **/
class StaticLibrary : public ManifestExtractor::Element {
 public:
  StaticLibrary() = default;
  std::string name;
  int version;
  int versionMajor;

  void Extract(xml::Element* element) override {
    auto parent_stack = extractor()->parent_stack();
    if (parent_stack.size() > 0 && ElementCast<Application>(parent_stack[0])) {
      name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
      version = GetAttributeIntegerDefault(FindAttribute(element, VERSION_ATTR), 0);
      versionMajor = GetAttributeIntegerDefault(FindAttribute(element, VERSION_MAJOR_ATTR), 0);
    }
  }

  void Print(text::Printer& printer) override {
    printer.Print(StringPrintf(
      "static-library: name='%s' version='%d' versionMajor='%d'\n",
      name.data(), version, versionMajor));
  }
};

/** Represents <uses-static-library> elements. **/
class UsesStaticLibrary : public ManifestExtractor::Element {
 public:
  UsesStaticLibrary() = default;
  std::string name;
  int version;
  int versionMajor;
  std::vector<std::string> certDigests;

  void Extract(xml::Element* element) override {
    auto parent_stack = extractor()->parent_stack();
    if (parent_stack.size() > 0 && ElementCast<Application>(parent_stack[0])) {
      name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
      version = GetAttributeIntegerDefault(FindAttribute(element, VERSION_ATTR), 0);
      versionMajor = GetAttributeIntegerDefault(FindAttribute(element, VERSION_MAJOR_ATTR), 0);
      AddCertDigest(element);
    }
  }

  void AddCertDigest(xml::Element* element) {
    std::string digest = GetAttributeStringDefault(FindAttribute(element, CERT_DIGEST_ATTR), "");
    // We allow ":" delimiters in the SHA declaration as this is the format
    // emitted by the certtool making it easy for developers to copy/paste.
    digest.erase(std::remove(digest.begin(), digest.end(), ':'), digest.end());
    if (!digest.empty()) {
      certDigests.push_back(digest);
    }
  }

  void Print(text::Printer& printer) override {
    printer.Print(StringPrintf(
      "uses-static-library: name='%s' version='%d' versionMajor='%d'",
      name.data(), version, versionMajor));
    for (size_t i = 0; i < certDigests.size(); i++) {
      printer.Print(StringPrintf(" certDigest='%s'", certDigests[i].data()));
    }
    printer.Print("\n");
  }
};

/**
 * Represents <meta-data> elements. These tags are only printed when a flag is passed in to
 * explicitly enable meta data printing.
@@ -1544,17 +1614,67 @@ class PackageVerifier : public ManifestExtractor::Element {
class UsesPackage : public ManifestExtractor::Element {
 public:
  UsesPackage() = default;
  const std::string* packageType = nullptr;
  const std::string* name = nullptr;
  int version;
  int versionMajor;
  std::vector<std::string> certDigests;

  void Extract(xml::Element* element) override {
    auto parent_stack = extractor()->parent_stack();
    if (parent_stack.size() > 0 && ElementCast<Application>(parent_stack[0])) {
      packageType = GetAttributeString(FindAttribute(element, PACKAGE_TYPE_ATTR));
      name = GetAttributeString(FindAttribute(element, NAME_ATTR));
      version = GetAttributeIntegerDefault(FindAttribute(element, VERSION_ATTR), 0);
      versionMajor = GetAttributeIntegerDefault(FindAttribute(element, VERSION_MAJOR_ATTR), 0);
      AddCertDigest(element);
    }
  }

  void AddCertDigest(xml::Element* element) {
    std::string digest = GetAttributeStringDefault(FindAttribute(element, CERT_DIGEST_ATTR), "");
    // We allow ":" delimiters in the SHA declaration as this is the format
    // emitted by the certtool making it easy for developers to copy/paste.
    digest.erase(std::remove(digest.begin(), digest.end(), ':'), digest.end());
    if (!digest.empty()) {
      certDigests.push_back(digest);
    }
  }

  void Print(text::Printer& printer) override {
    if (name) {
      if (packageType) {
        printer.Print(StringPrintf(
          "uses-typed-package: type='%s' name='%s' version='%d' versionMajor='%d'",
          packageType->data(), name->data(), version, versionMajor));
        for (size_t i = 0; i < certDigests.size(); i++) {
          printer.Print(StringPrintf(" certDigest='%s'", certDigests[i].data()));
        }
        printer.Print("\n");
      } else {
        printer.Print(StringPrintf("uses-package:'%s'\n", name->data()));
      }
    }
  }
};

/** Represents <additional-certificate> elements. **/
class AdditionalCertificate : public ManifestExtractor::Element {
 public:
  AdditionalCertificate() = default;

  void Extract(xml::Element* element) override {
    auto parent_stack = extractor()->parent_stack();
    if (parent_stack.size() > 0) {
      if (ElementCast<UsesPackage>(parent_stack[0])) {
        UsesPackage* uses = ElementCast<UsesPackage>(parent_stack[0]);
        uses->AddCertDigest(element);
      } else if (ElementCast<UsesStaticLibrary>(parent_stack[0])) {
        UsesStaticLibrary* uses = ElementCast<UsesStaticLibrary>(parent_stack[0]);
        uses->AddCertDigest(element);
      }
    }
  }
};

/** Represents <screen> elements found in <compatible-screens> elements. */
@@ -2065,6 +2185,9 @@ T* ElementCast(ManifestExtractor::Element* element) {
    {"uses-permission-sdk-23", std::is_base_of<UsesPermissionSdk23, T>::value},
    {"uses-library", std::is_base_of<UsesLibrary, T>::value},
    {"uses-package", std::is_base_of<UsesPackage, T>::value},
    {"static-library", std::is_base_of<StaticLibrary, T>::value},
    {"uses-static-library", std::is_base_of<UsesStaticLibrary, T>::value},
    {"additional-certificate", std::is_base_of<AdditionalCertificate, T>::value},
    {"uses-sdk", std::is_base_of<UsesSdkBadging, T>::value},
  };

@@ -2110,7 +2233,10 @@ std::unique_ptr<ManifestExtractor::Element> ManifestExtractor::Element::Inflate(
    {"uses-permission", &CreateType<UsesPermission>},
    {"uses-permission-sdk-23", &CreateType<UsesPermissionSdk23>},
    {"uses-library", &CreateType<UsesLibrary>},
    {"static-library", &CreateType<StaticLibrary>},
    {"uses-static-library", &CreateType<UsesStaticLibrary>},
    {"uses-package", &CreateType<UsesPackage>},
    {"additional-certificate", &CreateType<AdditionalCertificate>},
    {"uses-sdk", &CreateType<UsesSdkBadging>},
  };

+4 −0
Original line number Diff line number Diff line
@@ -393,6 +393,10 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
  uses_static_library_action.Action(RequiredAndroidAttribute("certDigest"));
  uses_static_library_action["additional-certificate"];

  xml::XmlNodeAction& uses_package_action = application_action["uses-package"];
  uses_package_action.Action(RequiredNameIsJavaPackage);
  uses_package_action["additional-certificate"];

  if (options_.debug_mode) {
    application_action.Action([&](xml::Element* el) -> bool {
      xml::Attribute *attr = el->FindOrCreateAttribute(xml::kSchemaAndroid, "debuggable");