Loading cmds/idmap2/include/idmap2/ResourceUtils.h +4 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,10 @@ typedef uint16_t EntryId; // eeee in 0xpptteeee namespace utils { // Returns whether the Res_value::data_type represents a dynamic or regular resource reference. bool IsReference(uint8_t data_type); // Converts the Res_value::data_type to a human-readable string representation. StringPiece DataTypeToString(uint8_t data_type); struct OverlayManifestInfo { Loading cmds/idmap2/libidmap2/ResourceMapping.cpp +10 −7 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include "idmap2/ResourceUtils.h" using android::base::StringPrintf; using android::idmap2::utils::IsReference; using android::idmap2::utils::ResToTypeEntryName; namespace android::idmap2 { Loading Loading @@ -200,8 +201,7 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMapping(const AssetManage // Only rewrite resources defined within the overlay package to their corresponding target // resource ids at runtime. bool rewrite_overlay_reference = (overlay_resource->dataType == Res_value::TYPE_REFERENCE || overlay_resource->dataType == Res_value::TYPE_DYNAMIC_REFERENCE) IsReference(overlay_resource->dataType) ? overlay_package_id == EXTRACT_PACKAGE(overlay_resource->data) : false; Loading Loading @@ -331,8 +331,13 @@ Result<ResourceMapping> ResourceMapping::FromApkAssets(const ApkAssets& target_a std::unique_ptr<uint8_t[]> string_pool_data; Result<ResourceMapping> resource_mapping = {{}}; if (overlay_info.resource_mapping != 0U) { // Use the dynamic reference table to find the assigned resource id of the map xml. const auto& ref_table = overlay_asset_manager.GetDynamicRefTableForCookie(0); uint32_t resource_mapping_id = overlay_info.resource_mapping; ref_table->lookupResourceId(&resource_mapping_id); // Load the overlay resource mappings from the file specified using android:resourcesMap. auto asset = OpenNonAssetFromResource(overlay_info.resource_mapping, overlay_asset_manager); auto asset = OpenNonAssetFromResource(resource_mapping_id, overlay_asset_manager); if (!asset) { return Error("failed opening xml for android:resourcesMap: %s", asset.GetErrorMessage().c_str()); Loading Loading @@ -404,8 +409,7 @@ Result<Unit> ResourceMapping::AddMapping(ResourceId target_resource, target_map_.insert(std::make_pair(target_resource, TargetValue{data_type, data_value})); if (rewrite_overlay_reference && (data_type == Res_value::TYPE_REFERENCE || data_type == Res_value::TYPE_DYNAMIC_REFERENCE)) { if (rewrite_overlay_reference && IsReference(data_type)) { overlay_map_.insert(std::make_pair(data_value, target_resource)); } Loading @@ -421,8 +425,7 @@ void ResourceMapping::RemoveMapping(ResourceId target_resource) { const TargetValue value = target_iter->second; target_map_.erase(target_iter); if (value.data_type != Res_value::TYPE_REFERENCE && value.data_type != Res_value::TYPE_DYNAMIC_REFERENCE) { if (!IsReference(value.data_type)) { return; } Loading cmds/idmap2/libidmap2/ResourceUtils.cpp +5 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,10 @@ using android::util::Utf16ToUtf8; namespace android::idmap2::utils { bool IsReference(uint8_t data_type) { return data_type == Res_value::TYPE_REFERENCE || data_type == Res_value::TYPE_DYNAMIC_REFERENCE; } StringPiece DataTypeToString(uint8_t data_type) { switch (data_type) { case Res_value::TYPE_NULL: Loading Loading @@ -133,7 +137,7 @@ Result<OverlayManifestInfo> ExtractOverlayManifestInfo(const std::string& path, } if (auto result_value = overlay_it->GetAttributeValue("resourcesMap")) { if ((*result_value).dataType == Res_value::TYPE_REFERENCE) { if (IsReference((*result_value).dataType)) { info.resource_mapping = (*result_value).data; } else { return Error("android:resourcesMap is not a reference in AndroidManifest.xml of %s", Loading cmds/idmap2/tests/FileUtilsTests.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -56,12 +56,12 @@ TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) { return type == DT_REG && path.size() > 4 && path.compare(path.size() - 4, 4, ".apk") == 0; }); ASSERT_THAT(v, NotNull()); ASSERT_EQ(v->size(), 10U); ASSERT_EQ(v->size(), 11U); ASSERT_EQ(std::set<std::string>(v->begin(), v->end()), std::set<std::string>( {root + "/target/target.apk", root + "/target/target-no-overlayable.apk", root + "/overlay/overlay.apk", root + "/overlay/overlay-no-name.apk", root + "/overlay/overlay-no-name-static.apk", root + "/overlay/overlay-no-name-static.apk", root + "/overlay/overlay-shared.apk", root + "/overlay/overlay-static-1.apk", root + "/overlay/overlay-static-2.apk", root + "/signature-overlay/signature-overlay.apk", root + "/system-overlay/system-overlay.apk", Loading cmds/idmap2/tests/IdmapTests.cpp +37 −0 Original line number Diff line number Diff line Loading @@ -247,6 +247,43 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssets) { ASSERT_OVERLAY_ENTRY(overlay_entries[3], 0x7f020002, 0x7f02000f); } TEST(IdmapTests, CreateIdmapDataFromApkAssetsSharedLibOverlay) { 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()); std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_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()); const auto& target_entries = data->GetTargetEntries(); ASSERT_EQ(target_entries.size(), 4U); ASSERT_TARGET_ENTRY(target_entries[0], 0x7f010000, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00010000); ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020000); ASSERT_TARGET_ENTRY(target_entries[2], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020001); ASSERT_TARGET_ENTRY(target_entries[3], 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020002); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(target_entries.size(), 4U); ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x00010000, 0x7f010000); ASSERT_OVERLAY_ENTRY(overlay_entries[1], 0x00020000, 0x7f02000c); ASSERT_OVERLAY_ENTRY(overlay_entries[2], 0x00020001, 0x7f02000e); ASSERT_OVERLAY_ENTRY(overlay_entries[3], 0x00020002, 0x7f02000f); } TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) { OverlayManifestInfo info{}; info.target_package = "test.target"; Loading Loading
cmds/idmap2/include/idmap2/ResourceUtils.h +4 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,10 @@ typedef uint16_t EntryId; // eeee in 0xpptteeee namespace utils { // Returns whether the Res_value::data_type represents a dynamic or regular resource reference. bool IsReference(uint8_t data_type); // Converts the Res_value::data_type to a human-readable string representation. StringPiece DataTypeToString(uint8_t data_type); struct OverlayManifestInfo { Loading
cmds/idmap2/libidmap2/ResourceMapping.cpp +10 −7 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ #include "idmap2/ResourceUtils.h" using android::base::StringPrintf; using android::idmap2::utils::IsReference; using android::idmap2::utils::ResToTypeEntryName; namespace android::idmap2 { Loading Loading @@ -200,8 +201,7 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMapping(const AssetManage // Only rewrite resources defined within the overlay package to their corresponding target // resource ids at runtime. bool rewrite_overlay_reference = (overlay_resource->dataType == Res_value::TYPE_REFERENCE || overlay_resource->dataType == Res_value::TYPE_DYNAMIC_REFERENCE) IsReference(overlay_resource->dataType) ? overlay_package_id == EXTRACT_PACKAGE(overlay_resource->data) : false; Loading Loading @@ -331,8 +331,13 @@ Result<ResourceMapping> ResourceMapping::FromApkAssets(const ApkAssets& target_a std::unique_ptr<uint8_t[]> string_pool_data; Result<ResourceMapping> resource_mapping = {{}}; if (overlay_info.resource_mapping != 0U) { // Use the dynamic reference table to find the assigned resource id of the map xml. const auto& ref_table = overlay_asset_manager.GetDynamicRefTableForCookie(0); uint32_t resource_mapping_id = overlay_info.resource_mapping; ref_table->lookupResourceId(&resource_mapping_id); // Load the overlay resource mappings from the file specified using android:resourcesMap. auto asset = OpenNonAssetFromResource(overlay_info.resource_mapping, overlay_asset_manager); auto asset = OpenNonAssetFromResource(resource_mapping_id, overlay_asset_manager); if (!asset) { return Error("failed opening xml for android:resourcesMap: %s", asset.GetErrorMessage().c_str()); Loading Loading @@ -404,8 +409,7 @@ Result<Unit> ResourceMapping::AddMapping(ResourceId target_resource, target_map_.insert(std::make_pair(target_resource, TargetValue{data_type, data_value})); if (rewrite_overlay_reference && (data_type == Res_value::TYPE_REFERENCE || data_type == Res_value::TYPE_DYNAMIC_REFERENCE)) { if (rewrite_overlay_reference && IsReference(data_type)) { overlay_map_.insert(std::make_pair(data_value, target_resource)); } Loading @@ -421,8 +425,7 @@ void ResourceMapping::RemoveMapping(ResourceId target_resource) { const TargetValue value = target_iter->second; target_map_.erase(target_iter); if (value.data_type != Res_value::TYPE_REFERENCE && value.data_type != Res_value::TYPE_DYNAMIC_REFERENCE) { if (!IsReference(value.data_type)) { return; } Loading
cmds/idmap2/libidmap2/ResourceUtils.cpp +5 −1 Original line number Diff line number Diff line Loading @@ -33,6 +33,10 @@ using android::util::Utf16ToUtf8; namespace android::idmap2::utils { bool IsReference(uint8_t data_type) { return data_type == Res_value::TYPE_REFERENCE || data_type == Res_value::TYPE_DYNAMIC_REFERENCE; } StringPiece DataTypeToString(uint8_t data_type) { switch (data_type) { case Res_value::TYPE_NULL: Loading Loading @@ -133,7 +137,7 @@ Result<OverlayManifestInfo> ExtractOverlayManifestInfo(const std::string& path, } if (auto result_value = overlay_it->GetAttributeValue("resourcesMap")) { if ((*result_value).dataType == Res_value::TYPE_REFERENCE) { if (IsReference((*result_value).dataType)) { info.resource_mapping = (*result_value).data; } else { return Error("android:resourcesMap is not a reference in AndroidManifest.xml of %s", Loading
cmds/idmap2/tests/FileUtilsTests.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -56,12 +56,12 @@ TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) { return type == DT_REG && path.size() > 4 && path.compare(path.size() - 4, 4, ".apk") == 0; }); ASSERT_THAT(v, NotNull()); ASSERT_EQ(v->size(), 10U); ASSERT_EQ(v->size(), 11U); ASSERT_EQ(std::set<std::string>(v->begin(), v->end()), std::set<std::string>( {root + "/target/target.apk", root + "/target/target-no-overlayable.apk", root + "/overlay/overlay.apk", root + "/overlay/overlay-no-name.apk", root + "/overlay/overlay-no-name-static.apk", root + "/overlay/overlay-no-name-static.apk", root + "/overlay/overlay-shared.apk", root + "/overlay/overlay-static-1.apk", root + "/overlay/overlay-static-2.apk", root + "/signature-overlay/signature-overlay.apk", root + "/system-overlay/system-overlay.apk", Loading
cmds/idmap2/tests/IdmapTests.cpp +37 −0 Original line number Diff line number Diff line Loading @@ -247,6 +247,43 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssets) { ASSERT_OVERLAY_ENTRY(overlay_entries[3], 0x7f020002, 0x7f02000f); } TEST(IdmapTests, CreateIdmapDataFromApkAssetsSharedLibOverlay) { 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()); std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_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()); const auto& target_entries = data->GetTargetEntries(); ASSERT_EQ(target_entries.size(), 4U); ASSERT_TARGET_ENTRY(target_entries[0], 0x7f010000, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00010000); ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020000); ASSERT_TARGET_ENTRY(target_entries[2], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020001); ASSERT_TARGET_ENTRY(target_entries[3], 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020002); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(target_entries.size(), 4U); ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x00010000, 0x7f010000); ASSERT_OVERLAY_ENTRY(overlay_entries[1], 0x00020000, 0x7f02000c); ASSERT_OVERLAY_ENTRY(overlay_entries[2], 0x00020001, 0x7f02000e); ASSERT_OVERLAY_ENTRY(overlay_entries[3], 0x00020002, 0x7f02000f); } TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) { OverlayManifestInfo info{}; info.target_package = "test.target"; Loading