diff options
author | 2019-04-09 17:13:50 -0700 | |
---|---|---|
committer | 2019-04-17 16:07:57 -0700 | |
commit | 939df096be11d242c8f3473954c7c10c371cf142 (patch) | |
tree | 0b4a8f3e490661546fe8fa728147da88a1b459e5 | |
parent | 488693532998d5e08f68b58b235b7d6dcd3df1fb (diff) |
Add odm and oem policies
This change adds parsing, encoding, and validating of odm and oem
overlayable policies to aapt2, libandroidfw, and idmap2.
Bug: 121033532
Test: aapt2_tests, idmap2_tests
Change-Id: Ifc0d4b6c9f9c37e06b2988abade69dbb277c50c2
27 files changed, 248 insertions, 94 deletions
diff --git a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl index 4a66715ad2b8..cd474c0fe056 100644 --- a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl +++ b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl @@ -25,6 +25,8 @@ interface IIdmap2 { const int POLICY_VENDOR_PARTITION = 0x00000004; const int POLICY_PRODUCT_PARTITION = 0x00000008; const int POLICY_SIGNATURE = 0x00000010; + const int POLICY_ODM_PARTITION = 0x00000020; + const int POLICY_OEM_PARTITION = 0x00000040; @utf8InCpp String getIdmapPath(@utf8InCpp String overlayApkPath, int userId); boolean removeIdmap(@utf8InCpp String overlayApkPath, int userId); diff --git a/cmds/idmap2/include/idmap2/Policies.h b/cmds/idmap2/include/idmap2/Policies.h index 90c698cc6e49..87edd3506d33 100644 --- a/cmds/idmap2/include/idmap2/Policies.h +++ b/cmds/idmap2/include/idmap2/Policies.h @@ -26,11 +26,13 @@ namespace android::idmap2 { -constexpr const char* kPolicyPublic = "public"; +constexpr const char* kPolicyOdm = "odm"; +constexpr const char* kPolicyOem = "oem"; constexpr const char* kPolicyProduct = "product"; +constexpr const char* kPolicyPublic = "public"; +constexpr const char* kPolicySignature = "signature"; constexpr const char* kPolicySystem = "system"; constexpr const char* kPolicyVendor = "vendor"; -constexpr const char* kPolicySignature = "signature"; using PolicyFlags = ResTable_overlayable_policy_header::PolicyFlags; using PolicyBitmask = uint32_t; diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp index aec1a6fc2bae..4649675965db 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -282,6 +282,7 @@ Result<Unit> CheckOverlayable(const LoadedPackage& target_package, const utils::OverlayManifestInfo& overlay_info, const PolicyBitmask& fulfilled_policies, const ResourceId& resid) { static constexpr const PolicyBitmask sDefaultPolicies = + PolicyFlags::POLICY_ODM_PARTITION | PolicyFlags::POLICY_OEM_PARTITION | PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION | PolicyFlags::POLICY_PRODUCT_PARTITION | PolicyFlags::POLICY_SIGNATURE; diff --git a/cmds/idmap2/libidmap2/Policies.cpp b/cmds/idmap2/libidmap2/Policies.cpp index 0a0cecf13932..495fe615a91f 100644 --- a/cmds/idmap2/libidmap2/Policies.cpp +++ b/cmds/idmap2/libidmap2/Policies.cpp @@ -17,8 +17,8 @@ #include "idmap2/Policies.h" #include <iterator> -#include <map> #include <string> +#include <unordered_map> #include <vector> #include "androidfw/ResourceTypes.h" @@ -27,19 +27,17 @@ namespace android::idmap2 { -namespace { - -const std::map<android::StringPiece, PolicyFlags> kStringToFlag = { - {kPolicyPublic, PolicyFlags::POLICY_PUBLIC}, - {kPolicyProduct, PolicyFlags::POLICY_PRODUCT_PARTITION}, - {kPolicySystem, PolicyFlags::POLICY_SYSTEM_PARTITION}, - {kPolicyVendor, PolicyFlags::POLICY_VENDOR_PARTITION}, - {kPolicySignature, PolicyFlags::POLICY_SIGNATURE}, -}; - -} // namespace - Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies) { + static const std::unordered_map<android::StringPiece, PolicyFlags> kStringToFlag = { + {kPolicyOdm, PolicyFlags::POLICY_ODM_PARTITION}, + {kPolicyOem, PolicyFlags::POLICY_OEM_PARTITION}, + {kPolicyPublic, PolicyFlags::POLICY_PUBLIC}, + {kPolicyProduct, PolicyFlags::POLICY_PRODUCT_PARTITION}, + {kPolicySignature, PolicyFlags::POLICY_SIGNATURE}, + {kPolicySystem, PolicyFlags::POLICY_SYSTEM_PARTITION}, + {kPolicyVendor, PolicyFlags::POLICY_VENDOR_PARTITION}, + }; + PolicyBitmask bitmask = 0; for (const std::string& policy : policies) { const auto iter = kStringToFlag.find(policy); @@ -55,6 +53,15 @@ Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask) { std::vector<std::string> policies; + + if ((bitmask & PolicyFlags::POLICY_ODM_PARTITION) != 0) { + policies.emplace_back(kPolicyOdm); + } + + if ((bitmask & PolicyFlags::POLICY_OEM_PARTITION) != 0) { + policies.emplace_back(kPolicyOem); + } + if ((bitmask & PolicyFlags::POLICY_PUBLIC) != 0) { policies.emplace_back(kPolicyPublic); } @@ -63,6 +70,10 @@ std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask) { policies.emplace_back(kPolicyProduct); } + if ((bitmask & PolicyFlags::POLICY_SIGNATURE) != 0) { + policies.emplace_back(kPolicySignature); + } + if ((bitmask & PolicyFlags::POLICY_SYSTEM_PARTITION) != 0) { policies.emplace_back(kPolicySystem); } @@ -71,10 +82,6 @@ std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask) { policies.emplace_back(kPolicyVendor); } - if ((bitmask & PolicyFlags::POLICY_SIGNATURE) != 0) { - policies.emplace_back(kPolicySignature); - } - return policies; } diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp index 9cdc86ca181a..9348ab721493 100644 --- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp +++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp @@ -109,49 +109,55 @@ TEST(BinaryStreamVisitorTests, CreateIdmapFromApkAssetsInteropWithLoadedIdmap) { success = LoadedIdmap::Lookup(header, 0x0002, &entry); // string/c ASSERT_FALSE(success); - success = LoadedIdmap::Lookup(header, 0x0003, &entry); // string/other + success = LoadedIdmap::Lookup(header, 0x0003, &entry); // string/policy_odm ASSERT_FALSE(success); - success = LoadedIdmap::Lookup(header, 0x0004, &entry); // string/not_overlayable + success = LoadedIdmap::Lookup(header, 0x0004, &entry); // string/policy_oem ASSERT_FALSE(success); - success = LoadedIdmap::Lookup(header, 0x0005, &entry); // string/policy_product + success = LoadedIdmap::Lookup(header, 0x0005, &entry); // string/other ASSERT_FALSE(success); - success = LoadedIdmap::Lookup(header, 0x0006, &entry); // string/policy_public + success = LoadedIdmap::Lookup(header, 0x0006, &entry); // string/not_overlayable ASSERT_FALSE(success); - success = LoadedIdmap::Lookup(header, 0x0007, &entry); // string/policy_system + success = LoadedIdmap::Lookup(header, 0x0007, &entry); // string/policy_product ASSERT_FALSE(success); - success = LoadedIdmap::Lookup(header, 0x0008, &entry); // string/policy_system_vendor + success = LoadedIdmap::Lookup(header, 0x0008, &entry); // string/policy_public ASSERT_FALSE(success); - success = LoadedIdmap::Lookup(header, 0x0009, &entry); // string/policy_signature + success = LoadedIdmap::Lookup(header, 0x0009, &entry); // string/policy_system ASSERT_FALSE(success); - success = LoadedIdmap::Lookup(header, 0x000a, &entry); // string/str1 + success = LoadedIdmap::Lookup(header, 0x000a, &entry); // string/policy_system_vendor + ASSERT_FALSE(success); + + success = LoadedIdmap::Lookup(header, 0x000b, &entry); // string/policy_signature + ASSERT_FALSE(success); + + success = LoadedIdmap::Lookup(header, 0x000c, &entry); // string/str1 ASSERT_TRUE(success); ASSERT_EQ(entry, 0x0000); - success = LoadedIdmap::Lookup(header, 0x000b, &entry); // string/str2 + success = LoadedIdmap::Lookup(header, 0x000d, &entry); // string/str2 ASSERT_FALSE(success); - success = LoadedIdmap::Lookup(header, 0x000c, &entry); // string/str3 + success = LoadedIdmap::Lookup(header, 0x000e, &entry); // string/str3 ASSERT_TRUE(success); ASSERT_EQ(entry, 0x0001); - success = LoadedIdmap::Lookup(header, 0x000d, &entry); // string/str4 + success = LoadedIdmap::Lookup(header, 0x000f, &entry); // string/str4 ASSERT_TRUE(success); ASSERT_EQ(entry, 0x0002); - success = LoadedIdmap::Lookup(header, 0x000e, &entry); // string/x + success = LoadedIdmap::Lookup(header, 0x0010, &entry); // string/x ASSERT_FALSE(success); - success = LoadedIdmap::Lookup(header, 0x000f, &entry); // string/y + success = LoadedIdmap::Lookup(header, 0x0011, &entry); // string/y ASSERT_FALSE(success); - success = LoadedIdmap::Lookup(header, 0x0010, &entry); // string/z + success = LoadedIdmap::Lookup(header, 0x0012, &entry); // string/z ASSERT_FALSE(success); } diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp index c18744ccb2d5..8a48f4b8e6d5 100644 --- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp +++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp @@ -128,9 +128,9 @@ TEST_F(Idmap2BinaryTests, Dump) { ASSERT_THAT(result, NotNull()); ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr; ASSERT_NE(result->stdout.find("0x7f010000 -> 0x7f010000 integer/int1"), std::string::npos); - ASSERT_NE(result->stdout.find("0x7f02000a -> 0x7f020000 string/str1"), std::string::npos); - ASSERT_NE(result->stdout.find("0x7f02000c -> 0x7f020001 string/str3"), std::string::npos); - ASSERT_NE(result->stdout.find("0x7f02000d -> 0x7f020002 string/str4"), std::string::npos); + ASSERT_NE(result->stdout.find("0x7f02000c -> 0x7f020000 string/str1"), std::string::npos); + ASSERT_NE(result->stdout.find("0x7f02000e -> 0x7f020001 string/str3"), std::string::npos); + ASSERT_NE(result->stdout.find("0x7f02000f -> 0x7f020002 string/str4"), std::string::npos); ASSERT_EQ(result->stdout.find("00000210: 007f target package id"), std::string::npos); // clang-format off @@ -299,7 +299,7 @@ TEST_F(Idmap2BinaryTests, Lookup) { "lookup", "--idmap-path", GetIdmapPath(), "--config", "", - "--resid", "0x7f02000a"}); // string/str1 + "--resid", "0x7f02000c"}); // string/str1 // clang-format on ASSERT_THAT(result, NotNull()); ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr; diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index 90fe9a79bd1f..0f47f1e77d7b 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -194,7 +194,7 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) { ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U); - ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xd513ca1b); + ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x76a20829); ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x8635c2ed); ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path); ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path); @@ -220,7 +220,7 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) { ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U); ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U); ASSERT_EQ(types[1]->GetEntryCount(), 4U); - ASSERT_EQ(types[1]->GetEntryOffset(), 10U); + ASSERT_EQ(types[1]->GetEntryOffset(), 12U); ASSERT_EQ(types[1]->GetEntry(0), 0x0000U); ASSERT_EQ(types[1]->GetEntry(1), kNoEntry); ASSERT_EQ(types[1]->GetEntry(2), 0x0001U); @@ -251,7 +251,7 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublic) { ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U); ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U); ASSERT_EQ(types[0]->GetEntryCount(), 4U); - ASSERT_EQ(types[0]->GetEntryOffset(), 6U); + ASSERT_EQ(types[0]->GetEntryOffset(), 8U); ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_public ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/policy_signature ASSERT_EQ(types[0]->GetEntry(2), 0x0001U); // string/policy_system @@ -281,7 +281,7 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySignature) { ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U); ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U); ASSERT_EQ(types[0]->GetEntryCount(), 1U); - ASSERT_EQ(types[0]->GetEntryOffset(), 7U); + ASSERT_EQ(types[0]->GetEntryOffset(), 9U); ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/policy_signature } @@ -310,11 +310,11 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) { ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U); ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U); ASSERT_EQ(types[0]->GetEntryCount(), 4U); - ASSERT_EQ(types[0]->GetEntryOffset(), 6U); - ASSERT_EQ(types[0]->GetEntry(0), 0x0003U); // string/policy_public + ASSERT_EQ(types[0]->GetEntryOffset(), 8U); + ASSERT_EQ(types[0]->GetEntry(0), 0x0005U); // string/policy_public ASSERT_EQ(types[0]->GetEntry(1), kNoEntry); // string/policy_signature - ASSERT_EQ(types[0]->GetEntry(2), 0x0005U); // string/policy_system - ASSERT_EQ(types[0]->GetEntry(3), 0x0006U); // string/policy_system_vendor + ASSERT_EQ(types[0]->GetEntry(2), 0x0007U); // string/policy_system + ASSERT_EQ(types[0]->GetEntry(3), 0x0008U); // string/policy_system_vendor } // Overlays should ignore all overlayable restrictions if enforcement of overlayable is disabled. @@ -341,15 +341,17 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalidIgn ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U); ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U); - ASSERT_EQ(types[0]->GetEntryCount(), 7U); + ASSERT_EQ(types[0]->GetEntryCount(), 9U); ASSERT_EQ(types[0]->GetEntryOffset(), 3U); ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable - ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/other - ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_product - ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_signature - ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_public - ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system - ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_system_vendor + ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/policy_odm + ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_oem + ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/other + ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_product + ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_public + ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_signature + ASSERT_EQ(types[0]->GetEntry(7), 0x0007U); // string/policy_system + ASSERT_EQ(types[0]->GetEntry(8), 0x0008U); // string/policy_system_vendor } // Overlays that do not specify a target <overlayable> can overlay resources defined as overlayable. @@ -381,7 +383,7 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsNoDefinedOverlayableAndNoTar ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U); ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U); ASSERT_EQ(types[1]->GetEntryCount(), 4U); - ASSERT_EQ(types[1]->GetEntryOffset(), 10U); + ASSERT_EQ(types[1]->GetEntryOffset(), 12U); ASSERT_EQ(types[1]->GetEntry(0), 0x0000U); // string/str1 ASSERT_EQ(types[1]->GetEntry(1), kNoEntry); // string/str2 ASSERT_EQ(types[1]->GetEntry(2), 0x0001U); // string/str3 @@ -412,7 +414,6 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPolicies) { ASSERT_EQ(dataBlocks.size(), 1U); const std::unique_ptr<const IdmapData>& data = dataBlocks[0]; - ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU); ASSERT_EQ(data->GetHeader()->GetTypeCount(), 1U); @@ -421,15 +422,17 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPolicies) { ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U); ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U); - ASSERT_EQ(types[0]->GetEntryCount(), 7U); + ASSERT_EQ(types[0]->GetEntryCount(), 9U); ASSERT_EQ(types[0]->GetEntryOffset(), 3U); ASSERT_EQ(types[0]->GetEntry(0), 0x0000U); // string/not_overlayable - ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/other - ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_product - ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/policy_public - ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/string/policy_signature - ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_system - ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_system_vendor + ASSERT_EQ(types[0]->GetEntry(1), 0x0001U); // string/policy_odm + ASSERT_EQ(types[0]->GetEntry(2), 0x0002U); // string/policy_oem + ASSERT_EQ(types[0]->GetEntry(3), 0x0003U); // string/other + ASSERT_EQ(types[0]->GetEntry(4), 0x0004U); // string/policy_product + ASSERT_EQ(types[0]->GetEntry(5), 0x0005U); // string/policy_public + ASSERT_EQ(types[0]->GetEntry(6), 0x0006U); // string/policy_signature + ASSERT_EQ(types[0]->GetEntry(7), 0x0007U); // string/policy_system + ASSERT_EQ(types[0]->GetEntry(8), 0x0008U); // string/policy_system_vendor }; CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_SIGNATURE, @@ -451,6 +454,16 @@ TEST(IdmapOverlayableTests, CreateIdmapFromApkAssetsDefaultPolicies) { /* enforce_overlayable */ true, &idmap); ASSERT_THAT(idmap, NotNull()); CheckEntries(); + + CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_ODM_PARTITION, + /* enforce_overlayable */ true, &idmap); + ASSERT_THAT(idmap, NotNull()); + CheckEntries(); + + CreateIdmap(target_apk_path, overlay_apk_path, PolicyFlags::POLICY_OEM_PARTITION, + /* enforce_overlayable */ true, &idmap); + ASSERT_THAT(idmap, NotNull()); + CheckEntries(); } TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) { diff --git a/cmds/idmap2/tests/PoliciesTests.cpp b/cmds/idmap2/tests/PoliciesTests.cpp index e30da76ddd98..eca74045f428 100644 --- a/cmds/idmap2/tests/PoliciesTests.cpp +++ b/cmds/idmap2/tests/PoliciesTests.cpp @@ -38,9 +38,10 @@ TEST(PoliciesTests, PoliciesToBitmasks) { ASSERT_TRUE(bitmask3); ASSERT_EQ(*bitmask3, PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION); - const auto bitmask4 = PoliciesToBitmask({"public", "product", "system", "vendor"}); + const auto bitmask4 = PoliciesToBitmask({"odm", "oem", "public", "product", "system", "vendor"}); ASSERT_TRUE(bitmask4); - ASSERT_EQ(*bitmask4, PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_PRODUCT_PARTITION | + ASSERT_EQ(*bitmask4, PolicyFlags::POLICY_ODM_PARTITION | PolicyFlags::POLICY_OEM_PARTITION | + PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_PRODUCT_PARTITION | PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION); @@ -64,4 +65,28 @@ TEST(PoliciesTests, PoliciesToBitmasks) { ASSERT_FALSE(bitmask10); } +TEST(PoliciesTests, BitmaskToPolicies) { + const auto policies1 = BitmaskToPolicies(PolicyFlags::POLICY_PUBLIC); + ASSERT_EQ(1, policies1.size()); + ASSERT_EQ(policies1[0], "public"); + + const auto policies2 = BitmaskToPolicies(PolicyFlags::POLICY_SYSTEM_PARTITION | + PolicyFlags::POLICY_VENDOR_PARTITION); + ASSERT_EQ(2, policies2.size()); + ASSERT_EQ(policies2[0], "system"); + ASSERT_EQ(policies2[1], "vendor"); + + const auto policies3 = BitmaskToPolicies( + PolicyFlags::POLICY_ODM_PARTITION | PolicyFlags::POLICY_OEM_PARTITION | + PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_PRODUCT_PARTITION | + PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION); + ASSERT_EQ(2, policies2.size()); + ASSERT_EQ(policies3[0], "odm"); + ASSERT_EQ(policies3[1], "oem"); + ASSERT_EQ(policies3[2], "public"); + ASSERT_EQ(policies3[3], "product"); + ASSERT_EQ(policies3[4], "system"); + ASSERT_EQ(policies3[5], "vendor"); +} + } // namespace android::idmap2 diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp index 64518fdf8dee..26951763cd66 100644 --- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp @@ -49,7 +49,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { ASSERT_NE(stream.str().find("00000000: 504d4449 magic\n"), std::string::npos); ASSERT_NE(stream.str().find("00000004: 00000001 version\n"), std::string::npos); - ASSERT_NE(stream.str().find("00000008: d513ca1b target crc\n"), std::string::npos); + ASSERT_NE(stream.str().find("00000008: 76a20829 target crc\n"), std::string::npos); ASSERT_NE(stream.str().find("0000000c: 8635c2ed overlay crc\n"), std::string::npos); ASSERT_NE(stream.str().find("0000021c: 00000000 0x7f010000 -> 0x7f010000 integer/int1\n"), std::string::npos); 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 02704009d743..9ebfae41e4c5 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 @@ -23,6 +23,8 @@ <!-- Requests to overlay a resource that belongs to a policy the overlay does not fulfill. --> <string name="policy_product">policy_product</string> <string name="policy_signature">policy_signature</string> + <string name="policy_odm">policy_odm</string> + <string name="policy_oem">policy_oem</string> <!-- Requests to overlay a resource that is not declared as overlayable. --> <string name="not_overlayable">not_overlayable</string> 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 Binary files differindex 9448939b5636..1456e749e796 100644 --- a/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk +++ b/cmds/idmap2/tests/data/system-overlay-invalid/system-overlay-invalid.apk diff --git a/cmds/idmap2/tests/data/target/res/values/overlayable.xml b/cmds/idmap2/tests/data/target/res/values/overlayable.xml index 0bf83fa50b75..8389f5635e15 100644 --- a/cmds/idmap2/tests/data/target/res/values/overlayable.xml +++ b/cmds/idmap2/tests/data/target/res/values/overlayable.xml @@ -33,6 +33,14 @@ <item type="string" name="policy_product" /> </policy> + <policy type="odm"> + <item type="string" name="policy_odm" /> + </policy> + + <policy type="oem"> + <item type="string" name="policy_oem" /> + </policy> + <!-- Resources publicly overlayable --> <policy type="public"> <item type="string" name="policy_public" /> diff --git a/cmds/idmap2/tests/data/target/res/values/values.xml b/cmds/idmap2/tests/data/target/res/values/values.xml index edd53f4c9b52..a892c98f0fbb 100644 --- a/cmds/idmap2/tests/data/target/res/values/values.xml +++ b/cmds/idmap2/tests/data/target/res/values/values.xml @@ -29,11 +29,13 @@ <!-- This resources is not marked as overlayable --> <string name="not_overlayable">not_overlayable</string> - <string name="policy_system">policy_system</string> - <string name="policy_system_vendor">policy_system_vendor</string> - <string name="policy_product">policy_product</string> <string name="policy_public">policy_public</string> + <string name="policy_odm">policy_odm</string> + <string name="policy_oem">policy_oem</string> + <string name="policy_product">policy_product</string> <string name="policy_signature">policy_signature</string> + <string name="policy_system">policy_system</string> + <string name="policy_system_vendor">policy_system_vendor</string> - <item type="string" name="other" /> + <string name="other">other</string> </resources> diff --git a/cmds/idmap2/tests/data/target/target-no-overlayable.apk b/cmds/idmap2/tests/data/target/target-no-overlayable.apk Binary files differindex 908b54a2f0c3..033305aaed4f 100644 --- a/cmds/idmap2/tests/data/target/target-no-overlayable.apk +++ b/cmds/idmap2/tests/data/target/target-no-overlayable.apk diff --git a/cmds/idmap2/tests/data/target/target.apk b/cmds/idmap2/tests/data/target/target.apk Binary files differindex da3c1aef5fba..9bcd6dcabcde 100644 --- a/cmds/idmap2/tests/data/target/target.apk +++ b/cmds/idmap2/tests/data/target/target.apk diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 875b90b7ac65..fc635aaeb0d8 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -1651,6 +1651,14 @@ struct ResTable_overlayable_policy_header // The overlay must be signed with the same signature as the actor of the target resource, // which can be separate or the same as the target package with the resource. POLICY_SIGNATURE = 0x00000010, + + // The overlay must reside of the odm partition or must have existed on the odm + // partition before an upgrade to overlay these resources. + POLICY_ODM_PARTITION = 0x00000020, + + // The overlay must reside of the oem partition or must have existed on the oem + // partition before an upgrade to overlay these resources. + POLICY_OEM_PARTITION = 0x00000040, }; uint32_t policy_flags; diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java index fd68a8bc1ca8..4b435de3538b 100644 --- a/services/core/java/com/android/server/om/IdmapManager.java +++ b/services/core/java/com/android/server/om/IdmapManager.java @@ -220,9 +220,19 @@ class IdmapManager { return fulfilledPolicies | IIdmap2.POLICY_PRODUCT_PARTITION; } + // Odm partition (/odm) + if (ai.isOdm()) { + return fulfilledPolicies | IIdmap2.POLICY_ODM_PARTITION; + } + + // Oem partition (/oem) + if (ai.isOem()) { + return fulfilledPolicies | IIdmap2.POLICY_OEM_PARTITION; + } + // Check partitions for which there exists no policy so overlays on these partitions will // not fulfill the system policy. - if (ai.isOem() || ai.isProductServices()) { + if (ai.isProductServices()) { return fulfilledPolicies; } diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index 5e8d870488c4..fe401e22c50e 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -1143,34 +1143,38 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource } else if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) { // Parse the polices separated by vertical bar characters to allow for specifying multiple // policies. Items within the policy tag will have the specified policy. - for (StringPiece part : util::Tokenize(maybe_type.value(), '|')) { + static const auto kPolicyMap = + ImmutableMap<StringPiece, OverlayableItem::Policy>::CreatePreSorted({ + {"odm", OverlayableItem::Policy::kOdm}, + {"oem", OverlayableItem::Policy::kOem}, + {"product", OverlayableItem::Policy::kProduct}, + {"public", OverlayableItem::Policy::kPublic}, + {"signature", OverlayableItem::Policy::kSignature}, + {"system", OverlayableItem::Policy::kSystem}, + {"vendor", OverlayableItem::Policy::kVendor}, + }); + + for (const StringPiece& part : util::Tokenize(maybe_type.value(), '|')) { StringPiece trimmed_part = util::TrimWhitespace(part); - if (trimmed_part == "public") { - current_policies |= OverlayableItem::Policy::kPublic; - } else if (trimmed_part == "product") { - current_policies |= OverlayableItem::Policy::kProduct; - } else if (trimmed_part == "system") { - current_policies |= OverlayableItem::Policy::kSystem; - } else if (trimmed_part == "vendor") { - current_policies |= OverlayableItem::Policy::kVendor; - } else if (trimmed_part == "signature") { - current_policies |= OverlayableItem::Policy::kSignature; - } else { + const auto policy = kPolicyMap.find(trimmed_part); + if (policy == kPolicyMap.end()) { diag_->Error(DiagMessage(element_source) << "<policy> has unsupported type '" << trimmed_part << "'"); error = true; continue; } + + current_policies |= policy->second; } } else { diag_->Error(DiagMessage(element_source) - << "<policy> must have a 'type' attribute"); + << "<policy> must have a 'type' attribute"); error = true; continue; } } else if (!ShouldIgnoreElement(element_namespace, element_name)) { diag_->Error(DiagMessage(element_source) << "invalid element <" << element_name << "> " - << " in <overlayable>"); + << " in <overlayable>"); error = true; break; } diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp index 857792192902..7c8b6d054cd5 100644 --- a/tools/aapt2/ResourceParser_test.cpp +++ b/tools/aapt2/ResourceParser_test.cpp @@ -971,6 +971,12 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { <policy type="signature"> <item type="string" name="foz" /> </policy> + <policy type="odm"> + <item type="string" name="biz" /> + </policy> + <policy type="oem"> + <item type="string" name="buz" /> + </policy> </overlayable>)"; ASSERT_TRUE(TestParse(input)); @@ -1013,6 +1019,22 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { result_overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature)); + + search_result = table_.FindResource(test::ParseNameOrDie("string/biz")); + ASSERT_TRUE(search_result); + ASSERT_THAT(search_result.value().entry, NotNull()); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kOdm)); + + search_result = table_.FindResource(test::ParseNameOrDie("string/buz")); + ASSERT_TRUE(search_result); + ASSERT_THAT(search_result.value().entry, NotNull()); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kOem)); } TEST_F(ResourceParserTest, ParseOverlayableNoPolicyError) { diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index 7ed78975a01d..30ba1aed25f8 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -79,22 +79,28 @@ struct OverlayableItem { // Represents the types overlays that are allowed to overlay the resource. typedef uint32_t PolicyFlags; enum Policy : uint32_t { - kNone = 0x00, + kNone = 0x00000000, // The resource can be overlaid by any overlay. - kPublic = 0x01, + kPublic = 0x00000001, // The resource can be overlaid by any overlay on the system partition. - kSystem = 0x02, + kSystem = 0x00000002, // The resource can be overlaid by any overlay on the vendor partition. - kVendor = 0x04, + kVendor = 0x00000004, // The resource can be overlaid by any overlay on the product partition. - kProduct = 0x08, + kProduct = 0x00000008, // The resource can be overlaid by any overlay signed with the same signature as its actor. - kSignature = 0x010, + kSignature = 0x00000010, + + // The resource can be overlaid by any overlay on the odm partition. + kOdm = 0x00000020, + + // The resource can be overlaid by any overlay on the oem partition. + kOem = 0x00000040, }; std::shared_ptr<Overlayable> overlayable; diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto index a2fd7c664b04..12cf65be05c7 100644 --- a/tools/aapt2/Resources.proto +++ b/tools/aapt2/Resources.proto @@ -157,6 +157,8 @@ message OverlayableItem { VENDOR = 3; PRODUCT = 4; SIGNATURE = 5; + ODM = 6; + OEM = 7; } // The location of the <item> declaration in source. diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp index 59eb9ec2d418..fd8e36ebf823 100644 --- a/tools/aapt2/format/binary/BinaryResourceParser.cpp +++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp @@ -475,6 +475,14 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) { & ResTable_overlayable_policy_header::POLICY_SIGNATURE) { policies |= OverlayableItem::Policy::kSignature; } + if (policy_header->policy_flags + & ResTable_overlayable_policy_header::POLICY_ODM_PARTITION) { + policies |= OverlayableItem::Policy::kOdm; + } + if (policy_header->policy_flags + & ResTable_overlayable_policy_header::POLICY_OEM_PARTITION) { + policies |= OverlayableItem::Policy::kOem; + } const ResTable_ref* const ref_begin = reinterpret_cast<const ResTable_ref*>( ((uint8_t *)policy_header) + util::DeviceToHost32(policy_header->header.headerSize)); diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp index aa578a2a6ff4..f2e72da4056a 100644 --- a/tools/aapt2/format/binary/TableFlattener.cpp +++ b/tools/aapt2/format/binary/TableFlattener.cpp @@ -496,6 +496,12 @@ class PackageFlattener { if (item.policies & OverlayableItem::Policy::kSignature) { policy_flags |= ResTable_overlayable_policy_header::POLICY_SIGNATURE; } + if (item.policies & OverlayableItem::Policy::kOdm) { + policy_flags |= ResTable_overlayable_policy_header::POLICY_ODM_PARTITION; + } + if (item.policies & OverlayableItem::Policy::kOem) { + policy_flags |= ResTable_overlayable_policy_header::POLICY_OEM_PARTITION; + } auto policy = overlayable_chunk->policy_ids.find(policy_flags); if (policy != overlayable_chunk->policy_ids.end()) { diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp index 4c5dbec8ade8..a9409235e07a 100644 --- a/tools/aapt2/format/binary/TableFlattener_test.cpp +++ b/tools/aapt2/format/binary/TableFlattener_test.cpp @@ -724,8 +724,8 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { std::string name_two = "com.app.test:integer/overlayable_two"; OverlayableItem overlayable_item_two(group); - overlayable_item_two.policies |= OverlayableItem::Policy::kProduct; - overlayable_item_two.policies |= OverlayableItem::Policy::kSystem; + overlayable_item_two.policies |= OverlayableItem::Policy::kOdm; + overlayable_item_two.policies |= OverlayableItem::Policy::kOem; overlayable_item_two.policies |= OverlayableItem::Policy::kVendor; std::string name_three = "com.app.test:integer/overlayable_three"; @@ -744,6 +744,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { .AddSimple(name_three, ResourceId(0x7f020003)) .SetOverlayable(name_three, overlayable_item_three) .Build(); + ResourceTable output_table; ASSERT_TRUE(Flatten(context_.get(), {}, table.get(), &output_table)); auto search_result = output_table.FindResource(test::ParseNameOrDie(name_zero)); @@ -755,6 +756,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme"); EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSystem | OverlayableItem::Policy::kProduct); + search_result = output_table.FindResource(test::ParseNameOrDie(name_one)); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); @@ -763,6 +765,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { EXPECT_EQ(result_overlayable.overlayable->name, "OtherName"); EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization"); EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic); + search_result = output_table.FindResource(test::ParseNameOrDie(name_two)); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); @@ -770,9 +773,10 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { result_overlayable = search_result.value().entry->overlayable_item.value(); EXPECT_EQ(result_overlayable.overlayable->name, "TestName"); EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme"); - EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSystem - | OverlayableItem::Policy::kProduct + EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kOdm + | OverlayableItem::Policy::kOem | OverlayableItem::Policy::kVendor); + search_result = output_table.FindResource(test::ParseNameOrDie(name_three)); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp index 06f1bf74d7e7..bb21c1c539fb 100644 --- a/tools/aapt2/format/proto/ProtoDeserialize.cpp +++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp @@ -393,6 +393,12 @@ bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable, case pb::OverlayableItem::SIGNATURE: out_overlayable->policies |= OverlayableItem::Policy::kSignature; break; + case pb::OverlayableItem::ODM: + out_overlayable->policies |= OverlayableItem::Policy::kOdm; + break; + case pb::OverlayableItem::OEM: + out_overlayable->policies |= OverlayableItem::Policy::kOem; + 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 eb2b1a2f35d3..58e1e6ee35ca 100644 --- a/tools/aapt2/format/proto/ProtoSerialize.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize.cpp @@ -312,6 +312,12 @@ static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item if (overlayable_item.policies & OverlayableItem::Policy::kSignature) { pb_overlayable_item->add_policy(pb::OverlayableItem::SIGNATURE); } + if (overlayable_item.policies & OverlayableItem::Policy::kOdm) { + pb_overlayable_item->add_policy(pb::OverlayableItem::ODM); + } + if (overlayable_item.policies & OverlayableItem::Policy::kOem) { + pb_overlayable_item->add_policy(pb::OverlayableItem::OEM); + } SerializeSourceToPb(overlayable_item.source, source_pool, pb_overlayable_item->mutable_source()); diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp index d369ac4c8816..f252f33f44fb 100644 --- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp @@ -529,6 +529,8 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { OverlayableItem overlayable_item_boz(std::make_shared<Overlayable>( "IconPack", "overlay://theme")); overlayable_item_boz.policies |= OverlayableItem::Policy::kSignature; + overlayable_item_boz.policies |= OverlayableItem::Policy::kOdm; + overlayable_item_boz.policies |= OverlayableItem::Policy::kOem; OverlayableItem overlayable_item_biz(std::make_shared<Overlayable>( "Other", "overlay://customization")); @@ -587,7 +589,9 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(overlayable_item.overlayable->name, Eq("IconPack")); EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme")); - EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature)); + EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature + | OverlayableItem::Policy::kOdm + | OverlayableItem::Policy::kOem)); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/biz")); ASSERT_TRUE(search_result); |