Loading libs/androidfw/LoadedArsc.cpp +11 −2 Original line number Diff line number Diff line Loading @@ -384,7 +384,16 @@ base::expected<uint32_t, NullOrIOError> LoadedPackage::FindEntryByName( return base::unexpected(IOError::PAGES_MISSING); } auto offset = dtohl(entry_offset_ptr.value()); uint32_t offset; uint16_t res_idx; if (type->flags & ResTable_type::FLAG_SPARSE) { auto sparse_entry = entry_offset_ptr.convert<ResTable_sparseTypeEntry>(); offset = dtohs(sparse_entry->offset) * 4u; res_idx = dtohs(sparse_entry->idx); } else { offset = dtohl(entry_offset_ptr.value()); res_idx = entry_idx; } if (offset != ResTable_type::NO_ENTRY) { auto entry = type.offset(dtohl(type->entriesStart) + offset).convert<ResTable_entry>(); if (!entry) { Loading @@ -394,7 +403,7 @@ base::expected<uint32_t, NullOrIOError> LoadedPackage::FindEntryByName( if (dtohl(entry->key.index) == static_cast<uint32_t>(*key_idx)) { // The package ID will be overridden by the caller (due to runtime assignment of package // IDs for shared libraries). return make_resid(0x00, *type_idx + type_id_offset_ + 1, entry_idx); return make_resid(0x00, *type_idx + type_id_offset_ + 1, res_idx); } } } Loading libs/androidfw/tests/LoadedArsc_test.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,38 @@ TEST(LoadedArscTest, LoadSparseEntryApp) { ASSERT_TRUE(LoadedPackage::GetEntry(type.type, entry_index).has_value()); } TEST(LoadedArscTest, FindSparseEntryApp) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/sparse/sparse.apk", "resources.arsc", &contents)); std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.length()); ASSERT_THAT(loaded_arsc, NotNull()); const LoadedPackage* package = loaded_arsc->GetPackageById(get_package_id(sparse::R::string::only_v26)); ASSERT_THAT(package, NotNull()); const uint8_t type_index = get_type_id(sparse::R::string::only_v26) - 1; const uint16_t entry_index = get_entry_id(sparse::R::string::only_v26); const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index); ASSERT_THAT(type_spec, NotNull()); ASSERT_THAT(type_spec->type_entries.size(), Ge(1u)); // Ensure that AAPT2 sparsely encoded the v26 config as expected. auto type_entry = std::find_if( type_spec->type_entries.begin(), type_spec->type_entries.end(), [](const TypeSpec::TypeEntry& x) { return x.config.sdkVersion == 26; }); ASSERT_NE(type_entry, type_spec->type_entries.end()); ASSERT_NE(type_entry->type->flags & ResTable_type::FLAG_SPARSE, 0); // Test fetching a resource with only sparsely encoded configs by name. auto id = package->FindEntryByName(u"string", u"only_v26"); ASSERT_EQ(id.value(), fix_package_id(sparse::R::string::only_v26, 0)); } TEST(LoadedArscTest, LoadSharedLibrary) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib_one/lib_one.apk", "resources.arsc", Loading libs/androidfw/tests/data/sparse/R.h +10 −9 Original line number Diff line number Diff line Loading @@ -27,21 +27,22 @@ struct R { struct integer { enum : uint32_t { foo_0 = 0x7f010000, foo_1 = 0x7f010000, foo_2 = 0x7f010000, foo_3 = 0x7f010000, foo_4 = 0x7f010000, foo_5 = 0x7f010000, foo_6 = 0x7f010000, foo_7 = 0x7f010000, foo_8 = 0x7f010000, foo_9 = 0x7f010000, foo_1 = 0x7f010001, foo_2 = 0x7f010002, foo_3 = 0x7f010003, foo_4 = 0x7f010004, foo_5 = 0x7f010005, foo_6 = 0x7f010006, foo_7 = 0x7f010007, foo_8 = 0x7f010008, foo_9 = 0x7f010009, }; }; struct string { enum : uint32_t { foo_999 = 0x7f0203e7, only_v26 = 0x7f0203e8 }; }; }; Loading libs/androidfw/tests/data/sparse/gen_strings.sh +2 −0 Original line number Diff line number Diff line Loading @@ -14,5 +14,7 @@ do fi done echo "</resources>" >> $OUTPUT_default echo " <string name=\"only_v26\">only v26</string>" >> $OUTPUT_v26 echo "</resources>" >> $OUTPUT_v26 libs/androidfw/tests/data/sparse/not_sparse.apk +184 B (60.7 KiB) File changed.No diff preview for this file type. View original file View changed file Loading
libs/androidfw/LoadedArsc.cpp +11 −2 Original line number Diff line number Diff line Loading @@ -384,7 +384,16 @@ base::expected<uint32_t, NullOrIOError> LoadedPackage::FindEntryByName( return base::unexpected(IOError::PAGES_MISSING); } auto offset = dtohl(entry_offset_ptr.value()); uint32_t offset; uint16_t res_idx; if (type->flags & ResTable_type::FLAG_SPARSE) { auto sparse_entry = entry_offset_ptr.convert<ResTable_sparseTypeEntry>(); offset = dtohs(sparse_entry->offset) * 4u; res_idx = dtohs(sparse_entry->idx); } else { offset = dtohl(entry_offset_ptr.value()); res_idx = entry_idx; } if (offset != ResTable_type::NO_ENTRY) { auto entry = type.offset(dtohl(type->entriesStart) + offset).convert<ResTable_entry>(); if (!entry) { Loading @@ -394,7 +403,7 @@ base::expected<uint32_t, NullOrIOError> LoadedPackage::FindEntryByName( if (dtohl(entry->key.index) == static_cast<uint32_t>(*key_idx)) { // The package ID will be overridden by the caller (due to runtime assignment of package // IDs for shared libraries). return make_resid(0x00, *type_idx + type_id_offset_ + 1, entry_idx); return make_resid(0x00, *type_idx + type_id_offset_ + 1, res_idx); } } } Loading
libs/androidfw/tests/LoadedArsc_test.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,38 @@ TEST(LoadedArscTest, LoadSparseEntryApp) { ASSERT_TRUE(LoadedPackage::GetEntry(type.type, entry_index).has_value()); } TEST(LoadedArscTest, FindSparseEntryApp) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/sparse/sparse.apk", "resources.arsc", &contents)); std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.length()); ASSERT_THAT(loaded_arsc, NotNull()); const LoadedPackage* package = loaded_arsc->GetPackageById(get_package_id(sparse::R::string::only_v26)); ASSERT_THAT(package, NotNull()); const uint8_t type_index = get_type_id(sparse::R::string::only_v26) - 1; const uint16_t entry_index = get_entry_id(sparse::R::string::only_v26); const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index); ASSERT_THAT(type_spec, NotNull()); ASSERT_THAT(type_spec->type_entries.size(), Ge(1u)); // Ensure that AAPT2 sparsely encoded the v26 config as expected. auto type_entry = std::find_if( type_spec->type_entries.begin(), type_spec->type_entries.end(), [](const TypeSpec::TypeEntry& x) { return x.config.sdkVersion == 26; }); ASSERT_NE(type_entry, type_spec->type_entries.end()); ASSERT_NE(type_entry->type->flags & ResTable_type::FLAG_SPARSE, 0); // Test fetching a resource with only sparsely encoded configs by name. auto id = package->FindEntryByName(u"string", u"only_v26"); ASSERT_EQ(id.value(), fix_package_id(sparse::R::string::only_v26, 0)); } TEST(LoadedArscTest, LoadSharedLibrary) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib_one/lib_one.apk", "resources.arsc", Loading
libs/androidfw/tests/data/sparse/R.h +10 −9 Original line number Diff line number Diff line Loading @@ -27,21 +27,22 @@ struct R { struct integer { enum : uint32_t { foo_0 = 0x7f010000, foo_1 = 0x7f010000, foo_2 = 0x7f010000, foo_3 = 0x7f010000, foo_4 = 0x7f010000, foo_5 = 0x7f010000, foo_6 = 0x7f010000, foo_7 = 0x7f010000, foo_8 = 0x7f010000, foo_9 = 0x7f010000, foo_1 = 0x7f010001, foo_2 = 0x7f010002, foo_3 = 0x7f010003, foo_4 = 0x7f010004, foo_5 = 0x7f010005, foo_6 = 0x7f010006, foo_7 = 0x7f010007, foo_8 = 0x7f010008, foo_9 = 0x7f010009, }; }; struct string { enum : uint32_t { foo_999 = 0x7f0203e7, only_v26 = 0x7f0203e8 }; }; }; Loading
libs/androidfw/tests/data/sparse/gen_strings.sh +2 −0 Original line number Diff line number Diff line Loading @@ -14,5 +14,7 @@ do fi done echo "</resources>" >> $OUTPUT_default echo " <string name=\"only_v26\">only v26</string>" >> $OUTPUT_v26 echo "</resources>" >> $OUTPUT_v26
libs/androidfw/tests/data/sparse/not_sparse.apk +184 B (60.7 KiB) File changed.No diff preview for this file type. View original file View changed file