Refactor AssetManager
Bug: 64071469
Test: atest CtsContentTestCases
Change-Id: Ia6856157e8813856268fba003e1e591d690cb26e
diff --git a/libs/androidfw/tests/ApkAssets_test.cpp b/libs/androidfw/tests/ApkAssets_test.cpp
index 6c43a67..e2b9f00 100644
--- a/libs/androidfw/tests/ApkAssets_test.cpp
+++ b/libs/androidfw/tests/ApkAssets_test.cpp
@@ -26,58 +26,56 @@
using ::android::base::unique_fd;
using ::com::android::basic::R;
+using ::testing::Eq;
+using ::testing::Ge;
+using ::testing::NotNull;
+using ::testing::SizeIs;
+using ::testing::StrEq;
namespace android {
TEST(ApkAssetsTest, LoadApk) {
std::unique_ptr<const ApkAssets> loaded_apk =
ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
- ASSERT_NE(nullptr, loaded_apk);
+ ASSERT_THAT(loaded_apk, NotNull());
const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
- ASSERT_NE(nullptr, loaded_arsc);
-
- const LoadedPackage* loaded_package = loaded_arsc->GetPackageForId(0x7f010000);
- ASSERT_NE(nullptr, loaded_package);
-
- std::unique_ptr<Asset> asset = loaded_apk->Open("res/layout/main.xml");
- ASSERT_NE(nullptr, asset);
+ ASSERT_THAT(loaded_arsc, NotNull());
+ ASSERT_THAT(loaded_arsc->GetPackageById(0x7fu), NotNull());
+ ASSERT_THAT(loaded_apk->Open("res/layout/main.xml"), NotNull());
}
TEST(ApkAssetsTest, LoadApkFromFd) {
const std::string path = GetTestDataPath() + "/basic/basic.apk";
unique_fd fd(::open(path.c_str(), O_RDONLY | O_BINARY));
- ASSERT_GE(fd.get(), 0);
+ ASSERT_THAT(fd.get(), Ge(0));
std::unique_ptr<const ApkAssets> loaded_apk =
ApkAssets::LoadFromFd(std::move(fd), path, false /*system*/, false /*force_shared_lib*/);
- ASSERT_NE(nullptr, loaded_apk);
+ ASSERT_THAT(loaded_apk, NotNull());
const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
- ASSERT_NE(nullptr, loaded_arsc);
-
- const LoadedPackage* loaded_package = loaded_arsc->GetPackageForId(0x7f010000);
- ASSERT_NE(nullptr, loaded_package);
-
- std::unique_ptr<Asset> asset = loaded_apk->Open("res/layout/main.xml");
- ASSERT_NE(nullptr, asset);
+ ASSERT_THAT(loaded_arsc, NotNull());
+ ASSERT_THAT(loaded_arsc->GetPackageById(0x7fu), NotNull());
+ ASSERT_THAT(loaded_apk->Open("res/layout/main.xml"), NotNull());
}
TEST(ApkAssetsTest, LoadApkAsSharedLibrary) {
std::unique_ptr<const ApkAssets> loaded_apk =
ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
- ASSERT_NE(nullptr, loaded_apk);
+ ASSERT_THAT(loaded_apk, NotNull());
+
const LoadedArsc* loaded_arsc = loaded_apk->GetLoadedArsc();
- ASSERT_NE(nullptr, loaded_arsc);
- ASSERT_EQ(1u, loaded_arsc->GetPackages().size());
+ ASSERT_THAT(loaded_arsc, NotNull());
+ ASSERT_THAT(loaded_arsc->GetPackages(), SizeIs(1u));
EXPECT_FALSE(loaded_arsc->GetPackages()[0]->IsDynamic());
loaded_apk = ApkAssets::LoadAsSharedLibrary(GetTestDataPath() + "/appaslib/appaslib.apk");
- ASSERT_NE(nullptr, loaded_apk);
+ ASSERT_THAT(loaded_apk, NotNull());
loaded_arsc = loaded_apk->GetLoadedArsc();
- ASSERT_NE(nullptr, loaded_arsc);
- ASSERT_EQ(1u, loaded_arsc->GetPackages().size());
+ ASSERT_THAT(loaded_arsc, NotNull());
+ ASSERT_THAT(loaded_arsc->GetPackages(), SizeIs(1u));
EXPECT_TRUE(loaded_arsc->GetPackages()[0]->IsDynamic());
}
@@ -86,19 +84,22 @@
ResTable target_table;
const std::string target_path = GetTestDataPath() + "/basic/basic.apk";
ASSERT_TRUE(ReadFileFromZipToString(target_path, "resources.arsc", &contents));
- ASSERT_EQ(NO_ERROR, target_table.add(contents.data(), contents.size(), 0, true /*copyData*/));
+ ASSERT_THAT(target_table.add(contents.data(), contents.size(), 0, true /*copyData*/),
+ Eq(NO_ERROR));
ResTable overlay_table;
const std::string overlay_path = GetTestDataPath() + "/overlay/overlay.apk";
ASSERT_TRUE(ReadFileFromZipToString(overlay_path, "resources.arsc", &contents));
- ASSERT_EQ(NO_ERROR, overlay_table.add(contents.data(), contents.size(), 0, true /*copyData*/));
+ ASSERT_THAT(overlay_table.add(contents.data(), contents.size(), 0, true /*copyData*/),
+ Eq(NO_ERROR));
util::unique_cptr<void> idmap_data;
void* temp_data;
size_t idmap_len;
- ASSERT_EQ(NO_ERROR, target_table.createIdmap(overlay_table, 0u, 0u, target_path.c_str(),
- overlay_path.c_str(), &temp_data, &idmap_len));
+ ASSERT_THAT(target_table.createIdmap(overlay_table, 0u, 0u, target_path.c_str(),
+ overlay_path.c_str(), &temp_data, &idmap_len),
+ Eq(NO_ERROR));
idmap_data.reset(temp_data);
TemporaryFile tf;
@@ -108,37 +109,30 @@
// Open something so that the destructor of TemporaryFile closes a valid fd.
tf.fd = open("/dev/null", O_WRONLY);
- std::unique_ptr<const ApkAssets> loaded_overlay_apk = ApkAssets::LoadOverlay(tf.path);
- ASSERT_NE(nullptr, loaded_overlay_apk);
+ ASSERT_THAT(ApkAssets::LoadOverlay(tf.path), NotNull());
}
TEST(ApkAssetsTest, CreateAndDestroyAssetKeepsApkAssetsOpen) {
std::unique_ptr<const ApkAssets> loaded_apk =
ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
- ASSERT_NE(nullptr, loaded_apk);
+ ASSERT_THAT(loaded_apk, NotNull());
- {
- std::unique_ptr<Asset> assets = loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER);
- ASSERT_NE(nullptr, assets);
- }
+ { ASSERT_THAT(loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER), NotNull()); }
- {
- std::unique_ptr<Asset> assets = loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER);
- ASSERT_NE(nullptr, assets);
- }
+ { ASSERT_THAT(loaded_apk->Open("res/layout/main.xml", Asset::ACCESS_BUFFER), NotNull()); }
}
TEST(ApkAssetsTest, OpenUncompressedAssetFd) {
std::unique_ptr<const ApkAssets> loaded_apk =
ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
- ASSERT_NE(nullptr, loaded_apk);
+ ASSERT_THAT(loaded_apk, NotNull());
auto asset = loaded_apk->Open("assets/uncompressed.txt", Asset::ACCESS_UNKNOWN);
- ASSERT_NE(nullptr, asset);
+ ASSERT_THAT(asset, NotNull());
off64_t start, length;
unique_fd fd(asset->openFileDescriptor(&start, &length));
- EXPECT_GE(fd.get(), 0);
+ ASSERT_THAT(fd.get(), Ge(0));
lseek64(fd.get(), start, SEEK_SET);
@@ -146,7 +140,7 @@
buffer.resize(length);
ASSERT_TRUE(base::ReadFully(fd.get(), &*buffer.begin(), length));
- EXPECT_EQ("This should be uncompressed.\n\n", buffer);
+ EXPECT_THAT(buffer, StrEq("This should be uncompressed.\n\n"));
}
} // namespace android
diff --git a/libs/androidfw/tests/AssetManager2_bench.cpp b/libs/androidfw/tests/AssetManager2_bench.cpp
index 85e8f25..437e147 100644
--- a/libs/androidfw/tests/AssetManager2_bench.cpp
+++ b/libs/androidfw/tests/AssetManager2_bench.cpp
@@ -81,17 +81,18 @@
}
BENCHMARK(BM_AssetManagerLoadFrameworkAssetsOld);
-static void BM_AssetManagerGetResource(benchmark::State& state) {
- GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
- basic::R::integer::number1, state);
+static void BM_AssetManagerGetResource(benchmark::State& state, uint32_t resid) {
+ GetResourceBenchmark({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/, resid, state);
}
-BENCHMARK(BM_AssetManagerGetResource);
+BENCHMARK_CAPTURE(BM_AssetManagerGetResource, number1, basic::R::integer::number1);
+BENCHMARK_CAPTURE(BM_AssetManagerGetResource, deep_ref, basic::R::integer::deep_ref);
-static void BM_AssetManagerGetResourceOld(benchmark::State& state) {
- GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/,
- basic::R::integer::number1, state);
+static void BM_AssetManagerGetResourceOld(benchmark::State& state, uint32_t resid) {
+ GetResourceBenchmarkOld({GetTestDataPath() + "/basic/basic.apk"}, nullptr /*config*/, resid,
+ state);
}
-BENCHMARK(BM_AssetManagerGetResourceOld);
+BENCHMARK_CAPTURE(BM_AssetManagerGetResourceOld, number1, basic::R::integer::number1);
+BENCHMARK_CAPTURE(BM_AssetManagerGetResourceOld, deep_ref, basic::R::integer::deep_ref);
static void BM_AssetManagerGetLibraryResource(benchmark::State& state) {
GetResourceBenchmark(
@@ -196,7 +197,7 @@
static void BM_AssetManagerGetResourceLocalesOld(benchmark::State& state) {
AssetManager assets;
if (!assets.addAssetPath(String8(kFrameworkPath), nullptr /*cookie*/, false /*appAsLib*/,
- false /*isSystemAssets*/)) {
+ true /*isSystemAssets*/)) {
state.SkipWithError("Failed to load assets");
return;
}
@@ -211,4 +212,44 @@
}
BENCHMARK(BM_AssetManagerGetResourceLocalesOld);
+static void BM_AssetManagerSetConfigurationFramework(benchmark::State& state) {
+ std::unique_ptr<const 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));
+
+ while (state.KeepRunning()) {
+ config.sdkVersion = ~config.sdkVersion;
+ assets.SetConfiguration(config);
+ }
+}
+BENCHMARK(BM_AssetManagerSetConfigurationFramework);
+
+static void BM_AssetManagerSetConfigurationFrameworkOld(benchmark::State& state) {
+ AssetManager assets;
+ if (!assets.addAssetPath(String8(kFrameworkPath), nullptr /*cookie*/, false /*appAsLib*/,
+ true /*isSystemAssets*/)) {
+ state.SkipWithError("Failed to load assets");
+ return;
+ }
+
+ const ResTable& table = assets.getResources(true);
+
+ ResTable_config config;
+ memset(&config, 0, sizeof(config));
+
+ while (state.KeepRunning()) {
+ config.sdkVersion = ~config.sdkVersion;
+ assets.setConfiguration(config);
+ }
+}
+BENCHMARK(BM_AssetManagerSetConfigurationFrameworkOld);
+
} // namespace android
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 92462a6..7cac2b3 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -36,6 +36,10 @@
namespace lib_two = com::android::lib_two;
namespace libclient = com::android::libclient;
+using ::testing::Eq;
+using ::testing::NotNull;
+using ::testing::StrEq;
+
namespace android {
class AssetManager2Test : public ::testing::Test {
@@ -59,11 +63,14 @@
libclient_assets_ = ApkAssets::Load(GetTestDataPath() + "/libclient/libclient.apk");
ASSERT_NE(nullptr, libclient_assets_);
- appaslib_assets_ = ApkAssets::Load(GetTestDataPath() + "/appaslib/appaslib.apk");
+ appaslib_assets_ = ApkAssets::LoadAsSharedLibrary(GetTestDataPath() + "/appaslib/appaslib.apk");
ASSERT_NE(nullptr, appaslib_assets_);
system_assets_ = ApkAssets::Load(GetTestDataPath() + "/system/system.apk", true /*system*/);
ASSERT_NE(nullptr, system_assets_);
+
+ app_assets_ = ApkAssets::Load(GetTestDataPath() + "/app/app.apk");
+ ASSERT_THAT(app_assets_, NotNull());
}
protected:
@@ -75,6 +82,7 @@
std::unique_ptr<const ApkAssets> libclient_assets_;
std::unique_ptr<const ApkAssets> appaslib_assets_;
std::unique_ptr<const ApkAssets> system_assets_;
+ std::unique_ptr<const ApkAssets> app_assets_;
};
TEST_F(AssetManager2Test, FindsResourceFromSingleApkAssets) {
@@ -233,6 +241,25 @@
assetmanager.SetApkAssets(
{lib_two_assets_.get(), lib_one_assets_.get(), libclient_assets_.get()});
+ const ResolvedBag* bag = assetmanager.GetBag(fix_package_id(lib_one::R::style::Theme, 0x03));
+ 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, get_package_id(bag->entries[0].key));
+ EXPECT_EQ(1, bag->entries[1].cookie);
+ EXPECT_EQ(0x03, get_package_id(bag->entries[1].key));
+}
+
+TEST_F(AssetManager2Test, FindsStyleResourceWithParentFromSharedLibrary) {
+ 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);
@@ -446,8 +473,68 @@
assetmanager.GetResourceId("main", "layout", "com.android.basic"));
}
-TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {}
+TEST_F(AssetManager2Test, OpensFileFromSingleApkAssets) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({system_assets_.get()});
-TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {}
+ std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER);
+ ASSERT_THAT(asset, NotNull());
+
+ const char* data = reinterpret_cast<const char*>(asset->getBuffer(false /*wordAligned*/));
+ ASSERT_THAT(data, NotNull());
+ EXPECT_THAT(std::string(data, asset->getLength()), StrEq("file\n"));
+}
+
+TEST_F(AssetManager2Test, OpensFileFromMultipleApkAssets) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()});
+
+ std::unique_ptr<Asset> asset = assetmanager.Open("file.txt", Asset::ACCESS_BUFFER);
+ ASSERT_THAT(asset, NotNull());
+
+ const char* data = reinterpret_cast<const char*>(asset->getBuffer(false /*wordAligned*/));
+ ASSERT_THAT(data, NotNull());
+ EXPECT_THAT(std::string(data, asset->getLength()), StrEq("app override file\n"));
+}
+
+TEST_F(AssetManager2Test, OpenDir) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({system_assets_.get()});
+
+ std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir("");
+ ASSERT_THAT(asset_dir, NotNull());
+ ASSERT_THAT(asset_dir->getFileCount(), Eq(2u));
+
+ EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("file.txt")));
+ EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular));
+
+ EXPECT_THAT(asset_dir->getFileName(1), Eq(String8("subdir")));
+ EXPECT_THAT(asset_dir->getFileType(1), Eq(FileType::kFileTypeDirectory));
+
+ asset_dir = assetmanager.OpenDir("subdir");
+ ASSERT_THAT(asset_dir, NotNull());
+ ASSERT_THAT(asset_dir->getFileCount(), Eq(1u));
+
+ EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("subdir_file.txt")));
+ EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular));
+}
+
+TEST_F(AssetManager2Test, OpenDirFromManyApks) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({system_assets_.get(), app_assets_.get()});
+
+ std::unique_ptr<AssetDir> asset_dir = assetmanager.OpenDir("");
+ ASSERT_THAT(asset_dir, NotNull());
+ ASSERT_THAT(asset_dir->getFileCount(), Eq(3u));
+
+ EXPECT_THAT(asset_dir->getFileName(0), Eq(String8("app_file.txt")));
+ EXPECT_THAT(asset_dir->getFileType(0), Eq(FileType::kFileTypeRegular));
+
+ EXPECT_THAT(asset_dir->getFileName(1), Eq(String8("file.txt")));
+ EXPECT_THAT(asset_dir->getFileType(1), Eq(FileType::kFileTypeRegular));
+
+ EXPECT_THAT(asset_dir->getFileName(2), Eq(String8("subdir")));
+ EXPECT_THAT(asset_dir->getFileType(2), Eq(FileType::kFileTypeDirectory));
+}
} // namespace android
diff --git a/libs/androidfw/tests/AttributeResolution_bench.cpp b/libs/androidfw/tests/AttributeResolution_bench.cpp
new file mode 100644
index 0000000..fa300c5
--- /dev/null
+++ b/libs/androidfw/tests/AttributeResolution_bench.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#include "benchmark/benchmark.h"
+
+//#include "android-base/stringprintf.h"
+#include "androidfw/ApkAssets.h"
+#include "androidfw/AssetManager.h"
+#include "androidfw/AssetManager2.h"
+#include "androidfw/AttributeResolution.h"
+#include "androidfw/ResourceTypes.h"
+
+#include "BenchmarkHelpers.h"
+#include "data/basic/R.h"
+#include "data/styles/R.h"
+
+namespace app = com::android::app;
+namespace basic = com::android::basic;
+
+namespace android {
+
+constexpr const static char* kFrameworkPath = "/system/framework/framework-res.apk";
+constexpr const static uint32_t Theme_Material_Light = 0x01030237u;
+
+static void BM_ApplyStyle(benchmark::State& state) {
+ std::unique_ptr<const ApkAssets> styles_apk =
+ ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
+ if (styles_apk == nullptr) {
+ state.SkipWithError("failed to load assets");
+ return;
+ }
+
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({styles_apk.get()});
+
+ std::unique_ptr<Asset> asset =
+ assetmanager.OpenNonAsset("res/layout/layout.xml", Asset::ACCESS_BUFFER);
+ if (asset == nullptr) {
+ state.SkipWithError("failed to load layout");
+ return;
+ }
+
+ ResXMLTree xml_tree;
+ if (xml_tree.setTo(asset->getBuffer(true), asset->getLength(), false /*copyData*/) != NO_ERROR) {
+ state.SkipWithError("corrupt xml layout");
+ return;
+ }
+
+ // Skip to the first tag.
+ while (xml_tree.next() != ResXMLParser::START_TAG) {
+ }
+
+ std::unique_ptr<Theme> theme = assetmanager.NewTheme();
+ theme->ApplyStyle(app::R::style::StyleTwo);
+
+ std::array<uint32_t, 6> attrs{{app::R::attr::attr_one, app::R::attr::attr_two,
+ app::R::attr::attr_three, app::R::attr::attr_four,
+ app::R::attr::attr_five, app::R::attr::attr_empty}};
+ std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
+ std::array<uint32_t, attrs.size() + 1> indices;
+
+ while (state.KeepRunning()) {
+ ApplyStyle(theme.get(), &xml_tree, 0u /*def_style_attr*/, 0u /*def_style_res*/, attrs.data(),
+ attrs.size(), values.data(), indices.data());
+ }
+}
+BENCHMARK(BM_ApplyStyle);
+
+static void BM_ApplyStyleFramework(benchmark::State& state) {
+ std::unique_ptr<const ApkAssets> framework_apk = ApkAssets::Load(kFrameworkPath);
+ if (framework_apk == nullptr) {
+ state.SkipWithError("failed to load framework assets");
+ return;
+ }
+
+ std::unique_ptr<const ApkAssets> basic_apk =
+ ApkAssets::Load(GetTestDataPath() + "/basic/basic.apk");
+ if (basic_apk == nullptr) {
+ state.SkipWithError("failed to load assets");
+ return;
+ }
+
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({framework_apk.get(), basic_apk.get()});
+
+ ResTable_config device_config;
+ memset(&device_config, 0, sizeof(device_config));
+ device_config.language[0] = 'e';
+ device_config.language[1] = 'n';
+ device_config.country[0] = 'U';
+ device_config.country[1] = 'S';
+ device_config.orientation = ResTable_config::ORIENTATION_PORT;
+ device_config.smallestScreenWidthDp = 700;
+ device_config.screenWidthDp = 700;
+ device_config.screenHeightDp = 1024;
+ device_config.sdkVersion = 27;
+
+ Res_value value;
+ ResTable_config config;
+ uint32_t flags = 0u;
+ ApkAssetsCookie cookie =
+ assetmanager.GetResource(basic::R::layout::layoutt, false /*may_be_bag*/,
+ 0u /*density_override*/, &value, &config, &flags);
+ if (cookie == kInvalidCookie) {
+ state.SkipWithError("failed to find R.layout.layout");
+ return;
+ }
+
+ size_t len = 0u;
+ const char* layout_path =
+ assetmanager.GetStringPoolForCookie(cookie)->string8At(value.data, &len);
+ if (layout_path == nullptr || len == 0u) {
+ state.SkipWithError("failed to lookup layout path");
+ return;
+ }
+
+ std::unique_ptr<Asset> asset = assetmanager.OpenNonAsset(
+ StringPiece(layout_path, len).to_string(), cookie, Asset::ACCESS_BUFFER);
+ if (asset == nullptr) {
+ state.SkipWithError("failed to load layout");
+ return;
+ }
+
+ ResXMLTree xml_tree;
+ if (xml_tree.setTo(asset->getBuffer(true), asset->getLength(), false /*copyData*/) != NO_ERROR) {
+ state.SkipWithError("corrupt xml layout");
+ return;
+ }
+
+ // Skip to the first tag.
+ while (xml_tree.next() != ResXMLParser::START_TAG) {
+ }
+
+ std::unique_ptr<Theme> theme = assetmanager.NewTheme();
+ theme->ApplyStyle(Theme_Material_Light);
+
+ std::array<uint32_t, 92> attrs{
+ {0x0101000e, 0x01010034, 0x01010095, 0x01010096, 0x01010097, 0x01010098, 0x01010099,
+ 0x0101009a, 0x0101009b, 0x010100ab, 0x010100af, 0x010100b0, 0x010100b1, 0x0101011f,
+ 0x01010120, 0x0101013f, 0x01010140, 0x0101014e, 0x0101014f, 0x01010150, 0x01010151,
+ 0x01010152, 0x01010153, 0x01010154, 0x01010155, 0x01010156, 0x01010157, 0x01010158,
+ 0x01010159, 0x0101015a, 0x0101015b, 0x0101015c, 0x0101015d, 0x0101015e, 0x0101015f,
+ 0x01010160, 0x01010161, 0x01010162, 0x01010163, 0x01010164, 0x01010165, 0x01010166,
+ 0x01010167, 0x01010168, 0x01010169, 0x0101016a, 0x0101016b, 0x0101016c, 0x0101016d,
+ 0x0101016e, 0x0101016f, 0x01010170, 0x01010171, 0x01010217, 0x01010218, 0x0101021d,
+ 0x01010220, 0x01010223, 0x01010224, 0x01010264, 0x01010265, 0x01010266, 0x010102c5,
+ 0x010102c6, 0x010102c7, 0x01010314, 0x01010315, 0x01010316, 0x0101035e, 0x0101035f,
+ 0x01010362, 0x01010374, 0x0101038c, 0x01010392, 0x01010393, 0x010103ac, 0x0101045d,
+ 0x010104b6, 0x010104b7, 0x010104d6, 0x010104d7, 0x010104dd, 0x010104de, 0x010104df,
+ 0x01010535, 0x01010536, 0x01010537, 0x01010538, 0x01010546, 0x01010567, 0x011100c9,
+ 0x011100ca}};
+
+ std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
+ std::array<uint32_t, attrs.size() + 1> indices;
+ while (state.KeepRunning()) {
+ ApplyStyle(theme.get(), &xml_tree, 0x01010084u /*def_style_attr*/, 0u /*def_style_res*/,
+ attrs.data(), attrs.size(), values.data(), indices.data());
+ }
+}
+BENCHMARK(BM_ApplyStyleFramework);
+
+} // namespace android
diff --git a/libs/androidfw/tests/AttributeResolution_test.cpp b/libs/androidfw/tests/AttributeResolution_test.cpp
index 2d73ce8..c8dbe20 100644
--- a/libs/androidfw/tests/AttributeResolution_test.cpp
+++ b/libs/androidfw/tests/AttributeResolution_test.cpp
@@ -21,6 +21,8 @@
#include "android-base/file.h"
#include "android-base/logging.h"
#include "android-base/macros.h"
+#include "androidfw/AssetManager2.h"
+#include "androidfw/ResourceUtils.h"
#include "TestHelpers.h"
#include "data/styles/R.h"
@@ -32,15 +34,14 @@
class AttributeResolutionTest : public ::testing::Test {
public:
virtual void SetUp() override {
- std::string contents;
- ASSERT_TRUE(ReadFileFromZipToString(
- GetTestDataPath() + "/styles/styles.apk", "resources.arsc", &contents));
- ASSERT_EQ(NO_ERROR, table_.add(contents.data(), contents.size(),
- 1 /*cookie*/, true /*copyData*/));
+ styles_assets_ = ApkAssets::Load(GetTestDataPath() + "/styles/styles.apk");
+ ASSERT_NE(nullptr, styles_assets_);
+ assetmanager_.SetApkAssets({styles_assets_.get()});
}
protected:
- ResTable table_;
+ std::unique_ptr<const ApkAssets> styles_assets_;
+ AssetManager2 assetmanager_;
};
class AttributeResolutionXmlTest : public AttributeResolutionTest {
@@ -48,13 +49,12 @@
virtual void SetUp() override {
AttributeResolutionTest::SetUp();
- std::string contents;
- ASSERT_TRUE(
- ReadFileFromZipToString(GetTestDataPath() + "/styles/styles.apk",
- "res/layout/layout.xml", &contents));
+ std::unique_ptr<Asset> asset =
+ assetmanager_.OpenNonAsset("res/layout/layout.xml", Asset::ACCESS_BUFFER);
+ ASSERT_NE(nullptr, asset);
- ASSERT_EQ(NO_ERROR, xml_parser_.setTo(contents.data(), contents.size(),
- true /*copyData*/));
+ ASSERT_EQ(NO_ERROR,
+ xml_parser_.setTo(asset->getBuffer(true), asset->getLength(), true /*copyData*/));
// Skip to the first tag.
while (xml_parser_.next() != ResXMLParser::START_TAG) {
@@ -65,15 +65,50 @@
ResXMLTree xml_parser_;
};
+TEST(AttributeResolutionLibraryTest, ApplyStyleWithDefaultStyleResId) {
+ AssetManager2 assetmanager;
+ auto apk_assets = ApkAssets::LoadAsSharedLibrary(GetTestDataPath() + "/styles/styles.apk");
+ ASSERT_NE(nullptr, apk_assets);
+ assetmanager.SetApkAssets({apk_assets.get()});
+
+ std::unique_ptr<Theme> theme = assetmanager.NewTheme();
+
+ std::array<uint32_t, 2> attrs{
+ {fix_package_id(R::attr::attr_one, 0x02), fix_package_id(R::attr::attr_two, 0x02)}};
+ std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
+ std::array<uint32_t, attrs.size() + 1> indices;
+ ApplyStyle(theme.get(), nullptr /*xml_parser*/, 0u /*def_style_attr*/,
+ fix_package_id(R::style::StyleOne, 0x02), attrs.data(), attrs.size(), values.data(),
+ indices.data());
+
+ const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
+
+ const uint32_t* values_cursor = values.data();
+ EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
+ EXPECT_EQ(1u, values_cursor[STYLE_DATA]);
+ EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
+ EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
+ EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
+ EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
+
+ values_cursor += STYLE_NUM_ENTRIES;
+ EXPECT_EQ(Res_value::TYPE_INT_DEC, values_cursor[STYLE_TYPE]);
+ EXPECT_EQ(2u, values_cursor[STYLE_DATA]);
+ EXPECT_EQ(0u, values_cursor[STYLE_RESOURCE_ID]);
+ EXPECT_EQ(1u, values_cursor[STYLE_ASSET_COOKIE]);
+ EXPECT_EQ(0u, values_cursor[STYLE_DENSITY]);
+ EXPECT_EQ(public_flag, values_cursor[STYLE_CHANGING_CONFIGURATIONS]);
+}
+
TEST_F(AttributeResolutionTest, Theme) {
- ResTable::Theme theme(table_);
- ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
+ std::unique_ptr<Theme> theme = assetmanager_.NewTheme();
+ ASSERT_TRUE(theme->ApplyStyle(R::style::StyleTwo));
std::array<uint32_t, 5> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
R::attr::attr_four, R::attr::attr_empty}};
std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
- ASSERT_TRUE(ResolveAttrs(&theme, 0 /*def_style_attr*/, 0 /*def_style_res*/,
+ ASSERT_TRUE(ResolveAttrs(theme.get(), 0u /*def_style_attr*/, 0u /*def_style_res*/,
nullptr /*src_values*/, 0 /*src_values_length*/, attrs.data(),
attrs.size(), values.data(), nullptr /*out_indices*/));
@@ -126,8 +161,8 @@
R::attr::attr_four, R::attr::attr_empty}};
std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
- ASSERT_TRUE(RetrieveAttributes(&table_, &xml_parser_, attrs.data(), attrs.size(), values.data(),
- nullptr /*out_indices*/));
+ ASSERT_TRUE(RetrieveAttributes(&assetmanager_, &xml_parser_, attrs.data(), attrs.size(),
+ values.data(), nullptr /*out_indices*/));
uint32_t* values_cursor = values.data();
EXPECT_EQ(Res_value::TYPE_NULL, values_cursor[STYLE_TYPE]);
@@ -171,15 +206,15 @@
}
TEST_F(AttributeResolutionXmlTest, ThemeAndXmlParser) {
- ResTable::Theme theme(table_);
- ASSERT_EQ(NO_ERROR, theme.applyStyle(R::style::StyleTwo));
+ std::unique_ptr<Theme> theme = assetmanager_.NewTheme();
+ ASSERT_TRUE(theme->ApplyStyle(R::style::StyleTwo));
std::array<uint32_t, 6> attrs{{R::attr::attr_one, R::attr::attr_two, R::attr::attr_three,
R::attr::attr_four, R::attr::attr_five, R::attr::attr_empty}};
std::array<uint32_t, attrs.size() * STYLE_NUM_ENTRIES> values;
std::array<uint32_t, attrs.size() + 1> indices;
- ApplyStyle(&theme, &xml_parser_, 0 /*def_style_attr*/, 0 /*def_style_res*/, attrs.data(),
+ ApplyStyle(theme.get(), &xml_parser_, 0u /*def_style_attr*/, 0u /*def_style_res*/, attrs.data(),
attrs.size(), values.data(), indices.data());
const uint32_t public_flag = ResTable_typeSpec::SPEC_PUBLIC;
diff --git a/libs/androidfw/tests/BenchmarkHelpers.cpp b/libs/androidfw/tests/BenchmarkHelpers.cpp
index 7149bee..faddfe5 100644
--- a/libs/androidfw/tests/BenchmarkHelpers.cpp
+++ b/libs/androidfw/tests/BenchmarkHelpers.cpp
@@ -33,19 +33,21 @@
}
}
+ // Make sure to force creation of the ResTable first, or else the configuration doesn't get set.
+ const ResTable& table = assetmanager.getResources(true);
if (config != nullptr) {
assetmanager.setConfiguration(*config);
}
- const ResTable& table = assetmanager.getResources(true);
-
Res_value value;
ResTable_config selected_config;
uint32_t flags;
+ uint32_t last_ref = 0u;
while (state.KeepRunning()) {
- table.getResource(resid, &value, false /*may_be_bag*/, 0u /*density*/, &flags,
- &selected_config);
+ ssize_t block = table.getResource(resid, &value, false /*may_be_bag*/, 0u /*density*/, &flags,
+ &selected_config);
+ table.resolveReference(&value, block, &last_ref, &flags, &selected_config);
}
}
@@ -72,10 +74,12 @@
Res_value value;
ResTable_config selected_config;
uint32_t flags;
+ uint32_t last_id = 0u;
while (state.KeepRunning()) {
- assetmanager.GetResource(resid, false /* may_be_bag */, 0u /* density_override */, &value,
- &selected_config, &flags);
+ ApkAssetsCookie cookie = assetmanager.GetResource(
+ resid, false /* may_be_bag */, 0u /* density_override */, &value, &selected_config, &flags);
+ assetmanager.ResolveReference(cookie, &value, &selected_config, &flags, &last_id);
}
}
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index 37ddafb..cae632d 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -16,6 +16,9 @@
#include "androidfw/LoadedArsc.h"
+#include "android-base/file.h"
+#include "androidfw/ResourceUtils.h"
+
#include "TestHelpers.h"
#include "data/basic/R.h"
#include "data/libclient/R.h"
@@ -27,6 +30,14 @@
namespace libclient = com::android::libclient;
namespace sparse = com::android::sparse;
+using ::android::base::ReadFileToString;
+using ::testing::Eq;
+using ::testing::Ge;
+using ::testing::IsNull;
+using ::testing::NotNull;
+using ::testing::SizeIs;
+using ::testing::StrEq;
+
namespace android {
TEST(LoadedArscTest, LoadSinglePackageArsc) {
@@ -35,39 +46,24 @@
&contents));
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
- ASSERT_NE(nullptr, loaded_arsc);
+ ASSERT_THAT(loaded_arsc, NotNull());
- 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());
+ const LoadedPackage* package =
+ loaded_arsc->GetPackageById(get_package_id(app::R::string::string_one));
+ ASSERT_THAT(package, NotNull());
+ EXPECT_THAT(package->GetPackageName(), StrEq("com.android.app"));
+ EXPECT_THAT(package->GetPackageId(), Eq(0x7f));
- ResTable_config config;
- memset(&config, 0, sizeof(config));
- config.sdkVersion = 24;
+ const uint8_t type_index = get_type_id(app::R::string::string_one) - 1;
+ const uint16_t entry_index = get_entry_id(app::R::string::string_one);
- FindEntryResult entry;
+ const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
+ ASSERT_THAT(type_spec, NotNull());
+ ASSERT_THAT(type_spec->type_count, Ge(1u));
- ASSERT_TRUE(loaded_arsc->FindEntry(app::R::string::string_one, config, &entry));
- ASSERT_NE(nullptr, entry.entry);
-}
-
-TEST(LoadedArscTest, FindDefaultEntry) {
- std::string contents;
- ASSERT_TRUE(
- ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
-
- std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
- ASSERT_NE(nullptr, loaded_arsc);
-
- ResTable_config desired_config;
- memset(&desired_config, 0, sizeof(desired_config));
- desired_config.language[0] = 'd';
- desired_config.language[1] = 'e';
-
- FindEntryResult entry;
- ASSERT_TRUE(loaded_arsc->FindEntry(basic::R::string::test1, desired_config, &entry));
- ASSERT_NE(nullptr, entry.entry);
+ const ResTable_type* type = type_spec->types[0];
+ ASSERT_THAT(type, NotNull());
+ ASSERT_THAT(LoadedPackage::GetEntry(type, entry_index), NotNull());
}
TEST(LoadedArscTest, LoadSparseEntryApp) {
@@ -76,15 +72,22 @@
&contents));
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
- ASSERT_NE(nullptr, loaded_arsc);
+ ASSERT_THAT(loaded_arsc, NotNull());
- ResTable_config config;
- memset(&config, 0, sizeof(config));
- config.sdkVersion = 26;
+ const LoadedPackage* package =
+ loaded_arsc->GetPackageById(get_package_id(sparse::R::integer::foo_9));
+ ASSERT_THAT(package, NotNull());
- FindEntryResult entry;
- ASSERT_TRUE(loaded_arsc->FindEntry(sparse::R::integer::foo_9, config, &entry));
- ASSERT_NE(nullptr, entry.entry);
+ 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_count, Ge(1u));
+
+ const ResTable_type* type = type_spec->types[0];
+ ASSERT_THAT(type, NotNull());
+ ASSERT_THAT(LoadedPackage::GetEntry(type, entry_index), NotNull());
}
TEST(LoadedArscTest, LoadSharedLibrary) {
@@ -93,14 +96,13 @@
&contents));
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
- ASSERT_NE(nullptr, loaded_arsc);
+ ASSERT_THAT(loaded_arsc, NotNull());
const auto& packages = loaded_arsc->GetPackages();
- ASSERT_EQ(1u, packages.size());
-
+ ASSERT_THAT(packages, SizeIs(1u));
EXPECT_TRUE(packages[0]->IsDynamic());
- EXPECT_EQ(std::string("com.android.lib_one"), packages[0]->GetPackageName());
- EXPECT_EQ(0, packages[0]->GetPackageId());
+ EXPECT_THAT(packages[0]->GetPackageName(), StrEq("com.android.lib_one"));
+ EXPECT_THAT(packages[0]->GetPackageId(), Eq(0));
const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
@@ -114,25 +116,23 @@
"resources.arsc", &contents));
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
- ASSERT_NE(nullptr, loaded_arsc);
+ ASSERT_THAT(loaded_arsc, NotNull());
const auto& packages = loaded_arsc->GetPackages();
- ASSERT_EQ(1u, packages.size());
-
+ ASSERT_THAT(packages, SizeIs(1u));
EXPECT_FALSE(packages[0]->IsDynamic());
- EXPECT_EQ(std::string("com.android.libclient"), packages[0]->GetPackageName());
- EXPECT_EQ(0x7f, packages[0]->GetPackageId());
+ EXPECT_THAT(packages[0]->GetPackageName(), StrEq("com.android.libclient"));
+ EXPECT_THAT(packages[0]->GetPackageId(), Eq(0x7f));
const auto& dynamic_pkg_map = packages[0]->GetDynamicPackageMap();
// The library has two dependencies.
- ASSERT_EQ(2u, dynamic_pkg_map.size());
+ ASSERT_THAT(dynamic_pkg_map, SizeIs(2u));
+ EXPECT_THAT(dynamic_pkg_map[0].package_name, StrEq("com.android.lib_one"));
+ EXPECT_THAT(dynamic_pkg_map[0].package_id, Eq(0x02));
- 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);
+ EXPECT_THAT(dynamic_pkg_map[1].package_name, StrEq("com.android.lib_two"));
+ EXPECT_THAT(dynamic_pkg_map[1].package_id, Eq(0x03));
}
TEST(LoadedArscTest, LoadAppAsSharedLibrary) {
@@ -143,13 +143,12 @@
std::unique_ptr<const LoadedArsc> loaded_arsc =
LoadedArsc::Load(StringPiece(contents), nullptr /*loaded_idmap*/, false /*system*/,
true /*load_as_shared_library*/);
- ASSERT_NE(nullptr, loaded_arsc);
+ ASSERT_THAT(loaded_arsc, NotNull());
const auto& packages = loaded_arsc->GetPackages();
- ASSERT_EQ(1u, packages.size());
-
+ ASSERT_THAT(packages, SizeIs(1u));
EXPECT_TRUE(packages[0]->IsDynamic());
- EXPECT_EQ(0x7f, packages[0]->GetPackageId());
+ EXPECT_THAT(packages[0]->GetPackageId(), Eq(0x7f));
}
TEST(LoadedArscTest, LoadFeatureSplit) {
@@ -157,21 +156,67 @@
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/feature/feature.apk", "resources.arsc",
&contents));
std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
- ASSERT_NE(nullptr, loaded_arsc);
+ ASSERT_THAT(loaded_arsc, NotNull());
- ResTable_config desired_config;
- memset(&desired_config, 0, sizeof(desired_config));
+ const LoadedPackage* package =
+ loaded_arsc->GetPackageById(get_package_id(basic::R::string::test3));
+ ASSERT_THAT(package, NotNull());
- FindEntryResult entry;
- ASSERT_TRUE(loaded_arsc->FindEntry(basic::R::string::test3, desired_config, &entry));
+ uint8_t type_index = get_type_id(basic::R::string::test3) - 1;
+ uint8_t entry_index = get_entry_id(basic::R::string::test3);
+
+ const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(type_index);
+ ASSERT_THAT(type_spec, NotNull());
+ ASSERT_THAT(type_spec->type_count, Ge(1u));
+ ASSERT_THAT(type_spec->types[0], NotNull());
size_t len;
- const char16_t* type_name16 = entry.type_string_ref.string16(&len);
- ASSERT_NE(nullptr, type_name16);
- ASSERT_NE(0u, len);
+ const char16_t* type_name16 =
+ package->GetTypeStringPool()->stringAt(type_spec->type_spec->id - 1, &len);
+ ASSERT_THAT(type_name16, NotNull());
+ EXPECT_THAT(util::Utf16ToUtf8(StringPiece16(type_name16, len)), StrEq("string"));
- std::string type_name = util::Utf16ToUtf8(StringPiece16(type_name16, len));
- EXPECT_EQ(std::string("string"), type_name);
+ 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 {
@@ -199,23 +244,33 @@
};
TEST(LoadedArscTest, LoadOverlay) {
- std::string contents, overlay_contents;
- ASSERT_TRUE(
- ReadFileFromZipToString(GetTestDataPath() + "/basic/basic.apk", "resources.arsc", &contents));
+ std::string contents;
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlay/overlay.apk", "resources.arsc",
- &overlay_contents));
+ &contents));
MockLoadedIdmap loaded_idmap;
std::unique_ptr<const LoadedArsc> loaded_arsc =
- LoadedArsc::Load(StringPiece(overlay_contents), &loaded_idmap);
- ASSERT_NE(nullptr, loaded_arsc);
+ LoadedArsc::Load(StringPiece(contents), &loaded_idmap);
+ ASSERT_THAT(loaded_arsc, NotNull());
- ResTable_config desired_config;
- memset(&desired_config, 0, sizeof(desired_config));
+ const LoadedPackage* package = loaded_arsc->GetPackageById(0x08u);
+ ASSERT_THAT(package, NotNull());
- FindEntryResult entry;
- ASSERT_TRUE(loaded_arsc->FindEntry(0x08030001u, desired_config, &entry));
+ const TypeSpec* type_spec = package->GetTypeSpecByTypeIndex(0x03u - 1);
+ ASSERT_THAT(type_spec, NotNull());
+ ASSERT_THAT(type_spec->type_count, Ge(1u));
+ ASSERT_THAT(type_spec->types[0], NotNull());
+
+ // The entry being overlaid doesn't exist at the original entry index.
+ ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0001u), IsNull());
+
+ // Since this is an overlay, the actual entry ID must be mapped.
+ ASSERT_THAT(type_spec->idmap_entries, NotNull());
+ uint16_t target_entry_id = 0u;
+ ASSERT_TRUE(LoadedIdmap::Lookup(type_spec->idmap_entries, 0x0001u, &target_entry_id));
+ ASSERT_THAT(target_entry_id, Eq(0x0u));
+ ASSERT_THAT(LoadedPackage::GetEntry(type_spec->types[0], 0x0000), NotNull());
}
// structs with size fields (like Res_value, ResTable_entry) should be
diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h
index 43a9955..df0c642 100644
--- a/libs/androidfw/tests/TestHelpers.h
+++ b/libs/androidfw/tests/TestHelpers.h
@@ -20,6 +20,7 @@
#include <string>
#include "androidfw/ResourceTypes.h"
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "CommonHelpers.h"
diff --git a/libs/androidfw/tests/data/app/app.apk b/libs/androidfw/tests/data/app/app.apk
index ccb0824..c8ad86d 100644
--- a/libs/androidfw/tests/data/app/app.apk
+++ b/libs/androidfw/tests/data/app/app.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/app/assets/app_file.txt b/libs/androidfw/tests/data/app/assets/app_file.txt
new file mode 100644
index 0000000..b214e06
--- /dev/null
+++ b/libs/androidfw/tests/data/app/assets/app_file.txt
@@ -0,0 +1 @@
+app file
diff --git a/libs/androidfw/tests/data/app/assets/file.txt b/libs/androidfw/tests/data/app/assets/file.txt
new file mode 100644
index 0000000..0811542
--- /dev/null
+++ b/libs/androidfw/tests/data/app/assets/file.txt
@@ -0,0 +1 @@
+app override file
diff --git a/libs/androidfw/tests/data/app/build b/libs/androidfw/tests/data/app/build
index d418158..09af842 100755
--- a/libs/androidfw/tests/data/app/build
+++ b/libs/androidfw/tests/data/app/build
@@ -17,4 +17,11 @@
set -e
-aapt package -I ../system/system.apk -M AndroidManifest.xml -S res -F app.apk -f
+aapt2 compile --dir res -o compiled.flata
+aapt2 link \
+ --manifest AndroidManifest.xml \
+ -I ../system/system.apk \
+ -A assets \
+ -o app.apk \
+ compiled.flata
+rm compiled.flata
diff --git a/libs/androidfw/tests/data/basic/R.h b/libs/androidfw/tests/data/basic/R.h
index 94a2a14..b7e814f 100644
--- a/libs/androidfw/tests/data/basic/R.h
+++ b/libs/androidfw/tests/data/basic/R.h
@@ -34,6 +34,7 @@
struct layout {
enum : uint32_t {
main = 0x7f020000,
+ layoutt = 0x7f020001,
};
};
@@ -55,6 +56,7 @@
number2 = 0x7f040001,
ref1 = 0x7f040002,
ref2 = 0x7f040003,
+ deep_ref = 0x7f040004,
// From feature
number3 = 0x80030000,
diff --git a/libs/androidfw/tests/data/basic/basic.apk b/libs/androidfw/tests/data/basic/basic.apk
index 18ef75e..1733b6a 100644
--- a/libs/androidfw/tests/data/basic/basic.apk
+++ b/libs/androidfw/tests/data/basic/basic.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/res/layout/layout.xml b/libs/androidfw/tests/data/basic/res/layout/layout.xml
new file mode 100644
index 0000000..045ede4
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/res/layout/layout.xml
@@ -0,0 +1,25 @@
+<?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.
+-->
+<Button xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/ok"
+ android:layout_width="0sp"
+ android:layout_height="fill_parent"
+ android:layout_weight="1"
+ android:layout_marginStart="2dip"
+ android:layout_marginEnd="2dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textStyle="bold"
+ android:text="@android:string/ok" />
\ No newline at end of file
diff --git a/libs/androidfw/tests/data/basic/res/values/values.xml b/libs/androidfw/tests/data/basic/res/values/values.xml
index 6c47459..b343562 100644
--- a/libs/androidfw/tests/data/basic/res/values/values.xml
+++ b/libs/androidfw/tests/data/basic/res/values/values.xml
@@ -22,6 +22,7 @@
<attr name="attr2" format="reference|integer" />
<public type="layout" name="main" id="0x7f020000" />
+ <public type="layout" name="layout" id="0x7f020001" />
<public type="string" name="test1" id="0x7f030000" />
<string name="test1">test1</string>
@@ -43,6 +44,18 @@
<public type="integer" name="ref2" id="0x7f040003" />
<integer name="ref2">12000</integer>
+ <public type="integer" name="deep_ref" id="0x7f040004" />
+ <integer name="deep_ref">@integer/deep_ref_1</integer>
+ <integer name="deep_ref_1">@integer/deep_ref_2</integer>
+ <integer name="deep_ref_2">@integer/deep_ref_3</integer>
+ <integer name="deep_ref_3">@integer/deep_ref_4</integer>
+ <integer name="deep_ref_4">@integer/deep_ref_5</integer>
+ <integer name="deep_ref_5">@integer/deep_ref_6</integer>
+ <integer name="deep_ref_6">@integer/deep_ref_7</integer>
+ <integer name="deep_ref_7">@integer/deep_ref_8</integer>
+ <integer name="deep_ref_8">@integer/deep_ref_9</integer>
+ <integer name="deep_ref_9">100</integer>
+
<public type="style" name="Theme1" id="0x7f050000" />
<style name="Theme1">
<item name="com.android.basic:attr1">100</item>
diff --git a/libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml b/libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml
new file mode 100644
index 0000000..34016db
--- /dev/null
+++ b/libs/androidfw/tests/data/out_of_order_types/AndroidManifest.xml
@@ -0,0 +1,18 @@
+<?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" />
diff --git a/libs/androidfw/tests/data/out_of_order_types/build b/libs/androidfw/tests/data/out_of_order_types/build
new file mode 100755
index 0000000..8496f81
--- /dev/null
+++ b/libs/androidfw/tests/data/out_of_order_types/build
@@ -0,0 +1,22 @@
+#!/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
diff --git a/libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt b/libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt
new file mode 100644
index 0000000..eca8f47
--- /dev/null
+++ b/libs/androidfw/tests/data/out_of_order_types/edited_resources.arsc.txt
@@ -0,0 +1,43 @@
+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 ............
diff --git a/libs/androidfw/tests/data/out_of_order_types/out_of_order_types.apk b/libs/androidfw/tests/data/out_of_order_types/out_of_order_types.apk
new file mode 100644
index 0000000..75146e0
--- /dev/null
+++ b/libs/androidfw/tests/data/out_of_order_types/out_of_order_types.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/out_of_order_types/res/values/values.xml b/libs/androidfw/tests/data/out_of_order_types/res/values/values.xml
new file mode 100644
index 0000000..7c54fba
--- /dev/null
+++ b/libs/androidfw/tests/data/out_of_order_types/res/values/values.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<resources>
+ <bool name="test">true</bool>
+ <integer name="test">1</integer>
+</resources>
diff --git a/libs/androidfw/tests/data/system/assets/file.txt b/libs/androidfw/tests/data/system/assets/file.txt
new file mode 100644
index 0000000..f73f309
--- /dev/null
+++ b/libs/androidfw/tests/data/system/assets/file.txt
@@ -0,0 +1 @@
+file
diff --git a/libs/androidfw/tests/data/system/assets/subdir/subdir_file.txt b/libs/androidfw/tests/data/system/assets/subdir/subdir_file.txt
new file mode 100644
index 0000000..3f74eb6
--- /dev/null
+++ b/libs/androidfw/tests/data/system/assets/subdir/subdir_file.txt
@@ -0,0 +1 @@
+subdir file
diff --git a/libs/androidfw/tests/data/system/build b/libs/androidfw/tests/data/system/build
index bfbdf4c..b65145a 100755
--- a/libs/androidfw/tests/data/system/build
+++ b/libs/androidfw/tests/data/system/build
@@ -17,4 +17,6 @@
set -e
-aapt package -x -M AndroidManifest.xml -S res -F system.apk -f
+aapt2 compile --dir res -o compiled.flata
+aapt2 link --manifest AndroidManifest.xml -A assets -o system.apk compiled.flata
+rm compiled.flata
diff --git a/libs/androidfw/tests/data/system/res/values-sv/values.xml b/libs/androidfw/tests/data/system/res/values-sv/values.xml
index b97bdb6..5f60d21 100644
--- a/libs/androidfw/tests/data/system/res/values-sv/values.xml
+++ b/libs/androidfw/tests/data/system/res/values-sv/values.xml
@@ -15,6 +15,5 @@
-->
<resources>
- <public type="integer" name="number" id="0x01030000" />
<integer name="number">1</integer>
</resources>
diff --git a/libs/androidfw/tests/data/system/res/values/themes.xml b/libs/androidfw/tests/data/system/res/values/themes.xml
index 35d43c7..7893c94 100644
--- a/libs/androidfw/tests/data/system/res/values/themes.xml
+++ b/libs/androidfw/tests/data/system/res/values/themes.xml
@@ -18,6 +18,7 @@
<public name="background" type="attr" id="0x01010000"/>
<public name="foreground" type="attr" id="0x01010001"/>
<public name="Theme.One" type="style" id="0x01020000"/>
+ <public type="integer" name="number" id="0x01030000" />
<attr name="background" format="color|reference"/>
<attr name="foreground" format="color|reference"/>
diff --git a/libs/androidfw/tests/data/system/system.apk b/libs/androidfw/tests/data/system/system.apk
index 1299016..9045d6c 100644
--- a/libs/androidfw/tests/data/system/system.apk
+++ b/libs/androidfw/tests/data/system/system.apk
Binary files differ