Loading libs/androidfw/LoadedArsc.cpp +33 −51 Original line number Diff line number Diff line Loading @@ -409,14 +409,10 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, util::ReadUtf16StringFromDevice(header->name, arraysize(header->name), &loaded_package->package_name_); // A TypeSpec builder. We use this 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::unique_ptr<TypeSpecPtrBuilder> types_builder; // Keep track of the last seen type index. Since type IDs are 1-based, // this records their index, which is 0-based (type ID - 1). uint8_t last_type_idx = 0; // 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<TypeSpecPtrBuilder>> type_builder_map; ChunkIterator iter(chunk.data_ptr(), chunk.data_size()); while (iter.HasNext()) { Loading Loading @@ -450,28 +446,6 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, case RES_TABLE_TYPE_SPEC_TYPE: { ATRACE_NAME("LoadTableTypeSpec"); // Starting a new TypeSpec, so finish the old one if there was one. if (types_builder) { TypeSpecPtr type_spec_ptr = types_builder->Build(); if (type_spec_ptr == nullptr) { LOG(ERROR) << "Too many type configurations, overflow detected."; return {}; } // We only add the type to the package if there is no IDMAP, or if the type is // overlaying something. if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) { // If this is an overlay, insert it at the target type ID. if (type_spec_ptr->idmap_entries != nullptr) { last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1; } loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr); } types_builder = {}; last_type_idx = 0; } const ResTable_typeSpec* type_spec = child_chunk.header<ResTable_typeSpec>(); if (type_spec == nullptr) { LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE too small."; Loading Loading @@ -506,8 +480,6 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, return {}; } last_type_idx = type_spec->id - 1; // If this is an overlay, associate the mapping of this type to the target type // from the IDMAP. const IdmapEntry_header* idmap_entry_header = nullptr; Loading @@ -515,7 +487,13 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, idmap_entry_header = loaded_idmap->GetEntryMapForType(type_spec->id); } types_builder = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header); 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); } else { LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x", type_spec->id); } } break; case RES_TABLE_TYPE_TYPE: { Loading @@ -530,12 +508,15 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, } // Type chunks must be preceded by their TypeSpec chunks. if (!types_builder || type->id - 1 != last_type_idx) { LOG(ERROR) << "RES_TABLE_TYPE_TYPE found without preceding RES_TABLE_TYPE_SPEC_TYPE."; std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type->id - 1]; if (builder_ptr != nullptr) { builder_ptr->AddType(type); } else { LOG(ERROR) << StringPrintf( "RES_TABLE_TYPE_TYPE with ID %02x found without preceding RES_TABLE_TYPE_SPEC_TYPE.", type->id); return {}; } types_builder->AddType(type); } break; case RES_TABLE_LIBRARY_TYPE: { Loading @@ -561,7 +542,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, arraysize(entry_iter->packageName), &package_name); if (dtohl(entry_iter->packageId) >= std::numeric_limits<uint8_t>::max()) { LOG(ERROR) << base::StringPrintf( LOG(ERROR) << StringPrintf( "Package ID %02x in RES_TABLE_LIBRARY_TYPE too large for package '%s'.", dtohl(entry_iter->packageId), package_name.c_str()); return {}; Loading @@ -574,14 +555,20 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, } break; default: LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type()); break; } } // Finish the last TypeSpec. if (types_builder) { TypeSpecPtr type_spec_ptr = types_builder->Build(); if (iter.HadError()) { LOG(ERROR) << iter.GetLastError(); return {}; } // Flatten and construct the TypeSpecs. for (auto& entry : type_builder_map) { uint8_t type_idx = static_cast<uint8_t>(entry.first); TypeSpecPtr type_spec_ptr = entry.second->Build(); if (type_spec_ptr == nullptr) { LOG(ERROR) << "Too many type configurations, overflow detected."; return {}; Loading @@ -592,20 +579,15 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) { // If this is an overlay, insert it at the target type ID. if (type_spec_ptr->idmap_entries != nullptr) { last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1; type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1; } loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr); loaded_package->type_specs_.editItemAt(type_idx) = std::move(type_spec_ptr); } } if (iter.HadError()) { LOG(ERROR) << iter.GetLastError(); return {}; } return std::move(loaded_package); } bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, bool load_as_shared_library) { ATRACE_CALL(); Loading Loading @@ -655,7 +637,7 @@ bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, } break; default: LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type()); break; } } Loading Loading @@ -687,7 +669,7 @@ std::unique_ptr<const LoadedArsc> LoadedArsc::Load(const StringPiece& data, break; default: LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type()); break; } } Loading libs/androidfw/tests/LoadedArsc_test.cpp +42 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "androidfw/LoadedArsc.h" #include "android-base/file.h" #include "androidfw/ResourceUtils.h" #include "TestHelpers.h" Loading @@ -29,6 +30,7 @@ namespace basic = com::android::basic; namespace libclient = com::android::libclient; namespace sparse = com::android::sparse; using ::android::base::ReadFileToString; using ::testing::Eq; using ::testing::Ge; using ::testing::IsNull; Loading Loading @@ -177,6 +179,46 @@ TEST(LoadedArscTest, LoadFeatureSplit) { ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], entry_index), NotNull()); } // AAPT(2) generates resource tables with chunks in a certain order. The rule is that // a RES_TABLE_TYPE_TYPE with id `i` must always be preceded by a RES_TABLE_TYPE_SPEC_TYPE with // id `i`. The RES_TABLE_TYPE_SPEC_TYPE does not need to be directly preceding, however. // // AAPT(2) generates something like: // RES_TABLE_TYPE_SPEC_TYPE id=1 // RES_TABLE_TYPE_TYPE id=1 // RES_TABLE_TYPE_SPEC_TYPE id=2 // RES_TABLE_TYPE_TYPE id=2 // // But the following is valid too: // RES_TABLE_TYPE_SPEC_TYPE id=1 // RES_TABLE_TYPE_SPEC_TYPE id=2 // RES_TABLE_TYPE_TYPE id=1 // RES_TABLE_TYPE_TYPE id=2 // TEST(LoadedArscTest, LoadOutOfOrderTypeSpecs) { std::string contents; ASSERT_TRUE( ReadFileFromZipToString(GetTestDataPath() + "/out_of_order_types/out_of_order_types.apk", "resources.arsc", &contents)); std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents)); ASSERT_THAT(loaded_arsc, NotNull()); ASSERT_THAT(loaded_arsc->GetPackages(), SizeIs(1u)); const auto& package = loaded_arsc->GetPackages()[0]; ASSERT_THAT(package, NotNull()); const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(0); ASSERT_THAT(type_spec, NotNull()); ASSERT_THAT(type_spec->type_count, Ge(1u)); ASSERT_THAT(type_spec->types[0], NotNull()); type_spec = package->GetTypeSpecByTypeIndex(1); ASSERT_THAT(type_spec, NotNull()); ASSERT_THAT(type_spec->type_count, Ge(1u)); ASSERT_THAT(type_spec->types[0], NotNull()); } class MockLoadedIdmap : public LoadedIdmap { public: MockLoadedIdmap() : LoadedIdmap() { Loading libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml 0 → 100644 +18 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2018 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.app" /> libs/androidfw/tests/data/out_of_order_types/build 0 → 100755 +22 −0 Original line number Diff line number Diff line #!/bin/bash # # Copyright (C) 2018 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # set -e aapt2 compile --dir res -o compiled.flata aapt2 link --manifest AndroidManifest.xml -o out_of_order_types.apk compiled.flata rm compiled.flata libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt 0 → 100644 +43 −0 Original line number Diff line number Diff line 00000000: 0200 0c00 ac02 0000 0100 0000 0100 1c00 ................ 00000010: 1c00 0000 0000 0000 0000 0000 0001 0000 ................ 00000020: 1c00 0000 0000 0000 0002 2001 8402 0000 .......... ..... 00000030: 7f00 0000 6300 6f00 6d00 2e00 6100 6e00 ....c.o.m...a.n. 00000040: 6400 7200 6f00 6900 6400 2e00 6100 7000 d.r.o.i.d...a.p. 00000050: 7000 0000 0000 0000 0000 0000 0000 0000 p............... 00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000000a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000000b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000000c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000000d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000000e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000000f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000100: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000110: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000120: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000130: 0000 0000 2001 0000 0000 0000 6401 0000 .... .......d... 00000140: 0000 0000 0000 0000 0100 1c00 4400 0000 ............D... 00000150: 0200 0000 0000 0000 0000 0000 2400 0000 ............$... 00000160: 0000 0000 0000 0000 0c00 0000 0400 6200 ..............b. 00000170: 6f00 6f00 6c00 0000 0700 6900 6e00 7400 o.o.l.....i.n.t. 00000180: 6500 6700 6500 7200 0000 0000 0100 1c00 e.g.e.r......... 00000190: 2800 0000 0100 0000 0000 0000 0001 0000 (............... 000001a0: 2000 0000 0000 0000 0000 0000 0404 7465 .............te 000001b0: 7374 0000 0202 1000 1400 0000 0100 0000 st.............. 000001c0: 0100 0000 0000 0000 0202 1000 1400 0000 000001d0: 0200 0000 0100 0000 0000 0000 0102 5400 000001e0: 6800 0000 0100 0000 0100 0000 5800 0000 000001f0: 4000 0000 0000 0000 0000 0000 0000 0000 00000200: 0000 0000 0000 0000 0000 0000 0000 0000 00000210: 0000 0000 0000 0000 0000 0000 0000 0000 00000220: 0000 0000 0000 0000 0000 0000 0000 0000 00000230: 0000 0000 0800 0000 0000 0000 0800 0012 00000240: ffff ffff 0102 5400 6800 0000 0200 0000 ......T.h....... 00000250: 0100 0000 5800 0000 4000 0000 0000 0000 ....X...@....... 00000260: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000270: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000280: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000290: 0000 0000 0000 0000 0000 0000 0800 0000 ................ 000002a0: 0000 0000 0800 0010 0100 0000 ............ Loading
libs/androidfw/LoadedArsc.cpp +33 −51 Original line number Diff line number Diff line Loading @@ -409,14 +409,10 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, util::ReadUtf16StringFromDevice(header->name, arraysize(header->name), &loaded_package->package_name_); // A TypeSpec builder. We use this 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::unique_ptr<TypeSpecPtrBuilder> types_builder; // Keep track of the last seen type index. Since type IDs are 1-based, // this records their index, which is 0-based (type ID - 1). uint8_t last_type_idx = 0; // 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<TypeSpecPtrBuilder>> type_builder_map; ChunkIterator iter(chunk.data_ptr(), chunk.data_size()); while (iter.HasNext()) { Loading Loading @@ -450,28 +446,6 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, case RES_TABLE_TYPE_SPEC_TYPE: { ATRACE_NAME("LoadTableTypeSpec"); // Starting a new TypeSpec, so finish the old one if there was one. if (types_builder) { TypeSpecPtr type_spec_ptr = types_builder->Build(); if (type_spec_ptr == nullptr) { LOG(ERROR) << "Too many type configurations, overflow detected."; return {}; } // We only add the type to the package if there is no IDMAP, or if the type is // overlaying something. if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) { // If this is an overlay, insert it at the target type ID. if (type_spec_ptr->idmap_entries != nullptr) { last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1; } loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr); } types_builder = {}; last_type_idx = 0; } const ResTable_typeSpec* type_spec = child_chunk.header<ResTable_typeSpec>(); if (type_spec == nullptr) { LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE too small."; Loading Loading @@ -506,8 +480,6 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, return {}; } last_type_idx = type_spec->id - 1; // If this is an overlay, associate the mapping of this type to the target type // from the IDMAP. const IdmapEntry_header* idmap_entry_header = nullptr; Loading @@ -515,7 +487,13 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, idmap_entry_header = loaded_idmap->GetEntryMapForType(type_spec->id); } types_builder = util::make_unique<TypeSpecPtrBuilder>(type_spec, idmap_entry_header); 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); } else { LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x", type_spec->id); } } break; case RES_TABLE_TYPE_TYPE: { Loading @@ -530,12 +508,15 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, } // Type chunks must be preceded by their TypeSpec chunks. if (!types_builder || type->id - 1 != last_type_idx) { LOG(ERROR) << "RES_TABLE_TYPE_TYPE found without preceding RES_TABLE_TYPE_SPEC_TYPE."; std::unique_ptr<TypeSpecPtrBuilder>& builder_ptr = type_builder_map[type->id - 1]; if (builder_ptr != nullptr) { builder_ptr->AddType(type); } else { LOG(ERROR) << StringPrintf( "RES_TABLE_TYPE_TYPE with ID %02x found without preceding RES_TABLE_TYPE_SPEC_TYPE.", type->id); return {}; } types_builder->AddType(type); } break; case RES_TABLE_LIBRARY_TYPE: { Loading @@ -561,7 +542,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, arraysize(entry_iter->packageName), &package_name); if (dtohl(entry_iter->packageId) >= std::numeric_limits<uint8_t>::max()) { LOG(ERROR) << base::StringPrintf( LOG(ERROR) << StringPrintf( "Package ID %02x in RES_TABLE_LIBRARY_TYPE too large for package '%s'.", dtohl(entry_iter->packageId), package_name.c_str()); return {}; Loading @@ -574,14 +555,20 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, } break; default: LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type()); break; } } // Finish the last TypeSpec. if (types_builder) { TypeSpecPtr type_spec_ptr = types_builder->Build(); if (iter.HadError()) { LOG(ERROR) << iter.GetLastError(); return {}; } // Flatten and construct the TypeSpecs. for (auto& entry : type_builder_map) { uint8_t type_idx = static_cast<uint8_t>(entry.first); TypeSpecPtr type_spec_ptr = entry.second->Build(); if (type_spec_ptr == nullptr) { LOG(ERROR) << "Too many type configurations, overflow detected."; return {}; Loading @@ -592,20 +579,15 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, if (loaded_idmap == nullptr || type_spec_ptr->idmap_entries != nullptr) { // If this is an overlay, insert it at the target type ID. if (type_spec_ptr->idmap_entries != nullptr) { last_type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1; type_idx = dtohs(type_spec_ptr->idmap_entries->target_type_id) - 1; } loaded_package->type_specs_.editItemAt(last_type_idx) = std::move(type_spec_ptr); loaded_package->type_specs_.editItemAt(type_idx) = std::move(type_spec_ptr); } } if (iter.HadError()) { LOG(ERROR) << iter.GetLastError(); return {}; } return std::move(loaded_package); } bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, bool load_as_shared_library) { ATRACE_CALL(); Loading Loading @@ -655,7 +637,7 @@ bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, } break; default: LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type()); break; } } Loading Loading @@ -687,7 +669,7 @@ std::unique_ptr<const LoadedArsc> LoadedArsc::Load(const StringPiece& data, break; default: LOG(WARNING) << base::StringPrintf("Unknown chunk type '%02x'.", chunk.type()); LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type()); break; } } Loading
libs/androidfw/tests/LoadedArsc_test.cpp +42 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "androidfw/LoadedArsc.h" #include "android-base/file.h" #include "androidfw/ResourceUtils.h" #include "TestHelpers.h" Loading @@ -29,6 +30,7 @@ namespace basic = com::android::basic; namespace libclient = com::android::libclient; namespace sparse = com::android::sparse; using ::android::base::ReadFileToString; using ::testing::Eq; using ::testing::Ge; using ::testing::IsNull; Loading Loading @@ -177,6 +179,46 @@ TEST(LoadedArscTest, LoadFeatureSplit) { ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], entry_index), NotNull()); } // AAPT(2) generates resource tables with chunks in a certain order. The rule is that // a RES_TABLE_TYPE_TYPE with id `i` must always be preceded by a RES_TABLE_TYPE_SPEC_TYPE with // id `i`. The RES_TABLE_TYPE_SPEC_TYPE does not need to be directly preceding, however. // // AAPT(2) generates something like: // RES_TABLE_TYPE_SPEC_TYPE id=1 // RES_TABLE_TYPE_TYPE id=1 // RES_TABLE_TYPE_SPEC_TYPE id=2 // RES_TABLE_TYPE_TYPE id=2 // // But the following is valid too: // RES_TABLE_TYPE_SPEC_TYPE id=1 // RES_TABLE_TYPE_SPEC_TYPE id=2 // RES_TABLE_TYPE_TYPE id=1 // RES_TABLE_TYPE_TYPE id=2 // TEST(LoadedArscTest, LoadOutOfOrderTypeSpecs) { std::string contents; ASSERT_TRUE( ReadFileFromZipToString(GetTestDataPath() + "/out_of_order_types/out_of_order_types.apk", "resources.arsc", &contents)); std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents)); ASSERT_THAT(loaded_arsc, NotNull()); ASSERT_THAT(loaded_arsc->GetPackages(), SizeIs(1u)); const auto& package = loaded_arsc->GetPackages()[0]; ASSERT_THAT(package, NotNull()); const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(0); ASSERT_THAT(type_spec, NotNull()); ASSERT_THAT(type_spec->type_count, Ge(1u)); ASSERT_THAT(type_spec->types[0], NotNull()); type_spec = package->GetTypeSpecByTypeIndex(1); ASSERT_THAT(type_spec, NotNull()); ASSERT_THAT(type_spec->type_count, Ge(1u)); ASSERT_THAT(type_spec->types[0], NotNull()); } class MockLoadedIdmap : public LoadedIdmap { public: MockLoadedIdmap() : LoadedIdmap() { Loading
libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml 0 → 100644 +18 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2018 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.app" />
libs/androidfw/tests/data/out_of_order_types/build 0 → 100755 +22 −0 Original line number Diff line number Diff line #!/bin/bash # # Copyright (C) 2018 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # set -e aapt2 compile --dir res -o compiled.flata aapt2 link --manifest AndroidManifest.xml -o out_of_order_types.apk compiled.flata rm compiled.flata
libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt 0 → 100644 +43 −0 Original line number Diff line number Diff line 00000000: 0200 0c00 ac02 0000 0100 0000 0100 1c00 ................ 00000010: 1c00 0000 0000 0000 0000 0000 0001 0000 ................ 00000020: 1c00 0000 0000 0000 0002 2001 8402 0000 .......... ..... 00000030: 7f00 0000 6300 6f00 6d00 2e00 6100 6e00 ....c.o.m...a.n. 00000040: 6400 7200 6f00 6900 6400 2e00 6100 7000 d.r.o.i.d...a.p. 00000050: 7000 0000 0000 0000 0000 0000 0000 0000 p............... 00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000000a0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000000b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000000c0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000000d0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000000e0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 000000f0: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000100: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000110: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000120: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000130: 0000 0000 2001 0000 0000 0000 6401 0000 .... .......d... 00000140: 0000 0000 0000 0000 0100 1c00 4400 0000 ............D... 00000150: 0200 0000 0000 0000 0000 0000 2400 0000 ............$... 00000160: 0000 0000 0000 0000 0c00 0000 0400 6200 ..............b. 00000170: 6f00 6f00 6c00 0000 0700 6900 6e00 7400 o.o.l.....i.n.t. 00000180: 6500 6700 6500 7200 0000 0000 0100 1c00 e.g.e.r......... 00000190: 2800 0000 0100 0000 0000 0000 0001 0000 (............... 000001a0: 2000 0000 0000 0000 0000 0000 0404 7465 .............te 000001b0: 7374 0000 0202 1000 1400 0000 0100 0000 st.............. 000001c0: 0100 0000 0000 0000 0202 1000 1400 0000 000001d0: 0200 0000 0100 0000 0000 0000 0102 5400 000001e0: 6800 0000 0100 0000 0100 0000 5800 0000 000001f0: 4000 0000 0000 0000 0000 0000 0000 0000 00000200: 0000 0000 0000 0000 0000 0000 0000 0000 00000210: 0000 0000 0000 0000 0000 0000 0000 0000 00000220: 0000 0000 0000 0000 0000 0000 0000 0000 00000230: 0000 0000 0800 0000 0000 0000 0800 0012 00000240: ffff ffff 0102 5400 6800 0000 0200 0000 ......T.h....... 00000250: 0100 0000 5800 0000 4000 0000 0000 0000 ....X...@....... 00000260: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000270: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000280: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000290: 0000 0000 0000 0000 0000 0000 0800 0000 ................ 000002a0: 0000 0000 0800 0010 0100 0000 ............