libandroidfw: Add new support for shared libraries
This adds support for shared resource libraries in the new
ResTable/AssetManager implementation.
The dynamic package map encoded in resources.arsc is parsed
and stored with LoadedArsc, and combined to form a resolved table
in AssetManager2.
Benchmarks show that this implementation is an order of magnitude
faster on angler-userdebug (make libandroidfw_benchmarks).
Test: libandroidfw_tests
Change-Id: I57c80248728b63b162bf8269ac9495b53c3e7fa0
diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp
index 9ff9478..b3c2dc3 100644
--- a/libs/androidfw/tests/AssetManager2_bench.cpp
+++ b/libs/androidfw/tests/AssetManager2_bench.cpp
@@ -16,6 +16,7 @@
#include "benchmark/benchmark.h"
+#include "android-base/stringprintf.h"
#include "androidfw/ApkAssets.h"
#include "androidfw/AssetManager.h"
#include "androidfw/AssetManager2.h"
@@ -23,10 +24,12 @@
#include "TestHelpers.h"
#include "data/basic/R.h"
+#include "data/libclient/R.h"
#include "data/styles/R.h"
-namespace basic = com::android::basic;
namespace app = com::android::app;
+namespace basic = com::android::basic;
+namespace libclient = com::android::libclient;
namespace android {
@@ -78,101 +81,108 @@
}
BENCHMARK(BM_AssetManagerLoadFrameworkAssetsOld);
-static void BM_AssetManagerGetResource(benchmark::State& state) {
- std::unique_ptr<ApkAssets> apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
- if (apk == nullptr) {
- state.SkipWithError("Failed to load assets");
- return;
+static void GetResourceBenchmark(const std::vector<std::string>& paths,
+ const ResTable_config* config, uint32_t resid,
+ benchmark::State& state) {
+ std::vector<std::unique_ptr<ApkAssets>> apk_assets;
+ std::vector<const ApkAssets*> apk_assets_ptrs;
+ for (const std::string& path : paths) {
+ std::unique_ptr<ApkAssets> apk = ApkAssets::Load(path);
+ if (apk == nullptr) {
+ state.SkipWithError(base::StringPrintf("Failed to load assets %s", path.c_str()).c_str());
+ return;
+ }
+ apk_assets_ptrs.push_back(apk.get());
+ apk_assets.push_back(std::move(apk));
}
- AssetManager2 assets;
- assets.SetApkAssets({apk.get()});
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets(apk_assets_ptrs);
+ if (config != nullptr) {
+ assetmanager.SetConfiguration(*config);
+ }
Res_value value;
ResTable_config selected_config;
uint32_t flags;
while (state.KeepRunning()) {
- assets.GetResource(basic::R::integer::number1, false /* may_be_bag */,
- 0u /* density_override */, &value, &selected_config, &flags);
+ assetmanager.GetResource(resid, false /* may_be_bag */, 0u /* density_override */, &value,
+ &selected_config, &flags);
}
}
+
+static void GetResourceBenchmarkOld(const std::vector<std::string>& paths,
+ const ResTable_config* config, uint32_t resid,
+ benchmark::State& state) {
+ AssetManager assetmanager;
+ for (const std::string& path : paths) {
+ if (!assetmanager.addAssetPath(String8(path.c_str()), nullptr /* cookie */,
+ false /* appAsLib */, false /* isSystemAssets */)) {
+ state.SkipWithError(base::StringPrintf("Failed to load assets %s", path.c_str()).c_str());
+ return;
+ }
+ }
+
+ if (config != nullptr) {
+ assetmanager.setConfiguration(*config);
+ }
+
+ const ResTable& table = assetmanager.getResources(true);
+
+ Res_value value;
+ ResTable_config selected_config;
+ uint32_t flags;
+
+ while (state.KeepRunning()) {
+ table.getResource(resid, &value, false /*may_be_bag*/, 0u /*density*/, &flags,
+ &selected_config);
+ }
+}
+
+static void BM_AssetManagerGetResource(benchmark::State& state) {
+ GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
+ basic::R::integer::number1, state);
+}
BENCHMARK(BM_AssetManagerGetResource);
static void BM_AssetManagerGetResourceOld(benchmark::State& state) {
- AssetManager assets;
- if (!assets.addAssetPath(String8((GetTestDataPath() + "/basic/basic.apk").data()),
- nullptr /* cookie */, false /* appAsLib */,
- false /* isSystemAssets */)) {
- state.SkipWithError("Failed to load assets");
- return;
- }
-
- const ResTable& table = assets.getResources(true);
-
- Res_value value;
- ResTable_config selected_config;
- uint32_t flags;
-
- while (state.KeepRunning()) {
- table.getResource(basic::R::integer::number1, &value, false /* may_be_bag */,
- 0u /* density_override */, &flags, &selected_config);
- }
+ GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
+ basic::R::integer::number1, state);
}
BENCHMARK(BM_AssetManagerGetResourceOld);
+static void BM_AssetManagerGetLibraryResource(benchmark::State& state) {
+ GetResourceBenchmark(
+ {GetTestDataPath() + "/lib_two/lib_two.apk", GetTestDataPath() + "/lib_one/lib_one.apk",
+ GetTestDataPath() + "/libclient/libclient.apk"},
+ nullptr /*config*/, libclient::R::string::foo_one, state);
+}
+BENCHMARK(BM_AssetManagerGetLibraryResource);
+
+static void BM_AssetManagerGetLibraryResourceOld(benchmark::State& state) {
+ GetResourceBenchmarkOld(
+ {GetTestDataPath() + "/lib_two/lib_two.apk", GetTestDataPath() + "/lib_one/lib_one.apk",
+ GetTestDataPath() + "/libclient/libclient.apk"},
+ nullptr /*config*/, libclient::R::string::foo_one, state);
+}
+BENCHMARK(BM_AssetManagerGetLibraryResourceOld);
+
constexpr static const uint32_t kStringOkId = 0x0104000au;
static void BM_AssetManagerGetResourceFrameworkLocale(benchmark::State& state) {
- std::unique_ptr<ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
- if (apk == nullptr) {
- state.SkipWithError("Failed to load assets");
- return;
- }
-
- AssetManager2 assets;
- assets.SetApkAssets({apk.get()});
-
ResTable_config config;
memset(&config, 0, sizeof(config));
memcpy(config.language, "fr", 2);
- assets.SetConfiguration(config);
-
- Res_value value;
- ResTable_config selected_config;
- uint32_t flags;
-
- while (state.KeepRunning()) {
- assets.GetResource(kStringOkId, false /* may_be_bag */, 0u /* density_override */, &value,
- &selected_config, &flags);
- }
+ GetResourceBenchmark({kFrameworkPath}, &config, kStringOkId, state);
}
BENCHMARK(BM_AssetManagerGetResourceFrameworkLocale);
static void BM_AssetManagerGetResourceFrameworkLocaleOld(benchmark::State& state) {
- AssetManager assets;
- if (!assets.addAssetPath(String8((GetTestDataPath() + "/basic/basic.apk").data()),
- nullptr /* cookie */, false /* appAsLib */,
- false /* isSystemAssets */)) {
- state.SkipWithError("Failed to load assets");
- return;
- }
-
ResTable_config config;
memset(&config, 0, sizeof(config));
memcpy(config.language, "fr", 2);
- assets.setConfiguration(config, nullptr);
-
- const ResTable& table = assets.getResources(true);
-
- Res_value value;
- ResTable_config selected_config;
- uint32_t flags;
-
- while (state.KeepRunning()) {
- table.getResource(kStringOkId, &value, false /* may_be_bag */, 0u /* density_override */,
- &flags, &selected_config);
- }
+ GetResourceBenchmarkOld({kFrameworkPath}, &config, kStringOkId, state);
}
BENCHMARK(BM_AssetManagerGetResourceFrameworkLocaleOld);
@@ -202,8 +212,7 @@
static void BM_AssetManagerGetBagOld(benchmark::State& state) {
AssetManager assets;
if (!assets.addAssetPath(String8((GetTestDataPath() + "/styles/styles.apk").data()),
- nullptr /* cookie */, false /* appAsLib */,
- false /* isSystemAssets */)) {
+ nullptr /*cookie*/, false /*appAsLib*/, false /*isSystemAssets*/)) {
state.SkipWithError("Failed to load assets");
return;
}