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

Commit e753ffef authored by Ryan Mitchell's avatar Ryan Mitchell
Browse files

Idmap format changes for bidirectional lookup

This change modifies the idmap file format to allow for target resources
to map to arbitrary type/value combinations and to allow overlay
resources to be mapped back to target resource ids so references to
overlay resources can appear as references to target resources at
runtime.

The mappings of target resources to overlay resources and vice-versa are
both encoded as sparse arrays. Instead of looking up a resource by
indexing into an array that maps to the overlay resource id, the runtime
will binary search over the sparse array to find the type and value that
overlays the target resource.

Bug: 135943783
Test: idmap2_tests
Change-Id: I5d5344cdb7fe35f4f2e8d6781016299dea5d1e20
parent 1ec87b3c
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -180,11 +180,11 @@ Result<Unit> Scan(const std::vector<std::string>& args) {

    // Note that conditional property enablement/exclusion only applies if
    // the attribute is present. In its absence, all overlays are presumed enabled.
    if (!overlay_info->requiredSystemPropertyName.empty()
        && !overlay_info->requiredSystemPropertyValue.empty()) {
    if (!overlay_info->requiredSystemPropertyName.empty() &&
        !overlay_info->requiredSystemPropertyValue.empty()) {
      // if property set & equal to value, then include overlay - otherwise skip
      if (android::base::GetProperty(overlay_info->requiredSystemPropertyName, "")
          != overlay_info->requiredSystemPropertyValue) {
      if (android::base::GetProperty(overlay_info->requiredSystemPropertyName, "") !=
          overlay_info->requiredSystemPropertyValue) {
        continue;
      }
    }
+2 −1
Original line number Diff line number Diff line
@@ -34,9 +34,10 @@ class BinaryStreamVisitor : public Visitor {
  void visit(const IdmapHeader& header) override;
  void visit(const IdmapData& data) override;
  void visit(const IdmapData::Header& header) override;
  void visit(const IdmapData::TypeEntry& type_entry) override;

 private:
  void Write(const void* value, size_t length);
  void Write8(uint8_t value);
  void Write16(uint16_t value);
  void Write32(uint32_t value);
  void WriteString(const StringPiece& value);
+55 −44
Original line number Diff line number Diff line
@@ -41,6 +41,18 @@
 * # idmap file format changelog
 * ## v1
 * - Identical to idmap v1.
 * ## v2
 * - Entries are no longer separated by type into type specific data blocks.
 * - Added overlay-indexed target resource id lookup capabilities.
 * - Target and overlay entries are stored as a sparse array in the data block. The target entries
 *   array maps from target resource id to overlay data type and value and the array is sorted by
 *   target resource id. The overlay entries array maps from overlay resource id to target resource
 *   id and the array is sorted by overlay resource id. It is important for both arrays to be sorted
 *   to allow for O(log(number_of_overlaid_resources)) performance when looking up resource
 *   mappings at runtime.
 * - Idmap can now encode a type and value to override a resource without needing a table entry.
 * - A string pool block is included to retrieve the value of strings that do not have a resource
 *   table entry.
 */

#ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
@@ -125,7 +137,6 @@ class IdmapHeader {
  friend Idmap;
  DISALLOW_COPY_AND_ASSIGN(IdmapHeader);
};

class IdmapData {
 public:
  class Header {
@@ -136,60 +147,51 @@ class IdmapData {
      return target_package_id_;
    }

    inline uint16_t GetTypeCount() const {
      return type_count_;
    inline PackageId GetOverlayPackageId() const {
      return overlay_package_id_;
    }

    void accept(Visitor* v) const;

   private:
    Header() {
    inline uint32_t GetTargetEntryCount() const {
      return target_entry_count;
    }

    PackageId target_package_id_;
    uint16_t type_count_;

    friend IdmapData;
    DISALLOW_COPY_AND_ASSIGN(Header);
  };

  class TypeEntry {
   public:
    static std::unique_ptr<const TypeEntry> FromBinaryStream(std::istream& stream);

    inline TypeId GetTargetTypeId() const {
      return target_type_id_;
    inline uint32_t GetOverlayEntryCount() const {
      return overlay_entry_count;
    }

    inline TypeId GetOverlayTypeId() const {
      return overlay_type_id_;
    inline uint32_t GetStringPoolIndexOffset() const {
      return string_pool_index_offset;
    }

    inline uint16_t GetEntryCount() const {
      return entries_.size();
    }

    inline uint16_t GetEntryOffset() const {
      return entry_offset_;
    }

    inline EntryId GetEntry(size_t i) const {
      return i < entries_.size() ? entries_[i] : 0xffffu;
    inline uint32_t GetStringPoolLength() const {
      return string_pool_len;
    }

    void accept(Visitor* v) const;

   private:
    TypeEntry() {
    }

    TypeId target_type_id_;
    TypeId overlay_type_id_;
    uint16_t entry_offset_;
    std::vector<EntryId> entries_;
    PackageId target_package_id_;
    PackageId overlay_package_id_;
    uint32_t target_entry_count;
    uint32_t overlay_entry_count;
    uint32_t string_pool_index_offset;
    uint32_t string_pool_len;
    Header() = default;

    friend Idmap;
    friend IdmapData;
    DISALLOW_COPY_AND_ASSIGN(TypeEntry);
    DISALLOW_COPY_AND_ASSIGN(Header);
  };

  struct TargetEntry {
    ResourceId target_id;
    TargetValue::DataType data_type;
    TargetValue::DataValue data_value;
  };

  struct OverlayEntry {
    ResourceId overlay_id;
    ResourceId target_id;
  };

  static std::unique_ptr<const IdmapData> FromBinaryStream(std::istream& stream);
@@ -201,8 +203,16 @@ class IdmapData {
    return header_;
  }

  inline const std::vector<std::unique_ptr<const TypeEntry>>& GetTypeEntries() const {
    return type_entries_;
  inline const std::vector<TargetEntry>& GetTargetEntries() const {
    return target_entries_;
  }

  inline const std::vector<OverlayEntry>& GetOverlayEntries() const {
    return overlay_entries_;
  }

  inline const void* GetStringPoolData() const {
    return string_pool_.get();
  }

  void accept(Visitor* v) const;
@@ -212,7 +222,9 @@ class IdmapData {
  }

  std::unique_ptr<const Header> header_;
  std::vector<std::unique_ptr<const TypeEntry>> type_entries_;
  std::vector<TargetEntry> target_entries_;
  std::vector<OverlayEntry> overlay_entries_;
  std::unique_ptr<uint8_t[]> string_pool_;

  friend Idmap;
  DISALLOW_COPY_AND_ASSIGN(IdmapData);
@@ -262,7 +274,6 @@ class Visitor {
  virtual void visit(const IdmapHeader& header) = 0;
  virtual void visit(const IdmapData& data) = 0;
  virtual void visit(const IdmapData::Header& header) = 0;
  virtual void visit(const IdmapData::TypeEntry& type_entry) = 0;
};

}  // namespace android::idmap2
+0 −2
Original line number Diff line number Diff line
@@ -38,13 +38,11 @@ class PrettyPrintVisitor : public Visitor {
  void visit(const IdmapHeader& header) override;
  void visit(const IdmapData& data) override;
  void visit(const IdmapData::Header& header) override;
  void visit(const IdmapData::TypeEntry& type_entry) override;

 private:
  std::ostream& stream_;
  std::unique_ptr<const ApkAssets> target_apk_;
  AssetManager2 target_am_;
  PackageId last_seen_package_id_;
};

}  // namespace idmap2
+4 −2
Original line number Diff line number Diff line
@@ -39,18 +39,20 @@ class RawPrintVisitor : public Visitor {
  void visit(const IdmapHeader& header) override;
  void visit(const IdmapData& data) override;
  void visit(const IdmapData::Header& header) override;
  void visit(const IdmapData::TypeEntry& type_entry) override;

 private:
  void print(uint8_t value, const char* fmt, ...);
  void print(uint16_t value, const char* fmt, ...);
  void print(uint32_t value, const char* fmt, ...);
  void print(const std::string& value, const char* fmt, ...);
  void print_raw(uint32_t length, const char* fmt, ...);

  std::ostream& stream_;
  std::unique_ptr<const ApkAssets> target_apk_;
  std::unique_ptr<const ApkAssets> overlay_apk_;
  AssetManager2 target_am_;
  AssetManager2 overlay_am_;
  size_t offset_;
  PackageId last_seen_package_id_;
};

}  // namespace idmap2
Loading