Loading libs/androidfw/AssetManager2.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -67,10 +67,10 @@ AssetManager2::AssetManager2() { } bool AssetManager2::SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches) { bool invalidate_caches, bool filter_incompatible_configs) { apk_assets_ = apk_assets; BuildDynamicRefTable(); RebuildFilterList(); RebuildFilterList(filter_incompatible_configs); if (invalidate_caches) { InvalidateCaches(static_cast<uint32_t>(-1)); } Loading Loading @@ -825,7 +825,7 @@ uint32_t AssetManager2::GetResourceId(const std::string& resource_name, return 0u; } void AssetManager2::RebuildFilterList() { void AssetManager2::RebuildFilterList(bool filter_incompatible_configs) { for (PackageGroup& group : package_groups_) { for (ConfiguredPackage& impl : group.packages_) { // Destroy it. Loading @@ -841,7 +841,7 @@ void AssetManager2::RebuildFilterList() { for (auto iter = spec->types; iter != iter_end; ++iter) { ResTable_config this_config; this_config.copyFromDtoH((*iter)->config); if (this_config.match(configuration_)) { if (!filter_incompatible_configs || this_config.match(configuration_)) { group.configurations.push_back(this_config); group.types.push_back(*iter); } Loading libs/androidfw/LoadedArsc.cpp +34 −0 Original line number Diff line number Diff line Loading @@ -203,6 +203,39 @@ static bool VerifyResTableEntry(const ResTable_type* type, uint32_t entry_offset return true; } LoadedPackage::iterator::iterator(const LoadedPackage* lp, size_t ti, size_t ei) : loadedPackage_(lp), typeIndex_(ti), entryIndex_(ei), typeIndexEnd_(lp->resource_ids_.size() + 1) { while (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] == 0) { typeIndex_++; } } LoadedPackage::iterator& LoadedPackage::iterator::operator++() { while (typeIndex_ < typeIndexEnd_) { if (entryIndex_ + 1 < loadedPackage_->resource_ids_[typeIndex_]) { entryIndex_++; break; } entryIndex_ = 0; typeIndex_++; if (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] != 0) { break; } } return *this; } uint32_t LoadedPackage::iterator::operator*() const { if (typeIndex_ >= typeIndexEnd_) { return 0; } return make_resid(loadedPackage_->package_id_, typeIndex_ + loadedPackage_->type_id_offset_, entryIndex_); } const ResTable_entry* LoadedPackage::GetEntry(const ResTable_type* type_chunk, uint16_t entry_index) { uint32_t entry_offset = GetEntryOffset(type_chunk, entry_index); Loading Loading @@ -488,6 +521,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type_spec->id - 1]; if (builder_ptr == nullptr) { builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header); loaded_package->resource_ids_.set(type_spec->id, entry_count); } else { LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x", type_spec->id); Loading libs/androidfw/include/androidfw/AssetManager2.h +7 −2 Original line number Diff line number Diff line Loading @@ -96,7 +96,12 @@ class AssetManager2 { // Only pass invalidate_caches=false when it is known that the structure // change in ApkAssets is due to a safe addition of resources with completely // new resource IDs. bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true); // // Only pass in filter_incompatible_configs=false when you want to load all // configurations (including incompatible ones) such as when constructing an // idmap. bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true, bool filter_incompatible_configs = true); inline const std::vector<const ApkAssets*> GetApkAssets() const { return apk_assets_; Loading Loading @@ -274,7 +279,7 @@ class AssetManager2 { // Triggers the re-construction of lists of types that match the set configuration. // This should always be called when mutating the AssetManager's configuration or ApkAssets set. void RebuildFilterList(); void RebuildFilterList(bool filter_incompatible_configs = true); // AssetManager2::GetBag(resid) wraps this function to track which resource ids have already // been seen while traversing bag parents. Loading libs/androidfw/include/androidfw/LoadedArsc.h +50 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,55 @@ using TypeSpecPtr = util::unique_cptr<TypeSpec>; class LoadedPackage { public: class iterator { public: iterator& operator=(const iterator& rhs) { loadedPackage_ = rhs.loadedPackage_; typeIndex_ = rhs.typeIndex_; entryIndex_ = rhs.entryIndex_; return *this; } bool operator==(const iterator& rhs) const { return loadedPackage_ == rhs.loadedPackage_ && typeIndex_ == rhs.typeIndex_ && entryIndex_ == rhs.entryIndex_; } bool operator!=(const iterator& rhs) const { return !(*this == rhs); } iterator operator++(int) { size_t prevTypeIndex_ = typeIndex_; size_t prevEntryIndex_ = entryIndex_; operator++(); return iterator(loadedPackage_, prevTypeIndex_, prevEntryIndex_); } iterator& operator++(); uint32_t operator*() const; private: friend class LoadedPackage; iterator(const LoadedPackage* lp, size_t ti, size_t ei); const LoadedPackage* loadedPackage_; size_t typeIndex_; size_t entryIndex_; const size_t typeIndexEnd_; // STL style end, so one past the last element }; iterator begin() const { return iterator(this, 0, 0); } iterator end() const { return iterator(this, resource_ids_.size() + 1, 0); } static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk, const LoadedIdmap* loaded_idmap, bool system, bool load_as_shared_library); Loading Loading @@ -182,6 +231,7 @@ class LoadedPackage { bool overlay_ = false; ByteBucketArray<TypeSpecPtr> type_specs_; ByteBucketArray<uint32_t> resource_ids_; std::vector<DynamicPackageEntry> dynamic_package_map_; }; Loading libs/androidfw/tests/LoadedArsc_test.cpp +48 −0 Original line number Diff line number Diff line Loading @@ -278,4 +278,52 @@ TEST(LoadedArscTest, LoadOverlay) { // sizeof(Res_value) might not be backwards compatible. TEST(LoadedArscTest, LoadingShouldBeForwardsAndBackwardsCompatible) { ASSERT_TRUE(false); } TEST(LoadedArscTest, ResourceIdentifierIterator) { std::string contents; ASSERT_TRUE( ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents)); std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents)); ASSERT_NE(nullptr, loaded_arsc); const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages(); ASSERT_EQ(1u, packages.size()); EXPECT_EQ(std::string("com.android.basic"), packages[0]->GetPackageName()); const auto& loaded_package = packages[0]; auto iter = loaded_package->begin(); auto end = loaded_package->end(); ASSERT_NE(end, iter); ASSERT_EQ(0x7f010000u, *iter++); ASSERT_EQ(0x7f010001u, *iter++); ASSERT_EQ(0x7f020000u, *iter++); ASSERT_EQ(0x7f020001u, *iter++); ASSERT_EQ(0x7f030000u, *iter++); ASSERT_EQ(0x7f030001u, *iter++); ASSERT_EQ(0x7f030002u, *iter++); // note: string without default, excluded by aapt2 dump ASSERT_EQ(0x7f040000u, *iter++); ASSERT_EQ(0x7f040001u, *iter++); ASSERT_EQ(0x7f040002u, *iter++); ASSERT_EQ(0x7f040003u, *iter++); ASSERT_EQ(0x7f040004u, *iter++); ASSERT_EQ(0x7f040005u, *iter++); ASSERT_EQ(0x7f040006u, *iter++); ASSERT_EQ(0x7f040007u, *iter++); ASSERT_EQ(0x7f040008u, *iter++); ASSERT_EQ(0x7f040009u, *iter++); ASSERT_EQ(0x7f04000au, *iter++); ASSERT_EQ(0x7f04000bu, *iter++); ASSERT_EQ(0x7f04000cu, *iter++); ASSERT_EQ(0x7f04000du, *iter++); ASSERT_EQ(0x7f050000u, *iter++); ASSERT_EQ(0x7f050001u, *iter++); ASSERT_EQ(0x7f060000u, *iter++); ASSERT_EQ(0x7f070000u, *iter++); ASSERT_EQ(0x7f070001u, *iter++); ASSERT_EQ(0x7f070002u, *iter++); ASSERT_EQ(0x7f070003u, *iter++); ASSERT_EQ(end, iter); } } // namespace android Loading
libs/androidfw/AssetManager2.cpp +4 −4 Original line number Diff line number Diff line Loading @@ -67,10 +67,10 @@ AssetManager2::AssetManager2() { } bool AssetManager2::SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches) { bool invalidate_caches, bool filter_incompatible_configs) { apk_assets_ = apk_assets; BuildDynamicRefTable(); RebuildFilterList(); RebuildFilterList(filter_incompatible_configs); if (invalidate_caches) { InvalidateCaches(static_cast<uint32_t>(-1)); } Loading Loading @@ -825,7 +825,7 @@ uint32_t AssetManager2::GetResourceId(const std::string& resource_name, return 0u; } void AssetManager2::RebuildFilterList() { void AssetManager2::RebuildFilterList(bool filter_incompatible_configs) { for (PackageGroup& group : package_groups_) { for (ConfiguredPackage& impl : group.packages_) { // Destroy it. Loading @@ -841,7 +841,7 @@ void AssetManager2::RebuildFilterList() { for (auto iter = spec->types; iter != iter_end; ++iter) { ResTable_config this_config; this_config.copyFromDtoH((*iter)->config); if (this_config.match(configuration_)) { if (!filter_incompatible_configs || this_config.match(configuration_)) { group.configurations.push_back(this_config); group.types.push_back(*iter); } Loading
libs/androidfw/LoadedArsc.cpp +34 −0 Original line number Diff line number Diff line Loading @@ -203,6 +203,39 @@ static bool VerifyResTableEntry(const ResTable_type* type, uint32_t entry_offset return true; } LoadedPackage::iterator::iterator(const LoadedPackage* lp, size_t ti, size_t ei) : loadedPackage_(lp), typeIndex_(ti), entryIndex_(ei), typeIndexEnd_(lp->resource_ids_.size() + 1) { while (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] == 0) { typeIndex_++; } } LoadedPackage::iterator& LoadedPackage::iterator::operator++() { while (typeIndex_ < typeIndexEnd_) { if (entryIndex_ + 1 < loadedPackage_->resource_ids_[typeIndex_]) { entryIndex_++; break; } entryIndex_ = 0; typeIndex_++; if (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] != 0) { break; } } return *this; } uint32_t LoadedPackage::iterator::operator*() const { if (typeIndex_ >= typeIndexEnd_) { return 0; } return make_resid(loadedPackage_->package_id_, typeIndex_ + loadedPackage_->type_id_offset_, entryIndex_); } const ResTable_entry* LoadedPackage::GetEntry(const ResTable_type* type_chunk, uint16_t entry_index) { uint32_t entry_offset = GetEntryOffset(type_chunk, entry_index); Loading Loading @@ -488,6 +521,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type_spec->id - 1]; if (builder_ptr == nullptr) { builder_ptr = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header); loaded_package->resource_ids_.set(type_spec->id, entry_count); } else { LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x", type_spec->id); Loading
libs/androidfw/include/androidfw/AssetManager2.h +7 −2 Original line number Diff line number Diff line Loading @@ -96,7 +96,12 @@ class AssetManager2 { // Only pass invalidate_caches=false when it is known that the structure // change in ApkAssets is due to a safe addition of resources with completely // new resource IDs. bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true); // // Only pass in filter_incompatible_configs=false when you want to load all // configurations (including incompatible ones) such as when constructing an // idmap. bool SetApkAssets(const std::vector<const ApkAssets*>& apk_assets, bool invalidate_caches = true, bool filter_incompatible_configs = true); inline const std::vector<const ApkAssets*> GetApkAssets() const { return apk_assets_; Loading Loading @@ -274,7 +279,7 @@ class AssetManager2 { // Triggers the re-construction of lists of types that match the set configuration. // This should always be called when mutating the AssetManager's configuration or ApkAssets set. void RebuildFilterList(); void RebuildFilterList(bool filter_incompatible_configs = true); // AssetManager2::GetBag(resid) wraps this function to track which resource ids have already // been seen while traversing bag parents. Loading
libs/androidfw/include/androidfw/LoadedArsc.h +50 −0 Original line number Diff line number Diff line Loading @@ -78,6 +78,55 @@ using TypeSpecPtr = util::unique_cptr<TypeSpec>; class LoadedPackage { public: class iterator { public: iterator& operator=(const iterator& rhs) { loadedPackage_ = rhs.loadedPackage_; typeIndex_ = rhs.typeIndex_; entryIndex_ = rhs.entryIndex_; return *this; } bool operator==(const iterator& rhs) const { return loadedPackage_ == rhs.loadedPackage_ && typeIndex_ == rhs.typeIndex_ && entryIndex_ == rhs.entryIndex_; } bool operator!=(const iterator& rhs) const { return !(*this == rhs); } iterator operator++(int) { size_t prevTypeIndex_ = typeIndex_; size_t prevEntryIndex_ = entryIndex_; operator++(); return iterator(loadedPackage_, prevTypeIndex_, prevEntryIndex_); } iterator& operator++(); uint32_t operator*() const; private: friend class LoadedPackage; iterator(const LoadedPackage* lp, size_t ti, size_t ei); const LoadedPackage* loadedPackage_; size_t typeIndex_; size_t entryIndex_; const size_t typeIndexEnd_; // STL style end, so one past the last element }; iterator begin() const { return iterator(this, 0, 0); } iterator end() const { return iterator(this, resource_ids_.size() + 1, 0); } static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk, const LoadedIdmap* loaded_idmap, bool system, bool load_as_shared_library); Loading Loading @@ -182,6 +231,7 @@ class LoadedPackage { bool overlay_ = false; ByteBucketArray<TypeSpecPtr> type_specs_; ByteBucketArray<uint32_t> resource_ids_; std::vector<DynamicPackageEntry> dynamic_package_map_; }; Loading
libs/androidfw/tests/LoadedArsc_test.cpp +48 −0 Original line number Diff line number Diff line Loading @@ -278,4 +278,52 @@ TEST(LoadedArscTest, LoadOverlay) { // sizeof(Res_value) might not be backwards compatible. TEST(LoadedArscTest, LoadingShouldBeForwardsAndBackwardsCompatible) { ASSERT_TRUE(false); } TEST(LoadedArscTest, ResourceIdentifierIterator) { std::string contents; ASSERT_TRUE( ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents)); std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents)); ASSERT_NE(nullptr, loaded_arsc); const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc->GetPackages(); ASSERT_EQ(1u, packages.size()); EXPECT_EQ(std::string("com.android.basic"), packages[0]->GetPackageName()); const auto& loaded_package = packages[0]; auto iter = loaded_package->begin(); auto end = loaded_package->end(); ASSERT_NE(end, iter); ASSERT_EQ(0x7f010000u, *iter++); ASSERT_EQ(0x7f010001u, *iter++); ASSERT_EQ(0x7f020000u, *iter++); ASSERT_EQ(0x7f020001u, *iter++); ASSERT_EQ(0x7f030000u, *iter++); ASSERT_EQ(0x7f030001u, *iter++); ASSERT_EQ(0x7f030002u, *iter++); // note: string without default, excluded by aapt2 dump ASSERT_EQ(0x7f040000u, *iter++); ASSERT_EQ(0x7f040001u, *iter++); ASSERT_EQ(0x7f040002u, *iter++); ASSERT_EQ(0x7f040003u, *iter++); ASSERT_EQ(0x7f040004u, *iter++); ASSERT_EQ(0x7f040005u, *iter++); ASSERT_EQ(0x7f040006u, *iter++); ASSERT_EQ(0x7f040007u, *iter++); ASSERT_EQ(0x7f040008u, *iter++); ASSERT_EQ(0x7f040009u, *iter++); ASSERT_EQ(0x7f04000au, *iter++); ASSERT_EQ(0x7f04000bu, *iter++); ASSERT_EQ(0x7f04000cu, *iter++); ASSERT_EQ(0x7f04000du, *iter++); ASSERT_EQ(0x7f050000u, *iter++); ASSERT_EQ(0x7f050001u, *iter++); ASSERT_EQ(0x7f060000u, *iter++); ASSERT_EQ(0x7f070000u, *iter++); ASSERT_EQ(0x7f070001u, *iter++); ASSERT_EQ(0x7f070002u, *iter++); ASSERT_EQ(0x7f070003u, *iter++); ASSERT_EQ(end, iter); } } // namespace android