Loading libs/androidfw/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -211,6 +211,8 @@ cc_test { "tests/data/**/*.apk", "tests/data/**/*.arsc", "tests/data/**/*.idmap", ":FrameworkResourcesSparseTestApp", ":FrameworkResourcesNotSparseTestApp", ], test_suites: ["device-tests"], } Loading libs/androidfw/tests/LoadedArsc_test.cpp +80 −56 Original line number Diff line number Diff line Loading @@ -71,62 +71,6 @@ TEST(LoadedArscTest, LoadSinglePackageArsc) { ASSERT_TRUE(LoadedPackage::GetEntry(type.type, entry_index).has_value()); } TEST(LoadedArscTest, LoadSparseEntryApp) { 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::integer::foo_9)); ASSERT_THAT(package, NotNull()); const uint8_t type_index = get_type_id(sparse::R::integer::foo_9) - 1; const uint16_t entry_index = get_entry_id(sparse::R::integer::foo_9); const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index); ASSERT_THAT(type_spec, NotNull()); ASSERT_THAT(type_spec->type_entries.size(), Ge(1u)); auto type = type_spec->type_entries[0]; 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 Loading @@ -404,4 +348,84 @@ TEST(LoadedArscTest, LoadCustomLoader) { // sizeof(Res_value) might not be backwards compatible. // TEST(LoadedArscTest, LoadingShouldBeForwardsAndBackwardsCompatible) { ASSERT_TRUE(false); } class LoadedArscParameterizedTest : public testing::TestWithParam<std::string> { }; TEST_P(LoadedArscParameterizedTest, LoadSparseEntryApp) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetParam(), "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::integer::foo_9)); ASSERT_THAT(package, NotNull()); const uint8_t type_index = get_type_id(sparse::R::integer::foo_9) - 1; const uint16_t entry_index = get_entry_id(sparse::R::integer::foo_9); const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index); ASSERT_THAT(type_spec, NotNull()); ASSERT_THAT(type_spec->type_entries.size(), Ge(1u)); auto type = type_spec->type_entries[0]; ASSERT_TRUE(LoadedPackage::GetEntry(type.type, entry_index).has_value()); } TEST_P(LoadedArscParameterizedTest, FindSparseEntryApp) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetParam(), "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_land)); ASSERT_THAT(package, NotNull()); const uint8_t type_index = get_type_id(sparse::R::string::only_land) - 1; const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index); ASSERT_THAT(type_spec, NotNull()); ASSERT_THAT(type_spec->type_entries.size(), Ge(1u)); // Type Entry with default orientation is not sparse encoded because the ratio of // populated entries to total entries is above threshold. // Only find out default locale because Soong build system will introduce pseudo // locales for the apk generated at runtime. auto type_entry_default = std::find_if( type_spec->type_entries.begin(), type_spec->type_entries.end(), [] (const TypeSpec::TypeEntry& x) { return x.config.orientation == 0 && x.config.locale == 0; }); ASSERT_NE(type_entry_default, type_spec->type_entries.end()); ASSERT_EQ(type_entry_default->type->flags & ResTable_type::FLAG_SPARSE, 0); // Type Entry with land orientation is sparse encoded as expected. // Only find out default locale because Soong build system will introduce pseudo // locales for the apk generated at runtime. auto type_entry_land = std::find_if( type_spec->type_entries.begin(), type_spec->type_entries.end(), [](const TypeSpec::TypeEntry& x) { return x.config.orientation == ResTable_config::ORIENTATION_LAND && x.config.locale == 0; }); ASSERT_NE(type_entry_land, type_spec->type_entries.end()); ASSERT_NE(type_entry_land->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_land"); ASSERT_EQ(id.value(), fix_package_id(sparse::R::string::only_land, 0)); } INSTANTIATE_TEST_SUITE_P( FrameWorkResourcesLoadedArscTests, LoadedArscParameterizedTest, ::testing::Values( base::GetExecutableDirectory() + "/tests/data/sparse/sparse.apk", base::GetExecutableDirectory() + "/FrameworkResourcesSparseTestApp.apk" )); } // namespace android libs/androidfw/tests/ResTable_test.cpp +40 −28 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ #include "androidfw/ResourceTypes.h" #include "android-base/file.h" #include <codecvt> #include <locale> Loading @@ -41,34 +42,6 @@ TEST(ResTableTest, ShouldLoadSuccessfully) { ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size())); } TEST(ResTableTest, ShouldLoadSparseEntriesSuccessfully) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/sparse/sparse.apk", "resources.arsc", &contents)); ResTable table; ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size())); ResTable_config config; memset(&config, 0, sizeof(config)); config.sdkVersion = 26; table.setParameters(&config); String16 name(u"com.android.sparse:integer/foo_9"); uint32_t flags; uint32_t resid = table.identifierForName(name.string(), name.size(), nullptr, 0, nullptr, 0, &flags); ASSERT_NE(0u, resid); Res_value val; ResTable_config selected_config; ASSERT_GE( table.getResource(resid, &val, false /*mayBeBag*/, 0u /*density*/, &flags, &selected_config), 0); EXPECT_EQ(Res_value::TYPE_INT_DEC, val.dataType); EXPECT_EQ(900u, val.data); } TEST(ResTableTest, SimpleTypeIsRetrievedCorrectly) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", Loading Loading @@ -476,4 +449,43 @@ TEST(ResTableTest, TruncatedEncodeLength) { ASSERT_FALSE(invalid_pool->stringAt(invalid_val.data).has_value()); } class ResTableParameterizedTest : public testing::TestWithParam<std::string> { }; TEST_P(ResTableParameterizedTest, ShouldLoadSparseEntriesSuccessfully) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetParam(), "resources.arsc", &contents)); ResTable table; ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size())); ResTable_config config; memset(&config, 0, sizeof(config)); config.orientation = ResTable_config::ORIENTATION_LAND; table.setParameters(&config); String16 name(u"com.android.sparse:integer/foo_9"); uint32_t flags; uint32_t resid = table.identifierForName(name.string(), name.size(), nullptr, 0, nullptr, 0, &flags); ASSERT_NE(0u, resid); Res_value val; ResTable_config selected_config; ASSERT_GE( table.getResource(resid, &val, false /*mayBeBag*/, 0u /*density*/, &flags, &selected_config), 0); EXPECT_EQ(Res_value::TYPE_INT_DEC, val.dataType); EXPECT_EQ(900u, val.data); } INSTANTIATE_TEST_SUITE_P( FrameWorkResourcesResTableTests, ResTableParameterizedTest, ::testing::Values( base::GetExecutableDirectory() + "/tests/data/sparse/sparse.apk", base::GetExecutableDirectory() + "/FrameworkResourcesSparseTestApp.apk" )); } // namespace android libs/androidfw/tests/SparseEntry_bench.cpp +51 −16 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "androidfw/AssetManager.h" #include "androidfw/ResourceTypes.h" #include "android-base/file.h" #include "BenchmarkHelpers.h" #include "data/sparse/R.h" Loading @@ -24,40 +25,74 @@ namespace sparse = com::android::sparse; namespace android { static void BM_SparseEntryGetResourceOldSparse(benchmark::State& state, uint32_t resid) { static void BM_SparseEntryGetResourceHelper(const std::vector<std::string>& paths, uint32_t resid, benchmark::State& state, void (*GetResourceBenchmarkFunc)( const std::vector<std::string>&, const ResTable_config*, uint32_t, benchmark::State&)){ ResTable_config config; memset(&config, 0, sizeof(config)); config.sdkVersion = 26; GetResourceBenchmarkOld({GetTestDataPath() + "/sparse/sparse.apk"}, &config, resid, state); config.orientation = ResTable_config::ORIENTATION_LAND; GetResourceBenchmarkFunc(paths, &config, resid, state); } static void BM_SparseEntryGetResourceOldSparse(benchmark::State& state, uint32_t resid) { BM_SparseEntryGetResourceHelper({GetTestDataPath() + "/sparse/sparse.apk"}, resid, state, &GetResourceBenchmarkOld); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldSparse, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldSparse, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceOldNotSparse(benchmark::State& state, uint32_t resid) { ResTable_config config; memset(&config, 0, sizeof(config)); config.sdkVersion = 26; GetResourceBenchmarkOld({GetTestDataPath() + "/sparse/not_sparse.apk"}, &config, resid, state); BM_SparseEntryGetResourceHelper({GetTestDataPath() + "/sparse/not_sparse.apk"}, resid, state, &GetResourceBenchmarkOld); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldNotSparse, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldNotSparse, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceSparse(benchmark::State& state, uint32_t resid) { ResTable_config config; memset(&config, 0, sizeof(config)); config.sdkVersion = 26; GetResourceBenchmark({GetTestDataPath() + "/sparse/sparse.apk"}, &config, resid, state); BM_SparseEntryGetResourceHelper({GetTestDataPath() + "/sparse/sparse.apk"}, resid, state, &GetResourceBenchmark); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceSparse, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceSparse, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceNotSparse(benchmark::State& state, uint32_t resid) { ResTable_config config; memset(&config, 0, sizeof(config)); config.sdkVersion = 26; GetResourceBenchmark({GetTestDataPath() + "/sparse/not_sparse.apk"}, &config, resid, state); BM_SparseEntryGetResourceHelper({GetTestDataPath() + "/sparse/not_sparse.apk"}, resid, state, &GetResourceBenchmark); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceNotSparse, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceNotSparse, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceOldSparseRuntime(benchmark::State& state, uint32_t resid) { BM_SparseEntryGetResourceHelper({base::GetExecutableDirectory() + "/FrameworkResourcesSparseTestApp.apk"}, resid, state, &GetResourceBenchmarkOld); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldSparseRuntime, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldSparseRuntime, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceOldNotSparseRuntime(benchmark::State& state, uint32_t resid) { BM_SparseEntryGetResourceHelper({base::GetExecutableDirectory() + "/FrameworkResourcesNotSparseTestApp.apk"}, resid, state, &GetResourceBenchmarkOld); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldNotSparseRuntime, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldNotSparseRuntime, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceSparseRuntime(benchmark::State& state, uint32_t resid) { BM_SparseEntryGetResourceHelper({base::GetExecutableDirectory() + "/FrameworkResourcesSparseTestApp.apk"}, resid, state, &GetResourceBenchmark); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceSparseRuntime, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceSparseRuntime, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceNotSparseRuntime(benchmark::State& state, uint32_t resid) { BM_SparseEntryGetResourceHelper({base::GetExecutableDirectory() + "/FrameworkResourcesNotSparseTestApp.apk"}, resid, state, &GetResourceBenchmark); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceNotSparseRuntime, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceNotSparseRuntime, Large, sparse::R::string::foo_999); } // namespace android libs/androidfw/tests/data/sparse/Android.bp 0 → 100644 +14 −0 Original line number Diff line number Diff line android_test_helper_app { name: "FrameworkResourcesSparseTestApp", sdk_version: "current", min_sdk_version: "32", aaptflags: [ "--enable-sparse-encoding", ], } android_test_helper_app { name: "FrameworkResourcesNotSparseTestApp", sdk_version: "current", min_sdk_version: "32", } Loading
libs/androidfw/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -211,6 +211,8 @@ cc_test { "tests/data/**/*.apk", "tests/data/**/*.arsc", "tests/data/**/*.idmap", ":FrameworkResourcesSparseTestApp", ":FrameworkResourcesNotSparseTestApp", ], test_suites: ["device-tests"], } Loading
libs/androidfw/tests/LoadedArsc_test.cpp +80 −56 Original line number Diff line number Diff line Loading @@ -71,62 +71,6 @@ TEST(LoadedArscTest, LoadSinglePackageArsc) { ASSERT_TRUE(LoadedPackage::GetEntry(type.type, entry_index).has_value()); } TEST(LoadedArscTest, LoadSparseEntryApp) { 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::integer::foo_9)); ASSERT_THAT(package, NotNull()); const uint8_t type_index = get_type_id(sparse::R::integer::foo_9) - 1; const uint16_t entry_index = get_entry_id(sparse::R::integer::foo_9); const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index); ASSERT_THAT(type_spec, NotNull()); ASSERT_THAT(type_spec->type_entries.size(), Ge(1u)); auto type = type_spec->type_entries[0]; 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 Loading @@ -404,4 +348,84 @@ TEST(LoadedArscTest, LoadCustomLoader) { // sizeof(Res_value) might not be backwards compatible. // TEST(LoadedArscTest, LoadingShouldBeForwardsAndBackwardsCompatible) { ASSERT_TRUE(false); } class LoadedArscParameterizedTest : public testing::TestWithParam<std::string> { }; TEST_P(LoadedArscParameterizedTest, LoadSparseEntryApp) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetParam(), "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::integer::foo_9)); ASSERT_THAT(package, NotNull()); const uint8_t type_index = get_type_id(sparse::R::integer::foo_9) - 1; const uint16_t entry_index = get_entry_id(sparse::R::integer::foo_9); const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index); ASSERT_THAT(type_spec, NotNull()); ASSERT_THAT(type_spec->type_entries.size(), Ge(1u)); auto type = type_spec->type_entries[0]; ASSERT_TRUE(LoadedPackage::GetEntry(type.type, entry_index).has_value()); } TEST_P(LoadedArscParameterizedTest, FindSparseEntryApp) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetParam(), "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_land)); ASSERT_THAT(package, NotNull()); const uint8_t type_index = get_type_id(sparse::R::string::only_land) - 1; const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index); ASSERT_THAT(type_spec, NotNull()); ASSERT_THAT(type_spec->type_entries.size(), Ge(1u)); // Type Entry with default orientation is not sparse encoded because the ratio of // populated entries to total entries is above threshold. // Only find out default locale because Soong build system will introduce pseudo // locales for the apk generated at runtime. auto type_entry_default = std::find_if( type_spec->type_entries.begin(), type_spec->type_entries.end(), [] (const TypeSpec::TypeEntry& x) { return x.config.orientation == 0 && x.config.locale == 0; }); ASSERT_NE(type_entry_default, type_spec->type_entries.end()); ASSERT_EQ(type_entry_default->type->flags & ResTable_type::FLAG_SPARSE, 0); // Type Entry with land orientation is sparse encoded as expected. // Only find out default locale because Soong build system will introduce pseudo // locales for the apk generated at runtime. auto type_entry_land = std::find_if( type_spec->type_entries.begin(), type_spec->type_entries.end(), [](const TypeSpec::TypeEntry& x) { return x.config.orientation == ResTable_config::ORIENTATION_LAND && x.config.locale == 0; }); ASSERT_NE(type_entry_land, type_spec->type_entries.end()); ASSERT_NE(type_entry_land->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_land"); ASSERT_EQ(id.value(), fix_package_id(sparse::R::string::only_land, 0)); } INSTANTIATE_TEST_SUITE_P( FrameWorkResourcesLoadedArscTests, LoadedArscParameterizedTest, ::testing::Values( base::GetExecutableDirectory() + "/tests/data/sparse/sparse.apk", base::GetExecutableDirectory() + "/FrameworkResourcesSparseTestApp.apk" )); } // namespace android
libs/androidfw/tests/ResTable_test.cpp +40 −28 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ #include "androidfw/ResourceTypes.h" #include "android-base/file.h" #include <codecvt> #include <locale> Loading @@ -41,34 +42,6 @@ TEST(ResTableTest, ShouldLoadSuccessfully) { ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size())); } TEST(ResTableTest, ShouldLoadSparseEntriesSuccessfully) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/sparse/sparse.apk", "resources.arsc", &contents)); ResTable table; ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size())); ResTable_config config; memset(&config, 0, sizeof(config)); config.sdkVersion = 26; table.setParameters(&config); String16 name(u"com.android.sparse:integer/foo_9"); uint32_t flags; uint32_t resid = table.identifierForName(name.string(), name.size(), nullptr, 0, nullptr, 0, &flags); ASSERT_NE(0u, resid); Res_value val; ResTable_config selected_config; ASSERT_GE( table.getResource(resid, &val, false /*mayBeBag*/, 0u /*density*/, &flags, &selected_config), 0); EXPECT_EQ(Res_value::TYPE_INT_DEC, val.dataType); EXPECT_EQ(900u, val.data); } TEST(ResTableTest, SimpleTypeIsRetrievedCorrectly) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", Loading Loading @@ -476,4 +449,43 @@ TEST(ResTableTest, TruncatedEncodeLength) { ASSERT_FALSE(invalid_pool->stringAt(invalid_val.data).has_value()); } class ResTableParameterizedTest : public testing::TestWithParam<std::string> { }; TEST_P(ResTableParameterizedTest, ShouldLoadSparseEntriesSuccessfully) { std::string contents; ASSERT_TRUE(ReadFileFromZipToString(GetParam(), "resources.arsc", &contents)); ResTable table; ASSERT_EQ(NO_ERROR, table.add(contents.data(), contents.size())); ResTable_config config; memset(&config, 0, sizeof(config)); config.orientation = ResTable_config::ORIENTATION_LAND; table.setParameters(&config); String16 name(u"com.android.sparse:integer/foo_9"); uint32_t flags; uint32_t resid = table.identifierForName(name.string(), name.size(), nullptr, 0, nullptr, 0, &flags); ASSERT_NE(0u, resid); Res_value val; ResTable_config selected_config; ASSERT_GE( table.getResource(resid, &val, false /*mayBeBag*/, 0u /*density*/, &flags, &selected_config), 0); EXPECT_EQ(Res_value::TYPE_INT_DEC, val.dataType); EXPECT_EQ(900u, val.data); } INSTANTIATE_TEST_SUITE_P( FrameWorkResourcesResTableTests, ResTableParameterizedTest, ::testing::Values( base::GetExecutableDirectory() + "/tests/data/sparse/sparse.apk", base::GetExecutableDirectory() + "/FrameworkResourcesSparseTestApp.apk" )); } // namespace android
libs/androidfw/tests/SparseEntry_bench.cpp +51 −16 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "androidfw/AssetManager.h" #include "androidfw/ResourceTypes.h" #include "android-base/file.h" #include "BenchmarkHelpers.h" #include "data/sparse/R.h" Loading @@ -24,40 +25,74 @@ namespace sparse = com::android::sparse; namespace android { static void BM_SparseEntryGetResourceOldSparse(benchmark::State& state, uint32_t resid) { static void BM_SparseEntryGetResourceHelper(const std::vector<std::string>& paths, uint32_t resid, benchmark::State& state, void (*GetResourceBenchmarkFunc)( const std::vector<std::string>&, const ResTable_config*, uint32_t, benchmark::State&)){ ResTable_config config; memset(&config, 0, sizeof(config)); config.sdkVersion = 26; GetResourceBenchmarkOld({GetTestDataPath() + "/sparse/sparse.apk"}, &config, resid, state); config.orientation = ResTable_config::ORIENTATION_LAND; GetResourceBenchmarkFunc(paths, &config, resid, state); } static void BM_SparseEntryGetResourceOldSparse(benchmark::State& state, uint32_t resid) { BM_SparseEntryGetResourceHelper({GetTestDataPath() + "/sparse/sparse.apk"}, resid, state, &GetResourceBenchmarkOld); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldSparse, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldSparse, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceOldNotSparse(benchmark::State& state, uint32_t resid) { ResTable_config config; memset(&config, 0, sizeof(config)); config.sdkVersion = 26; GetResourceBenchmarkOld({GetTestDataPath() + "/sparse/not_sparse.apk"}, &config, resid, state); BM_SparseEntryGetResourceHelper({GetTestDataPath() + "/sparse/not_sparse.apk"}, resid, state, &GetResourceBenchmarkOld); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldNotSparse, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldNotSparse, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceSparse(benchmark::State& state, uint32_t resid) { ResTable_config config; memset(&config, 0, sizeof(config)); config.sdkVersion = 26; GetResourceBenchmark({GetTestDataPath() + "/sparse/sparse.apk"}, &config, resid, state); BM_SparseEntryGetResourceHelper({GetTestDataPath() + "/sparse/sparse.apk"}, resid, state, &GetResourceBenchmark); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceSparse, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceSparse, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceNotSparse(benchmark::State& state, uint32_t resid) { ResTable_config config; memset(&config, 0, sizeof(config)); config.sdkVersion = 26; GetResourceBenchmark({GetTestDataPath() + "/sparse/not_sparse.apk"}, &config, resid, state); BM_SparseEntryGetResourceHelper({GetTestDataPath() + "/sparse/not_sparse.apk"}, resid, state, &GetResourceBenchmark); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceNotSparse, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceNotSparse, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceOldSparseRuntime(benchmark::State& state, uint32_t resid) { BM_SparseEntryGetResourceHelper({base::GetExecutableDirectory() + "/FrameworkResourcesSparseTestApp.apk"}, resid, state, &GetResourceBenchmarkOld); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldSparseRuntime, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldSparseRuntime, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceOldNotSparseRuntime(benchmark::State& state, uint32_t resid) { BM_SparseEntryGetResourceHelper({base::GetExecutableDirectory() + "/FrameworkResourcesNotSparseTestApp.apk"}, resid, state, &GetResourceBenchmarkOld); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldNotSparseRuntime, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceOldNotSparseRuntime, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceSparseRuntime(benchmark::State& state, uint32_t resid) { BM_SparseEntryGetResourceHelper({base::GetExecutableDirectory() + "/FrameworkResourcesSparseTestApp.apk"}, resid, state, &GetResourceBenchmark); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceSparseRuntime, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceSparseRuntime, Large, sparse::R::string::foo_999); static void BM_SparseEntryGetResourceNotSparseRuntime(benchmark::State& state, uint32_t resid) { BM_SparseEntryGetResourceHelper({base::GetExecutableDirectory() + "/FrameworkResourcesNotSparseTestApp.apk"}, resid, state, &GetResourceBenchmark); } BENCHMARK_CAPTURE(BM_SparseEntryGetResourceNotSparseRuntime, Small, sparse::R::integer::foo_9); BENCHMARK_CAPTURE(BM_SparseEntryGetResourceNotSparseRuntime, Large, sparse::R::string::foo_999); } // namespace android
libs/androidfw/tests/data/sparse/Android.bp 0 → 100644 +14 −0 Original line number Diff line number Diff line android_test_helper_app { name: "FrameworkResourcesSparseTestApp", sdk_version: "current", min_sdk_version: "32", aaptflags: [ "--enable-sparse-encoding", ], } android_test_helper_app { name: "FrameworkResourcesNotSparseTestApp", sdk_version: "current", min_sdk_version: "32", }