summaryrefslogtreecommitdiff
path: root/libs/androidfw/tests
diff options
context:
space:
mode:
author Adam Lesinski <adamlesinski@google.com> 2016-12-29 16:08:16 -0500
committer Adam Lesinski <adamlesinski@google.com> 2017-01-11 17:20:36 -0800
commitda431a22da38f9c4085b5d71ed9a9c6122c6a5a6 (patch)
tree7fc684c1ec3c653ff98bdc8eff50addc081a02e1 /libs/androidfw/tests
parent7ad1110ecd6a840fcd2895c62668828a1ca029c6 (diff)
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
Diffstat (limited to 'libs/androidfw/tests')
-rw-r--r--libs/androidfw/tests/ApkAssets_test.cpp19
-rw-r--r--libs/androidfw/tests/AssetManager2_bench.cpp133
-rw-r--r--libs/androidfw/tests/AssetManager2_test.cpp122
-rw-r--r--libs/androidfw/tests/LoadedArsc_test.cpp81
-rw-r--r--libs/androidfw/tests/ResTable_test.cpp6
-rw-r--r--libs/androidfw/tests/Theme_test.cpp46
-rw-r--r--libs/androidfw/tests/data/lib/lib.apkbin1221 -> 0 bytes
-rw-r--r--libs/androidfw/tests/data/lib_one/AndroidManifest.xml (renamed from libs/androidfw/tests/data/lib/AndroidManifest.xml)2
-rw-r--r--libs/androidfw/tests/data/lib_one/R.h (renamed from libs/androidfw/tests/data/lib/R.h)16
-rwxr-xr-xlibs/androidfw/tests/data/lib_one/build (renamed from libs/androidfw/tests/data/lib/build)2
-rw-r--r--libs/androidfw/tests/data/lib_one/lib_one.apkbin0 -> 1414 bytes
-rw-r--r--libs/androidfw/tests/data/lib_one/res/values/values.xml32
-rw-r--r--libs/androidfw/tests/data/lib_two/AndroidManifest.xml19
-rw-r--r--libs/androidfw/tests/data/lib_two/R.h39
-rwxr-xr-xlibs/androidfw/tests/data/lib_two/build20
-rw-r--r--libs/androidfw/tests/data/lib_two/lib_two.apkbin0 -> 1106 bytes
-rw-r--r--libs/androidfw/tests/data/lib_two/res/values/values.xml (renamed from libs/androidfw/tests/data/lib/res/values/values.xml)10
-rw-r--r--libs/androidfw/tests/data/libclient/AndroidManifest.xml19
-rw-r--r--libs/androidfw/tests/data/libclient/R.h52
-rwxr-xr-xlibs/androidfw/tests/data/libclient/build30
-rw-r--r--libs/androidfw/tests/data/libclient/libclient.apkbin0 -> 1982 bytes
-rw-r--r--libs/androidfw/tests/data/libclient/res/values/values.xml35
22 files changed, 590 insertions, 93 deletions
diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp
index 3a1fc8fa0d3f..02037120f098 100644
--- a/libs/androidfw/tests/ApkAssets_test.cpp
+++ b/libs/androidfw/tests/ApkAssets_test.cpp
@@ -26,9 +26,28 @@ namespace android {
TEST(ApkAssetsTest, LoadApk) {
std::unique_ptr<ApkAssets> loaded_apk = ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
ASSERT_NE(nullptr, loaded_apk);
+ EXPECT_NE(nullptr, loaded_apk->GetLoadedArsc());
std::unique_ptr<Asset> asset = loaded_apk->Open("res/layout/main.xml");
ASSERT_NE(nullptr, asset);
}
+TEST(ApkAssetsTest, LoadApkAsSharedLibrary) {
+ std::unique_ptr<ApkAssets> loaded_apk =
+ ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
+ ASSERT_NE(nullptr, loaded_apk);
+ const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
+ ASSERT_NE(nullptr, loaded_arsc);
+ ASSERT_EQ(1u, loaded_arsc->GetPackages().size());
+ EXPECT_FALSE(loaded_arsc->GetPackages()[0]->IsDynamic());
+
+ loaded_apk = ApkAssets::LoadAsSharedLibrary(GetTestDataPath() + "/appaslib/appaslib.apk");
+ ASSERT_NE(nullptr, loaded_apk);
+
+ loaded_arsc = loaded_apk->GetLoadedArsc();
+ ASSERT_NE(nullptr, loaded_arsc);
+ ASSERT_EQ(1u, loaded_arsc->GetPackages().size());
+ EXPECT_TRUE(loaded_arsc->GetPackages()[0]->IsDynamic());
+}
+
} // namespace android
diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp
index 9ff947807a1e..b3c2dc34cdcf 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 @@ static void BM_AssetManagerLoadFrameworkAssetsOld(benchmark::State& state) {
}
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);
}
}
-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;
+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;
+ }
}
- const ResTable& table = assets.getResources(true);
+ 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(basic::R::integer::number1, &value, false /* may_be_bag */,
- 0u /* density_override */, &flags, &selected_config);
+ 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) {
+ GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
+ basic::R::integer::number1, state);
+}
BENCHMARK(BM_AssetManagerGetResourceOld);
-constexpr static const uint32_t kStringOkId = 0x0104000au;
+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_AssetManagerGetResourceFrameworkLocale(benchmark::State& state) {
- std::unique_ptr<ApkAssets> apk = ApkAssets::Load(kFrameworkPath);
- if (apk == nullptr) {
- state.SkipWithError("Failed to load assets");
- return;
- }
+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);
- AssetManager2 assets;
- assets.SetApkAssets({apk.get()});
+constexpr static const uint32_t kStringOkId = 0x0104000au;
+static void BM_AssetManagerGetResourceFrameworkLocale(benchmark::State& state) {
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 @@ BENCHMARK(BM_AssetManagerGetBag);
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;
}
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 39c5381feb04..543456afa2f4 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -20,11 +20,19 @@
#include "android-base/logging.h"
#include "TestHelpers.h"
+#include "data/appaslib/R.h"
#include "data/basic/R.h"
+#include "data/lib_one/R.h"
+#include "data/lib_two/R.h"
+#include "data/libclient/R.h"
#include "data/styles/R.h"
-namespace basic = com::android::basic;
namespace app = com::android::app;
+namespace appaslib = com::android::appaslib::app;
+namespace basic = com::android::basic;
+namespace lib_one = com::android::lib_one;
+namespace lib_two = com::android::lib_two;
+namespace libclient = com::android::libclient;
namespace android {
@@ -39,15 +47,31 @@ class AssetManager2Test : public ::testing::Test {
style_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
ASSERT_NE(nullptr, style_assets_);
+
+ lib_one_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_one/lib_one.apk");
+ ASSERT_NE(nullptr, lib_one_assets_);
+
+ lib_two_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_two/lib_two.apk");
+ ASSERT_NE(nullptr, lib_two_assets_);
+
+ libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk");
+ ASSERT_NE(nullptr, libclient_assets_);
+
+ appaslib_assets_ = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
+ ASSERT_NE(nullptr, appaslib_assets_);
}
protected:
std::unique_ptr<ApkAssets> basic_assets_;
std::unique_ptr<ApkAssets> basic_de_fr_assets_;
std::unique_ptr<ApkAssets> style_assets_;
+ std::unique_ptr<ApkAssets> lib_one_assets_;
+ std::unique_ptr<ApkAssets> lib_two_assets_;
+ std::unique_ptr<ApkAssets> libclient_assets_;
+ std::unique_ptr<ApkAssets> appaslib_assets_;
};
-TEST_F(AssetManager2Test, FindsResourcesFromSingleApkAssets) {
+TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) {
ResTable_config desired_config;
memset(&desired_config, 0, sizeof(desired_config));
desired_config.language[0] = 'd';
@@ -77,7 +101,7 @@ TEST_F(AssetManager2Test, FindsResourcesFromSingleApkAssets) {
EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
}
-TEST_F(AssetManager2Test, FindsResourcesFromMultipleApkAssets) {
+TEST_F(AssetManager2Test, FindsResourceFromMultipleApkAssets) {
ResTable_config desired_config;
memset(&desired_config, 0, sizeof(desired_config));
desired_config.language[0] = 'd';
@@ -99,7 +123,7 @@ TEST_F(AssetManager2Test, FindsResourcesFromMultipleApkAssets) {
// Came from our de_fr ApkAssets.
EXPECT_EQ(1, cookie);
- // The configuration is german.
+ // The configuration is German.
EXPECT_EQ('d', selected_config.language[0]);
EXPECT_EQ('e', selected_config.language[1]);
@@ -107,7 +131,72 @@ TEST_F(AssetManager2Test, FindsResourcesFromMultipleApkAssets) {
EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
}
-TEST_F(AssetManager2Test, FindsBagResourcesFromSingleApkAssets) {
+TEST_F(AssetManager2Test, FindsResourceFromSharedLibrary) {
+ AssetManager2 assetmanager;
+
+ // libclient is built with lib_one and then lib_two in order.
+ // Reverse the order to test that proper package ID re-assignment is happening.
+ assetmanager.SetApkAssets(
+ {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+
+ Res_value value;
+ ResTable_config selected_config;
+ uint32_t flags;
+
+ ApkAssetsCookie cookie =
+ assetmanager.GetResource(libclient::R::string::foo_one, false /*may_be_bag*/,
+ 0 /*density_override*/, &value, &selected_config, &flags);
+ ASSERT_NE(kInvalidCookie, cookie);
+
+ // Reference comes from libclient.
+ EXPECT_EQ(2, cookie);
+ EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
+
+ // Lookup the reference.
+ cookie = assetmanager.GetResource(value.data, false /* may_be_bag */, 0 /* density_override*/,
+ &value, &selected_config, &flags);
+ ASSERT_NE(kInvalidCookie, cookie);
+ EXPECT_EQ(1, cookie);
+ EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
+ EXPECT_EQ(std::string("Foo from lib_one"),
+ GetStringFromPool(assetmanager.GetStringPoolForCookie(cookie), value.data));
+
+ cookie = assetmanager.GetResource(libclient::R::string::foo_two, false /*may_be_bag*/,
+ 0 /*density_override*/, &value, &selected_config, &flags);
+ ASSERT_NE(kInvalidCookie, cookie);
+
+ // Reference comes from libclient.
+ EXPECT_EQ(2, cookie);
+ EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
+
+ // Lookup the reference.
+ cookie = assetmanager.GetResource(value.data, false /* may_be_bag */, 0 /* density_override*/,
+ &value, &selected_config, &flags);
+ ASSERT_NE(kInvalidCookie, cookie);
+ EXPECT_EQ(0, cookie);
+ EXPECT_EQ(Res_value::TYPE_STRING, value.dataType);
+ EXPECT_EQ(std::string("Foo from lib_two"),
+ GetStringFromPool(assetmanager.GetStringPoolForCookie(cookie), value.data));
+}
+
+TEST_F(AssetManager2Test, FindsResourceFromAppLoadedAsSharedLibrary) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({appaslib_assets_.get()});
+
+ // The appaslib package will have been assigned the package ID 0x02.
+
+ Res_value value;
+ ResTable_config selected_config;
+ uint32_t flags;
+ ApkAssetsCookie cookie = assetmanager.GetResource(
+ util::fix_package_id(appaslib::R::integer::number1, 0x02), false /*may_be_bag*/,
+ 0u /*density_override*/, &value, &selected_config, &flags);
+ ASSERT_NE(kInvalidCookie, cookie);
+ EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
+ EXPECT_EQ(util::fix_package_id(appaslib::R::array::integerArray1, 0x02), value.data);
+}
+
+TEST_F(AssetManager2Test, FindsBagResourceFromSingleApkAssets) {
AssetManager2 assetmanager;
assetmanager.SetApkAssets({basic_assets_.get()});
@@ -128,6 +217,27 @@ TEST_F(AssetManager2Test, FindsBagResourcesFromSingleApkAssets) {
EXPECT_EQ(0, bag->entries[2].cookie);
}
+TEST_F(AssetManager2Test, FindsBagResourceFromMultipleApkAssets) {}
+
+TEST_F(AssetManager2Test, FindsBagResourceFromSharedLibrary) {
+ AssetManager2 assetmanager;
+
+ // libclient is built with lib_one and then lib_two in order.
+ // Reverse the order to test that proper package ID re-assignment is happening.
+ assetmanager.SetApkAssets(
+ {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+
+ const ResolvedBag* bag = assetmanager.GetBag(libclient::R::style::Theme);
+ ASSERT_NE(nullptr, bag);
+ ASSERT_GE(bag->entry_count, 2u);
+
+ // First two attributes come from lib_one.
+ EXPECT_EQ(1, bag->entries[0].cookie);
+ EXPECT_EQ(0x03, util::get_package_id(bag->entries[0].key));
+ EXPECT_EQ(1, bag->entries[1].cookie);
+ EXPECT_EQ(0x03, util::get_package_id(bag->entries[1].key));
+}
+
TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) {
AssetManager2 assetmanager;
assetmanager.SetApkAssets({style_assets_.get()});
@@ -181,8 +291,6 @@ TEST_F(AssetManager2Test, MergesStylesWithParentFromSingleApkAssets) {
EXPECT_EQ(0, bag_two->entries[4].cookie);
}
-TEST_F(AssetManager2Test, FindsBagResourcesFromMultipleApkAssets) {}
-
TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {}
TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {}
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index 47b3894f0398..045507e2e277 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -16,21 +16,18 @@
#include "androidfw/LoadedArsc.h"
-#include "android-base/file.h"
-#include "android-base/logging.h"
-#include "android-base/macros.h"
-
#include "TestHelpers.h"
#include "data/basic/R.h"
+#include "data/libclient/R.h"
#include "data/styles/R.h"
namespace app = com::android::app;
namespace basic = com::android::basic;
+namespace libclient = com::android::libclient;
namespace android {
TEST(LoadedArscTest, LoadSinglePackageArsc) {
- base::ScopedLogSeverity _log(base::LogSeverity::DEBUG);
std::string contents;
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/styles/styles.apk", "resources.arsc",
&contents));
@@ -38,11 +35,16 @@ TEST(LoadedArscTest, LoadSinglePackageArsc) {
std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size());
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.app"), packages[0]->GetPackageName());
+ EXPECT_EQ(0x7f, packages[0]->GetPackageId());
+
ResTable_config config;
memset(&config, 0, sizeof(config));
config.sdkVersion = 24;
- LoadedArsc::Entry entry;
+ LoadedArscEntry entry;
ResTable_config selected_config;
uint32_t flags;
@@ -52,7 +54,6 @@ TEST(LoadedArscTest, LoadSinglePackageArsc) {
}
TEST(LoadedArscTest, FindDefaultEntry) {
- base::ScopedLogSeverity _log(base::LogSeverity::DEBUG);
std::string contents;
ASSERT_TRUE(
ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
@@ -65,7 +66,7 @@ TEST(LoadedArscTest, FindDefaultEntry) {
desired_config.language[0] = 'd';
desired_config.language[1] = 'e';
- LoadedArsc::Entry entry;
+ LoadedArscEntry entry;
ResTable_config selected_config;
uint32_t flags;
@@ -74,6 +75,70 @@ TEST(LoadedArscTest, FindDefaultEntry) {
ASSERT_NE(nullptr, entry.entry);
}
+TEST(LoadedArscTest, LoadSharedLibrary) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib_one/lib_one.apk", "resources.arsc",
+ &contents));
+
+ std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size());
+ ASSERT_NE(nullptr, loaded_arsc);
+
+ const auto& packages = loaded_arsc->GetPackages();
+ ASSERT_EQ(1u, packages.size());
+
+ EXPECT_TRUE(packages[0]->IsDynamic());
+ EXPECT_EQ(std::string("com.android.lib_one"), packages[0]->GetPackageName());
+ EXPECT_EQ(0, packages[0]->GetPackageId());
+
+ const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
+
+ // The library has no dependencies.
+ ASSERT_TRUE(dynamic_pkg_map.empty());
+}
+
+TEST(LoadedArscTest, LoadAppLinkedAgainstSharedLibrary) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/libclient/libclient.apk",
+ "resources.arsc", &contents));
+
+ std::unique_ptr<LoadedArsc> loaded_arsc = LoadedArsc::Load(contents.data(), contents.size());
+ ASSERT_NE(nullptr, loaded_arsc);
+
+ const auto& packages = loaded_arsc->GetPackages();
+ ASSERT_EQ(1u, packages.size());
+
+ EXPECT_FALSE(packages[0]->IsDynamic());
+ EXPECT_EQ(std::string("com.android.libclient"), packages[0]->GetPackageName());
+ EXPECT_EQ(0x7f, packages[0]->GetPackageId());
+
+ const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
+
+ // The library has two dependencies.
+ ASSERT_EQ(2u, dynamic_pkg_map.size());
+
+ EXPECT_EQ(std::string("com.android.lib_one"), dynamic_pkg_map[0].package_name);
+ EXPECT_EQ(0x02, dynamic_pkg_map[0].package_id);
+
+ EXPECT_EQ(std::string("com.android.lib_two"), dynamic_pkg_map[1].package_name);
+ EXPECT_EQ(0x03, dynamic_pkg_map[1].package_id);
+}
+
+TEST(LoadedArscTest, LoadAppAsSharedLibrary) {
+ std::string contents;
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/appaslib/appaslib.apk",
+ "resources.arsc", &contents));
+
+ std::unique_ptr<LoadedArsc> loaded_arsc =
+ LoadedArsc::Load(contents.data(), contents.size(), true /*load_as_shared_library*/);
+ ASSERT_NE(nullptr, loaded_arsc);
+
+ const auto& packages = loaded_arsc->GetPackages();
+ ASSERT_EQ(1u, packages.size());
+
+ EXPECT_TRUE(packages[0]->IsDynamic());
+ EXPECT_EQ(0x7f, packages[0]->GetPackageId());
+}
+
// structs with size fields (like Res_value, ResTable_entry) should be
// backwards and forwards compatible (aka checking the size field against
// sizeof(Res_value) might not be backwards compatible.
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp
index b151f3f96496..ad1cd2b289d6 100644
--- a/libs/androidfw/tests/ResTable_test.cpp
+++ b/libs/androidfw/tests/ResTable_test.cpp
@@ -25,10 +25,10 @@
#include "TestHelpers.h"
#include "data/basic/R.h"
-#include "data/lib/R.h"
+#include "data/lib_one/R.h"
namespace basic = com::android::basic;
-namespace lib = com::android::lib;
+namespace lib = com::android::lib_one;
namespace android {
@@ -119,7 +119,7 @@ TEST(ResTableTest, ParentThemeIsAppliedCorrectly) {
TEST(ResTableTest, LibraryThemeIsAppliedCorrectly) {
std::string contents;
- ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib/lib.apk",
+ ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/lib_one/lib_one.apk",
"resources.arsc", &contents));
ResTable table;
diff --git a/libs/androidfw/tests/Theme_test.cpp b/libs/androidfw/tests/Theme_test.cpp
index c0011b6d6e89..59cb18a36e6f 100644
--- a/libs/androidfw/tests/Theme_test.cpp
+++ b/libs/androidfw/tests/Theme_test.cpp
@@ -19,9 +19,13 @@
#include "android-base/logging.h"
#include "TestHelpers.h"
+#include "data/lib_one/R.h"
+#include "data/libclient/R.h"
#include "data/styles/R.h"
namespace app = com::android::app;
+namespace lib_one = com::android::lib_one;
+namespace libclient = com::android::libclient;
namespace android {
@@ -30,10 +34,22 @@ class ThemeTest : public ::testing::Test {
void SetUp() override {
style_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
ASSERT_NE(nullptr, style_assets_);
+
+ libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk");
+ ASSERT_NE(nullptr, libclient_assets_);
+
+ lib_one_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_one/lib_one.apk");
+ ASSERT_NE(nullptr, lib_one_assets_);
+
+ lib_two_assets_ = ApkAssets::Load(GetTestDataPath() + "/lib_two/lib_two.apk");
+ ASSERT_NE(nullptr, lib_two_assets_);
}
protected:
std::unique_ptr<ApkAssets> style_assets_;
+ std::unique_ptr<ApkAssets> libclient_assets_;
+ std::unique_ptr<ApkAssets> lib_one_assets_;
+ std::unique_ptr<ApkAssets> lib_two_assets_;
};
TEST_F(ThemeTest, EmptyTheme) {
@@ -174,6 +190,36 @@ TEST_F(ThemeTest, MultipleThemesOverlaidForced) {
EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
}
+TEST_F(ThemeTest, ResolveDynamicAttributesAndReferencesToSharedLibrary) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets(
+ {lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+
+ std::unique_ptr<Theme> theme = assetmanager.NewTheme();
+ ASSERT_TRUE(theme->ApplyStyle(libclient::R::style::Theme, false /*force*/));
+
+ Res_value value;
+ uint32_t flags;
+ ApkAssetsCookie cookie;
+
+ // The attribute should be resolved to the final value.
+ cookie = theme->GetAttribute(libclient::R::attr::foo, &value, &flags);
+ ASSERT_NE(kInvalidCookie, cookie);
+ EXPECT_EQ(Res_value::TYPE_INT_DEC, value.dataType);
+ EXPECT_EQ(700u, value.data);
+ EXPECT_EQ(static_cast<uint32_t>(ResTable_typeSpec::SPEC_PUBLIC), flags);
+
+ // The reference should be resolved to a TYPE_REFERENCE.
+ cookie = theme->GetAttribute(libclient::R::attr::bar, &value, &flags);
+ ASSERT_NE(kInvalidCookie, cookie);
+ EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
+
+ // lib_one is assigned package ID 0x03.
+ EXPECT_EQ(3u, util::get_package_id(value.data));
+ EXPECT_EQ(util::get_type_id(lib_one::R::string::foo), util::get_type_id(value.data));
+ EXPECT_EQ(util::get_entry_id(lib_one::R::string::foo), util::get_entry_id(value.data));
+}
+
TEST_F(ThemeTest, CopyThemeSameAssetManager) {
AssetManager2 assetmanager;
assetmanager.SetApkAssets({style_assets_.get()});
diff --git a/libs/androidfw/tests/data/lib/lib.apk b/libs/androidfw/tests/data/lib/lib.apk
deleted file mode 100644
index 44c27c79ae7c..000000000000
--- a/libs/androidfw/tests/data/lib/lib.apk
+++ /dev/null
Binary files differ
diff --git a/libs/androidfw/tests/data/lib/AndroidManifest.xml b/libs/androidfw/tests/data/lib_one/AndroidManifest.xml
index 02f5d3efabea..860adf758f92 100644
--- a/libs/androidfw/tests/data/lib/AndroidManifest.xml
+++ b/libs/androidfw/tests/data/lib_one/AndroidManifest.xml
@@ -15,6 +15,6 @@
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.lib">
+ package="com.android.lib_one">
<application />
</manifest>
diff --git a/libs/androidfw/tests/data/lib/R.h b/libs/androidfw/tests/data/lib_one/R.h
index bb22d22f90e1..fcaeb8dceffb 100644
--- a/libs/androidfw/tests/data/lib/R.h
+++ b/libs/androidfw/tests/data/lib_one/R.h
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-#ifndef TEST_DATA_LIB_R_H_
-#define TEST_DATA_LIB_R_H_
+#ifndef TEST_DATA_LIB_ONE_R_H_
+#define TEST_DATA_LIB_ONE_R_H_
#include <cstdint>
namespace com {
namespace android {
-namespace lib {
+namespace lib_one {
struct R {
struct attr {
@@ -36,10 +36,16 @@ struct R {
Theme = 0x02020000, // default
};
};
+
+ struct string {
+ enum : uint32_t {
+ foo = 0x02030000, // default
+ };
+ };
};
-} // namespace lib
+} // namespace lib_one
} // namespace android
} // namespace com
-#endif // TEST_DATA_R_H_
+#endif // TEST_DATA_LIB_ONE_R_H_
diff --git a/libs/androidfw/tests/data/lib/build b/libs/androidfw/tests/data/lib_one/build
index 5c3d02c850bf..c6adf0b1dda6 100755
--- a/libs/androidfw/tests/data/lib/build
+++ b/libs/androidfw/tests/data/lib_one/build
@@ -17,4 +17,4 @@
set -e
-aapt package -M AndroidManifest.xml -S res -F lib.apk -f --shared-lib
+aapt package -M AndroidManifest.xml -S res -F lib_one.apk -f --shared-lib
diff --git a/libs/androidfw/tests/data/lib_one/lib_one.apk b/libs/androidfw/tests/data/lib_one/lib_one.apk
new file mode 100644
index 000000000000..f287554d674d
--- /dev/null
+++ b/libs/androidfw/tests/data/lib_one/lib_one.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/lib_one/res/values/values.xml b/libs/androidfw/tests/data/lib_one/res/values/values.xml
new file mode 100644
index 000000000000..752b7e912ab6
--- /dev/null
+++ b/libs/androidfw/tests/data/lib_one/res/values/values.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+
+<resources>
+ <public type="attr" name="attr1" id="0x00010000" />
+ <attr name="attr1" format="integer" />
+
+ <public type="attr" name="attr2" id="0x00010001" />
+ <attr name="attr2" format="integer" />
+
+ <public type="style" name="Theme" id="0x00020000" />
+ <style name="Theme">
+ <item name="com.android.lib_one:attr1">700</item>
+ <item name="com.android.lib_one:attr2">?com.android.lib_one:attr1</item>
+ </style>
+
+ <public type="string" name="foo" id="0x00030000" />
+ <string name="foo">Foo from lib_one</string>
+</resources>
diff --git a/libs/androidfw/tests/data/lib_two/AndroidManifest.xml b/libs/androidfw/tests/data/lib_two/AndroidManifest.xml
new file mode 100644
index 000000000000..4b131e55a8a4
--- /dev/null
+++ b/libs/androidfw/tests/data/lib_two/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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 package="com.android.lib_two">
+ <application />
+</manifest>
diff --git a/libs/androidfw/tests/data/lib_two/R.h b/libs/androidfw/tests/data/lib_two/R.h
new file mode 100644
index 000000000000..c04a9d3b4de0
--- /dev/null
+++ b/libs/androidfw/tests/data/lib_two/R.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef TEST_DATA_LIB_TWO_R_H_
+#define TEST_DATA_LIB_TWO_R_H_
+
+#include <cstdint>
+
+namespace com {
+namespace android {
+namespace lib_two {
+
+struct R {
+ struct string {
+ enum : uint32_t {
+ LibraryString = 0x02020000, // default
+ foo = 0x02020001, // default
+ };
+ };
+};
+
+} // namespace lib_two
+} // namespace android
+} // namespace com
+
+#endif // TEST_DATA_LIB_TWO_R_H_
diff --git a/libs/androidfw/tests/data/lib_two/build b/libs/androidfw/tests/data/lib_two/build
new file mode 100755
index 000000000000..fd75e1dc7428
--- /dev/null
+++ b/libs/androidfw/tests/data/lib_two/build
@@ -0,0 +1,20 @@
+#!/bin/bash
+#
+# Copyright (C) 2014 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
+
+aapt package -M AndroidManifest.xml -S res -F lib_two.apk -f --shared-lib
diff --git a/libs/androidfw/tests/data/lib_two/lib_two.apk b/libs/androidfw/tests/data/lib_two/lib_two.apk
new file mode 100644
index 000000000000..ad44f9c21e31
--- /dev/null
+++ b/libs/androidfw/tests/data/lib_two/lib_two.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/lib/res/values/values.xml b/libs/androidfw/tests/data/lib_two/res/values/values.xml
index 51e3a407c538..f4eea2610cab 100644
--- a/libs/androidfw/tests/data/lib/res/values/values.xml
+++ b/libs/androidfw/tests/data/lib_two/res/values/values.xml
@@ -15,11 +15,9 @@
-->
<resources>
- <attr name="attr1" format="integer" />
- <attr name="attr2" format="integer" />
+ <public type="string" name="LibraryString" id="0x00020000" />
+ <string name="LibraryString">Hi from library two</string>
- <style name="Theme">
- <item name="com.android.lib:attr1">700</item>
- <item name="com.android.lib:attr2">?com.android.lib:attr1</item>
- </style>
+ <public type="string" name="foo" id="0x00020001" />
+ <string name="foo">Foo from lib_two</string>
</resources>
diff --git a/libs/androidfw/tests/data/libclient/AndroidManifest.xml b/libs/androidfw/tests/data/libclient/AndroidManifest.xml
new file mode 100644
index 000000000000..8436383dbd81
--- /dev/null
+++ b/libs/androidfw/tests/data/libclient/AndroidManifest.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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 package="com.android.libclient">
+ <application />
+</manifest>
diff --git a/libs/androidfw/tests/data/libclient/R.h b/libs/androidfw/tests/data/libclient/R.h
new file mode 100644
index 000000000000..43d1f9bb68e7
--- /dev/null
+++ b/libs/androidfw/tests/data/libclient/R.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+#ifndef TEST_DATA_LIB_R_H_
+#define TEST_DATA_LIB_R_H_
+
+#include <cstdint>
+
+namespace com {
+namespace android {
+namespace libclient {
+
+struct R {
+ struct attr {
+ enum : uint32_t {
+ foo = 0x7f010000, // default
+ bar = 0x7f010001, // default
+ };
+ };
+
+ struct style {
+ enum : uint32_t {
+ Theme = 0x7f020000, // default
+ };
+ };
+
+ struct string {
+ enum : uint32_t {
+ foo_one = 0x7f030000, // default
+ foo_two = 0x7f030001, // default
+ };
+ };
+};
+
+} // namespace libclient
+} // namespace android
+} // namespace com
+
+#endif // TEST_DATA_R_H_
diff --git a/libs/androidfw/tests/data/libclient/build b/libs/androidfw/tests/data/libclient/build
new file mode 100755
index 000000000000..08310e3c6eb8
--- /dev/null
+++ b/libs/androidfw/tests/data/libclient/build
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Copyright (C) 2014 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
+
+PATH_TO_FRAMEWORK_RES=${ANDROID_BUILD_TOP}/prebuilts/sdk/current/android.jar
+PATH_TO_LIB_ONE=../lib_one/lib_one.apk
+PATH_TO_LIB_TWO=../lib_two/lib_two.apk
+
+aapt package \
+ -M AndroidManifest.xml \
+ -S res \
+ -I $PATH_TO_FRAMEWORK_RES \
+ -I $PATH_TO_LIB_ONE \
+ -I $PATH_TO_LIB_TWO \
+ -F libclient.apk -f
diff --git a/libs/androidfw/tests/data/libclient/libclient.apk b/libs/androidfw/tests/data/libclient/libclient.apk
new file mode 100644
index 000000000000..17990248e862
--- /dev/null
+++ b/libs/androidfw/tests/data/libclient/libclient.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/libclient/res/values/values.xml b/libs/androidfw/tests/data/libclient/res/values/values.xml
new file mode 100644
index 000000000000..fead7c323767
--- /dev/null
+++ b/libs/androidfw/tests/data/libclient/res/values/values.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<resources>
+ <public type="attr" name="foo" id="0x7f010000" />
+ <attr name="foo" />
+
+ <public type="attr" name="bar" id="0x7f010001" />
+ <attr name="bar" />
+
+ <public type="style" name="Theme" id="0x7f020000" />
+ <style name="Theme" parent="com.android.lib_one:style/Theme">
+ <item name="foo">?com.android.lib_one:attr/attr2</item>
+ <item name="bar">@com.android.lib_one:string/foo</item>
+ </style>
+
+ <public type="string" name="foo_one" id="0x7f030000" />
+ <string name="foo_one">@com.android.lib_one:string/foo</string>
+
+ <public type="string" name="foo_two" id="0x7f030001" />
+ <string name="foo_two">@com.android.lib_two:string/foo</string>
+</resources>