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

Commit d52bd685 authored by Jeremy Meyer's avatar Jeremy Meyer
Browse files

Flag support for bag resource types

Test: Automated
Bug: 329436914
Flag: EXEMPT Aconfig not supported on host tools
Change-Id: I891c93c3ffcab172d28701b44a80c50f1e24d99e
parent d439c619
Loading
Loading
Loading
Loading
+22 −3
Original line number Original line Diff line number Diff line
@@ -68,6 +68,16 @@ public class ResourceFlaggingTest {
        assertThat(getBoolean("res3")).isTrue();
        assertThat(getBoolean("res3")).isTrue();
    }
    }


    @Test
    public void testFlagDisabledStringArrayElement() {
        assertThat(getStringArray("strarr1")).isEqualTo(new String[]{"one", "two", "three"});
    }

    @Test
    public void testFlagDisabledIntArrayElement() {
        assertThat(getIntArray("intarr1")).isEqualTo(new int[]{1, 2, 3});
    }

    private boolean getBoolean(String name) {
    private boolean getBoolean(String name) {
        int resId = mResources.getIdentifier(
        int resId = mResources.getIdentifier(
                name,
                name,
@@ -77,13 +87,22 @@ public class ResourceFlaggingTest {
        return mResources.getBoolean(resId);
        return mResources.getBoolean(resId);
    }
    }


    private String getString(String name) {
    private String[] getStringArray(String name) {
        int resId = mResources.getIdentifier(
                name,
                "array",
                "com.android.intenal.flaggedresources");
        assertThat(resId).isNotEqualTo(0);
        return mResources.getStringArray(resId);
    }

    private int[] getIntArray(String name) {
        int resId = mResources.getIdentifier(
        int resId = mResources.getIdentifier(
                name,
                name,
                "string",
                "array",
                "com.android.intenal.flaggedresources");
                "com.android.intenal.flaggedresources");
        assertThat(resId).isNotEqualTo(0);
        assertThat(resId).isNotEqualTo(0);
        return mResources.getString(resId);
        return mResources.getIntArray(resId);
    }
    }


    private String extractApkAndGetPath(int id) throws Exception {
    private String extractApkAndGetPath(int id) throws Exception {
+38 −23
Original line number Original line Diff line number Diff line
@@ -151,6 +151,7 @@ static bool AddResourcesToTable(ResourceTable* table, android::IDiagnostics* dia
  }
  }


  if (res->value != nullptr) {
  if (res->value != nullptr) {
    res->value->SetFlagStatus(res->flag_status);
    // Attach the comment, source and config to the value.
    // Attach the comment, source and config to the value.
    res->value->SetComment(std::move(res->comment));
    res->value->SetComment(std::move(res->comment));
    res->value->SetSource(std::move(res->source));
    res->value->SetSource(std::move(res->source));
@@ -546,30 +547,11 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
  });
  });


  std::string resource_type = parser->element_name();
  std::string resource_type = parser->element_name();
  std::optional<StringPiece> flag =
  auto flag_status = GetFlagStatus(parser);
      xml::FindAttribute(parser, "http://schemas.android.com/apk/res/android", "featureFlag");
  if (!flag_status) {
  out_resource->flag_status = FlagStatus::NoFlag;
  if (flag) {
    auto flag_it = options_.feature_flag_values.find(flag.value());
    if (flag_it == options_.feature_flag_values.end()) {
      diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number()))
                   << "Resource flag value undefined");
      return false;
    }
    const auto& flag_properties = flag_it->second;
    if (!flag_properties.read_only) {
      diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number()))
                   << "Only read only flags may be used with resources");
    return false;
    return false;
  }
  }
    if (!flag_properties.enabled.has_value()) {
  out_resource->flag_status = flag_status.value();
      diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number()))
                   << "Only flags with a value may be used with resources");
      return false;
    }
    out_resource->flag_status =
        flag_properties.enabled.value() ? FlagStatus::Enabled : FlagStatus::Disabled;
  }


  // The value format accepted for this resource.
  // The value format accepted for this resource.
  uint32_t resource_format = 0u;
  uint32_t resource_format = 0u;
@@ -751,6 +733,33 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
  return false;
  return false;
}
}


std::optional<FlagStatus> ResourceParser::GetFlagStatus(xml::XmlPullParser* parser) {
  auto flag_status = FlagStatus::NoFlag;

  std::optional<StringPiece> flag = xml::FindAttribute(parser, xml::kSchemaAndroid, "featureFlag");
  if (flag) {
    auto flag_it = options_.feature_flag_values.find(flag.value());
    if (flag_it == options_.feature_flag_values.end()) {
      diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number()))
                   << "Resource flag value undefined");
      return {};
    }
    const auto& flag_properties = flag_it->second;
    if (!flag_properties.read_only) {
      diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number()))
                   << "Only read only flags may be used with resources");
      return {};
    }
    if (!flag_properties.enabled.has_value()) {
      diag_->Error(android::DiagMessage(source_.WithLine(parser->line_number()))
                   << "Only flags with a value may be used with resources");
      return {};
    }
    flag_status = flag_properties.enabled.value() ? FlagStatus::Enabled : FlagStatus::Disabled;
  }
  return flag_status;
}

bool ResourceParser::ParseItem(xml::XmlPullParser* parser,
bool ResourceParser::ParseItem(xml::XmlPullParser* parser,
                               ParsedResource* out_resource,
                               ParsedResource* out_resource,
                               const uint32_t format) {
                               const uint32_t format) {
@@ -1657,12 +1666,18 @@ bool ResourceParser::ParseArrayImpl(xml::XmlPullParser* parser,
    const std::string& element_namespace = parser->element_namespace();
    const std::string& element_namespace = parser->element_namespace();
    const std::string& element_name = parser->element_name();
    const std::string& element_name = parser->element_name();
    if (element_namespace.empty() && element_name == "item") {
    if (element_namespace.empty() && element_name == "item") {
      auto flag_status = GetFlagStatus(parser);
      if (!flag_status) {
        error = true;
        continue;
      }
      std::unique_ptr<Item> item = ParseXml(parser, typeMask, kNoRawString);
      std::unique_ptr<Item> item = ParseXml(parser, typeMask, kNoRawString);
      if (!item) {
      if (!item) {
        diag_->Error(android::DiagMessage(item_source) << "could not parse array item");
        diag_->Error(android::DiagMessage(item_source) << "could not parse array item");
        error = true;
        error = true;
        continue;
        continue;
      }
      }
      item->SetFlagStatus(flag_status.value());
      item->SetSource(item_source);
      item->SetSource(item_source);
      array->elements.emplace_back(std::move(item));
      array->elements.emplace_back(std::move(item));


+2 −0
Original line number Original line Diff line number Diff line
@@ -85,6 +85,8 @@ class ResourceParser {
 private:
 private:
  DISALLOW_COPY_AND_ASSIGN(ResourceParser);
  DISALLOW_COPY_AND_ASSIGN(ResourceParser);


  std::optional<FlagStatus> GetFlagStatus(xml::XmlPullParser* parser);

  std::optional<FlattenedXmlSubTree> CreateFlattenSubTree(xml::XmlPullParser* parser);
  std::optional<FlattenedXmlSubTree> CreateFlattenSubTree(xml::XmlPullParser* parser);


  // Parses the XML subtree as a StyleString (flattened XML representation for strings with
  // Parses the XML subtree as a StyleString (flattened XML representation for strings with
+3 −4
Original line number Original line Diff line number Diff line
@@ -605,11 +605,11 @@ bool ResourceTable::AddResource(NewResource&& res, android::IDiagnostics* diag)
    if (!config_value->value) {
    if (!config_value->value) {
      // Resource does not exist, add it now.
      // Resource does not exist, add it now.
      config_value->value = std::move(res.value);
      config_value->value = std::move(res.value);
      config_value->flag_status = res.flag_status;
    } else {
    } else {
      // When validation is enabled, ensure that a resource cannot have multiple values defined for
      // When validation is enabled, ensure that a resource cannot have multiple values defined for
      // the same configuration unless protected by flags.
      // the same configuration unless protected by flags.
      auto result = validate ? ResolveFlagCollision(config_value->flag_status, res.flag_status)
      auto result =
          validate ? ResolveFlagCollision(config_value->value->GetFlagStatus(), res.flag_status)
                   : CollisionResult::kKeepBoth;
                   : CollisionResult::kKeepBoth;
      if (result == CollisionResult::kConflict) {
      if (result == CollisionResult::kConflict) {
        result = ResolveValueCollision(config_value->value.get(), res.value.get());
        result = ResolveValueCollision(config_value->value.get(), res.value.get());
@@ -619,7 +619,6 @@ bool ResourceTable::AddResource(NewResource&& res, android::IDiagnostics* diag)
          // Insert the value ignoring for duplicate configurations
          // Insert the value ignoring for duplicate configurations
          entry->values.push_back(util::make_unique<ResourceConfigValue>(res.config, res.product));
          entry->values.push_back(util::make_unique<ResourceConfigValue>(res.config, res.product));
          entry->values.back()->value = std::move(res.value);
          entry->values.back()->value = std::move(res.value);
          entry->values.back()->flag_status = res.flag_status;
          break;
          break;


        case CollisionResult::kTakeNew:
        case CollisionResult::kTakeNew:
+0 −2
Original line number Original line Diff line number Diff line
@@ -104,8 +104,6 @@ class ResourceConfigValue {
  // The actual Value.
  // The actual Value.
  std::unique_ptr<Value> value;
  std::unique_ptr<Value> value;


  FlagStatus flag_status = FlagStatus::NoFlag;

  ResourceConfigValue(const android::ConfigDescription& config, android::StringPiece product)
  ResourceConfigValue(const android::ConfigDescription& config, android::StringPiece product)
      : config(config), product(product) {
      : config(config), product(product) {
  }
  }
Loading