Add fabricated RRO generation to libidmap2
Fabricated Runtime Resource Overlays are overlays that are generated
at runtime and are stored in the data/ partition.
The system can fabricate RROs at runtime to dynamically theme the
device. Idmaps can now be created from APK RROs and fabricated RROs.
Rather than operating on ApkAssets, libidmap2 now operates on abstract
resource "containers" that supply resource values. Target resource
containers implement methods needed to query overlayable and target
overlay information. Currently only APKs can be loaded as target
resource containers. Overlay resource containers implement methods to
supply the mapping of target resource to overlay value and other
overlay information.
The format of a fabricated RRO is as follows:
0x00 - 0x04 : fabricated overlay magic (always FRRO)
0x04 - 0x08 : file format version
0x08 - 0x0c : crc of version + proto data
0x0c - EOF : proto fabricated overlay data
The magic is used to quickly detect if the file is a fabricated overlay.
The version is incremented whenever backwards incompatible changes are
made to the proto file format. Idmap must always be able to upgrade
fabricated overlays from previous versions to new versions, so all
previous versions must be checked into the tree.
Bug: 172471315
Test: libidmap2_tests && libandroidfw_tests
Change-Id: I4c9f29da278672e5695fb57d131a44c11a835180
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index 524aabc..bf63327 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -33,7 +33,7 @@
namespace android::idmap2 {
TEST(BinaryStreamVisitorTests, CreateBinaryStreamViaBinaryStreamVisitor) {
- std::string raw(reinterpret_cast<const char*>(idmap_raw_data), kIdmapRawDataLen);
+ std::string raw(reinterpret_cast<const char*>(kIdmapRawData), kIdmapRawDataLen);
std::istringstream raw_stream(raw);
auto result1 = Idmap::FromBinaryStream(raw_stream);
diff --git a/cmds/idmap2/tests/FabricatedOverlayTests.cpp b/cmds/idmap2/tests/FabricatedOverlayTests.cpp
new file mode 100644
index 0000000..79ab243
--- /dev/null
+++ b/cmds/idmap2/tests/FabricatedOverlayTests.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2021 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 <android-base/file.h>
+#include <gtest/gtest.h>
+#include <idmap2/FabricatedOverlay.h>
+
+#include <fstream>
+
+namespace android::idmap2 {
+
+TEST(FabricatedOverlayTests, OverlayInfo) {
+ auto overlay =
+ FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "com.example.target")
+ .SetOverlayable("TestResources")
+ .Build();
+
+ ASSERT_TRUE(overlay);
+ auto container = FabricatedOverlayContainer::FromOverlay(std::move(*overlay));
+ auto info = container->FindOverlayInfo("SandTheme");
+ ASSERT_TRUE(info);
+ EXPECT_EQ("SandTheme", (*info).name);
+ EXPECT_EQ("TestResources", (*info).target_name);
+
+ info = container->FindOverlayInfo("OceanTheme");
+ ASSERT_FALSE(info);
+}
+
+TEST(FabricatedOverlayTests, SetResourceValue) {
+ auto overlay =
+ FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "com.example.target")
+ .SetResourceValue("com.example.target:integer/int1", Res_value::TYPE_INT_DEC, 1U)
+ .SetResourceValue("com.example.target.split:integer/int2", Res_value::TYPE_INT_DEC, 2U)
+ .SetResourceValue("string/int3", Res_value::TYPE_REFERENCE, 0x7f010000)
+ .Build();
+ ASSERT_TRUE(overlay);
+ auto container = FabricatedOverlayContainer::FromOverlay(std::move(*overlay));
+ auto info = container->FindOverlayInfo("SandTheme");
+ ASSERT_TRUE(info);
+ ASSERT_TRUE((*info).target_name.empty());
+
+ auto crc = (*container).GetCrc();
+ ASSERT_TRUE(crc) << crc.GetErrorMessage();
+ EXPECT_NE(0U, *crc);
+
+ auto pairs = container->GetOverlayData(*info);
+ ASSERT_TRUE(pairs);
+ EXPECT_FALSE(pairs->string_pool_data.has_value());
+ ASSERT_EQ(3U, pairs->pairs.size());
+
+ auto& it = pairs->pairs[0];
+ ASSERT_EQ("com.example.target:integer/int1", it.resource_name);
+ auto entry = std::get_if<TargetValue>(&it.value);
+ ASSERT_NE(nullptr, entry);
+ ASSERT_EQ(1U, entry->data_value);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, entry->data_type);
+
+ it = pairs->pairs[1];
+ ASSERT_EQ("com.example.target:string/int3", it.resource_name);
+ entry = std::get_if<TargetValue>(&it.value);
+ ASSERT_NE(nullptr, entry);
+ ASSERT_EQ(0x7f010000, entry->data_value);
+ ASSERT_EQ(Res_value::TYPE_REFERENCE, entry->data_type);
+
+ it = pairs->pairs[2];
+ ASSERT_EQ("com.example.target.split:integer/int2", it.resource_name);
+ entry = std::get_if<TargetValue>(&it.value);
+ ASSERT_NE(nullptr, entry);
+ ASSERT_EQ(2U, entry->data_value);
+ ASSERT_EQ(Res_value::TYPE_INT_DEC, entry->data_type);
+}
+
+TEST(FabricatedOverlayTests, SetResourceValueBadArgs) {
+ {
+ auto builder =
+ FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "com.example.target")
+ .SetResourceValue("int1", Res_value::TYPE_INT_DEC, 1U);
+ ASSERT_FALSE(builder.Build());
+ }
+ {
+ auto builder =
+ FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "com.example.target")
+ .SetResourceValue("com.example.target:int2", Res_value::TYPE_INT_DEC, 1U);
+ ASSERT_FALSE(builder.Build());
+ }
+}
+
+TEST(FabricatedOverlayTests, SerializeAndDeserialize) {
+ auto overlay =
+ FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "com.example.target")
+ .SetOverlayable("TestResources")
+ .SetResourceValue("com.example.target:integer/int1", Res_value::TYPE_INT_DEC, 1U)
+ .Build();
+ ASSERT_TRUE(overlay);
+ TemporaryFile tf;
+ std::ofstream out(tf.path);
+ ASSERT_TRUE((*overlay).ToBinaryStream(out));
+ out.close();
+
+ auto container = OverlayResourceContainer::FromPath(tf.path);
+ ASSERT_TRUE(container) << container.GetErrorMessage();
+ EXPECT_EQ(tf.path, (*container)->GetPath());
+
+ auto crc = (*container)->GetCrc();
+ ASSERT_TRUE(crc) << crc.GetErrorMessage();
+ EXPECT_NE(0U, *crc);
+
+ auto info = (*container)->FindOverlayInfo("SandTheme");
+ ASSERT_TRUE(info) << info.GetErrorMessage();
+ EXPECT_EQ("SandTheme", (*info).name);
+ EXPECT_EQ("TestResources", (*info).target_name);
+
+ auto pairs = (*container)->GetOverlayData(*info);
+ ASSERT_TRUE(pairs) << pairs.GetErrorMessage();
+ EXPECT_EQ(1U, pairs->pairs.size());
+
+ auto& it = pairs->pairs[0];
+ ASSERT_EQ("com.example.target:integer/int1", it.resource_name);
+ auto entry = std::get_if<TargetValue>(&it.value);
+ ASSERT_NE(nullptr, entry);
+ EXPECT_EQ(1U, entry->data_value);
+ EXPECT_EQ(Res_value::TYPE_INT_DEC, entry->data_type);
+}
+
+} // namespace android::idmap2
\ No newline at end of file
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 16b68f0..9516ff8 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include <android-base/file.h>
+
#include <cstdio> // fclose
#include <fstream>
#include <memory>
@@ -61,12 +63,12 @@
}
TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) {
- std::string raw(reinterpret_cast<const char*>(idmap_raw_data), kIdmapRawDataLen);
+ std::string raw(reinterpret_cast<const char*>(kIdmapRawData), kIdmapRawDataLen);
std::istringstream stream(raw);
std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
ASSERT_THAT(header, NotNull());
ASSERT_EQ(header->GetMagic(), 0x504d4449U);
- ASSERT_EQ(header->GetVersion(), 0x07U);
+ ASSERT_EQ(header->GetVersion(), 0x08U);
ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
ASSERT_EQ(header->GetFulfilledPolicies(), 0x11);
@@ -81,7 +83,7 @@
std::stringstream stream;
stream << android::kIdmapMagic;
stream << 0xffffffffU;
- stream << std::string(kJunkSize, (char) 0xffU);
+ stream << std::string(kJunkSize, (char)0xffU);
ASSERT_FALSE(Idmap::FromBinaryStream(stream));
}
@@ -90,14 +92,13 @@
std::stringstream stream;
stream << 0xffffffffU;
stream << android::kIdmapCurrentVersion;
- stream << std::string(kJunkSize, (char) 0xffU);
+ stream << std::string(kJunkSize, (char)0xffU);
ASSERT_FALSE(Idmap::FromBinaryStream(stream));
}
TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
const size_t offset = kIdmapRawDataOffset;
- std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
- kIdmapRawDataLen - offset);
+ std::string raw(reinterpret_cast<const char*>(kIdmapRawData + offset), kIdmapRawDataLen - offset);
std::istringstream stream(raw);
std::unique_ptr<const IdmapData::Header> header = IdmapData::Header::FromBinaryStream(stream);
@@ -108,8 +109,7 @@
TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
const size_t offset = kIdmapRawDataOffset;
- std::string raw(reinterpret_cast<const char*>(idmap_raw_data + offset),
- kIdmapRawDataLen - offset);
+ std::string raw(reinterpret_cast<const char*>(kIdmapRawData + offset), kIdmapRawDataLen - offset);
std::istringstream stream(raw);
std::unique_ptr<const IdmapData> data = IdmapData::FromBinaryStream(stream);
@@ -134,7 +134,7 @@
}
TEST(IdmapTests, CreateIdmapFromBinaryStream) {
- std::string raw(reinterpret_cast<const char*>(idmap_raw_data), kIdmapRawDataLen);
+ std::string raw(reinterpret_cast<const char*>(kIdmapRawData), kIdmapRawDataLen);
std::istringstream stream(raw);
auto result = Idmap::FromBinaryStream(stream);
@@ -143,7 +143,7 @@
ASSERT_THAT(idmap->GetHeader(), NotNull());
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
- ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x07U);
+ ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x08U);
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), kIdmapRawDataPolicies);
@@ -177,7 +177,7 @@
}
TEST(IdmapTests, GracefullyFailToCreateIdmapFromCorruptBinaryStream) {
- std::string raw(reinterpret_cast<const char*>(idmap_raw_data),
+ std::string raw(reinterpret_cast<const char*>(kIdmapRawData),
10); // data too small
std::istringstream stream(raw);
@@ -189,14 +189,14 @@
std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- ASSERT_THAT(target_apk, NotNull());
+ auto target = TargetResourceContainer::FromPath(target_apk_path);
+ ASSERT_TRUE(target);
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- ASSERT_THAT(overlay_apk, NotNull());
+ auto overlay = OverlayResourceContainer::FromPath(overlay_apk_path);
+ ASSERT_TRUE(overlay);
- auto idmap_result = Idmap::FromApkAssets(
- *target_apk, *overlay_apk, TestConstants::OVERLAY_NAME_ALL_POLICIES, PolicyFlags::PUBLIC,
+ auto idmap_result = Idmap::FromContainers(
+ **target, **overlay, TestConstants::OVERLAY_NAME_ALL_POLICIES, PolicyFlags::PUBLIC,
/* enforce_overlayable */ true);
ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
auto& idmap = *idmap_result;
@@ -204,7 +204,7 @@
ASSERT_THAT(idmap->GetHeader(), NotNull());
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
- ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x07U);
+ ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x08U);
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), android::idmap2::TestConstants::TARGET_CRC);
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), android::idmap2::TestConstants::OVERLAY_CRC);
ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), PolicyFlags::PUBLIC);
@@ -218,15 +218,15 @@
std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- ASSERT_THAT(target_apk, NotNull());
+ auto target = TargetResourceContainer::FromPath(target_apk_path);
+ ASSERT_TRUE(target);
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- ASSERT_THAT(overlay_apk, NotNull());
+ auto overlay = OverlayResourceContainer::FromPath(overlay_apk_path);
+ ASSERT_TRUE(overlay);
- auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk,
- TestConstants::OVERLAY_NAME_DEFAULT, PolicyFlags::PUBLIC,
- /* enforce_overlayable */ true);
+ auto idmap_result = Idmap::FromContainers(
+ **target, **overlay, TestConstants::OVERLAY_NAME_DEFAULT, PolicyFlags::PUBLIC,
+ /* enforce_overlayable */ true);
ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
auto& idmap = *idmap_result;
ASSERT_THAT(idmap, NotNull());
@@ -255,25 +255,66 @@
ASSERT_OVERLAY_ENTRY(overlay_entries[3], R::overlay::string::str4, R::target::string::str4);
}
+TEST(IdmapTests, FabricatedOverlay) {
+ std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
+ auto target = TargetResourceContainer::FromPath(target_apk_path);
+ ASSERT_TRUE(target);
+
+ auto frro = FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "test.target")
+ .SetOverlayable("TestResources")
+ .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U)
+ .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000)
+ .Build();
+
+ ASSERT_TRUE(frro);
+ TemporaryFile tf;
+ std::ofstream out(tf.path);
+ ASSERT_TRUE((*frro).ToBinaryStream(out));
+ out.close();
+
+ auto overlay = OverlayResourceContainer::FromPath(tf.path);
+ ASSERT_TRUE(overlay);
+
+ auto idmap_result = Idmap::FromContainers(**target, **overlay, "SandTheme", PolicyFlags::PUBLIC,
+ /* enforce_overlayable */ true);
+ ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
+ auto& idmap = *idmap_result;
+ ASSERT_THAT(idmap, NotNull());
+
+ const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
+ ASSERT_EQ(dataBlocks.size(), 1U);
+
+ const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
+ ASSERT_THAT(data, NotNull());
+ ASSERT_EQ(data->GetTargetEntries().size(), 0U);
+ ASSERT_EQ(data->GetOverlayEntries().size(), 0U);
+
+ const auto& target_inline_entries = data->GetTargetInlineEntries();
+ ASSERT_EQ(target_inline_entries.size(), 2U);
+ ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1,
+ Res_value::TYPE_INT_DEC, 2U);
+ ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1,
+ Res_value::TYPE_REFERENCE, 0x7f010000);
+}
+
TEST(IdmapTests, FailCreateIdmapInvalidName) {
std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay.apk";
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- ASSERT_THAT(target_apk, NotNull());
+ auto target = TargetResourceContainer::FromPath(target_apk_path);
+ ASSERT_TRUE(target);
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- ASSERT_THAT(overlay_apk, NotNull());
+ auto overlay = OverlayResourceContainer::FromPath(overlay_apk_path);
+ ASSERT_TRUE(overlay);
{
- auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, "", PolicyFlags::PUBLIC,
- /* enforce_overlayable */ true);
+ auto idmap_result = Idmap::FromContainers(**target, **overlay, "", PolicyFlags::PUBLIC,
+ /* enforce_overlayable */ true);
ASSERT_FALSE(idmap_result);
}
{
- auto idmap_result =
- Idmap::FromApkAssets(*target_apk, *overlay_apk, "unknown", PolicyFlags::PUBLIC,
- /* enforce_overlayable */ true);
+ auto idmap_result = Idmap::FromContainers(**target, **overlay, "unknown", PolicyFlags::PUBLIC,
+ /* enforce_overlayable */ true);
ASSERT_FALSE(idmap_result);
}
}
@@ -282,15 +323,15 @@
std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-shared.apk";
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- ASSERT_THAT(target_apk, NotNull());
+ auto target = TargetResourceContainer::FromPath(target_apk_path);
+ ASSERT_TRUE(target);
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- ASSERT_THAT(overlay_apk, NotNull());
+ auto overlay = OverlayResourceContainer::FromPath(overlay_apk_path);
+ ASSERT_TRUE(overlay);
- auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk,
- TestConstants::OVERLAY_NAME_DEFAULT, PolicyFlags::PUBLIC,
- /* enforce_overlayable */ true);
+ auto idmap_result = Idmap::FromContainers(
+ **target, **overlay, TestConstants::OVERLAY_NAME_DEFAULT, PolicyFlags::PUBLIC,
+ /* enforce_overlayable */ true);
ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
auto& idmap = *idmap_result;
ASSERT_THAT(idmap, NotNull());
@@ -328,30 +369,29 @@
}
Result<std::unique_ptr<const IdmapData>> TestIdmapDataFromApkAssets(
- const std::string& local_target_apk_path, const std::string& local_overlay_apk_path,
+ const std::string& local_target_path, const std::string& local_overlay_path,
const std::string& overlay_name, const PolicyBitmask& fulfilled_policies,
bool enforce_overlayable) {
- auto overlay_info =
- utils::ExtractOverlayManifestInfo(GetTestDataPath() + local_overlay_apk_path, overlay_name);
+ const std::string target_path(GetTestDataPath() + local_target_path);
+ auto target = TargetResourceContainer::FromPath(target_path);
+ if (!target) {
+ return Error(R"(Failed to load target "%s")", target_path.c_str());
+ }
+
+ const std::string overlay_path(GetTestDataPath() + local_overlay_path);
+ auto overlay = OverlayResourceContainer::FromPath(overlay_path);
+ if (!overlay) {
+ return Error(R"(Failed to load overlay "%s")", overlay_path.c_str());
+ }
+
+ auto overlay_info = (*overlay)->FindOverlayInfo(overlay_name);
if (!overlay_info) {
- return overlay_info.GetError();
- }
-
- const std::string target_apk_path(GetTestDataPath() + local_target_apk_path);
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- if (!target_apk) {
- return Error(R"(Failed to load target apk "%s")", target_apk_path.data());
- }
-
- const std::string overlay_apk_path(GetTestDataPath() + local_overlay_apk_path);
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- if (!overlay_apk) {
- return Error(R"(Failed to load overlay apk "%s")", overlay_apk_path.data());
+ return Error(R"(Failed to find overlay name "%s")", overlay_name.c_str());
}
LogInfo log_info;
- auto mapping = ResourceMapping::FromApkAssets(*target_apk, *overlay_apk, *overlay_info,
- fulfilled_policies, enforce_overlayable, log_info);
+ auto mapping = ResourceMapping::FromContainers(**target, **overlay, *overlay_info,
+ fulfilled_policies, enforce_overlayable, log_info);
if (!mapping) {
return mapping.GetError();
}
@@ -360,11 +400,9 @@
}
TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) {
- auto idmap_data =
- TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk", "DifferentPackages",
-
- PolicyFlags::PUBLIC,
- /* enforce_overlayable */ false);
+ auto idmap_data = TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk",
+ "DifferentPackages", PolicyFlags::PUBLIC,
+ /* enforce_overlayable */ false);
ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage();
auto& data = *idmap_data;
@@ -417,7 +455,7 @@
const uint32_t target_crc = kIdmapRawDataTargetCrc;
const uint32_t overlay_crc = kIdmapRawOverlayCrc;
- std::string raw(reinterpret_cast<const char*>(idmap_raw_data), kIdmapRawDataLen);
+ std::string raw(reinterpret_cast<const char*>(kIdmapRawData), kIdmapRawDataLen);
std::istringstream raw_stream(raw);
auto result = Idmap::FromBinaryStream(raw_stream);
@@ -468,8 +506,8 @@
ASSERT_THAT(bad_target_crc_header, NotNull());
ASSERT_NE(header->GetTargetCrc(), bad_target_crc_header->GetTargetCrc());
ASSERT_FALSE(bad_target_crc_header->IsUpToDate(target_apk_path, overlay_apk_path, overlay_name,
- target_crc, overlay_crc, policies,
- /* enforce_overlayable */ true));
+ target_crc, overlay_crc, policies,
+ /* enforce_overlayable */ true));
// overlay crc: bytes (0xc, 0xf)
std::string bad_overlay_crc_string(stream.str());
@@ -483,8 +521,8 @@
ASSERT_THAT(bad_overlay_crc_header, NotNull());
ASSERT_NE(header->GetOverlayCrc(), bad_overlay_crc_header->GetOverlayCrc());
ASSERT_FALSE(bad_overlay_crc_header->IsUpToDate(target_apk_path, overlay_apk_path, overlay_name,
- target_crc, overlay_crc, policies,
- /* enforce_overlayable */ true));
+ target_crc, overlay_crc, policies,
+ /* enforce_overlayable */ true));
// fulfilled policy: bytes (0x10, 0x13)
std::string bad_policy_string(stream.str());
@@ -522,8 +560,8 @@
ASSERT_THAT(bad_target_path_header, NotNull());
ASSERT_NE(header->GetTargetPath(), bad_target_path_header->GetTargetPath());
ASSERT_FALSE(bad_target_path_header->IsUpToDate(target_apk_path, overlay_apk_path, overlay_name,
- target_crc, overlay_crc, policies,
- /* enforce_overlayable */ true));
+ target_crc, overlay_crc, policies,
+ /* enforce_overlayable */ true));
// overlay path: bytes (0x2c, 0x37)
std::string bad_overlay_path_string(stream.str());
@@ -576,7 +614,7 @@
};
TEST(IdmapTests, TestVisitor) {
- std::string raw(reinterpret_cast<const char*>(idmap_raw_data), kIdmapRawDataLen);
+ std::string raw(reinterpret_cast<const char*>(kIdmapRawData), kIdmapRawDataLen);
std::istringstream stream(raw);
const auto idmap = Idmap::FromBinaryStream(stream);
diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
index 87ce0f1..3d3d82a 100644
--- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
@@ -27,35 +27,31 @@
#include "idmap2/Idmap.h"
#include "idmap2/PrettyPrintVisitor.h"
-using android::ApkAssets;
using android::base::StringPrintf;
-using ::testing::NotNull;
-using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace android::idmap2 {
TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitor) {
const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- ASSERT_THAT(target_apk, NotNull());
+ auto target = TargetResourceContainer::FromPath(target_apk_path);
+ ASSERT_TRUE(target);
const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- ASSERT_THAT(overlay_apk, NotNull());
+ auto overlay = OverlayResourceContainer::FromPath(overlay_apk_path);
+ ASSERT_TRUE(overlay);
- const auto idmap = Idmap::FromApkAssets(*target_apk, *overlay_apk,
- TestConstants::OVERLAY_NAME_DEFAULT, PolicyFlags::PUBLIC,
- /* enforce_overlayable */ true);
+ const auto idmap = Idmap::FromContainers(**target, **overlay, TestConstants::OVERLAY_NAME_DEFAULT,
+ PolicyFlags::PUBLIC, /* enforce_overlayable */ true);
ASSERT_TRUE(idmap);
std::stringstream stream;
PrettyPrintVisitor visitor(stream);
(*idmap)->accept(&visitor);
- ASSERT_NE(stream.str().find("target apk path : "), std::string::npos);
- ASSERT_NE(stream.str().find("overlay apk path : "), std::string::npos);
+ ASSERT_NE(stream.str().find("target path : "), std::string::npos);
+ ASSERT_NE(stream.str().find("overlay path : "), std::string::npos);
ASSERT_NE(stream.str().find(StringPrintf("0x%08x -> 0x%08x (integer/int1 -> integer/int1)\n",
R::target::integer::int1, R::overlay::integer::int1)),
std::string::npos);
@@ -64,7 +60,7 @@
TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitorWithoutAccessToApks) {
fclose(stderr); // silence expected warnings from libandroidfw
- std::string raw(reinterpret_cast<const char*>(idmap_raw_data), kIdmapRawDataLen);
+ std::string raw(reinterpret_cast<const char*>(kIdmapRawData), kIdmapRawDataLen);
std::istringstream raw_stream(raw);
const auto idmap = Idmap::FromBinaryStream(raw_stream);
@@ -74,8 +70,8 @@
PrettyPrintVisitor visitor(stream);
(*idmap)->accept(&visitor);
- ASSERT_NE(stream.str().find("target apk path : "), std::string::npos);
- ASSERT_NE(stream.str().find("overlay apk path : "), std::string::npos);
+ ASSERT_NE(stream.str().find("target path : "), std::string::npos);
+ ASSERT_NE(stream.str().find("overlay path : "), std::string::npos);
ASSERT_NE(stream.str().find("0x7f020000 -> 0x7f020000 (\?\?\? -> \?\?\?)\n"), std::string::npos);
}
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index 88f85ef..a6371cb 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -30,17 +30,16 @@
#include "idmap2/RawPrintVisitor.h"
using android::base::StringPrintf;
-using ::testing::NotNull;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace android::idmap2 {
-#define ASSERT_CONTAINS_REGEX(pattern, str) \
- do { \
- ASSERT_TRUE(std::regex_search(str, std::regex(pattern))) \
- << "pattern '" << pattern << "' not found in\n--------\n" \
- << str << "--------"; \
+#define ASSERT_CONTAINS_REGEX(pattern, str) \
+ do { \
+ ASSERT_TRUE(std::regex_search(str, std::regex(pattern))) \
+ << "pattern '" << (pattern) << "' not found in\n--------\n" \
+ << (str) << "--------"; \
} while (0)
#define ADDRESS "[0-9a-f]{8}: "
@@ -49,16 +48,15 @@
fclose(stderr); // silence expected warnings
const std::string target_apk_path(GetTestDataPath() + "/target/target.apk");
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- ASSERT_THAT(target_apk, NotNull());
+ auto target = TargetResourceContainer::FromPath(target_apk_path);
+ ASSERT_TRUE(target);
const std::string overlay_apk_path(GetTestDataPath() + "/overlay/overlay.apk");
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- ASSERT_THAT(overlay_apk, NotNull());
+ auto overlay = OverlayResourceContainer::FromPath(overlay_apk_path);
+ ASSERT_TRUE(overlay);
- const auto idmap =
- Idmap::FromApkAssets(*target_apk, *overlay_apk, TestConstants::OVERLAY_NAME_DEFAULT,
- PolicyFlags::PUBLIC, /* enforce_overlayable */ true);
+ const auto idmap = Idmap::FromContainers(**target, **overlay, TestConstants::OVERLAY_NAME_DEFAULT,
+ PolicyFlags::PUBLIC, /* enforce_overlayable */ true);
ASSERT_TRUE(idmap);
std::stringstream stream;
@@ -66,7 +64,7 @@
(*idmap)->accept(&visitor);
ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS "00000007 version\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000008 version\n", stream.str());
ASSERT_CONTAINS_REGEX(
StringPrintf(ADDRESS "%s target crc\n", android::idmap2::TestConstants::TARGET_CRC_STRING),
stream.str());
@@ -75,8 +73,6 @@
stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000001 fulfilled policies: public\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000001 enforce overlayable\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS " 7f target package id\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS " 7f overlay package id\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 target entry count", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000000 target inline entry count", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 overlay entry count", stream.str());
@@ -104,7 +100,7 @@
TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
fclose(stderr); // silence expected warnings from libandroidfw
- std::string raw(reinterpret_cast<const char*>(idmap_raw_data), kIdmapRawDataLen);
+ std::string raw(reinterpret_cast<const char*>(kIdmapRawData), kIdmapRawDataLen);
std::istringstream raw_stream(raw);
const auto idmap = Idmap::FromBinaryStream(raw_stream);
@@ -115,7 +111,7 @@
(*idmap)->accept(&visitor);
ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS "00000007 version\n", stream.str());
+ ASSERT_CONTAINS_REGEX(ADDRESS "00000008 version\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00001234 target crc\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00005678 overlay crc\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000011 fulfilled policies: public|signature\n", stream.str());
@@ -126,8 +122,6 @@
ASSERT_CONTAINS_REGEX(ADDRESS "........ overlay path: overlayX.apk\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "0000000b overlay name size\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "........ overlay name: OverlayName\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS " 7f target package id\n", stream.str());
- ASSERT_CONTAINS_REGEX(ADDRESS " 7f overlay package id\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000003 target entry count\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000001 target inline entry count\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000003 overlay entry count\n", stream.str());
@@ -140,7 +134,7 @@
ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 overlay id\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "7f030002 target id\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 string pool size\n", stream.str());
- ASSERT_CONTAINS_REGEX("000000a8: ........ string pool\n", stream.str());
+ ASSERT_CONTAINS_REGEX("000000a4: ........ string pool\n", stream.str());
}
} // namespace android::idmap2
diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp
index 0362529..5a1d808 100644
--- a/cmds/idmap2/tests/ResourceMappingTests.cpp
+++ b/cmds/idmap2/tests/ResourceMappingTests.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+#include <android-base/file.h>
+#include <androidfw/ResourceTypes.h>
+#include <gtest/gtest.h>
+
#include <cstdio> // fclose
#include <fstream>
#include <memory>
@@ -22,14 +26,10 @@
#include "R.h"
#include "TestConstants.h"
#include "TestHelpers.h"
-#include "androidfw/ResourceTypes.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
#include "idmap2/LogInfo.h"
#include "idmap2/ResourceMapping.h"
using android::Res_value;
-using android::idmap2::utils::ExtractOverlayManifestInfo;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
@@ -41,32 +41,36 @@
ASSERT_TRUE(result) << result.GetErrorMessage(); \
} while (0)
-Result<ResourceMapping> TestGetResourceMapping(const std::string& local_target_apk_path,
- const std::string& local_overlay_apk_path,
+Result<ResourceMapping> TestGetResourceMapping(const std::string& local_target_path,
+ const std::string& local_overlay_path,
const std::string& overlay_name,
const PolicyBitmask& fulfilled_policies,
bool enforce_overlayable) {
- auto overlay_info =
- ExtractOverlayManifestInfo(GetTestDataPath() + local_overlay_apk_path, overlay_name);
+ const std::string target_path = (local_target_path[0] == '/')
+ ? local_target_path
+ : (GetTestDataPath() + "/" + local_target_path);
+ auto target = TargetResourceContainer::FromPath(target_path);
+ if (!target) {
+ return Error(target.GetError(), R"(Failed to load target "%s")", target_path.c_str());
+ }
+
+ const std::string overlay_path = (local_overlay_path[0] == '/')
+ ? local_overlay_path
+ : (GetTestDataPath() + "/" + local_overlay_path);
+ auto overlay = OverlayResourceContainer::FromPath(overlay_path);
+ if (!overlay) {
+ return Error(overlay.GetError(), R"(Failed to load overlay "%s")", overlay_path.c_str());
+ }
+
+ auto overlay_info = (*overlay)->FindOverlayInfo(overlay_name);
if (!overlay_info) {
- return overlay_info.GetError();
- }
-
- const std::string target_apk_path(GetTestDataPath() + local_target_apk_path);
- std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
- if (!target_apk) {
- return Error(R"(Failed to load target apk "%s")", target_apk_path.data());
- }
-
- const std::string overlay_apk_path(GetTestDataPath() + local_overlay_apk_path);
- std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
- if (!overlay_apk) {
- return Error(R"(Failed to load overlay apk "%s")", overlay_apk_path.data());
+ return Error(overlay_info.GetError(), R"(Failed to find overlay name "%s")",
+ overlay_name.c_str());
}
LogInfo log_info;
- return ResourceMapping::FromApkAssets(*target_apk, *overlay_apk, *overlay_info,
- fulfilled_policies, enforce_overlayable, log_info);
+ return ResourceMapping::FromContainers(**target, **overlay, *overlay_info, fulfilled_policies,
+ enforce_overlayable, log_info);
}
Result<Unit> MappingExists(const ResourceMapping& mapping, ResourceId target_resource,
@@ -128,7 +132,7 @@
}
TEST(ResourceMappingTests, ResourcesFromApkAssetsLegacy) {
- auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay-legacy.apk", "",
+ auto resources = TestGetResourceMapping("target/target.apk", "overlay/overlay-legacy.apk", "",
PolicyFlags::PUBLIC, /* enforce_overlayable */ false);
ASSERT_TRUE(resources) << resources.GetErrorMessage();
@@ -145,7 +149,7 @@
}
TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) {
- auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", "SwapNames",
+ auto resources = TestGetResourceMapping("target/target.apk", "overlay/overlay.apk", "SwapNames",
PolicyFlags::PUBLIC,
/* enforce_overlayable */ false);
@@ -161,7 +165,7 @@
}
TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) {
- auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk",
+ auto resources = TestGetResourceMapping("target/target.apk", "overlay/overlay.apk",
"DifferentPackages", PolicyFlags::PUBLIC,
/* enforce_overlayable */ false);
@@ -176,7 +180,7 @@
}
TEST(ResourceMappingTests, InlineResources) {
- auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", "Inline",
+ auto resources = TestGetResourceMapping("target/target.apk", "overlay/overlay.apk", "Inline",
PolicyFlags::PUBLIC, /* enforce_overlayable */ false);
constexpr size_t overlay_string_pool_size = 10U;
@@ -189,8 +193,32 @@
ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_INT_DEC, 73U));
}
+TEST(ResourceMappingTests, FabricatedOverlay) {
+ auto frro = FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "test.target")
+ .SetOverlayable("TestResources")
+ .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U)
+ .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000)
+ .Build();
+
+ ASSERT_TRUE(frro);
+ TemporaryFile tf;
+ std::ofstream out(tf.path);
+ ASSERT_TRUE((*frro).ToBinaryStream(out));
+ out.close();
+
+ auto resources = TestGetResourceMapping("target/target.apk", tf.path, "SandTheme",
+ PolicyFlags::PUBLIC, /* enforce_overlayable */ false);
+
+ ASSERT_TRUE(resources) << resources.GetErrorMessage();
+ auto& res = *resources;
+ ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
+ ASSERT_EQ(res.GetOverlayToTargetMap().size(), 0U);
+ ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE, 0x7f010000));
+ ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_INT_DEC, 2U));
+}
+
TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
- auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk",
+ auto resources = TestGetResourceMapping("target/target.apk", "overlay/overlay.apk",
TestConstants::OVERLAY_NAME_ALL_POLICIES,
PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC,
/* enforce_overlayable */ true);
@@ -209,7 +237,7 @@
// Resources that are not declared as overlayable and resources that a protected by policies the
// overlay does not fulfill must not map to overlay resources.
TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
- auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk",
+ auto resources = TestGetResourceMapping("target/target.apk", "overlay/overlay.apk",
TestConstants::OVERLAY_NAME_ALL_POLICIES,
PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC,
/* enforce_overlayable */ true);
@@ -229,7 +257,7 @@
// overlay does not fulfilled can map to overlay resources when overlayable enforcement is turned
// off.
TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
- auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk",
+ auto resources = TestGetResourceMapping("target/target.apk", "overlay/overlay.apk",
TestConstants::OVERLAY_NAME_ALL_POLICIES,
PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC,
/* enforce_overlayable */ false);
@@ -264,7 +292,7 @@
// Overlays that do not target an <overlayable> tag can overlay any resource if overlayable
// enforcement is disabled.
TEST(ResourceMappingTests, ResourcesFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
- auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay-legacy.apk", "",
+ auto resources = TestGetResourceMapping("target/target.apk", "overlay/overlay-legacy.apk", "",
PolicyFlags::PUBLIC,
/* enforce_overlayable */ false);
@@ -284,10 +312,9 @@
// Overlays that are neither pre-installed nor signed with the same signature as the target cannot
// overlay packages that have not defined overlayable resources.
TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) {
- auto resources =
- TestGetResourceMapping("/target/target-no-overlayable.apk", "/overlay/overlay.apk",
- "NoTargetName", PolicyFlags::PUBLIC,
- /* enforce_overlayable */ true);
+ auto resources = TestGetResourceMapping("target/target-no-overlayable.apk", "overlay/overlay.apk",
+ "NoTargetName", PolicyFlags::PUBLIC,
+ /* enforce_overlayable */ true);
ASSERT_TRUE(resources) << resources.GetErrorMessage();
ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U);
@@ -297,9 +324,9 @@
// signed with the same signature as the reference package can overlay packages that have not
// defined overlayable resources.
TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
- auto CheckEntries = [&](const PolicyBitmask& fulfilled_policies) -> void {
+ auto CheckEntries = [&](const PolicyBitmask& fulfilled_policies) {
auto resources =
- TestGetResourceMapping("/target/target-no-overlayable.apk", "/overlay/overlay.apk",
+ TestGetResourceMapping("target/target-no-overlayable.apk", "overlay/overlay.apk",
TestConstants::OVERLAY_NAME_ALL_POLICIES, fulfilled_policies,
/* enforce_overlayable */ true);
diff --git a/cmds/idmap2/tests/ResourceUtilsTests.cpp b/cmds/idmap2/tests/ResourceUtilsTests.cpp
index 1f6bf49..6914208 100644
--- a/cmds/idmap2/tests/ResourceUtilsTests.cpp
+++ b/cmds/idmap2/tests/ResourceUtilsTests.cpp
@@ -17,10 +17,12 @@
#include <memory>
#include <string>
+#include "R.h"
#include "TestHelpers.h"
#include "androidfw/ApkAssets.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "idmap2/ResourceContainer.h"
#include "idmap2/ResourceUtils.h"
#include "idmap2/Result.h"
@@ -49,8 +51,8 @@
};
TEST_F(ResourceUtilsTests, ResToTypeEntryName) {
- Result<std::string> name = utils::ResToTypeEntryName(GetAssetManager(), 0x7f010000U);
- ASSERT_TRUE(name);
+ Result<std::string> name = utils::ResToTypeEntryName(GetAssetManager(), R::target::integer::int1);
+ ASSERT_TRUE(name) << name.GetErrorMessage();
ASSERT_EQ(*name, "integer/int1");
}
@@ -60,25 +62,34 @@
}
TEST_F(ResourceUtilsTests, InvalidValidOverlayNameInvalidAttributes) {
- auto info = utils::ExtractOverlayManifestInfo(GetTestDataPath() + "/overlay/overlay-invalid.apk",
- "InvalidName");
+ auto overlay =
+ OverlayResourceContainer::FromPath(GetTestDataPath() + "/overlay/overlay-invalid.apk");
+ ASSERT_TRUE(overlay);
+
+ auto info = (*overlay)->FindOverlayInfo("InvalidName");
ASSERT_FALSE(info);
}
TEST_F(ResourceUtilsTests, ValidOverlayNameInvalidAttributes) {
- auto info = utils::ExtractOverlayManifestInfo(GetTestDataPath() + "/overlay/overlay-invalid.apk",
- "ValidName");
+ auto overlay =
+ OverlayResourceContainer::FromPath(GetTestDataPath() + "/overlay/overlay-invalid.apk");
+ ASSERT_TRUE(overlay);
+
+ auto info = (*overlay)->FindOverlayInfo("ValidName");
ASSERT_FALSE(info);
}
TEST_F(ResourceUtilsTests, ValidOverlayNameAndTargetPackageInvalidAttributes) {
- auto info = utils::ExtractOverlayManifestInfo(GetTestDataPath() + "/overlay/overlay-invalid.apk",
- "ValidNameAndTargetPackage");
+ auto overlay =
+ OverlayResourceContainer::FromPath(GetTestDataPath() + "/overlay/overlay-invalid.apk");
+ ASSERT_TRUE(overlay);
+
+ auto info = (*overlay)->FindOverlayInfo("ValidNameAndTargetPackage");
ASSERT_TRUE(info);
ASSERT_EQ("ValidNameAndTargetPackage", info->name);
ASSERT_EQ("Valid", info->target_package);
- ASSERT_EQ("", info->target_name); // Attribute resource id could not be found
- ASSERT_EQ(0, info->resource_mapping); // Attribute resource id could not be found
+ ASSERT_EQ("", info->target_name); // Attribute resource id could not be found
+ ASSERT_EQ(0, info->resource_mapping); // Attribute resource id could not be found
}
-}// namespace android::idmap2
+} // namespace android::idmap2
diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h
index 842af3d..6b5f3a8 100644
--- a/cmds/idmap2/tests/TestHelpers.h
+++ b/cmds/idmap2/tests/TestHelpers.h
@@ -24,13 +24,13 @@
namespace android::idmap2 {
-const unsigned char idmap_raw_data[] = {
+const unsigned char kIdmapRawData[] = {
// IDMAP HEADER
// 0x0: magic
0x49, 0x44, 0x4d, 0x50,
// 0x4: version
- 0x07, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x00, 0x00,
// 0x8: target crc
0x34, 0x12, 0x00, 0x00,
@@ -70,81 +70,72 @@
0x64, 0x65, 0x62, 0x75, 0x67, 0x00, 0x00, 0x00,
// DATA HEADER
- // 0x54: target_package_id
- 0x7f,
-
- // 0x55: overlay_package_id
- 0x7f,
-
- // 0x56: padding
- 0x00, 0x00,
-
- // 0x58: target_entry_count
+ // 0x54: target_entry_count
0x03, 0x00, 0x00, 0x00,
- // 0x5c: target_inline_entry_count
+ // 0x58: target_inline_entry_count
0x01, 0x00, 0x00, 0x00,
- // 0x60: overlay_entry_count
+ // 0x5c: overlay_entry_count
0x03, 0x00, 0x00, 0x00,
- // 0x64: string_pool_offset
+ // 0x60: string_pool_offset
0x00, 0x00, 0x00, 0x00,
// TARGET ENTRIES
- // 0x68: target id (0x7f020000)
+ // 0x64: target id (0x7f020000)
0x00, 0x00, 0x02, 0x7f,
- // 0x6c: overlay_id (0x7f020000)
+ // 0x68: overlay_id (0x7f020000)
0x00, 0x00, 0x02, 0x7f,
- // 0x70: target id (0x7f030000)
+ // 0x6c: target id (0x7f030000)
0x00, 0x00, 0x03, 0x7f,
- // 0x74: overlay_id (0x7f030000)
+ // 0x70: overlay_id (0x7f030000)
0x00, 0x00, 0x03, 0x7f,
- // 0x78: target id (0x7f030002)
+ // 0x74: target id (0x7f030002)
0x02, 0x00, 0x03, 0x7f,
- // 0x7c: overlay_id (0x7f030001)
+ // 0x78: overlay_id (0x7f030001)
0x01, 0x00, 0x03, 0x7f,
// INLINE TARGET ENTRIES
- // 0x80: target_id
+ // 0x7c: target_id
0x00, 0x00, 0x04, 0x7f,
- // 0x84: Res_value::size (value ignored by idmap)
+ // 0x80: Res_value::size (value ignored by idmap)
0x08, 0x00,
- // 0x87: Res_value::res0 (value ignored by idmap)
+ // 0x82: Res_value::res0 (value ignored by idmap)
0x00,
- // 0x88: Res_value::dataType (TYPE_INT_HEX)
+ // 0x83: Res_value::dataType (TYPE_INT_HEX)
0x11,
- // 0x8c: Res_value::data
+ // 0x84: Res_value::data
0x78, 0x56, 0x34, 0x12,
// OVERLAY ENTRIES
- // 0x90: 0x7f020000 -> 0x7f020000
+ // 0x88: 0x7f020000 -> 0x7f020000
0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f,
- // 0x98: 0x7f030000 -> 0x7f030000
+ // 0x90: 0x7f030000 -> 0x7f030000
0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x03, 0x7f,
- // 0xa0: 0x7f030001 -> 0x7f030002
+ // 0x98: 0x7f030001 -> 0x7f030002
0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f,
- // 0xa4: string pool
+ // 0xa0: string pool
// string length,
0x04, 0x00, 0x00, 0x00,
- // 0xa8 string contents "test"
+ // 0xa4 string contents "test"
0x74, 0x65, 0x73, 0x74};
-const unsigned int kIdmapRawDataLen = 0xac;
+const unsigned int kIdmapRawDataLen = 0xa8;
const unsigned int kIdmapRawDataOffset = 0x54;
const unsigned int kIdmapRawDataTargetCrc = 0x1234;
const unsigned int kIdmapRawOverlayCrc = 0x5678;
diff --git a/cmds/idmap2/tests/XmlParserTests.cpp b/cmds/idmap2/tests/XmlParserTests.cpp
index 1a7eaca..eaf10a7 100644
--- a/cmds/idmap2/tests/XmlParserTests.cpp
+++ b/cmds/idmap2/tests/XmlParserTests.cpp
@@ -19,25 +19,25 @@
#include <string>
#include "TestHelpers.h"
-#include "gmock/gmock.h"
+#include "androidfw/AssetsProvider.h"
#include "gtest/gtest.h"
#include "idmap2/XmlParser.h"
-#include "idmap2/ZipFile.h"
namespace android::idmap2 {
-Result<std::unique_ptr<const XmlParser>> CreateTestParser(const std::string& test_file) {
- auto zip = ZipFile::Open(GetTestDataPath() + "/target/target.apk");
+Result<XmlParser> CreateTestParser(const std::string& test_file) {
+ auto zip = ZipAssetsProvider::Create(GetTestDataPath() + "/target/target.apk");
if (zip == nullptr) {
return Error("Failed to open zip file");
}
- auto data = zip->Uncompress(test_file);
+ auto data = zip->Open(test_file);
if (data == nullptr) {
return Error("Failed to open xml file");
}
- return XmlParser::Create(data->buf, data->size, /* copy_data */ true);
+ return XmlParser::Create(data->getBuffer(true /* aligned*/), data->getLength(),
+ /* copy_data */ true);
}
TEST(XmlParserTests, Create) {
@@ -54,7 +54,7 @@
auto xml = CreateTestParser("res/xml/test.xml");
ASSERT_TRUE(xml) << xml.GetErrorMessage();
- auto root_iter = (*xml)->tree_iterator();
+ auto root_iter = xml->tree_iterator();
ASSERT_EQ(root_iter->event(), XmlParser::Event::START_TAG);
ASSERT_EQ(root_iter->name(), "a");
@@ -85,7 +85,7 @@
ASSERT_TRUE(xml) << xml.GetErrorMessage();
// Start at the <a> tag.
- auto root_iter = (*xml)->tree_iterator();
+ auto root_iter = xml->tree_iterator();
// Start at the <b> tag.
auto a_iter = root_iter.begin();
@@ -111,8 +111,8 @@
ASSERT_TRUE(xml) << xml.GetErrorMessage();
// Start at the <a> tag.
- auto root_iter_1 = (*xml)->tree_iterator();
- auto root_iter_2 = (*xml)->tree_iterator();
+ auto root_iter_1 = xml->tree_iterator();
+ auto root_iter_2 = xml->tree_iterator();
ASSERT_EQ(root_iter_1, root_iter_2);
ASSERT_EQ(*root_iter_1, *root_iter_2);
@@ -146,7 +146,7 @@
ASSERT_TRUE(xml) << xml.GetErrorMessage();
// Start at the <a> tag.
- auto root_iter_1 = (*xml)->tree_iterator();
+ auto root_iter_1 = xml->tree_iterator();
// Start at the <b> tag.
auto a_iter_1 = root_iter_1.begin();
diff --git a/cmds/idmap2/tests/ZipFileTests.cpp b/cmds/idmap2/tests/ZipFileTests.cpp
deleted file mode 100644
index 3fca436..0000000
--- a/cmds/idmap2/tests/ZipFileTests.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.
- */
-
-#include <cstdio> // fclose
-#include <string>
-
-#include "TestHelpers.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include "idmap2/Result.h"
-#include "idmap2/ZipFile.h"
-
-using ::testing::IsNull;
-using ::testing::NotNull;
-
-namespace android::idmap2 {
-
-TEST(ZipFileTests, BasicOpen) {
- auto zip = ZipFile::Open(GetTestDataPath() + "/target/target.apk");
- ASSERT_THAT(zip, NotNull());
-
- fclose(stderr); // silence expected warnings from libziparchive
- auto fail = ZipFile::Open(GetTestDataPath() + "/does-not-exist");
- ASSERT_THAT(fail, IsNull());
-}
-
-TEST(ZipFileTests, Crc) {
- auto zip = ZipFile::Open(GetTestDataPath() + "/target/target.apk");
- ASSERT_THAT(zip, NotNull());
-
- Result<uint32_t> crc = zip->Crc("AndroidManifest.xml");
- ASSERT_TRUE(crc);
- ASSERT_EQ(*crc, 0x762f3d24);
-
- Result<uint32_t> crc2 = zip->Crc("does-not-exist");
- ASSERT_FALSE(crc2);
-}
-
-TEST(ZipFileTests, Uncompress) {
- auto zip = ZipFile::Open(GetTestDataPath() + "/target/target.apk");
- ASSERT_THAT(zip, NotNull());
-
- auto data = zip->Uncompress("assets/lorem-ipsum.txt");
- ASSERT_THAT(data, NotNull());
- const std::string lorem_ipsum("Lorem ipsum dolor sit amet.\n");
- ASSERT_THAT(data->size, lorem_ipsum.size());
- ASSERT_THAT(std::string(reinterpret_cast<const char*>(data->buf), data->size), lorem_ipsum);
-
- auto fail = zip->Uncompress("does-not-exist");
- ASSERT_THAT(fail, IsNull());
-}
-
-} // namespace android::idmap2