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

Commit 08c54a71 authored by Jeremy Meyer's avatar Jeremy Meyer
Browse files

Persist whether xml resources have flags

This stores whether an xml document has feature flags in it in a
ResTable_entry so that at runtime we can know not to do extra work
looking for flags.

Test: Automation
Bug: 377974898
Flag: android.content.res.layout_readwrite_flags

Change-Id: Id43b2d9941d1fab8c654d081bf19df5a33a464f3
parent 61c93118
Loading
Loading
Loading
Loading
+66 −28
Original line number Diff line number Diff line
@@ -6557,6 +6557,44 @@ bool ResTable::getResourceFlags(uint32_t resID, uint32_t* outFlags) const {
  return true;
}

bool ResTable::getResourceEntryFlags(uint32_t resID, uint32_t* outFlags) const {
  if (mError != NO_ERROR) {
    return false;
  }

  const ssize_t p = getResourcePackageIndex(resID);
  const int t = Res_GETTYPE(resID);
  const int e = Res_GETENTRY(resID);

  if (p < 0) {
    if (Res_GETPACKAGE(resID)+1 == 0) {
      ALOGW("No package identifier when getting flags for resource number 0x%08x", resID);
    } else {
      ALOGW("No known package when getting flags for resource number 0x%08x", resID);
    }
    return false;
  }
  if (t < 0) {
    ALOGW("No type identifier when getting flags for resource number 0x%08x", resID);
    return false;
  }

  const PackageGroup* const grp = mPackageGroups[p];
  if (grp == NULL) {
    ALOGW("Bad identifier when getting flags for resource number 0x%08x", resID);
    return false;
  }

  Entry entry;
  status_t err = getEntry(grp, t, e, NULL, &entry);
  if (err != NO_ERROR) {
    return false;
  }

  *outFlags = entry.entry->flags();
  return true;
}

bool ResTable::isPackageDynamic(uint8_t packageID) const {
  if (mError != NO_ERROR) {
      return false;
+5 −0
Original line number Diff line number Diff line
@@ -1593,6 +1593,8 @@ union ResTable_entry
        // If set, this is a compact entry with data type and value directly
        // encoded in the this entry, see ResTable_entry::compact
        FLAG_COMPACT = 0x0008,
        // If set, this entry relies on read write android feature flags
        FLAG_USES_FEATURE_FLAGS = 0x0010,
    };

    struct Full {
@@ -1622,6 +1624,7 @@ union ResTable_entry
    uint16_t flags()  const { return dtohs(full.flags); };
    bool is_compact() const { return flags() & FLAG_COMPACT; }
    bool is_complex() const { return flags() & FLAG_COMPLEX; }
    bool uses_feature_flags() const { return flags() & FLAG_USES_FEATURE_FLAGS; }

    size_t size() const {
        return is_compact() ? sizeof(ResTable_entry) : dtohs(this->full.size);
@@ -2039,6 +2042,8 @@ public:

    bool getResourceFlags(uint32_t resID, uint32_t* outFlags) const;

    bool getResourceEntryFlags(uint32_t resID, uint32_t* outFlags) const;

    /**
     * Returns whether or not the package for the given resource has been dynamically assigned.
     * If the resource can't be found, returns 'false'.
+2 −0
Original line number Diff line number Diff line
@@ -249,6 +249,8 @@ struct ResourceFile {

  // Flag
  std::optional<FeatureFlagAttribute> flag;

  bool uses_readwrite_feature_flags = false;
};

/**
+9 −0
Original line number Diff line number Diff line
@@ -664,6 +664,7 @@ bool ResourceTable::AddResource(NewResource&& res, android::IDiagnostics* diag)
    if (!config_value->value) {
      // Resource does not exist, add it now.
      config_value->value = std::move(res.value);
      config_value->uses_readwrite_feature_flags = res.uses_readwrite_feature_flags;
    } else {
      // When validation is enabled, ensure that a resource cannot have multiple values defined for
      // the same configuration unless protected by flags.
@@ -681,12 +682,14 @@ bool ResourceTable::AddResource(NewResource&& res, android::IDiagnostics* diag)
                               ConfigKey{&res.config, res.product}, lt_config_key_ref()),
              util::make_unique<ResourceConfigValue>(res.config, res.product));
          (*it)->value = std::move(res.value);
          (*it)->uses_readwrite_feature_flags = res.uses_readwrite_feature_flags;
          break;
        }

        case CollisionResult::kTakeNew:
          // Take the incoming value.
          config_value->value = std::move(res.value);
          config_value->uses_readwrite_feature_flags = res.uses_readwrite_feature_flags;
          break;

        case CollisionResult::kConflict:
@@ -843,6 +846,12 @@ NewResourceBuilder& NewResourceBuilder::SetAllowMangled(bool allow_mangled) {
  return *this;
}

NewResourceBuilder& NewResourceBuilder::SetUsesReadWriteFeatureFlags(
    bool uses_readwrite_feature_flags) {
  res_.uses_readwrite_feature_flags = uses_readwrite_feature_flags;
  return *this;
}

NewResource NewResourceBuilder::Build() {
  return std::move(res_);
}
+5 −0
Original line number Diff line number Diff line
@@ -104,6 +104,9 @@ class ResourceConfigValue {
  // The actual Value.
  std::unique_ptr<Value> value;

  // Whether the value uses read/write feature flags
  bool uses_readwrite_feature_flags = false;

  ResourceConfigValue(const android::ConfigDescription& config, android::StringPiece product)
      : config(config), product(product) {
  }
@@ -284,6 +287,7 @@ struct NewResource {
  std::optional<AllowNew> allow_new;
  std::optional<StagedId> staged_id;
  bool allow_mangled = false;
  bool uses_readwrite_feature_flags = false;
};

struct NewResourceBuilder {
@@ -297,6 +301,7 @@ struct NewResourceBuilder {
  NewResourceBuilder& SetAllowNew(AllowNew allow_new);
  NewResourceBuilder& SetStagedId(StagedId id);
  NewResourceBuilder& SetAllowMangled(bool allow_mangled);
  NewResourceBuilder& SetUsesReadWriteFeatureFlags(bool uses_feature_flags);
  NewResource Build();

 private:
Loading