Merge changes from topic "actor-signature-policy-rvc-dev" into rvc-dev

* changes:
  Actor signature overlayable policy
  Refactor overlayable policy
This commit is contained in:
Winson Chiu
2020-02-27 18:27:53 +00:00
committed by Android (Google) Code Review
56 changed files with 1108 additions and 692 deletions

View File

@@ -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",
}

View File

@@ -20,15 +20,14 @@
#include <fstream>
#include <memory>
#include <ostream>
#include <sstream>
#include <string>
#include <vector>
#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<Unit> Create(const std::vector<std::string>& args) {
SYSTRACE << "Create " << args;
std::string target_apk_path;
@@ -78,7 +78,7 @@ Result<Unit> Create(const std::vector<std::string>& 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<Unit> Create(const std::vector<std::string>& args) {
}
if (fulfilled_policies == 0) {
fulfilled_policies |= PolicyFlags::POLICY_PUBLIC;
fulfilled_policies |= PolicyFlags::PUBLIC;
}
const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);

View File

@@ -20,8 +20,6 @@
#include <fstream>
#include <memory>
#include <ostream>
#include <sstream>
#include <string>
#include <vector>
#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<Unit> CreateMultiple(const std::vector<std::string>& args) {
@@ -81,7 +78,7 @@ Result<Unit> CreateMultiple(const std::vector<std::string>& 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<Unit> CreateMultiple(const std::vector<std::string>& args) {
}
if (fulfilled_policies == 0) {
fulfilled_policies |= PolicyFlags::POLICY_PUBLIC;
fulfilled_policies |= PolicyFlags::PUBLIC;
}
const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);

View File

@@ -20,7 +20,6 @@
#include <memory>
#include <ostream>
#include <set>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
@@ -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 {

View File

@@ -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() {

View File

@@ -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,

View File

@@ -0,0 +1,32 @@
/*
* 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;
const int ACTOR_SIGNATURE = 0x00000080;
}

View File

@@ -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 {

View File

@@ -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 <string>
#include <vector>
#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<PolicyBitmask> PoliciesToBitmaskResult(const std::vector<std::string>& policies);
// Converts a bitmask of policy flags into a list of their string representation as would be written
// into XML
std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask);
} // namespace android::idmap2::utils
#endif // IDMAP2_INCLUDE_IDMAP2_POLICYUTILS_H_

View File

@@ -30,6 +30,8 @@
using android::idmap2::utils::OverlayManifestInfo;
using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
namespace android::idmap2 {
struct TargetValue {

View File

@@ -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 <iterator>
#include <string>
#include <unordered_map>
#include <vector>
#include "androidfw/ResourceTypes.h"
#include "idmap2/Idmap.h"
#include "idmap2/Result.h"
namespace android::idmap2 {
Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies) {
static const std::unordered_map<android::StringPiece, PolicyFlags> kStringToFlag = {
{kPolicyOdm, PolicyFlags::POLICY_ODM_PARTITION},
{kPolicyOem, PolicyFlags::POLICY_OEM_PARTITION},
{kPolicyPublic, PolicyFlags::POLICY_PUBLIC},
{kPolicyProduct, PolicyFlags::POLICY_PRODUCT_PARTITION},
{kPolicySignature, PolicyFlags::POLICY_SIGNATURE},
{kPolicySystem, PolicyFlags::POLICY_SYSTEM_PARTITION},
{kPolicyVendor, PolicyFlags::POLICY_VENDOR_PARTITION},
};
PolicyBitmask bitmask = 0;
for (const std::string& policy : policies) {
const auto iter = kStringToFlag.find(policy);
if (iter != kStringToFlag.end()) {
bitmask |= iter->second;
} else {
return Error("unknown policy \"%s\"", policy.c_str());
}
}
return Result<PolicyBitmask>(bitmask);
}
std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask) {
std::vector<std::string> policies;
if ((bitmask & PolicyFlags::POLICY_ODM_PARTITION) != 0) {
policies.emplace_back(kPolicyOdm);
}
if ((bitmask & PolicyFlags::POLICY_OEM_PARTITION) != 0) {
policies.emplace_back(kPolicyOem);
}
if ((bitmask & PolicyFlags::POLICY_PUBLIC) != 0) {
policies.emplace_back(kPolicyPublic);
}
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

View File

@@ -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 <sstream>
#include "android-base/strings.h"
#include "idmap2/Policies.h"
using android::idmap2::policy::kPolicyStringToFlag;
namespace android::idmap2::utils {
Result<PolicyBitmask> PoliciesToBitmaskResult(const std::vector<std::string>& policies) {
std::vector<std::string> 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<PolicyBitmask>(bitmask);
}
auto prefix = unknown_policies.size() == 1 ? "policy" : "policies";
return Error("unknown %s: \"%s\"", prefix, android::base::Join(unknown_policies, ",").c_str());
}
std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask) {
std::vector<std::string> policies;
for (const auto& policy : kPolicyStringToFlag) {
if ((bitmask & policy.second) != 0) {
policies.emplace_back(policy.first.to_string());
}
}
return policies;
}
} // namespace android::idmap2::utils

View File

@@ -24,11 +24,16 @@
#include <vector>
#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<Unit> 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.

View File

@@ -14,18 +14,22 @@
* limitations under the License.
*/
#include <string>
#include <vector>
#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 <array>
#include <string>
#include <vector>
#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* kPolicyActor = "actor";
constexpr const char* kPolicyOdm = "odm";
constexpr const char* kPolicyOem = "oem";
constexpr const char* kPolicyProduct = "product";
@@ -34,15 +38,16 @@ 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<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies);
// Retrieves the string representations of policies in the bitmask.
std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask);
} // namespace android::idmap2
inline static const std::array<std::pair<StringPiece, PolicyFlags>, 8> kPolicyStringToFlag = {
std::pair{kPolicyActor, PolicyFlags::ACTOR_SIGNATURE},
{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_

View File

@@ -34,6 +34,7 @@
#include <string>
#include <vector>
#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;

View File

@@ -22,6 +22,8 @@
#include <utility>
#include <vector>
#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<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
ASSERT_THAT(overlay_apk, NotNull());
auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
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<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
ASSERT_THAT(overlay_apk, NotNull());
auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
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<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
ASSERT_THAT(overlay_apk, NotNull());
auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
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;
@@ -271,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) {
@@ -290,7 +306,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 +314,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 +330,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 +339,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 +362,7 @@ TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
std::unique_ptr<const ApkAssets> 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 +378,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) {
std::unique_ptr<const ApkAssets> 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);

View File

@@ -17,76 +17,96 @@
#include <string>
#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);
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) {
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");
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

View File

@@ -18,19 +18,22 @@
#include <sstream>
#include <string>
#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<const ApkAssets> 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) {

107
cmds/idmap2/tests/R.h Normal file
View File

@@ -0,0 +1,107 @@
/*
* 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 <idmap2/ResourceUtils.h>
namespace android::idmap2 {
static std::string hexify(ResourceId id) {
std::stringstream stream;
stream << std::hex << static_cast<uint32_t>(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_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);
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::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;
constexpr ResourceId policy_system_vendor = 0x7f010002;
}
namespace R::system_overlay_invalid::string {
constexpr ResourceId not_overlayable = 0x7f010000;
constexpr ResourceId other = 0x7f010001;
constexpr ResourceId policy_actor = 0x7f010002;
constexpr ResourceId policy_odm = 0x7f010003;
constexpr ResourceId policy_oem = 0x7f010004;
constexpr ResourceId policy_product = 0x7f010005;
constexpr ResourceId policy_public = 0x7f010006;
constexpr ResourceId policy_signature = 0x7f010007;
constexpr ResourceId policy_system = 0x7f010008;
constexpr ResourceId policy_system_vendor = 0x7f010009;
};
// clang-format on
} // namespace android::idmap2
#endif // IDMAP2_TESTS_R_H

View File

@@ -20,14 +20,20 @@
#include <sstream>
#include <string>
#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<const ApkAssets> 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());

View File

@@ -22,7 +22,9 @@
#include <utility>
#include <vector>
#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,120 @@ 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_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,
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 <overlayable> tag can overlay resources defined within any
// <overlayable> 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);
@@ -293,33 +309,44 @@ 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_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 */));
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

View File

@@ -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 = 0x41c60c8c;
constexpr const auto TARGET_CRC_STRING = "41c60c8c";
constexpr const auto OVERLAY_CRC = 0xc054fb26;
constexpr const auto OVERLAY_CRC_STRING = "c054fb26";
} // namespace android::idmap2::TestConstants
#endif // IDMAP2_TESTS_TESTCONSTANTS_H

View File

@@ -25,6 +25,7 @@
<string name="policy_signature">policy_signature</string>
<string name="policy_odm">policy_odm</string>
<string name="policy_oem">policy_oem</string>
<string name="policy_actor">policy_actor</string>
<!-- Requests to overlay a resource that is not declared as overlayable. -->
<string name="not_overlayable">not_overlayable</string>

View File

@@ -41,6 +41,10 @@
<item type="string" name="policy_oem" />
</policy>
<policy type="actor">
<item type="string" name="policy_actor" />
</policy>
<!-- Resources publicly overlayable -->
<policy type="public">
<item type="string" name="policy_public" />
@@ -63,4 +67,4 @@
<item type="string" name="other" />
</policy>
</overlayable>
</resources>
</resources>

View File

@@ -36,6 +36,7 @@
<string name="policy_signature">policy_signature</string>
<string name="policy_system">policy_system</string>
<string name="policy_system_vendor">policy_system_vendor</string>
<string name="policy_actor">policy_actor</string>
<string name="other">other</string>
</resources>

View File

@@ -138,6 +138,7 @@ public final class OverlayInfo implements Parcelable {
*
* @hide
*/
@NonNull
public final String packageName;
/**
@@ -145,6 +146,7 @@ public final class OverlayInfo implements Parcelable {
*
* @hide
*/
@NonNull
public final String targetPackageName;
/**
@@ -165,6 +167,7 @@ public final class OverlayInfo implements Parcelable {
* Full path to the base APK for this overlay package
* @hide
*/
@NonNull
public final String baseCodePath;
/**
@@ -292,6 +295,7 @@ public final class OverlayInfo implements Parcelable {
return targetOverlayableName;
}
@SuppressWarnings("ConstantConditions")
private void ensureValidState() {
if (packageName == null) {
throw new IllegalArgumentException("packageName must not be null");

View File

@@ -191,4 +191,3 @@ cc_benchmark {
shared_libs: common_test_libs,
data: ["tests/data/**/*.apk"],
}

View File

@@ -22,6 +22,7 @@
#include <androidfw/Asset.h>
#include <androidfw/LocaleData.h>
#include <androidfw/StringPiece.h>
#include <utils/Errors.h>
#include <utils/String16.h>
#include <utils/Vector.h>
@@ -34,6 +35,7 @@
#include <android/configuration.h>
#include <array>
#include <memory>
namespace android {
@@ -1676,42 +1678,64 @@ 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
*/
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,
// The overlay must be signed with the same signature as the package containing the target
// resource
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,
// The overlay must be signed with the same signature as the actor declared for the target
// resource
ACTOR_SIGNATURE = 0x00000080,
};
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<ResTable_overlayable_policy_header::PolicyFlags>(first | second);
return first;
}
#pragma pack(push, 1)
struct Idmap_header {
// Always 0x504D4449 ('IDMP')

View File

@@ -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) {

View File

@@ -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: [

View File

@@ -21,17 +21,17 @@ import static com.android.server.om.OverlayManagerService.TAG;
import android.annotation.NonNull;
import android.content.om.OverlayInfo;
import android.content.om.OverlayableInfo;
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;
import com.android.server.om.OverlayManagerServiceImpl.PackageManagerHelper;
import java.io.File;
import java.io.IOException;
/**
* Handle the creation and deletion of idmap files.
@@ -55,11 +55,11 @@ class IdmapManager {
VENDOR_IS_Q_OR_LATER = isQOrLater;
}
private final PackageManagerHelper mPackageManager;
private final OverlayableInfoCallback mOverlayableCallback;
private final IdmapDaemon mIdmapDaemon;
IdmapManager(final PackageManagerHelper packageManager) {
mPackageManager = packageManager;
IdmapManager(final OverlayableInfoCallback verifyCallback) {
mOverlayableCallback = verifyCallback;
mIdmapDaemon = IdmapDaemon.getInstance();
}
@@ -148,40 +148,67 @@ 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,
if (mOverlayableCallback.signaturesMatching(targetPackage.packageName,
overlayPackage.packageName, userId)) {
fulfilledPolicies |= IIdmap2.POLICY_SIGNATURE;
fulfilledPolicies |= OverlayablePolicy.SIGNATURE;
}
// Overlay matches actor signature
if (matchesActorSignature(targetPackage, overlayPackage, userId)) {
fulfilledPolicies |= OverlayablePolicy.ACTOR_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;
}
private boolean matchesActorSignature(@NonNull PackageInfo targetPackage,
@NonNull PackageInfo overlayPackage, int userId) {
String targetOverlayableName = overlayPackage.targetOverlayableName;
if (targetOverlayableName != null) {
try {
OverlayableInfo overlayableInfo = mOverlayableCallback.getOverlayableForTarget(
targetPackage.packageName, targetOverlayableName, userId);
if (overlayableInfo != null) {
String actorPackageName = OverlayActorEnforcer.getPackageNameForActor(
overlayableInfo.actor, mOverlayableCallback.getNamedActors()).first;
if (mOverlayableCallback.signaturesMatching(actorPackageName,
overlayPackage.packageName, userId)) {
return true;
}
}
} catch (IOException ignored) {
}
}
return false;
}
}

View File

@@ -17,7 +17,6 @@
package com.android.server.om;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.om.OverlayInfo;
import android.content.om.OverlayableInfo;
import android.content.pm.ApplicationInfo;
@@ -46,7 +45,7 @@ public class OverlayActorEnforcer {
// By default, the reason is not logged to prevent leaks of why it failed
private static final boolean DEBUG_REASON = false;
private final VerifyCallback mVerifyCallback;
private final OverlayableInfoCallback mOverlayableCallback;
/**
* @return nullable actor result with {@link ActorState} failure status
@@ -80,8 +79,8 @@ public class OverlayActorEnforcer {
return Pair.create(packageName, ActorState.ALLOWED);
}
public OverlayActorEnforcer(@NonNull VerifyCallback verifyCallback) {
mVerifyCallback = verifyCallback;
public OverlayActorEnforcer(@NonNull OverlayableInfoCallback overlayableCallback) {
mOverlayableCallback = overlayableCallback;
}
void enforceActor(@NonNull OverlayInfo overlayInfo, @NonNull String methodName,
@@ -117,7 +116,7 @@ public class OverlayActorEnforcer {
return ActorState.ALLOWED;
}
String[] callingPackageNames = mVerifyCallback.getPackagesForUid(callingUid);
String[] callingPackageNames = mOverlayableCallback.getPackagesForUid(callingUid);
if (ArrayUtils.isEmpty(callingPackageNames)) {
return ActorState.NO_PACKAGES_FOR_UID;
}
@@ -132,12 +131,12 @@ public class OverlayActorEnforcer {
if (TextUtils.isEmpty(targetOverlayableName)) {
try {
if (mVerifyCallback.doesTargetDefineOverlayable(targetPackageName, userId)) {
if (mOverlayableCallback.doesTargetDefineOverlayable(targetPackageName, userId)) {
return ActorState.MISSING_TARGET_OVERLAYABLE_NAME;
} else {
// If there's no overlayable defined, fallback to the legacy permission check
try {
mVerifyCallback.enforcePermission(
mOverlayableCallback.enforcePermission(
android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName);
// If the previous method didn't throw, check passed
@@ -153,7 +152,7 @@ public class OverlayActorEnforcer {
OverlayableInfo targetOverlayable;
try {
targetOverlayable = mVerifyCallback.getOverlayableForTarget(targetPackageName,
targetOverlayable = mOverlayableCallback.getOverlayableForTarget(targetPackageName,
targetOverlayableName, userId);
} catch (IOException e) {
return ActorState.UNABLE_TO_GET_TARGET;
@@ -167,7 +166,7 @@ public class OverlayActorEnforcer {
if (TextUtils.isEmpty(actor)) {
// If there's no actor defined, fallback to the legacy permission check
try {
mVerifyCallback.enforcePermission(
mOverlayableCallback.enforcePermission(
android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName);
// If the previous method didn't throw, check passed
@@ -177,7 +176,7 @@ public class OverlayActorEnforcer {
}
}
Map<String, Map<String, String>> namedActors = mVerifyCallback.getNamedActors();
Map<String, Map<String, String>> namedActors = mOverlayableCallback.getNamedActors();
Pair<String, ActorState> 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<String, Map<String, String>> 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;
}
}

View File

@@ -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<HashMap<String, PackageInfo>> 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) {

View File

@@ -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<PackageInfo> getOverlayPackages(int userId);
}
}

View File

@@ -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<String, Map<String, String>> 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);
}

View File

@@ -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<PackageInfo> getOverlayPackages(int userId);
}

View File

@@ -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()
}
}
}

View File

@@ -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 {

View File

@@ -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<String, Map<String, String>> 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 {

View File

@@ -59,6 +59,7 @@ cc_defaults {
"libprotobuf-cpp-full",
"libz",
"libbuildversion",
"libidmap2_policies",
],
stl: "libc++_static",
group_static_libs: true,

View File

@@ -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<OverlayableItem::PolicyFlags, std::string> 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";
}

View File

@@ -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 <policy> tags
current_policies = OverlayableItem::Policy::kNone;
current_policies = PolicyFlags::NONE;
continue;
} else if (event == xml::XmlPullParser::Event::kComment) {
// Retrieve the comment of individual <item> 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)
<< "<item> within an <overlayable> must be inside a <policy> 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) << "<policy> blocks cannot be recursively nested");
error = true;
@@ -1141,21 +1145,14 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
} else if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) {
// Parse the polices separated by vertical bar characters to allow for specifying multiple
// policies. Items within the policy tag will have the specified policy.
static const auto kPolicyMap =
ImmutableMap<StringPiece, OverlayableItem::Policy>::CreatePreSorted({
{"odm", OverlayableItem::Policy::kOdm},
{"oem", OverlayableItem::Policy::kOem},
{"product", OverlayableItem::Policy::kProduct},
{"public", OverlayableItem::Policy::kPublic},
{"signature", OverlayableItem::Policy::kSignature},
{"system", OverlayableItem::Policy::kSystem},
{"vendor", OverlayableItem::Policy::kVendor},
});
for (const StringPiece& part : util::Tokenize(maybe_type.value(), '|')) {
StringPiece trimmed_part = util::TrimWhitespace(part);
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)
<< "<policy> has unsupported type '" << trimmed_part << "'");
error = true;

View File

@@ -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 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\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) {
@@ -1005,6 +1007,9 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
<policy type="oem">
<item type="string" name="buz" />
</policy>
<policy type="actor">
<item type="string" name="actor" />
</policy>
</overlayable>)";
ASSERT_TRUE(TestParse(input));
@@ -1014,7 +1019,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 +1027,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 +1035,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 +1043,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 +1051,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 +1059,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 +1067,15 @@ 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));
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) {
@@ -1125,8 +1138,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 +1147,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) {

View File

@@ -36,6 +36,8 @@
#include <unordered_map>
#include <vector>
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(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> overlayable;
PolicyFlags policies = Policy::kNone;
PolicyFlags policies = PolicyFlags::NONE;
std::string comment;
Source source;
};

View File

@@ -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<Overlayable>("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<Overlayable>("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<Overlayable>("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<Overlayable>("Name2", "overlay://theme"));
overlayable_item2.policies = OverlayableItem::Policy::kProduct;
overlayable_item2.policies = PolicyFlags::PRODUCT_PARTITION;
ASSERT_TRUE(table.SetOverlayable(bar, overlayable_item2, test::GetDiagnostics()));
}

View File

@@ -167,6 +167,7 @@ message OverlayableItem {
SIGNATURE = 5;
ODM = 6;
OEM = 7;
ACTOR = 8;
}
// The location of the <item> declaration in source.

View File

@@ -455,35 +455,6 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) {
const ResTable_overlayable_policy_header* policy_header =
ConvertTo<ResTable_overlayable_policy_header>(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<const ResTable_ref*>(
((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;
}

View File

@@ -233,7 +233,7 @@ class MapFlattenVisitor : public ValueVisitor {
struct OverlayableChunk {
std::string actor;
Source source;
std::map<OverlayableItem::PolicyFlags, std::set<ResourceId>> policy_ids;
std::map<PolicyFlags, std::set<ResourceId>> 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<ResourceId>{id}));
std::make_pair(item.policies, std::set<ResourceId>{id}));
}
}
}
@@ -559,7 +536,8 @@ class PackageFlattener {
ChunkWriter policy_writer(buffer);
auto* policy_type = policy_writer.StartChunk<ResTable_overlayable_policy_header>(
RES_TABLE_OVERLAYABLE_POLICY_TYPE);
policy_type->policy_flags = util::HostToDevice32(static_cast<uint32_t>(policy_ids.first));
policy_type->policy_flags =
static_cast<PolicyFlags>(util::HostToDevice32(static_cast<uint32_t>(policy_ids.first)));
policy_type->entry_count = util::HostToDevice32(static_cast<uint32_t>(
policy_ids.second.size()));
// Write the ids after the policy header

View File

@@ -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<Overlayable>("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<ResourceTable> 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<Overlayable>("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<ResourceTable> table =
test::ResourceTableBuilder()
@@ -732,47 +734,48 @@ 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<Overlayable>("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<Overlayable>("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;
overlayable_item_three.policies |= PolicyFlags::ACTOR_SIGNATURE;
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
@@ -796,8 +799,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 +809,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 +818,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 +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, OverlayableItem::Policy::kSignature);
EXPECT_EQ(result_overlayable.policies, PolicyFlags::SIGNATURE
| PolicyFlags::ACTOR_SIGNATURE);
}
TEST_F(TableFlattenerTest, FlattenOverlayableNoPolicyFails) {

View File

@@ -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,28 @@ 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;
case pb::OverlayableItem::ACTOR:
out_overlayable->policies |= PolicyFlags::ACTOR_SIGNATURE;
break;
default:
*out_error = "unknown overlayable policy";

View File

@@ -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,27 +301,30 @@ 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);
}
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,

View File

@@ -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,28 @@ TEST(ProtoSerializeTest, SerializeDeserializeConfiguration) {
TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
OverlayableItem overlayable_item_foo(std::make_shared<Overlayable>(
"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<Overlayable>(
"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<Overlayable>(
"FontPack", "overlay://theme"));
overlayable_item_baz.policies |= OverlayableItem::Policy::kPublic;
overlayable_item_baz.policies |= PolicyFlags::PUBLIC;
OverlayableItem overlayable_item_boz(std::make_shared<Overlayable>(
"IconPack", "overlay://theme"));
overlayable_item_boz.policies |= OverlayableItem::Policy::kSignature;
overlayable_item_boz.policies |= OverlayableItem::Policy::kOdm;
overlayable_item_boz.policies |= OverlayableItem::Policy::kOem;
overlayable_item_boz.policies |= PolicyFlags::SIGNATURE;
overlayable_item_boz.policies |= PolicyFlags::ODM_PARTITION;
overlayable_item_boz.policies |= PolicyFlags::OEM_PARTITION;
OverlayableItem overlayable_item_actor_config(std::make_shared<Overlayable>(
"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<Overlayable>(
"Other", "overlay://customization"));
@@ -546,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();
@@ -565,8 +573,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 +582,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 +591,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 +599,25 @@ 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/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);
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"));

View File

@@ -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<Overlayable>("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<ResourceTable> 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<ResourceTable> 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<Overlayable>("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<ResourceTable> table_a =
test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f)
@@ -570,7 +572,7 @@ TEST_F(TableMergerTest, SameResourceDifferentNameFail) {
auto overlayable_second = std::make_shared<Overlayable>("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<ResourceTable> table_b =
test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f)
@@ -589,7 +591,7 @@ TEST_F(TableMergerTest, SameResourceDifferentActorFail) {
auto overlayable_first = std::make_shared<Overlayable>("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<ResourceTable> table_a =
test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f)
@@ -599,7 +601,7 @@ TEST_F(TableMergerTest, SameResourceDifferentActorFail) {
auto overlayable_second = std::make_shared<Overlayable>("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<ResourceTable> table_b =
test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f)
@@ -618,7 +620,7 @@ TEST_F(TableMergerTest, SameResourceDifferentPoliciesFail) {
auto overlayable_first = std::make_shared<Overlayable>("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<ResourceTable> table_a =
test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f)
@@ -628,7 +630,7 @@ TEST_F(TableMergerTest, SameResourceDifferentPoliciesFail) {
auto overlayable_second = std::make_shared<Overlayable>("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<ResourceTable> 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<ResourceTable> 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<ResourceTable> table_b =
test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f)