From 0f942f99cac4f5f61b40847d20ecb3a94c96c843 Mon Sep 17 00:00:00 2001 From: Zoran Jovanovic Date: Tue, 9 Jun 2020 18:51:57 +0200 Subject: [PATCH 1/4] OMS: Add config_signature policy handling Alongside SIGNATURE and ACTOR_SIGNATURE policies, add CONFIG_SIGNATURE policy to overlayable that overlay fulfills if it is signed with the same certificate as the reference package whose package name is declared in 'config-signature' tag of SystemConfig and is vetted by OMS that it's a system pre-installed package. BUG: 158726924 TEST: regular aapt2, idmap2, OMS tests Merged-In: I645ee72271496008742886274be0d63a2985201b Change-Id: I645ee72271496008742886274be0d63a2985201b --- .../aidl/android/os/OverlayablePolicy.aidl | 1 + cmds/idmap2/libidmap2/ResourceMapping.cpp | 7 +- .../include/idmap2/Policies.h | 4 +- cmds/idmap2/tests/R.h | 38 ++++---- cmds/idmap2/tests/ResourceMappingTests.cpp | 18 +++- cmds/idmap2/tests/TestConstants.h | 8 +- .../data/overlay/overlay-no-name-static.apk | Bin 3477 -> 3485 bytes .../tests/data/overlay/overlay-no-name.apk | Bin 3389 -> 3393 bytes .../tests/data/overlay/overlay-shared.apk | Bin 3757 -> 3757 bytes .../tests/data/overlay/overlay-static-1.apk | Bin 3469 -> 3477 bytes .../tests/data/overlay/overlay-static-2.apk | Bin 3469 -> 3477 bytes cmds/idmap2/tests/data/overlay/overlay.apk | Bin 3489 -> 3489 bytes .../signature-overlay/signature-overlay.apk | Bin 1315 -> 1299 bytes .../res/values/values.xml | 1 + .../system-overlay-invalid.apk | Bin 1827 -> 1907 bytes .../data/system-overlay/system-overlay.apk | Bin 1319 -> 1387 bytes .../data/target/res/values/overlayable.xml | 4 + .../tests/data/target/res/values/values.xml | 1 + .../data/target/target-no-overlayable.apk | Bin 2311 -> 2391 bytes cmds/idmap2/tests/data/target/target.apk | Bin 5097 -> 5201 bytes .../java/com/android/server/SystemConfig.java | 36 +++++++ .../include/androidfw/ResourceTypes.h | 4 + .../content/pm/PackageManagerInternal.java | 1 + .../com/android/server/om/IdmapManager.java | 34 +++++-- .../server/om/OverlayActorEnforcer.java | 20 ++-- .../server/om/OverlayManagerService.java | 11 ++- .../server/om/OverlayableInfoCallback.java | 83 ----------------- .../server/om/PackageManagerHelper.java | 68 +++++++++++++- .../server/pm/PackageManagerService.java | 67 +++++++------ .../server/pm/PackageManagerServiceUtils.java | 12 +++ .../server/om/OverlayActorEnforcerTests.kt | 10 +- .../OverlayManagerServiceImplRebootTests.java | 10 +- .../om/OverlayManagerServiceImplTests.java | 88 ++++++++++++++++++ .../OverlayManagerServiceImplTestsBase.java | 53 +++++++++-- tools/aapt2/Resources.proto | 1 + .../format/binary/TableFlattener_test.cpp | 4 +- tools/aapt2/format/proto/ProtoDeserialize.cpp | 3 + tools/aapt2/format/proto/ProtoSerialize.cpp | 3 + 38 files changed, 415 insertions(+), 175 deletions(-) delete mode 100644 services/core/java/com/android/server/om/OverlayableInfoCallback.java diff --git a/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl b/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl index 02b27a8800b61..403d8c55de164 100644 --- a/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl +++ b/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl @@ -29,4 +29,5 @@ interface OverlayablePolicy { const int ODM_PARTITION = 0x00000020; const int OEM_PARTITION = 0x00000040; const int ACTOR_SIGNATURE = 0x00000080; + const int CONFIG_SIGNATURE = 0x0000100; } diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp index 34589a1c39dcc..fd8b4eb86b4a4 100644 --- a/cmds/idmap2/libidmap2/ResourceMapping.cpp +++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp @@ -61,10 +61,13 @@ Result CheckOverlayable(const LoadedPackage& target_package, const ResourceId& target_resource) { static constexpr const PolicyBitmask sDefaultPolicies = PolicyFlags::ODM_PARTITION | PolicyFlags::OEM_PARTITION | PolicyFlags::SYSTEM_PARTITION | - PolicyFlags::VENDOR_PARTITION | PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE; + PolicyFlags::VENDOR_PARTITION | PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE | + PolicyFlags::CONFIG_SIGNATURE; // If the resource does not have an overlayable definition, allow the resource to be overlaid if - // the overlay is preinstalled or signed with the same signature as the target. + // the overlay is preinstalled, signed with the same signature as the target or signed with the + // same signature as reference package defined in SystemConfig under 'overlay-config-signature' + // tag. if (!target_package.DefinesOverlayable()) { return (sDefaultPolicies & fulfilled_policies) != 0 ? Result({}) diff --git a/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h b/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h index 5bd353af4ad3b..8046319824908 100644 --- a/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h +++ b/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h @@ -37,16 +37,18 @@ constexpr const char* kPolicyOdm = "odm"; constexpr const char* kPolicyOem = "oem"; constexpr const char* kPolicyProduct = "product"; constexpr const char* kPolicyPublic = "public"; +constexpr const char* kPolicyConfigSignature = "config_signature"; constexpr const char* kPolicySignature = "signature"; constexpr const char* kPolicySystem = "system"; constexpr const char* kPolicyVendor = "vendor"; -inline static const std::array, 8> kPolicyStringToFlag = { +inline static const std::array, 9> kPolicyStringToFlag = { std::pair{kPolicyActor, PolicyFlags::ACTOR_SIGNATURE}, {kPolicyOdm, PolicyFlags::ODM_PARTITION}, {kPolicyOem, PolicyFlags::OEM_PARTITION}, {kPolicyProduct, PolicyFlags::PRODUCT_PARTITION}, {kPolicyPublic, PolicyFlags::PUBLIC}, + {kPolicyConfigSignature, PolicyFlags::CONFIG_SIGNATURE}, {kPolicySignature, PolicyFlags::SIGNATURE}, {kPolicySystem, PolicyFlags::SYSTEM_PARTITION}, {kPolicyVendor, PolicyFlags::VENDOR_PARTITION}, diff --git a/cmds/idmap2/tests/R.h b/cmds/idmap2/tests/R.h index aed263a49aa3d..89b43466ba5e6 100644 --- a/cmds/idmap2/tests/R.h +++ b/cmds/idmap2/tests/R.h @@ -41,16 +41,17 @@ namespace R::target { constexpr ResourceId not_overlayable = 0x7f020003; constexpr ResourceId other = 0x7f020004; constexpr ResourceId policy_actor = 0x7f020005; - constexpr ResourceId policy_odm = 0x7f020006; - constexpr ResourceId policy_oem = 0x7f020007; - constexpr ResourceId policy_product = 0x7f020008; - constexpr ResourceId policy_public = 0x7f020009; - constexpr ResourceId policy_signature = 0x7f02000a; - constexpr ResourceId policy_system = 0x7f02000b; - constexpr ResourceId policy_system_vendor = 0x7f02000c; - constexpr ResourceId str1 = 0x7f02000d; - constexpr ResourceId str3 = 0x7f02000f; - constexpr ResourceId str4 = 0x7f020010; + constexpr ResourceId policy_config_signature = 0x7f020006; + constexpr ResourceId policy_odm = 0x7f020007; + constexpr ResourceId policy_oem = 0x7f020008; + constexpr ResourceId policy_product = 0x7f020009; + constexpr ResourceId policy_public = 0x7f02000a; + constexpr ResourceId policy_signature = 0x7f02000b; + constexpr ResourceId policy_system = 0x7f02000c; + constexpr ResourceId policy_system_vendor = 0x7f02000d; + constexpr ResourceId str1 = 0x7f02000e; + constexpr ResourceId str3 = 0x7f020010; + constexpr ResourceId str4 = 0x7f020011; namespace literal { inline const std::string str1 = hexify(R::target::string::str1); @@ -92,14 +93,15 @@ namespace R::system_overlay_invalid::string { constexpr ResourceId not_overlayable = 0x7f010000; constexpr ResourceId other = 0x7f010001; constexpr ResourceId policy_actor = 0x7f010002; - constexpr ResourceId policy_odm = 0x7f010003; - constexpr ResourceId policy_oem = 0x7f010004; - constexpr ResourceId policy_product = 0x7f010005; - constexpr ResourceId policy_public = 0x7f010006; - constexpr ResourceId policy_signature = 0x7f010007; - constexpr ResourceId policy_system = 0x7f010008; - constexpr ResourceId policy_system_vendor = 0x7f010009; -}; + constexpr ResourceId policy_config_signature = 0x7f010003; + constexpr ResourceId policy_odm = 0x7f010004; + constexpr ResourceId policy_oem = 0x7f010005; + constexpr ResourceId policy_product = 0x7f010006; + constexpr ResourceId policy_public = 0x7f010007; + constexpr ResourceId policy_signature = 0x7f010008; + constexpr ResourceId policy_system = 0x7f010009; + constexpr ResourceId policy_system_vendor = 0x7f01000a; +} // clang-format on } // namespace android::idmap2 diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp index de039f440e33f..3ec6ac24b238e 100644 --- a/cmds/idmap2/tests/ResourceMappingTests.cpp +++ b/cmds/idmap2/tests/ResourceMappingTests.cpp @@ -237,7 +237,7 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnore ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; - ASSERT_EQ(res.GetTargetToOverlayMap().size(), 10U); + ASSERT_EQ(res.GetTargetToOverlayMap().size(), 11U); ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::not_overlayable, false /* rewrite */)); @@ -256,6 +256,10 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnore ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::policy_public, false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature, + Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::policy_config_signature, + false /* rewrite */)); ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::policy_signature, false /* rewrite */)); @@ -298,8 +302,9 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) { ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U); } -// Overlays that are pre-installed or are signed with the same signature as the target can overlay -// packages that have not defined overlayable resources. +// Overlays that are pre-installed or are signed with the same signature as the target or are 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 resources = TestGetResourceMapping("/target/target-no-overlayable.apk", @@ -309,7 +314,7 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) { ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; - ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 10U); + ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 11U); ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::not_overlayable, false /* rewrite */)); @@ -330,6 +335,10 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) { ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::policy_public, false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature, + Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::policy_config_signature, + false /* rewrite */)); ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::policy_signature, false /* rewrite */)); @@ -342,6 +351,7 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) { }; CheckEntries(PolicyFlags::SIGNATURE); + CheckEntries(PolicyFlags::CONFIG_SIGNATURE); CheckEntries(PolicyFlags::PRODUCT_PARTITION); CheckEntries(PolicyFlags::SYSTEM_PARTITION); CheckEntries(PolicyFlags::VENDOR_PARTITION); diff --git a/cmds/idmap2/tests/TestConstants.h b/cmds/idmap2/tests/TestConstants.h index 6bc924e5ac3cd..641a7a8d45aa1 100644 --- a/cmds/idmap2/tests/TestConstants.h +++ b/cmds/idmap2/tests/TestConstants.h @@ -19,11 +19,11 @@ namespace android::idmap2::TestConstants { -constexpr const auto TARGET_CRC = 0x41c60c8c; -constexpr const auto TARGET_CRC_STRING = "41c60c8c"; +constexpr const auto TARGET_CRC = 0x7c2d4719; +constexpr const auto TARGET_CRC_STRING = "7c2d4719"; -constexpr const auto OVERLAY_CRC = 0xc054fb26; -constexpr const auto OVERLAY_CRC_STRING = "c054fb26"; +constexpr const auto OVERLAY_CRC = 0x5afff726; +constexpr const auto OVERLAY_CRC_STRING = "5afff726"; } // namespace android::idmap2::TestConstants diff --git a/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk b/cmds/idmap2/tests/data/overlay/overlay-no-name-static.apk index 7c25985e5a61298b55ce10d3c227f46c7057c5bb..dab25b1f81317f6d7366993527bba85fb1d8f4f5 100644 GIT binary patch delta 723 zcmbO#Jy*Iuz?+$c0SGvNNRc7SPW0j~Mg|5IpqMaF)G;rmC_gjBH!&|WEw#8ruOc^R z>ZJXC(vAYh_J5Tu-so)5$kZaLDiqqa*<+@V)e;33L07IRFJ#!Y|EbRx?&NdTtl*i~ z)HF$bq2EmLhWl%#-zl89G{yh^yEo?d-<&xYx1>HII`rhqrKh{LEUKx|xsm;V_Xe~2 z1N9wj<`2aFn9V=Te(VAJ4yOGF#GW6M%3d_jt!~~cp1(q`)xX7mk$lZyeKkDow)a=} zd$n&GpC>;umaTj*Vm&o-GOe^D>#=;u?lZD89?q{3&HWs? z_5IECCpKSRd(_|W@ZPJdyGUNhvhn>!ul1!}WnSC1XMIl1@DJnsX9>y+~GZSI`i5&DtQMejr_!b{&Bu5T(9p1`p6%Hb|F8it+Vi4;~dTFCWO0nB2ug91=YcrrhaSpC#VXZ2VdMOyt|I{u#f zakGNQhAl5Vb#!lbv~VOTDy1Adf5hi}N|nbO9UYsN;~O@8Qn@zmUc>sVt~_0#UB$2N zS(Uz98@*jCV8zd-6qD8Ma+y9a%jbMlKWKD=!TkZBO=J28rh5l=P2_Xr$vdcA!P@sF=QI-b3F>+WMKmi=E4mAvNAk@(+|Z+Ap}pP~9@$K#yfaF@_I`d=6Kb!H#F zzTwg&y$fYGvRzaEvAkt{#dgXi&`x_)4!Z++f>R%qHPr7t_rsLhU+NVNA7iRC;xVm?a*51Pl zeNw(XdmH_zHz_^!4ATuAiQ)^{KGG@<%Usq5aqjutdV}!-bN&2>Z_Qua`?RF$@9u58 zoTS2MeV!BhzW8t0h3D7XH@cn|wKbpAz4c#)p5wJ^iRTR`u1r30J@CYpg+6+ZEg!$$ zzSC>|^CI&*Pk-5pFWLC`8rwegpSI00>+PzO>Rvu%M~%|WKN+&(y zP33?Bnya|>{RSqUFH8&!BA`?R2M;F)@Th14mFP3X>|O&D?f|ALHMlg0!N<%1vP!=q zH%EW6A*a;j?L2~D_nqdEV)+M@ocxYWS|`Ap5okCFKvJmB>UE({fV>8vs3ce%M*L!# YY{07lHX)itpET3 diff --git a/cmds/idmap2/tests/data/overlay/overlay-no-name.apk b/cmds/idmap2/tests/data/overlay/overlay-no-name.apk index c75f3e1dbddfe53947511311ecd9fa02e2b72099..c8b95c2601ad9ea333a4320bc1d00a92c37e0045 100644 GIT binary patch delta 647 zcmdlhbx=w=z?+$c0SGvNNRgpPR?{Mmk%1wBnSnug@_KHu`l%DodL4EUX+3Xp&29Aq ze{rrLfn7xtANa+r%GTs~6twZG*z6@LffuIkD0+CQ{o}$K_P=SfZV70<;7zYPXZ!u! z%ueGM*yEcWw_x~j8lX{q#_2K5h2_YN-imB?f+Ilx-MEPw3V$5F+k>)X#IY(74Eu7)Yo zzL^~G_S^5=S|j=hONuzxuc(tyPb-SM1=rpqe))Yqo0cPySo=6=rsO zm&8g=zSeuP;f&P0C8i%-bqub*jc=&e{b(jOclxx`t1rw{das=8pWXQUUg$jY(~olx znR4f?49dQKT6JCI4~v9*IzKZ+?0inP_fB23f9~E#aaXO@7u|ok_spE~A8e@MuepkA z-)~@Sd|_f>5CPIfn^!SPGBN{WX7Vwnw_ti3^G^`Hc@v8SSYq>8)+4Mu$Z7IFBIM z{%js8mNmfSF}aUTT06j-5vUFXAnC_v^}5g}Kwbk-R1z!>BUVg4&!Y)8;5UyHowO6V>z?+$c0SGu47#ij?PRY1z8pX)K5W~#CAPf|B%u6ZC&rI=6%*#wmEiTck z$jzBL(b4;`gGfudboS!V6*rojx~jfRh&j5rYTBX;lf^e)6`Q?8CGf&z_m407Kf3=^ zzLLLvCGW(hycu`5e}1<2%)6>jr7u0*qHnGBTs^DTPqY3WN9KYBmqe~m#-Sw<4KKEn(tj+U(XDpuggG*~2 zQ%UFS<+sv2qwDPN-T6^6>063Vl(`zSk*>_ge-FAh9*AN${V`oA|M;TfOJ$X!R>4nd zm)yP_^LD{u3o7PRQG2xP5_T+Hi)J5mk#mN+|%bFW* z`Tk2x+Bw@AX4Kf&JeN_6kr@~*lTR_d1=G8je}d@E+gK#P5}Plw9%1D{j=0GSxlQGO z0-CG1_WcIN;1?za1`$vM!$J4tFWf3%)1-N%n07EtzQLq1Ii80XER@e9#kgW}7mv0g v&q4IZ^)&#^kc8_8F_r++%;XJhl9S&<_5BCx+do-~SCOrS8>9dLi7Wj0 diff --git a/cmds/idmap2/tests/data/overlay/overlay-shared.apk b/cmds/idmap2/tests/data/overlay/overlay-shared.apk index 93dcc82f93584f77a551c90a8175755b843672c4..0a8b7372172e92f79c466bc02f6d99886b2ebdeb 100644 GIT binary patch delta 591 zcmZ20yH-{@z?+$c0SGvNNRi?AkF^{3F)}cu0L6qS%kzrWPYvGfci2H-PWR_Jhb93g zPQ?rj4WSnTswO6#0t#7+_MAK%mNX$lKvngA!zaZlHH`BQm|r+}=UETG`@{pwJIy!m zE-uc#?I?BDV!?*aOr8kG3e&X_pMM|GG*nu4MEj##jlld}Zj9zfm_PdL5qR%1ZP#uW zuGlMv2RUQ1w%-VB@UKtn;rsv7BKeNP{Qa^g)9O>Rd)g08k9cbI?ZV-PGptvC?MO0N zR@HC$w%{>;XyfFI{bloRihb70lQdOXXY|@o{4nG6vRchO{hxP6)t<8YIx8jS-JFBEsrN6qANvt7jlZS#lcm+On2UC6%g_Fv zb@X}fyyTafKhx6cybt<3`FVcFl!rnO_i5VpCfr}KPk3grf&bQofA>)%c=KOIO-5#5 zOi$Kiegmc@Sbl=&%_6KKV2RDzY}eS>p=n_<2d@=al`F43m~Q6{1k<;9-N3X8p9`4I H=5qo7XA%PS delta 591 zcmZ20yH-{@z?+$c0SGu47#ij?9{<9oy^oQBAq6NVJXxMstbS_nZZBp>5!=aUlaqyf zU0fU;51vxmDB_))Bjj@Q)&%p)H=80^4<5R7Du2U?_K2UXbxrpZR;TBs-7QpIU_9r| z-RkG_EQ^g^A8@ti)yPSl#uO&lzfJV@AI3s2pAN~7PJ4vjA7Kv+bC|zFeO^cUquzp( zyWO8$a2F1qb3nPgT~@We+k#5 z9~Z>D@z@`<+r@Tm$b`TwuP2+m9H*{q|32ZzlY*ywjGE8n*Y1&HJ(fL3vUvYjEA@BU z`Lkv0c~g!CTSNxyOX|(-wwNxw*DB8Qi+`4E`=1tkn?+bfz!ICa*{-p%L({@!4qhv;Dpy{6Fx}1@2&QlIx`AmGJ{K^Z H&F2IF_}m2! diff --git a/cmds/idmap2/tests/data/overlay/overlay-static-1.apk b/cmds/idmap2/tests/data/overlay/overlay-static-1.apk index 5b8a6e4a90ed68c406af3a5d8a5607bde9daf056..fd41182f84936793abd12a2ae9ae9923df23e8a0 100644 GIT binary patch delta 741 zcmeB`o+>RJ;LXg!00bOBq{zT`_K@2KMg|5EpqTLF|J-8rQzzN`OFIf2yu8kw!JT)2IU?zP zgzeX>A=m5Kr54RUTt9Dv-DS;te09G2f8L6kRV#e=Sbnvgn*GIj{d^y?H?7Nlb7z@b zux?28s?C=ftaq8t&a_+Vdw<)P z<41q>>7L#xpP>Ex&ch|ewG$Y2D&6&T{cuD$IsMJH2kV3O*lympdXn1V{W-htSgik{ zTOc<7lW>@c=%e@ztp`Mz%%`6;{h!_Cc)H#0jZF7SyH5-IV^;Am{S@;c=EeOiG56=6 z%6}d5W!IB>t~aCikk2O5#b?&I85h1k^Fb0dN;kh`)M8`?#_eP==C@#)jpZkZ-ps@* z!Ke&ms4uG&vi}Op1l2eQI5{rtH85lNOvn^xgfTfPfFS#w{fE>+L zT>E|l6V4YVU~&PaAUJq9*?~tz6R1R=A!hd)pl}B;MXAB1K@2`-29P!S6}dV3lNC9o zCNJj^1iNiFj}*&4pycFxY|`2R-i$!QK>(6EeO9jveFEe)07WIi;xOXZWO-gqumRq@ QQjDUL(|8rx?r?)-0j^dPSpWb4 delta 698 zcmbO#-78%m;LXg!00bNi3=Q)cpB;0$xQda1K?Eo!3>0MdM$gDNFb$i)%l`=80X>~nQr^YAc zzLfuPX2z@1rJR@de4kVK+*ZDLS)-Gy<;e`ce&$Q{OR8S0JatcC&1p(5;GcJpyMpz7 z!eI}01-9}BoO>EO_AHFbTD@%9@3NBaI+^NI|D4h*tbd5ce%xA}`Q-RZv%13{6+d=< zyOYVjU+H#f>lxmxDfxtF=CRUx-_jx4$bANV!ztrNT+ zzGTmT{pi?r;^A|?&#{#+F%C0$asK!Q*7Kq^=JPtY{&P{g_AN2rXzr`zE8i!2e_a@& z_t^6B@9jIg?pE&%|NE%TM*K_C@-@7Fd^VXjpINiZ*swP32PbOmZhp_G#mEed=E*Y5 zZ^1MV%TEx!nS)h=Q4z>cUwX%F1}g&t2=g&8G8Cm2=a&{Grxxoa78NINc4k|~$^lCz zlRt7>f(_B-kz%|(*@H&~%*zMzI3{=Tn8^VZc5RKaKMYJqbAV||8kEf7;K$^9JlYU9 f@Jca$nXJyM3DSV-0Jv%(gMV@!uOizOZjcxNCE6cD diff --git a/cmds/idmap2/tests/data/overlay/overlay-static-2.apk b/cmds/idmap2/tests/data/overlay/overlay-static-2.apk index 698a1fd6e70218b200b5bfdfc1d073381336c6da..b24765fc666a2c986faa5fac3a712dabb7a16679 100644 GIT binary patch delta 713 zcmeB`o+>RJ;LXg!00bOBq{#40LbQA{BLjm7P)vC8e{Qk*sgvyer5y#1-v8B8d!x|c zh?C2vMN51WwWmzE;L7D>xM+ccf;EfwKlS;|PxutMPSwm3netQRisnzI53|2Y#p^jW zS?`^F(>%W{EnPooO;lXbs@LIuQCA;X`u#NBz-ia4T)>)lK)!(cozAn4M!_8{`wzx% zIJa-3o7C#n3;+9>xYoxXoVVfMy8MdjAGv=YWM{AZ;$I@Z|NYMye_V9s=RVk;8oT}G zPXFF@RV$)iZMe*MPhxGT?1HM_JXiVd^PPFHG0ty(#oF7o*Emi0S6N^2|8(o#^sX1| zDSZ!jN4#8o?tU)LpLw8a+5LOv!g*h>o+!Ec;mx0GZ}PR4 zZ+UrpnqJJB?>BbM`OUEJ$z1E0qC6fUh47`;E4kiPCcW8oSL{z|*Y@R4cCX6R{BwHQ zY5h;D-ZQ0tY?{AekyFS1L+e=bR12p1to!M*J~+nmOXBm2$*&g6{5rAxSAdqjxP|zy z?X#}_-1%qjxgALl7P-EgbyMSvO0@B*Gg)@R-;eOfGoZ%m=2whbjLg93oh;7$7EH6V z`~=aPnOP;k5}W1N4zqH=62Rn_+?H}cj^-+^eZPTe;|mioMSv0s96Xuqz@s7$RHDxi zvwICtxC5AI)Zo$}h9L7~K~~|(TAYHDm-7gMZQacy#l*-07Jkphr4!)I2s9W3Ac@as q^}5g}Kwbk-R1z!>BmROkNl&)s9nh{| zpY3MFWVnOb{{gSd6W*&~?xkDrY+oJyW%7;SZ{k*mZy#O%s%!mS@8tV_pYzue)Ab#wq%JPVUQD zD^`78DtN`PP`3VuRan$T)mwU7uZ29DzF@D*U6+|Frd*s}lb-s+%yz2f#+j$>Keg#O zpLuuZd-Ce-C6DtiK6rD@@a-9s=Lu4INzdQ$&Wd`@R>rqAUhTvD83$jxtf;P?Y7{$F z=61dD?|3Qy%**+?*XMF>ZHb*=csjv4|IEV)hO!eFW-9&lbp3FUYh(Rl1@`|F9=(++ zu633A^gng=Y5qrD-Saj-Kb&`rtL^VkmTeDqHa%A}-gs^PsUx@S-uR{k*Y^Cj`?S(- z%BiWJ=Y0HoJLc%Wy?0iB+aY+KwfTl*HnaWYoU;nXtN;0&(Kr6Xf*QS=tGM?421e@_ zCSVi;>7vxlEKCxN%)pqREYJKFO!Kq+1kszhSs@ae)z}WRa=_BYe?D*e;CM{158@dU~w4nlX>!e9xbqb u9$qP?uPl=#S*5iR`hn_zR{zlzuA0HhzyQL0Fs)!(U~(R>BHI;i5C;IGd>WYm diff --git a/cmds/idmap2/tests/data/overlay/overlay.apk b/cmds/idmap2/tests/data/overlay/overlay.apk index 1db303ff05b54b93770d8b7a7cc7ef7b660049ae..870575efa10ccbb92506845b77c9816dd9695d5f 100644 GIT binary patch delta 610 zcmZ1|y->P7z?+$c0SGvNNRi?8yiHb{j&?LabshFXmA@o8()x@MzKp{)%lL~)yr{f|GTAle zFKFI*R#LuCsnK6JKdt=vvuoR$O{5AP5@jb#)Ng3{kQK4#yw|Byy1i4xYDIF7@{TKcn-(+7Kf{sx?{ndyA6&NowyDnkJ9Vw097lZ8 z)YCVd#cPeyLtZ~@y4dk5_Su%hTkS(w{o3qrRi@28vwKHkiE820$o`!Y-*#+yUHq_i z&bceEg0HQtzpn7ONZj`DoG;ZS7gIy$);1oO^*i$XQ$YjQ^%+0;O4*E-7rCs=@e2{$ zEB8Kl{nVMVmlqj4**~ptRqf6lQ!js?xm);Hw@*!IOjf&YSpSNm6PsWDG=1jt&feBE z`_#UVq4Nr-ZZ7)vnO!baYWAhISHuE)wN1S=Ox27$moDfkVHTvwQs6X zcr*F@MZ@P^-!k`l-wW5V%l{(d?SInT_-iy*n$r3DQ%iZKb9_(j{w(lD`f9mSG2gS5 z&(8dpMvihOMTX7)7_}IgfssF1oB1u6mS*`0qBo1PN`NIc8?hZ`Wrrq@$$z-5z^W{H Y?7?(3Pav2+&*KKBC3s!HbUd#U04nPL!TP7z?+$c0SGu47#ij?-ky{wvY(NGAq6NV3>08o38A9ui zNPl#!5lUtK(oy|rW`*KC&e^-FUHEKG3=eX~WNnWObaFW6K0TlDoWyp62l?Tfy!UV7 zJ*NCnJLaj;w+qK7oMFAnwj=3D@ZR%t%69y04_!FeFLWR9T zi|5UH!TV#5<=V4vGrAAW$d`Q_^1G-|J6+zWT)k)di|=hauJBpMybXRjBmMH-VzDo8 z?M-_l`k5cEwtBuw;Plb|wYG9odu3OKXH8$ReCj7-FW-)uFwGT4e?QdA3B}87yQ8S! z`cL!N>%fFP$7ULSk6yod(XLP19{$Kw(6()zYWj21#Y-_OcFtLG^`qCKu-_I_YL(?H zA3GndQMfee{6(YZUe_}BX4_p)uDSRk($H4*{+ToGs&6{)G)PW2j#0ZcUGP}r$PA49$=b|s!L&5XPY}IXoK*rWvDt|2Fe^JWc})Jp dZ3R|k$zu@000002mk;GApnSuYXRW_005W-kr*6*ZWBQihX2XhWHAYG zE(J)YKtdE0c8e$|fEI)jM1g25n_T4E%HANkqs$XTh-cs-cmOJ%fJfjB;5%n$*=12A z*wMdp=0BJD=j?2vR3BSXP)}brq~E3_yj(K z@8E#ikHIEYhg#`>sTLaR9a$;0mO5i??_6uRZRR2C6C!fG#2#tF`@}Oke|TSD&tj!B zDj&Hw#~#7$@?PN2SWk&MV%LdYV=albUFSsI{)ebi@%;CGL5HsO6{{6H9{Rk{IawpO z?Yu)W#xM)&jA3rTWQ?gRER+^19?+Ydk?D~Jj1~S<>dd@@e$+hhdK2cQ?>YEu z$J8s#Ssh2ErfZ@1e!eNbwKG|x&$nEqDLnSCGt(2!W*r(|(VPFtslMAj(S@#lLscJk z?H=ob^{$Gn-vQ}ENOg~SOCj{YUGTgW!kcyoORxe8UGzy^@RR4dSG0TE)kTfBXAAp) z(T?}u;@Z)FpAvc}a@V|b)?+1`(SOtLUBT@}Zl{rJcDIphIv%R{2TL8Ds3X*LsH$bZ zrIL8AW}el{J-_0&W4%_bUZ`p7ls$?6ylLBuTvDu^OC#5+X|cJ~(%ds?^uFwIxZ<1q z0#Hi>1ONa4000002q6GVX}IA)0ssI&0ssIG00ICGa%FRGb#h~6b1q?Wb7Qkk0!ji6 p000O800mLk;gh8VIRgkG0F&Va8UYfM`~)EefCK;l004ag6g&U` delta 619 zcmbQtwU|pHz?+$cfq?@E85-s@GQhz^37Pu7%MK!K|0C7caPFS4S43f{qmzh;XSaq% zgBXj>A_tSeLvd5O*B((=y7-Q|Lr3}p#R>+kc@6Flcpq3FPtNHHW9qLvKl6Xgv-yt; z7lp`M2VHQ8-?oJL>iNvW_t>`|RQ@3KR23ECda0S(0;IBVGMA5`4>zBzYQ z-_~o+^{KO7@kVNH4YNwleeWc_Blel$YhfiW+oSU`j{QDjTvcB&KS4ifsj-&)&g}>0 z9eDfk+=u6Dp1a6yeC?yZG3>~#b>55e{y2v$t@v5Je?j`XudJ(0t?j;BUXI?RmUp}I zc#2P=(JPtE}C?bY77_e5;=(^+@(pU&#rt@Zz) zm%IKe4qn++**Ei7s?1wGH~lNu`Sm~VMy$WQLR{)rRjB_X`}|wql&4S0etzjhsZ>uw(Y2f%or0Zavuv;a;5z_j2km$~Di0}}%S2=g&8 zGZdv3=a&{Grxxoa78NHmY_?d DgG3m) diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml index 7119d82830615..ebaf49c347621 100644 --- a/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml +++ b/cmds/idmap2/tests/data/system-overlay-invalid/res/values/values.xml @@ -26,6 +26,7 @@ policy_odm policy_oem policy_actor + policy_config_signature not_overlayable diff --git a/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk index bd990983693c96f3c9998032c34f0a55dc1525ee..a63daf86caf58b9e1ddc414ac9832239707ea404 100644 GIT binary patch delta 362 zcmZ3?_nD6`z?+$c0SGvNNReS9-wQ@(Al>dJ#Bl;B4#Ip4j0{Do#rdU0$*IM9iABZ9 z3``6>U@1nRMn(o15W&C=G6e*HY>&ygEaH;RKu!P<#{zL45Z3|mL?B)`c_xdFq_}uN zeokg`WqfjeURq{)d~s%aUSdgUQR?IgOyw+03XFR;^D_H03R2tbGF~Po0R|hOJ3y}I zo*c-mFUrUi!e9X8f<=I$4M6MwlyRPXhE;`e!Q{8Bixq$Y#J~l_K$;mu2Y53w0VyDW X1l{BXY<4`zK{xpon=#u1HjoMc=QKkA delta 331 zcmey&x0sJFz?+$c0SGu47#ij?ZsdExSP!HRFL?640w@l`d<={XMXAO4rA5i9#d?WF z#mNjz3_M^dMxaJU1{sDYK$;6=3J3rNT_7wlDFh^?fLIfV&4Ab$h(mxl1&GUmxE+Z3 z`SbEi;`7T=i*gbxCs#7bOkU4a#>T+Fq`=s*S(DkH(Uu|`CTB9~fK23LU}6$rumD;J zayZxILT2sB8(3L*Wq@3;2vD?U@(S)a{(x+PbuT!zUKGgT@tX-qm%+%ifhPsB9qKl60o{}b;7wv zj^}no|8l;1!1H3@!4H|cm9`c zJT~`t&pNZv#4ji2FD`y*6?jf#>fYyFm$MCzzdLhky|DB03yD|1_^n;Xq)rA@x7C(qpD3=Eoc>JNQj+rO*ESm)BZq zCSF?76Un+;`Ph-l?*jufq-^ zt>8TP{*R1*80>4VGnUQm z;qbGVY5jbjW$}BJMy)7LmBq{M^=_$O@G|4+BhwAMdIyXv7}r1GU9&l#`%Poe%&UfB!EJcD)H~ z_NB!SXB+3An9)4RF!SaNo)acA_Zj4SBEuU^nCoXge!D_I|1-d_)vsq%oqOiJ zE}m6&{`y_7)MC#5e!u(PvVWiN)vGrz + + + + diff --git a/cmds/idmap2/tests/data/target/res/values/values.xml b/cmds/idmap2/tests/data/target/res/values/values.xml index 5230e25e626be..00909a9e481c2 100644 --- a/cmds/idmap2/tests/data/target/res/values/values.xml +++ b/cmds/idmap2/tests/data/target/res/values/values.xml @@ -37,6 +37,7 @@ policy_system policy_system_vendor policy_actor + policy_config_signature other diff --git a/cmds/idmap2/tests/data/target/target-no-overlayable.apk b/cmds/idmap2/tests/data/target/target-no-overlayable.apk index 58504a74a83a0a4229a2d7b89da8624ff646a87d..cc3491de894d8adf7a5c66723579e48716f9f1bf 100644 GIT binary patch delta 421 zcmZn{x-P^Q;LXg!00bOBq{uLl?>;Y(QvJ=;qQK6;puj%ymlQ9E#Rycw$RNXzGx;X7 z^kf@G33Gp-NDL5X0&x`(cLDKSAYKc^M}YV|5Z?mgr$GDxh`#{w4+e(GUMyyk;^GDQ zIho0o@yYplX_@Kq#hK}Oi6x~)sgvtj$|f5zS+X!GFs|5K$dt|~m;tm}45$|jfb5dV zFPYU%!+_jmAT9vnMj)OD#7ls93lN_M;!8k$6Nn!G@pB-44aDy!JF?j0wR`?#1=a@6 z6rfrrAQqiGkttk|ktu}X2hd)y2vBszWL~z(j1HUUvNSJIA!h=A%0c1D>06Yy- Ab^rhX delta 351 zcmY+=ze~eV5Ww+!FF#C&7AaMvt)MtL)of0+=p+p^sC2GV7Y7H$#X)os1)=4(E-p?T zgi-`Ib#W1)4k}pC4*nHRe$zqlg%5YRJ08isXHT=4xazpV2}F)AO*`|ICKS4d8v|ct z;J1JBvq@$cF;bM6B$v!5hkQpvvk(P2;;chaf69ZhHy%uL5sj~@|n LcpivLEK}qc&^twS diff --git a/cmds/idmap2/tests/data/target/target.apk b/cmds/idmap2/tests/data/target/target.apk index c80e5eb65ff214ba5b7b15ce6dc28c311e6f2dde..4a58c5e28f4994a3ee32203631c0a1866cfbba16 100644 GIT binary patch delta 635 zcmaKq&r2IY6vt;~vq?5hqVBr+(I`ZVs25ui1hJ`sUJ43&5OXO=Sfd2g$gUCf&?0ye zFY$pl(L)ct^bpeg1@=}Cwos%8QAE(v77M-Prr%i-np0=?!`t_L@68*A_oMeqUwCR< z@h~huzAjb@Unnr;KLI`jo7xnC(^keLVaA!Aa|%V<$~gmB+p(BnK{v!v&shiCCQVJy zD-j!=gz_5X!6w)N2jBzv1kS(}_zh}6!4W?2h%mBM1)+L*Np%k%k#Stq}+ zoLw#2IXV%?sz~y5OJ!fNdD|+AqBy`^_+O{E+B-4>*8(eG3zWb+@DY3lU%_{932wko za0mWUQ62kl^EK-CKE)+7-Ysno6#|%4Rx&0R)2xOYxC+$wAdSdN+VxHFG=1}3@DNq~ zRtQhcOaQBxWNMBUse9o{Nqgeqx0PxLCP3$HiBvliZ&lIC+L0sAMhiUqKh0a$LQR_N zAoDaD)D80M!Omn|@ik?o>zbdI^k{dZhb)w}USu|g11_e4_Vh_P9dxa~aBYt<8f=~t fS~Q-yfkWf5_@&d49*azktMZ1-gMAPC+>qV_-7{~x delta 529 zcmYk(KS)AB90%~b_k8M!KH@#AK?%#D8jKpsAuOpOBEz7_)ey-c$P{Tzs3~ZWUo8!_ zI7FMdv_!N-LlKep^4n;vrO?^+SJos>T-}}RR_p9{Oy7ieU)xyy1jOF)vL4Q=y zmEIkE9R0ySEtqOyOwt)=nPhf3mq{eEeG8dvf+@^dU*b5=nU|$7XqA`AhH;ugia$7p zNfhFchIJq~gcG=c8+d>kyut^z>}f;vrsXKEPTLq$eEd@{AE_D6=P00fD6Dx0C$V)N z7GV`OVHZkp45x4oS5SdlxT76y6c-n1+nN_~Bnr5x(-w0*b9q5CbGV9J_{0)|IuN(*z#Td81}!itf69w)6BX2_0R zzw3C?`ii3|^EEPSQx42a??7<> mNamedActors = null; + // Package name of the package pre-installed on a read-only + // partition that is used to verify if an overlay package fulfills + // the 'config_signature' policy by comparing their signatures: + // if the overlay package is signed with the same certificate as + // the package declared in 'config-signature' tag, then the + // overlay package fulfills the 'config_signature' policy. + private String mOverlayConfigSignaturePackage; + public static SystemConfig getInstance() { if (!isSystemProcess()) { Slog.wtf(TAG, "SystemConfig is being accessed by a process other than " @@ -433,6 +442,12 @@ public class SystemConfig { return mNamedActors != null ? mNamedActors : Collections.emptyMap(); } + @Nullable + public String getOverlayConfigSignaturePackage() { + return TextUtils.isEmpty(mOverlayConfigSignaturePackage) + ? null : mOverlayConfigSignaturePackage; + } + /** * Only use for testing. Do NOT use in production code. * @param readPermissions false to create an empty SystemConfig; true to read the permissions. @@ -1151,6 +1166,27 @@ public class SystemConfig { } XmlUtils.skipCurrentTag(parser); } break; + case "overlay-config-signature": { + if (allowAll) { + String pkgName = parser.getAttributeValue(null, "package"); + if (pkgName == null) { + Slog.w(TAG, "<" + name + "> without package in " + permFile + + " at " + parser.getPositionDescription()); + } else { + if (TextUtils.isEmpty(mOverlayConfigSignaturePackage)) { + mOverlayConfigSignaturePackage = pkgName.intern(); + } else { + throw new IllegalStateException("Reference signature package " + + "defined as both " + + mOverlayConfigSignaturePackage + + " and " + pkgName); + } + } + } else { + logNotAllowedInPartition(name, permFile, parser); + } + XmlUtils.skipCurrentTag(parser); + } break; case "rollback-whitelisted-app": { String pkgname = parser.getAttributeValue(null, "package"); if (pkgname == null) { diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index e351a46d633ac..e10a7f3f5c61b 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -1717,6 +1717,10 @@ struct ResTable_overlayable_policy_header // The overlay must be signed with the same signature as the actor declared for the target // resource ACTOR_SIGNATURE = 0x00000080, + + // The overlay must be signed with the same signature as the reference package declared + // in the SystemConfig + CONFIG_SIGNATURE = 0x00000100, }; using PolicyBitmask = uint32_t; diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index b241bd16d3eea..ad1986a6669fb 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -69,6 +69,7 @@ public abstract class PackageManagerInternal { public static final int PACKAGE_WIFI = 13; public static final int PACKAGE_COMPANION = 14; public static final int PACKAGE_RETAIL_DEMO = 15; + public static final int PACKAGE_OVERLAY_CONFIG_SIGNATURE = 16; @IntDef(flag = true, prefix = "RESOLVE_", value = { RESOLVE_NON_BROWSER_ONLY, diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java index d6b1b27360caa..cb6e960b721de 100644 --- a/services/core/java/com/android/server/om/IdmapManager.java +++ b/services/core/java/com/android/server/om/IdmapManager.java @@ -27,6 +27,7 @@ import android.content.pm.PackageInfo; import android.os.Build.VERSION_CODES; import android.os.OverlayablePolicy; import android.os.SystemProperties; +import android.text.TextUtils; import android.util.Slog; import java.io.IOException; @@ -53,11 +54,20 @@ final class IdmapManager { } private final IdmapDaemon mIdmapDaemon; - private final OverlayableInfoCallback mOverlayableCallback; + private final PackageManagerHelper mPackageManager; - IdmapManager(final IdmapDaemon idmapDaemon, final OverlayableInfoCallback verifyCallback) { - mOverlayableCallback = verifyCallback; + /** + * Package name of the reference package defined in 'config-signature' tag of + * SystemConfig or empty String if tag not defined. This package is vetted on scan by + * PackageManagerService that it's a system package and is used to check if overlay matches + * its signature in order to fulfill the config_signature policy. + */ + private final String mConfigSignaturePackage; + + IdmapManager(final IdmapDaemon idmapDaemon, final PackageManagerHelper packageManager) { + mPackageManager = packageManager; mIdmapDaemon = idmapDaemon; + mConfigSignaturePackage = packageManager.getConfigSignaturePackage(); } /** @@ -139,7 +149,7 @@ final class IdmapManager { int fulfilledPolicies = OverlayablePolicy.PUBLIC; // Overlay matches target signature - if (mOverlayableCallback.signaturesMatching(targetPackage.packageName, + if (mPackageManager.signaturesMatching(targetPackage.packageName, overlayPackage.packageName, userId)) { fulfilledPolicies |= OverlayablePolicy.SIGNATURE; } @@ -149,6 +159,16 @@ final class IdmapManager { fulfilledPolicies |= OverlayablePolicy.ACTOR_SIGNATURE; } + // If SystemConfig defines 'config-signature' package, given that + // this package is vetted by OverlayManagerService that it's a + // preinstalled package, check if overlay matches its signature. + if (!TextUtils.isEmpty(mConfigSignaturePackage) + && mPackageManager.signaturesMatching(mConfigSignaturePackage, + overlayPackage.packageName, + userId)) { + fulfilledPolicies |= OverlayablePolicy.CONFIG_SIGNATURE; + } + // Vendor partition (/vendor) if (ai.isVendor()) { return fulfilledPolicies | OverlayablePolicy.VENDOR_PARTITION; @@ -183,12 +203,12 @@ final class IdmapManager { String targetOverlayableName = overlayPackage.targetOverlayableName; if (targetOverlayableName != null) { try { - OverlayableInfo overlayableInfo = mOverlayableCallback.getOverlayableForTarget( + OverlayableInfo overlayableInfo = mPackageManager.getOverlayableForTarget( targetPackage.packageName, targetOverlayableName, userId); if (overlayableInfo != null && overlayableInfo.actor != null) { String actorPackageName = OverlayActorEnforcer.getPackageNameForActor( - overlayableInfo.actor, mOverlayableCallback.getNamedActors()).first; - if (mOverlayableCallback.signaturesMatching(actorPackageName, + overlayableInfo.actor, mPackageManager.getNamedActors()).first; + if (mPackageManager.signaturesMatching(actorPackageName, overlayPackage.packageName, userId)) { return true; } diff --git a/services/core/java/com/android/server/om/OverlayActorEnforcer.java b/services/core/java/com/android/server/om/OverlayActorEnforcer.java index 2bc34998785b3..8c03c6ce3092b 100644 --- a/services/core/java/com/android/server/om/OverlayActorEnforcer.java +++ b/services/core/java/com/android/server/om/OverlayActorEnforcer.java @@ -45,7 +45,7 @@ public class OverlayActorEnforcer { // By default, the reason is not logged to prevent leaks of why it failed private static final boolean DEBUG_REASON = false; - private final OverlayableInfoCallback mOverlayableCallback; + private final PackageManagerHelper mPackageManager; /** * @return nullable actor result with {@link ActorState} failure status @@ -79,8 +79,8 @@ public class OverlayActorEnforcer { return Pair.create(packageName, ActorState.ALLOWED); } - public OverlayActorEnforcer(@NonNull OverlayableInfoCallback overlayableCallback) { - mOverlayableCallback = overlayableCallback; + public OverlayActorEnforcer(@NonNull PackageManagerHelper packageManager) { + mPackageManager = packageManager; } void enforceActor(@NonNull OverlayInfo overlayInfo, @NonNull String methodName, @@ -110,7 +110,7 @@ public class OverlayActorEnforcer { return ActorState.ALLOWED; } - String[] callingPackageNames = mOverlayableCallback.getPackagesForUid(callingUid); + String[] callingPackageNames = mPackageManager.getPackagesForUid(callingUid); if (ArrayUtils.isEmpty(callingPackageNames)) { return ActorState.NO_PACKAGES_FOR_UID; } @@ -125,12 +125,12 @@ public class OverlayActorEnforcer { if (TextUtils.isEmpty(targetOverlayableName)) { try { - if (mOverlayableCallback.doesTargetDefineOverlayable(targetPackageName, userId)) { + if (mPackageManager.doesTargetDefineOverlayable(targetPackageName, userId)) { return ActorState.MISSING_TARGET_OVERLAYABLE_NAME; } else { // If there's no overlayable defined, fallback to the legacy permission check try { - mOverlayableCallback.enforcePermission( + mPackageManager.enforcePermission( android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName); // If the previous method didn't throw, check passed @@ -146,7 +146,7 @@ public class OverlayActorEnforcer { OverlayableInfo targetOverlayable; try { - targetOverlayable = mOverlayableCallback.getOverlayableForTarget(targetPackageName, + targetOverlayable = mPackageManager.getOverlayableForTarget(targetPackageName, targetOverlayableName, userId); } catch (IOException e) { return ActorState.UNABLE_TO_GET_TARGET; @@ -160,7 +160,7 @@ public class OverlayActorEnforcer { if (TextUtils.isEmpty(actor)) { // If there's no actor defined, fallback to the legacy permission check try { - mOverlayableCallback.enforcePermission( + mPackageManager.enforcePermission( android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName); // If the previous method didn't throw, check passed @@ -170,7 +170,7 @@ public class OverlayActorEnforcer { } } - Map> namedActors = mOverlayableCallback.getNamedActors(); + Map> namedActors = mPackageManager.getNamedActors(); Pair actorUriPair = getPackageNameForActor(actor, namedActors); ActorState actorUriState = actorUriPair.second; if (actorUriState != ActorState.ALLOWED) { @@ -178,7 +178,7 @@ public class OverlayActorEnforcer { } String packageName = actorUriPair.first; - PackageInfo packageInfo = mOverlayableCallback.getPackageInfo(packageName, userId); + PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, userId); if (packageInfo == null) { return ActorState.MISSING_APP_INFO; } diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 3968153998749..0f8c9c789a3f5 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -1053,8 +1053,7 @@ public final class OverlayManagerService extends SystemService { } } - private static final class PackageManagerHelperImpl implements PackageManagerHelper, - OverlayableInfoCallback { + private static final class PackageManagerHelperImpl implements PackageManagerHelper { private final Context mContext; private final IPackageManager mPackageManager; @@ -1127,6 +1126,14 @@ public final class OverlayManagerService extends SystemService { return overlays; } + @Override + public String getConfigSignaturePackage() { + final String[] pkgs = mPackageManagerInternal.getKnownPackageNames( + PackageManagerInternal.PACKAGE_OVERLAY_CONFIG_SIGNATURE, + UserHandle.USER_SYSTEM); + return (pkgs.length == 0) ? null : pkgs[0]; + } + @Nullable @Override public OverlayableInfo getOverlayableForTarget(@NonNull String packageName, diff --git a/services/core/java/com/android/server/om/OverlayableInfoCallback.java b/services/core/java/com/android/server/om/OverlayableInfoCallback.java deleted file mode 100644 index 5066ecdd6316f..0000000000000 --- a/services/core/java/com/android/server/om/OverlayableInfoCallback.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2020 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. - */ - -package com.android.server.om; - - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.om.OverlayableInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; - -import com.android.server.pm.PackageManagerServiceUtils; - -import java.io.IOException; -import java.util.Map; - -/** - * Delegate to the system for querying information about overlayables and packages. - */ -public interface OverlayableInfoCallback { - - /** - * Read from the APK and AndroidManifest of a package to return the overlayable defined for - * a given name. - * - * @throws IOException if the target can't be read - */ - @Nullable - OverlayableInfo getOverlayableForTarget(@NonNull String packageName, - @NonNull String targetOverlayableName, int userId) - throws IOException; - - /** - * @see PackageManager#getPackagesForUid(int) - */ - @Nullable - String[] getPackagesForUid(int uid); - - /** - * @param userId user to filter package visibility by - * @see PackageManager#getPackageInfo(String, int) - */ - @Nullable - PackageInfo getPackageInfo(@NonNull String packageName, int userId); - - /** - * @return map of system pre-defined, uniquely named actors; keys are namespace, - * value maps actor name to package name - */ - @NonNull - Map> getNamedActors(); - - /** - * @return true if the target package has declared an overlayable - */ - boolean doesTargetDefineOverlayable(String targetPackageName, int userId) throws IOException; - - /** - * @throws SecurityException containing message if the caller doesn't have the given - * permission - */ - void enforcePermission(String permission, String message) throws SecurityException; - - /** - * @return true if {@link PackageManagerServiceUtils#compareSignatures} run on both packages - * in the system returns {@link PackageManager#SIGNATURE_MATCH} - */ - boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId); -} diff --git a/services/core/java/com/android/server/om/PackageManagerHelper.java b/services/core/java/com/android/server/om/PackageManagerHelper.java index ec9c5e64e390f..b1a8b4ee4d9fd 100644 --- a/services/core/java/com/android/server/om/PackageManagerHelper.java +++ b/services/core/java/com/android/server/om/PackageManagerHelper.java @@ -17,11 +17,17 @@ package com.android.server.om; import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.om.OverlayableInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; +import com.android.server.pm.PackageManagerServiceUtils; + +import java.io.IOException; import java.util.List; +import java.util.Map; /** * Delegate for {@link PackageManager} and {@link PackageManagerInternal} functionality, @@ -30,7 +36,65 @@ import java.util.List; * @hide */ interface PackageManagerHelper { - PackageInfo getPackageInfo(@NonNull String packageName, int userId); - boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId); + /** + * @return true if the target package has declared an overlayable + */ + boolean doesTargetDefineOverlayable(String targetPackageName, int userId) throws IOException; + + /** + * @throws SecurityException containing message if the caller doesn't have the given + * permission + */ + void enforcePermission(String permission, String message) throws SecurityException; + + /** + * Returns the package name of the reference package defined in 'overlay-config-signature' tag + * of SystemConfig. This package is vetted on scan by PackageManagerService that it's a system + * package and is used to check if overlay matches its signature in order to fulfill the + * config_signature policy. + */ + @Nullable + String getConfigSignaturePackage(); + + /** + * @return map of system pre-defined, uniquely named actors; keys are namespace, + * value maps actor name to package name + */ + @NonNull + Map> getNamedActors(); + + /** + * @see PackageManagerInternal#getOverlayPackages(int) + */ List getOverlayPackages(int userId); + + /** + * Read from the APK and AndroidManifest of a package to return the overlayable defined for + * a given name. + * + * @throws IOException if the target can't be read + */ + @Nullable + OverlayableInfo getOverlayableForTarget(@NonNull String packageName, + @NonNull String targetOverlayableName, int userId) + throws IOException; + + /** + * @see PackageManager#getPackagesForUid(int) + */ + @Nullable + String[] getPackagesForUid(int uid); + + /** + * @param userId user to filter package visibility by + * @see PackageManager#getPackageInfo(String, int) + */ + @Nullable + PackageInfo getPackageInfo(@NonNull String packageName, int userId); + + /** + * @return true if {@link PackageManagerServiceUtils#compareSignatures} run on both packages + * in the system returns {@link PackageManager#SIGNATURE_MATCH} + */ + boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 4f0c707a1dae8..fddd46a9c026b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -120,6 +120,7 @@ import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet; import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; import static com.android.server.pm.InstructionSets.getPreferredInstructionSet; import static com.android.server.pm.PackageManagerServiceCompilerMapping.getDefaultCompilerFilter; +import static com.android.server.pm.PackageManagerServiceUtils.comparePackageSignatures; import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures; import static com.android.server.pm.PackageManagerServiceUtils.compressedFileExists; import static com.android.server.pm.PackageManagerServiceUtils.decompressFile; @@ -1114,6 +1115,7 @@ public class PackageManagerService extends IPackageManager.Stub public @Nullable String storageManagerPackage; public @Nullable String defaultTextClassifierPackage; public @Nullable String systemTextClassifierPackage; + public @Nullable String overlayConfigSignaturePackage; public ViewCompiler viewCompiler; public @Nullable String wellbeingPackage; public @Nullable String retailDemoPackage; @@ -1646,6 +1648,7 @@ public class PackageManagerService extends IPackageManager.Stub final @Nullable String mServicesExtensionPackageName; final @Nullable String mSharedSystemSharedLibraryPackageName; final @Nullable String mRetailDemoPackage; + final @Nullable String mOverlayConfigSignaturePackage; private final PackageUsage mPackageUsage = new PackageUsage(); private final CompilerStats mCompilerStats = new CompilerStats(); @@ -2808,6 +2811,7 @@ public class PackageManagerService extends IPackageManager.Stub mIncidentReportApproverPackage = testParams.incidentReportApproverPackage; mServicesExtensionPackageName = testParams.servicesExtensionPackageName; mSharedSystemSharedLibraryPackageName = testParams.sharedSystemSharedLibraryPackageName; + mOverlayConfigSignaturePackage = testParams.overlayConfigSignaturePackage; mResolveComponentName = testParams.resolveComponentName; mPackages.putAll(testParams.packages); @@ -3373,6 +3377,7 @@ public class PackageManagerService extends IPackageManager.Stub mAppPredictionServicePackage = getAppPredictionServicePackageName(); mIncidentReportApproverPackage = getIncidentReportApproverPackageName(); mRetailDemoPackage = getRetailDemoPackageName(); + mOverlayConfigSignaturePackage = getOverlayConfigSignaturePackageName(); // Now that we know all of the shared libraries, update all clients to have // the correct library paths. @@ -12096,12 +12101,8 @@ public class PackageManagerService extends IPackageManager.Stub if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) { // Exempt SharedUsers signed with the platform key. PackageSetting platformPkgSetting = mSettings.mPackages.get("android"); - if ((platformPkgSetting.signatures.mSigningDetails - != PackageParser.SigningDetails.UNKNOWN) - && (compareSignatures( - platformPkgSetting.signatures.mSigningDetails.signatures, - pkg.getSigningDetails().signatures) - != PackageManager.SIGNATURE_MATCH)) { + if (!comparePackageSignatures(platformPkgSetting, + pkg.getSigningDetails().signatures)) { throw new PackageManagerException("Apps that share a user with a " + "privileged app must themselves be marked as privileged. " + pkg.getPackageName() + " shares privileged user " + @@ -12148,12 +12149,8 @@ public class PackageManagerService extends IPackageManager.Stub if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.Q) { final PackageSetting platformPkgSetting = mSettings.getPackageLPr("android"); - if ((platformPkgSetting.signatures.mSigningDetails - != PackageParser.SigningDetails.UNKNOWN) - && (compareSignatures( - platformPkgSetting.signatures.mSigningDetails.signatures, - pkg.getSigningDetails().signatures) - != PackageManager.SIGNATURE_MATCH)) { + if (!comparePackageSignatures(platformPkgSetting, + pkg.getSigningDetails().signatures)) { throw new PackageManagerException("Overlay " + pkg.getPackageName() + " must target Q or later, " @@ -12162,24 +12159,35 @@ public class PackageManagerService extends IPackageManager.Stub } // A non-preloaded overlay package, without , will - // only be used if it is signed with the same certificate as its target. If the - // target is already installed, check this here to augment the last line of - // defence which is OMS. + // only be used if it is signed with the same certificate as its target OR if + // it is signed with the same certificate as a reference package declared + // in 'config-signature' tag of SystemConfig. + // If the target is already installed or 'config-signature' tag in SystemConfig + // is set, check this here to augment the last line of defence which is OMS. if (pkg.getOverlayTargetName() == null) { final PackageSetting targetPkgSetting = mSettings.getPackageLPr(pkg.getOverlayTarget()); if (targetPkgSetting != null) { - if ((targetPkgSetting.signatures.mSigningDetails - != PackageParser.SigningDetails.UNKNOWN) - && (compareSignatures( - targetPkgSetting.signatures.mSigningDetails.signatures, - pkg.getSigningDetails().signatures) - != PackageManager.SIGNATURE_MATCH)) { - throw new PackageManagerException("Overlay " - + pkg.getPackageName() + " and target " - + pkg.getOverlayTarget() + " signed with" - + " different certificates, and the overlay lacks" - + " "); + if (!comparePackageSignatures(targetPkgSetting, + pkg.getSigningDetails().signatures)) { + // check reference signature + if (mOverlayConfigSignaturePackage == null) { + throw new PackageManagerException("Overlay " + + pkg.getPackageName() + " and target " + + pkg.getOverlayTarget() + " signed with" + + " different certificates, and the overlay lacks" + + " "); + } + final PackageSetting refPkgSetting = + mSettings.getPackageLPr(mOverlayConfigSignaturePackage); + if (!comparePackageSignatures(refPkgSetting, + pkg.getSigningDetails().signatures)) { + throw new PackageManagerException("Overlay " + + pkg.getPackageName() + " signed with a different " + + "certificate than both the reference package and " + + "target " + pkg.getOverlayTarget() + ", and the " + + "overlay lacks "); + } } } } @@ -20712,6 +20720,11 @@ public class PackageManagerService extends IPackageManager.Stub return ensureSystemPackageName(contentCaptureServiceComponentName.getPackageName()); } + public String getOverlayConfigSignaturePackageName() { + return ensureSystemPackageName(SystemConfig.getInstance() + .getOverlayConfigSignaturePackage()); + } + @Nullable private String getRetailDemoPackageName() { final String predefinedPkgName = mContext.getString(R.string.config_retailDemoPackage); @@ -24228,6 +24241,8 @@ public class PackageManagerService extends IPackageManager.Stub return TextUtils.isEmpty(mRetailDemoPackage) ? ArrayUtils.emptyArray(String.class) : new String[] {mRetailDemoPackage}; + case PackageManagerInternal.PACKAGE_OVERLAY_CONFIG_SIGNATURE: + return filterOnlySystemPackages(getOverlayConfigSignaturePackageName()); default: return ArrayUtils.emptyArray(String.class); } diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index 03f4708c09c4a..de0e4b53adabf 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -487,6 +487,18 @@ public class PackageManagerServiceUtils { return PackageManager.SIGNATURE_NO_MATCH; } + /** + * Returns true if the signature set of the package is identical to the specified signature + * set or if the signing details of the package are unknown. + */ + public static boolean comparePackageSignatures(PackageSetting pkgSetting, + Signature[] signatures) { + return pkgSetting.signatures.mSigningDetails + == PackageParser.SigningDetails.UNKNOWN + || compareSignatures(pkgSetting.signatures.mSigningDetails.signatures, signatures) + == PackageManager.SIGNATURE_MATCH; + } + /** * Used for backward compatibility to make sure any packages with * certificate chains get upgraded to the new style. {@code existingSigs} diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt index e08eea298aaf7..08392737350af 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt +++ b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt @@ -160,7 +160,7 @@ class OverlayActorEnforcerTests { private val hasPermission: Boolean = false, private val overlayableInfo: OverlayableInfo? = null, private vararg val packageNames: String = arrayOf("com.test.actor.one") - ) : OverlayableInfoCallback { + ) : PackageManagerHelper { override fun getNamedActors() = if (isActor) { mapOf(NAMESPACE to mapOf(ACTOR_NAME to ACTOR_PKG_NAME)) @@ -195,6 +195,14 @@ class OverlayActorEnforcerTests { } } + override fun getConfigSignaturePackage(): String { + throw UnsupportedOperationException() + } + + override fun getOverlayPackages(userId: Int): MutableList { + throw UnsupportedOperationException() + } + override fun signaturesMatching(pkgName1: String, pkgName2: String, userId: Int): Boolean { throw UnsupportedOperationException() } diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java index b7692f912e393..e281f2b206f59 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java @@ -44,9 +44,9 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI @Test public void testUpdateOverlaysForUser() { final OverlayManagerServiceImpl impl = getImpl(); - addSystemPackage(target(TARGET), USER); - addSystemPackage(target("some.other.target"), USER);; - addSystemPackage(overlay(OVERLAY, TARGET), USER); + addPackage(target(TARGET), USER); + addPackage(target("some.other.target"), USER); + addPackage(overlay(OVERLAY, TARGET), USER); // do nothing, expect no change final List a = impl.updateOverlaysForUser(USER); @@ -54,7 +54,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI assertTrue(a.contains(TARGET)); // upgrade overlay, keep target - addSystemPackage(overlay(OVERLAY, TARGET), USER); + addPackage(overlay(OVERLAY, TARGET), USER); final List b = impl.updateOverlaysForUser(USER); assertEquals(1, b.size()); @@ -66,7 +66,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI assertTrue(c.contains(TARGET)); // upgrade overlay, switch to new target - addSystemPackage(overlay(OVERLAY, "some.other.target"), USER); + addPackage(overlay(OVERLAY, "some.other.target"), USER); final List d = impl.updateOverlaysForUser(USER); assertEquals(2, d.size()); assertTrue(d.containsAll(Arrays.asList(TARGET, "some.other.target"))); diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java index f4c5506c7001b..c1d862ab2ad4b 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java @@ -19,6 +19,7 @@ package com.android.server.om; import static android.content.om.OverlayInfo.STATE_DISABLED; import static android.content.om.OverlayInfo.STATE_ENABLED; import static android.content.om.OverlayInfo.STATE_MISSING_TARGET; +import static android.os.OverlayablePolicy.CONFIG_SIGNATURE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -49,6 +50,10 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes private static final String OVERLAY3 = OVERLAY + "3"; private static final int USER3 = USER2 + 1; + private static final String CONFIG_SIGNATURE_REFERENCE_PKG = "com.dummy.ref"; + private static final String CERT_CONFIG_OK = "config_certificate_ok"; + private static final String CERT_CONFIG_NOK = "config_certificate_nok"; + @Test public void testGetOverlayInfo() { installNewPackage(overlay(OVERLAY, TARGET), USER); @@ -204,4 +209,87 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes impl.setEnabled(OVERLAY, true, USER); assertEquals(0, listener.count); } + + @Test + public void testConfigSignaturePolicyOk() { + setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG); + reinitializeImpl(); + + addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER); + installNewPackage(target(TARGET), USER); + installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_OK), USER); + + final DummyIdmapDaemon idmapd = getIdmapd(); + final DummyDeviceState state = getState(); + String overlayPath = state.select(OVERLAY, USER).apkPath; + assertTrue(idmapd.idmapExists(overlayPath, USER)); + + DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + assertTrue((CONFIG_SIGNATURE & idmap.policies) == CONFIG_SIGNATURE); + } + + @Test + public void testConfigSignaturePolicyCertNok() { + setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG); + reinitializeImpl(); + + addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER); + installNewPackage(target(TARGET), USER); + installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); + + final DummyIdmapDaemon idmapd = getIdmapd(); + final DummyDeviceState state = getState(); + String overlayPath = state.select(OVERLAY, USER).apkPath; + assertTrue(idmapd.idmapExists(overlayPath, USER)); + + DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0); + } + + @Test + public void testConfigSignaturePolicyNoConfig() { + addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER); + installNewPackage(target(TARGET), USER); + installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); + + final DummyIdmapDaemon idmapd = getIdmapd(); + final DummyDeviceState state = getState(); + String overlayPath = state.select(OVERLAY, USER).apkPath; + assertTrue(idmapd.idmapExists(overlayPath, USER)); + + DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0); + } + + @Test + public void testConfigSignaturePolicyNoRefPkg() { + installNewPackage(target(TARGET), USER); + installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); + + final DummyIdmapDaemon idmapd = getIdmapd(); + final DummyDeviceState state = getState(); + String overlayPath = state.select(OVERLAY, USER).apkPath; + assertTrue(idmapd.idmapExists(overlayPath, USER)); + + DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0); + } + + @Test + public void testConfigSignaturePolicyRefPkgNotSystem() { + setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG); + reinitializeImpl(); + + addPackage(app(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER); + installNewPackage(target(TARGET), USER); + installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); + + final DummyIdmapDaemon idmapd = getIdmapd(); + final DummyDeviceState state = getState(); + String overlayPath = state.select(OVERLAY, USER).apkPath; + assertTrue(idmapd.idmapExists(overlayPath, USER)); + + DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0); + } } diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java index 733310b2508a2..2faf29f453759 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java @@ -27,6 +27,7 @@ import android.content.om.OverlayInfo.State; import android.content.om.OverlayableInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -52,6 +53,7 @@ class OverlayManagerServiceImplTestsBase { private DummyPackageManagerHelper mPackageManager; private DummyIdmapDaemon mIdmapDaemon; private OverlayConfig mOverlayConfig; + private String mConfigSignaturePackageName; @Before public void setUp() { @@ -83,6 +85,18 @@ class OverlayManagerServiceImplTestsBase { return mListener; } + DummyIdmapDaemon getIdmapd() { + return mIdmapDaemon; + } + + DummyDeviceState getState() { + return mState; + } + + void setConfigSignaturePackageName(String packageName) { + mConfigSignaturePackageName = packageName; + } + void assertState(@State int expected, final String overlayPackageName, int userId) { final OverlayInfo info = mImpl.getOverlayInfo(overlayPackageName, userId); if (info == null) { @@ -102,9 +116,14 @@ class OverlayManagerServiceImplTestsBase { assertEquals(expected, actual); } + DummyDeviceState.PackageBuilder app(String packageName) { + return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */, + null /* targetOverlayableName */, "data"); + } + DummyDeviceState.PackageBuilder target(String packageName) { return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */, - null /* targetOverlayableName */); + null /* targetOverlayableName */, ""); } DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName) { @@ -114,10 +133,10 @@ class OverlayManagerServiceImplTestsBase { DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName, String targetOverlayableName) { return new DummyDeviceState.PackageBuilder(packageName, targetPackageName, - targetOverlayableName); + targetOverlayableName, ""); } - void addSystemPackage(DummyDeviceState.PackageBuilder pkg, int userId) { + void addPackage(DummyDeviceState.PackageBuilder pkg, int userId) { mState.add(pkg, userId); } @@ -242,15 +261,17 @@ class OverlayManagerServiceImplTestsBase { private String packageName; private String targetPackage; private String certificate = "[default]"; + private String partition; private int version = 0; private ArrayList overlayableNames = new ArrayList<>(); private String targetOverlayableName; private PackageBuilder(String packageName, String targetPackage, - String targetOverlayableName) { + String targetOverlayableName, String partition) { this.packageName = packageName; this.targetPackage = targetPackage; this.targetOverlayableName = targetOverlayableName; + this.partition = partition; } PackageBuilder setCertificate(String certificate) { @@ -269,9 +290,19 @@ class OverlayManagerServiceImplTestsBase { } Package build() { - final String apkPath = String.format("%s/%s/base.apk", - targetPackage == null ? "/system/app/:" : "/vendor/overlay/:", - packageName); + String path = ""; + if (TextUtils.isEmpty(partition)) { + if (targetPackage == null) { + path = "/system/app"; + } else { + path = "/vendor/overlay"; + } + } else { + String type = targetPackage == null ? "app" : "overlay"; + path = String.format("%s/%s", partition, type); + } + + final String apkPath = String.format("%s/%s/base.apk", path, packageName); final Package newPackage = new Package(packageName, targetPackage, targetOverlayableName, version, apkPath, certificate); newPackage.overlayableNames.addAll(overlayableNames); @@ -302,8 +333,7 @@ class OverlayManagerServiceImplTestsBase { } } - static final class DummyPackageManagerHelper implements PackageManagerHelper, - OverlayableInfoCallback { + final class DummyPackageManagerHelper implements PackageManagerHelper { private final DummyDeviceState mState; private DummyPackageManagerHelper(DummyDeviceState state) { @@ -343,6 +373,11 @@ class OverlayManagerServiceImplTestsBase { .collect(Collectors.toList()); } + @Override + public @NonNull String getConfigSignaturePackage() { + return mConfigSignaturePackageName; + } + @Nullable @Override public OverlayableInfo getOverlayableForTarget(@NonNull String packageName, diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto index ab9ce66b0ae3a..b1e1a77e12240 100644 --- a/tools/aapt2/Resources.proto +++ b/tools/aapt2/Resources.proto @@ -168,6 +168,7 @@ message OverlayableItem { ODM = 6; OEM = 7; ACTOR = 8; + CONFIG_SIGNATURE = 9; } // The location of the declaration in source. diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp index 59627ce579afe..6932baf76c75c 100644 --- a/tools/aapt2/format/binary/TableFlattener_test.cpp +++ b/tools/aapt2/format/binary/TableFlattener_test.cpp @@ -776,6 +776,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { OverlayableItem overlayable_item_three(group_one); overlayable_item_three.policies |= PolicyFlags::SIGNATURE; overlayable_item_three.policies |= PolicyFlags::ACTOR_SIGNATURE; + overlayable_item_three.policies |= PolicyFlags::CONFIG_SIGNATURE; std::unique_ptr table = test::ResourceTableBuilder() @@ -830,7 +831,8 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { EXPECT_EQ(result_overlayable.overlayable->name, "OtherName"); EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization"); EXPECT_EQ(result_overlayable.policies, PolicyFlags::SIGNATURE - | PolicyFlags::ACTOR_SIGNATURE); + | PolicyFlags::ACTOR_SIGNATURE + | PolicyFlags::CONFIG_SIGNATURE); } TEST_F(TableFlattenerTest, FlattenOverlayableNoPolicyFails) { diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp index 2fd01d7f3dee4..7eb8ebd9a0433 100644 --- a/tools/aapt2/format/proto/ProtoDeserialize.cpp +++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp @@ -404,6 +404,9 @@ bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable, case pb::OverlayableItem::ACTOR: out_overlayable->policies |= PolicyFlags::ACTOR_SIGNATURE; break; + case pb::OverlayableItem::CONFIG_SIGNATURE: + out_overlayable->policies |= PolicyFlags::CONFIG_SIGNATURE; + break; default: *out_error = "unknown overlayable policy"; return false; diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp index ba6df22af9d3a..831229ffa3832 100644 --- a/tools/aapt2/format/proto/ProtoSerialize.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize.cpp @@ -325,6 +325,9 @@ static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item if (overlayable_item.policies & PolicyFlags::ACTOR_SIGNATURE) { pb_overlayable_item->add_policy(pb::OverlayableItem::ACTOR); } + if (overlayable_item.policies & PolicyFlags::CONFIG_SIGNATURE) { + pb_overlayable_item->add_policy(pb::OverlayableItem::CONFIG_SIGNATURE); + } if (source_pool != nullptr) { SerializeSourceToPb(overlayable_item.source, source_pool, From bf1f45b071bd2fb28cbea7e7cea86cd2e4944a7c Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Tue, 29 Sep 2020 17:22:52 -0700 Subject: [PATCH 2/4] Remove malloc/free for inline overlay values Remove malloc/free of android::ResTable_entry for inline overlay values. Add `target_entry_inline` to the idmap format to encode inline overlay values separate from direct mapping of target resource to overlay resource. This reduces the number of bytes needed to represent a direct mapping of target resource to overlay resource from 9 bytes to 8 bytes per entry. Fixed all idmap alignment issues that required the framework to use "#pragma pack(push, 1)" when loading idmaps. Bug: 170341022 Test: idmap2_tests and libandroidfw_tests Change-Id: Iab4d3902508f02773464724913e0ee966e3689e4 --- cmds/idmap2/idmap2d/Idmap2Service.h | 2 + .../include/idmap2/BinaryStreamVisitor.h | 3 +- cmds/idmap2/include/idmap2/Idmap.h | 118 ++++++------ .../include/idmap2/PrettyPrintVisitor.h | 3 +- cmds/idmap2/include/idmap2/RawPrintVisitor.h | 4 +- cmds/idmap2/include/idmap2/ResourceMapping.h | 21 +- cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp | 34 ++-- cmds/idmap2/libidmap2/Idmap.cpp | 86 +++++---- cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp | 77 +++++--- cmds/idmap2/libidmap2/RawPrintVisitor.cpp | 87 +++++---- cmds/idmap2/libidmap2/ResourceMapping.cpp | 56 +++--- .../idmap2/tests/BinaryStreamVisitorTests.cpp | 13 +- cmds/idmap2/tests/Idmap2BinaryTests.cpp | 8 +- cmds/idmap2/tests/IdmapTests.cpp | 114 ++++++----- cmds/idmap2/tests/PrettyPrintVisitorTests.cpp | 5 +- cmds/idmap2/tests/RawPrintVisitorTests.cpp | 24 ++- cmds/idmap2/tests/ResourceMappingTests.cpp | 180 ++++++++++-------- cmds/idmap2/tests/TestConstants.h | 2 +- cmds/idmap2/tests/TestHelpers.h | 90 +++++---- libs/androidfw/AssetManager2.cpp | 51 ++--- libs/androidfw/Idmap.cpp | 115 ++++++----- libs/androidfw/include/androidfw/Idmap.h | 36 ++-- .../include/androidfw/ResourceTypes.h | 67 ++----- libs/androidfw/tests/data/overlay/overlay.apk | Bin 2992 -> 2988 bytes .../tests/data/overlay/overlay.idmap | Bin 1090 -> 1092 bytes 25 files changed, 669 insertions(+), 527 deletions(-) diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h index abee999dd2b29..0127e874b444a 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.h +++ b/cmds/idmap2/idmap2d/Idmap2Service.h @@ -20,6 +20,8 @@ #include #include +#include + #include "android/os/BnIdmap2.h" namespace android::os { diff --git a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h index ff45b1407deaa..bf31cbf8d4f73 100644 --- a/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h +++ b/cmds/idmap2/include/idmap2/BinaryStreamVisitor.h @@ -36,12 +36,11 @@ class BinaryStreamVisitor : public Visitor { void visit(const IdmapData::Header& header) override; private: - void Write(const void* value, size_t length); void Write8(uint8_t value); void Write16(uint16_t value); void Write32(uint32_t value); void WriteString256(const StringPiece& value); - void WriteString(const std::string& value); + void WriteString(const StringPiece& value); std::ostream& stream_; }; diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h index 0f05592b70f3c..a35fad9d686c0 100644 --- a/cmds/idmap2/include/idmap2/Idmap.h +++ b/cmds/idmap2/include/idmap2/Idmap.h @@ -17,48 +17,45 @@ /* * # idmap file format (current version) * - * idmap := header data* - * header := magic version target_crc overlay_crc target_path overlay_path debug_info - * data := data_header data_block* - * data_header := target_package_id types_count - * data_block := target_type overlay_type entry_count entry_offset entry* - * overlay_path := string256 - * target_path := string256 - * debug_info := string - * string := + '\0'+ - * entry := - * entry_count := - * entry_offset := - * magic := - * overlay_crc := - * overlay_type := - * string256 := [256] - * target_crc := - * target_package_id := - * target_type := - * types_count := - * version := + * idmap := header data* + * header := magic version target_crc overlay_crc fulfilled_policies + * enforce_overlayable target_path overlay_path debug_info + * data := data_header target_entry* target_inline_entry* overlay_entry* + * string_pool + * data_header := target_package_id overlay_package_id padding(2) target_entry_count + * target_inline_entry_count overlay_entry_count string_pool_index + * target_entry := target_id overlay_id + * target_inline_entry := target_id Res_value::size padding(1) Res_value::type + * Res_value::value + * overlay_entry := overlay_id target_id * - * - * # idmap file format changelog - * ## v1 - * - Identical to idmap v1. - * - * ## v2 - * - Entries are no longer separated by type into type specific data blocks. - * - Added overlay-indexed target resource id lookup capabilities. - * - Target and overlay entries are stored as a sparse array in the data block. The target entries - * array maps from target resource id to overlay data type and value and the array is sorted by - * target resource id. The overlay entries array maps from overlay resource id to target resource - * id and the array is sorted by overlay resource id. It is important for both arrays to be sorted - * to allow for O(log(number_of_overlaid_resources)) performance when looking up resource - * mappings at runtime. - * - Idmap can now encode a type and value to override a resource without needing a table entry. - * - A string pool block is included to retrieve the value of strings that do not have a resource - * table entry. - * - * ## v3 - * - Add 'debug' block to IdmapHeader. + * debug_info := string + * enforce_overlayable := + * fulfilled_policies := + * magic := + * overlay_crc := + * overlay_entry_count := + * overlay_id := + * overlay_package_id := + * overlay_path := string256 + * padding(n) := [n] + * Res_value::size := + * Res_value::type := + * Res_value::value := + * string := + padding(n) + * string256 := [256] + * string_pool := string + * string_pool_index := + * string_pool_length := + * target_crc := + * target_entry_count := + * target_inline_entry_count := + * target_id := + * target_package_id := + * target_path := string256 + * value_type := + * value_data := + * version := */ #ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_ @@ -183,6 +180,10 @@ class IdmapData { return target_entry_count; } + inline uint32_t GetTargetInlineEntryCount() const { + return target_entry_inline_count; + } + inline uint32_t GetOverlayEntryCount() const { return overlay_entry_count; } @@ -191,19 +192,15 @@ class IdmapData { return string_pool_index_offset; } - inline uint32_t GetStringPoolLength() const { - return string_pool_len; - } - void accept(Visitor* v) const; private: PackageId target_package_id_; PackageId overlay_package_id_; uint32_t target_entry_count; + uint32_t target_entry_inline_count; uint32_t overlay_entry_count; uint32_t string_pool_index_offset; - uint32_t string_pool_len; Header() = default; friend Idmap; @@ -213,8 +210,12 @@ class IdmapData { struct TargetEntry { ResourceId target_id; - TargetValue::DataType data_type; - TargetValue::DataValue data_value; + ResourceId overlay_id; + }; + + struct TargetInlineEntry { + ResourceId target_id; + TargetValue value; }; struct OverlayEntry { @@ -227,20 +228,24 @@ class IdmapData { static Result> FromResourceMapping( const ResourceMapping& resource_mapping); - inline const std::unique_ptr& GetHeader() const { + const std::unique_ptr& GetHeader() const { return header_; } - inline const std::vector& GetTargetEntries() const { + const std::vector& GetTargetEntries() const { return target_entries_; } - inline const std::vector& GetOverlayEntries() const { + const std::vector& GetTargetInlineEntries() const { + return target_inline_entries_; + } + + const std::vector& GetOverlayEntries() const { return overlay_entries_; } - inline const void* GetStringPoolData() const { - return string_pool_.get(); + const std::string& GetStringPoolData() const { + return string_pool_data_; } void accept(Visitor* v) const; @@ -251,8 +256,9 @@ class IdmapData { std::unique_ptr header_; std::vector target_entries_; + std::vector target_inline_entries_; std::vector overlay_entries_; - std::unique_ptr string_pool_; + std::string string_pool_data_; friend Idmap; DISALLOW_COPY_AND_ASSIGN(IdmapData); @@ -304,6 +310,10 @@ class Visitor { virtual void visit(const IdmapData::Header& header) = 0; }; +inline size_t CalculatePadding(size_t data_length) { + return (4 - (data_length % 4)) % 4; +} + } // namespace android::idmap2 #endif // IDMAP2_INCLUDE_IDMAP2_IDMAP_H_ diff --git a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h index 5dcf217e2aa3f..2b4c761241754 100644 --- a/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h +++ b/cmds/idmap2/include/idmap2/PrettyPrintVisitor.h @@ -41,8 +41,9 @@ class PrettyPrintVisitor : public Visitor { private: std::ostream& stream_; - std::unique_ptr target_apk_; AssetManager2 target_am_; + AssetManager2 overlay_am_; + std::vector> apk_assets_; }; } // namespace idmap2 diff --git a/cmds/idmap2/include/idmap2/RawPrintVisitor.h b/cmds/idmap2/include/idmap2/RawPrintVisitor.h index 92c1864536112..58edc99715fd0 100644 --- a/cmds/idmap2/include/idmap2/RawPrintVisitor.h +++ b/cmds/idmap2/include/idmap2/RawPrintVisitor.h @@ -45,11 +45,9 @@ class RawPrintVisitor : public Visitor { void print(uint16_t value, const char* fmt, ...); void print(uint32_t value, const char* fmt, ...); void print(const std::string& value, size_t encoded_size, const char* fmt, ...); - void print_raw(uint32_t length, const char* fmt, ...); std::ostream& stream_; - std::unique_ptr target_apk_; - std::unique_ptr overlay_apk_; + std::vector> apk_assets_; AssetManager2 target_am_; AssetManager2 overlay_am_; size_t offset_; diff --git a/cmds/idmap2/include/idmap2/ResourceMapping.h b/cmds/idmap2/include/idmap2/ResourceMapping.h index 5869409e7db91..0a58ec43d8ff7 100644 --- a/cmds/idmap2/include/idmap2/ResourceMapping.h +++ b/cmds/idmap2/include/idmap2/ResourceMapping.h @@ -41,7 +41,7 @@ struct TargetValue { DataValue data_value; }; -using TargetResourceMap = std::map; +using TargetResourceMap = std::map>; using OverlayResourceMap = std::map; class ResourceMapping { @@ -56,7 +56,7 @@ class ResourceMapping { bool enforce_overlayable, LogInfo& log_info); // Retrieves the mapping of target resource id to overlay value. - inline TargetResourceMap GetTargetToOverlayMap() const { + inline const TargetResourceMap& GetTargetToOverlayMap() const { return target_map_; } @@ -81,19 +81,24 @@ class ResourceMapping { } // Retrieves the raw string pool data from the xml referenced in android:resourcesMap. - inline const std::pair GetStringPoolData() const { - return std::make_pair(string_pool_data_.get(), string_pool_data_length_); + inline const StringPiece GetStringPoolData() const { + return StringPiece(reinterpret_cast(string_pool_data_.get()), + string_pool_data_length_); } private: ResourceMapping() = default; - // Apps a mapping of target resource id to the type and value of the data that overlays the - // target resource. The data_type is the runtime format of the data value (see - // Res_value::dataType). If rewrite_overlay_reference is `true` then references to an overlay + // Maps a target resource id to an overlay resource id. + // If rewrite_overlay_reference is `true` then references to the overlay // resource should appear as a reference to its corresponding target resource at runtime. + Result AddMapping(ResourceId target_resource, ResourceId overlay_resource, + bool rewrite_overlay_reference); + + // Maps a target resource id to a data type and value combination. + // The `data_type` is the runtime format of the data value (see Res_value::dataType). Result AddMapping(ResourceId target_resource, TargetValue::DataType data_type, - TargetValue::DataValue data_value, bool rewrite_overlay_reference); + TargetValue::DataValue data_value); // Removes the overlay value mapping for the target resource. void RemoveMapping(ResourceId target_resource); diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp index 255212ad4c66b..726f6c5c2c99a 100644 --- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp +++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp @@ -24,10 +24,6 @@ namespace android::idmap2 { -void BinaryStreamVisitor::Write(const void* value, size_t length) { - stream_.write(reinterpret_cast(value), length); -} - void BinaryStreamVisitor::Write8(uint8_t value) { stream_.write(reinterpret_cast(&value), sizeof(uint8_t)); } @@ -49,11 +45,11 @@ void BinaryStreamVisitor::WriteString256(const StringPiece& value) { stream_.write(buf, sizeof(buf)); } -void BinaryStreamVisitor::WriteString(const std::string& value) { - // pad with null to nearest word boundary; include at least one terminating null - size_t padding_size = 4 - (value.size() % 4); - Write32(value.size() + padding_size); - stream_.write(value.c_str(), value.size()); +void BinaryStreamVisitor::WriteString(const StringPiece& value) { + // pad with null to nearest word boundary; + size_t padding_size = CalculatePadding(value.size()); + Write32(value.size()); + stream_.write(value.data(), value.size()); stream_.write("\0\0\0\0", padding_size); } @@ -67,7 +63,7 @@ void BinaryStreamVisitor::visit(const IdmapHeader& header) { Write32(header.GetTargetCrc()); Write32(header.GetOverlayCrc()); Write32(header.GetFulfilledPolicies()); - Write8(static_cast(header.GetEnforceOverlayable())); + Write32(static_cast(header.GetEnforceOverlayable())); WriteString256(header.GetTargetPath()); WriteString256(header.GetOverlayPath()); WriteString(header.GetDebugInfo()); @@ -76,8 +72,16 @@ void BinaryStreamVisitor::visit(const IdmapHeader& header) { void BinaryStreamVisitor::visit(const IdmapData& data) { for (const auto& target_entry : data.GetTargetEntries()) { Write32(target_entry.target_id); - Write8(target_entry.data_type); - Write32(target_entry.data_value); + Write32(target_entry.overlay_id); + } + + static constexpr uint16_t kValueSize = 8U; + for (const auto& target_entry : data.GetTargetInlineEntries()) { + Write32(target_entry.target_id); + Write16(kValueSize); + Write8(0U); // padding + Write8(target_entry.value.data_type); + Write32(target_entry.value.data_value); } for (const auto& overlay_entry : data.GetOverlayEntries()) { @@ -85,16 +89,18 @@ void BinaryStreamVisitor::visit(const IdmapData& data) { Write32(overlay_entry.target_id); } - Write(data.GetStringPoolData(), data.GetHeader()->GetStringPoolLength()); + WriteString(data.GetStringPoolData()); } void BinaryStreamVisitor::visit(const IdmapData::Header& header) { Write8(header.GetTargetPackageId()); Write8(header.GetOverlayPackageId()); + Write8(0U); // padding + Write8(0U); // padding Write32(header.GetTargetEntryCount()); + Write32(header.GetTargetInlineEntryCount()); Write32(header.GetOverlayEntryCount()); Write32(header.GetStringPoolIndexOffset()); - Write32(header.GetStringPoolLength()); } } // namespace android::idmap2 diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp index 23c25a7089dec..1129413584b2a 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -51,19 +51,19 @@ bool WARN_UNUSED Read8(std::istream& stream, uint8_t* out) { return false; } -bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) { - uint32_t value; - if (stream.read(reinterpret_cast(&value), sizeof(uint32_t))) { - *out = dtohl(value); +bool WARN_UNUSED Read16(std::istream& stream, uint16_t* out) { + uint16_t value; + if (stream.read(reinterpret_cast(&value), sizeof(uint16_t))) { + *out = dtohs(value); return true; } return false; } -bool WARN_UNUSED ReadBuffer(std::istream& stream, std::unique_ptr* out, size_t length) { - auto buffer = std::unique_ptr(new uint8_t[length]); - if (stream.read(reinterpret_cast(buffer.get()), length)) { - *out = std::move(buffer); +bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) { + uint32_t value; + if (stream.read(reinterpret_cast(&value), sizeof(uint32_t))) { + *out = dtohl(value); return true; } return false; @@ -95,8 +95,11 @@ Result ReadString(std::istream& stream) { if (!stream.read(buf.data(), size)) { return Error("failed to read string of size %u", size); } - // buf is guaranteed to be null terminated (with enough nulls to end on a word boundary) - buf.resize(strlen(buf.c_str())); + uint32_t padding_size = CalculatePadding(size); + std::string padding(padding_size, '\0'); + if (!stream.read(padding.data(), padding_size)) { + return Error("failed to read string padding of size %u", padding_size); + } return buf; } @@ -112,16 +115,16 @@ Result GetPackageCrc(const ZipFile& zip) { std::unique_ptr IdmapHeader::FromBinaryStream(std::istream& stream) { std::unique_ptr idmap_header(new IdmapHeader()); - uint8_t enforce_overlayable; + uint32_t enforce_overlayable; if (!Read32(stream, &idmap_header->magic_) || !Read32(stream, &idmap_header->version_) || !Read32(stream, &idmap_header->target_crc_) || !Read32(stream, &idmap_header->overlay_crc_) || - !Read32(stream, &idmap_header->fulfilled_policies_) || !Read8(stream, &enforce_overlayable) || - !ReadString256(stream, idmap_header->target_path_) || + !Read32(stream, &idmap_header->fulfilled_policies_) || + !Read32(stream, &enforce_overlayable) || !ReadString256(stream, idmap_header->target_path_) || !ReadString256(stream, idmap_header->overlay_path_)) { return nullptr; } - idmap_header->enforce_overlayable_ = static_cast(enforce_overlayable); + idmap_header->enforce_overlayable_ = enforce_overlayable != 0U; auto debug_str = ReadString(stream); if (!debug_str) { @@ -207,12 +210,13 @@ Result IdmapHeader::IsUpToDate(const char* target_path, const char* overla std::unique_ptr IdmapData::Header::FromBinaryStream(std::istream& stream) { std::unique_ptr idmap_data_header(new IdmapData::Header()); + uint8_t padding; if (!Read8(stream, &idmap_data_header->target_package_id_) || - !Read8(stream, &idmap_data_header->overlay_package_id_) || - !Read32(stream, &idmap_data_header->target_entry_count) || + !Read8(stream, &idmap_data_header->overlay_package_id_) || !Read8(stream, &padding) || + !Read8(stream, &padding) || !Read32(stream, &idmap_data_header->target_entry_count) || + !Read32(stream, &idmap_data_header->target_entry_inline_count) || !Read32(stream, &idmap_data_header->overlay_entry_count) || - !Read32(stream, &idmap_data_header->string_pool_index_offset) || - !Read32(stream, &idmap_data_header->string_pool_len)) { + !Read32(stream, &idmap_data_header->string_pool_index_offset)) { return nullptr; } @@ -225,14 +229,27 @@ std::unique_ptr IdmapData::FromBinaryStream(std::istream& strea if (!data->header_) { return nullptr; } + // Read the mapping of target resource id to overlay resource value. for (size_t i = 0; i < data->header_->GetTargetEntryCount(); i++) { TargetEntry target_entry{}; - if (!Read32(stream, &target_entry.target_id) || !Read8(stream, &target_entry.data_type) || - !Read32(stream, &target_entry.data_value)) { + if (!Read32(stream, &target_entry.target_id) || !Read32(stream, &target_entry.overlay_id)) { return nullptr; } - data->target_entries_.emplace_back(target_entry); + data->target_entries_.push_back(target_entry); + } + + // Read the mapping of target resource id to inline overlay values. + uint8_t unused1; + uint16_t unused2; + for (size_t i = 0; i < data->header_->GetTargetInlineEntryCount(); i++) { + TargetInlineEntry target_entry{}; + if (!Read32(stream, &target_entry.target_id) || !Read16(stream, &unused2) || + !Read8(stream, &unused1) || !Read8(stream, &target_entry.value.data_type) || + !Read32(stream, &target_entry.value.data_value)) { + return nullptr; + } + data->target_inline_entries_.push_back(target_entry); } // Read the mapping of overlay resource id to target resource id. @@ -245,9 +262,11 @@ std::unique_ptr IdmapData::FromBinaryStream(std::istream& strea } // Read raw string pool bytes. - if (!ReadBuffer(stream, &data->string_pool_, data->header_->string_pool_len)) { + auto string_pool_data = ReadString(stream); + if (!string_pool_data) { return nullptr; } + data->string_pool_data_ = std::move(*string_pool_data); return std::move(data); } @@ -290,27 +309,28 @@ Result> IdmapData::FromResourceMapping( } std::unique_ptr data(new IdmapData()); - for (const auto& mappings : resource_mapping.GetTargetToOverlayMap()) { - data->target_entries_.emplace_back(IdmapData::TargetEntry{ - mappings.first, mappings.second.data_type, mappings.second.data_value}); + data->string_pool_data_ = resource_mapping.GetStringPoolData().to_string(); + for (const auto& mapping : resource_mapping.GetTargetToOverlayMap()) { + if (auto overlay_resource = std::get_if(&mapping.second)) { + data->target_entries_.push_back({mapping.first, *overlay_resource}); + } else { + data->target_inline_entries_.push_back( + {mapping.first, std::get(mapping.second)}); + } } - for (const auto& mappings : resource_mapping.GetOverlayToTargetMap()) { - data->overlay_entries_.emplace_back(IdmapData::OverlayEntry{mappings.first, mappings.second}); + for (const auto& mapping : resource_mapping.GetOverlayToTargetMap()) { + data->overlay_entries_.emplace_back(IdmapData::OverlayEntry{mapping.first, mapping.second}); } std::unique_ptr data_header(new IdmapData::Header()); data_header->target_package_id_ = resource_mapping.GetTargetPackageId(); data_header->overlay_package_id_ = resource_mapping.GetOverlayPackageId(); data_header->target_entry_count = static_cast(data->target_entries_.size()); + data_header->target_entry_inline_count = + static_cast(data->target_inline_entries_.size()); data_header->overlay_entry_count = static_cast(data->overlay_entries_.size()); data_header->string_pool_index_offset = resource_mapping.GetStringPoolOffset(); - - const auto string_pool_data = resource_mapping.GetStringPoolData(); - data_header->string_pool_len = string_pool_data.second; - data->string_pool_ = std::unique_ptr(new uint8_t[data_header->string_pool_len]); - memcpy(data->string_pool_.get(), string_pool_data.first, data_header->string_pool_len); - data->header_ = std::move(data_header); return {std::move(data)}; } diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp index 63ee8a6483529..a93202a64d318 100644 --- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp +++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp @@ -38,6 +38,7 @@ void PrettyPrintVisitor::visit(const IdmapHeader& header) { stream_ << "Paths:" << std::endl << TAB "target apk path : " << header.GetTargetPath() << std::endl << TAB "overlay apk path : " << header.GetOverlayPath() << std::endl; + const std::string& debug = header.GetDebugInfo(); if (!debug.empty()) { std::istringstream debug_stream(debug); @@ -48,10 +49,16 @@ void PrettyPrintVisitor::visit(const IdmapHeader& header) { } } - target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string()); - if (target_apk_) { + if (auto target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string())) { target_am_.SetApkAssets({target_apk_.get()}); + apk_assets_.push_back(std::move(target_apk_)); } + + if (auto overlay_apk = ApkAssets::Load(header.GetOverlayPath().to_string())) { + overlay_am_.SetApkAssets({overlay_apk.get()}); + apk_assets_.push_back(std::move(overlay_apk)); + } + stream_ << "Mapping:" << std::endl; } @@ -59,34 +66,56 @@ void PrettyPrintVisitor::visit(const IdmapData::Header& header ATTRIBUTE_UNUSED) } void PrettyPrintVisitor::visit(const IdmapData& data) { + static constexpr const char* kUnknownResourceName = "???"; + const bool target_package_loaded = !target_am_.GetApkAssets().empty(); - const ResStringPool string_pool(data.GetStringPoolData(), - data.GetHeader()->GetStringPoolLength()); + const bool overlay_package_loaded = !overlay_am_.GetApkAssets().empty(); + + const ResStringPool string_pool(data.GetStringPoolData().data(), data.GetStringPoolData().size()); const size_t string_pool_offset = data.GetHeader()->GetStringPoolIndexOffset(); - for (auto& target_entry : data.GetTargetEntries()) { - stream_ << TAB << base::StringPrintf("0x%08x ->", target_entry.target_id); - - if (target_entry.data_type != Res_value::TYPE_REFERENCE && - target_entry.data_type != Res_value::TYPE_DYNAMIC_REFERENCE) { - stream_ << " " << utils::DataTypeToString(target_entry.data_type); - } - - if (target_entry.data_type == Res_value::TYPE_STRING) { - stream_ << " \"" - << string_pool.string8ObjectAt(target_entry.data_value - string_pool_offset).c_str() - << "\""; - } else { - stream_ << " " << base::StringPrintf("0x%08x", target_entry.data_value); - } - + for (const auto& target_entry : data.GetTargetEntries()) { + std::string target_name = kUnknownResourceName; if (target_package_loaded) { - Result name = utils::ResToTypeEntryName(target_am_, target_entry.target_id); - if (name) { - stream_ << " " << *name; + if (auto name = utils::ResToTypeEntryName(target_am_, target_entry.target_id)) { + target_name = *name; } } - stream_ << std::endl; + + std::string overlay_name = kUnknownResourceName; + if (overlay_package_loaded) { + if (auto name = utils::ResToTypeEntryName(overlay_am_, target_entry.overlay_id)) { + overlay_name = *name; + } + } + + stream_ << TAB + << base::StringPrintf("0x%08x -> 0x%08x (%s -> %s)", target_entry.target_id, + target_entry.overlay_id, target_name.c_str(), + overlay_name.c_str()) + << std::endl; + } + + for (auto& target_entry : data.GetTargetInlineEntries()) { + stream_ << TAB << base::StringPrintf("0x%08x -> ", target_entry.target_id) + << utils::DataTypeToString(target_entry.value.data_type); + + size_t unused; + if (target_entry.value.data_type == Res_value::TYPE_STRING) { + auto str = string_pool.stringAt(target_entry.value.data_value - string_pool_offset, &unused); + stream_ << " \"" << StringPiece16(str) << "\""; + } else { + stream_ << " " << base::StringPrintf("0x%08x", target_entry.value.data_value); + } + + std::string target_name = kUnknownResourceName; + if (target_package_loaded) { + if (auto name = utils::ResToTypeEntryName(target_am_, target_entry.target_id)) { + target_name = *name; + } + } + + stream_ << " (" << target_name << ")" << std::endl; } } diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp index 3f62a2ae20294..82f5d26cbbb31 100644 --- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp +++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp @@ -30,15 +30,6 @@ using android::ApkAssets; using android::idmap2::policy::PoliciesToDebugString; -namespace { - -size_t StringSizeWhenEncoded(const std::string& s) { - size_t null_bytes = 4 - (s.size() % 4); - return sizeof(uint32_t) + s.size() + null_bytes; -} - -} // namespace - namespace android::idmap2 { void RawPrintVisitor::visit(const Idmap& idmap ATTRIBUTE_UNUSED) { @@ -51,19 +42,24 @@ void RawPrintVisitor::visit(const IdmapHeader& header) { print(header.GetOverlayCrc(), "overlay crc"); print(header.GetFulfilledPolicies(), "fulfilled policies: %s", PoliciesToDebugString(header.GetFulfilledPolicies()).c_str()); - print(static_cast(header.GetEnforceOverlayable()), "enforce overlayable"); + print(static_cast(header.GetEnforceOverlayable()), "enforce overlayable"); print(header.GetTargetPath().to_string(), kIdmapStringLength, "target path"); print(header.GetOverlayPath().to_string(), kIdmapStringLength, "overlay path"); - print("...", StringSizeWhenEncoded(header.GetDebugInfo()), "debug info"); - target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string()); + uint32_t debug_info_size = header.GetDebugInfo().size(); + print(debug_info_size, "debug info size"); + print("...", debug_info_size + CalculatePadding(debug_info_size), "debug info"); + + auto target_apk_ = ApkAssets::Load(header.GetTargetPath().to_string()); if (target_apk_) { target_am_.SetApkAssets({target_apk_.get()}); + apk_assets_.push_back(std::move(target_apk_)); } - overlay_apk_ = ApkAssets::Load(header.GetOverlayPath().to_string()); + auto overlay_apk_ = ApkAssets::Load(header.GetOverlayPath().to_string()); if (overlay_apk_) { overlay_am_.SetApkAssets({overlay_apk_.get()}); + apk_assets_.push_back(std::move(overlay_apk_)); } } @@ -82,18 +78,44 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) { print(target_entry.target_id, "target id"); } - print(target_entry.data_type, "type: %s", - utils::DataTypeToString(target_entry.data_type).data()); - Result overlay_name(Error("")); - if (overlay_package_loaded && (target_entry.data_type == Res_value::TYPE_REFERENCE || - target_entry.data_type == Res_value::TYPE_DYNAMIC_REFERENCE)) { - overlay_name = utils::ResToTypeEntryName(overlay_am_, target_entry.data_value); + if (overlay_package_loaded) { + overlay_name = utils::ResToTypeEntryName(overlay_am_, target_entry.overlay_id); } if (overlay_name) { - print(target_entry.data_value, "value: %s", overlay_name->c_str()); + print(target_entry.overlay_id, "overlay id: %s", overlay_name->c_str()); } else { - print(target_entry.data_value, "value"); + print(target_entry.overlay_id, "overlay id"); + } + } + + for (auto& target_entry : data.GetTargetInlineEntries()) { + Result target_name(Error("")); + if (target_package_loaded) { + target_name = utils::ResToTypeEntryName(target_am_, target_entry.target_id); + } + if (target_name) { + print(target_entry.target_id, "target id: %s", target_name->c_str()); + } else { + print(target_entry.target_id, "target id"); + } + + print("...", sizeof(Res_value::size) + sizeof(Res_value::res0), "padding"); + + print(target_entry.value.data_type, "type: %s", + utils::DataTypeToString(target_entry.value.data_type).data()); + + Result overlay_name(Error("")); + if (overlay_package_loaded && + (target_entry.value.data_value == Res_value::TYPE_REFERENCE || + target_entry.value.data_value == Res_value::TYPE_DYNAMIC_REFERENCE)) { + overlay_name = utils::ResToTypeEntryName(overlay_am_, target_entry.value.data_value); + } + + if (overlay_name) { + print(target_entry.value.data_value, "data: %s", overlay_name->c_str()); + } else { + print(target_entry.value.data_value, "data"); } } @@ -121,19 +143,19 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) { } } - const size_t string_pool_length = data.GetHeader()->GetStringPoolLength(); - if (string_pool_length > 0) { - print_raw(string_pool_length, "%zu raw string pool bytes", string_pool_length); - } + uint32_t string_pool_size = data.GetStringPoolData().size(); + print(string_pool_size, "string pool size"); + print("...", string_pool_size + CalculatePadding(string_pool_size), "string pool"); } void RawPrintVisitor::visit(const IdmapData::Header& header) { print(header.GetTargetPackageId(), "target package id"); print(header.GetOverlayPackageId(), "overlay package id"); + print("...", sizeof(Idmap_data_header::p0), "padding"); print(header.GetTargetEntryCount(), "target entry count"); + print(header.GetTargetInlineEntryCount(), "target inline entry count"); print(header.GetOverlayEntryCount(), "overlay entry count"); print(header.GetStringPoolIndexOffset(), "string pool index offset"); - print(header.GetStringPoolLength(), "string pool byte length"); } // NOLINTNEXTLINE(cert-dcl50-cpp) @@ -190,17 +212,4 @@ void RawPrintVisitor::print(const std::string& value, size_t encoded_size, const offset_ += encoded_size; } -// NOLINTNEXTLINE(cert-dcl50-cpp) -void RawPrintVisitor::print_raw(uint32_t length, const char* fmt, ...) { - va_list ap; - va_start(ap, fmt); - std::string comment; - base::StringAppendV(&comment, fmt, ap); - va_end(ap); - - stream_ << base::StringPrintf("%08zx: ", offset_) << "........ " << comment << std::endl; - - offset_ += length; -} - } // namespace android::idmap2 diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp index fd8b4eb86b4a4..122f0682aec6c 100644 --- a/cmds/idmap2/libidmap2/ResourceMapping.cpp +++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp @@ -205,19 +205,14 @@ Result ResourceMapping::CreateResourceMapping(const AssetManage overlay_resource->data += string_pool_offset; } - // Only rewrite resources defined within the overlay package to their corresponding target - // resource ids at runtime. - bool rewrite_overlay_reference = - IsReference(overlay_resource->dataType) - ? overlay_package_id == EXTRACT_PACKAGE(overlay_resource->data) - : false; - - if (rewrite_overlay_reference) { - overlay_resource->dataType = Res_value::TYPE_DYNAMIC_REFERENCE; + if (IsReference(overlay_resource->dataType)) { + // Only rewrite resources defined within the overlay package to their corresponding target + // resource ids at runtime. + bool rewrite_reference = overlay_package_id == EXTRACT_PACKAGE(overlay_resource->data); + resource_mapping.AddMapping(target_id, overlay_resource->data, rewrite_reference); + } else { + resource_mapping.AddMapping(target_id, overlay_resource->dataType, overlay_resource->data); } - - resource_mapping.AddMapping(target_id, overlay_resource->dataType, overlay_resource->data, - rewrite_overlay_reference); } return resource_mapping; @@ -246,9 +241,8 @@ Result ResourceMapping::CreateResourceMappingLegacy( // Retrieve the compile-time resource id of the target resource. target_resource = REWRITE_PACKAGE(target_resource, target_package_id); - - resource_mapping.AddMapping(target_resource, Res_value::TYPE_REFERENCE, overlay_resid, - /* rewrite_overlay_reference */ false); + resource_mapping.AddMapping(target_resource, overlay_resid, + false /* rewrite_overlay_reference */); } return resource_mapping; @@ -396,9 +390,7 @@ OverlayResourceMap ResourceMapping::GetOverlayToTargetMap() const { return map; } -Result ResourceMapping::AddMapping(ResourceId target_resource, - TargetValue::DataType data_type, - TargetValue::DataValue data_value, +Result ResourceMapping::AddMapping(ResourceId target_resource, ResourceId overlay_resource, bool rewrite_overlay_reference) { if (target_map_.find(target_resource) != target_map_.end()) { return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource); @@ -407,13 +399,26 @@ Result ResourceMapping::AddMapping(ResourceId target_resource, // TODO(141485591): Ensure that the overlay type is compatible with the target type. If the // runtime types are not compatible, it could cause runtime crashes when the resource is resolved. - target_map_.insert(std::make_pair(target_resource, TargetValue{data_type, data_value})); + target_map_.insert(std::make_pair(target_resource, overlay_resource)); - if (rewrite_overlay_reference && IsReference(data_type)) { - overlay_map_.insert(std::make_pair(data_value, target_resource)); + if (rewrite_overlay_reference) { + overlay_map_.insert(std::make_pair(overlay_resource, target_resource)); + } + return Unit{}; +} + +Result ResourceMapping::AddMapping(ResourceId target_resource, + TargetValue::DataType data_type, + TargetValue::DataValue data_value) { + if (target_map_.find(target_resource) != target_map_.end()) { + return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource); } - return Result({}); + // TODO(141485591): Ensure that the overlay type is compatible with the target type. If the + // runtime types are not compatible, it could cause runtime crashes when the resource is resolved. + + target_map_.insert(std::make_pair(target_resource, TargetValue{data_type, data_value})); + return Unit{}; } void ResourceMapping::RemoveMapping(ResourceId target_resource) { @@ -422,14 +427,15 @@ void ResourceMapping::RemoveMapping(ResourceId target_resource) { return; } - const TargetValue value = target_iter->second; + const auto value = target_iter->second; target_map_.erase(target_iter); - if (!IsReference(value.data_type)) { + const ResourceId* overlay_resource = std::get_if(&value); + if (overlay_resource == nullptr) { return; } - auto overlay_iter = overlay_map_.equal_range(value.data_value); + auto overlay_iter = overlay_map_.equal_range(*overlay_resource); for (auto i = overlay_iter.first; i != overlay_iter.second; ++i) { if (i->second == target_resource) { overlay_map_.erase(i); diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp index 5fea7bcdaac59..c3a3e0ba90472 100644 --- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp +++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp @@ -72,13 +72,20 @@ TEST(BinaryStreamVisitorTests, CreateBinaryStreamViaBinaryStreamVisitor) { const auto& target_entries2 = data2->GetTargetEntries(); ASSERT_EQ(target_entries1.size(), target_entries2.size()); ASSERT_EQ(target_entries1[0].target_id, target_entries2[0].target_id); - ASSERT_EQ(target_entries1[0].data_value, target_entries2[0].data_value); + ASSERT_EQ(target_entries1[0].overlay_id, target_entries2[0].overlay_id); ASSERT_EQ(target_entries1[1].target_id, target_entries2[1].target_id); - ASSERT_EQ(target_entries1[1].data_value, target_entries2[1].data_value); + ASSERT_EQ(target_entries1[1].overlay_id, target_entries2[1].overlay_id); ASSERT_EQ(target_entries1[2].target_id, target_entries2[2].target_id); - ASSERT_EQ(target_entries1[2].data_value, target_entries2[2].data_value); + ASSERT_EQ(target_entries1[2].overlay_id, target_entries2[2].overlay_id); + + const auto& target_inline_entries1 = data1->GetTargetInlineEntries(); + const auto& target_inline_entries2 = data2->GetTargetInlineEntries(); + ASSERT_EQ(target_inline_entries1.size(), target_inline_entries2.size()); + ASSERT_EQ(target_inline_entries1[0].target_id, target_inline_entries2[0].target_id); + ASSERT_EQ(target_inline_entries1[0].value.data_type, target_inline_entries2[0].value.data_type); + ASSERT_EQ(target_inline_entries1[0].value.data_value, target_inline_entries2[0].value.data_value); const auto& overlay_entries1 = data1->GetOverlayEntries(); const auto& overlay_entries2 = data2->GetOverlayEntries(); diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp index d896cf9c11ba5..eba102da07631 100644 --- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp +++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp @@ -128,13 +128,13 @@ TEST_F(Idmap2BinaryTests, Dump) { // clang-format on ASSERT_THAT(result, NotNull()); ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr; - ASSERT_NE(result->stdout.find(R::target::integer::literal::int1 + " -> 0x7f010000 integer/int1"), + ASSERT_NE(result->stdout.find(R::target::integer::literal::int1 + " -> 0x7f010000"), std::string::npos); - ASSERT_NE(result->stdout.find(R::target::string::literal::str1 + " -> 0x7f020000 string/str1"), + ASSERT_NE(result->stdout.find(R::target::string::literal::str1 + " -> 0x7f020000"), std::string::npos); - ASSERT_NE(result->stdout.find(R::target::string::literal::str3 + " -> 0x7f020001 string/str3"), + ASSERT_NE(result->stdout.find(R::target::string::literal::str3 + " -> 0x7f020001"), std::string::npos); - ASSERT_NE(result->stdout.find(R::target::string::literal::str4 + " -> 0x7f020002 string/str4"), + ASSERT_NE(result->stdout.find(R::target::string::literal::str4 + " -> 0x7f020002"), std::string::npos); // clang-format off diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index 6fab5e0f8ae12..9b42a2781b58f 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -42,14 +42,18 @@ using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; namespace android::idmap2 { -#define ASSERT_TARGET_ENTRY(entry, target_resid, type, value) \ - ASSERT_EQ(entry.target_id, target_resid); \ - ASSERT_EQ(entry.data_type, type); \ - ASSERT_EQ(entry.data_value, value) +#define ASSERT_TARGET_ENTRY(entry, target_resid, overlay_resid) \ + ASSERT_EQ((entry).target_id, (target_resid)); \ + ASSERT_EQ((entry).overlay_id, (overlay_resid)) + +#define ASSERT_TARGET_INLINE_ENTRY(entry, target_resid, expected_type, expected_value) \ + ASSERT_EQ((entry).target_id, target_resid); \ + ASSERT_EQ((entry).value.data_type, (expected_type)); \ + ASSERT_EQ((entry).value.data_value, (expected_value)) #define ASSERT_OVERLAY_ENTRY(entry, overlay_resid, target_resid) \ - ASSERT_EQ(entry.overlay_id, overlay_resid); \ - ASSERT_EQ(entry.target_id, target_resid) + ASSERT_EQ((entry).overlay_id, (overlay_resid)); \ + ASSERT_EQ((entry).target_id, (target_resid)) TEST(IdmapTests, TestCanonicalIdmapPathFor) { ASSERT_EQ(Idmap::CanonicalIdmapPathFor("/foo", "/vendor/overlay/bar.apk"), @@ -62,7 +66,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) { std::unique_ptr header = IdmapHeader::FromBinaryStream(stream); ASSERT_THAT(header, NotNull()); ASSERT_EQ(header->GetMagic(), 0x504d4449U); - ASSERT_EQ(header->GetVersion(), 0x04U); + ASSERT_EQ(header->GetVersion(), 0x05U); ASSERT_EQ(header->GetTargetCrc(), 0x1234U); ASSERT_EQ(header->GetOverlayCrc(), 0x5678U); ASSERT_EQ(header->GetFulfilledPolicies(), 0x11); @@ -75,7 +79,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) { TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) { std::string raw(reinterpret_cast(idmap_raw_data), idmap_raw_data_len); // overwrite the target path string, including the terminating null, with '.' - for (size_t i = 0x15; i < 0x115; i++) { + for (size_t i = 0x18; i < 0x118; i++) { raw[i] = '.'; } std::istringstream stream(raw); @@ -84,7 +88,7 @@ TEST(IdmapTests, FailToCreateIdmapHeaderFromBinaryStreamIfPathTooLong) { } TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) { - const size_t offset = 0x221; + const size_t offset = 0x224; std::string raw(reinterpret_cast(idmap_raw_data + offset), idmap_raw_data_len - offset); std::istringstream stream(raw); @@ -96,7 +100,7 @@ TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) { } TEST(IdmapTests, CreateIdmapDataFromBinaryStream) { - const size_t offset = 0x221; + const size_t offset = 0x224; std::string raw(reinterpret_cast(idmap_raw_data + offset), idmap_raw_data_len - offset); std::istringstream stream(raw); @@ -106,12 +110,14 @@ TEST(IdmapTests, CreateIdmapDataFromBinaryStream) { const auto& target_entries = data->GetTargetEntries(); ASSERT_EQ(target_entries.size(), 3U); - ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, 0x01 /* Res_value::TYPE_REFERENCE */, - 0x7f020000); - ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, 0x01 /* Res_value::TYPE_REFERENCE */, - 0x7f030000); - ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, 0x01 /* Res_value::TYPE_REFERENCE */, - 0x7f030001); + ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, 0x7f020000); + ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, 0x7f030000); + ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, 0x7f030001); + + const auto& target_inline_entries = data->GetTargetInlineEntries(); + ASSERT_EQ(target_inline_entries.size(), 1U); + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, Res_value::TYPE_INT_HEX, + 0x12345678); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(target_entries.size(), 3U); @@ -130,7 +136,7 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) { ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); - ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x04U); + ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x05U); ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U); ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U); ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), 0x11); @@ -146,9 +152,14 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) { const auto& target_entries = data->GetTargetEntries(); ASSERT_EQ(target_entries.size(), 3U); - ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, Res_value::TYPE_REFERENCE, 0x7f020000); - ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, Res_value::TYPE_REFERENCE, 0x7f030000); - ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, Res_value::TYPE_REFERENCE, 0x7f030001); + ASSERT_TARGET_ENTRY(target_entries[0], 0x7f020000, 0x7f020000); + ASSERT_TARGET_ENTRY(target_entries[1], 0x7f030000, 0x7f030000); + ASSERT_TARGET_ENTRY(target_entries[2], 0x7f030002, 0x7f030001); + + const auto& target_inline_entries = data->GetTargetInlineEntries(); + ASSERT_EQ(target_inline_entries.size(), 1U); + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, Res_value::TYPE_INT_HEX, + 0x12345678); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(target_entries.size(), 3U); @@ -184,7 +195,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromApkAssets) { ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); - ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x04U); + ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x05U); 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); @@ -244,14 +255,13 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssets) { const auto& target_entries = data->GetTargetEntries(); ASSERT_EQ(target_entries.size(), 4U); - ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1, - Res_value::TYPE_DYNAMIC_REFERENCE, R::overlay::integer::int1); - ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, Res_value::TYPE_DYNAMIC_REFERENCE, - R::overlay::string::str1); - ASSERT_TARGET_ENTRY(target_entries[2], R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE, - R::overlay::string::str3); - ASSERT_TARGET_ENTRY(target_entries[3], R::target::string::str4, Res_value::TYPE_DYNAMIC_REFERENCE, - R::overlay::string::str4); + ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1, R::overlay::integer::int1); + ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, R::overlay::string::str1); + ASSERT_TARGET_ENTRY(target_entries[2], R::target::string::str3, R::overlay::string::str3); + ASSERT_TARGET_ENTRY(target_entries[3], R::target::string::str4, R::overlay::string::str4); + + const auto& target_inline_entries = data->GetTargetInlineEntries(); + ASSERT_EQ(target_inline_entries.size(), 0U); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(target_entries.size(), 4U); @@ -286,13 +296,13 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssetsSharedLibOverlay) { const auto& target_entries = data->GetTargetEntries(); ASSERT_EQ(target_entries.size(), 4U); ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1, - Res_value::TYPE_DYNAMIC_REFERENCE, R::overlay_shared::integer::int1); - ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, Res_value::TYPE_DYNAMIC_REFERENCE, - R::overlay_shared::string::str1); - ASSERT_TARGET_ENTRY(target_entries[2], R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE, - R::overlay_shared::string::str3); - ASSERT_TARGET_ENTRY(target_entries[3], R::target::string::str4, Res_value::TYPE_DYNAMIC_REFERENCE, - R::overlay_shared::string::str4); + R::overlay_shared::integer::int1); + ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, R::overlay_shared::string::str1); + ASSERT_TARGET_ENTRY(target_entries[2], R::target::string::str3, R::overlay_shared::string::str3); + ASSERT_TARGET_ENTRY(target_entries[3], R::target::string::str4, R::overlay_shared::string::str4); + + const auto& target_inline_entries = data->GetTargetInlineEntries(); + ASSERT_EQ(target_inline_entries.size(), 0U); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(target_entries.size(), 4U); @@ -320,10 +330,12 @@ TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) { const auto& target_entries = data->GetTargetEntries(); ASSERT_EQ(target_entries.size(), 2U); - ASSERT_TARGET_ENTRY(target_entries[0], R::target::string::str1, Res_value::TYPE_REFERENCE, + ASSERT_TARGET_ENTRY(target_entries[0], R::target::string::str1, 0x0104000a); // -> android:string/ok - ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE, - R::overlay::string::str3); + ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str3, R::overlay::string::str3); + + const auto& target_inline_entries = data->GetTargetInlineEntries(); + ASSERT_EQ(target_inline_entries.size(), 0U); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(overlay_entries.size(), 1U); @@ -342,13 +354,17 @@ TEST(IdmapTests, CreateIdmapDataInlineResources) { ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage(); auto& data = *idmap_data; - constexpr size_t overlay_string_pool_size = 8U; const auto& target_entries = data->GetTargetEntries(); - ASSERT_EQ(target_entries.size(), 2U); - ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1, Res_value::TYPE_INT_DEC, - 73U); // -> 73 - ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, Res_value::TYPE_STRING, - overlay_string_pool_size + 0U); // -> "Hello World" + ASSERT_EQ(target_entries.size(), 0U); + + constexpr size_t overlay_string_pool_size = 8U; + 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, 73U); // -> 73 + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1, + Res_value::TYPE_STRING, + overlay_string_pool_size + 0U); // -> "Hello World" const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(overlay_entries.size(), 0U); @@ -479,9 +495,9 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { ASSERT_FALSE(bad_enforce_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), PolicyFlags::PUBLIC, /* enforce_overlayable */ true)); - // target path: bytes (0x15, 0x114) + // target path: bytes (0x18, 0x117) std::string bad_target_path_string(stream.str()); - bad_target_path_string[0x15] = '\0'; + bad_target_path_string[0x18] = '\0'; std::stringstream bad_target_path_stream(bad_target_path_string); std::unique_ptr bad_target_path_header = IdmapHeader::FromBinaryStream(bad_target_path_stream); @@ -490,9 +506,9 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { ASSERT_FALSE(bad_magic_header->IsUpToDate(target_apk_path.c_str(), overlay_apk_path.c_str(), PolicyFlags::PUBLIC, /* enforce_overlayable */ true)); - // overlay path: bytes (0x115, 0x214) + // overlay path: bytes (0x118, 0x217) std::string bad_overlay_path_string(stream.str()); - bad_overlay_path_string[0x115] = '\0'; + bad_overlay_path_string[0x118] = '\0'; std::stringstream bad_overlay_path_stream(bad_overlay_path_string); std::unique_ptr bad_overlay_path_header = IdmapHeader::FromBinaryStream(bad_overlay_path_stream); diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp index 9a10079772bf5..d30fbfcb1d3ce 100644 --- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp @@ -56,7 +56,8 @@ TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitor) { 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(R::target::integer::literal::int1 + " -> 0x7f010000 integer/int1\n"), + ASSERT_NE(stream.str().find(R::target::integer::literal::int1 + + " -> 0x7f010000 (integer/int1 -> integer/int1)\n"), std::string::npos); } @@ -75,7 +76,7 @@ TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitorWithoutAccessToApks) { 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("0x7f020000 -> 0x7f020000\n"), std::string::npos); + ASSERT_NE(stream.str().find("0x7f020000 -> 0x7f020000 (\?\?\? -> \?\?\?)\n"), std::string::npos); } } // namespace android::idmap2 diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp index b268d5add1413..95bd94733ab37 100644 --- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp @@ -65,7 +65,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { (*idmap)->accept(&visitor); ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "00000004 version\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000005 version\n", stream.str()); ASSERT_CONTAINS_REGEX( StringPrintf(ADDRESS "%s target crc\n", android::idmap2::TestConstants::TARGET_CRC_STRING), stream.str()); @@ -73,19 +73,19 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { StringPrintf(ADDRESS "%s overlay crc\n", android::idmap2::TestConstants::OVERLAY_CRC_STRING), stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000001 fulfilled policies: public\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS " 01 enforce overlayable\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\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000004 overlay entry count\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000004 overlay entry count\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000008 string pool index offset\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "000000b4 string pool byte length\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 target id: integer/int1\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS " 07 type: reference \\(dynamic\\)\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 value: integer/int1\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 overlay id: integer/int1\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 overlay id: integer/int1\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 target id: integer/int1\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "000000b4 string pool size\n", stream.str()); + ASSERT_CONTAINS_REGEX("000002bc: ........ string pool: ...\n", stream.str()); } TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) { @@ -102,22 +102,26 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) { (*idmap)->accept(&visitor); ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "00000004 version\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000005 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()); - ASSERT_CONTAINS_REGEX(ADDRESS " 01 enforce overlayable\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 "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()); ASSERT_CONTAINS_REGEX(ADDRESS "00000000 string pool index offset\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "00000000 string pool byte length\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS " 01 type: reference\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 value\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 overlay id\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS " 11 type: integer\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "12345678 data\n", stream.str()); + 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("00000278: ........ string pool: ...\n", stream.str()); } } // namespace android::idmap2 diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp index 3ec6ac24b238e..185e9292346d0 100644 --- a/cmds/idmap2/tests/ResourceMappingTests.cpp +++ b/cmds/idmap2/tests/ResourceMappingTests.cpp @@ -77,30 +77,61 @@ Result TestGetResourceMapping(const android::StringPiece& local fulfilled_policies, enforce_overlayable); } -Result MappingExists(const ResourceMapping& mapping, const ResourceId& target_resource, - const uint8_t type, const uint32_t value, bool rewrite) { +Result MappingExists(const ResourceMapping& mapping, ResourceId target_resource, + ResourceId overlay_resource, bool rewrite) { auto target_map = mapping.GetTargetToOverlayMap(); auto entry_map = target_map.find(target_resource); if (entry_map == target_map.end()) { return Error("Failed to find mapping for target resource"); } - if (entry_map->second.data_type != type) { - return Error(R"(Expected type: "0x%02x" Actual type: "0x%02x")", type, - entry_map->second.data_type); + auto actual_overlay_resource = std::get_if(&entry_map->second); + if (actual_overlay_resource == nullptr) { + return Error("Target resource is not mapped to an overlay resource id"); } - if (entry_map->second.data_value != value) { - return Error(R"(Expected value: "0x%08x" Actual value: "0x%08x")", type, - entry_map->second.data_value); + if (*actual_overlay_resource != overlay_resource) { + return Error(R"(Expected id: "0x%02x" Actual id: "0x%02x")", overlay_resource, + *actual_overlay_resource); } auto overlay_map = mapping.GetOverlayToTargetMap(); - auto overlay_iter = overlay_map.find(entry_map->second.data_value); + auto overlay_iter = overlay_map.find(overlay_resource); if ((overlay_iter != overlay_map.end()) != rewrite) { return Error(R"(Expected rewriting: "%s")", rewrite ? "true" : "false"); } + if (rewrite && overlay_iter->second != target_resource) { + return Error(R"(Expected rewrite id: "0x%02x" Actual id: "0x%02x")", target_resource, + overlay_iter->second); + } + + return Result({}); +} + +Result MappingExists(const ResourceMapping& mapping, const ResourceId& target_resource, + const uint8_t type, const uint32_t value) { + auto target_map = mapping.GetTargetToOverlayMap(); + auto entry_map = target_map.find(target_resource); + if (entry_map == target_map.end()) { + return Error("Failed to find mapping for target resource"); + } + + auto actual_overlay_value = std::get_if(&entry_map->second); + if (actual_overlay_value == nullptr) { + return Error("Target resource is not mapped to an inline value"); + } + + if (actual_overlay_value->data_type != type) { + return Error(R"(Expected type: "0x%02x" Actual type: "0x%02x")", type, + actual_overlay_value->data_type); + } + + if (actual_overlay_value->data_value != value) { + return Error(R"(Expected value: "0x%08x" Actual value: "0x%08x")", type, + actual_overlay_value->data_value); + } + return Result({}); } @@ -116,14 +147,14 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsLegacy) { ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U); - ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_REFERENCE, - R::overlay::integer::int1, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE, - R::overlay::string::str1, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_REFERENCE, - R::overlay::string::str3, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_REFERENCE, - R::overlay::string::str4, false /* rewrite */)); + ASSERT_RESULT( + MappingExists(res, R::target::integer::int1, R::overlay::integer::int1, false /* rewrite */)); + ASSERT_RESULT( + MappingExists(res, R::target::string::str1, R::overlay::string::str1, false /* rewrite */)); + ASSERT_RESULT( + MappingExists(res, R::target::string::str3, R::overlay::string::str3, false /* rewrite */)); + ASSERT_RESULT( + MappingExists(res, R::target::string::str4, R::overlay::string::str4, false /* rewrite */)); } TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) { @@ -138,12 +169,12 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) { ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U); - ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_DYNAMIC_REFERENCE, - R::overlay::string::str4, true /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE, - R::overlay::string::str1, true /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_DYNAMIC_REFERENCE, - R::overlay::string::str3, true /* rewrite */)); + ASSERT_RESULT( + MappingExists(res, R::target::string::str1, R::overlay::string::str4, true /* rewrite */)); + ASSERT_RESULT( + MappingExists(res, R::target::string::str3, R::overlay::string::str1, true /* rewrite */)); + ASSERT_RESULT( + MappingExists(res, R::target::string::str4, R::overlay::string::str3, true /* rewrite */)); } TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) { @@ -159,10 +190,9 @@ TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) { auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U); ASSERT_EQ(res.GetOverlayToTargetMap().size(), 1U); - ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE, 0x0104000a, + ASSERT_RESULT(MappingExists(res, R::target::string::str1, 0x0104000a, false /* rewrite */)); // -> android:string/ok - ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE, - 0x7f020001, true /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::str3, 0x7f020001, true /* rewrite */)); } TEST(ResourceMappingTests, InlineResources) { @@ -180,10 +210,8 @@ TEST(ResourceMappingTests, InlineResources) { ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U); ASSERT_EQ(res.GetOverlayToTargetMap().size(), 0U); ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_STRING, - overlay_string_pool_size + 0U, - false /* rewrite */)); // -> "Hello World" - ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_INT_DEC, 73U, - false /* rewrite */)); // -> 73 + overlay_string_pool_size + 0U)); // -> "Hello World" + ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_INT_DEC, 73U)); } TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublic) { @@ -195,13 +223,13 @@ TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublic) { ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, R::system_overlay::string::policy_public, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, R::system_overlay::string::policy_system, false /* rewrite */)); - ASSERT_RESULT( - MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE, - R::system_overlay::string::policy_system_vendor, false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_system_vendor, + R::system_overlay::string::policy_system_vendor, + false /* rewrite */)); } // Resources that are not declared as overlayable and resources that a protected by policies the @@ -215,15 +243,15 @@ TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) { ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, R::system_overlay_invalid::string::policy_public, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, R::system_overlay_invalid::string::policy_system, false /* rewrite */)); - ASSERT_RESULT( - MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_system_vendor, + R::system_overlay_invalid::string::policy_system_vendor, + false /* rewrite */)); } // Resources that are not declared as overlayable and resources that a protected by policies the @@ -238,37 +266,36 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnore ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 11U); - ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, R::system_overlay_invalid::string::not_overlayable, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::other, R::system_overlay_invalid::string::other, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, R::system_overlay_invalid::string::policy_actor, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, R::system_overlay_invalid::string::policy_odm, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, R::system_overlay_invalid::string::policy_oem, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, R::system_overlay_invalid::string::policy_product, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, R::system_overlay_invalid::string::policy_public, false /* rewrite */)); ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature, - Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::policy_config_signature, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, R::system_overlay_invalid::string::policy_signature, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, R::system_overlay_invalid::string::policy_system, false /* rewrite */)); - ASSERT_RESULT( - MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_system_vendor, + R::system_overlay_invalid::string::policy_system_vendor, + false /* rewrite */)); } // Overlays that do not target an tag can overlay resources defined within any @@ -281,14 +308,14 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsNoDefinedOverlayableAndNoTarget ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U); - ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_REFERENCE, - R::overlay::integer::int1, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE, - R::overlay::string::str1, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_REFERENCE, - R::overlay::string::str3, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_REFERENCE, - R::overlay::string::str4, false /* rewrite */)); + ASSERT_RESULT( + MappingExists(res, R::target::integer::int1, R::overlay::integer::int1, false /* rewrite */)); + ASSERT_RESULT( + MappingExists(res, R::target::string::str1, R::overlay::string::str1, false /* rewrite */)); + ASSERT_RESULT( + MappingExists(res, R::target::string::str3, R::overlay::string::str3, false /* rewrite */)); + ASSERT_RESULT( + MappingExists(res, R::target::string::str4, R::overlay::string::str4, false /* rewrite */)); } // Overlays that are neither pre-installed nor signed with the same signature as the target cannot @@ -302,9 +329,9 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) { ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U); } -// Overlays that are pre-installed or are signed with the same signature as the target or are signed -// with the same signature as the reference package can overlay packages that have not defined -// overlayable resources. +// Overlays that are pre-installed or are signed with the same signature as the target or are +// 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 resources = TestGetResourceMapping("/target/target-no-overlayable.apk", @@ -315,39 +342,38 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) { ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 11U); - ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, R::system_overlay_invalid::string::not_overlayable, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::other, R::system_overlay_invalid::string::other, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, R::system_overlay_invalid::string::policy_actor, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, R::system_overlay_invalid::string::policy_odm, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, R::system_overlay_invalid::string::policy_oem, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, R::system_overlay_invalid::string::policy_product, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, R::system_overlay_invalid::string::policy_public, false /* rewrite */)); ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature, - Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::policy_config_signature, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, R::system_overlay_invalid::string::policy_signature, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE, + ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, R::system_overlay_invalid::string::policy_system, false /* rewrite */)); - ASSERT_RESULT(MappingExists( - res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_system_vendor, + R::system_overlay_invalid::string::policy_system_vendor, + false /* rewrite */)); }; CheckEntries(PolicyFlags::SIGNATURE); diff --git a/cmds/idmap2/tests/TestConstants.h b/cmds/idmap2/tests/TestConstants.h index 641a7a8d45aa1..9bbb065f46f0f 100644 --- a/cmds/idmap2/tests/TestConstants.h +++ b/cmds/idmap2/tests/TestConstants.h @@ -19,7 +19,7 @@ namespace android::idmap2::TestConstants { -constexpr const auto TARGET_CRC = 0x7c2d4719; +constexpr const auto TARGET_CRC = 0x7c2d4719; constexpr const auto TARGET_CRC_STRING = "7c2d4719"; constexpr const auto OVERLAY_CRC = 0x5afff726; diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h index b599dcb0069ab..d0a8e3db8ecae 100644 --- a/cmds/idmap2/tests/TestHelpers.h +++ b/cmds/idmap2/tests/TestHelpers.h @@ -30,7 +30,7 @@ const unsigned char idmap_raw_data[] = { 0x49, 0x44, 0x4d, 0x50, // 0x4: version - 0x04, 0x00, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, // 0x8: target crc 0x34, 0x12, 0x00, 0x00, @@ -42,9 +42,9 @@ const unsigned char idmap_raw_data[] = { 0x11, 0x00, 0x00, 0x00, // 0x14: enforce overlayable - 0x01, + 0x01, 0x00, 0x00, 0x00, - // 0x15: target path "targetX.apk" + // 0x18: target path "targetX.apk" 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -62,7 +62,7 @@ const unsigned char idmap_raw_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // 0x115: overlay path "overlayX.apk" + // 0x118: overlay path "overlayX.apk" 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x61, 0x79, 0x58, 0x2e, 0x61, 0x70, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -80,71 +80,89 @@ const unsigned char idmap_raw_data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // 0x215: debug string - // string length, including terminating null - 0x08, 0x00, 0x00, 0x00, + // 0x218: debug string + // string length, + 0x05, 0x00, 0x00, 0x00, - // string contents "debug\0\0\0" (padded to word alignment) + // 0x21c string contents "debug\0\0\0" (padded to word alignment) 0x64, 0x65, 0x62, 0x75, 0x67, 0x00, 0x00, 0x00, // DATA HEADER - // 0x221: target_package_id + // 0x224: target_package_id 0x7f, - // 0x222: overlay_package_id + // 0x225: overlay_package_id 0x7f, - // 0x223: target_entry_count + // 0x226: padding + 0x00, 0x00, + + // 0x228: target_entry_count 0x03, 0x00, 0x00, 0x00, - // 0x227: overlay_entry_count + // 0x22c: target_inline_entry_count + 0x01, 0x00, 0x00, 0x00, + + // 0x230: overlay_entry_count 0x03, 0x00, 0x00, 0x00, - // 0x22b: string_pool_offset - 0x00, 0x00, 0x00, 0x00, - - // 0x22f: string_pool_byte_length + // 0x234: string_pool_offset 0x00, 0x00, 0x00, 0x00, // TARGET ENTRIES - // 0x233: 0x7f020000 + // 0x238: target id (0x7f020000) 0x00, 0x00, 0x02, 0x7f, - // 0x237: TYPE_REFERENCE - 0x01, - - // 0x238: 0x7f020000 + // 0x23c: overlay_id (0x7f020000) 0x00, 0x00, 0x02, 0x7f, - // 0x23c: 0x7f030000 + // 0x240: target id (0x7f030000) 0x00, 0x00, 0x03, 0x7f, - // 0x240: TYPE_REFERENCE - 0x01, - - // 0x241: 0x7f030000 + // 0x244: overlay_id (0x7f030000) 0x00, 0x00, 0x03, 0x7f, - // 0x245: 0x7f030002 + // 0x248: target id (0x7f030002) 0x02, 0x00, 0x03, 0x7f, - // 0x249: TYPE_REFERENCE - 0x01, - - // 0x24a: 0x7f030001 + // 0x24c: overlay_id (0x7f030001) 0x01, 0x00, 0x03, 0x7f, + // INLINE TARGET ENTRIES + + // 0x250: target_id + 0x00, 0x00, 0x04, 0x7f, + + // 0x254: Res_value::size (value ignored by idmap) + 0x08, 0x00, + + // 0x256: Res_value::res0 (value ignored by idmap) + 0x00, + + // 0x257: Res_value::dataType (TYPE_INT_HEX) + 0x11, + + // 0x258: Res_value::data + 0x78, 0x56, 0x34, 0x12, + // OVERLAY ENTRIES - // 0x24e: 0x7f020000 -> 0x7f020000 + // 0x25c: 0x7f020000 -> 0x7f020000 0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f, - // 0x256: 0x7f030000 -> 0x7f030000 + // 0x264: 0x7f030000 -> 0x7f030000 0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x03, 0x7f, - // 0x25e: 0x7f030001 -> 0x7f030002 - 0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f}; + // 0x26c: 0x7f030001 -> 0x7f030002 + 0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f, -const unsigned int idmap_raw_data_len = 0x266; + // 0x274: string pool + // string length, + 0x04, 0x00, 0x00, 0x00, + + // 0x278 string contents "test" (padded to word alignment) + 0x74, 0x65, 0x73, 0x74}; + +const unsigned int idmap_raw_data_len = 0x27c; std::string GetTestDataPath(); diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index b9765ea7212c1..99dd3134ff8a6 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -39,10 +39,8 @@ namespace android { struct FindEntryResult { - // A pointer to the resource table entry for this resource. - // If the size of the entry is > sizeof(ResTable_entry), it can be cast to - // a ResTable_map_entry and processed as a bag/map. - ResTable_entry_handle entry; + // A pointer to the value of the resource table entry. + std::variant entry; // The configuration for which the resulting entry was defined. This is already swapped to host // endianness. @@ -554,11 +552,9 @@ ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_overri if (!overlay_entry) { // No id map entry exists for this target resource. continue; - } - - if (overlay_entry.IsTableEntry()) { + } else if (overlay_entry.IsInlineValue()) { // The target resource is overlaid by an inline value not represented by a resource. - out_entry->entry = overlay_entry.GetTableEntry(); + out_entry->entry = overlay_entry.GetInlineValue(); out_entry->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); cookie = id_map.cookie; continue; @@ -580,7 +576,7 @@ ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_overri } cookie = overlay_cookie; - out_entry->entry = std::move(overlay_result.entry); + out_entry->entry = overlay_result.entry; out_entry->config = overlay_result.config; out_entry->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); if (resource_resolution_logging_enabled_) { @@ -761,7 +757,19 @@ ApkAssetsCookie AssetManager2::FindEntryInternal(const PackageGroup& package_gro return kInvalidCookie; } - out_entry->entry = ResTable_entry_handle::unmanaged(best_entry); + const uint16_t entry_size = dtohs(best_entry->size); + if (entry_size >= sizeof(ResTable_map_entry) && + (dtohs(best_entry->flags) & ResTable_entry::FLAG_COMPLEX)) { + // The entry represents a bag/map. + out_entry->entry = reinterpret_cast(best_entry); + } else { + // The entry represents a value. + Res_value value; + value.copyFrom_dtoh(*reinterpret_cast( + reinterpret_cast(best_entry) + entry_size)); + out_entry->entry = value; + } + out_entry->config = *best_config; out_entry->type_flags = type_flags; out_entry->package_name = &best_package->GetPackageName(); @@ -905,8 +913,8 @@ ApkAssetsCookie AssetManager2::GetResource(uint32_t resid, bool may_be_bag, return kInvalidCookie; } - const ResTable_entry* table_entry = *entry.entry; - if (dtohs(table_entry->flags) & ResTable_entry::FLAG_COMPLEX) { + auto result_map_entry = std::get_if(&entry.entry); + if (result_map_entry != nullptr) { if (!may_be_bag) { LOG(ERROR) << base::StringPrintf("Resource %08x is a complex map type.", resid); return kInvalidCookie; @@ -920,11 +928,8 @@ ApkAssetsCookie AssetManager2::GetResource(uint32_t resid, bool may_be_bag, return cookie; } - const Res_value* device_value = reinterpret_cast( - reinterpret_cast(table_entry) + dtohs(table_entry->size)); - out_value->copyFrom_dtoh(*device_value); - // Convert the package ID to the runtime assigned package ID. + *out_value = std::get(entry.entry); entry.dynamic_ref_table->lookupResourceValue(out_value); *out_selected_config = entry.config; @@ -1004,19 +1009,15 @@ const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector& return nullptr; } - // Check that the size of the entry header is at least as big as - // the desired ResTable_map_entry. Also verify that the entry - // was intended to be a map. - const ResTable_entry* table_entry = *entry.entry; - if (dtohs(table_entry->size) < sizeof(ResTable_map_entry) || - (dtohs(table_entry->flags) & ResTable_entry::FLAG_COMPLEX) == 0) { + auto result_map_entry = std::get_if(&entry.entry); + if (result_map_entry == nullptr) { // Not a bag, nothing to do. return nullptr; } - const ResTable_map_entry* map = reinterpret_cast(table_entry); - const ResTable_map* map_entry = - reinterpret_cast(reinterpret_cast(map) + map->size); + auto map = reinterpret_cast(*result_map_entry); + auto map_entry = reinterpret_cast( + reinterpret_cast(map) + map->size); const ResTable_map* const map_entry_end = map_entry + dtohl(map->count); // Keep track of ids that have already been seen to prevent infinite loops caused by circular diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp index 5f231ffe47862..4e03ce5d95843 100644 --- a/libs/androidfw/Idmap.cpp +++ b/libs/androidfw/Idmap.cpp @@ -36,16 +36,12 @@ using ::android::base::StringPrintf; namespace android { -static bool compare_target_entries(const Idmap_target_entry &e1, const uint32_t target_id) { - return dtohl(e1.target_id) < target_id; -} - -static bool compare_overlay_entries(const Idmap_overlay_entry& e1, const uint32_t overlay_id) { - return dtohl(e1.overlay_id) < overlay_id; +uint32_t round_to_4_bytes(uint32_t size) { + return size + (4U - (size % 4U)) % 4U; } size_t Idmap_header::Size() const { - return sizeof(Idmap_header) + sizeof(uint8_t) * dtohl(debug_info_size); + return sizeof(Idmap_header) + sizeof(uint8_t) * round_to_4_bytes(dtohl(debug_info_size)); } OverlayStringPool::OverlayStringPool(const LoadedIdmap* loaded_idmap) @@ -88,7 +84,10 @@ OverlayDynamicRefTable::OverlayDynamicRefTable(const Idmap_data_header* data_hea status_t OverlayDynamicRefTable::lookupResourceId(uint32_t* resId) const { const Idmap_overlay_entry* first_entry = entries_; const Idmap_overlay_entry* end_entry = entries_ + dtohl(data_header_->overlay_entry_count); - auto entry = std::lower_bound(first_entry, end_entry, *resId, compare_overlay_entries); + auto entry = std::lower_bound(first_entry, end_entry, *resId, + [](const Idmap_overlay_entry& e1, const uint32_t overlay_id) { + return dtohl(e1.overlay_id) < overlay_id; + }); if (entry == end_entry || dtohl(entry->overlay_id) != *resId) { // A mapping for the target resource id could not be found. @@ -96,7 +95,7 @@ status_t OverlayDynamicRefTable::lookupResourceId(uint32_t* resId) const { } *resId = (0x00FFFFFFU & dtohl(entry->target_id)) - | (((uint32_t) target_assigned_package_id_) << 24); + | (((uint32_t) target_assigned_package_id_) << 24U); return NO_ERROR; } @@ -106,62 +105,58 @@ status_t OverlayDynamicRefTable::lookupResourceIdNoRewrite(uint32_t* resId) cons IdmapResMap::IdmapResMap(const Idmap_data_header* data_header, const Idmap_target_entry* entries, + const Idmap_target_entry_inline* inline_entries, uint8_t target_assigned_package_id, const OverlayDynamicRefTable* overlay_ref_table) : data_header_(data_header), entries_(entries), + inline_entries_(inline_entries), target_assigned_package_id_(target_assigned_package_id), - overlay_ref_table_(overlay_ref_table) { }; + overlay_ref_table_(overlay_ref_table) { } IdmapResMap::Result IdmapResMap::Lookup(uint32_t target_res_id) const { - if ((target_res_id >> 24) != target_assigned_package_id_) { + if ((target_res_id >> 24U) != target_assigned_package_id_) { // The resource id must have the same package id as the target package. return {}; } // The resource ids encoded within the idmap are build-time resource ids. target_res_id = (0x00FFFFFFU & target_res_id) - | (((uint32_t) data_header_->target_package_id) << 24); + | (((uint32_t) data_header_->target_package_id) << 24U); - const Idmap_target_entry* first_entry = entries_; - const Idmap_target_entry* end_entry = entries_ + dtohl(data_header_->target_entry_count); - auto entry = std::lower_bound(first_entry, end_entry, target_res_id, compare_target_entries); - - if (entry == end_entry || dtohl(entry->target_id) != target_res_id) { - // A mapping for the target resource id could not be found. - return {}; - } - - // A reference should be treated as an alias of the resource. Instead of returning the table - // entry, return the alias resource id to look up. The alias resource might not reside within the - // overlay package, so the resource id must be fixed with the dynamic reference table of the - // overlay before returning. - if (entry->type == Res_value::TYPE_REFERENCE - || entry->type == Res_value::TYPE_DYNAMIC_REFERENCE) { - uint32_t overlay_resource_id = dtohl(entry->value); + // Check if the target resource is mapped to an overlay resource. + auto first_entry = entries_; + auto end_entry = entries_ + dtohl(data_header_->target_entry_count); + auto entry = std::lower_bound(first_entry, end_entry, target_res_id, + [](const Idmap_target_entry &e, const uint32_t target_id) { + return dtohl(e.target_id) < target_id; + }); + if (entry != end_entry && dtohl(entry->target_id) == target_res_id) { + uint32_t overlay_resource_id = dtohl(entry->overlay_id); // Lookup the resource without rewriting the overlay resource id back to the target resource id // being looked up. overlay_ref_table_->lookupResourceIdNoRewrite(&overlay_resource_id); return Result(overlay_resource_id); } - // Copy the type and value into the ResTable_entry structure needed by asset manager. - uint16_t malloc_size = sizeof(ResTable_entry) + sizeof(Res_value); - auto table_entry = reinterpret_cast(malloc(malloc_size)); - memset(table_entry, 0, malloc_size); - table_entry->size = htods(sizeof(ResTable_entry)); + // Check if the target resources is mapped to an inline table entry. + auto first_inline_entry = inline_entries_; + auto end_inline_entry = inline_entries_ + dtohl(data_header_->target_inline_entry_count); + auto inline_entry = std::lower_bound(first_inline_entry, end_inline_entry, target_res_id, + [](const Idmap_target_entry_inline &e, + const uint32_t target_id) { + return dtohl(e.target_id) < target_id; + }); - auto table_value = reinterpret_cast(reinterpret_cast(table_entry) - + sizeof(ResTable_entry)); - table_value->dataType = entry->type; - table_value->data = entry->value; - - return Result(ResTable_entry_handle::managed(table_entry, [](auto p) { free(p); })); + if (inline_entry != end_inline_entry && dtohl(inline_entry->target_id) == target_res_id) { + return Result(inline_entry->value); + } + return {}; } static bool is_word_aligned(const void* data) { - return (reinterpret_cast(data) & 0x03) == 0; + return (reinterpret_cast(data) & 0x03U) == 0U; } static bool IsValidIdmapHeader(const StringPiece& data) { @@ -175,7 +170,7 @@ static bool IsValidIdmapHeader(const StringPiece& data) { return false; } - const Idmap_header* header = reinterpret_cast(data.data()); + auto header = reinterpret_cast(data.data()); if (dtohl(header->magic) != kIdmapMagic) { LOG(ERROR) << StringPrintf("Invalid Idmap file: bad magic value (was 0x%08x, expected 0x%08x)", dtohl(header->magic), kIdmapMagic); @@ -198,11 +193,13 @@ LoadedIdmap::LoadedIdmap(std::string&& idmap_path, const Idmap_header* header, const Idmap_data_header* data_header, const Idmap_target_entry* target_entries, + const Idmap_target_entry_inline* target_inline_entries, const Idmap_overlay_entry* overlay_entries, ResStringPool* string_pool) : header_(header), data_header_(data_header), target_entries_(target_entries), + target_inline_entries_(target_inline_entries), overlay_entries_(overlay_entries), string_pool_(string_pool), idmap_path_(std::move(idmap_path)), @@ -233,7 +230,7 @@ std::unique_ptr LoadedIdmap::Load(const StringPiece& idmap_pa data_ptr += sizeof(*data_header); data_size -= sizeof(*data_header); - // Make sure there is enough space for the target entries declared in the header. + // Make sure there is enough space for the target entries declared in the header const auto target_entries = reinterpret_cast(data_ptr); if (data_size / sizeof(Idmap_target_entry) < static_cast(dtohl(data_header->target_entry_count))) { @@ -248,6 +245,21 @@ std::unique_ptr LoadedIdmap::Load(const StringPiece& idmap_pa data_ptr += target_entry_size_bytes; data_size -= target_entry_size_bytes; + // Make sure there is enough space for the target entries declared in the header. + const auto target_inline_entries = reinterpret_cast(data_ptr); + if (data_size / sizeof(Idmap_target_entry_inline) < + static_cast(dtohl(data_header->target_inline_entry_count))) { + LOG(ERROR) << StringPrintf("Idmap too small for the number of target inline entries (%d)", + (int)dtohl(data_header->target_inline_entry_count)); + return {}; + } + + // Advance the data pointer past the target entries. + const size_t target_inline_entry_size_bytes = + (dtohl(data_header->target_inline_entry_count) * sizeof(Idmap_target_entry_inline)); + data_ptr += target_inline_entry_size_bytes; + data_size -= target_inline_entry_size_bytes; + // Make sure there is enough space for the overlay entries declared in the header. const auto overlay_entries = reinterpret_cast(data_ptr); if (data_size / sizeof(Idmap_overlay_entry) < @@ -257,22 +269,26 @@ std::unique_ptr LoadedIdmap::Load(const StringPiece& idmap_pa return {}; } - // Advance the data pointer past the target entries. + // Advance the data pointer past the overlay entries. const size_t overlay_entry_size_bytes = (dtohl(data_header->overlay_entry_count) * sizeof(Idmap_overlay_entry)); data_ptr += overlay_entry_size_bytes; data_size -= overlay_entry_size_bytes; // Read the idmap string pool that holds the value of inline string entries. - if (data_size < dtohl(data_header->string_pool_length)) { + uint32_t string_pool_size = dtohl(*reinterpret_cast(data_ptr)); + data_ptr += sizeof(uint32_t); + data_size -= sizeof(uint32_t); + + if (data_size < string_pool_size) { LOG(ERROR) << StringPrintf("Idmap too small for string pool (length %d)", - (int)dtohl(data_header->string_pool_length)); + (int)string_pool_size); return {}; } auto idmap_string_pool = util::make_unique(); - if (dtohl(data_header->string_pool_length) > 0) { - status_t err = idmap_string_pool->setTo(data_ptr, dtohl(data_header->string_pool_length)); + if (string_pool_size > 0) { + status_t err = idmap_string_pool->setTo(data_ptr, string_pool_size); if (err != NO_ERROR) { LOG(ERROR) << "idmap string pool corrupt."; return {}; @@ -280,9 +296,10 @@ std::unique_ptr LoadedIdmap::Load(const StringPiece& idmap_pa } // Can't use make_unique because LoadedIdmap constructor is private. - std::unique_ptr loaded_idmap = std::unique_ptr( + auto loaded_idmap = std::unique_ptr( new LoadedIdmap(idmap_path.to_string(), getFileModDate(idmap_path.data()), header, - data_header, target_entries, overlay_entries, idmap_string_pool.release())); + data_header, target_entries, target_inline_entries, overlay_entries, + idmap_string_pool.release())); return std::move(loaded_idmap); } diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h index ecc1ce65d124a..ab0f47f025d20 100644 --- a/libs/androidfw/include/androidfw/Idmap.h +++ b/libs/androidfw/include/androidfw/Idmap.h @@ -77,40 +77,40 @@ class OverlayDynamicRefTable : public DynamicRefTable { // A mapping of target resource ids to a values or resource ids that should overlay the target. class IdmapResMap { public: - // Represents the result of a idmap lookup. The result can be one of three possibillities: + // Represents the result of a idmap lookup. The result can be one of three possibilities: // 1) The result is a resource id which represents the overlay resource that should act as an // alias of the target resource. // 2) The result is a table entry which overlays the type and value of the target resource. // 3) The result is neither and the target resource is not overlaid. class Result { public: - Result() : data_(nullptr) {}; + Result() = default; explicit Result(uint32_t value) : data_(value) {}; - explicit Result(ResTable_entry_handle&& value) : data_(value) { }; + explicit Result(const Res_value& value) : data_(value) { }; // Returns `true` if the resource is overlaid. - inline explicit operator bool() const { - return !std::get_if(&data_); + explicit operator bool() const { + return std::get_if(&data_) == nullptr; } - inline bool IsResourceId() const { - return std::get_if(&data_); + bool IsResourceId() const { + return std::get_if(&data_) != nullptr; } - inline uint32_t GetResourceId() const { - return *std::get_if(&data_); + uint32_t GetResourceId() const { + return std::get(data_); } - inline bool IsTableEntry() const { - return std::get_if(&data_); + bool IsInlineValue() const { + return std::get_if(&data_) != nullptr; } - inline const ResTable_entry_handle& GetTableEntry() const { - return *std::get_if(&data_); + const Res_value& GetInlineValue() const { + return std::get(data_); } private: - std::variant data_; + std::variant data_; }; // Looks up the value that overlays the target resource id. @@ -123,11 +123,13 @@ class IdmapResMap { private: explicit IdmapResMap(const Idmap_data_header* data_header, const Idmap_target_entry* entries, + const Idmap_target_entry_inline* inline_entries, uint8_t target_assigned_package_id, const OverlayDynamicRefTable* overlay_ref_table); const Idmap_data_header* data_header_; const Idmap_target_entry* entries_; + const Idmap_target_entry_inline* inline_entries_; const uint8_t target_assigned_package_id_; const OverlayDynamicRefTable* overlay_ref_table_; @@ -163,8 +165,8 @@ class LoadedIdmap { // Returns a mapping from target resource ids to overlay values. inline const IdmapResMap GetTargetResourcesMap( uint8_t target_assigned_package_id, const OverlayDynamicRefTable* overlay_ref_table) const { - return IdmapResMap(data_header_, target_entries_, target_assigned_package_id, - overlay_ref_table); + return IdmapResMap(data_header_, target_entries_, target_inline_entries_, + target_assigned_package_id, overlay_ref_table); } // Returns a dynamic reference table for a loaded overlay package. @@ -184,6 +186,7 @@ class LoadedIdmap { const Idmap_header* header_; const Idmap_data_header* data_header_; const Idmap_target_entry* target_entries_; + const Idmap_target_entry_inline* target_inline_entries_; const Idmap_overlay_entry* overlay_entries_; const std::unique_ptr string_pool_; @@ -200,6 +203,7 @@ class LoadedIdmap { const Idmap_header* header, const Idmap_data_header* data_header, const Idmap_target_entry* target_entries, + const Idmap_target_entry_inline* target_inline_entries, const Idmap_overlay_entry* overlay_entries, ResStringPool* string_pool); diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index e10a7f3f5c61b..04ba78b6705db 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -41,7 +41,7 @@ namespace android { constexpr const static uint32_t kIdmapMagic = 0x504D4449u; -constexpr const static uint32_t kIdmapCurrentVersion = 0x00000004u; +constexpr const static uint32_t kIdmapCurrentVersion = 0x00000005u; /** * In C++11, char16_t is defined as *at least* 16 bits. We do a lot of @@ -1476,7 +1476,7 @@ struct ResTable_entry // If set, this is a weak resource and may be overriden by strong // resources of the same name/type. This is only useful during // linking with other resource tables. - FLAG_WEAK = 0x0004 + FLAG_WEAK = 0x0004, }; uint16_t flags; @@ -1586,50 +1586,6 @@ struct ResTable_map Res_value value; }; - -// A ResTable_entry variant that either holds an unmanaged pointer to a constant ResTable_entry or -// holds a ResTable_entry which is tied to the lifetime of the handle. -class ResTable_entry_handle { - public: - ResTable_entry_handle() = default; - - ResTable_entry_handle(const ResTable_entry_handle& handle) { - entry_ = handle.entry_; - } - - ResTable_entry_handle(ResTable_entry_handle&& handle) noexcept { - entry_ = handle.entry_; - } - - inline static ResTable_entry_handle managed(ResTable_entry* entry, void (*deleter)(void *)) { - return ResTable_entry_handle(std::shared_ptr(entry, deleter)); - } - - inline static ResTable_entry_handle unmanaged(const ResTable_entry* entry) { - return ResTable_entry_handle(std::shared_ptr(entry, [](auto /*p */){})); - } - - inline ResTable_entry_handle& operator=(const ResTable_entry_handle& handle) noexcept { - entry_ = handle.entry_; - return *this; - } - - inline ResTable_entry_handle& operator=(ResTable_entry_handle&& handle) noexcept { - entry_ = handle.entry_; - return *this; - } - - inline const ResTable_entry* operator*() & { - return entry_.get(); - } - - private: - explicit ResTable_entry_handle(std::shared_ptr entry) - : entry_(std::move(entry)) { } - - std::shared_ptr entry_; -}; - /** * A package-id to package name mapping for any shared libraries used * in this resource table. The package-id's encoded in this resource @@ -1740,7 +1696,6 @@ inline ResTable_overlayable_policy_header::PolicyFlags& operator |=( return first; } -#pragma pack(push, 1) struct Idmap_header { // Always 0x504D4449 ('IDMP') uint32_t magic; @@ -1751,7 +1706,7 @@ struct Idmap_header { uint32_t overlay_crc32; uint32_t fulfilled_policies; - uint8_t enforce_overlayable; + uint32_t enforce_overlayable; uint8_t target_path[256]; uint8_t overlay_path[256]; @@ -1765,23 +1720,31 @@ struct Idmap_header { struct Idmap_data_header { uint8_t target_package_id; uint8_t overlay_package_id; + + // Padding to ensure 4 byte alignment for target_entry_count + uint16_t p0; + uint32_t target_entry_count; + uint32_t target_inline_entry_count; uint32_t overlay_entry_count; + uint32_t string_pool_index_offset; - uint32_t string_pool_length; }; struct Idmap_target_entry { uint32_t target_id; - uint8_t type; - uint32_t value; + uint32_t overlay_id; +}; + +struct Idmap_target_entry_inline { + uint32_t target_id; + Res_value value; }; struct Idmap_overlay_entry { uint32_t overlay_id; uint32_t target_id; }; -#pragma pack(pop) class AssetManager2; diff --git a/libs/androidfw/tests/data/overlay/overlay.apk b/libs/androidfw/tests/data/overlay/overlay.apk index f1ed59279fdb47bee0004f87f32601ef5c500b8c..c9bf2527c82aaa7d4666568dfdf019a1c6bc336e 100644 GIT binary patch delta 527 zcmV+q0`UE?7pxZ>P)h>@000002mk>CnNxWc^l_UyQT3Y)YB0hxAU}a_H1K8^~lhGs_ z1l{GIIs5=Nn)+O#%x<>G5F*Wk!y-X4fpmhIaPV+OAVYc$c%n57wC*HTPb zVvjbqjdg@(Yb@iR|AT+jSC_P?Q}{Mjud2w~BF8Bnb(eQAQ)h*LqTA;=bEgNzf!aft zp~2U&U)%05zIui%{U@1+v1*&R2+z9K=$1W~$}cDKpP25=xHTcSRhpMErKB;Z*_8GWpgfJa&u#|`vj>43D)ll45k4902q_43Q_^rk_$!w^pi&m RK>^E?i3=eHkO}|*001Ow_CEjs delta 526 zcmV+p0`dK<7qAx>P)h>@000002mkOgg!=!j^O zxU6&D_FL-jP}hHntBxNbDLpsA7HHDAHgxTLE>Ld3p_^f=Yvdx?8T1;n)KSjpr3qizd_tLLm3CB<=n&0T zStft-5BX6?Mbey3;hWUGtP-t($0-?A=iBYnnxW)YdQN}e+J#bA?OEqg9Vh0Kuibxa;lg>I=ufqX^yiC=pZ8kH$+WWT-XlV!<1}a?tF>sTcr@5>`**<=cZVI%@KT&LV@1Is ea|2b(`4vKLvYL6Z{pIXt&u*jbd|=`JvO&K+dKjSq delta 166 zcmX@Yafn0I)5SM{g@J*=H>84u6F<5{ME+B(Zn1O|n8^~Y=8NtB71k?cJF@SXfc|arU Y1+>6YY#=FSpvdG&OlF(UFjX)D0G)9bga7~l From 7d0ccc133bd0a691f0f1f1e56be533f57ee19e95 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Wed, 14 Oct 2020 14:19:19 -0700 Subject: [PATCH 3/4] Fix non-inclusive OMS test language Bug: 162729394 Test: atest . Change-Id: I86b869af11c0d70bbb2aeaaa85d5c1eb83fc2e3a --- .../OverlayManagerServiceImplRebootTests.java | 4 +- .../om/OverlayManagerServiceImplTests.java | 48 ++++++------ .../OverlayManagerServiceImplTestsBase.java | 76 +++++++++---------- .../om/OverlayManagerSettingsTests.java | 56 +++++++------- 4 files changed, 92 insertions(+), 92 deletions(-) diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java index e281f2b206f59..391611b72dab8 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java @@ -35,8 +35,8 @@ import java.util.function.BiConsumer; @RunWith(AndroidJUnit4.class) public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceImplTestsBase { - private static final String OVERLAY = "com.dummy.overlay"; - private static final String TARGET = "com.dummy.target"; + private static final String OVERLAY = "com.test.overlay"; + private static final String TARGET = "com.test.target"; private static final int USER = 0; private static final String OVERLAY2 = OVERLAY + "2"; diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java index c1d862ab2ad4b..4f882ce13dd4f 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java @@ -39,8 +39,8 @@ import java.util.Map; @RunWith(AndroidJUnit4.class) public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase { - private static final String OVERLAY = "com.dummy.overlay"; - private static final String TARGET = "com.dummy.target"; + private static final String OVERLAY = "com.test.overlay"; + private static final String TARGET = "com.test.target"; private static final int USER = 0; private static final String OVERLAY2 = OVERLAY + "2"; @@ -50,7 +50,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes private static final String OVERLAY3 = OVERLAY + "3"; private static final int USER3 = USER2 + 1; - private static final String CONFIG_SIGNATURE_REFERENCE_PKG = "com.dummy.ref"; + private static final String CONFIG_SIGNATURE_REFERENCE_PKG = "com.test.ref"; private static final String CERT_CONFIG_OK = "config_certificate_ok"; private static final String CERT_CONFIG_NOK = "config_certificate_nok"; @@ -149,7 +149,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes installNewPackage(overlay(OVERLAY, TARGET), USER); assertState(STATE_MISSING_TARGET, OVERLAY, USER); - final DummyDeviceState.PackageBuilder target = target(TARGET); + final FakeDeviceState.PackageBuilder target = target(TARGET); installNewPackage(target, USER); assertState(STATE_DISABLED, OVERLAY, USER); @@ -169,9 +169,9 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes @Test public void testOnOverlayPackageUpgraded() { - final DummyListener listener = getListener(); - final DummyDeviceState.PackageBuilder target = target(TARGET); - final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET); + final FakeListener listener = getListener(); + final FakeDeviceState.PackageBuilder target = target(TARGET); + final FakeDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET); installNewPackage(target, USER); installNewPackage(overlay, USER); listener.count = 0; @@ -181,7 +181,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes // upgrade to a version where the overlay has changed its target // expect once for the old target package, once for the new target package listener.count = 0; - final DummyDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target"); + final FakeDeviceState.PackageBuilder overlay2 = overlay(OVERLAY, "some.other.target"); upgradePackage(overlay2, USER); assertEquals(3, listener.count); @@ -193,7 +193,7 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes @Test public void testListener() { final OverlayManagerServiceImpl impl = getImpl(); - final DummyListener listener = getListener(); + final FakeListener listener = getListener(); installNewPackage(overlay(OVERLAY, TARGET), USER); assertEquals(1, listener.count); listener.count = 0; @@ -219,12 +219,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_OK), USER); - final DummyIdmapDaemon idmapd = getIdmapd(); - final DummyDeviceState state = getState(); + final FakeIdmapDaemon idmapd = getIdmapd(); + final FakeDeviceState state = getState(); String overlayPath = state.select(OVERLAY, USER).apkPath; assertTrue(idmapd.idmapExists(overlayPath, USER)); - DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); assertTrue((CONFIG_SIGNATURE & idmap.policies) == CONFIG_SIGNATURE); } @@ -237,12 +237,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); - final DummyIdmapDaemon idmapd = getIdmapd(); - final DummyDeviceState state = getState(); + final FakeIdmapDaemon idmapd = getIdmapd(); + final FakeDeviceState state = getState(); String overlayPath = state.select(OVERLAY, USER).apkPath; assertTrue(idmapd.idmapExists(overlayPath, USER)); - DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0); } @@ -252,12 +252,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); - final DummyIdmapDaemon idmapd = getIdmapd(); - final DummyDeviceState state = getState(); + final FakeIdmapDaemon idmapd = getIdmapd(); + final FakeDeviceState state = getState(); String overlayPath = state.select(OVERLAY, USER).apkPath; assertTrue(idmapd.idmapExists(overlayPath, USER)); - DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0); } @@ -266,12 +266,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); - final DummyIdmapDaemon idmapd = getIdmapd(); - final DummyDeviceState state = getState(); + final FakeIdmapDaemon idmapd = getIdmapd(); + final FakeDeviceState state = getState(); String overlayPath = state.select(OVERLAY, USER).apkPath; assertTrue(idmapd.idmapExists(overlayPath, USER)); - DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0); } @@ -284,12 +284,12 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes installNewPackage(target(TARGET), USER); installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER); - final DummyIdmapDaemon idmapd = getIdmapd(); - final DummyDeviceState state = getState(); + final FakeIdmapDaemon idmapd = getIdmapd(); + final FakeDeviceState state = getState(); String overlayPath = state.select(OVERLAY, USER).apkPath; assertTrue(idmapd.idmapExists(overlayPath, USER)); - DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); + FakeIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath); assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0); } } diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java index 2faf29f453759..006dda0f80e35 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java @@ -48,19 +48,19 @@ import java.util.stream.Collectors; /** Base class for creating {@link OverlayManagerServiceImplTests} tests. */ class OverlayManagerServiceImplTestsBase { private OverlayManagerServiceImpl mImpl; - private DummyDeviceState mState; - private DummyListener mListener; - private DummyPackageManagerHelper mPackageManager; - private DummyIdmapDaemon mIdmapDaemon; + private FakeDeviceState mState; + private FakeListener mListener; + private FakePackageManagerHelper mPackageManager; + private FakeIdmapDaemon mIdmapDaemon; private OverlayConfig mOverlayConfig; private String mConfigSignaturePackageName; @Before public void setUp() { - mState = new DummyDeviceState(); - mListener = new DummyListener(); - mPackageManager = new DummyPackageManagerHelper(mState); - mIdmapDaemon = new DummyIdmapDaemon(mState); + mState = new FakeDeviceState(); + mListener = new FakeListener(); + mPackageManager = new FakePackageManagerHelper(mState); + mIdmapDaemon = new FakeIdmapDaemon(mState); mOverlayConfig = mock(OverlayConfig.class); when(mOverlayConfig.getPriority(any())).thenReturn(OverlayConfig.DEFAULT_PRIORITY); when(mOverlayConfig.isEnabled(any())).thenReturn(false); @@ -81,15 +81,15 @@ class OverlayManagerServiceImplTestsBase { return mImpl; } - DummyListener getListener() { + FakeListener getListener() { return mListener; } - DummyIdmapDaemon getIdmapd() { + FakeIdmapDaemon getIdmapd() { return mIdmapDaemon; } - DummyDeviceState getState() { + FakeDeviceState getState() { return mState; } @@ -116,27 +116,27 @@ class OverlayManagerServiceImplTestsBase { assertEquals(expected, actual); } - DummyDeviceState.PackageBuilder app(String packageName) { - return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */, + FakeDeviceState.PackageBuilder app(String packageName) { + return new FakeDeviceState.PackageBuilder(packageName, null /* targetPackageName */, null /* targetOverlayableName */, "data"); } - DummyDeviceState.PackageBuilder target(String packageName) { - return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */, + FakeDeviceState.PackageBuilder target(String packageName) { + return new FakeDeviceState.PackageBuilder(packageName, null /* targetPackageName */, null /* targetOverlayableName */, ""); } - DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName) { + FakeDeviceState.PackageBuilder overlay(String packageName, String targetPackageName) { return overlay(packageName, targetPackageName, null /* targetOverlayableName */); } - DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName, + FakeDeviceState.PackageBuilder overlay(String packageName, String targetPackageName, String targetOverlayableName) { - return new DummyDeviceState.PackageBuilder(packageName, targetPackageName, + return new FakeDeviceState.PackageBuilder(packageName, targetPackageName, targetOverlayableName, ""); } - void addPackage(DummyDeviceState.PackageBuilder pkg, int userId) { + void addPackage(FakeDeviceState.PackageBuilder pkg, int userId) { mState.add(pkg, userId); } @@ -155,7 +155,7 @@ class OverlayManagerServiceImplTestsBase { * * @throws IllegalStateException if the package is currently installed */ - void installNewPackage(DummyDeviceState.PackageBuilder pkg, int userId) { + void installNewPackage(FakeDeviceState.PackageBuilder pkg, int userId) { if (mState.select(pkg.packageName, userId) != null) { throw new IllegalStateException("package " + pkg.packageName + " already installed"); } @@ -178,8 +178,8 @@ class OverlayManagerServiceImplTestsBase { * * @throws IllegalStateException if the package is not currently installed */ - void upgradePackage(DummyDeviceState.PackageBuilder pkg, int userId) { - final DummyDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId); + void upgradePackage(FakeDeviceState.PackageBuilder pkg, int userId) { + final FakeDeviceState.Package replacedPackage = mState.select(pkg.packageName, userId); if (replacedPackage == null) { throw new IllegalStateException("package " + pkg.packageName + " not installed"); } @@ -204,7 +204,7 @@ class OverlayManagerServiceImplTestsBase { * @throws IllegalStateException if the package is not currently installed */ void uninstallPackage(String packageName, int userId) { - final DummyDeviceState.Package pkg = mState.select(packageName, userId); + final FakeDeviceState.Package pkg = mState.select(packageName, userId); if (pkg == null) { throw new IllegalStateException("package " + packageName+ " not installed"); } @@ -217,7 +217,7 @@ class OverlayManagerServiceImplTestsBase { } /** Represents the state of packages installed on a fake device. */ - static class DummyDeviceState { + static class FakeDeviceState { private ArrayMap mPackages = new ArrayMap<>(); void add(PackageBuilder pkgBuilder, int userId) { @@ -333,16 +333,16 @@ class OverlayManagerServiceImplTestsBase { } } - final class DummyPackageManagerHelper implements PackageManagerHelper { - private final DummyDeviceState mState; + final class FakePackageManagerHelper implements PackageManagerHelper { + private final FakeDeviceState mState; - private DummyPackageManagerHelper(DummyDeviceState state) { + private FakePackageManagerHelper(FakeDeviceState state) { mState = state; } @Override public PackageInfo getPackageInfo(@NonNull String packageName, int userId) { - final DummyDeviceState.Package pkg = mState.select(packageName, userId); + final FakeDeviceState.Package pkg = mState.select(packageName, userId); if (pkg == null) { return null; } @@ -353,15 +353,15 @@ class OverlayManagerServiceImplTestsBase { pi.packageName = pkg.packageName; pi.overlayTarget = pkg.targetPackageName; pi.targetOverlayableName = pkg.targetOverlayableName; - pi.overlayCategory = "dummy-category-" + pkg.targetPackageName; + pi.overlayCategory = "Fake-category-" + pkg.targetPackageName; return pi; } @Override public boolean signaturesMatching(@NonNull String packageName1, @NonNull String packageName2, int userId) { - final DummyDeviceState.Package pkg1 = mState.select(packageName1, userId); - final DummyDeviceState.Package pkg2 = mState.select(packageName2, userId); + final FakeDeviceState.Package pkg1 = mState.select(packageName1, userId); + final FakeDeviceState.Package pkg2 = mState.select(packageName2, userId); return pkg1 != null && pkg2 != null && pkg1.certificate.equals(pkg2.certificate); } @@ -382,7 +382,7 @@ class OverlayManagerServiceImplTestsBase { @Override public OverlayableInfo getOverlayableForTarget(@NonNull String packageName, @NonNull String targetOverlayableName, int userId) { - final DummyDeviceState.Package pkg = mState.select(packageName, userId); + final FakeDeviceState.Package pkg = mState.select(packageName, userId); if (pkg == null || !pkg.overlayableNames.contains(targetOverlayableName)) { return null; } @@ -403,7 +403,7 @@ class OverlayManagerServiceImplTestsBase { @Override public boolean doesTargetDefineOverlayable(String targetPackageName, int userId) { - final DummyDeviceState.Package pkg = mState.select(targetPackageName, userId); + final FakeDeviceState.Package pkg = mState.select(targetPackageName, userId); return pkg != null && pkg.overlayableNames.contains(targetPackageName); } @@ -413,16 +413,16 @@ class OverlayManagerServiceImplTestsBase { } } - static class DummyIdmapDaemon extends IdmapDaemon { - private final DummyDeviceState mState; + static class FakeIdmapDaemon extends IdmapDaemon { + private final FakeDeviceState mState; private final ArrayMap mIdmapFiles = new ArrayMap<>(); - DummyIdmapDaemon(DummyDeviceState state) { + FakeIdmapDaemon(FakeDeviceState state) { this.mState = state; } private int getCrc(@NonNull final String path) { - final DummyDeviceState.Package pkg = mState.selectFromPath(path); + final FakeDeviceState.Package pkg = mState.selectFromPath(path); Assert.assertNotNull(pkg); return pkg.versionCode; } @@ -486,7 +486,7 @@ class OverlayManagerServiceImplTestsBase { } } - static class DummyListener implements OverlayManagerServiceImpl.OverlayChangeListener { + static class FakeListener implements OverlayManagerServiceImpl.OverlayChangeListener { public int count; public void onOverlaysChanged(@NonNull String targetPackage, int userId) { diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java index 146f60aff7243..9ef755791c802 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java @@ -50,55 +50,55 @@ public class OverlayManagerSettingsTests { private OverlayManagerSettings mSettings; private static final OverlayInfo OVERLAY_A0 = new OverlayInfo( - "com.dummy.overlay_a", - "com.dummy.target", + "com.test.overlay_a", + "com.test.target", null, "some-category", - "/data/app/com.dummy.overlay_a-1/base.apk", + "/data/app/com.test.overlay_a-1/base.apk", STATE_DISABLED, 0, 0, true); private static final OverlayInfo OVERLAY_B0 = new OverlayInfo( - "com.dummy.overlay_b", - "com.dummy.target", + "com.test.overlay_b", + "com.test.target", null, "some-category", - "/data/app/com.dummy.overlay_b-1/base.apk", + "/data/app/com.test.overlay_b-1/base.apk", STATE_DISABLED, 0, 0, true); private static final OverlayInfo OVERLAY_C0 = new OverlayInfo( - "com.dummy.overlay_c", - "com.dummy.target", + "com.test.overlay_c", + "com.test.target", null, "some-category", - "/data/app/com.dummy.overlay_c-1/base.apk", + "/data/app/com.test.overlay_c-1/base.apk", STATE_DISABLED, 0, 0, true); private static final OverlayInfo OVERLAY_A1 = new OverlayInfo( - "com.dummy.overlay_a", - "com.dummy.target", + "com.test.overlay_a", + "com.test.target", null, "some-category", - "/data/app/com.dummy.overlay_a-1/base.apk", + "/data/app/com.test.overlay_a-1/base.apk", STATE_DISABLED, 1, 0, true); private static final OverlayInfo OVERLAY_B1 = new OverlayInfo( - "com.dummy.overlay_b", - "com.dummy.target", + "com.test.overlay_b", + "com.test.target", null, "some-category", - "/data/app/com.dummy.overlay_b-1/base.apk", + "/data/app/com.test.overlay_b-1/base.apk", STATE_DISABLED, 1, 0, @@ -230,11 +230,11 @@ public class OverlayManagerSettingsTests { assertListsAreEqual(list, OVERLAY_A0, OVERLAY_C0, OVERLAY_B0); OverlayInfo otherTarget = new OverlayInfo( - "com.dummy.overlay_other", - "com.dummy.some.other.target", + "com.test.overlay_other", + "com.test.some.other.target", null, "some-category", - "/data/app/com.dummy.overlay_other-1/base.apk", + "/data/app/com.test.overlay_other-1/base.apk", STATE_DISABLED, 0, 0, @@ -350,7 +350,7 @@ public class OverlayManagerSettingsTests { ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8")); mSettings.restore(is); - assertDoesNotContain(mSettings, "com.dummy.overlay", 0); + assertDoesNotContain(mSettings, "com.test.overlay", 0); } @Test @@ -359,27 +359,27 @@ public class OverlayManagerSettingsTests { final String xml = "\n" + "\n" - + "\n" + "\n"; ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8")); mSettings.restore(is); - OverlayInfo oi = mSettings.getOverlayInfo("com.dummy.overlay", 1234); + OverlayInfo oi = mSettings.getOverlayInfo("com.test.overlay", 1234); assertNotNull(oi); - assertEquals("com.dummy.overlay", oi.packageName); - assertEquals("com.dummy.target", oi.targetPackageName); - assertEquals("/data/app/com.dummy.overlay-1/base.apk", oi.baseCodePath); + assertEquals("com.test.overlay", oi.packageName); + assertEquals("com.test.target", oi.targetPackageName); + assertEquals("/data/app/com.test.overlay-1/base.apk", oi.baseCodePath); assertEquals(1234, oi.userId); assertEquals(STATE_DISABLED, oi.state); - assertFalse(mSettings.getEnabled("com.dummy.overlay", 1234)); + assertFalse(mSettings.getEnabled("com.test.overlay", 1234)); } @Test From 70e02d428565b1cb9882ad2aa04ba7636fa3f099 Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Wed, 14 Oct 2020 14:19:51 -0700 Subject: [PATCH 4/4] Fix comments Fix comments that refer to as . Bug: none Test: build Change-Id: I1d3e5e66ec3da993082f3441997b0d243d61520b --- cmds/idmap2/libidmap2/ResourceMapping.cpp | 6 +++--- core/java/com/android/server/SystemConfig.java | 2 +- services/core/java/com/android/server/om/IdmapManager.java | 4 ++-- .../java/com/android/server/pm/PackageManagerService.java | 7 ++++--- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp index 122f0682aec6c..31f1c16ba5a68 100644 --- a/cmds/idmap2/libidmap2/ResourceMapping.cpp +++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp @@ -71,9 +71,9 @@ Result CheckOverlayable(const LoadedPackage& target_package, if (!target_package.DefinesOverlayable()) { return (sDefaultPolicies & fulfilled_policies) != 0 ? Result({}) - : Error( - "overlay must be preinstalled or signed with the same signature as the " - "target"); + : Error("overlay must be preinstalled, signed with the same signature as the target," + " or signed with the same signature as the package referenced through" + " ."); } const OverlayableInfo* overlayable_info = target_package.GetOverlayableInfo(target_resource); diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index 4fc66bc802f3e..d6e2c2f6d7836 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -243,7 +243,7 @@ public class SystemConfig { // partition that is used to verify if an overlay package fulfills // the 'config_signature' policy by comparing their signatures: // if the overlay package is signed with the same certificate as - // the package declared in 'config-signature' tag, then the + // the package declared in 'overlay-config-signature' tag, then the // overlay package fulfills the 'config_signature' policy. private String mOverlayConfigSignaturePackage; diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java index cb6e960b721de..eeb26552e63da 100644 --- a/services/core/java/com/android/server/om/IdmapManager.java +++ b/services/core/java/com/android/server/om/IdmapManager.java @@ -57,7 +57,7 @@ final class IdmapManager { private final PackageManagerHelper mPackageManager; /** - * Package name of the reference package defined in 'config-signature' tag of + * Package name of the reference package defined in 'overlay-config-signature' tag of * SystemConfig or empty String if tag not defined. This package is vetted on scan by * PackageManagerService that it's a system package and is used to check if overlay matches * its signature in order to fulfill the config_signature policy. @@ -159,7 +159,7 @@ final class IdmapManager { fulfilledPolicies |= OverlayablePolicy.ACTOR_SIGNATURE; } - // If SystemConfig defines 'config-signature' package, given that + // If SystemConfig defines 'overlay-config-signature' package, given that // this package is vetted by OverlayManagerService that it's a // preinstalled package, check if overlay matches its signature. if (!TextUtils.isEmpty(mConfigSignaturePackage) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index fddd46a9c026b..373c052dca04f 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -12161,9 +12161,10 @@ public class PackageManagerService extends IPackageManager.Stub // A non-preloaded overlay package, without , will // only be used if it is signed with the same certificate as its target OR if // it is signed with the same certificate as a reference package declared - // in 'config-signature' tag of SystemConfig. - // If the target is already installed or 'config-signature' tag in SystemConfig - // is set, check this here to augment the last line of defence which is OMS. + // in 'overlay-config-signature' tag of SystemConfig. + // If the target is already installed or 'overlay-config-signature' tag in + // SystemConfig is set, check this here to augment the last line of defense + // which is OMS. if (pkg.getOverlayTargetName() == null) { final PackageSetting targetPkgSetting = mSettings.getPackageLPr(pkg.getOverlayTarget());