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

Commit 4f48ffd4 authored by Yurii Zubrytskyi's avatar Yurii Zubrytskyi
Browse files

[res] Store the number of types in typeSpec

Bug: 282215580
Test: build + boot + perf record

Change-Id: Ide34e48f8ba63a38a93f0a15618d601857498683
parent 77e28bd5
Loading
Loading
Loading
Loading
+13 −9
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <algorithm>
#include <cstddef>
#include <limits>
#include <optional>

#include "android-base/logging.h"
#include "android-base/stringprintf.h"
@@ -50,7 +51,9 @@ namespace {
// contiguous block of memory to store both the TypeSpec struct and
// the Type structs.
struct TypeSpecBuilder {
  explicit TypeSpecBuilder(incfs::verified_map_ptr<ResTable_typeSpec> header) : header_(header) {}
  explicit TypeSpecBuilder(incfs::verified_map_ptr<ResTable_typeSpec> header) : header_(header) {
    type_entries.reserve(dtohs(header_->typesCount));
  }

  void AddType(incfs::verified_map_ptr<ResTable_type> type) {
    TypeSpec::TypeEntry& entry = type_entries.emplace_back();
@@ -59,6 +62,7 @@ struct TypeSpecBuilder {
  }

  TypeSpec Build() {
    type_entries.shrink_to_fit();
    return {header_, std::move(type_entries)};
  }

@@ -499,7 +503,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
  // A map of TypeSpec builders, each associated with an type index.
  // We use these to accumulate the set of Types available for a TypeSpec, and later build a single,
  // contiguous block of memory that holds all the Types together with the TypeSpec.
  std::unordered_map<int, std::unique_ptr<TypeSpecBuilder>> type_builder_map;
  std::unordered_map<int, std::optional<TypeSpecBuilder>> type_builder_map;

  ChunkIterator iter(chunk.data_ptr(), chunk.data_size());
  while (iter.HasNext()) {
@@ -567,14 +571,14 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
          return {};
        }

        if (entry_count * sizeof(uint32_t) > chunk.data_size()) {
        if (entry_count * sizeof(uint32_t) > child_chunk.data_size()) {
          LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE too small to hold entries.";
          return {};
        }

        std::unique_ptr<TypeSpecBuilder>& builder_ptr = type_builder_map[type_spec->id];
        if (builder_ptr == nullptr) {
          builder_ptr = util::make_unique<TypeSpecBuilder>(type_spec.verified());
        auto& maybe_type_builder = type_builder_map[type_spec->id];
        if (!maybe_type_builder) {
          maybe_type_builder.emplace(type_spec.verified());
          loaded_package->resource_ids_.set(type_spec->id, entry_count);
        } else {
          LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x",
@@ -594,9 +598,9 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
        }

        // Type chunks must be preceded by their TypeSpec chunks.
        std::unique_ptr<TypeSpecBuilder>& builder_ptr = type_builder_map[type->id];
        if (builder_ptr != nullptr) {
          builder_ptr->AddType(type.verified());
        auto& maybe_type_builder = type_builder_map[type->id];
        if (maybe_type_builder) {
          maybe_type_builder->AddType(type.verified());
        } else {
          LOG(ERROR) << StringPrintf(
              "RES_TABLE_TYPE_TYPE with ID %02x found without preceding RES_TABLE_TYPE_SPEC_TYPE.",
+2 −2
Original line number Diff line number Diff line
@@ -1401,8 +1401,8 @@ struct ResTable_typeSpec
    
    // Must be 0.
    uint8_t res0;
    // Must be 0.
    uint16_t res1;
    // Used to be reserved, if >0 specifies the number of ResTable_type entries for this spec.
    uint16_t typesCount;
    
    // Number of uint32_t entry configuration masks that follow.
    uint32_t entryCount;
+11 −6
Original line number Diff line number Diff line
@@ -381,7 +381,7 @@ class PackageFlattener {
    return true;
  }

  bool FlattenTypeSpec(const ResourceTableTypeView& type,
  ResTable_typeSpec* FlattenTypeSpec(const ResourceTableTypeView& type,
                                     const std::vector<ResourceTableEntryView>& sorted_entries,
                                     BigBuffer* buffer) {
    ChunkWriter type_spec_writer(buffer);
@@ -391,7 +391,7 @@ class PackageFlattener {

    if (sorted_entries.empty()) {
      type_spec_writer.Finish();
      return true;
      return spec_header;
    }

    // We can't just take the size of the vector. There may be holes in the
@@ -427,7 +427,7 @@ class PackageFlattener {
      }
    }
    type_spec_writer.Finish();
    return true;
    return spec_header;
  }

  bool FlattenTypes(BigBuffer* buffer) {
@@ -450,7 +450,8 @@ class PackageFlattener {
      expected_type_id++;
      type_pool_.MakeRef(type.named_type.to_string());

      if (!FlattenTypeSpec(type, type.entries, buffer)) {
      const auto type_spec_header = FlattenTypeSpec(type, type.entries, buffer);
      if (!type_spec_header) {
        return false;
      }

@@ -511,6 +512,10 @@ class PackageFlattener {
          return false;
        }
      }

      // And now we can update the type entries count in the typeSpec header.
      type_spec_header->typesCount = android::util::HostToDevice16(uint16_t(std::min<uint32_t>(
          config_to_entry_list_map.size(), std::numeric_limits<uint16_t>::max())));
    }
    return true;
  }