From 62ac8b56a9f7cf75f3f0677ec37d8acb8def475c Mon Sep 17 00:00:00 2001 From: Winson Date: Wed, 4 Dec 2019 08:36:48 -0800 Subject: [PATCH 1/2] Refactor overlayable policy To make it easier to add the actor policy in a follow up CL, move most of the policy handling to a central location. The strings and transformation between strings and flags is now handled in libidmap2policies, with libandroidfw containing the single source of policy flags. This also extracts all the test resource IDs into an R.h so they can be swapped without having to edit a dozen files each time. Bug: 130563563 Test: m aapt2_tests idmapt2_tests and run from host test output Test: atest libandroidfw_tests Change-Id: Ie533c9cebf938215df7586f00c38763ae467e606 --- cmds/idmap2/Android.bp | 64 ++++- cmds/idmap2/idmap2/Create.cpp | 16 +- cmds/idmap2/idmap2/CreateMultiple.cpp | 11 +- cmds/idmap2/idmap2/Scan.cpp | 18 +- cmds/idmap2/idmap2d/Idmap2Service.cpp | 4 +- .../idmap2d/aidl/android/os/IIdmap2.aidl | 8 - .../aidl/android/os/OverlayablePolicy.aidl | 31 +++ cmds/idmap2/include/idmap2/Idmap.h | 1 - cmds/idmap2/include/idmap2/PolicyUtils.h | 41 ++++ cmds/idmap2/include/idmap2/ResourceMapping.h | 2 + cmds/idmap2/libidmap2/Policies.cpp | 88 ------- cmds/idmap2/libidmap2/PolicyUtils.cpp | 61 +++++ cmds/idmap2/libidmap2/ResourceMapping.cpp | 10 +- .../include/idmap2/Policies.h | 39 +-- cmds/idmap2/tests/Idmap2BinaryTests.cpp | 15 +- cmds/idmap2/tests/IdmapTests.cpp | 60 +++-- cmds/idmap2/tests/PoliciesTests.cpp | 66 ++--- cmds/idmap2/tests/PrettyPrintVisitorTests.cpp | 12 +- cmds/idmap2/tests/R.h | 94 ++++++++ cmds/idmap2/tests/RawPrintVisitorTests.cpp | 16 +- cmds/idmap2/tests/ResourceMappingTests.cpp | 225 ++++++++++-------- cmds/idmap2/tests/TestConstants.h | 30 +++ libs/androidfw/Android.bp | 1 - .../include/androidfw/ResourceTypes.h | 41 +++- libs/androidfw/tests/LoadedArsc_test.cpp | 14 +- services/core/Android.bp | 2 + .../com/android/server/om/IdmapManager.java | 16 +- tools/aapt2/Android.bp | 1 + tools/aapt2/Debug.cpp | 31 ++- tools/aapt2/ResourceParser.cpp | 31 ++- tools/aapt2/ResourceParser_test.cpp | 28 ++- tools/aapt2/ResourceTable.h | 32 +-- tools/aapt2/ResourceTable_test.cpp | 20 +- .../format/binary/BinaryResourceParser.cpp | 31 +-- tools/aapt2/format/binary/TableFlattener.cpp | 32 +-- .../format/binary/TableFlattener_test.cpp | 66 ++--- tools/aapt2/format/proto/ProtoDeserialize.cpp | 16 +- tools/aapt2/format/proto/ProtoSerialize.cpp | 16 +- .../format/proto/ProtoSerialize_test.cpp | 38 +-- tools/aapt2/link/TableMerger_test.cpp | 34 +-- 40 files changed, 788 insertions(+), 574 deletions(-) create mode 100644 cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl create mode 100644 cmds/idmap2/include/idmap2/PolicyUtils.h delete mode 100644 cmds/idmap2/libidmap2/Policies.cpp create mode 100644 cmds/idmap2/libidmap2/PolicyUtils.cpp rename cmds/idmap2/{ => libidmap2_policies}/include/idmap2/Policies.h (63%) create mode 100644 cmds/idmap2/tests/R.h create mode 100644 cmds/idmap2/tests/TestConstants.h diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp index 66f5c3908e4bb..645dc935fc07b 100644 --- a/cmds/idmap2/Android.bp +++ b/cmds/idmap2/Android.bp @@ -36,18 +36,7 @@ cc_library { ], host_supported: true, srcs: [ - "libidmap2/BinaryStreamVisitor.cpp", - "libidmap2/CommandLineOptions.cpp", - "libidmap2/FileUtils.cpp", - "libidmap2/Idmap.cpp", - "libidmap2/Policies.cpp", - "libidmap2/PrettyPrintVisitor.cpp", - "libidmap2/RawPrintVisitor.cpp", - "libidmap2/ResourceMapping.cpp", - "libidmap2/ResourceUtils.cpp", - "libidmap2/Result.cpp", - "libidmap2/XmlParser.cpp", - "libidmap2/ZipFile.cpp", + "libidmap2/**/*.cpp", ], export_include_dirs: ["include"], target: { @@ -61,6 +50,7 @@ cc_library { "libcutils", "libutils", "libziparchive", + "libidmap2_policies", ], }, host: { @@ -73,6 +63,37 @@ cc_library { "libcutils", "libutils", "libziparchive", + "libidmap2_policies", + ], + }, + }, +} + +cc_library { + name: "libidmap2_policies", + defaults: [ + "idmap2_defaults", + ], + host_supported: true, + export_include_dirs: ["libidmap2_policies/include"], + target: { + windows: { + enabled: true, + }, + android: { + static: { + enabled: false, + }, + shared_libs: [ + "libandroidfw", + ], + }, + host: { + shared: { + enabled: false, + }, + static_libs: [ + "libandroidfw", ], }, }, @@ -118,6 +139,7 @@ cc_test { "libutils", "libz", "libziparchive", + "libidmap2_policies", ], }, host: { @@ -129,6 +151,7 @@ cc_test { "liblog", "libutils", "libziparchive", + "libidmap2_policies", ], shared_libs: [ "libz", @@ -162,6 +185,7 @@ cc_binary { "libidmap2", "libutils", "libziparchive", + "libidmap2_policies", ], }, host: { @@ -173,12 +197,14 @@ cc_binary { "liblog", "libutils", "libziparchive", + "libidmap2_policies", ], shared_libs: [ "libz", ], }, }, + } cc_binary { @@ -199,6 +225,7 @@ cc_binary { "libidmap2", "libutils", "libziparchive", + "libidmap2_policies", ], static_libs: [ "libidmap2daidl", @@ -231,3 +258,16 @@ filegroup { ], path: "idmap2d/aidl", } + +aidl_interface { + name: "overlayable_policy_aidl", + srcs: [":overlayable_policy_aidl_files"], +} + +filegroup { + name: "overlayable_policy_aidl_files", + srcs: [ + "idmap2d/aidl/android/os/OverlayablePolicy.aidl", + ], + path: "idmap2d/aidl", +} diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp index 3ff6d3514331c..9682b6ead2932 100644 --- a/cmds/idmap2/idmap2/Create.cpp +++ b/cmds/idmap2/idmap2/Create.cpp @@ -20,15 +20,14 @@ #include #include #include -#include -#include #include +#include "androidfw/ResourceTypes.h" #include "idmap2/BinaryStreamVisitor.h" #include "idmap2/CommandLineOptions.h" #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" -#include "idmap2/Policies.h" +#include "idmap2/PolicyUtils.h" #include "idmap2/SysTrace.h" using android::ApkAssets; @@ -36,14 +35,15 @@ using android::idmap2::BinaryStreamVisitor; using android::idmap2::CommandLineOptions; using android::idmap2::Error; using android::idmap2::Idmap; -using android::idmap2::PoliciesToBitmask; -using android::idmap2::PolicyBitmask; -using android::idmap2::PolicyFlags; using android::idmap2::Result; using android::idmap2::Unit; using android::idmap2::utils::kIdmapFilePermissionMask; +using android::idmap2::utils::PoliciesToBitmaskResult; using android::idmap2::utils::UidHasWriteAccessToPath; +using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + Result Create(const std::vector& args) { SYSTRACE << "Create " << args; std::string target_apk_path; @@ -78,7 +78,7 @@ Result Create(const std::vector& args) { } PolicyBitmask fulfilled_policies = 0; - auto conv_result = PoliciesToBitmask(policies); + auto conv_result = PoliciesToBitmaskResult(policies); if (conv_result) { fulfilled_policies |= *conv_result; } else { @@ -86,7 +86,7 @@ Result Create(const std::vector& args) { } if (fulfilled_policies == 0) { - fulfilled_policies |= PolicyFlags::POLICY_PUBLIC; + fulfilled_policies |= PolicyFlags::PUBLIC; } const std::unique_ptr target_apk = ApkAssets::Load(target_apk_path); diff --git a/cmds/idmap2/idmap2/CreateMultiple.cpp b/cmds/idmap2/idmap2/CreateMultiple.cpp index d4e888fd3119c..ba4ca62826b62 100644 --- a/cmds/idmap2/idmap2/CreateMultiple.cpp +++ b/cmds/idmap2/idmap2/CreateMultiple.cpp @@ -20,8 +20,6 @@ #include #include #include -#include -#include #include #include "android-base/stringprintf.h" @@ -30,6 +28,7 @@ #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" #include "idmap2/Policies.h" +#include "idmap2/PolicyUtils.h" #include "idmap2/SysTrace.h" #include "Commands.h" @@ -39,13 +38,11 @@ using android::idmap2::BinaryStreamVisitor; using android::idmap2::CommandLineOptions; using android::idmap2::Error; using android::idmap2::Idmap; -using android::idmap2::PoliciesToBitmask; -using android::idmap2::PolicyBitmask; -using android::idmap2::PolicyFlags; using android::idmap2::Result; using android::idmap2::Unit; using android::idmap2::utils::kIdmapCacheDir; using android::idmap2::utils::kIdmapFilePermissionMask; +using android::idmap2::utils::PoliciesToBitmaskResult; using android::idmap2::utils::UidHasWriteAccessToPath; Result CreateMultiple(const std::vector& args) { @@ -81,7 +78,7 @@ Result CreateMultiple(const std::vector& args) { } PolicyBitmask fulfilled_policies = 0; - auto conv_result = PoliciesToBitmask(policies); + auto conv_result = PoliciesToBitmaskResult(policies); if (conv_result) { fulfilled_policies |= *conv_result; } else { @@ -89,7 +86,7 @@ Result CreateMultiple(const std::vector& args) { } if (fulfilled_policies == 0) { - fulfilled_policies |= PolicyFlags::POLICY_PUBLIC; + fulfilled_policies |= PolicyFlags::PUBLIC; } const std::unique_ptr target_apk = ApkAssets::Load(target_apk_path); diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp index b4fdd0b8a94db..da0453216f032 100644 --- a/cmds/idmap2/idmap2/Scan.cpp +++ b/cmds/idmap2/idmap2/Scan.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -34,25 +33,24 @@ #include "idmap2/Result.h" #include "idmap2/SysTrace.h" #include "idmap2/XmlParser.h" -#include "idmap2/ZipFile.h" using android::idmap2::CommandLineOptions; using android::idmap2::Error; using android::idmap2::Idmap; -using android::idmap2::kPolicyOdm; -using android::idmap2::kPolicyOem; -using android::idmap2::kPolicyProduct; -using android::idmap2::kPolicyPublic; -using android::idmap2::kPolicySystem; -using android::idmap2::kPolicyVendor; -using android::idmap2::PolicyBitmask; -using android::idmap2::PolicyFlags; using android::idmap2::Result; using android::idmap2::Unit; +using android::idmap2::policy::kPolicyOdm; +using android::idmap2::policy::kPolicyOem; +using android::idmap2::policy::kPolicyProduct; +using android::idmap2::policy::kPolicyPublic; +using android::idmap2::policy::kPolicySystem; +using android::idmap2::policy::kPolicyVendor; using android::idmap2::utils::ExtractOverlayManifestInfo; using android::idmap2::utils::FindFiles; using android::idmap2::utils::OverlayManifestInfo; +using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask; + namespace { struct InputOverlay { diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp index 4aabf8399a253..f84e4b5f2575c 100644 --- a/cmds/idmap2/idmap2d/Idmap2Service.cpp +++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp @@ -33,7 +33,6 @@ #include "idmap2/BinaryStreamVisitor.h" #include "idmap2/FileUtils.h" #include "idmap2/Idmap.h" -#include "idmap2/Policies.h" #include "idmap2/SysTrace.h" #include "utils/String8.h" @@ -42,11 +41,12 @@ using android::binder::Status; using android::idmap2::BinaryStreamVisitor; using android::idmap2::Idmap; using android::idmap2::IdmapHeader; -using android::idmap2::PolicyBitmask; using android::idmap2::utils::kIdmapCacheDir; using android::idmap2::utils::kIdmapFilePermissionMask; using android::idmap2::utils::UidHasWriteAccessToPath; +using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask; + namespace { Status ok() { diff --git a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl index cd474c0fe0564..f4cf65134023a 100644 --- a/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl +++ b/cmds/idmap2/idmap2d/aidl/android/os/IIdmap2.aidl @@ -20,14 +20,6 @@ package android.os; * @hide */ interface IIdmap2 { - const int POLICY_PUBLIC = 0x00000001; - const int POLICY_SYSTEM_PARTITION = 0x00000002; - 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); boolean verifyIdmap(@utf8InCpp String overlayApkPath, int fulfilledPolicies, diff --git a/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl b/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl new file mode 100644 index 0000000000000..85b5eff46efa5 --- /dev/null +++ b/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2019 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 android.os; + +/** + * @see ResourcesTypes.h ResTable_overlayable_policy_header::PolicyFlags + * @hide + */ +interface OverlayablePolicy { + const int PUBLIC = 0x00000001; + const int SYSTEM_PARTITION = 0x00000002; + const int VENDOR_PARTITION = 0x00000004; + const int PRODUCT_PARTITION = 0x00000008; + const int SIGNATURE = 0x00000010; + const int ODM_PARTITION = 0x00000020; + const int OEM_PARTITION = 0x00000040; +} diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h index d4a0c3221c203..2e4836e297ec2 100644 --- a/cmds/idmap2/include/idmap2/Idmap.h +++ b/cmds/idmap2/include/idmap2/Idmap.h @@ -73,7 +73,6 @@ #include "androidfw/ApkAssets.h" #include "androidfw/ResourceTypes.h" #include "androidfw/StringPiece.h" -#include "idmap2/Policies.h" #include "idmap2/ResourceMapping.h" namespace android::idmap2 { diff --git a/cmds/idmap2/include/idmap2/PolicyUtils.h b/cmds/idmap2/include/idmap2/PolicyUtils.h new file mode 100644 index 0000000000000..b95b8b420658c --- /dev/null +++ b/cmds/idmap2/include/idmap2/PolicyUtils.h @@ -0,0 +1,41 @@ +/* + * 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. + */ + +#ifndef IDMAP2_INCLUDE_IDMAP2_POLICYUTILS_H_ +#define IDMAP2_INCLUDE_IDMAP2_POLICYUTILS_H_ + +#include +#include + +#include "androidfw/ResourceTypes.h" +#include "idmap2/Policies.h" +#include "idmap2/Result.h" + +using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask; + +namespace android::idmap2::utils { + +// Returns a Result object containing a policy flag bitmask built from a list of policy strings. +// On error will contain a human readable message listing the invalid policies. +Result PoliciesToBitmaskResult(const std::vector& policies); + +// Converts a bitmask of policy flags into a list of their string representation as would be written +// into XML +std::vector BitmaskToPolicies(const PolicyBitmask& bitmask); + +} // namespace android::idmap2::utils + +#endif // IDMAP2_INCLUDE_IDMAP2_POLICYUTILS_H_ diff --git a/cmds/idmap2/include/idmap2/ResourceMapping.h b/cmds/idmap2/include/idmap2/ResourceMapping.h index 86dfab20e4487..5869409e7db91 100644 --- a/cmds/idmap2/include/idmap2/ResourceMapping.h +++ b/cmds/idmap2/include/idmap2/ResourceMapping.h @@ -30,6 +30,8 @@ using android::idmap2::utils::OverlayManifestInfo; +using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask; + namespace android::idmap2 { struct TargetValue { diff --git a/cmds/idmap2/libidmap2/Policies.cpp b/cmds/idmap2/libidmap2/Policies.cpp deleted file mode 100644 index 495fe615a91f9..0000000000000 --- a/cmds/idmap2/libidmap2/Policies.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "idmap2/Policies.h" - -#include -#include -#include -#include - -#include "androidfw/ResourceTypes.h" -#include "idmap2/Idmap.h" -#include "idmap2/Result.h" - -namespace android::idmap2 { - -Result PoliciesToBitmask(const std::vector& policies) { - static const std::unordered_map 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); - if (iter != kStringToFlag.end()) { - bitmask |= iter->second; - } else { - return Error("unknown policy \"%s\"", policy.c_str()); - } - } - - return Result(bitmask); -} - -std::vector BitmaskToPolicies(const PolicyBitmask& bitmask) { - std::vector 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); - } - - if ((bitmask & PolicyFlags::POLICY_PRODUCT_PARTITION) != 0) { - 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); - } - - if ((bitmask & PolicyFlags::POLICY_VENDOR_PARTITION) != 0) { - policies.emplace_back(kPolicyVendor); - } - - return policies; -} - -} // namespace android::idmap2 diff --git a/cmds/idmap2/libidmap2/PolicyUtils.cpp b/cmds/idmap2/libidmap2/PolicyUtils.cpp new file mode 100644 index 0000000000000..fc5182af61c12 --- /dev/null +++ b/cmds/idmap2/libidmap2/PolicyUtils.cpp @@ -0,0 +1,61 @@ +/* + * 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. + */ + +#include "include/idmap2/PolicyUtils.h" + +#include + +#include "android-base/strings.h" +#include "idmap2/Policies.h" + +using android::idmap2::policy::kPolicyStringToFlag; + +namespace android::idmap2::utils { + +Result PoliciesToBitmaskResult(const std::vector& policies) { + std::vector unknown_policies; + PolicyBitmask bitmask = 0; + for (const std::string& policy : policies) { + const auto result = std::find_if(kPolicyStringToFlag.begin(), kPolicyStringToFlag.end(), + [policy](const auto& it) { return policy == it.first; }); + if (result != kPolicyStringToFlag.end()) { + bitmask |= result->second; + } else { + unknown_policies.emplace_back(policy.empty() ? "empty" : policy); + } + } + + if (unknown_policies.empty()) { + return Result(bitmask); + } + + auto prefix = unknown_policies.size() == 1 ? "policy" : "policies"; + return Error("unknown %s: \"%s\"", prefix, android::base::Join(unknown_policies, ",").c_str()); +} + +std::vector BitmaskToPolicies(const PolicyBitmask& bitmask) { + std::vector policies; + + for (const auto& policy : kPolicyStringToFlag) { + if ((bitmask & policy.second) != 0) { + policies.emplace_back(policy.first.to_string()); + } + } + + return policies; +} + +} // namespace android::idmap2::utils diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp index 43cfec3f9cf92..f82c8f1af7139 100644 --- a/cmds/idmap2/libidmap2/ResourceMapping.cpp +++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp @@ -24,11 +24,16 @@ #include #include "android-base/stringprintf.h" +#include "androidfw/ResourceTypes.h" +#include "idmap2/PolicyUtils.h" #include "idmap2/ResourceUtils.h" using android::base::StringPrintf; +using android::idmap2::utils::BitmaskToPolicies; using android::idmap2::utils::IsReference; using android::idmap2::utils::ResToTypeEntryName; +using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; namespace android::idmap2 { @@ -55,9 +60,8 @@ Result CheckOverlayable(const LoadedPackage& target_package, const PolicyBitmask& fulfilled_policies, const ResourceId& target_resource) { 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; + PolicyFlags::ODM_PARTITION | PolicyFlags::OEM_PARTITION | PolicyFlags::SYSTEM_PARTITION | + PolicyFlags::VENDOR_PARTITION | PolicyFlags::PRODUCT_PARTITION | PolicyFlags::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. diff --git a/cmds/idmap2/include/idmap2/Policies.h b/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h similarity index 63% rename from cmds/idmap2/include/idmap2/Policies.h rename to cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h index 87edd3506d334..9f9b836e31d54 100644 --- a/cmds/idmap2/include/idmap2/Policies.h +++ b/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h @@ -14,17 +14,20 @@ * limitations under the License. */ -#include -#include - -#include "Result.h" -#include "androidfw/ResourceTypes.h" -#include "androidfw/StringPiece.h" - #ifndef IDMAP2_INCLUDE_IDMAP2_POLICIES_H_ #define IDMAP2_INCLUDE_IDMAP2_POLICIES_H_ -namespace android::idmap2 { +#include +#include +#include + +#include "androidfw/ResourceTypes.h" +#include "androidfw/StringPiece.h" + +using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + +namespace android::idmap2::policy { constexpr const char* kPolicyOdm = "odm"; constexpr const char* kPolicyOem = "oem"; @@ -34,15 +37,15 @@ constexpr const char* kPolicySignature = "signature"; constexpr const char* kPolicySystem = "system"; constexpr const char* kPolicyVendor = "vendor"; -using PolicyFlags = ResTable_overlayable_policy_header::PolicyFlags; -using PolicyBitmask = uint32_t; - -// Parses the string representations of policies into a bitmask. -Result PoliciesToBitmask(const std::vector& policies); - -// Retrieves the string representations of policies in the bitmask. -std::vector BitmaskToPolicies(const PolicyBitmask& bitmask); - -} // namespace android::idmap2 +inline static const std::array, 7> kPolicyStringToFlag = { + std::pair{kPolicyOdm, PolicyFlags::ODM_PARTITION}, + {kPolicyOem, PolicyFlags::OEM_PARTITION}, + {kPolicyProduct, PolicyFlags::PRODUCT_PARTITION}, + {kPolicyPublic, PolicyFlags::PUBLIC}, + {kPolicySignature, PolicyFlags::SIGNATURE}, + {kPolicySystem, PolicyFlags::SYSTEM_PARTITION}, + {kPolicyVendor, PolicyFlags::VENDOR_PARTITION}, +}; +} // namespace android::idmap2::policy #endif // IDMAP2_INCLUDE_IDMAP2_POLICIES_H_ diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp index b535f30de1f50..d896cf9c11ba5 100644 --- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp +++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp @@ -34,6 +34,7 @@ #include #include +#include "R.h" #include "TestHelpers.h" #include "androidfw/PosixUtils.h" #include "gmock/gmock.h" @@ -127,10 +128,14 @@ TEST_F(Idmap2BinaryTests, Dump) { // clang-format on 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("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_NE(result->stdout.find(R::target::integer::literal::int1 + " -> 0x7f010000 integer/int1"), + std::string::npos); + ASSERT_NE(result->stdout.find(R::target::string::literal::str1 + " -> 0x7f020000 string/str1"), + std::string::npos); + ASSERT_NE(result->stdout.find(R::target::string::literal::str3 + " -> 0x7f020001 string/str3"), + std::string::npos); + ASSERT_NE(result->stdout.find(R::target::string::literal::str4 + " -> 0x7f020002 string/str4"), + std::string::npos); // clang-format off result = ExecuteBinary({"idmap2", @@ -297,7 +302,7 @@ TEST_F(Idmap2BinaryTests, Lookup) { "lookup", "--idmap-path", GetIdmapPath(), "--config", "", - "--resid", "0x7f02000c"}); // string/str1 + "--resid", R::target::string::literal::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 a2c156063757d..76c6eaf75adc2 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -22,6 +22,8 @@ #include #include +#include "R.h" +#include "TestConstants.h" #include "TestHelpers.h" #include "android-base/macros.h" #include "androidfw/ApkAssets.h" @@ -36,6 +38,8 @@ using android::Res_value; using ::testing::IsNull; using ::testing::NotNull; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + namespace android::idmap2 { #define ASSERT_TARGET_ENTRY(entry, target_resid, type, value) \ @@ -168,7 +172,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromApkAssets) { std::unique_ptr overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); - auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC, + auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::PUBLIC, /* enforce_overlayable */ true); ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage(); auto& idmap = *idmap_result; @@ -177,8 +181,8 @@ TEST(IdmapTests, CreateIdmapHeaderFromApkAssets) { ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x03U); - ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x76a20829); - ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xc054fb26); + ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), android::idmap2::TestConstants::TARGET_CRC); + ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), android::idmap2::TestConstants::OVERLAY_CRC); ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path); ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path); } @@ -220,7 +224,7 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssets) { std::unique_ptr overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); - auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC, + auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::PUBLIC, /* enforce_overlayable */ true); ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage(); auto& idmap = *idmap_result; @@ -234,17 +238,21 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssets) { const auto& target_entries = data->GetTargetEntries(); ASSERT_EQ(target_entries.size(), 4U); - ASSERT_TARGET_ENTRY(target_entries[0], 0x7f010000, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f010000); - ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020000); - ASSERT_TARGET_ENTRY(target_entries[2], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001); - ASSERT_TARGET_ENTRY(target_entries[3], 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020002); + 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); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(target_entries.size(), 4U); - ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x7f010000, 0x7f010000); - ASSERT_OVERLAY_ENTRY(overlay_entries[1], 0x7f020000, 0x7f02000c); - ASSERT_OVERLAY_ENTRY(overlay_entries[2], 0x7f020001, 0x7f02000e); - ASSERT_OVERLAY_ENTRY(overlay_entries[3], 0x7f020002, 0x7f02000f); + ASSERT_OVERLAY_ENTRY(overlay_entries[0], R::overlay::integer::int1, R::target::integer::int1); + ASSERT_OVERLAY_ENTRY(overlay_entries[1], R::overlay::string::str1, R::target::string::str1); + ASSERT_OVERLAY_ENTRY(overlay_entries[2], R::overlay::string::str3, R::target::string::str3); + ASSERT_OVERLAY_ENTRY(overlay_entries[3], R::overlay::string::str4, R::target::string::str4); } TEST(IdmapTests, CreateIdmapDataFromApkAssetsSharedLibOverlay) { @@ -257,7 +265,7 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssetsSharedLibOverlay) { std::unique_ptr overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); - auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC, + auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::PUBLIC, /* enforce_overlayable */ true); ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage(); auto& idmap = *idmap_result; @@ -290,7 +298,7 @@ TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) { info.target_name = "TestResources"; info.resource_mapping = 0x7f030001; // xml/overlays_different_packages auto idmap_data = TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk", info, - PolicyFlags::POLICY_PUBLIC, + PolicyFlags::PUBLIC, /* enforce_overlayable */ false); ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage(); @@ -298,14 +306,14 @@ TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) { const auto& target_entries = data->GetTargetEntries(); ASSERT_EQ(target_entries.size(), 2U); - ASSERT_TARGET_ENTRY(target_entries[0], 0x7f02000c, Res_value::TYPE_REFERENCE, - 0x0104000a); // string/str1 -> android:string/ok - ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, - 0x7f020001); // string/str3 -> string/str4 + ASSERT_TARGET_ENTRY(target_entries[0], R::target::string::str1, Res_value::TYPE_REFERENCE, + 0x0104000a); // -> android:string/ok + ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE, + R::overlay::string::str3); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(overlay_entries.size(), 1U); - ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x7f020001, 0x7f02000e); // string/str3 <- string/str4 + ASSERT_OVERLAY_ENTRY(overlay_entries[0], R::overlay::string::str3, R::target::string::str3); } TEST(IdmapTests, CreateIdmapDataInlineResources) { @@ -314,7 +322,7 @@ TEST(IdmapTests, CreateIdmapDataInlineResources) { info.target_name = "TestResources"; info.resource_mapping = 0x7f030002; // xml/overlays_inline auto idmap_data = TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk", info, - PolicyFlags::POLICY_PUBLIC, + PolicyFlags::PUBLIC, /* enforce_overlayable */ false); ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage(); @@ -323,10 +331,10 @@ TEST(IdmapTests, CreateIdmapDataInlineResources) { 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], 0x7f010000, Res_value::TYPE_INT_DEC, - 73U); // integer/int1 -> 73 - ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_STRING, - overlay_string_pool_size + 0U); // string/str1 -> "Hello World" + 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" const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(overlay_entries.size(), 0U); @@ -346,7 +354,7 @@ TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) { std::unique_ptr overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); - const auto result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC, + const auto result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::PUBLIC, /* enforce_overlayable */ true); ASSERT_FALSE(result); } @@ -362,7 +370,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) { std::unique_ptr overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); - auto result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC, + auto result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::PUBLIC, /* enforce_overlayable */ true); ASSERT_TRUE(result); const auto idmap = std::move(*result); diff --git a/cmds/idmap2/tests/PoliciesTests.cpp b/cmds/idmap2/tests/PoliciesTests.cpp index eca74045f4289..4b395c7912d12 100644 --- a/cmds/idmap2/tests/PoliciesTests.cpp +++ b/cmds/idmap2/tests/PoliciesTests.cpp @@ -17,74 +17,78 @@ #include #include "TestHelpers.h" +#include "androidfw/ResourceTypes.h" #include "gtest/gtest.h" -#include "idmap2/Policies.h" +#include "idmap2/PolicyUtils.h" -using android::idmap2::PolicyBitmask; -using android::idmap2::PolicyFlags; +using android::idmap2::utils::BitmaskToPolicies; +using android::idmap2::utils::PoliciesToBitmaskResult; + +using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; namespace android::idmap2 { -TEST(PoliciesTests, PoliciesToBitmasks) { - const auto bitmask1 = PoliciesToBitmask({"system"}); +TEST(PoliciesTests, PoliciesToBitmaskResults) { + const auto bitmask1 = PoliciesToBitmaskResult({"system"}); ASSERT_TRUE(bitmask1); - ASSERT_EQ(*bitmask1, PolicyFlags::POLICY_SYSTEM_PARTITION); + ASSERT_EQ(*bitmask1, PolicyFlags::SYSTEM_PARTITION); - const auto bitmask2 = PoliciesToBitmask({"system", "vendor"}); + const auto bitmask2 = PoliciesToBitmaskResult({"system", "vendor"}); ASSERT_TRUE(bitmask2); - ASSERT_EQ(*bitmask2, PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION); + ASSERT_EQ(*bitmask2, PolicyFlags::SYSTEM_PARTITION | PolicyFlags::VENDOR_PARTITION); - const auto bitmask3 = PoliciesToBitmask({"vendor", "system"}); + const auto bitmask3 = PoliciesToBitmaskResult({"vendor", "system"}); ASSERT_TRUE(bitmask3); - ASSERT_EQ(*bitmask3, PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION); + ASSERT_EQ(*bitmask3, PolicyFlags::SYSTEM_PARTITION | PolicyFlags::VENDOR_PARTITION); - const auto bitmask4 = PoliciesToBitmask({"odm", "oem", "public", "product", "system", "vendor"}); + const auto bitmask4 = + PoliciesToBitmaskResult({"odm", "oem", "public", "product", "system", "vendor"}); ASSERT_TRUE(bitmask4); - 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); + ASSERT_EQ(*bitmask4, PolicyFlags::ODM_PARTITION | PolicyFlags::OEM_PARTITION | + PolicyFlags::PUBLIC | PolicyFlags::PRODUCT_PARTITION | + PolicyFlags::SYSTEM_PARTITION | PolicyFlags::VENDOR_PARTITION); - const auto bitmask5 = PoliciesToBitmask({"system", "system", "system"}); + const auto bitmask5 = PoliciesToBitmaskResult({"system", "system", "system"}); ASSERT_TRUE(bitmask5); - ASSERT_EQ(*bitmask5, PolicyFlags::POLICY_SYSTEM_PARTITION); + ASSERT_EQ(*bitmask5, PolicyFlags::SYSTEM_PARTITION); - const auto bitmask6 = PoliciesToBitmask({""}); + const auto bitmask6 = PoliciesToBitmaskResult({""}); ASSERT_FALSE(bitmask6); - const auto bitmask7 = PoliciesToBitmask({"foo"}); + const auto bitmask7 = PoliciesToBitmaskResult({"foo"}); ASSERT_FALSE(bitmask7); - const auto bitmask8 = PoliciesToBitmask({"system", "foo"}); + const auto bitmask8 = PoliciesToBitmaskResult({"system", "foo"}); ASSERT_FALSE(bitmask8); - const auto bitmask9 = PoliciesToBitmask({"system", ""}); + const auto bitmask9 = PoliciesToBitmaskResult({"system", ""}); ASSERT_FALSE(bitmask9); - const auto bitmask10 = PoliciesToBitmask({"system "}); + const auto bitmask10 = PoliciesToBitmaskResult({"system "}); ASSERT_FALSE(bitmask10); } TEST(PoliciesTests, BitmaskToPolicies) { - const auto policies1 = BitmaskToPolicies(PolicyFlags::POLICY_PUBLIC); + const auto policies1 = BitmaskToPolicies(PolicyFlags::PUBLIC); ASSERT_EQ(1, policies1.size()); ASSERT_EQ(policies1[0], "public"); - const auto policies2 = BitmaskToPolicies(PolicyFlags::POLICY_SYSTEM_PARTITION | - PolicyFlags::POLICY_VENDOR_PARTITION); + const auto policies2 = + BitmaskToPolicies(PolicyFlags::SYSTEM_PARTITION | PolicyFlags::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); + const auto policies3 = + BitmaskToPolicies(PolicyFlags::ODM_PARTITION | PolicyFlags::OEM_PARTITION | + PolicyFlags::PUBLIC | PolicyFlags::PRODUCT_PARTITION | + PolicyFlags::SYSTEM_PARTITION | PolicyFlags::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[2], "product"); + ASSERT_EQ(policies3[3], "public"); ASSERT_EQ(policies3[4], "system"); ASSERT_EQ(policies3[5], "vendor"); } diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp index 1d34e42e188d0..9a10079772bf5 100644 --- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp @@ -18,19 +18,22 @@ #include #include +#include "R.h" #include "TestHelpers.h" #include "androidfw/ApkAssets.h" #include "androidfw/Idmap.h" +#include "androidfw/ResourceTypes.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "idmap2/Idmap.h" -#include "idmap2/Policies.h" #include "idmap2/PrettyPrintVisitor.h" using ::testing::NotNull; using android::ApkAssets; -using android::idmap2::PolicyBitmask; + +using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; namespace android::idmap2 { @@ -43,7 +46,7 @@ TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitor) { std::unique_ptr overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); - const auto idmap = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC, + const auto idmap = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::PUBLIC, /* enforce_overlayable */ true); ASSERT_TRUE(idmap); @@ -53,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("0x7f010000 -> 0x7f010000 integer/int1\n"), std::string::npos); + ASSERT_NE(stream.str().find(R::target::integer::literal::int1 + " -> 0x7f010000 integer/int1\n"), + std::string::npos); } TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitorWithoutAccessToApks) { diff --git a/cmds/idmap2/tests/R.h b/cmds/idmap2/tests/R.h new file mode 100644 index 0000000000000..b2a589144c773 --- /dev/null +++ b/cmds/idmap2/tests/R.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2019 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. + */ + +#ifndef IDMAP2_TESTS_R_H +#define IDMAP2_TESTS_R_H + +#include + +namespace android::idmap2 { + +static std::string hexify(ResourceId id) { + std::stringstream stream; + stream << std::hex << static_cast(id); + return stream.str(); +} + +// clang-format off +namespace R::target { + namespace integer { + constexpr ResourceId int1 = 0x7f010000; + + namespace literal { + inline const std::string int1 = hexify(R::target::integer::int1); + } + } + + namespace string { + constexpr ResourceId not_overlayable = 0x7f020003; + constexpr ResourceId other = 0x7f020004; + constexpr ResourceId policy_odm = 0x7f020005; + constexpr ResourceId policy_oem = 0x7f020006; + constexpr ResourceId policy_product = 0x7f020007; + constexpr ResourceId policy_public = 0x7f020008; + constexpr ResourceId policy_signature = 0x7f020009; + constexpr ResourceId policy_system = 0x7f02000a; + constexpr ResourceId policy_system_vendor = 0x7f02000b; + constexpr ResourceId str1 = 0x7f02000c; + constexpr ResourceId str3 = 0x7f02000e; + constexpr ResourceId str4 = 0x7f02000f; + + namespace literal { + inline const std::string str1 = hexify(R::target::string::str1); + inline const std::string str3 = hexify(R::target::string::str3); + inline const std::string str4 = hexify(R::target::string::str4); + } + } +} + +namespace R::overlay { + namespace integer { + constexpr ResourceId int1 = 0x7f010000; + } + namespace string { + constexpr ResourceId str1 = 0x7f020000; + constexpr ResourceId str3 = 0x7f020001; + constexpr ResourceId str4 = 0x7f020002; + } +} + +namespace R::system_overlay::string { + constexpr ResourceId policy_public = 0x7f010000; + constexpr ResourceId policy_system = 0x7f010001; + constexpr ResourceId policy_system_vendor = 0x7f010002; +} + +namespace R::system_overlay_invalid::string { + constexpr ResourceId not_overlayable = 0x7f010000; + constexpr ResourceId other = 0x7f010001; + constexpr ResourceId policy_odm = 0x7f010002; + constexpr ResourceId policy_oem = 0x7f010003; + constexpr ResourceId policy_product = 0x7f010004; + constexpr ResourceId policy_public = 0x7f010005; + constexpr ResourceId policy_signature = 0x7f010006; + constexpr ResourceId policy_system = 0x7f010007; + constexpr ResourceId policy_system_vendor = 0x7f010008; +}; +// clang-format on + +} // namespace android::idmap2 + +#endif // IDMAP2_TESTS_R_H diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp index b22fdafb09bbb..5c5c81edee90d 100644 --- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp @@ -20,14 +20,20 @@ #include #include +#include "TestConstants.h" #include "TestHelpers.h" +#include "android-base/stringprintf.h" +#include "androidfw/ResourceTypes.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "idmap2/Idmap.h" #include "idmap2/RawPrintVisitor.h" +using android::base::StringPrintf; using ::testing::NotNull; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + namespace android::idmap2 { #define ASSERT_CONTAINS_REGEX(pattern, str) \ @@ -48,7 +54,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { std::unique_ptr overlay_apk = ApkAssets::Load(overlay_apk_path); ASSERT_THAT(overlay_apk, NotNull()); - const auto idmap = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC, + const auto idmap = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::PUBLIC, /* enforce_overlayable */ true); ASSERT_TRUE(idmap); @@ -59,8 +65,12 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { #define ADDRESS "[0-9a-f]{8}: " ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000003 version\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "76a20829 target crc\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "c054fb26 overlay crc\n", stream.str()); + ASSERT_CONTAINS_REGEX( + StringPrintf(ADDRESS "%s target crc\n", android::idmap2::TestConstants::TARGET_CRC_STRING), + stream.str()); + ASSERT_CONTAINS_REGEX( + StringPrintf(ADDRESS "%s overlay crc\n", android::idmap2::TestConstants::OVERLAY_CRC_STRING), + 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()); diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp index 39c4937b09300..8d0e6609ac409 100644 --- a/cmds/idmap2/tests/ResourceMappingTests.cpp +++ b/cmds/idmap2/tests/ResourceMappingTests.cpp @@ -22,7 +22,9 @@ #include #include +#include "R.h" #include "TestHelpers.h" +#include "androidfw/ResourceTypes.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "idmap2/LogInfo.h" @@ -31,6 +33,8 @@ using android::Res_value; using android::idmap2::utils::ExtractOverlayManifestInfo; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + namespace android::idmap2 { #define ASSERT_RESULT(r) \ @@ -106,20 +110,20 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsLegacy) { info.target_name = "TestResources"; info.resource_mapping = 0U; // no xml auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info, - PolicyFlags::POLICY_PUBLIC, + PolicyFlags::PUBLIC, /* enforce_overlayable */ false); ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U); - ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_REFERENCE, 0x7f010000, - false /* rewrite */)); // integer/int1 - ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x7f020000, - false /* rewrite */)); // string/str1 - ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_REFERENCE, 0x7f020001, - false /* rewrite */)); // string/str3 - ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_REFERENCE, 0x7f020002, - false /* rewrite */)); // string/str4 + 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 */)); } TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) { @@ -128,18 +132,18 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) { info.target_name = "TestResources"; info.resource_mapping = 0x7f030003; // xml/overlays_swap auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info, - PolicyFlags::POLICY_PUBLIC, + PolicyFlags::PUBLIC, /* enforce_overlayable */ false); ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U); - ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020002, - true /* rewrite */)); // string/str1 -> string/str4 - ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020000, - true /* rewrite */)); // string/str3 -> string/str1 - ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001, - true /* rewrite */)); // string/str4 -> string/str3 + 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 */)); } TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) { @@ -148,17 +152,17 @@ TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) { info.target_name = "TestResources"; info.resource_mapping = 0x7f030001; // xml/overlays_different_packages auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info, - PolicyFlags::POLICY_PUBLIC, + PolicyFlags::PUBLIC, /* enforce_overlayable */ false); ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U); ASSERT_EQ(res.GetOverlayToTargetMap().size(), 1U); - ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x0104000a, - false /* rewrite */)); // string/str1 -> android:string/ok - ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001, - true /* rewrite */)); // string/str3 -> string/str4 + ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE, 0x0104000a, + false /* rewrite */)); // -> android:string/ok + ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE, + 0x7f020001, true /* rewrite */)); } TEST(ResourceMappingTests, InlineResources) { @@ -167,7 +171,7 @@ TEST(ResourceMappingTests, InlineResources) { info.target_name = "TestResources"; info.resource_mapping = 0x7f030002; // xml/overlays_inline auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info, - PolicyFlags::POLICY_PUBLIC, + PolicyFlags::PUBLIC, /* enforce_overlayable */ false); constexpr size_t overlay_string_pool_size = 8U; @@ -175,108 +179,117 @@ TEST(ResourceMappingTests, InlineResources) { auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U); ASSERT_EQ(res.GetOverlayToTargetMap().size(), 0U); - ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_STRING, + ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_STRING, overlay_string_pool_size + 0U, - false /* rewrite */)); // string/str1 -> "Hello World" - ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_INT_DEC, 73U, - false /* rewrite */)); // string/str1 -> "Hello World" + false /* rewrite */)); // -> "Hello World" + ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_INT_DEC, 73U, + false /* rewrite */)); // -> 73 } TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublic) { auto resources = TestGetResourceMapping("/target/target.apk", "/system-overlay/system-overlay.apk", - PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC, + PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC, /* enforce_overlayable */ true); ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U); - ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010000, - false /* rewrite */)); // string/policy_public - ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010001, - false /* rewrite */)); // string/policy_system - ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010002, - false /* rewrite */)); // string/policy_system_vendor + ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE, + R::system_overlay::string::policy_public, false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE, + 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 */)); } // Resources that are not declared as overlayable and resources that a protected by policies the // overlay does not fulfill must not map to overlay resources. TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) { - auto resources = TestGetResourceMapping( - "/target/target.apk", "/system-overlay-invalid/system-overlay-invalid.apk", - PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC, - /* enforce_overlayable */ true); + auto resources = TestGetResourceMapping("/target/target.apk", + "/system-overlay-invalid/system-overlay-invalid.apk", + PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC, + /* enforce_overlayable */ true); ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U); - ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005, - false /* rewrite */)); // string/policy_public - ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007, - false /* rewrite */)); // string/policy_system - ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008, - false /* rewrite */)); // string/policy_system_vendor + 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_system, Res_value::TYPE_REFERENCE, + 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 */)); } // Resources that are not declared as overlayable and resources that a protected by policies the // overlay does not fulfilled can map to overlay resources when overlayable enforcement is turned // off. TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) { - auto resources = TestGetResourceMapping( - "/target/target.apk", "/system-overlay-invalid/system-overlay-invalid.apk", - PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC, - /* enforce_overlayable */ false); + auto resources = TestGetResourceMapping("/target/target.apk", + "/system-overlay-invalid/system-overlay-invalid.apk", + PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC, + /* enforce_overlayable */ false); ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 9U); - ASSERT_RESULT(MappingExists(res, 0x7f020003, Res_value::TYPE_REFERENCE, 0x7f010000, - false /* rewrite */)); // string/not_overlayable - ASSERT_RESULT(MappingExists(res, 0x7f020004, Res_value::TYPE_REFERENCE, 0x7f010001, - false /* rewrite */)); // string/other - ASSERT_RESULT(MappingExists(res, 0x7f020005, Res_value::TYPE_REFERENCE, 0x7f010002, - false /* rewrite */)); // string/policy_odm - ASSERT_RESULT(MappingExists(res, 0x7f020006, Res_value::TYPE_REFERENCE, 0x7f010003, - false /* rewrite */)); // string/policy_oem - ASSERT_RESULT(MappingExists(res, 0x7f020007, Res_value::TYPE_REFERENCE, 0x7f010004, - false /* rewrite */)); // string/policy_product - ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005, - false /* rewrite */)); // string/policy_public - ASSERT_RESULT(MappingExists(res, 0x7f020009, Res_value::TYPE_REFERENCE, 0x7f010006, - false /* rewrite */)); // string/policy_signature - ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007, - false /* rewrite */)); // string/policy_system - ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008, - false /* rewrite */)); // string/policy_system_vendor + ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::not_overlayable, + false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::other, false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::policy_odm, false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::policy_oem, false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::policy_product, + false /* rewrite */)); + 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_signature, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::policy_signature, + false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE, + 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 */)); } // Overlays that do not target an tag can overlay resources defined within any // tag. TEST(ResourceMappingTests, ResourcesFromApkAssetsNoDefinedOverlayableAndNoTargetName) { auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay-no-name.apk", - PolicyFlags::POLICY_PUBLIC, + PolicyFlags::PUBLIC, /* enforce_overlayable */ false); ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U); - ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_REFERENCE, 0x7f010000, - false /* rewrite */)); // integer/int1 - ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x7f020000, - false /* rewrite */)); // string/str1 - ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_REFERENCE, 0x7f020001, - false /* rewrite */)); // string/str3 - ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_REFERENCE, 0x7f020002, - false /* rewrite */)); // string/str4 + 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 */)); } // Overlays that are neither pre-installed nor signed with the same signature as the target cannot // overlay packages that have not defined overlayable resources. TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) { - auto resources = - TestGetResourceMapping("/target/target-no-overlayable.apk", "/overlay/overlay-no-name.apk", - PolicyFlags::POLICY_PUBLIC, - /* enforce_overlayable */ true); + auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk", + "/overlay/overlay-no-name.apk", PolicyFlags::PUBLIC, + /* enforce_overlayable */ true); ASSERT_TRUE(resources) << resources.GetErrorMessage(); ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U); @@ -294,32 +307,40 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) { ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 9U); - ASSERT_RESULT(MappingExists(res, 0x7f020003, Res_value::TYPE_REFERENCE, 0x7f010000, - false /* rewrite */)); // string/not_overlayable - ASSERT_RESULT(MappingExists(res, 0x7f020004, Res_value::TYPE_REFERENCE, 0x7f010001, - false /* rewrite */)); // string/other - ASSERT_RESULT(MappingExists(res, 0x7f020005, Res_value::TYPE_REFERENCE, 0x7f010002, - false /* rewrite */)); // string/policy_odm - ASSERT_RESULT(MappingExists(res, 0x7f020006, Res_value::TYPE_REFERENCE, 0x7f010003, - false /* rewrite */)); // string/policy_oem - ASSERT_RESULT(MappingExists(res, 0x7f020007, Res_value::TYPE_REFERENCE, 0x7f010004, - false /* rewrite */)); // string/policy_product - ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005, - false /* rewrite */)); // string/policy_public - ASSERT_RESULT(MappingExists(res, 0x7f020009, Res_value::TYPE_REFERENCE, 0x7f010006, - false /* rewrite */)); // string/policy_signature - ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007, - false /* rewrite */)); // string/policy_system - ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008, - false /* rewrite */)); // string/policy_system_vendor + ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::not_overlayable, + false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::other, false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::policy_odm, + false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::policy_oem, + false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::policy_product, + false /* rewrite */)); + 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_signature, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::policy_signature, + false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE, + 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 */)); }; - CheckEntries(PolicyFlags::POLICY_SIGNATURE); - CheckEntries(PolicyFlags::POLICY_PRODUCT_PARTITION); - CheckEntries(PolicyFlags::POLICY_SYSTEM_PARTITION); - CheckEntries(PolicyFlags::POLICY_VENDOR_PARTITION); - CheckEntries(PolicyFlags::POLICY_ODM_PARTITION); - CheckEntries(PolicyFlags::POLICY_OEM_PARTITION); + CheckEntries(PolicyFlags::SIGNATURE); + CheckEntries(PolicyFlags::PRODUCT_PARTITION); + CheckEntries(PolicyFlags::SYSTEM_PARTITION); + CheckEntries(PolicyFlags::VENDOR_PARTITION); + CheckEntries(PolicyFlags::ODM_PARTITION); + CheckEntries(PolicyFlags::OEM_PARTITION); } } // namespace android::idmap2 diff --git a/cmds/idmap2/tests/TestConstants.h b/cmds/idmap2/tests/TestConstants.h new file mode 100644 index 0000000000000..c874dc93ce792 --- /dev/null +++ b/cmds/idmap2/tests/TestConstants.h @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#ifndef IDMAP2_TESTS_TESTCONSTANTS_H +#define IDMAP2_TESTS_TESTCONSTANTS_H + +namespace android::idmap2::TestConstants { + +constexpr const auto TARGET_CRC = 0x76a20829; +constexpr const auto TARGET_CRC_STRING = "76a20829"; + +constexpr const auto OVERLAY_CRC = 0xc054fb26; +constexpr const auto OVERLAY_CRC_STRING = "c054fb26"; + +} // namespace android::idmap2::TestConstants + +#endif // IDMAP2_TESTS_TESTCONSTANTS_H diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp index 3f2f3495ae8f1..f87f98a59a126 100644 --- a/libs/androidfw/Android.bp +++ b/libs/androidfw/Android.bp @@ -191,4 +191,3 @@ cc_benchmark { shared_libs: common_test_libs, data: ["tests/data/**/*.apk"], } - diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 35cebd425dc71..d15a3a27cbb12 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -34,6 +35,7 @@ #include +#include #include namespace android { @@ -1676,42 +1678,61 @@ struct ResTable_overlayable_header */ struct ResTable_overlayable_policy_header { - struct ResChunk_header header; - + /** + * Flags for a bitmask for all possible overlayable policy options. + * + * Any changes to this set should also update aidl/android/os/OverlayablePolicy.aidl + * and proto/OverlayablePolicy.proto. + */ enum PolicyFlags : uint32_t { + // Base + NONE = 0x00000000, + // Any overlay can overlay these resources. - POLICY_PUBLIC = 0x00000001, + PUBLIC = 0x00000001, // The overlay must reside of the system partition or must have existed on the system partition // before an upgrade to overlay these resources. - POLICY_SYSTEM_PARTITION = 0x00000002, + SYSTEM_PARTITION = 0x00000002, // The overlay must reside of the vendor partition or must have existed on the vendor partition // before an upgrade to overlay these resources. - POLICY_VENDOR_PARTITION = 0x00000004, + VENDOR_PARTITION = 0x00000004, // The overlay must reside of the product partition or must have existed on the product // partition before an upgrade to overlay these resources. - POLICY_PRODUCT_PARTITION = 0x00000008, + PRODUCT_PARTITION = 0x00000008, // 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, + 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, + 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, + OEM_PARTITION = 0x00000040, }; - uint32_t policy_flags; + + using PolicyBitmask = uint32_t; + + struct ResChunk_header header; + + PolicyFlags policy_flags; // The number of ResTable_ref that follow this header. uint32_t entry_count; }; +inline ResTable_overlayable_policy_header::PolicyFlags& operator |=( + ResTable_overlayable_policy_header::PolicyFlags& first, + ResTable_overlayable_policy_header::PolicyFlags second) { + first = static_cast(first | second); + return first; +} + #pragma pack(push, 1) struct Idmap_header { // Always 0x504D4449 ('IDMP') diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp index 8615069e98ddd..2d69dfe4f4295 100644 --- a/libs/androidfw/tests/LoadedArsc_test.cpp +++ b/libs/androidfw/tests/LoadedArsc_test.cpp @@ -41,6 +41,8 @@ using ::testing::NotNull; using ::testing::SizeIs; using ::testing::StrEq; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + namespace android { TEST(LoadedArscTest, LoadSinglePackageArsc) { @@ -240,29 +242,29 @@ TEST(LoadedArscTest, LoadOverlayable) { ASSERT_THAT(info, NotNull()); EXPECT_THAT(info->name, Eq("OverlayableResources1")); EXPECT_THAT(info->actor, Eq("overlay://theme")); - EXPECT_THAT(info->policy_flags, Eq(ResTable_overlayable_policy_header::POLICY_PUBLIC)); + EXPECT_THAT(info->policy_flags, Eq(PolicyFlags::PUBLIC)); info = package->GetOverlayableInfo(overlayable::R::string::overlayable2); ASSERT_THAT(info, NotNull()); EXPECT_THAT(info->name, Eq("OverlayableResources1")); EXPECT_THAT(info->actor, Eq("overlay://theme")); EXPECT_THAT(info->policy_flags, - Eq(ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION - | ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION)); + Eq(PolicyFlags::SYSTEM_PARTITION + | PolicyFlags::PRODUCT_PARTITION)); info = package->GetOverlayableInfo(overlayable::R::string::overlayable3); ASSERT_THAT(info, NotNull()); EXPECT_THAT(info->name, Eq("OverlayableResources2")); EXPECT_THAT(info->actor, Eq("overlay://com.android.overlayable")); EXPECT_THAT(info->policy_flags, - Eq(ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION - | ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION)); + Eq(PolicyFlags::VENDOR_PARTITION + | PolicyFlags::PRODUCT_PARTITION)); info = package->GetOverlayableInfo(overlayable::R::string::overlayable4); EXPECT_THAT(info->name, Eq("OverlayableResources1")); EXPECT_THAT(info->actor, Eq("overlay://theme")); ASSERT_THAT(info, NotNull()); - EXPECT_THAT(info->policy_flags, Eq(ResTable_overlayable_policy_header::POLICY_PUBLIC)); + EXPECT_THAT(info->policy_flags, Eq(PolicyFlags::PUBLIC)); } TEST(LoadedArscTest, ResourceIdentifierIterator) { diff --git a/services/core/Android.bp b/services/core/Android.bp index 3180ceb8f8e17..84ce34b4676fc 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -127,6 +127,8 @@ java_library_static { "android.hidl.manager-V1.2-java", "dnsresolver_aidl_interface-V2-java", "netd_event_listener_interface-java", + "ike-stubs", + "overlayable_policy_aidl-java", ], plugins: [ diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java index f3c912817d05c..48a1afd2be59c 100644 --- a/services/core/java/com/android/server/om/IdmapManager.java +++ b/services/core/java/com/android/server/om/IdmapManager.java @@ -24,7 +24,7 @@ import android.content.om.OverlayInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.os.Build.VERSION_CODES; -import android.os.IIdmap2; +import android.os.OverlayablePolicy; import android.os.SystemProperties; import android.os.UserHandle; import android.util.Slog; @@ -148,38 +148,38 @@ class IdmapManager { private int calculateFulfilledPolicies(@NonNull final PackageInfo targetPackage, @NonNull final PackageInfo overlayPackage, int userId) { final ApplicationInfo ai = overlayPackage.applicationInfo; - int fulfilledPolicies = IIdmap2.POLICY_PUBLIC; + int fulfilledPolicies = OverlayablePolicy.PUBLIC; // Overlay matches target signature if (mPackageManager.signaturesMatching(targetPackage.packageName, overlayPackage.packageName, userId)) { - fulfilledPolicies |= IIdmap2.POLICY_SIGNATURE; + fulfilledPolicies |= OverlayablePolicy.SIGNATURE; } // Vendor partition (/vendor) if (ai.isVendor()) { - return fulfilledPolicies | IIdmap2.POLICY_VENDOR_PARTITION; + return fulfilledPolicies | OverlayablePolicy.VENDOR_PARTITION; } // Product partition (/product) if (ai.isProduct()) { - return fulfilledPolicies | IIdmap2.POLICY_PRODUCT_PARTITION; + return fulfilledPolicies | OverlayablePolicy.PRODUCT_PARTITION; } // Odm partition (/odm) if (ai.isOdm()) { - return fulfilledPolicies | IIdmap2.POLICY_ODM_PARTITION; + return fulfilledPolicies | OverlayablePolicy.ODM_PARTITION; } // Oem partition (/oem) if (ai.isOem()) { - return fulfilledPolicies | IIdmap2.POLICY_OEM_PARTITION; + return fulfilledPolicies | OverlayablePolicy.OEM_PARTITION; } // System_ext partition (/system_ext) is considered as system // Check this last since every partition except for data is scanned as system in the PMS. if (ai.isSystemApp() || ai.isSystemExt()) { - return fulfilledPolicies | IIdmap2.POLICY_SYSTEM_PARTITION; + return fulfilledPolicies | OverlayablePolicy.SYSTEM_PARTITION; } return fulfilledPolicies; diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp index 6f442300bce7d..c1d05e47bc19c 100644 --- a/tools/aapt2/Android.bp +++ b/tools/aapt2/Android.bp @@ -59,6 +59,7 @@ cc_defaults { "libprotobuf-cpp-full", "libz", "libbuildversion", + "libidmap2_policies", ], stl: "libc++_static", group_static_libs: true, diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp index 137fbd671865f..1eb7d95f381ad 100644 --- a/tools/aapt2/Debug.cpp +++ b/tools/aapt2/Debug.cpp @@ -32,10 +32,16 @@ #include "text/Printer.h" #include "util/Util.h" +#include "idmap2/Policies.h" + using ::aapt::text::Printer; using ::android::StringPiece; using ::android::base::StringPrintf; +using android::idmap2::policy::kPolicyStringToFlag; + +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + namespace aapt { namespace { @@ -246,32 +252,25 @@ class ValueBodyPrinter : public ConstValueVisitor { Printer* printer_; }; -std::string OverlayablePoliciesToString(OverlayableItem::PolicyFlags policies) { - static const std::map kFlagToString = { - {OverlayableItem::kPublic, "public"}, - {OverlayableItem::kSystem, "system"}, - {OverlayableItem::kVendor, "vendor"}, - {OverlayableItem::kProduct, "product"}, - {OverlayableItem::kSignature, "signature"}, - {OverlayableItem::kOdm, "odm"}, - {OverlayableItem::kOem, "oem"}, - }; +std::string OverlayablePoliciesToString(PolicyFlags policies) { std::string str; - for (auto const& policy : kFlagToString) { - if ((policies & policy.first) != policy.first) { + + uint32_t remaining = policies; + for (auto const& policy : kPolicyStringToFlag) { + if ((policies & policy.second) != policy.second) { continue; } if (!str.empty()) { str.append("|"); } - str.append(policy.second); - policies &= ~policy.first; + str.append(policy.first.data()); + remaining &= ~policy.second; } - if (policies != 0) { + if (remaining != 0) { if (!str.empty()) { str.append("|"); } - str.append(StringPrintf("0x%08x", policies)); + str.append(StringPrintf("0x%08x", remaining)); } return !str.empty() ? str : "none"; } diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index 74e2a0987c3f1..234cbc4b37e08 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -32,11 +32,15 @@ #include "util/Util.h" #include "xml/XmlPullParser.h" +#include "idmap2/Policies.h" + using ::aapt::ResourceUtils::StringBuilder; using ::aapt::text::Utf8Iterator; using ::android::ConfigDescription; using ::android::StringPiece; +using android::idmap2::policy::kPolicyStringToFlag; + namespace aapt { constexpr const char* sXliffNamespaceUri = "urn:oasis:names:tc:xliff:document:1.2"; @@ -1063,7 +1067,7 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource bool error = false; std::string comment; - OverlayableItem::PolicyFlags current_policies = OverlayableItem::Policy::kNone; + PolicyFlags current_policies = PolicyFlags::NONE; const size_t start_depth = parser->depth(); while (xml::XmlPullParser::IsGoodEvent(parser->Next())) { xml::XmlPullParser::Event event = parser->event(); @@ -1073,7 +1077,7 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource } else if (event == xml::XmlPullParser::Event::kEndElement && parser->depth() == start_depth + 1) { // Clear the current policies when exiting the tags - current_policies = OverlayableItem::Policy::kNone; + current_policies = PolicyFlags::NONE; continue; } else if (event == xml::XmlPullParser::Event::kComment) { // Retrieve the comment of individual tags @@ -1088,7 +1092,7 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource const std::string& element_name = parser->element_name(); const std::string& element_namespace = parser->element_namespace(); if (element_namespace.empty() && element_name == "item") { - if (current_policies == OverlayableItem::Policy::kNone) { + if (current_policies == PolicyFlags::NONE) { diag_->Error(DiagMessage(element_source) << " within an must be inside a block"); error = true; @@ -1133,7 +1137,7 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource out_resource->child_resources.push_back(std::move(child_resource)); } else if (element_namespace.empty() && element_name == "policy") { - if (current_policies != OverlayableItem::Policy::kNone) { + if (current_policies != PolicyFlags::NONE) { // If the policy list is not empty, then we are currently inside a policy element diag_->Error(DiagMessage(element_source) << " blocks cannot be recursively nested"); error = true; @@ -1141,21 +1145,14 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource } else if (Maybe 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. - static const auto kPolicyMap = - ImmutableMap::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); - const auto policy = kPolicyMap.find(trimmed_part); - if (policy == kPolicyMap.end()) { + const auto policy = std::find_if(kPolicyStringToFlag.begin(), + kPolicyStringToFlag.end(), + [trimmed_part](const auto& it) { + return trimmed_part == it.first; + }); + if (policy == kPolicyStringToFlag.end()) { diag_->Error(DiagMessage(element_source) << " has unsupported type '" << trimmed_part << "'"); error = true; diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp index 24531bc164459..77e7fc55a2294 100644 --- a/tools/aapt2/ResourceParser_test.cpp +++ b/tools/aapt2/ResourceParser_test.cpp @@ -41,6 +41,8 @@ using ::testing::Pointee; using ::testing::SizeIs; using ::testing::StrEq; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + namespace aapt { constexpr const char* kXmlPreamble = "\n"; @@ -959,7 +961,7 @@ TEST_F(ResourceParserTest, ParseOverlayable) { OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme")); - EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::SIGNATURE)); search_result = table_.FindResource(test::ParseNameOrDie("drawable/bar")); ASSERT_TRUE(search_result); @@ -968,7 +970,7 @@ TEST_F(ResourceParserTest, ParseOverlayable) { result_overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme")); - EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::SIGNATURE)); } TEST_F(ResourceParserTest, ParseOverlayableRequiresName) { @@ -1014,7 +1016,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { ASSERT_TRUE(search_result.value().entry->overlayable_item); OverlayableItem 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::kProduct)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PRODUCT_PARTITION)); search_result = table_.FindResource(test::ParseNameOrDie("string/fiz")); ASSERT_TRUE(search_result); @@ -1022,7 +1024,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { 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::kSystem)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::SYSTEM_PARTITION)); search_result = table_.FindResource(test::ParseNameOrDie("string/fuz")); ASSERT_TRUE(search_result); @@ -1030,7 +1032,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { 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::kVendor)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::VENDOR_PARTITION)); search_result = table_.FindResource(test::ParseNameOrDie("string/faz")); ASSERT_TRUE(search_result); @@ -1038,7 +1040,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { 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::kPublic)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PUBLIC)); search_result = table_.FindResource(test::ParseNameOrDie("string/foz")); ASSERT_TRUE(search_result); @@ -1046,7 +1048,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { 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::kSignature)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::SIGNATURE)); search_result = table_.FindResource(test::ParseNameOrDie("string/biz")); ASSERT_TRUE(search_result); @@ -1054,7 +1056,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { 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)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::ODM_PARTITION)); search_result = table_.FindResource(test::ParseNameOrDie("string/buz")); ASSERT_TRUE(search_result); @@ -1062,7 +1064,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { 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)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::OEM_PARTITION)); } TEST_F(ResourceParserTest, ParseOverlayableNoPolicyError) { @@ -1125,8 +1127,8 @@ TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) { ASSERT_TRUE(search_result.value().entry->overlayable_item); OverlayableItem 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::kVendor - | OverlayableItem::Policy::kPublic)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::VENDOR_PARTITION + | PolicyFlags::PUBLIC)); search_result = table_.FindResource(test::ParseNameOrDie("string/bar")); ASSERT_TRUE(search_result); @@ -1134,8 +1136,8 @@ TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) { 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::kProduct - | OverlayableItem::Policy::kSystem)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PRODUCT_PARTITION + | PolicyFlags::SYSTEM_PARTITION)); } TEST_F(ResourceParserTest, DuplicateOverlayableIsError) { diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index 30ba1aed25f89..93a7a314d6bab 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -36,6 +36,8 @@ #include #include +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + namespace aapt { // The Public status of a resource. @@ -75,36 +77,8 @@ struct Overlayable { struct OverlayableItem { explicit OverlayableItem(const std::shared_ptr& overlayable) : overlayable(overlayable) {} - - // Represents the types overlays that are allowed to overlay the resource. - typedef uint32_t PolicyFlags; - enum Policy : uint32_t { - kNone = 0x00000000, - - // The resource can be overlaid by any overlay. - kPublic = 0x00000001, - - // The resource can be overlaid by any overlay on the system partition. - kSystem = 0x00000002, - - // The resource can be overlaid by any overlay on the vendor partition. - kVendor = 0x00000004, - - // The resource can be overlaid by any overlay on the product partition. - kProduct = 0x00000008, - - // The resource can be overlaid by any overlay signed with the same signature as its actor. - 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; - PolicyFlags policies = Policy::kNone; + PolicyFlags policies = PolicyFlags::NONE; std::string comment; Source source; }; diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp index b97dc6b205cab..9271a7e6bae15 100644 --- a/tools/aapt2/ResourceTable_test.cpp +++ b/tools/aapt2/ResourceTable_test.cpp @@ -30,6 +30,8 @@ using ::testing::Eq; using ::testing::NotNull; using ::testing::StrEq; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + namespace aapt { TEST(ResourceTableTest, FailToAddResourceWithBadName) { @@ -247,8 +249,8 @@ TEST(ResourceTableTest, SetOverlayable) { auto overlayable = std::make_shared("Name", "overlay://theme", Source("res/values/overlayable.xml", 40)); OverlayableItem overlayable_item(overlayable); - overlayable_item.policies |= OverlayableItem::Policy::kProduct; - overlayable_item.policies |= OverlayableItem::Policy::kVendor; + overlayable_item.policies |= PolicyFlags::PRODUCT_PARTITION; + overlayable_item.policies |= PolicyFlags::VENDOR_PARTITION; overlayable_item.comment = "comment"; overlayable_item.source = Source("res/values/overlayable.xml", 42); @@ -264,8 +266,8 @@ TEST(ResourceTableTest, SetOverlayable) { EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme")); EXPECT_THAT(result_overlayable_item.overlayable->source.path, Eq("res/values/overlayable.xml")); EXPECT_THAT(result_overlayable_item.overlayable->source.line, 40); - EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct - | OverlayableItem::Policy::kVendor)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PRODUCT_PARTITION + | PolicyFlags::VENDOR_PARTITION)); ASSERT_THAT(result_overlayable_item.comment, StrEq("comment")); EXPECT_THAT(result_overlayable_item.source.path, Eq("res/values/overlayable.xml")); EXPECT_THAT(result_overlayable_item.source.line, 42); @@ -277,17 +279,17 @@ TEST(ResourceTableTest, SetMultipleOverlayableResources) { const ResourceName foo = test::ParseNameOrDie("android:string/foo"); auto group = std::make_shared("Name", "overlay://theme"); OverlayableItem overlayable(group); - overlayable.policies = OverlayableItem::Policy::kProduct; + overlayable.policies = PolicyFlags::PRODUCT_PARTITION; ASSERT_TRUE(table.SetOverlayable(foo, overlayable, test::GetDiagnostics())); const ResourceName bar = test::ParseNameOrDie("android:string/bar"); OverlayableItem overlayable2(group); - overlayable2.policies = OverlayableItem::Policy::kProduct; + overlayable2.policies = PolicyFlags::PRODUCT_PARTITION; ASSERT_TRUE(table.SetOverlayable(bar, overlayable2, test::GetDiagnostics())); const ResourceName baz = test::ParseNameOrDie("android:string/baz"); OverlayableItem overlayable3(group); - overlayable3.policies = OverlayableItem::Policy::kVendor; + overlayable3.policies = PolicyFlags::VENDOR_PARTITION; ASSERT_TRUE(table.SetOverlayable(baz, overlayable3, test::GetDiagnostics())); } @@ -296,12 +298,12 @@ TEST(ResourceTableTest, SetOverlayableDifferentResourcesDifferentName) { const ResourceName foo = test::ParseNameOrDie("android:string/foo"); OverlayableItem overlayable_item(std::make_shared("Name", "overlay://theme")); - overlayable_item.policies = OverlayableItem::Policy::kProduct; + overlayable_item.policies = PolicyFlags::PRODUCT_PARTITION; ASSERT_TRUE(table.SetOverlayable(foo, overlayable_item, test::GetDiagnostics())); const ResourceName bar = test::ParseNameOrDie("android:string/bar"); OverlayableItem overlayable_item2(std::make_shared("Name2", "overlay://theme")); - overlayable_item2.policies = OverlayableItem::Policy::kProduct; + overlayable_item2.policies = PolicyFlags::PRODUCT_PARTITION; ASSERT_TRUE(table.SetOverlayable(bar, overlayable_item2, test::GetDiagnostics())); } diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp index fcd6aaafba7ab..f362744c09424 100644 --- a/tools/aapt2/format/binary/BinaryResourceParser.cpp +++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp @@ -455,35 +455,6 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) { const ResTable_overlayable_policy_header* policy_header = ConvertTo(parser.chunk()); - OverlayableItem::PolicyFlags policies = OverlayableItem::Policy::kNone; - if (policy_header->policy_flags & ResTable_overlayable_policy_header::POLICY_PUBLIC) { - policies |= OverlayableItem::Policy::kPublic; - } - if (policy_header->policy_flags - & ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION) { - policies |= OverlayableItem::Policy::kSystem; - } - if (policy_header->policy_flags - & ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION) { - policies |= OverlayableItem::Policy::kVendor; - } - if (policy_header->policy_flags - & ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION) { - policies |= OverlayableItem::Policy::kProduct; - } - if (policy_header->policy_flags - & 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( ((uint8_t *)policy_header) + util::DeviceToHost32(policy_header->header.headerSize)); const ResTable_ref* const ref_end = ref_begin @@ -501,7 +472,7 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) { } OverlayableItem overlayable_item(overlayable); - overlayable_item.policies = policies; + overlayable_item.policies = policy_header->policy_flags; if (!table_->SetOverlayable(iter->second, overlayable_item, diag_)) { return false; } diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp index cbce8a59bae39..4784ecf3d12c2 100644 --- a/tools/aapt2/format/binary/TableFlattener.cpp +++ b/tools/aapt2/format/binary/TableFlattener.cpp @@ -233,7 +233,7 @@ class MapFlattenVisitor : public ValueVisitor { struct OverlayableChunk { std::string actor; Source source; - std::map> policy_ids; + std::map> policy_ids; }; class PackageFlattener { @@ -493,35 +493,12 @@ class PackageFlattener { return false; } - uint32_t policy_flags = 0; - if (item.policies & OverlayableItem::Policy::kPublic) { - policy_flags |= ResTable_overlayable_policy_header::POLICY_PUBLIC; - } - if (item.policies & OverlayableItem::Policy::kSystem) { - policy_flags |= ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION; - } - if (item.policies & OverlayableItem::Policy::kVendor) { - policy_flags |= ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION; - } - if (item.policies & OverlayableItem::Policy::kProduct) { - policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION; - } - 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); + auto policy = overlayable_chunk->policy_ids.find(item.policies); if (policy != overlayable_chunk->policy_ids.end()) { policy->second.insert(id); } else { overlayable_chunk->policy_ids.insert( - std::make_pair(policy_flags, std::set{id})); + std::make_pair(item.policies, std::set{id})); } } } @@ -559,7 +536,8 @@ class PackageFlattener { ChunkWriter policy_writer(buffer); auto* policy_type = policy_writer.StartChunk( RES_TABLE_OVERLAYABLE_POLICY_TYPE); - policy_type->policy_flags = util::HostToDevice32(static_cast(policy_ids.first)); + policy_type->policy_flags = + static_cast(util::HostToDevice32(static_cast(policy_ids.first))); policy_type->entry_count = util::HostToDevice32(static_cast( policy_ids.second.size())); // Write the ids after the policy header diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp index af2293f0f82b5..e1e0f17c8dbba 100644 --- a/tools/aapt2/format/binary/TableFlattener_test.cpp +++ b/tools/aapt2/format/binary/TableFlattener_test.cpp @@ -32,6 +32,8 @@ using ::testing::Gt; using ::testing::IsNull; using ::testing::NotNull; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + namespace aapt { class TableFlattenerTest : public ::testing::Test { @@ -671,9 +673,9 @@ TEST_F(TableFlattenerTest, ObfuscatingResourceNamesWithNameCollapseExemptionsSuc TEST_F(TableFlattenerTest, FlattenOverlayable) { OverlayableItem overlayable_item(std::make_shared("TestName", "overlay://theme")); - overlayable_item.policies |= OverlayableItem::Policy::kProduct; - overlayable_item.policies |= OverlayableItem::Policy::kSystem; - overlayable_item.policies |= OverlayableItem::Policy::kVendor; + overlayable_item.policies |= PolicyFlags::PRODUCT_PARTITION; + overlayable_item.policies |= PolicyFlags::SYSTEM_PARTITION; + overlayable_item.policies |= PolicyFlags::VENDOR_PARTITION; std::string name = "com.app.test:integer/overlayable"; std::unique_ptr table = @@ -691,27 +693,27 @@ TEST_F(TableFlattenerTest, FlattenOverlayable) { ASSERT_THAT(search_result.value().entry, NotNull()); ASSERT_TRUE(search_result.value().entry->overlayable_item); OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); - EXPECT_EQ(result_overlayable_item.policies, OverlayableItem::Policy::kSystem - | OverlayableItem::Policy::kVendor - | OverlayableItem::Policy::kProduct); + EXPECT_EQ(result_overlayable_item.policies, PolicyFlags::SYSTEM_PARTITION + | PolicyFlags::VENDOR_PARTITION + | PolicyFlags::PRODUCT_PARTITION); } TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) { auto overlayable = std::make_shared("TestName", "overlay://theme"); std::string name_zero = "com.app.test:integer/overlayable_zero_item"; OverlayableItem overlayable_item_zero(overlayable); - overlayable_item_zero.policies |= OverlayableItem::Policy::kProduct; - overlayable_item_zero.policies |= OverlayableItem::Policy::kSystem; + overlayable_item_zero.policies |= PolicyFlags::PRODUCT_PARTITION; + overlayable_item_zero.policies |= PolicyFlags::SYSTEM_PARTITION; std::string name_one = "com.app.test:integer/overlayable_one_item"; OverlayableItem overlayable_item_one(overlayable); - overlayable_item_one.policies |= OverlayableItem::Policy::kPublic; + overlayable_item_one.policies |= PolicyFlags::PUBLIC; std::string name_two = "com.app.test:integer/overlayable_two_item"; OverlayableItem overlayable_item_two(overlayable); - overlayable_item_two.policies |= OverlayableItem::Policy::kProduct; - overlayable_item_two.policies |= OverlayableItem::Policy::kSystem; - overlayable_item_two.policies |= OverlayableItem::Policy::kVendor; + overlayable_item_two.policies |= PolicyFlags::PRODUCT_PARTITION; + overlayable_item_two.policies |= PolicyFlags::SYSTEM_PARTITION; + overlayable_item_two.policies |= PolicyFlags::VENDOR_PARTITION; std::unique_ptr table = test::ResourceTableBuilder() @@ -732,47 +734,47 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) { ASSERT_THAT(search_result.value().entry, NotNull()); ASSERT_TRUE(search_result.value().entry->overlayable_item); OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value(); - EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kSystem - | OverlayableItem::Policy::kProduct); + EXPECT_EQ(overlayable_item.policies, PolicyFlags::SYSTEM_PARTITION + | PolicyFlags::PRODUCT_PARTITION); search_result = output_table.FindResource(test::ParseNameOrDie(name_one)); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); ASSERT_TRUE(search_result.value().entry->overlayable_item); overlayable_item = search_result.value().entry->overlayable_item.value(); - EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic); + EXPECT_EQ(overlayable_item.policies, PolicyFlags::PUBLIC); search_result = output_table.FindResource(test::ParseNameOrDie(name_two)); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); ASSERT_TRUE(search_result.value().entry->overlayable_item); overlayable_item = search_result.value().entry->overlayable_item.value(); - EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kSystem - | OverlayableItem::Policy::kProduct - | OverlayableItem::Policy::kVendor); + EXPECT_EQ(overlayable_item.policies, PolicyFlags::SYSTEM_PARTITION + | PolicyFlags::PRODUCT_PARTITION + | PolicyFlags::VENDOR_PARTITION); } TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { auto group = std::make_shared("TestName", "overlay://theme"); std::string name_zero = "com.app.test:integer/overlayable_zero"; OverlayableItem overlayable_item_zero(group); - overlayable_item_zero.policies |= OverlayableItem::Policy::kProduct; - overlayable_item_zero.policies |= OverlayableItem::Policy::kSystem; + overlayable_item_zero.policies |= PolicyFlags::PRODUCT_PARTITION; + overlayable_item_zero.policies |= PolicyFlags::SYSTEM_PARTITION; auto group_one = std::make_shared("OtherName", "overlay://customization"); std::string name_one = "com.app.test:integer/overlayable_one"; OverlayableItem overlayable_item_one(group_one); - overlayable_item_one.policies |= OverlayableItem::Policy::kPublic; + overlayable_item_one.policies |= PolicyFlags::PUBLIC; std::string name_two = "com.app.test:integer/overlayable_two"; OverlayableItem overlayable_item_two(group); - overlayable_item_two.policies |= OverlayableItem::Policy::kOdm; - overlayable_item_two.policies |= OverlayableItem::Policy::kOem; - overlayable_item_two.policies |= OverlayableItem::Policy::kVendor; + overlayable_item_two.policies |= PolicyFlags::ODM_PARTITION; + overlayable_item_two.policies |= PolicyFlags::OEM_PARTITION; + overlayable_item_two.policies |= PolicyFlags::VENDOR_PARTITION; std::string name_three = "com.app.test:integer/overlayable_three"; OverlayableItem overlayable_item_three(group_one); - overlayable_item_three.policies |= OverlayableItem::Policy::kSignature; + overlayable_item_three.policies |= PolicyFlags::SIGNATURE; std::unique_ptr table = test::ResourceTableBuilder() @@ -796,8 +798,8 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { OverlayableItem& 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, PolicyFlags::SYSTEM_PARTITION + | PolicyFlags::PRODUCT_PARTITION); search_result = output_table.FindResource(test::ParseNameOrDie(name_one)); ASSERT_TRUE(search_result); @@ -806,7 +808,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { result_overlayable = search_result.value().entry->overlayable_item.value(); EXPECT_EQ(result_overlayable.overlayable->name, "OtherName"); EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization"); - EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic); + EXPECT_EQ(result_overlayable.policies, PolicyFlags::PUBLIC); search_result = output_table.FindResource(test::ParseNameOrDie(name_two)); ASSERT_TRUE(search_result); @@ -815,9 +817,9 @@ 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::kOdm - | OverlayableItem::Policy::kOem - | OverlayableItem::Policy::kVendor); + EXPECT_EQ(result_overlayable.policies, PolicyFlags::ODM_PARTITION + | PolicyFlags::OEM_PARTITION + | PolicyFlags::VENDOR_PARTITION); search_result = output_table.FindResource(test::ParseNameOrDie(name_three)); ASSERT_TRUE(search_result); @@ -826,7 +828,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { result_overlayable = search_result.value().entry->overlayable_item.value(); EXPECT_EQ(result_overlayable.overlayable->name, "OtherName"); EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization"); - EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSignature); + EXPECT_EQ(result_overlayable.policies, PolicyFlags::SIGNATURE); } TEST_F(TableFlattenerTest, FlattenOverlayableNoPolicyFails) { diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp index 4cd6e930915d8..db8e093594a0e 100644 --- a/tools/aapt2/format/proto/ProtoDeserialize.cpp +++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp @@ -30,6 +30,8 @@ using ::android::ConfigDescription; using ::android::LocaleValue; using ::android::ResStringPool; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + namespace aapt { namespace { @@ -379,25 +381,25 @@ bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable, for (const int policy : pb_overlayable.policy()) { switch (policy) { case pb::OverlayableItem::PUBLIC: - out_overlayable->policies |= OverlayableItem::Policy::kPublic; + out_overlayable->policies |= PolicyFlags::PUBLIC; break; case pb::OverlayableItem::SYSTEM: - out_overlayable->policies |= OverlayableItem::Policy::kSystem; + out_overlayable->policies |= PolicyFlags::SYSTEM_PARTITION; break; case pb::OverlayableItem::VENDOR: - out_overlayable->policies |= OverlayableItem::Policy::kVendor; + out_overlayable->policies |= PolicyFlags::VENDOR_PARTITION; break; case pb::OverlayableItem::PRODUCT: - out_overlayable->policies |= OverlayableItem::Policy::kProduct; + out_overlayable->policies |= PolicyFlags::PRODUCT_PARTITION; break; case pb::OverlayableItem::SIGNATURE: - out_overlayable->policies |= OverlayableItem::Policy::kSignature; + out_overlayable->policies |= PolicyFlags::SIGNATURE; break; case pb::OverlayableItem::ODM: - out_overlayable->policies |= OverlayableItem::Policy::kOdm; + out_overlayable->policies |= PolicyFlags::ODM_PARTITION; break; case pb::OverlayableItem::OEM: - out_overlayable->policies |= OverlayableItem::Policy::kOem; + out_overlayable->policies |= PolicyFlags::OEM_PARTITION; break; default: *out_error = "unknown overlayable policy"; diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp index d9f6c193fc2f5..6bc4524d3d5c3 100644 --- a/tools/aapt2/format/proto/ProtoSerialize.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize.cpp @@ -21,6 +21,8 @@ using android::ConfigDescription; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + namespace aapt { void SerializeStringPoolToPb(const StringPool& pool, pb::StringPool* out_pb_pool, IDiagnostics* diag) { @@ -299,25 +301,25 @@ static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item pb::OverlayableItem* pb_overlayable_item = pb_entry->mutable_overlayable_item(); pb_overlayable_item->set_overlayable_idx(i); - if (overlayable_item.policies & OverlayableItem::Policy::kPublic) { + if (overlayable_item.policies & PolicyFlags::PUBLIC) { pb_overlayable_item->add_policy(pb::OverlayableItem::PUBLIC); } - if (overlayable_item.policies & OverlayableItem::Policy::kProduct) { + if (overlayable_item.policies & PolicyFlags::PRODUCT_PARTITION) { pb_overlayable_item->add_policy(pb::OverlayableItem::PRODUCT); } - if (overlayable_item.policies & OverlayableItem::Policy::kSystem) { + if (overlayable_item.policies & PolicyFlags::SYSTEM_PARTITION) { pb_overlayable_item->add_policy(pb::OverlayableItem::SYSTEM); } - if (overlayable_item.policies & OverlayableItem::Policy::kVendor) { + if (overlayable_item.policies & PolicyFlags::VENDOR_PARTITION) { pb_overlayable_item->add_policy(pb::OverlayableItem::VENDOR); } - if (overlayable_item.policies & OverlayableItem::Policy::kSignature) { + if (overlayable_item.policies & PolicyFlags::SIGNATURE) { pb_overlayable_item->add_policy(pb::OverlayableItem::SIGNATURE); } - if (overlayable_item.policies & OverlayableItem::Policy::kOdm) { + if (overlayable_item.policies & PolicyFlags::ODM_PARTITION) { pb_overlayable_item->add_policy(pb::OverlayableItem::ODM); } - if (overlayable_item.policies & OverlayableItem::Policy::kOem) { + if (overlayable_item.policies & PolicyFlags::OEM_PARTITION) { pb_overlayable_item->add_policy(pb::OverlayableItem::OEM); } diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp index 61a8335e17a7f..cdc86597b2f3a 100644 --- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp @@ -28,6 +28,8 @@ using ::testing::NotNull; using ::testing::SizeIs; using ::testing::StrEq; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + namespace aapt { class MockFileCollection : public io::IFileCollection { @@ -171,7 +173,7 @@ TEST(ProtoSerializeTest, SerializeSinglePackage) { EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme")); EXPECT_THAT(result_overlayable_item.overlayable->source.path, Eq("res/values/overlayable.xml")); EXPECT_THAT(result_overlayable_item.overlayable->source.line, Eq(40)); - EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kNone)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::NONE)); EXPECT_THAT(result_overlayable_item.source.path, Eq("res/values/overlayable.xml")); EXPECT_THAT(result_overlayable_item.source.line, Eq(42)); } @@ -516,23 +518,23 @@ TEST(ProtoSerializeTest, SerializeDeserializeConfiguration) { TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { OverlayableItem overlayable_item_foo(std::make_shared( "CustomizableResources", "overlay://customization")); - overlayable_item_foo.policies |= OverlayableItem::Policy::kSystem; - overlayable_item_foo.policies |= OverlayableItem::Policy::kProduct; + overlayable_item_foo.policies |= PolicyFlags::SYSTEM_PARTITION; + overlayable_item_foo.policies |= PolicyFlags::PRODUCT_PARTITION; OverlayableItem overlayable_item_bar(std::make_shared( "TaskBar", "overlay://theme")); - overlayable_item_bar.policies |= OverlayableItem::Policy::kPublic; - overlayable_item_bar.policies |= OverlayableItem::Policy::kVendor; + overlayable_item_bar.policies |= PolicyFlags::PUBLIC; + overlayable_item_bar.policies |= PolicyFlags::VENDOR_PARTITION; OverlayableItem overlayable_item_baz(std::make_shared( "FontPack", "overlay://theme")); - overlayable_item_baz.policies |= OverlayableItem::Policy::kPublic; + overlayable_item_baz.policies |= PolicyFlags::PUBLIC; OverlayableItem overlayable_item_boz(std::make_shared( "IconPack", "overlay://theme")); - overlayable_item_boz.policies |= OverlayableItem::Policy::kSignature; - overlayable_item_boz.policies |= OverlayableItem::Policy::kOdm; - overlayable_item_boz.policies |= OverlayableItem::Policy::kOem; + overlayable_item_boz.policies |= PolicyFlags::SIGNATURE; + overlayable_item_boz.policies |= PolicyFlags::ODM_PARTITION; + overlayable_item_boz.policies |= PolicyFlags::OEM_PARTITION; OverlayableItem overlayable_item_biz(std::make_shared( "Other", "overlay://customization")); @@ -565,8 +567,8 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(overlayable_item.overlayable->name, Eq("CustomizableResources")); EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://customization")); - EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kSystem - | OverlayableItem::Policy::kProduct)); + EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::SYSTEM_PARTITION + | PolicyFlags::PRODUCT_PARTITION)); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/bar")); ASSERT_TRUE(search_result); @@ -574,8 +576,8 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(overlayable_item.overlayable->name, Eq("TaskBar")); EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme")); - EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic - | OverlayableItem::Policy::kVendor)); + EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::PUBLIC + | PolicyFlags::VENDOR_PARTITION)); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/baz")); ASSERT_TRUE(search_result); @@ -583,7 +585,7 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(overlayable_item.overlayable->name, Eq("FontPack")); EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme")); - EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic)); + EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::PUBLIC)); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/boz")); ASSERT_TRUE(search_result); @@ -591,16 +593,16 @@ 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 - | OverlayableItem::Policy::kOdm - | OverlayableItem::Policy::kOem)); + EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::SIGNATURE + | PolicyFlags::ODM_PARTITION + | PolicyFlags::OEM_PARTITION)); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/biz")); ASSERT_TRUE(search_result); ASSERT_TRUE(search_result.value().entry->overlayable_item); overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(overlayable_item.overlayable->name, Eq("Other")); - EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kNone)); + EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::NONE)); EXPECT_THAT(overlayable_item.comment, Eq("comment")); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/fiz")); diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp index 0be4ccf9ae859..69cf5ee7002b6 100644 --- a/tools/aapt2/link/TableMerger_test.cpp +++ b/tools/aapt2/link/TableMerger_test.cpp @@ -29,6 +29,8 @@ using ::testing::Pointee; using ::testing::StrEq; using ::testing::UnorderedElementsAreArray; +using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; + namespace aapt { struct TableMergerTest : public ::testing::Test { @@ -487,8 +489,8 @@ TEST_F(TableMergerTest, SetOverlayable) { auto overlayable = std::make_shared("CustomizableResources", "overlay://customization"); OverlayableItem overlayable_item(overlayable); - overlayable_item.policies |= OverlayableItem::Policy::kProduct; - overlayable_item.policies |= OverlayableItem::Policy::kVendor; + overlayable_item.policies |= PolicyFlags::PRODUCT_PARTITION; + overlayable_item.policies |= PolicyFlags::VENDOR_PARTITION; std::unique_ptr table_a = test::ResourceTableBuilder() @@ -516,8 +518,8 @@ TEST_F(TableMergerTest, SetOverlayable) { OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("CustomizableResources")); EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://customization")); - EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct - | OverlayableItem::Policy::kVendor)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PRODUCT_PARTITION + | PolicyFlags::VENDOR_PARTITION)); } TEST_F(TableMergerTest, SetOverlayableLater) { @@ -530,8 +532,8 @@ TEST_F(TableMergerTest, SetOverlayableLater) { .Build(); OverlayableItem overlayable_item(overlayable); - overlayable_item.policies |= OverlayableItem::Policy::kPublic; - overlayable_item.policies |= OverlayableItem::Policy::kSystem; + overlayable_item.policies |= PolicyFlags::PUBLIC; + overlayable_item.policies |= PolicyFlags::SYSTEM_PARTITION; std::unique_ptr table_b = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) @@ -552,15 +554,15 @@ TEST_F(TableMergerTest, SetOverlayableLater) { OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("CustomizableResources")); EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://customization")); - EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic - | OverlayableItem::Policy::kSystem)); + EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PUBLIC + | PolicyFlags::SYSTEM_PARTITION)); } TEST_F(TableMergerTest, SameResourceDifferentNameFail) { auto overlayable_first = std::make_shared("CustomizableResources", "overlay://customization"); OverlayableItem overlayable_item_first(overlayable_first); - overlayable_item_first.policies |= OverlayableItem::Policy::kProduct; + overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION; std::unique_ptr table_a = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) @@ -570,7 +572,7 @@ TEST_F(TableMergerTest, SameResourceDifferentNameFail) { auto overlayable_second = std::make_shared("ThemeResources", "overlay://customization"); OverlayableItem overlayable_item_second(overlayable_second); - overlayable_item_second.policies |= OverlayableItem::Policy::kProduct; + overlayable_item_second.policies |= PolicyFlags::PRODUCT_PARTITION; std::unique_ptr table_b = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) @@ -589,7 +591,7 @@ TEST_F(TableMergerTest, SameResourceDifferentActorFail) { auto overlayable_first = std::make_shared("CustomizableResources", "overlay://customization"); OverlayableItem overlayable_item_first(overlayable_first); - overlayable_item_first.policies |= OverlayableItem::Policy::kProduct; + overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION; std::unique_ptr table_a = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) @@ -599,7 +601,7 @@ TEST_F(TableMergerTest, SameResourceDifferentActorFail) { auto overlayable_second = std::make_shared("CustomizableResources", "overlay://theme"); OverlayableItem overlayable_item_second(overlayable_second); - overlayable_item_second.policies |= OverlayableItem::Policy::kProduct; + overlayable_item_second.policies |= PolicyFlags::PRODUCT_PARTITION; std::unique_ptr table_b = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) @@ -618,7 +620,7 @@ TEST_F(TableMergerTest, SameResourceDifferentPoliciesFail) { auto overlayable_first = std::make_shared("CustomizableResources", "overlay://customization"); OverlayableItem overlayable_item_first(overlayable_first); - overlayable_item_first.policies |= OverlayableItem::Policy::kProduct; + overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION; std::unique_ptr table_a = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) @@ -628,7 +630,7 @@ TEST_F(TableMergerTest, SameResourceDifferentPoliciesFail) { auto overlayable_second = std::make_shared("CustomizableResources", "overlay://customization"); OverlayableItem overlayable_item_second(overlayable_second); - overlayable_item_second.policies |= OverlayableItem::Policy::kSignature; + overlayable_item_second.policies |= PolicyFlags::SIGNATURE; std::unique_ptr table_b = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) @@ -648,7 +650,7 @@ TEST_F(TableMergerTest, SameResourceSameOverlayable) { "overlay://customization"); OverlayableItem overlayable_item_first(overlayable); - overlayable_item_first.policies |= OverlayableItem::Policy::kProduct; + overlayable_item_first.policies |= PolicyFlags::PRODUCT_PARTITION; std::unique_ptr table_a = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) @@ -656,7 +658,7 @@ TEST_F(TableMergerTest, SameResourceSameOverlayable) { .Build(); OverlayableItem overlayable_item_second(overlayable); - overlayable_item_second.policies |= OverlayableItem::Policy::kProduct; + overlayable_item_second.policies |= PolicyFlags::PRODUCT_PARTITION; std::unique_ptr table_b = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) From f56ade365aa22e55655f0149cf47181cb3da6e8d Mon Sep 17 00:00:00 2001 From: Winson Date: Wed, 4 Dec 2019 11:32:41 -0800 Subject: [PATCH 2/2] Actor signature overlayable policy There are cases where an app can ship overlays for itself, but the "signature" policy as described would open up a vulnerability by allowing the system actor to create and sign any arbitrary overlay that will apply to the target. To prevent this, redefine "signature" as target package only, and introduce "actor" for checking against the actor signature. Any app that wishes to use both can include both policies. Bug: 130563563 Test: m aapt2_tests idmapt2_tests and run from host test output Test: atest libandroidfw_tests Change-Id: I1c583a5b37f4abbeb18fc6a35c502377d8977a41 --- .../aidl/android/os/OverlayablePolicy.aidl | 1 + .../include/idmap2/Policies.h | 6 +- cmds/idmap2/tests/IdmapTests.cpp | 24 +++-- cmds/idmap2/tests/PoliciesTests.cpp | 16 ++++ cmds/idmap2/tests/R.h | 47 ++++++---- cmds/idmap2/tests/ResourceMappingTests.cpp | 10 ++- cmds/idmap2/tests/TestConstants.h | 4 +- .../res/values/values.xml | 1 + .../system-overlay-invalid.apk | Bin 1779 -> 1827 bytes .../data/target/res/values/overlayable.xml | 6 +- .../tests/data/target/res/values/values.xml | 1 + .../data/target/target-no-overlayable.apk | Bin 2749 -> 2311 bytes cmds/idmap2/tests/data/target/target.apk | Bin 5017 -> 5097 bytes core/java/android/content/om/OverlayInfo.java | 4 + .../include/androidfw/ResourceTypes.h | 9 +- .../com/android/server/om/IdmapManager.java | 39 ++++++-- .../server/om/OverlayActorEnforcer.java | 72 +++------------ .../server/om/OverlayManagerService.java | 18 ++-- .../server/om/OverlayManagerServiceImpl.java | 8 -- .../server/om/OverlayableInfoCallback.java | 85 ++++++++++++++++++ .../server/om/PackageManagerHelper.java | 36 ++++++++ .../server/om/OverlayActorEnforcerTests.kt | 9 +- .../om/OverlayManagerServiceImplTests.java | 14 --- .../OverlayManagerServiceImplTestsBase.java | 37 +++++++- tools/aapt2/ResourceParser_test.cpp | 11 +++ 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 + .../format/proto/ProtoSerialize_test.cpp | 15 ++++ 30 files changed, 343 insertions(+), 141 deletions(-) create mode 100644 services/core/java/com/android/server/om/OverlayableInfoCallback.java create mode 100644 services/core/java/com/android/server/om/PackageManagerHelper.java diff --git a/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl b/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl index 85b5eff46efa5..02b27a8800b61 100644 --- a/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl +++ b/cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl @@ -28,4 +28,5 @@ interface OverlayablePolicy { const int SIGNATURE = 0x00000010; const int ODM_PARTITION = 0x00000020; const int OEM_PARTITION = 0x00000040; + const int ACTOR_SIGNATURE = 0x00000080; } diff --git a/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h b/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h index 9f9b836e31d54..4973b7638d10b 100644 --- a/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h +++ b/cmds/idmap2/libidmap2_policies/include/idmap2/Policies.h @@ -29,6 +29,7 @@ using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags; namespace android::idmap2::policy { +constexpr const char* kPolicyActor = "actor"; constexpr const char* kPolicyOdm = "odm"; constexpr const char* kPolicyOem = "oem"; constexpr const char* kPolicyProduct = "product"; @@ -37,8 +38,9 @@ constexpr const char* kPolicySignature = "signature"; constexpr const char* kPolicySystem = "system"; constexpr const char* kPolicyVendor = "vendor"; -inline static const std::array, 7> kPolicyStringToFlag = { - std::pair{kPolicyOdm, PolicyFlags::ODM_PARTITION}, +inline static const std::array, 8> kPolicyStringToFlag = { + std::pair{kPolicyActor, PolicyFlags::ACTOR_SIGNATURE}, + {kPolicyOdm, PolicyFlags::ODM_PARTITION}, {kPolicyOem, PolicyFlags::OEM_PARTITION}, {kPolicyProduct, PolicyFlags::PRODUCT_PARTITION}, {kPolicyPublic, PolicyFlags::PUBLIC}, diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index 76c6eaf75adc2..87da36c01192a 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -279,17 +279,25 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssetsSharedLibOverlay) { const auto& target_entries = data->GetTargetEntries(); ASSERT_EQ(target_entries.size(), 4U); - ASSERT_TARGET_ENTRY(target_entries[0], 0x7f010000, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00010000); - ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020000); - ASSERT_TARGET_ENTRY(target_entries[2], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020001); - ASSERT_TARGET_ENTRY(target_entries[3], 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020002); + 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); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(target_entries.size(), 4U); - ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x00010000, 0x7f010000); - ASSERT_OVERLAY_ENTRY(overlay_entries[1], 0x00020000, 0x7f02000c); - ASSERT_OVERLAY_ENTRY(overlay_entries[2], 0x00020001, 0x7f02000e); - ASSERT_OVERLAY_ENTRY(overlay_entries[3], 0x00020002, 0x7f02000f); + ASSERT_OVERLAY_ENTRY(overlay_entries[0], R::overlay_shared::integer::int1, + R::target::integer::int1); + ASSERT_OVERLAY_ENTRY(overlay_entries[1], R::overlay_shared::string::str1, + R::target::string::str1); + ASSERT_OVERLAY_ENTRY(overlay_entries[2], R::overlay_shared::string::str3, + R::target::string::str3); + ASSERT_OVERLAY_ENTRY(overlay_entries[3], R::overlay_shared::string::str4, + R::target::string::str4); } TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) { diff --git a/cmds/idmap2/tests/PoliciesTests.cpp b/cmds/idmap2/tests/PoliciesTests.cpp index 4b395c7912d12..1b2775939886a 100644 --- a/cmds/idmap2/tests/PoliciesTests.cpp +++ b/cmds/idmap2/tests/PoliciesTests.cpp @@ -67,6 +67,14 @@ TEST(PoliciesTests, PoliciesToBitmaskResults) { const auto bitmask10 = PoliciesToBitmaskResult({"system "}); ASSERT_FALSE(bitmask10); + + const auto bitmask11 = PoliciesToBitmaskResult({"signature"}); + ASSERT_TRUE(bitmask11); + ASSERT_EQ(*bitmask11, PolicyFlags::SIGNATURE); + + const auto bitmask12 = PoliciesToBitmaskResult({"actor"}); + ASSERT_TRUE(bitmask12); + ASSERT_EQ(*bitmask12, PolicyFlags::ACTOR_SIGNATURE); } TEST(PoliciesTests, BitmaskToPolicies) { @@ -91,6 +99,14 @@ TEST(PoliciesTests, BitmaskToPolicies) { ASSERT_EQ(policies3[3], "public"); ASSERT_EQ(policies3[4], "system"); ASSERT_EQ(policies3[5], "vendor"); + + const auto policies4 = BitmaskToPolicies(PolicyFlags::SIGNATURE); + ASSERT_EQ(1, policies4.size()); + ASSERT_EQ(policies4[0], "signature"); + + const auto policies5 = BitmaskToPolicies(PolicyFlags::ACTOR_SIGNATURE); + ASSERT_EQ(1, policies5.size()); + ASSERT_EQ(policies5[0], "actor"); } } // namespace android::idmap2 diff --git a/cmds/idmap2/tests/R.h b/cmds/idmap2/tests/R.h index b2a589144c773..aed263a49aa3d 100644 --- a/cmds/idmap2/tests/R.h +++ b/cmds/idmap2/tests/R.h @@ -40,16 +40,17 @@ namespace R::target { namespace string { constexpr ResourceId not_overlayable = 0x7f020003; constexpr ResourceId other = 0x7f020004; - constexpr ResourceId policy_odm = 0x7f020005; - constexpr ResourceId policy_oem = 0x7f020006; - constexpr ResourceId policy_product = 0x7f020007; - constexpr ResourceId policy_public = 0x7f020008; - constexpr ResourceId policy_signature = 0x7f020009; - constexpr ResourceId policy_system = 0x7f02000a; - constexpr ResourceId policy_system_vendor = 0x7f02000b; - constexpr ResourceId str1 = 0x7f02000c; - constexpr ResourceId str3 = 0x7f02000e; - constexpr ResourceId str4 = 0x7f02000f; + 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; namespace literal { inline const std::string str1 = hexify(R::target::string::str1); @@ -70,6 +71,17 @@ namespace R::overlay { } } +namespace R::overlay_shared { + namespace integer { + constexpr ResourceId int1 = 0x00010000; + } + namespace string { + constexpr ResourceId str1 = 0x00020000; + constexpr ResourceId str3 = 0x00020001; + constexpr ResourceId str4 = 0x00020002; + } +} + namespace R::system_overlay::string { constexpr ResourceId policy_public = 0x7f010000; constexpr ResourceId policy_system = 0x7f010001; @@ -79,13 +91,14 @@ namespace R::system_overlay::string { namespace R::system_overlay_invalid::string { constexpr ResourceId not_overlayable = 0x7f010000; constexpr ResourceId other = 0x7f010001; - constexpr ResourceId policy_odm = 0x7f010002; - constexpr ResourceId policy_oem = 0x7f010003; - constexpr ResourceId policy_product = 0x7f010004; - constexpr ResourceId policy_public = 0x7f010005; - constexpr ResourceId policy_signature = 0x7f010006; - constexpr ResourceId policy_system = 0x7f010007; - constexpr ResourceId policy_system_vendor = 0x7f010008; + 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; }; // clang-format on diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp index 8d0e6609ac409..de039f440e33f 100644 --- a/cmds/idmap2/tests/ResourceMappingTests.cpp +++ b/cmds/idmap2/tests/ResourceMappingTests.cpp @@ -237,12 +237,15 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnore ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; - ASSERT_EQ(res.GetTargetToOverlayMap().size(), 9U); + ASSERT_EQ(res.GetTargetToOverlayMap().size(), 10U); ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::not_overlayable, false /* rewrite */)); ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::other, false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::policy_actor, + false /* rewrite */)); ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::policy_odm, false /* rewrite */)); ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE, @@ -306,12 +309,15 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) { ASSERT_TRUE(resources) << resources.GetErrorMessage(); auto& res = *resources; - ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 9U); + ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 10U); ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::not_overlayable, false /* rewrite */)); ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::other, false /* rewrite */)); + ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE, + R::system_overlay_invalid::string::policy_actor, + false /* rewrite */)); ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE, R::system_overlay_invalid::string::policy_odm, false /* rewrite */)); diff --git a/cmds/idmap2/tests/TestConstants.h b/cmds/idmap2/tests/TestConstants.h index c874dc93ce792..6bc924e5ac3cd 100644 --- a/cmds/idmap2/tests/TestConstants.h +++ b/cmds/idmap2/tests/TestConstants.h @@ -19,8 +19,8 @@ namespace android::idmap2::TestConstants { -constexpr const auto TARGET_CRC = 0x76a20829; -constexpr const auto TARGET_CRC_STRING = "76a20829"; +constexpr const auto TARGET_CRC = 0x41c60c8c; +constexpr const auto TARGET_CRC_STRING = "41c60c8c"; constexpr const auto OVERLAY_CRC = 0xc054fb26; constexpr const auto OVERLAY_CRC_STRING = "c054fb26"; 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 9ebfae41e4c53..7119d82830615 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 @@ -25,6 +25,7 @@ policy_signature policy_odm policy_oem + policy_actor 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 1456e749e796460ab3c0be174f99779d26de548d..bd990983693c96f3c9998032c34f0a55dc1525ee 100644 GIT binary patch delta 872 zcmey&yO^&&z?+$c0SGu47#ij?zWnn!co!oBg9lJd7%1wPmr|6Unc|z6mzkDYT%uQz zn=^ItZX*^)iB|vj5yw&^r#Cn$2y&#gdU+^0Xim9tZC&)+)NN_gwPrdzFl15ke;{bn zoGx(c=dQ1_4824zmu~xSSO0&x|9@j?jVsq0QnoCp|J`J=@{8rUBf$xxIgMr&4E+xz z_cWMq$X&t6xr5dJfvC=6>m|jZSFbKhx>|bZ-J~jm&T|o8x46dyH{Um&F8g!ZUDZ6x zx=FEyh3?{6hh!F9yC4|Y^o!N2Jv-M{>9#ou!KeeSyAYQ5#}c3WOk4K)?NT^+J= z#o;3_t|Yo8TJ_Ycy_PC`fBGm_`8z|asPNW{s`Y(-r%RPiX}aDkKKjyhhH!b>)8m~B zgEKZ;ef3+rJ|g^Goo~_gzL!s`tX{`NwJ(3;7jW}I-Ztm2@l~Ja&-x;JcJuGc;Zur5 z56128dF$koI=klT*LRzzXQqDp>us*~gnR0-lrus%Bn{Lwr7p7?rPkMYrG7YPe8h%_ z>qEKZJv-$i#yyMvuY0@iz;owqdR2YaBLyW-K?h zb9#R`rAFiGrh0SMe{nypR&Rg%D!A^-Yf+=BWB2d=()eD@#Aa(g!%}&@=##2j@8|wp zdR-nC+rX#=#`fU_Pcq+E0HYd&`4|`(ic*X7ON)|Ii}ezVijx_b72hSKcg-6jj!Ti5@4_Z+79vo*W^HEZBa(15C$0_7c2r4tpQ>Opp5h6 z4Xg@`6DFT!ovZ@P3k;k<45XPsbbvP_6OaM|L@t?J!e%QC3_zstgD8QJuP2{jQ)HXK H2I2t#x@av3 delta 844 zcmZ3?_nEgoz?+$cfq?@E85-s@G9UqAAlor7r6@l$#Wyi8GcC2aM6V(@XX<2Izrzk9 zE$PWj&+Hkw1WZgsMEFz}wX`WI{B!Z0@?m+4MG=#bEGz5r1q&Xr$TS)kuz6MeD7%@E z+`l^eVG`$2ztB%k`{3>F)NedHBOH+KX0-p^u4%|?rp!B=JVg&^}zC68@H%7C>PT=3`)FC`v8PFD*(=E!ImcDo$o#V&DNw zfszR$gABt3Ak7KZ3l?B-fU$wJ5D-fNu{sc&0I@3&hXQd15LW;(KYw0+Nqqj~#Vo>; zCo+|@Fexy`Z02S5XS5{S)X6hhWPxUt@iH+9fb9gilXG$)v$`lFQwReGkP8-py1)S_ w<2?BctHR_DtP?~6ycwB*67ZY=3Z= + + + + @@ -63,4 +67,4 @@ - \ No newline at end of file + diff --git a/cmds/idmap2/tests/data/target/res/values/values.xml b/cmds/idmap2/tests/data/target/res/values/values.xml index a892c98f0fbbe..5230e25e626be 100644 --- a/cmds/idmap2/tests/data/target/res/values/values.xml +++ b/cmds/idmap2/tests/data/target/res/values/values.xml @@ -36,6 +36,7 @@ policy_signature policy_system policy_system_vendor + policy_actor other diff --git a/cmds/idmap2/tests/data/target/target-no-overlayable.apk b/cmds/idmap2/tests/data/target/target-no-overlayable.apk index 2eb7c477c3b42d707b37cd1ccfc8cd1ca9022dca..58504a74a83a0a4229a2d7b89da8624ff646a87d 100644 GIT binary patch delta 534 zcmZY6F-SsD6b9gP-&J4AQ`2m!A)np zjEe}LnUC8RvNrHFtMuyLuX~+SyY6*P0p07Ig1Xl^b?9E_6wKY}IagGsEm6^&p{5_k5^L$o4;$)U!m&W9kyMh# z&5XLcyq-;0Ujsk_3m`|e7_G`Gvq@<)T5a*@*cdJfd=F0tk^o!dCkFCwY}A`rruEQh%%&{SyJeI#~+(_AL^WVen&sxw@ithA3iH9 z#~w{CeXKiKq)Hjw5Y=7l@Ojl{-22%e;Sl?rTPc``H7{PjQ}>oMkONr4MZ?ITPfQ67iiNVzjL_#5nW|TYB80|&!5d&gFTu3u=1L;SG zktfI$;zwoyNH)KP)bRE&xqNlkiHg-Q)4i3fj8WO>VS)wDM4wwppvL~?hoK)sdbrIp z4ywQmCXDHxbn=Q*Z%@J~6VV}Mh!Z)7bRgG}n@AtxM(!gc$S6tW6Y!QTBA%x+K_Y`( zk|HdyNI1E`=7utCA&lcC0~yS=6RD`4w2QpeQjBoSu#*Ah1O=H83mOxDZoiSve?BX-if*MQ>C_FT|0QpaKak)9oR|CvH8A-hbvEmk2hCy83_Q pX&L&uKlaaNWY*E*kV5+&q8N*_bf1J*d(vnWz;^S&yhM@|PK=?aX1xlI_fC$*S#4qPX`>`MYxp`liLMmr~xIKx#@ddNVuT KAB+vJQT+nVYFdZ@ delta 461 zcmYk(y-UMD7zXh7u1VUHR%)UWsA8c)>EIVy1VIQWD2S*~(7~mYf?A0KZt5T} z4&qV-2N$UnQ5O*v2T^oX2ZwI{5u#5+l_vbid+&3(eB4+3AYS zO+C)f@=lXcaarB>xk5~GpNw#?ZYReuX9|{J1vX$Cj^G3;Z~@nF3lH$f1$_`J7C2!H zNIYQCD5_-ysLA3p-&}`~DSE|=dmVJk;2@dc9se}H`JY6Hj{_OD)tah*Xn@EUtnR6p zCT^T6+1YC-bXGgz3G!rflt=ONQdsHQyHNc5(j)94vo gG;8XAXE> namedActors = mVerifyCallback.getNamedActors(); + Map> namedActors = mOverlayableCallback.getNamedActors(); Pair actorUriPair = getPackageNameForActor(actor, namedActors); ActorState actorUriState = actorUriPair.second; if (actorUriState != ActorState.ALLOWED) { @@ -185,7 +184,7 @@ public class OverlayActorEnforcer { } String packageName = actorUriPair.first; - PackageInfo packageInfo = mVerifyCallback.getPackageInfo(packageName, userId); + PackageInfo packageInfo = mOverlayableCallback.getPackageInfo(packageName, userId); if (packageInfo == null) { return ActorState.MISSING_APP_INFO; } @@ -211,7 +210,7 @@ public class OverlayActorEnforcer { * For easier logging/debugging, a set of all possible failure/success states when running * enforcement. */ - enum ActorState { + public enum ActorState { ALLOWED, INVALID_ACTOR, MISSING_NAMESPACE, @@ -228,53 +227,4 @@ public class OverlayActorEnforcer { UNABLE_TO_GET_TARGET, MISSING_LEGACY_PERMISSION } - - /** - * Delegate to the system for querying information about packages. - */ - public interface VerifyCallback { - - /** - * 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, - @Nullable String targetOverlayableName, int userId) - throws IOException; - - /** - * @see android.content.pm.PackageManager#getPackagesForUid(int) - */ - @Nullable - String[] getPackagesForUid(int uid); - - /** - * @param userId user to filter package visibility by - * @see android.content.pm.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 RemoteException, IOException; - - /** - * @throws SecurityException containing message if the caller doesn't have the given - * permission - */ - void enforcePermission(String permission, String message) throws SecurityException; - } } diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index f22128533ac25..c81f7cd4a8b48 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -226,7 +226,7 @@ public final class OverlayManagerService extends SystemService { private final AtomicFile mSettingsFile; - private final PackageManagerHelper mPackageManager; + private final PackageManagerHelperImpl mPackageManager; private final UserManagerService mUserManager; @@ -244,7 +244,7 @@ public final class OverlayManagerService extends SystemService { traceBegin(TRACE_TAG_RRO, "OMS#OverlayManagerService"); mSettingsFile = new AtomicFile( new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays"); - mPackageManager = new PackageManagerHelper(context); + mPackageManager = new PackageManagerHelperImpl(context); mUserManager = UserManagerService.getInstance(); IdmapManager im = new IdmapManager(mPackageManager); mSettings = new OverlayManagerSettings(); @@ -1053,14 +1053,8 @@ public final class OverlayManagerService extends SystemService { } } - /** - * Delegate for {@link android.content.pm.PackageManager} and {@link PackageManagerInternal} - * functionality, separated for easy testing. - * - * @hide - */ - public static final class PackageManagerHelper implements - OverlayManagerServiceImpl.PackageManagerHelper, OverlayActorEnforcer.VerifyCallback { + private static final class PackageManagerHelperImpl implements PackageManagerHelper, + OverlayableInfoCallback { private final Context mContext; private final IPackageManager mPackageManager; @@ -1073,7 +1067,7 @@ public final class OverlayManagerService extends SystemService { // behind until all pending intents have been processed. private final SparseArray> mCache = new SparseArray<>(); - PackageManagerHelper(Context context) { + PackageManagerHelperImpl(Context context) { mContext = context; mPackageManager = getPackageManager(); mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); @@ -1132,7 +1126,7 @@ public final class OverlayManagerService extends SystemService { @Nullable @Override public OverlayableInfo getOverlayableForTarget(@NonNull String packageName, - @Nullable String targetOverlayableName, int userId) + @NonNull String targetOverlayableName, int userId) throws IOException { PackageInfo packageInfo = getPackageInfo(packageName, userId); if (packageInfo == null) { diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index 2493057e01212..5734271ecb83a 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -18,7 +18,6 @@ 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_ENABLED_IMMUTABLE; import static android.content.om.OverlayInfo.STATE_MISSING_TARGET; import static android.content.om.OverlayInfo.STATE_NO_IDMAP; import static android.content.om.OverlayInfo.STATE_OVERLAY_IS_BEING_REPLACED; @@ -806,11 +805,4 @@ final class OverlayManagerServiceImpl { **/ void onOverlaysChanged(@NonNull String targetPackage, int userId); } - - interface PackageManagerHelper { - PackageInfo getPackageInfo(@NonNull String packageName, int userId); - boolean signaturesMatching(@NonNull String packageName1, @NonNull String packageName2, - int userId); - List getOverlayPackages(int userId); - } } diff --git a/services/core/java/com/android/server/om/OverlayableInfoCallback.java b/services/core/java/com/android/server/om/OverlayableInfoCallback.java new file mode 100644 index 0000000000000..6b818849c2579 --- /dev/null +++ b/services/core/java/com/android/server/om/OverlayableInfoCallback.java @@ -0,0 +1,85 @@ +/* + * 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 android.os.RemoteException; + +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 RemoteException, 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 new file mode 100644 index 0000000000000..ec9c5e64e390f --- /dev/null +++ b/services/core/java/com/android/server/om/PackageManagerHelper.java @@ -0,0 +1,36 @@ +/* + * 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.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManagerInternal; + +import java.util.List; + +/** + * Delegate for {@link PackageManager} and {@link PackageManagerInternal} functionality, + * separated for easy testing. + * + * @hide + */ +interface PackageManagerHelper { + PackageInfo getPackageInfo(@NonNull String packageName, int userId); + boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId); + List getOverlayPackages(int userId); +} 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 233e16c297a30..e08eea298aaf7 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt +++ b/services/tests/servicestests/src/com/android/server/om/OverlayActorEnforcerTests.kt @@ -24,6 +24,7 @@ import android.os.Process import org.junit.Rule import org.junit.Test import org.junit.rules.ExpectedException +import java.lang.UnsupportedOperationException class OverlayActorEnforcerTests { companion object { @@ -159,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") - ) : OverlayActorEnforcer.VerifyCallback { + ) : OverlayableInfoCallback { override fun getNamedActors() = if (isActor) { mapOf(NAMESPACE to mapOf(ACTOR_NAME to ACTOR_PKG_NAME)) @@ -169,7 +170,7 @@ class OverlayActorEnforcerTests { override fun getOverlayableForTarget( packageName: String, - targetOverlayableName: String?, + targetOverlayableName: String, userId: Int ) = overlayableInfo @@ -193,5 +194,9 @@ class OverlayActorEnforcerTests { throw SecurityException() } } + + override fun signaturesMatching(pkgName1: String, pkgName2: String, userId: Int): Boolean { + throw UnsupportedOperationException() + } } } 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 a428a97e51cdc..cd73432357507 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java @@ -24,30 +24,16 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import android.annotation.NonNull; import android.content.om.OverlayInfo; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.util.ArraySet; import androidx.test.runner.AndroidJUnit4; -import com.android.internal.content.om.OverlayConfig; - -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; import java.util.List; import java.util.Map; -import java.util.Set; @RunWith(AndroidJUnit4.class) public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase { 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 a753aac39c489..820e61cb0a08c 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java @@ -23,10 +23,13 @@ import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.content.om.OverlayInfo; import android.content.om.OverlayInfo.State; +import android.content.om.OverlayableInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.util.ArraySet; +import androidx.annotation.Nullable; + import com.android.internal.content.om.OverlayConfig; import org.junit.Before; @@ -35,6 +38,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.stream.Collectors; @@ -281,8 +285,8 @@ class OverlayManagerServiceImplTestsBase { } } - static final class DummyPackageManagerHelper implements - OverlayManagerServiceImpl.PackageManagerHelper { + static final class DummyPackageManagerHelper implements PackageManagerHelper, + OverlayableInfoCallback { private final DummyDeviceState mState; private DummyPackageManagerHelper(DummyDeviceState state) { @@ -320,6 +324,35 @@ class OverlayManagerServiceImplTestsBase { .map(p -> getPackageInfo(p.packageName, p.userId)) .collect(Collectors.toList()); } + + @Nullable + @Override + public OverlayableInfo getOverlayableForTarget(@NonNull String packageName, + @NonNull String targetOverlayableName, int userId) { + throw new UnsupportedOperationException(); + } + + @Nullable + @Override + public String[] getPackagesForUid(int uid) { + throw new UnsupportedOperationException(); + } + + @NonNull + @Override + public Map> getNamedActors() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean doesTargetDefineOverlayable(String targetPackageName, int userId) { + throw new UnsupportedOperationException(); + } + + @Override + public void enforcePermission(String permission, String message) throws SecurityException { + throw new UnsupportedOperationException(); + } } static class DummyIdmapManager extends IdmapManager { diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp index 77e7fc55a2294..9b70079a98c97 100644 --- a/tools/aapt2/ResourceParser_test.cpp +++ b/tools/aapt2/ResourceParser_test.cpp @@ -1007,6 +1007,9 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { + + + )"; ASSERT_TRUE(TestParse(input)); @@ -1065,6 +1068,14 @@ 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(PolicyFlags::OEM_PARTITION)); + + search_result = table_.FindResource(test::ParseNameOrDie("string/actor")); + 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(PolicyFlags::ACTOR_SIGNATURE)); } TEST_F(ResourceParserTest, ParseOverlayableNoPolicyError) { diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto index 8a2f5afa72559..ab9ce66b0ae3a 100644 --- a/tools/aapt2/Resources.proto +++ b/tools/aapt2/Resources.proto @@ -167,6 +167,7 @@ message OverlayableItem { SIGNATURE = 5; ODM = 6; OEM = 7; + ACTOR = 8; } // 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 e1e0f17c8dbba..59627ce579afe 100644 --- a/tools/aapt2/format/binary/TableFlattener_test.cpp +++ b/tools/aapt2/format/binary/TableFlattener_test.cpp @@ -775,6 +775,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { std::string name_three = "com.app.test:integer/overlayable_three"; OverlayableItem overlayable_item_three(group_one); overlayable_item_three.policies |= PolicyFlags::SIGNATURE; + overlayable_item_three.policies |= PolicyFlags::ACTOR_SIGNATURE; std::unique_ptr table = test::ResourceTableBuilder() @@ -828,7 +829,8 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { result_overlayable = search_result.value().entry->overlayable_item.value(); EXPECT_EQ(result_overlayable.overlayable->name, "OtherName"); EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization"); - EXPECT_EQ(result_overlayable.policies, PolicyFlags::SIGNATURE); + EXPECT_EQ(result_overlayable.policies, PolicyFlags::SIGNATURE + | PolicyFlags::ACTOR_SIGNATURE); } TEST_F(TableFlattenerTest, FlattenOverlayableNoPolicyFails) { diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp index db8e093594a0e..2fd01d7f3dee4 100644 --- a/tools/aapt2/format/proto/ProtoDeserialize.cpp +++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp @@ -401,6 +401,9 @@ bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable, case pb::OverlayableItem::OEM: out_overlayable->policies |= PolicyFlags::OEM_PARTITION; break; + case pb::OverlayableItem::ACTOR: + out_overlayable->policies |= PolicyFlags::ACTOR_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 6bc4524d3d5c3..ba6df22af9d3a 100644 --- a/tools/aapt2/format/proto/ProtoSerialize.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize.cpp @@ -322,6 +322,9 @@ static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item if (overlayable_item.policies & PolicyFlags::OEM_PARTITION) { pb_overlayable_item->add_policy(pb::OverlayableItem::OEM); } + if (overlayable_item.policies & PolicyFlags::ACTOR_SIGNATURE) { + pb_overlayable_item->add_policy(pb::OverlayableItem::ACTOR); + } if (source_pool != nullptr) { SerializeSourceToPb(overlayable_item.source, source_pool, diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp index cdc86597b2f3a..1a7de6dc1c483 100644 --- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp @@ -536,6 +536,11 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { overlayable_item_boz.policies |= PolicyFlags::ODM_PARTITION; overlayable_item_boz.policies |= PolicyFlags::OEM_PARTITION; + OverlayableItem overlayable_item_actor_config(std::make_shared( + "ActorConfig", "overlay://theme")); + overlayable_item_actor_config.policies |= PolicyFlags::SIGNATURE; + overlayable_item_actor_config.policies |= PolicyFlags::ACTOR_SIGNATURE; + OverlayableItem overlayable_item_biz(std::make_shared( "Other", "overlay://customization")); overlayable_item_biz.comment ="comment"; @@ -548,6 +553,7 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { .SetOverlayable("com.app.a:bool/baz", overlayable_item_baz) .SetOverlayable("com.app.a:bool/boz", overlayable_item_boz) .SetOverlayable("com.app.a:bool/biz", overlayable_item_biz) + .SetOverlayable("com.app.a:bool/actor_config", overlayable_item_actor_config) .AddValue("com.app.a:bool/fiz", ResourceUtils::TryParseBool("true")) .Build(); @@ -597,6 +603,15 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { | PolicyFlags::ODM_PARTITION | PolicyFlags::OEM_PARTITION)); + search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/actor_config")); + ASSERT_TRUE(search_result); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(overlayable_item.overlayable->name, Eq("ActorConfig")); + EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme")); + EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::SIGNATURE + | PolicyFlags::ACTOR_SIGNATURE)); + search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/biz")); ASSERT_TRUE(search_result); ASSERT_TRUE(search_result.value().entry->overlayable_item);