From 5035d66aee53c5a0246b99e21a62a1d27fc6de4e Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Wed, 22 Jan 2020 13:19:41 -0800 Subject: [PATCH] Fix resourcesMap to work with shared libraries android:resourcesMap is not working at all with shared libraries. This change fixes that so overlays built as shared libraries can use the attribute. Bug: None Test: idmap2_tests Change-Id: I767481f88c58892a3818a919616056291b09b57e --- cmds/idmap2/include/idmap2/ResourceUtils.h | 4 ++ cmds/idmap2/libidmap2/ResourceMapping.cpp | 17 ++++---- cmds/idmap2/libidmap2/ResourceUtils.cpp | 6 ++- cmds/idmap2/tests/FileUtilsTests.cpp | 4 +- cmds/idmap2/tests/IdmapTests.cpp | 37 ++++++++++++++++++ cmds/idmap2/tests/data/overlay/build | 8 ++++ .../tests/data/overlay/overlay-shared.apk | Bin 0 -> 3757 bytes 7 files changed, 66 insertions(+), 10 deletions(-) create mode 100644 cmds/idmap2/tests/data/overlay/overlay-shared.apk diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h index de1dbc90eb2d0..c643b0e8800cc 100644 --- a/cmds/idmap2/include/idmap2/ResourceUtils.h +++ b/cmds/idmap2/include/idmap2/ResourceUtils.h @@ -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 { diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp index 407478945151c..43cfec3f9cf92 100644 --- a/cmds/idmap2/libidmap2/ResourceMapping.cpp +++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp @@ -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 { @@ -200,8 +201,7 @@ Result 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; @@ -331,8 +331,13 @@ Result ResourceMapping::FromApkAssets(const ApkAssets& target_a std::unique_ptr string_pool_data; Result 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()); @@ -404,8 +409,7 @@ Result 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)); } @@ -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; } diff --git a/cmds/idmap2/libidmap2/ResourceUtils.cpp b/cmds/idmap2/libidmap2/ResourceUtils.cpp index a5df746ca7330..98d026bc70dc6 100644 --- a/cmds/idmap2/libidmap2/ResourceUtils.cpp +++ b/cmds/idmap2/libidmap2/ResourceUtils.cpp @@ -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: @@ -133,7 +137,7 @@ Result 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", diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp index f55acee029dc7..8af4037be954f 100644 --- a/cmds/idmap2/tests/FileUtilsTests.cpp +++ b/cmds/idmap2/tests/FileUtilsTests.cpp @@ -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(v->begin(), v->end()), std::set( {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", diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index 4bc625565144a..a2c156063757d 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -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 target_apk = ApkAssets::Load(target_apk_path); + ASSERT_THAT(target_apk, NotNull()); + + std::unique_ptr 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>& dataBlocks = idmap->GetData(); + ASSERT_EQ(dataBlocks.size(), 1U); + + const std::unique_ptr& 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"; diff --git a/cmds/idmap2/tests/data/overlay/build b/cmds/idmap2/tests/data/overlay/build index b921b0d3d3add..114b099598faf 100755 --- a/cmds/idmap2/tests/data/overlay/build +++ b/cmds/idmap2/tests/data/overlay/build @@ -51,4 +51,12 @@ aapt2 link \ -o overlay-static-2.apk \ compiled.flata +aapt2 link \ + --no-resource-removal \ + --shared-lib \ + -I "$FRAMEWORK_RES_APK" \ + --manifest AndroidManifest.xml \ + -o overlay-shared.apk \ + compiled.flata + rm compiled.flata diff --git a/cmds/idmap2/tests/data/overlay/overlay-shared.apk b/cmds/idmap2/tests/data/overlay/overlay-shared.apk new file mode 100644 index 0000000000000000000000000000000000000000..93dcc82f93584f77a551c90a8175755b843672c4 GIT binary patch literal 3757 zcmd^Cdpy)x8$UCH(U@@^X<{~SLM69VE0r1%VhfFm(#tf4W*S2?gM?PC(!P;fq*B;) zbLr^Zv2>=RTj$_xC*KocTTHdA{d4=Xb{4 z6{i58C<73ag}F1LWKxX*z#sN$!CpI_KR=l5zk$JH2e1S}v%NvwG!G`hdyQ z+~D9~XIFb~{#CMT5LeUTR(q0lM1P65Vy&ps#|H0>ed4arujy;CiR+;@B zk+06$2)^$7dEH9VLM|g6yG0}Mns(n9W{=CaM<_#UZ)gtG<2|;}vMP+v9tjjDgxsxi z>iWe=i=O$jL3kY1F!sK}>mk#6%FEe@$KI?D?Qtrv-Md6W*cuTZO|;nAeUNMKV@YUO z?YF_?*;w5b=eu2}s~R|Qp=#Fg+cev}M{{gf=sY-)LXxEWTyA>0VEbuGV&pEoO3NF1 zT}C`Vl%E6^WjUNnlbU;WBucTJe^5JU7+p~scbh>En* zM6asU_^iQ5dr!`x9fhh5{QITsckL=sAKcvPhLO;rxI z1)fPB9G9+A7rV5}aqp7ecZK|}idob>ui(a4inn)XQUo=lD~#Wo1fSMhL-M~xU+zse zr;=D}es zK9><8Ki{oJH(e&t4yL-_i-O-JtxOMCeyel@* z2bLE6d)P00U1h0vny$)o^Lz=7Og(m?JOAYZ%5?6ue&8$PHawQ_+txRX|LqX zcSHCuxf;_f%+7-x9f8}!Xa=r){n-HlEIx}T^bKJ!cQXQ6Quf@g5=0i{8%x>r{!O=P z?LziwYuqXtG+q(A=@P+m_A|YYyKjnAc7_g$h8p$^m^C*HxyOj~Ff=7hIrX>Vt_+_f z6TaKrR)z4`@>dTf*RJO*G^@3~xbMMLNkvdHD`&V|#ksYRQ*`V@cv>md+4Bd(!1b#Y z^Y0ut{_&k&7pWOHv_RamtTl3dcdtX4r_r)y2R%-Cm(KIP${cozOIQ8a!O-rw%FNIn zec|i-WxD?=-?pX>rkM%T)txC_Hjm5ZP3Bkya|Aa=NV6}CJF`1G^DAsB2!yu}73~)} zs7RAk9^Y)9vQqr+oG|mQPc@@j)B{PGE?q?a7Ku9b(3!rL}+jDB^ul@6LNo9A!K;%V&7mb+vMJAf z^5}5yXv(8gPyLzuGTsJdfn|#=d>9pmMDm=1HSuAJhmDCvu{nhJ|IBl|h{cI$J=ER@?>o|(z8n9QDk}-Z zMHYs`323^c1OS36z@gJ3IF!$13CtLL0TccP3y9J|STX=Di4Xb*KGss)_-HGHq10&VWe# z6p^VQ?6c-l)C5?4OtB&i9EuRIfB-(tKrqaS1^9pq7$9O|@Ne+cM~e?dIH{41YQYm~ z9BNF;LYV=zCd7OQJYWN!l)*qLa{wqwx#Uax1K}@lU@r)Qj86EhfO-~$RN#EHNfRkN zgbu`45QY#-Agm!!903pt3T&Rx5|Bu|V4*LY=PP9J16e}YEfDf8CzREMS_+hvWgkQ^ zcdpEwUSmK_?bF~yT|xJsdQdIFd9he^Y271w;PLWFFj!9z1zWOyA86A)jsAH<9lk2t zgHWrFLqTmckF1Si(t~Xj4_YJXg%D~aD6SZ&Wn+HOra}BwL2=1qLB3%u((*vDAp^Bh zjQ?+bwDtb1pt)t-$mWOVnv^S)Kbjxa5aLE3YI$B@msC)ExzLi0`$L;19rSwS}kc@Ofp%P9}KaE0YPOh0>O@+p6XoAOD3RWi-z z)TdBBIQjd~lp`frUeg@OzM4~R;0x344^vJ6pu%c~Za%wBxVtK%3WsH`1kOPYN6>u% F`~heh%5wk! literal 0 HcmV?d00001