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

Commit 65f9099a authored by Sergey Nikolaienkov's avatar Sergey Nikolaienkov
Browse files

Teach appt2 to handle <required-(not-)feature>

Introducing 'required-feature' and 'requred-not-feature' tags that could
be used "inside" 'uses-permission' elements.
Elements of both types should have non-empty 'android:name' attribute to
specify the name of the feature.

Bug: 168079571
Test: make aapt2
Test: make aapt2_tests
Test: out/host/linux-x86/nativetest64/aapt2_tests/aapt2_tests
Test: create AndroidManifest.xml with <required(-not)-feature>
Test: aapt2 link -o out.apk -I $ANDROID_SDK/platforms/android-30/android.jar --manifest AndroidManifest.xml
Test: aapt2 dump badging out.apk
Test: appt2 dump permissions out.apk
Change-Id: I67ba0731daa6d31cd976b922217853f159cf7c3a
parent d8ba97d6
Loading
Loading
Loading
Loading
+120 −77
Original line number Diff line number Diff line
@@ -1063,17 +1063,23 @@ class UsesPermission : public ManifestExtractor::Element {
 public:
  UsesPermission() = default;
  std::string name;
  std::string requiredFeature;
  std::string requiredNotFeature;
  std::vector<std::string> requiredFeatures;
  std::vector<std::string> requiredNotFeatures;
  int32_t required = true;
  int32_t maxSdkVersion = -1;

  void Extract(xml::Element* element) override {
    name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
    requiredFeature = GetAttributeStringDefault(
        FindAttribute(element, REQUIRED_FEATURE_ATTR), "");
    requiredNotFeature = GetAttributeStringDefault(
        FindAttribute(element, REQUIRED_NOT_FEATURE_ATTR), "");
    std::string feature =
        GetAttributeStringDefault(FindAttribute(element, REQUIRED_FEATURE_ATTR), "");
    if (!feature.empty()) {
      requiredFeatures.push_back(feature);
    }
    feature = GetAttributeStringDefault(FindAttribute(element, REQUIRED_NOT_FEATURE_ATTR), "");
    if (!feature.empty()) {
      requiredNotFeatures.push_back(feature);
    }

    required = GetAttributeIntegerDefault(FindAttribute(element, REQUIRED_ATTR), 1);
    maxSdkVersion = GetAttributeIntegerDefault(
        FindAttribute(element, MAX_SDK_VERSION_ATTR), -1);
@@ -1090,13 +1096,13 @@ class UsesPermission : public ManifestExtractor::Element {
      if (maxSdkVersion >= 0) {
        printer->Print(StringPrintf(" maxSdkVersion='%d'", maxSdkVersion));
      }
      if (!requiredFeature.empty()) {
        printer->Print(StringPrintf(" requiredFeature='%s'", requiredFeature.data()));
      printer->Print("\n");
      for (const std::string& requiredFeature : requiredFeatures) {
        printer->Print(StringPrintf("  required-feature='%s'\n", requiredFeature.data()));
      }
      if (!requiredNotFeature.empty()) {
        printer->Print(StringPrintf(" requiredNotFeature='%s'", requiredNotFeature.data()));
      for (const std::string& requiredNotFeature : requiredNotFeatures) {
        printer->Print(StringPrintf("  required-not-feature='%s'\n", requiredNotFeature.data()));
      }
      printer->Print("\n");
      if (required == 0) {
        printer->Print(StringPrintf("optional-permission: name='%s'", name.data()));
        if (maxSdkVersion >= 0) {
@@ -1116,6 +1122,38 @@ class UsesPermission : public ManifestExtractor::Element {
  }
};

/** Represents <required-feature> elements. **/
class RequiredFeature : public ManifestExtractor::Element {
 public:
  RequiredFeature() = default;
  std::string name;

  void Extract(xml::Element* element) override {
    name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
    auto parent_stack = extractor()->parent_stack();
    if (!name.empty() && ElementCast<UsesPermission>(parent_stack[0])) {
      UsesPermission* uses_permission = ElementCast<UsesPermission>(parent_stack[0]);
      uses_permission->requiredFeatures.push_back(name);
    }
  }
};

/** Represents <required-not-feature> elements. **/
class RequiredNotFeature : public ManifestExtractor::Element {
 public:
  RequiredNotFeature() = default;
  std::string name;

  void Extract(xml::Element* element) override {
    name = GetAttributeStringDefault(FindAttribute(element, NAME_ATTR), "");
    auto parent_stack = extractor()->parent_stack();
    if (!name.empty() && ElementCast<UsesPermission>(parent_stack[0])) {
      UsesPermission* uses_permission = ElementCast<UsesPermission>(parent_stack[0]);
      uses_permission->requiredNotFeatures.push_back(name);
    }
  }
};

/** Represents <uses-permission-sdk-23> elements. **/
class UsesPermissionSdk23 : public ManifestExtractor::Element {
 public:
@@ -1845,7 +1883,8 @@ bool ManifestExtractor::Dump(text::Printer* printer, IDiagnostics* diag) {
      for (xml::Element* child : element->GetChildElements()) {
        if (child->name == "uses-permission" || child->name == "uses-permission-sdk-23"
            || child->name == "permission") {
          auto permission_element = ManifestExtractor::Element::Inflate(this, child);
          // Inflate the element and its descendants
          auto permission_element = Visit(child);
          manifest->AddChild(permission_element);
        }
      }
@@ -2239,6 +2278,7 @@ T* ElementCast(ManifestExtractor::Element* element) {
  const std::unordered_map<std::string, bool> kTagCheck = {
      {"action", std::is_base_of<Action, T>::value},
      {"activity", std::is_base_of<Activity, T>::value},
      {"additional-certificate", std::is_base_of<AdditionalCertificate, T>::value},
      {"application", std::is_base_of<Application, T>::value},
      {"category", std::is_base_of<Category, T>::value},
      {"compatible-screens", std::is_base_of<CompatibleScreens, T>::value},
@@ -2253,22 +2293,23 @@ T* ElementCast(ManifestExtractor::Element* element) {
      {"permission", std::is_base_of<Permission, T>::value},
      {"provider", std::is_base_of<Provider, T>::value},
      {"receiver", std::is_base_of<Receiver, T>::value},
      {"required-feature", std::is_base_of<RequiredFeature, T>::value},
      {"required-not-feature", std::is_base_of<RequiredNotFeature, T>::value},
      {"screen", std::is_base_of<Screen, T>::value},
      {"service", std::is_base_of<Service, T>::value},
      {"static-library", std::is_base_of<StaticLibrary, T>::value},
      {"supports-gl-texture", std::is_base_of<SupportsGlTexture, T>::value},
      {"supports-input", std::is_base_of<SupportsInput, T>::value},
      {"supports-screens", std::is_base_of<SupportsScreen, T>::value},
      {"uses-configuration", std::is_base_of<UsesConfiguarion, T>::value},
      {"uses-feature", std::is_base_of<UsesFeature, T>::value},
    {"uses-permission", std::is_base_of<UsesPermission, T>::value},
    {"uses-permission-sdk-23", std::is_base_of<UsesPermissionSdk23, T>::value},
      {"uses-library", std::is_base_of<UsesLibrary, T>::value},
      {"uses-native-library", std::is_base_of<UsesNativeLibrary, 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-permission", std::is_base_of<UsesPermission, T>::value},
      {"uses-permission-sdk-23", std::is_base_of<UsesPermissionSdk23, T>::value},
      {"uses-sdk", std::is_base_of<UsesSdkBadging, T>::value},
    {"uses-native-library", std::is_base_of<UsesNativeLibrary, T>::value},
      {"uses-static-library", std::is_base_of<UsesStaticLibrary, T>::value},
  };

  auto check = kTagCheck.find(element->tag());
@@ -2290,6 +2331,7 @@ std::unique_ptr<ManifestExtractor::Element> ManifestExtractor::Element::Inflate(
      kTagCheck = {
          {"action", &CreateType<Action>},
          {"activity", &CreateType<Activity>},
          {"additional-certificate", &CreateType<AdditionalCertificate>},
          {"application", &CreateType<Application>},
          {"category", &CreateType<Category>},
          {"compatible-screens", &CreateType<CompatibleScreens>},
@@ -2304,22 +2346,23 @@ std::unique_ptr<ManifestExtractor::Element> ManifestExtractor::Element::Inflate(
          {"permission", &CreateType<Permission>},
          {"provider", &CreateType<Provider>},
          {"receiver", &CreateType<Receiver>},
          {"required-feature", &CreateType<RequiredFeature>},
          {"required-not-feature", &CreateType<RequiredNotFeature>},
          {"screen", &CreateType<Screen>},
          {"service", &CreateType<Service>},
          {"static-library", &CreateType<StaticLibrary>},
          {"supports-gl-texture", &CreateType<SupportsGlTexture>},
          {"supports-input", &CreateType<SupportsInput>},
          {"supports-screens", &CreateType<SupportsScreen>},
          {"uses-configuration", &CreateType<UsesConfiguarion>},
          {"uses-feature", &CreateType<UsesFeature>},
    {"uses-permission", &CreateType<UsesPermission>},
    {"uses-permission-sdk-23", &CreateType<UsesPermissionSdk23>},
          {"uses-library", &CreateType<UsesLibrary>},
    {"static-library", &CreateType<StaticLibrary>},
    {"uses-static-library", &CreateType<UsesStaticLibrary>},
          {"uses-native-library", &CreateType<UsesNativeLibrary>},
          {"uses-package", &CreateType<UsesPackage>},
    {"additional-certificate", &CreateType<AdditionalCertificate>},
          {"uses-permission", &CreateType<UsesPermission>},
          {"uses-permission-sdk-23", &CreateType<UsesPermissionSdk23>},
          {"uses-sdk", &CreateType<UsesSdkBadging>},
    {"uses-native-library", &CreateType<UsesNativeLibrary>},
          {"uses-static-library", &CreateType<UsesStaticLibrary>},
      };

  // Attempt to map the xml tag to a element inflater
+2 −0
Original line number Diff line number Diff line
@@ -393,6 +393,8 @@ bool ManifestFixer::BuildRules(xml::XmlActionExecutor* executor,
  manifest_action["protected-broadcast"];
  manifest_action["adopt-permissions"];
  manifest_action["uses-permission"];
  manifest_action["uses-permission"]["required-feature"].Action(RequiredNameIsNotEmpty);
  manifest_action["uses-permission"]["required-not-feature"].Action(RequiredNameIsNotEmpty);
  manifest_action["uses-permission-sdk-23"];
  manifest_action["permission"];
  manifest_action["permission"]["meta-data"] = meta_data_action;