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

Commit 2ad1f912 authored by Ryan Mitchell's avatar Ryan Mitchell Committed by Android (Google) Code Review
Browse files

Merge "Sort bag by attribute key when using libs"

parents 43d10670 155d5396
Loading
Loading
Loading
Loading
+26 −3
Original line number Diff line number Diff line
@@ -992,6 +992,11 @@ const ResolvedBag* AssetManager2::GetBag(uint32_t resid) {
  return bag;
}

static bool compare_bag_entries(const ResolvedBag::Entry& entry1,
    const ResolvedBag::Entry& entry2) {
  return entry1.key < entry2.key;
}

const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector<uint32_t>& child_resids) {
  auto cached_iter = cached_bags_.find(resid);
  if (cached_iter != cached_bags_.end()) {
@@ -1027,13 +1032,15 @@ const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector<uint32_t>&
  child_resids.push_back(resid);

  uint32_t parent_resid = dtohl(map->parent.ident);
  if (parent_resid == 0 || std::find(child_resids.begin(), child_resids.end(), parent_resid)
  if (parent_resid == 0U || std::find(child_resids.begin(), child_resids.end(), parent_resid)
      != child_resids.end()) {
    // There is no parent or that a circular dependency exist, meaning there is nothing to
    // inherit and we can do a simple copy of the entries in the map.
    // There is no parent or a circular dependency exist, meaning there is nothing to inherit and
    // we can do a simple copy of the entries in the map.
    const size_t entry_count = map_entry_end - map_entry;
    util::unique_cptr<ResolvedBag> new_bag{reinterpret_cast<ResolvedBag*>(
        malloc(sizeof(ResolvedBag) + (entry_count * sizeof(ResolvedBag::Entry))))};

    bool sort_entries = false;
    ResolvedBag::Entry* new_entry = new_bag->entries;
    for (; map_entry != map_entry_end; ++map_entry) {
      uint32_t new_key = dtohl(map_entry->name.ident);
@@ -1059,8 +1066,15 @@ const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector<uint32_t>&
            new_entry->value.data, new_key);
        return nullptr;
      }
      sort_entries = sort_entries ||
          (new_entry != new_bag->entries && (new_entry->key < (new_entry - 1U)->key));
      ++new_entry;
    }

    if (sort_entries) {
      std::sort(new_bag->entries, new_bag->entries + entry_count, compare_bag_entries);
    }

    new_bag->type_spec_flags = entry.type_flags;
    new_bag->entry_count = static_cast<uint32_t>(entry_count);
    ResolvedBag* result = new_bag.get();
@@ -1091,6 +1105,7 @@ const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector<uint32_t>&
  const ResolvedBag::Entry* const parent_entry_end = parent_entry + parent_bag->entry_count;

  // The keys are expected to be in sorted order. Merge the two bags.
  bool sort_entries = false;
  while (map_entry != map_entry_end && parent_entry != parent_entry_end) {
    uint32_t child_key = dtohl(map_entry->name.ident);
    if (!is_internal_resid(child_key)) {
@@ -1123,6 +1138,8 @@ const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector<uint32_t>&
      memcpy(new_entry, parent_entry, sizeof(*new_entry));
    }

    sort_entries = sort_entries ||
        (new_entry != new_bag->entries && (new_entry->key < (new_entry - 1U)->key));
    if (child_key >= parent_entry->key) {
      // Move to the next parent entry if we used it or it was overridden.
      ++parent_entry;
@@ -1153,6 +1170,8 @@ const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector<uint32_t>&
                                       new_entry->value.dataType, new_entry->value.data, new_key);
      return nullptr;
    }
    sort_entries = sort_entries ||
        (new_entry != new_bag->entries && (new_entry->key < (new_entry - 1U)->key));
    ++map_entry;
    ++new_entry;
  }
@@ -1172,6 +1191,10 @@ const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector<uint32_t>&
        new_bag.release(), sizeof(ResolvedBag) + (actual_count * sizeof(ResolvedBag::Entry)))));
  }

  if (sort_entries) {
    std::sort(new_bag->entries, new_bag->entries + actual_count, compare_bag_entries);
  }

  // Combine flags from the parent and our own bag.
  new_bag->type_spec_flags = entry.type_flags | parent_bag->type_spec_flags;
  new_bag->entry_count = static_cast<uint32_t>(actual_count);
+21 −0
Original line number Diff line number Diff line
@@ -285,6 +285,27 @@ TEST_F(AssetManager2Test, FindsBagResourceFromSharedLibrary) {
  EXPECT_EQ(0x03, get_package_id(bag->entries[1].key));
}

TEST_F(AssetManager2Test, FindsBagResourceFromMultipleSharedLibraries) {
  AssetManager2 assetmanager;

  // libclient is built with lib_one and then lib_two in order.
  // Reverse the order to test that proper package ID re-assignment is happening.
  assetmanager.SetApkAssets(
      {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});

  const ResolvedBag* bag = assetmanager.GetBag(libclient::R::style::ThemeMultiLib);
  ASSERT_NE(nullptr, bag);
  ASSERT_EQ(bag->entry_count, 2u);

  // First attribute comes from lib_two.
  EXPECT_EQ(2, bag->entries[0].cookie);
  EXPECT_EQ(0x02, get_package_id(bag->entries[0].key));

  // The next two attributes come from lib_one.
  EXPECT_EQ(2, bag->entries[1].cookie);
  EXPECT_EQ(0x03, get_package_id(bag->entries[1].key));
}

TEST_F(AssetManager2Test, FindsStyleResourceWithParentFromSharedLibrary) {
  AssetManager2 assetmanager;

+9 −3
Original line number Diff line number Diff line
@@ -30,16 +30,22 @@ struct R {
    };
  };

  struct integer {
    enum : uint32_t {
      bar = 0x02020000, // default
    };
  };

  struct string {
    enum : uint32_t {
      LibraryString = 0x02020000,  // default
      foo = 0x02020001, // default
      LibraryString = 0x02030000,  // default
      foo = 0x02030001, // default
    };
  };

  struct style {
    enum : uint32_t {
      Theme = 0x02030000, // default
      Theme = 0x02040000, // default
    };
  };
};
+7 −4
Original line number Diff line number Diff line
@@ -18,14 +18,17 @@
    <public type="attr" name="attr3" id="0x00010000" />
    <attr name="attr3" format="integer" />

    <public type="string" name="LibraryString" id="0x00020000" />
    <public type="integer" name="bar" id="0x00020000" />
    <integer name="bar">1337</integer>

    <public type="string" name="LibraryString" id="0x00030000" />
    <string name="LibraryString">Hi from library two</string>

    <public type="string" name="foo" id="0x00020001" />
    <public type="string" name="foo" id="0x00030001" />
    <string name="foo">Foo from lib_two</string>

    <public type="style" name="Theme" id="0x02030000" />
    <public type="style" name="Theme" id="0x00040000" />
    <style name="Theme">
        <item name="com.android.lib_two:attr3">800</item>
        <item name="com.android.lib_two:attr3">@integer/bar</item>
    </style>
</resources>
Loading