Refactor overlayable policy
To make it easier to add the actor policy in a follow up CL, move most of the policy handling to a central location. The strings and transformation between strings and flags is now handled in libidmap2policies, with libandroidfw containing the single source of policy flags. This also extracts all the test resource IDs into an R.h so they can be swapped without having to edit a dozen files each time. Bug: 130563563 Test: m aapt2_tests idmapt2_tests and run from host test output Test: atest libandroidfw_tests Change-Id: Ie533c9cebf938215df7586f00c38763ae467e606
This commit is contained in:
@@ -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",
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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,
|
||||
|
||||
31
cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl
Normal file
31
cmds/idmap2/idmap2d/aidl/android/os/OverlayablePolicy.aidl
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.os;
|
||||
|
||||
/**
|
||||
* @see ResourcesTypes.h ResTable_overlayable_policy_header::PolicyFlags
|
||||
* @hide
|
||||
*/
|
||||
interface OverlayablePolicy {
|
||||
const int PUBLIC = 0x00000001;
|
||||
const int SYSTEM_PARTITION = 0x00000002;
|
||||
const int VENDOR_PARTITION = 0x00000004;
|
||||
const int PRODUCT_PARTITION = 0x00000008;
|
||||
const int SIGNATURE = 0x00000010;
|
||||
const int ODM_PARTITION = 0x00000020;
|
||||
const int OEM_PARTITION = 0x00000040;
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
41
cmds/idmap2/include/idmap2/PolicyUtils.h
Normal file
41
cmds/idmap2/include/idmap2/PolicyUtils.h
Normal 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_
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
using android::idmap2::utils::OverlayManifestInfo;
|
||||
|
||||
using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
|
||||
|
||||
namespace android::idmap2 {
|
||||
|
||||
struct TargetValue {
|
||||
|
||||
@@ -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
|
||||
61
cmds/idmap2/libidmap2/PolicyUtils.cpp
Normal file
61
cmds/idmap2/libidmap2/PolicyUtils.cpp
Normal 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
|
||||
@@ -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.
|
||||
|
||||
@@ -14,17 +14,20 @@
|
||||
* 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* kPolicyOdm = "odm";
|
||||
constexpr const char* kPolicyOem = "oem";
|
||||
@@ -34,15 +37,15 @@ constexpr const char* kPolicySignature = "signature";
|
||||
constexpr const char* kPolicySystem = "system";
|
||||
constexpr const char* kPolicyVendor = "vendor";
|
||||
|
||||
using PolicyFlags = ResTable_overlayable_policy_header::PolicyFlags;
|
||||
using PolicyBitmask = uint32_t;
|
||||
|
||||
// Parses the string representations of policies into a bitmask.
|
||||
Result<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>, 7> kPolicyStringToFlag = {
|
||||
std::pair{kPolicyOdm, PolicyFlags::ODM_PARTITION},
|
||||
{kPolicyOem, PolicyFlags::OEM_PARTITION},
|
||||
{kPolicyProduct, PolicyFlags::PRODUCT_PARTITION},
|
||||
{kPolicyPublic, PolicyFlags::PUBLIC},
|
||||
{kPolicySignature, PolicyFlags::SIGNATURE},
|
||||
{kPolicySystem, PolicyFlags::SYSTEM_PARTITION},
|
||||
{kPolicyVendor, PolicyFlags::VENDOR_PARTITION},
|
||||
};
|
||||
} // namespace android::idmap2::policy
|
||||
|
||||
#endif // IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -290,7 +298,7 @@ TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) {
|
||||
info.target_name = "TestResources";
|
||||
info.resource_mapping = 0x7f030001; // xml/overlays_different_packages
|
||||
auto idmap_data = TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk", info,
|
||||
PolicyFlags::POLICY_PUBLIC,
|
||||
PolicyFlags::PUBLIC,
|
||||
/* enforce_overlayable */ false);
|
||||
|
||||
ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage();
|
||||
@@ -298,14 +306,14 @@ TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) {
|
||||
|
||||
const auto& target_entries = data->GetTargetEntries();
|
||||
ASSERT_EQ(target_entries.size(), 2U);
|
||||
ASSERT_TARGET_ENTRY(target_entries[0], 0x7f02000c, Res_value::TYPE_REFERENCE,
|
||||
0x0104000a); // string/str1 -> android:string/ok
|
||||
ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE,
|
||||
0x7f020001); // string/str3 -> string/str4
|
||||
ASSERT_TARGET_ENTRY(target_entries[0], R::target::string::str1, Res_value::TYPE_REFERENCE,
|
||||
0x0104000a); // -> android:string/ok
|
||||
ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
|
||||
R::overlay::string::str3);
|
||||
|
||||
const auto& overlay_entries = data->GetOverlayEntries();
|
||||
ASSERT_EQ(overlay_entries.size(), 1U);
|
||||
ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x7f020001, 0x7f02000e); // string/str3 <- string/str4
|
||||
ASSERT_OVERLAY_ENTRY(overlay_entries[0], R::overlay::string::str3, R::target::string::str3);
|
||||
}
|
||||
|
||||
TEST(IdmapTests, CreateIdmapDataInlineResources) {
|
||||
@@ -314,7 +322,7 @@ TEST(IdmapTests, CreateIdmapDataInlineResources) {
|
||||
info.target_name = "TestResources";
|
||||
info.resource_mapping = 0x7f030002; // xml/overlays_inline
|
||||
auto idmap_data = TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk", info,
|
||||
PolicyFlags::POLICY_PUBLIC,
|
||||
PolicyFlags::PUBLIC,
|
||||
/* enforce_overlayable */ false);
|
||||
|
||||
ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage();
|
||||
@@ -323,10 +331,10 @@ TEST(IdmapTests, CreateIdmapDataInlineResources) {
|
||||
constexpr size_t overlay_string_pool_size = 8U;
|
||||
const auto& target_entries = data->GetTargetEntries();
|
||||
ASSERT_EQ(target_entries.size(), 2U);
|
||||
ASSERT_TARGET_ENTRY(target_entries[0], 0x7f010000, Res_value::TYPE_INT_DEC,
|
||||
73U); // integer/int1 -> 73
|
||||
ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_STRING,
|
||||
overlay_string_pool_size + 0U); // string/str1 -> "Hello World"
|
||||
ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1, Res_value::TYPE_INT_DEC,
|
||||
73U); // -> 73
|
||||
ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, Res_value::TYPE_STRING,
|
||||
overlay_string_pool_size + 0U); // -> "Hello World"
|
||||
|
||||
const auto& overlay_entries = data->GetOverlayEntries();
|
||||
ASSERT_EQ(overlay_entries.size(), 0U);
|
||||
@@ -346,7 +354,7 @@ TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
|
||||
std::unique_ptr<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 +370,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);
|
||||
|
||||
@@ -17,74 +17,78 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
94
cmds/idmap2/tests/R.h
Normal file
94
cmds/idmap2/tests/R.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef IDMAP2_TESTS_R_H
|
||||
#define IDMAP2_TESTS_R_H
|
||||
|
||||
#include <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_odm = 0x7f020005;
|
||||
constexpr ResourceId policy_oem = 0x7f020006;
|
||||
constexpr ResourceId policy_product = 0x7f020007;
|
||||
constexpr ResourceId policy_public = 0x7f020008;
|
||||
constexpr ResourceId policy_signature = 0x7f020009;
|
||||
constexpr ResourceId policy_system = 0x7f02000a;
|
||||
constexpr ResourceId policy_system_vendor = 0x7f02000b;
|
||||
constexpr ResourceId str1 = 0x7f02000c;
|
||||
constexpr ResourceId str3 = 0x7f02000e;
|
||||
constexpr ResourceId str4 = 0x7f02000f;
|
||||
|
||||
namespace literal {
|
||||
inline const std::string str1 = hexify(R::target::string::str1);
|
||||
inline const std::string str3 = hexify(R::target::string::str3);
|
||||
inline const std::string str4 = hexify(R::target::string::str4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace R::overlay {
|
||||
namespace integer {
|
||||
constexpr ResourceId int1 = 0x7f010000;
|
||||
}
|
||||
namespace string {
|
||||
constexpr ResourceId str1 = 0x7f020000;
|
||||
constexpr ResourceId str3 = 0x7f020001;
|
||||
constexpr ResourceId str4 = 0x7f020002;
|
||||
}
|
||||
}
|
||||
|
||||
namespace R::system_overlay::string {
|
||||
constexpr ResourceId policy_public = 0x7f010000;
|
||||
constexpr ResourceId policy_system = 0x7f010001;
|
||||
constexpr ResourceId policy_system_vendor = 0x7f010002;
|
||||
}
|
||||
|
||||
namespace R::system_overlay_invalid::string {
|
||||
constexpr ResourceId not_overlayable = 0x7f010000;
|
||||
constexpr ResourceId other = 0x7f010001;
|
||||
constexpr ResourceId policy_odm = 0x7f010002;
|
||||
constexpr ResourceId policy_oem = 0x7f010003;
|
||||
constexpr ResourceId policy_product = 0x7f010004;
|
||||
constexpr ResourceId policy_public = 0x7f010005;
|
||||
constexpr ResourceId policy_signature = 0x7f010006;
|
||||
constexpr ResourceId policy_system = 0x7f010007;
|
||||
constexpr ResourceId policy_system_vendor = 0x7f010008;
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
} // namespace android::idmap2
|
||||
|
||||
#endif // IDMAP2_TESTS_R_H
|
||||
@@ -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());
|
||||
|
||||
@@ -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,117 @@ TEST(ResourceMappingTests, InlineResources) {
|
||||
auto& res = *resources;
|
||||
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
|
||||
ASSERT_EQ(res.GetOverlayToTargetMap().size(), 0U);
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_STRING,
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_STRING,
|
||||
overlay_string_pool_size + 0U,
|
||||
false /* rewrite */)); // string/str1 -> "Hello World"
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_INT_DEC, 73U,
|
||||
false /* rewrite */)); // string/str1 -> "Hello World"
|
||||
false /* rewrite */)); // -> "Hello World"
|
||||
ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_INT_DEC, 73U,
|
||||
false /* rewrite */)); // -> 73
|
||||
}
|
||||
|
||||
TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
|
||||
auto resources =
|
||||
TestGetResourceMapping("/target/target.apk", "/system-overlay/system-overlay.apk",
|
||||
PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
|
||||
PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC,
|
||||
/* enforce_overlayable */ true);
|
||||
|
||||
ASSERT_TRUE(resources) << resources.GetErrorMessage();
|
||||
auto& res = *resources;
|
||||
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010000,
|
||||
false /* rewrite */)); // string/policy_public
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010001,
|
||||
false /* rewrite */)); // string/policy_system
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010002,
|
||||
false /* rewrite */)); // string/policy_system_vendor
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay::string::policy_public, false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay::string::policy_system, false /* rewrite */));
|
||||
ASSERT_RESULT(
|
||||
MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay::string::policy_system_vendor, false /* rewrite */));
|
||||
}
|
||||
|
||||
// Resources that are not declared as overlayable and resources that a protected by policies the
|
||||
// overlay does not fulfill must not map to overlay resources.
|
||||
TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
|
||||
auto resources = TestGetResourceMapping(
|
||||
"/target/target.apk", "/system-overlay-invalid/system-overlay-invalid.apk",
|
||||
PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
|
||||
/* enforce_overlayable */ true);
|
||||
auto resources = TestGetResourceMapping("/target/target.apk",
|
||||
"/system-overlay-invalid/system-overlay-invalid.apk",
|
||||
PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC,
|
||||
/* enforce_overlayable */ true);
|
||||
|
||||
ASSERT_TRUE(resources) << resources.GetErrorMessage();
|
||||
auto& res = *resources;
|
||||
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005,
|
||||
false /* rewrite */)); // string/policy_public
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007,
|
||||
false /* rewrite */)); // string/policy_system
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008,
|
||||
false /* rewrite */)); // string/policy_system_vendor
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_public,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_system,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(
|
||||
MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */));
|
||||
}
|
||||
|
||||
// Resources that are not declared as overlayable and resources that a protected by policies the
|
||||
// overlay does not fulfilled can map to overlay resources when overlayable enforcement is turned
|
||||
// off.
|
||||
TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
|
||||
auto resources = TestGetResourceMapping(
|
||||
"/target/target.apk", "/system-overlay-invalid/system-overlay-invalid.apk",
|
||||
PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC,
|
||||
/* enforce_overlayable */ false);
|
||||
auto resources = TestGetResourceMapping("/target/target.apk",
|
||||
"/system-overlay-invalid/system-overlay-invalid.apk",
|
||||
PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC,
|
||||
/* enforce_overlayable */ false);
|
||||
|
||||
ASSERT_TRUE(resources) << resources.GetErrorMessage();
|
||||
auto& res = *resources;
|
||||
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 9U);
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020003, Res_value::TYPE_REFERENCE, 0x7f010000,
|
||||
false /* rewrite */)); // string/not_overlayable
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020004, Res_value::TYPE_REFERENCE, 0x7f010001,
|
||||
false /* rewrite */)); // string/other
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020005, Res_value::TYPE_REFERENCE, 0x7f010002,
|
||||
false /* rewrite */)); // string/policy_odm
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020006, Res_value::TYPE_REFERENCE, 0x7f010003,
|
||||
false /* rewrite */)); // string/policy_oem
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020007, Res_value::TYPE_REFERENCE, 0x7f010004,
|
||||
false /* rewrite */)); // string/policy_product
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005,
|
||||
false /* rewrite */)); // string/policy_public
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020009, Res_value::TYPE_REFERENCE, 0x7f010006,
|
||||
false /* rewrite */)); // string/policy_signature
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007,
|
||||
false /* rewrite */)); // string/policy_system
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008,
|
||||
false /* rewrite */)); // string/policy_system_vendor
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::not_overlayable,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::other, false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_odm, false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_oem, false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_product,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_public,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_signature,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_system,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(
|
||||
MappingExists(res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */));
|
||||
}
|
||||
|
||||
// Overlays that do not target an <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);
|
||||
@@ -294,32 +307,40 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
|
||||
ASSERT_TRUE(resources) << resources.GetErrorMessage();
|
||||
auto& res = *resources;
|
||||
ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 9U);
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020003, Res_value::TYPE_REFERENCE, 0x7f010000,
|
||||
false /* rewrite */)); // string/not_overlayable
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020004, Res_value::TYPE_REFERENCE, 0x7f010001,
|
||||
false /* rewrite */)); // string/other
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020005, Res_value::TYPE_REFERENCE, 0x7f010002,
|
||||
false /* rewrite */)); // string/policy_odm
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020006, Res_value::TYPE_REFERENCE, 0x7f010003,
|
||||
false /* rewrite */)); // string/policy_oem
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020007, Res_value::TYPE_REFERENCE, 0x7f010004,
|
||||
false /* rewrite */)); // string/policy_product
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005,
|
||||
false /* rewrite */)); // string/policy_public
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f020009, Res_value::TYPE_REFERENCE, 0x7f010006,
|
||||
false /* rewrite */)); // string/policy_signature
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007,
|
||||
false /* rewrite */)); // string/policy_system
|
||||
ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008,
|
||||
false /* rewrite */)); // string/policy_system_vendor
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::not_overlayable,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::other, false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_odm,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_oem,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_product,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_public,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_signature,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_system,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(
|
||||
res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */));
|
||||
};
|
||||
|
||||
CheckEntries(PolicyFlags::POLICY_SIGNATURE);
|
||||
CheckEntries(PolicyFlags::POLICY_PRODUCT_PARTITION);
|
||||
CheckEntries(PolicyFlags::POLICY_SYSTEM_PARTITION);
|
||||
CheckEntries(PolicyFlags::POLICY_VENDOR_PARTITION);
|
||||
CheckEntries(PolicyFlags::POLICY_ODM_PARTITION);
|
||||
CheckEntries(PolicyFlags::POLICY_OEM_PARTITION);
|
||||
CheckEntries(PolicyFlags::SIGNATURE);
|
||||
CheckEntries(PolicyFlags::PRODUCT_PARTITION);
|
||||
CheckEntries(PolicyFlags::SYSTEM_PARTITION);
|
||||
CheckEntries(PolicyFlags::VENDOR_PARTITION);
|
||||
CheckEntries(PolicyFlags::ODM_PARTITION);
|
||||
CheckEntries(PolicyFlags::OEM_PARTITION);
|
||||
}
|
||||
|
||||
} // namespace android::idmap2
|
||||
|
||||
30
cmds/idmap2/tests/TestConstants.h
Normal file
30
cmds/idmap2/tests/TestConstants.h
Normal 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 = 0x76a20829;
|
||||
constexpr const auto TARGET_CRC_STRING = "76a20829";
|
||||
|
||||
constexpr const auto OVERLAY_CRC = 0xc054fb26;
|
||||
constexpr const auto OVERLAY_CRC_STRING = "c054fb26";
|
||||
|
||||
} // namespace android::idmap2::TestConstants
|
||||
|
||||
#endif // IDMAP2_TESTS_TESTCONSTANTS_H
|
||||
@@ -191,4 +191,3 @@ cc_benchmark {
|
||||
shared_libs: common_test_libs,
|
||||
data: ["tests/data/**/*.apk"],
|
||||
}
|
||||
|
||||
|
||||
@@ -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,61 @@ struct ResTable_overlayable_header
|
||||
*/
|
||||
struct ResTable_overlayable_policy_header
|
||||
{
|
||||
struct ResChunk_header header;
|
||||
|
||||
/**
|
||||
* Flags for a bitmask for all possible overlayable policy options.
|
||||
*
|
||||
* Any changes to this set should also update aidl/android/os/OverlayablePolicy.aidl
|
||||
* and proto/OverlayablePolicy.proto.
|
||||
*/
|
||||
enum PolicyFlags : uint32_t {
|
||||
// Base
|
||||
NONE = 0x00000000,
|
||||
|
||||
// Any overlay can overlay these resources.
|
||||
POLICY_PUBLIC = 0x00000001,
|
||||
PUBLIC = 0x00000001,
|
||||
|
||||
// The overlay must reside of the system partition or must have existed on the system partition
|
||||
// before an upgrade to overlay these resources.
|
||||
POLICY_SYSTEM_PARTITION = 0x00000002,
|
||||
SYSTEM_PARTITION = 0x00000002,
|
||||
|
||||
// The overlay must reside of the vendor partition or must have existed on the vendor partition
|
||||
// before an upgrade to overlay these resources.
|
||||
POLICY_VENDOR_PARTITION = 0x00000004,
|
||||
VENDOR_PARTITION = 0x00000004,
|
||||
|
||||
// The overlay must reside of the product partition or must have existed on the product
|
||||
// partition before an upgrade to overlay these resources.
|
||||
POLICY_PRODUCT_PARTITION = 0x00000008,
|
||||
PRODUCT_PARTITION = 0x00000008,
|
||||
|
||||
// The overlay must be signed with the same signature as the actor of the target resource,
|
||||
// which can be separate or the same as the target package with the resource.
|
||||
POLICY_SIGNATURE = 0x00000010,
|
||||
SIGNATURE = 0x00000010,
|
||||
|
||||
// The overlay must reside of the odm partition or must have existed on the odm
|
||||
// partition before an upgrade to overlay these resources.
|
||||
POLICY_ODM_PARTITION = 0x00000020,
|
||||
ODM_PARTITION = 0x00000020,
|
||||
|
||||
// The overlay must reside of the oem partition or must have existed on the oem
|
||||
// partition before an upgrade to overlay these resources.
|
||||
POLICY_OEM_PARTITION = 0x00000040,
|
||||
OEM_PARTITION = 0x00000040,
|
||||
};
|
||||
uint32_t policy_flags;
|
||||
|
||||
using PolicyBitmask = uint32_t;
|
||||
|
||||
struct ResChunk_header header;
|
||||
|
||||
PolicyFlags policy_flags;
|
||||
|
||||
// The number of ResTable_ref that follow this header.
|
||||
uint32_t entry_count;
|
||||
};
|
||||
|
||||
inline ResTable_overlayable_policy_header::PolicyFlags& operator |=(
|
||||
ResTable_overlayable_policy_header::PolicyFlags& first,
|
||||
ResTable_overlayable_policy_header::PolicyFlags second) {
|
||||
first = static_cast<ResTable_overlayable_policy_header::PolicyFlags>(first | second);
|
||||
return first;
|
||||
}
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct Idmap_header {
|
||||
// Always 0x504D4449 ('IDMP')
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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: [
|
||||
|
||||
@@ -24,7 +24,7 @@ import android.content.om.OverlayInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.os.IIdmap2;
|
||||
import android.os.OverlayablePolicy;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Slog;
|
||||
@@ -148,38 +148,38 @@ class IdmapManager {
|
||||
private int calculateFulfilledPolicies(@NonNull final PackageInfo targetPackage,
|
||||
@NonNull final PackageInfo overlayPackage, int userId) {
|
||||
final ApplicationInfo ai = overlayPackage.applicationInfo;
|
||||
int fulfilledPolicies = IIdmap2.POLICY_PUBLIC;
|
||||
int fulfilledPolicies = OverlayablePolicy.PUBLIC;
|
||||
|
||||
// Overlay matches target signature
|
||||
if (mPackageManager.signaturesMatching(targetPackage.packageName,
|
||||
overlayPackage.packageName, userId)) {
|
||||
fulfilledPolicies |= IIdmap2.POLICY_SIGNATURE;
|
||||
fulfilledPolicies |= OverlayablePolicy.SIGNATURE;
|
||||
}
|
||||
|
||||
// Vendor partition (/vendor)
|
||||
if (ai.isVendor()) {
|
||||
return fulfilledPolicies | IIdmap2.POLICY_VENDOR_PARTITION;
|
||||
return fulfilledPolicies | OverlayablePolicy.VENDOR_PARTITION;
|
||||
}
|
||||
|
||||
// Product partition (/product)
|
||||
if (ai.isProduct()) {
|
||||
return fulfilledPolicies | IIdmap2.POLICY_PRODUCT_PARTITION;
|
||||
return fulfilledPolicies | OverlayablePolicy.PRODUCT_PARTITION;
|
||||
}
|
||||
|
||||
// Odm partition (/odm)
|
||||
if (ai.isOdm()) {
|
||||
return fulfilledPolicies | IIdmap2.POLICY_ODM_PARTITION;
|
||||
return fulfilledPolicies | OverlayablePolicy.ODM_PARTITION;
|
||||
}
|
||||
|
||||
// Oem partition (/oem)
|
||||
if (ai.isOem()) {
|
||||
return fulfilledPolicies | IIdmap2.POLICY_OEM_PARTITION;
|
||||
return fulfilledPolicies | OverlayablePolicy.OEM_PARTITION;
|
||||
}
|
||||
|
||||
// System_ext partition (/system_ext) is considered as system
|
||||
// Check this last since every partition except for data is scanned as system in the PMS.
|
||||
if (ai.isSystemApp() || ai.isSystemExt()) {
|
||||
return fulfilledPolicies | IIdmap2.POLICY_SYSTEM_PARTITION;
|
||||
return fulfilledPolicies | OverlayablePolicy.SYSTEM_PARTITION;
|
||||
}
|
||||
|
||||
return fulfilledPolicies;
|
||||
|
||||
@@ -59,6 +59,7 @@ cc_defaults {
|
||||
"libprotobuf-cpp-full",
|
||||
"libz",
|
||||
"libbuildversion",
|
||||
"libidmap2_policies",
|
||||
],
|
||||
stl: "libc++_static",
|
||||
group_static_libs: true,
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
@@ -1014,7 +1016,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
|
||||
ASSERT_TRUE(search_result.value().entry->overlayable_item);
|
||||
OverlayableItem result_overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PRODUCT_PARTITION));
|
||||
|
||||
search_result = table_.FindResource(test::ParseNameOrDie("string/fiz"));
|
||||
ASSERT_TRUE(search_result);
|
||||
@@ -1022,7 +1024,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
|
||||
ASSERT_TRUE(search_result.value().entry->overlayable_item);
|
||||
result_overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kSystem));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::SYSTEM_PARTITION));
|
||||
|
||||
search_result = table_.FindResource(test::ParseNameOrDie("string/fuz"));
|
||||
ASSERT_TRUE(search_result);
|
||||
@@ -1030,7 +1032,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
|
||||
ASSERT_TRUE(search_result.value().entry->overlayable_item);
|
||||
result_overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kVendor));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::VENDOR_PARTITION));
|
||||
|
||||
search_result = table_.FindResource(test::ParseNameOrDie("string/faz"));
|
||||
ASSERT_TRUE(search_result);
|
||||
@@ -1038,7 +1040,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
|
||||
ASSERT_TRUE(search_result.value().entry->overlayable_item);
|
||||
result_overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PUBLIC));
|
||||
|
||||
search_result = table_.FindResource(test::ParseNameOrDie("string/foz"));
|
||||
ASSERT_TRUE(search_result);
|
||||
@@ -1046,7 +1048,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
|
||||
ASSERT_TRUE(search_result.value().entry->overlayable_item);
|
||||
result_overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::SIGNATURE));
|
||||
|
||||
search_result = table_.FindResource(test::ParseNameOrDie("string/biz"));
|
||||
ASSERT_TRUE(search_result);
|
||||
@@ -1054,7 +1056,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
|
||||
ASSERT_TRUE(search_result.value().entry->overlayable_item);
|
||||
result_overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kOdm));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::ODM_PARTITION));
|
||||
|
||||
search_result = table_.FindResource(test::ParseNameOrDie("string/buz"));
|
||||
ASSERT_TRUE(search_result);
|
||||
@@ -1062,7 +1064,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
|
||||
ASSERT_TRUE(search_result.value().entry->overlayable_item);
|
||||
result_overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kOem));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::OEM_PARTITION));
|
||||
}
|
||||
|
||||
TEST_F(ResourceParserTest, ParseOverlayableNoPolicyError) {
|
||||
@@ -1125,8 +1127,8 @@ TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) {
|
||||
ASSERT_TRUE(search_result.value().entry->overlayable_item);
|
||||
OverlayableItem result_overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kVendor
|
||||
| OverlayableItem::Policy::kPublic));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::VENDOR_PARTITION
|
||||
| PolicyFlags::PUBLIC));
|
||||
|
||||
search_result = table_.FindResource(test::ParseNameOrDie("string/bar"));
|
||||
ASSERT_TRUE(search_result);
|
||||
@@ -1134,8 +1136,8 @@ TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) {
|
||||
ASSERT_TRUE(search_result.value().entry->overlayable_item);
|
||||
result_overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct
|
||||
| OverlayableItem::Policy::kSystem));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PRODUCT_PARTITION
|
||||
| PolicyFlags::SYSTEM_PARTITION));
|
||||
}
|
||||
|
||||
TEST_F(ResourceParserTest, DuplicateOverlayableIsError) {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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()));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,47 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) {
|
||||
ASSERT_THAT(search_result.value().entry, NotNull());
|
||||
ASSERT_TRUE(search_result.value().entry->overlayable_item);
|
||||
OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kSystem
|
||||
| OverlayableItem::Policy::kProduct);
|
||||
EXPECT_EQ(overlayable_item.policies, PolicyFlags::SYSTEM_PARTITION
|
||||
| PolicyFlags::PRODUCT_PARTITION);
|
||||
|
||||
search_result = output_table.FindResource(test::ParseNameOrDie(name_one));
|
||||
ASSERT_TRUE(search_result);
|
||||
ASSERT_THAT(search_result.value().entry, NotNull());
|
||||
ASSERT_TRUE(search_result.value().entry->overlayable_item);
|
||||
overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic);
|
||||
EXPECT_EQ(overlayable_item.policies, PolicyFlags::PUBLIC);
|
||||
|
||||
search_result = output_table.FindResource(test::ParseNameOrDie(name_two));
|
||||
ASSERT_TRUE(search_result);
|
||||
ASSERT_THAT(search_result.value().entry, NotNull());
|
||||
ASSERT_TRUE(search_result.value().entry->overlayable_item);
|
||||
overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kSystem
|
||||
| OverlayableItem::Policy::kProduct
|
||||
| OverlayableItem::Policy::kVendor);
|
||||
EXPECT_EQ(overlayable_item.policies, PolicyFlags::SYSTEM_PARTITION
|
||||
| PolicyFlags::PRODUCT_PARTITION
|
||||
| PolicyFlags::VENDOR_PARTITION);
|
||||
}
|
||||
|
||||
TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
|
||||
auto group = std::make_shared<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;
|
||||
|
||||
std::unique_ptr<ResourceTable> table =
|
||||
test::ResourceTableBuilder()
|
||||
@@ -796,8 +798,8 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
|
||||
OverlayableItem& result_overlayable = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_EQ(result_overlayable.overlayable->name, "TestName");
|
||||
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme");
|
||||
EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSystem
|
||||
| OverlayableItem::Policy::kProduct);
|
||||
EXPECT_EQ(result_overlayable.policies, PolicyFlags::SYSTEM_PARTITION
|
||||
| PolicyFlags::PRODUCT_PARTITION);
|
||||
|
||||
search_result = output_table.FindResource(test::ParseNameOrDie(name_one));
|
||||
ASSERT_TRUE(search_result);
|
||||
@@ -806,7 +808,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
|
||||
result_overlayable = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_EQ(result_overlayable.overlayable->name, "OtherName");
|
||||
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization");
|
||||
EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kPublic);
|
||||
EXPECT_EQ(result_overlayable.policies, PolicyFlags::PUBLIC);
|
||||
|
||||
search_result = output_table.FindResource(test::ParseNameOrDie(name_two));
|
||||
ASSERT_TRUE(search_result);
|
||||
@@ -815,9 +817,9 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
|
||||
result_overlayable = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_EQ(result_overlayable.overlayable->name, "TestName");
|
||||
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme");
|
||||
EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kOdm
|
||||
| OverlayableItem::Policy::kOem
|
||||
| OverlayableItem::Policy::kVendor);
|
||||
EXPECT_EQ(result_overlayable.policies, PolicyFlags::ODM_PARTITION
|
||||
| PolicyFlags::OEM_PARTITION
|
||||
| PolicyFlags::VENDOR_PARTITION);
|
||||
|
||||
search_result = output_table.FindResource(test::ParseNameOrDie(name_three));
|
||||
ASSERT_TRUE(search_result);
|
||||
@@ -826,7 +828,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
|
||||
result_overlayable = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_EQ(result_overlayable.overlayable->name, "OtherName");
|
||||
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization");
|
||||
EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSignature);
|
||||
EXPECT_EQ(result_overlayable.policies, PolicyFlags::SIGNATURE);
|
||||
}
|
||||
|
||||
TEST_F(TableFlattenerTest, FlattenOverlayableNoPolicyFails) {
|
||||
|
||||
@@ -30,6 +30,8 @@ using ::android::ConfigDescription;
|
||||
using ::android::LocaleValue;
|
||||
using ::android::ResStringPool;
|
||||
|
||||
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
|
||||
|
||||
namespace aapt {
|
||||
|
||||
namespace {
|
||||
@@ -379,25 +381,25 @@ bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable,
|
||||
for (const int policy : pb_overlayable.policy()) {
|
||||
switch (policy) {
|
||||
case pb::OverlayableItem::PUBLIC:
|
||||
out_overlayable->policies |= OverlayableItem::Policy::kPublic;
|
||||
out_overlayable->policies |= PolicyFlags::PUBLIC;
|
||||
break;
|
||||
case pb::OverlayableItem::SYSTEM:
|
||||
out_overlayable->policies |= OverlayableItem::Policy::kSystem;
|
||||
out_overlayable->policies |= PolicyFlags::SYSTEM_PARTITION;
|
||||
break;
|
||||
case pb::OverlayableItem::VENDOR:
|
||||
out_overlayable->policies |= OverlayableItem::Policy::kVendor;
|
||||
out_overlayable->policies |= PolicyFlags::VENDOR_PARTITION;
|
||||
break;
|
||||
case pb::OverlayableItem::PRODUCT:
|
||||
out_overlayable->policies |= OverlayableItem::Policy::kProduct;
|
||||
out_overlayable->policies |= PolicyFlags::PRODUCT_PARTITION;
|
||||
break;
|
||||
case pb::OverlayableItem::SIGNATURE:
|
||||
out_overlayable->policies |= OverlayableItem::Policy::kSignature;
|
||||
out_overlayable->policies |= PolicyFlags::SIGNATURE;
|
||||
break;
|
||||
case pb::OverlayableItem::ODM:
|
||||
out_overlayable->policies |= OverlayableItem::Policy::kOdm;
|
||||
out_overlayable->policies |= PolicyFlags::ODM_PARTITION;
|
||||
break;
|
||||
case pb::OverlayableItem::OEM:
|
||||
out_overlayable->policies |= OverlayableItem::Policy::kOem;
|
||||
out_overlayable->policies |= PolicyFlags::OEM_PARTITION;
|
||||
break;
|
||||
default:
|
||||
*out_error = "unknown overlayable policy";
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
|
||||
using android::ConfigDescription;
|
||||
|
||||
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
|
||||
|
||||
namespace aapt {
|
||||
|
||||
void SerializeStringPoolToPb(const StringPool& pool, pb::StringPool* out_pb_pool, IDiagnostics* diag) {
|
||||
@@ -299,25 +301,25 @@ static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item
|
||||
pb::OverlayableItem* pb_overlayable_item = pb_entry->mutable_overlayable_item();
|
||||
pb_overlayable_item->set_overlayable_idx(i);
|
||||
|
||||
if (overlayable_item.policies & OverlayableItem::Policy::kPublic) {
|
||||
if (overlayable_item.policies & PolicyFlags::PUBLIC) {
|
||||
pb_overlayable_item->add_policy(pb::OverlayableItem::PUBLIC);
|
||||
}
|
||||
if (overlayable_item.policies & OverlayableItem::Policy::kProduct) {
|
||||
if (overlayable_item.policies & PolicyFlags::PRODUCT_PARTITION) {
|
||||
pb_overlayable_item->add_policy(pb::OverlayableItem::PRODUCT);
|
||||
}
|
||||
if (overlayable_item.policies & OverlayableItem::Policy::kSystem) {
|
||||
if (overlayable_item.policies & PolicyFlags::SYSTEM_PARTITION) {
|
||||
pb_overlayable_item->add_policy(pb::OverlayableItem::SYSTEM);
|
||||
}
|
||||
if (overlayable_item.policies & OverlayableItem::Policy::kVendor) {
|
||||
if (overlayable_item.policies & PolicyFlags::VENDOR_PARTITION) {
|
||||
pb_overlayable_item->add_policy(pb::OverlayableItem::VENDOR);
|
||||
}
|
||||
if (overlayable_item.policies & OverlayableItem::Policy::kSignature) {
|
||||
if (overlayable_item.policies & PolicyFlags::SIGNATURE) {
|
||||
pb_overlayable_item->add_policy(pb::OverlayableItem::SIGNATURE);
|
||||
}
|
||||
if (overlayable_item.policies & OverlayableItem::Policy::kOdm) {
|
||||
if (overlayable_item.policies & PolicyFlags::ODM_PARTITION) {
|
||||
pb_overlayable_item->add_policy(pb::OverlayableItem::ODM);
|
||||
}
|
||||
if (overlayable_item.policies & OverlayableItem::Policy::kOem) {
|
||||
if (overlayable_item.policies & PolicyFlags::OEM_PARTITION) {
|
||||
pb_overlayable_item->add_policy(pb::OverlayableItem::OEM);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ using ::testing::NotNull;
|
||||
using ::testing::SizeIs;
|
||||
using ::testing::StrEq;
|
||||
|
||||
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
|
||||
|
||||
namespace aapt {
|
||||
|
||||
class MockFileCollection : public io::IFileCollection {
|
||||
@@ -171,7 +173,7 @@ TEST(ProtoSerializeTest, SerializeSinglePackage) {
|
||||
EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme"));
|
||||
EXPECT_THAT(result_overlayable_item.overlayable->source.path, Eq("res/values/overlayable.xml"));
|
||||
EXPECT_THAT(result_overlayable_item.overlayable->source.line, Eq(40));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kNone));
|
||||
EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::NONE));
|
||||
EXPECT_THAT(result_overlayable_item.source.path, Eq("res/values/overlayable.xml"));
|
||||
EXPECT_THAT(result_overlayable_item.source.line, Eq(42));
|
||||
}
|
||||
@@ -516,23 +518,23 @@ TEST(ProtoSerializeTest, SerializeDeserializeConfiguration) {
|
||||
TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
|
||||
OverlayableItem overlayable_item_foo(std::make_shared<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_biz(std::make_shared<Overlayable>(
|
||||
"Other", "overlay://customization"));
|
||||
@@ -565,8 +567,8 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
|
||||
OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(overlayable_item.overlayable->name, Eq("CustomizableResources"));
|
||||
EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://customization"));
|
||||
EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kSystem
|
||||
| OverlayableItem::Policy::kProduct));
|
||||
EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::SYSTEM_PARTITION
|
||||
| PolicyFlags::PRODUCT_PARTITION));
|
||||
|
||||
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/bar"));
|
||||
ASSERT_TRUE(search_result);
|
||||
@@ -574,8 +576,8 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
|
||||
overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(overlayable_item.overlayable->name, Eq("TaskBar"));
|
||||
EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme"));
|
||||
EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic
|
||||
| OverlayableItem::Policy::kVendor));
|
||||
EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::PUBLIC
|
||||
| PolicyFlags::VENDOR_PARTITION));
|
||||
|
||||
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/baz"));
|
||||
ASSERT_TRUE(search_result);
|
||||
@@ -583,7 +585,7 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
|
||||
overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(overlayable_item.overlayable->name, Eq("FontPack"));
|
||||
EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme"));
|
||||
EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic));
|
||||
EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::PUBLIC));
|
||||
|
||||
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/boz"));
|
||||
ASSERT_TRUE(search_result);
|
||||
@@ -591,16 +593,16 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
|
||||
overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(overlayable_item.overlayable->name, Eq("IconPack"));
|
||||
EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme"));
|
||||
EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature
|
||||
| OverlayableItem::Policy::kOdm
|
||||
| OverlayableItem::Policy::kOem));
|
||||
EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::SIGNATURE
|
||||
| PolicyFlags::ODM_PARTITION
|
||||
| PolicyFlags::OEM_PARTITION));
|
||||
|
||||
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/biz"));
|
||||
ASSERT_TRUE(search_result);
|
||||
ASSERT_TRUE(search_result.value().entry->overlayable_item);
|
||||
overlayable_item = search_result.value().entry->overlayable_item.value();
|
||||
EXPECT_THAT(overlayable_item.overlayable->name, Eq("Other"));
|
||||
EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kNone));
|
||||
EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::NONE));
|
||||
EXPECT_THAT(overlayable_item.comment, Eq("comment"));
|
||||
|
||||
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/fiz"));
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user