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

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

View File

@@ -36,18 +36,7 @@ cc_library {
], ],
host_supported: true, host_supported: true,
srcs: [ srcs: [
"libidmap2/BinaryStreamVisitor.cpp", "libidmap2/**/*.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",
], ],
export_include_dirs: ["include"], export_include_dirs: ["include"],
target: { target: {
@@ -61,6 +50,7 @@ cc_library {
"libcutils", "libcutils",
"libutils", "libutils",
"libziparchive", "libziparchive",
"libidmap2_policies",
], ],
}, },
host: { host: {
@@ -73,6 +63,37 @@ cc_library {
"libcutils", "libcutils",
"libutils", "libutils",
"libziparchive", "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", "libutils",
"libz", "libz",
"libziparchive", "libziparchive",
"libidmap2_policies",
], ],
}, },
host: { host: {
@@ -129,6 +151,7 @@ cc_test {
"liblog", "liblog",
"libutils", "libutils",
"libziparchive", "libziparchive",
"libidmap2_policies",
], ],
shared_libs: [ shared_libs: [
"libz", "libz",
@@ -162,6 +185,7 @@ cc_binary {
"libidmap2", "libidmap2",
"libutils", "libutils",
"libziparchive", "libziparchive",
"libidmap2_policies",
], ],
}, },
host: { host: {
@@ -173,12 +197,14 @@ cc_binary {
"liblog", "liblog",
"libutils", "libutils",
"libziparchive", "libziparchive",
"libidmap2_policies",
], ],
shared_libs: [ shared_libs: [
"libz", "libz",
], ],
}, },
}, },
} }
cc_binary { cc_binary {
@@ -199,6 +225,7 @@ cc_binary {
"libidmap2", "libidmap2",
"libutils", "libutils",
"libziparchive", "libziparchive",
"libidmap2_policies",
], ],
static_libs: [ static_libs: [
"libidmap2daidl", "libidmap2daidl",
@@ -231,3 +258,16 @@ filegroup {
], ],
path: "idmap2d/aidl", path: "idmap2d/aidl",
} }
aidl_interface {
name: "overlayable_policy_aidl",
srcs: [":overlayable_policy_aidl_files"],
}
filegroup {
name: "overlayable_policy_aidl_files",
srcs: [
"idmap2d/aidl/android/os/OverlayablePolicy.aidl",
],
path: "idmap2d/aidl",
}

View File

@@ -20,15 +20,14 @@
#include <fstream> #include <fstream>
#include <memory> #include <memory>
#include <ostream> #include <ostream>
#include <sstream>
#include <string>
#include <vector> #include <vector>
#include "androidfw/ResourceTypes.h"
#include "idmap2/BinaryStreamVisitor.h" #include "idmap2/BinaryStreamVisitor.h"
#include "idmap2/CommandLineOptions.h" #include "idmap2/CommandLineOptions.h"
#include "idmap2/FileUtils.h" #include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h" #include "idmap2/Idmap.h"
#include "idmap2/Policies.h" #include "idmap2/PolicyUtils.h"
#include "idmap2/SysTrace.h" #include "idmap2/SysTrace.h"
using android::ApkAssets; using android::ApkAssets;
@@ -36,14 +35,15 @@ using android::idmap2::BinaryStreamVisitor;
using android::idmap2::CommandLineOptions; using android::idmap2::CommandLineOptions;
using android::idmap2::Error; using android::idmap2::Error;
using android::idmap2::Idmap; using android::idmap2::Idmap;
using android::idmap2::PoliciesToBitmask;
using android::idmap2::PolicyBitmask;
using android::idmap2::PolicyFlags;
using android::idmap2::Result; using android::idmap2::Result;
using android::idmap2::Unit; using android::idmap2::Unit;
using android::idmap2::utils::kIdmapFilePermissionMask; using android::idmap2::utils::kIdmapFilePermissionMask;
using android::idmap2::utils::PoliciesToBitmaskResult;
using android::idmap2::utils::UidHasWriteAccessToPath; 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) { Result<Unit> Create(const std::vector<std::string>& args) {
SYSTRACE << "Create " << args; SYSTRACE << "Create " << args;
std::string target_apk_path; std::string target_apk_path;
@@ -78,7 +78,7 @@ Result<Unit> Create(const std::vector<std::string>& args) {
} }
PolicyBitmask fulfilled_policies = 0; PolicyBitmask fulfilled_policies = 0;
auto conv_result = PoliciesToBitmask(policies); auto conv_result = PoliciesToBitmaskResult(policies);
if (conv_result) { if (conv_result) {
fulfilled_policies |= *conv_result; fulfilled_policies |= *conv_result;
} else { } else {
@@ -86,7 +86,7 @@ Result<Unit> Create(const std::vector<std::string>& args) {
} }
if (fulfilled_policies == 0) { 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); const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);

View File

@@ -20,8 +20,6 @@
#include <fstream> #include <fstream>
#include <memory> #include <memory>
#include <ostream> #include <ostream>
#include <sstream>
#include <string>
#include <vector> #include <vector>
#include "android-base/stringprintf.h" #include "android-base/stringprintf.h"
@@ -30,6 +28,7 @@
#include "idmap2/FileUtils.h" #include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h" #include "idmap2/Idmap.h"
#include "idmap2/Policies.h" #include "idmap2/Policies.h"
#include "idmap2/PolicyUtils.h"
#include "idmap2/SysTrace.h" #include "idmap2/SysTrace.h"
#include "Commands.h" #include "Commands.h"
@@ -39,13 +38,11 @@ using android::idmap2::BinaryStreamVisitor;
using android::idmap2::CommandLineOptions; using android::idmap2::CommandLineOptions;
using android::idmap2::Error; using android::idmap2::Error;
using android::idmap2::Idmap; using android::idmap2::Idmap;
using android::idmap2::PoliciesToBitmask;
using android::idmap2::PolicyBitmask;
using android::idmap2::PolicyFlags;
using android::idmap2::Result; using android::idmap2::Result;
using android::idmap2::Unit; using android::idmap2::Unit;
using android::idmap2::utils::kIdmapCacheDir; using android::idmap2::utils::kIdmapCacheDir;
using android::idmap2::utils::kIdmapFilePermissionMask; using android::idmap2::utils::kIdmapFilePermissionMask;
using android::idmap2::utils::PoliciesToBitmaskResult;
using android::idmap2::utils::UidHasWriteAccessToPath; using android::idmap2::utils::UidHasWriteAccessToPath;
Result<Unit> CreateMultiple(const std::vector<std::string>& args) { 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; PolicyBitmask fulfilled_policies = 0;
auto conv_result = PoliciesToBitmask(policies); auto conv_result = PoliciesToBitmaskResult(policies);
if (conv_result) { if (conv_result) {
fulfilled_policies |= *conv_result; fulfilled_policies |= *conv_result;
} else { } else {
@@ -89,7 +86,7 @@ Result<Unit> CreateMultiple(const std::vector<std::string>& args) {
} }
if (fulfilled_policies == 0) { 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); const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);

View File

@@ -20,7 +20,6 @@
#include <memory> #include <memory>
#include <ostream> #include <ostream>
#include <set> #include <set>
#include <sstream>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
@@ -34,25 +33,24 @@
#include "idmap2/Result.h" #include "idmap2/Result.h"
#include "idmap2/SysTrace.h" #include "idmap2/SysTrace.h"
#include "idmap2/XmlParser.h" #include "idmap2/XmlParser.h"
#include "idmap2/ZipFile.h"
using android::idmap2::CommandLineOptions; using android::idmap2::CommandLineOptions;
using android::idmap2::Error; using android::idmap2::Error;
using android::idmap2::Idmap; 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::Result;
using android::idmap2::Unit; 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::ExtractOverlayManifestInfo;
using android::idmap2::utils::FindFiles; using android::idmap2::utils::FindFiles;
using android::idmap2::utils::OverlayManifestInfo; using android::idmap2::utils::OverlayManifestInfo;
using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
namespace { namespace {
struct InputOverlay { struct InputOverlay {

View File

@@ -33,7 +33,6 @@
#include "idmap2/BinaryStreamVisitor.h" #include "idmap2/BinaryStreamVisitor.h"
#include "idmap2/FileUtils.h" #include "idmap2/FileUtils.h"
#include "idmap2/Idmap.h" #include "idmap2/Idmap.h"
#include "idmap2/Policies.h"
#include "idmap2/SysTrace.h" #include "idmap2/SysTrace.h"
#include "utils/String8.h" #include "utils/String8.h"
@@ -42,11 +41,12 @@ using android::binder::Status;
using android::idmap2::BinaryStreamVisitor; using android::idmap2::BinaryStreamVisitor;
using android::idmap2::Idmap; using android::idmap2::Idmap;
using android::idmap2::IdmapHeader; using android::idmap2::IdmapHeader;
using android::idmap2::PolicyBitmask;
using android::idmap2::utils::kIdmapCacheDir; using android::idmap2::utils::kIdmapCacheDir;
using android::idmap2::utils::kIdmapFilePermissionMask; using android::idmap2::utils::kIdmapFilePermissionMask;
using android::idmap2::utils::UidHasWriteAccessToPath; using android::idmap2::utils::UidHasWriteAccessToPath;
using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
namespace { namespace {
Status ok() { Status ok() {

View File

@@ -20,14 +20,6 @@ package android.os;
* @hide * @hide
*/ */
interface IIdmap2 { 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); @utf8InCpp String getIdmapPath(@utf8InCpp String overlayApkPath, int userId);
boolean removeIdmap(@utf8InCpp String overlayApkPath, int userId); boolean removeIdmap(@utf8InCpp String overlayApkPath, int userId);
boolean verifyIdmap(@utf8InCpp String overlayApkPath, int fulfilledPolicies, boolean verifyIdmap(@utf8InCpp String overlayApkPath, int fulfilledPolicies,

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.os;
/**
* @see ResourcesTypes.h ResTable_overlayable_policy_header::PolicyFlags
* @hide
*/
interface OverlayablePolicy {
const int PUBLIC = 0x00000001;
const int SYSTEM_PARTITION = 0x00000002;
const int VENDOR_PARTITION = 0x00000004;
const int PRODUCT_PARTITION = 0x00000008;
const int SIGNATURE = 0x00000010;
const int ODM_PARTITION = 0x00000020;
const int OEM_PARTITION = 0x00000040;
const int ACTOR_SIGNATURE = 0x00000080;
}

View File

@@ -73,7 +73,6 @@
#include "androidfw/ApkAssets.h" #include "androidfw/ApkAssets.h"
#include "androidfw/ResourceTypes.h" #include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h" #include "androidfw/StringPiece.h"
#include "idmap2/Policies.h"
#include "idmap2/ResourceMapping.h" #include "idmap2/ResourceMapping.h"
namespace android::idmap2 { namespace android::idmap2 {

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef IDMAP2_INCLUDE_IDMAP2_POLICYUTILS_H_
#define IDMAP2_INCLUDE_IDMAP2_POLICYUTILS_H_
#include <string>
#include <vector>
#include "androidfw/ResourceTypes.h"
#include "idmap2/Policies.h"
#include "idmap2/Result.h"
using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
namespace android::idmap2::utils {
// Returns a Result object containing a policy flag bitmask built from a list of policy strings.
// On error will contain a human readable message listing the invalid policies.
Result<PolicyBitmask> PoliciesToBitmaskResult(const std::vector<std::string>& policies);
// Converts a bitmask of policy flags into a list of their string representation as would be written
// into XML
std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask);
} // namespace android::idmap2::utils
#endif // IDMAP2_INCLUDE_IDMAP2_POLICYUTILS_H_

View File

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

View File

@@ -1,88 +0,0 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "idmap2/Policies.h"
#include <iterator>
#include <string>
#include <unordered_map>
#include <vector>
#include "androidfw/ResourceTypes.h"
#include "idmap2/Idmap.h"
#include "idmap2/Result.h"
namespace android::idmap2 {
Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies) {
static const std::unordered_map<android::StringPiece, PolicyFlags> kStringToFlag = {
{kPolicyOdm, PolicyFlags::POLICY_ODM_PARTITION},
{kPolicyOem, PolicyFlags::POLICY_OEM_PARTITION},
{kPolicyPublic, PolicyFlags::POLICY_PUBLIC},
{kPolicyProduct, PolicyFlags::POLICY_PRODUCT_PARTITION},
{kPolicySignature, PolicyFlags::POLICY_SIGNATURE},
{kPolicySystem, PolicyFlags::POLICY_SYSTEM_PARTITION},
{kPolicyVendor, PolicyFlags::POLICY_VENDOR_PARTITION},
};
PolicyBitmask bitmask = 0;
for (const std::string& policy : policies) {
const auto iter = kStringToFlag.find(policy);
if (iter != kStringToFlag.end()) {
bitmask |= iter->second;
} else {
return Error("unknown policy \"%s\"", policy.c_str());
}
}
return Result<PolicyBitmask>(bitmask);
}
std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask) {
std::vector<std::string> policies;
if ((bitmask & PolicyFlags::POLICY_ODM_PARTITION) != 0) {
policies.emplace_back(kPolicyOdm);
}
if ((bitmask & PolicyFlags::POLICY_OEM_PARTITION) != 0) {
policies.emplace_back(kPolicyOem);
}
if ((bitmask & PolicyFlags::POLICY_PUBLIC) != 0) {
policies.emplace_back(kPolicyPublic);
}
if ((bitmask & PolicyFlags::POLICY_PRODUCT_PARTITION) != 0) {
policies.emplace_back(kPolicyProduct);
}
if ((bitmask & PolicyFlags::POLICY_SIGNATURE) != 0) {
policies.emplace_back(kPolicySignature);
}
if ((bitmask & PolicyFlags::POLICY_SYSTEM_PARTITION) != 0) {
policies.emplace_back(kPolicySystem);
}
if ((bitmask & PolicyFlags::POLICY_VENDOR_PARTITION) != 0) {
policies.emplace_back(kPolicyVendor);
}
return policies;
}
} // namespace android::idmap2

View File

@@ -0,0 +1,61 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "include/idmap2/PolicyUtils.h"
#include <sstream>
#include "android-base/strings.h"
#include "idmap2/Policies.h"
using android::idmap2::policy::kPolicyStringToFlag;
namespace android::idmap2::utils {
Result<PolicyBitmask> PoliciesToBitmaskResult(const std::vector<std::string>& policies) {
std::vector<std::string> unknown_policies;
PolicyBitmask bitmask = 0;
for (const std::string& policy : policies) {
const auto result = std::find_if(kPolicyStringToFlag.begin(), kPolicyStringToFlag.end(),
[policy](const auto& it) { return policy == it.first; });
if (result != kPolicyStringToFlag.end()) {
bitmask |= result->second;
} else {
unknown_policies.emplace_back(policy.empty() ? "empty" : policy);
}
}
if (unknown_policies.empty()) {
return Result<PolicyBitmask>(bitmask);
}
auto prefix = unknown_policies.size() == 1 ? "policy" : "policies";
return Error("unknown %s: \"%s\"", prefix, android::base::Join(unknown_policies, ",").c_str());
}
std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask) {
std::vector<std::string> policies;
for (const auto& policy : kPolicyStringToFlag) {
if ((bitmask & policy.second) != 0) {
policies.emplace_back(policy.first.to_string());
}
}
return policies;
}
} // namespace android::idmap2::utils

View File

@@ -24,11 +24,16 @@
#include <vector> #include <vector>
#include "android-base/stringprintf.h" #include "android-base/stringprintf.h"
#include "androidfw/ResourceTypes.h"
#include "idmap2/PolicyUtils.h"
#include "idmap2/ResourceUtils.h" #include "idmap2/ResourceUtils.h"
using android::base::StringPrintf; using android::base::StringPrintf;
using android::idmap2::utils::BitmaskToPolicies;
using android::idmap2::utils::IsReference; using android::idmap2::utils::IsReference;
using android::idmap2::utils::ResToTypeEntryName; using android::idmap2::utils::ResToTypeEntryName;
using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace android::idmap2 { namespace android::idmap2 {
@@ -55,9 +60,8 @@ Result<Unit> CheckOverlayable(const LoadedPackage& target_package,
const PolicyBitmask& fulfilled_policies, const PolicyBitmask& fulfilled_policies,
const ResourceId& target_resource) { const ResourceId& target_resource) {
static constexpr const PolicyBitmask sDefaultPolicies = static constexpr const PolicyBitmask sDefaultPolicies =
PolicyFlags::POLICY_ODM_PARTITION | PolicyFlags::POLICY_OEM_PARTITION | PolicyFlags::ODM_PARTITION | PolicyFlags::OEM_PARTITION | PolicyFlags::SYSTEM_PARTITION |
PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION | PolicyFlags::VENDOR_PARTITION | PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE;
PolicyFlags::POLICY_PRODUCT_PARTITION | PolicyFlags::POLICY_SIGNATURE;
// If the resource does not have an overlayable definition, allow the resource to be overlaid if // If the resource does not have an overlayable definition, allow the resource to be overlaid if
// the overlay is preinstalled or signed with the same signature as the target. // the overlay is preinstalled or signed with the same signature as the target.

View File

@@ -14,18 +14,22 @@
* limitations under the License. * 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_ #ifndef IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
#define IDMAP2_INCLUDE_IDMAP2_POLICIES_H_ #define IDMAP2_INCLUDE_IDMAP2_POLICIES_H_
namespace android::idmap2 { #include <array>
#include <string>
#include <vector>
#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace android::idmap2::policy {
constexpr const char* kPolicyActor = "actor";
constexpr const char* kPolicyOdm = "odm"; constexpr const char* kPolicyOdm = "odm";
constexpr const char* kPolicyOem = "oem"; constexpr const char* kPolicyOem = "oem";
constexpr const char* kPolicyProduct = "product"; constexpr const char* kPolicyProduct = "product";
@@ -34,15 +38,16 @@ constexpr const char* kPolicySignature = "signature";
constexpr const char* kPolicySystem = "system"; constexpr const char* kPolicySystem = "system";
constexpr const char* kPolicyVendor = "vendor"; constexpr const char* kPolicyVendor = "vendor";
using PolicyFlags = ResTable_overlayable_policy_header::PolicyFlags; inline static const std::array<std::pair<StringPiece, PolicyFlags>, 8> kPolicyStringToFlag = {
using PolicyBitmask = uint32_t; std::pair{kPolicyActor, PolicyFlags::ACTOR_SIGNATURE},
{kPolicyOdm, PolicyFlags::ODM_PARTITION},
// Parses the string representations of policies into a bitmask. {kPolicyOem, PolicyFlags::OEM_PARTITION},
Result<PolicyBitmask> PoliciesToBitmask(const std::vector<std::string>& policies); {kPolicyProduct, PolicyFlags::PRODUCT_PARTITION},
{kPolicyPublic, PolicyFlags::PUBLIC},
// Retrieves the string representations of policies in the bitmask. {kPolicySignature, PolicyFlags::SIGNATURE},
std::vector<std::string> BitmaskToPolicies(const PolicyBitmask& bitmask); {kPolicySystem, PolicyFlags::SYSTEM_PARTITION},
{kPolicyVendor, PolicyFlags::VENDOR_PARTITION},
} // namespace android::idmap2 };
} // namespace android::idmap2::policy
#endif // IDMAP2_INCLUDE_IDMAP2_POLICIES_H_ #endif // IDMAP2_INCLUDE_IDMAP2_POLICIES_H_

View File

@@ -34,6 +34,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "R.h"
#include "TestHelpers.h" #include "TestHelpers.h"
#include "androidfw/PosixUtils.h" #include "androidfw/PosixUtils.h"
#include "gmock/gmock.h" #include "gmock/gmock.h"
@@ -127,10 +128,14 @@ TEST_F(Idmap2BinaryTests, Dump) {
// clang-format on // clang-format on
ASSERT_THAT(result, NotNull()); ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr; 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(R::target::integer::literal::int1 + " -> 0x7f010000 integer/int1"),
ASSERT_NE(result->stdout.find("0x7f02000c -> 0x7f020000 string/str1"), std::string::npos); std::string::npos);
ASSERT_NE(result->stdout.find("0x7f02000e -> 0x7f020001 string/str3"), std::string::npos); ASSERT_NE(result->stdout.find(R::target::string::literal::str1 + " -> 0x7f020000 string/str1"),
ASSERT_NE(result->stdout.find("0x7f02000f -> 0x7f020002 string/str4"), std::string::npos); 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 // clang-format off
result = ExecuteBinary({"idmap2", result = ExecuteBinary({"idmap2",
@@ -297,7 +302,7 @@ TEST_F(Idmap2BinaryTests, Lookup) {
"lookup", "lookup",
"--idmap-path", GetIdmapPath(), "--idmap-path", GetIdmapPath(),
"--config", "", "--config", "",
"--resid", "0x7f02000c"}); // string/str1 "--resid", R::target::string::literal::str1});
// clang-format on // clang-format on
ASSERT_THAT(result, NotNull()); ASSERT_THAT(result, NotNull());
ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr; ASSERT_EQ(result->status, EXIT_SUCCESS) << result->stderr;

View File

@@ -22,6 +22,8 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "R.h"
#include "TestConstants.h"
#include "TestHelpers.h" #include "TestHelpers.h"
#include "android-base/macros.h" #include "android-base/macros.h"
#include "androidfw/ApkAssets.h" #include "androidfw/ApkAssets.h"
@@ -36,6 +38,8 @@ using android::Res_value;
using ::testing::IsNull; using ::testing::IsNull;
using ::testing::NotNull; using ::testing::NotNull;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace android::idmap2 { namespace android::idmap2 {
#define ASSERT_TARGET_ENTRY(entry, target_resid, type, value) \ #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); std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
ASSERT_THAT(overlay_apk, NotNull()); 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); /* enforce_overlayable */ true);
ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage(); ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
auto& idmap = *idmap_result; auto& idmap = *idmap_result;
@@ -177,8 +181,8 @@ TEST(IdmapTests, CreateIdmapHeaderFromApkAssets) {
ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_THAT(idmap->GetHeader(), NotNull());
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x03U); ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x03U);
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x76a20829); ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), android::idmap2::TestConstants::TARGET_CRC);
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xc054fb26); ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), android::idmap2::TestConstants::OVERLAY_CRC);
ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path); ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_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); std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
ASSERT_THAT(overlay_apk, NotNull()); 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); /* enforce_overlayable */ true);
ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage(); ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
auto& idmap = *idmap_result; auto& idmap = *idmap_result;
@@ -234,17 +238,21 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssets) {
const auto& target_entries = data->GetTargetEntries(); const auto& target_entries = data->GetTargetEntries();
ASSERT_EQ(target_entries.size(), 4U); ASSERT_EQ(target_entries.size(), 4U);
ASSERT_TARGET_ENTRY(target_entries[0], 0x7f010000, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f010000); ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1,
ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020000); Res_value::TYPE_DYNAMIC_REFERENCE, R::overlay::integer::int1);
ASSERT_TARGET_ENTRY(target_entries[2], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001); ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, Res_value::TYPE_DYNAMIC_REFERENCE,
ASSERT_TARGET_ENTRY(target_entries[3], 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020002); 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(); const auto& overlay_entries = data->GetOverlayEntries();
ASSERT_EQ(target_entries.size(), 4U); ASSERT_EQ(target_entries.size(), 4U);
ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x7f010000, 0x7f010000); ASSERT_OVERLAY_ENTRY(overlay_entries[0], R::overlay::integer::int1, R::target::integer::int1);
ASSERT_OVERLAY_ENTRY(overlay_entries[1], 0x7f020000, 0x7f02000c); ASSERT_OVERLAY_ENTRY(overlay_entries[1], R::overlay::string::str1, R::target::string::str1);
ASSERT_OVERLAY_ENTRY(overlay_entries[2], 0x7f020001, 0x7f02000e); ASSERT_OVERLAY_ENTRY(overlay_entries[2], R::overlay::string::str3, R::target::string::str3);
ASSERT_OVERLAY_ENTRY(overlay_entries[3], 0x7f020002, 0x7f02000f); ASSERT_OVERLAY_ENTRY(overlay_entries[3], R::overlay::string::str4, R::target::string::str4);
} }
TEST(IdmapTests, CreateIdmapDataFromApkAssetsSharedLibOverlay) { TEST(IdmapTests, CreateIdmapDataFromApkAssetsSharedLibOverlay) {
@@ -257,7 +265,7 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssetsSharedLibOverlay) {
std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
ASSERT_THAT(overlay_apk, NotNull()); 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); /* enforce_overlayable */ true);
ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage(); ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
auto& idmap = *idmap_result; auto& idmap = *idmap_result;
@@ -271,17 +279,25 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssetsSharedLibOverlay) {
const auto& target_entries = data->GetTargetEntries(); const auto& target_entries = data->GetTargetEntries();
ASSERT_EQ(target_entries.size(), 4U); ASSERT_EQ(target_entries.size(), 4U);
ASSERT_TARGET_ENTRY(target_entries[0], 0x7f010000, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00010000); ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1,
ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020000); Res_value::TYPE_DYNAMIC_REFERENCE, R::overlay_shared::integer::int1);
ASSERT_TARGET_ENTRY(target_entries[2], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020001); ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, Res_value::TYPE_DYNAMIC_REFERENCE,
ASSERT_TARGET_ENTRY(target_entries[3], 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020002); R::overlay_shared::string::str1);
ASSERT_TARGET_ENTRY(target_entries[2], R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
R::overlay_shared::string::str3);
ASSERT_TARGET_ENTRY(target_entries[3], R::target::string::str4, Res_value::TYPE_DYNAMIC_REFERENCE,
R::overlay_shared::string::str4);
const auto& overlay_entries = data->GetOverlayEntries(); const auto& overlay_entries = data->GetOverlayEntries();
ASSERT_EQ(target_entries.size(), 4U); ASSERT_EQ(target_entries.size(), 4U);
ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x00010000, 0x7f010000); ASSERT_OVERLAY_ENTRY(overlay_entries[0], R::overlay_shared::integer::int1,
ASSERT_OVERLAY_ENTRY(overlay_entries[1], 0x00020000, 0x7f02000c); R::target::integer::int1);
ASSERT_OVERLAY_ENTRY(overlay_entries[2], 0x00020001, 0x7f02000e); ASSERT_OVERLAY_ENTRY(overlay_entries[1], R::overlay_shared::string::str1,
ASSERT_OVERLAY_ENTRY(overlay_entries[3], 0x00020002, 0x7f02000f); R::target::string::str1);
ASSERT_OVERLAY_ENTRY(overlay_entries[2], R::overlay_shared::string::str3,
R::target::string::str3);
ASSERT_OVERLAY_ENTRY(overlay_entries[3], R::overlay_shared::string::str4,
R::target::string::str4);
} }
TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) { TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) {
@@ -290,7 +306,7 @@ TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) {
info.target_name = "TestResources"; info.target_name = "TestResources";
info.resource_mapping = 0x7f030001; // xml/overlays_different_packages info.resource_mapping = 0x7f030001; // xml/overlays_different_packages
auto idmap_data = TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk", info, auto idmap_data = TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk", info,
PolicyFlags::POLICY_PUBLIC, PolicyFlags::PUBLIC,
/* enforce_overlayable */ false); /* enforce_overlayable */ false);
ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage(); ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage();
@@ -298,14 +314,14 @@ TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) {
const auto& target_entries = data->GetTargetEntries(); const auto& target_entries = data->GetTargetEntries();
ASSERT_EQ(target_entries.size(), 2U); ASSERT_EQ(target_entries.size(), 2U);
ASSERT_TARGET_ENTRY(target_entries[0], 0x7f02000c, Res_value::TYPE_REFERENCE, ASSERT_TARGET_ENTRY(target_entries[0], R::target::string::str1, Res_value::TYPE_REFERENCE,
0x0104000a); // string/str1 -> android:string/ok 0x0104000a); // -> android:string/ok
ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
0x7f020001); // string/str3 -> string/str4 R::overlay::string::str3);
const auto& overlay_entries = data->GetOverlayEntries(); const auto& overlay_entries = data->GetOverlayEntries();
ASSERT_EQ(overlay_entries.size(), 1U); 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) { TEST(IdmapTests, CreateIdmapDataInlineResources) {
@@ -314,7 +330,7 @@ TEST(IdmapTests, CreateIdmapDataInlineResources) {
info.target_name = "TestResources"; info.target_name = "TestResources";
info.resource_mapping = 0x7f030002; // xml/overlays_inline info.resource_mapping = 0x7f030002; // xml/overlays_inline
auto idmap_data = TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk", info, auto idmap_data = TestIdmapDataFromApkAssets("/target/target.apk", "/overlay/overlay.apk", info,
PolicyFlags::POLICY_PUBLIC, PolicyFlags::PUBLIC,
/* enforce_overlayable */ false); /* enforce_overlayable */ false);
ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage(); ASSERT_TRUE(idmap_data) << idmap_data.GetErrorMessage();
@@ -323,10 +339,10 @@ TEST(IdmapTests, CreateIdmapDataInlineResources) {
constexpr size_t overlay_string_pool_size = 8U; constexpr size_t overlay_string_pool_size = 8U;
const auto& target_entries = data->GetTargetEntries(); const auto& target_entries = data->GetTargetEntries();
ASSERT_EQ(target_entries.size(), 2U); ASSERT_EQ(target_entries.size(), 2U);
ASSERT_TARGET_ENTRY(target_entries[0], 0x7f010000, Res_value::TYPE_INT_DEC, ASSERT_TARGET_ENTRY(target_entries[0], R::target::integer::int1, Res_value::TYPE_INT_DEC,
73U); // integer/int1 -> 73 73U); // -> 73
ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_STRING, ASSERT_TARGET_ENTRY(target_entries[1], R::target::string::str1, Res_value::TYPE_STRING,
overlay_string_pool_size + 0U); // string/str1 -> "Hello World" overlay_string_pool_size + 0U); // -> "Hello World"
const auto& overlay_entries = data->GetOverlayEntries(); const auto& overlay_entries = data->GetOverlayEntries();
ASSERT_EQ(overlay_entries.size(), 0U); ASSERT_EQ(overlay_entries.size(), 0U);
@@ -346,7 +362,7 @@ TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
ASSERT_THAT(overlay_apk, NotNull()); 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); /* enforce_overlayable */ true);
ASSERT_FALSE(result); ASSERT_FALSE(result);
} }
@@ -362,7 +378,7 @@ TEST(IdmapTests, IdmapHeaderIsUpToDate) {
std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
ASSERT_THAT(overlay_apk, NotNull()); 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); /* enforce_overlayable */ true);
ASSERT_TRUE(result); ASSERT_TRUE(result);
const auto idmap = std::move(*result); const auto idmap = std::move(*result);

View File

@@ -17,76 +17,96 @@
#include <string> #include <string>
#include "TestHelpers.h" #include "TestHelpers.h"
#include "androidfw/ResourceTypes.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "idmap2/Policies.h" #include "idmap2/PolicyUtils.h"
using android::idmap2::PolicyBitmask; using android::idmap2::utils::BitmaskToPolicies;
using android::idmap2::PolicyFlags; using android::idmap2::utils::PoliciesToBitmaskResult;
using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace android::idmap2 { namespace android::idmap2 {
TEST(PoliciesTests, PoliciesToBitmasks) { TEST(PoliciesTests, PoliciesToBitmaskResults) {
const auto bitmask1 = PoliciesToBitmask({"system"}); const auto bitmask1 = PoliciesToBitmaskResult({"system"});
ASSERT_TRUE(bitmask1); 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_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_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_TRUE(bitmask4);
ASSERT_EQ(*bitmask4, PolicyFlags::POLICY_ODM_PARTITION | PolicyFlags::POLICY_OEM_PARTITION | ASSERT_EQ(*bitmask4, PolicyFlags::ODM_PARTITION | PolicyFlags::OEM_PARTITION |
PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_PRODUCT_PARTITION | PolicyFlags::PUBLIC | PolicyFlags::PRODUCT_PARTITION |
PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::SYSTEM_PARTITION | PolicyFlags::VENDOR_PARTITION);
PolicyFlags::POLICY_VENDOR_PARTITION);
const auto bitmask5 = PoliciesToBitmask({"system", "system", "system"}); const auto bitmask5 = PoliciesToBitmaskResult({"system", "system", "system"});
ASSERT_TRUE(bitmask5); 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); ASSERT_FALSE(bitmask6);
const auto bitmask7 = PoliciesToBitmask({"foo"}); const auto bitmask7 = PoliciesToBitmaskResult({"foo"});
ASSERT_FALSE(bitmask7); ASSERT_FALSE(bitmask7);
const auto bitmask8 = PoliciesToBitmask({"system", "foo"}); const auto bitmask8 = PoliciesToBitmaskResult({"system", "foo"});
ASSERT_FALSE(bitmask8); ASSERT_FALSE(bitmask8);
const auto bitmask9 = PoliciesToBitmask({"system", ""}); const auto bitmask9 = PoliciesToBitmaskResult({"system", ""});
ASSERT_FALSE(bitmask9); ASSERT_FALSE(bitmask9);
const auto bitmask10 = PoliciesToBitmask({"system "}); const auto bitmask10 = PoliciesToBitmaskResult({"system "});
ASSERT_FALSE(bitmask10); ASSERT_FALSE(bitmask10);
const auto bitmask11 = PoliciesToBitmaskResult({"signature"});
ASSERT_TRUE(bitmask11);
ASSERT_EQ(*bitmask11, PolicyFlags::SIGNATURE);
const auto bitmask12 = PoliciesToBitmaskResult({"actor"});
ASSERT_TRUE(bitmask12);
ASSERT_EQ(*bitmask12, PolicyFlags::ACTOR_SIGNATURE);
} }
TEST(PoliciesTests, BitmaskToPolicies) { TEST(PoliciesTests, BitmaskToPolicies) {
const auto policies1 = BitmaskToPolicies(PolicyFlags::POLICY_PUBLIC); const auto policies1 = BitmaskToPolicies(PolicyFlags::PUBLIC);
ASSERT_EQ(1, policies1.size()); ASSERT_EQ(1, policies1.size());
ASSERT_EQ(policies1[0], "public"); ASSERT_EQ(policies1[0], "public");
const auto policies2 = BitmaskToPolicies(PolicyFlags::POLICY_SYSTEM_PARTITION | const auto policies2 =
PolicyFlags::POLICY_VENDOR_PARTITION); BitmaskToPolicies(PolicyFlags::SYSTEM_PARTITION | PolicyFlags::VENDOR_PARTITION);
ASSERT_EQ(2, policies2.size()); ASSERT_EQ(2, policies2.size());
ASSERT_EQ(policies2[0], "system"); ASSERT_EQ(policies2[0], "system");
ASSERT_EQ(policies2[1], "vendor"); ASSERT_EQ(policies2[1], "vendor");
const auto policies3 = BitmaskToPolicies( const auto policies3 =
PolicyFlags::POLICY_ODM_PARTITION | PolicyFlags::POLICY_OEM_PARTITION | BitmaskToPolicies(PolicyFlags::ODM_PARTITION | PolicyFlags::OEM_PARTITION |
PolicyFlags::POLICY_PUBLIC | PolicyFlags::POLICY_PRODUCT_PARTITION | PolicyFlags::PUBLIC | PolicyFlags::PRODUCT_PARTITION |
PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_VENDOR_PARTITION); PolicyFlags::SYSTEM_PARTITION | PolicyFlags::VENDOR_PARTITION);
ASSERT_EQ(2, policies2.size()); ASSERT_EQ(2, policies2.size());
ASSERT_EQ(policies3[0], "odm"); ASSERT_EQ(policies3[0], "odm");
ASSERT_EQ(policies3[1], "oem"); ASSERT_EQ(policies3[1], "oem");
ASSERT_EQ(policies3[2], "public"); ASSERT_EQ(policies3[2], "product");
ASSERT_EQ(policies3[3], "product"); ASSERT_EQ(policies3[3], "public");
ASSERT_EQ(policies3[4], "system"); ASSERT_EQ(policies3[4], "system");
ASSERT_EQ(policies3[5], "vendor"); ASSERT_EQ(policies3[5], "vendor");
const auto policies4 = BitmaskToPolicies(PolicyFlags::SIGNATURE);
ASSERT_EQ(1, policies4.size());
ASSERT_EQ(policies4[0], "signature");
const auto policies5 = BitmaskToPolicies(PolicyFlags::ACTOR_SIGNATURE);
ASSERT_EQ(1, policies5.size());
ASSERT_EQ(policies5[0], "actor");
} }
} // namespace android::idmap2 } // namespace android::idmap2

View File

@@ -18,19 +18,22 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#include "R.h"
#include "TestHelpers.h" #include "TestHelpers.h"
#include "androidfw/ApkAssets.h" #include "androidfw/ApkAssets.h"
#include "androidfw/Idmap.h" #include "androidfw/Idmap.h"
#include "androidfw/ResourceTypes.h"
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "idmap2/Idmap.h" #include "idmap2/Idmap.h"
#include "idmap2/Policies.h"
#include "idmap2/PrettyPrintVisitor.h" #include "idmap2/PrettyPrintVisitor.h"
using ::testing::NotNull; using ::testing::NotNull;
using android::ApkAssets; 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 { namespace android::idmap2 {
@@ -43,7 +46,7 @@ TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitor) {
std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path); std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
ASSERT_THAT(overlay_apk, NotNull()); 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); /* enforce_overlayable */ true);
ASSERT_TRUE(idmap); 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("target apk path : "), std::string::npos);
ASSERT_NE(stream.str().find("overlay 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) { TEST(PrettyPrintVisitorTests, CreatePrettyPrintVisitorWithoutAccessToApks) {

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

@@ -0,0 +1,107 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef IDMAP2_TESTS_R_H
#define IDMAP2_TESTS_R_H
#include <idmap2/ResourceUtils.h>
namespace android::idmap2 {
static std::string hexify(ResourceId id) {
std::stringstream stream;
stream << std::hex << static_cast<uint32_t>(id);
return stream.str();
}
// clang-format off
namespace R::target {
namespace integer {
constexpr ResourceId int1 = 0x7f010000;
namespace literal {
inline const std::string int1 = hexify(R::target::integer::int1);
}
}
namespace string {
constexpr ResourceId not_overlayable = 0x7f020003;
constexpr ResourceId other = 0x7f020004;
constexpr ResourceId policy_actor = 0x7f020005;
constexpr ResourceId policy_odm = 0x7f020006;
constexpr ResourceId policy_oem = 0x7f020007;
constexpr ResourceId policy_product = 0x7f020008;
constexpr ResourceId policy_public = 0x7f020009;
constexpr ResourceId policy_signature = 0x7f02000a;
constexpr ResourceId policy_system = 0x7f02000b;
constexpr ResourceId policy_system_vendor = 0x7f02000c;
constexpr ResourceId str1 = 0x7f02000d;
constexpr ResourceId str3 = 0x7f02000f;
constexpr ResourceId str4 = 0x7f020010;
namespace literal {
inline const std::string str1 = hexify(R::target::string::str1);
inline const std::string str3 = hexify(R::target::string::str3);
inline const std::string str4 = hexify(R::target::string::str4);
}
}
}
namespace R::overlay {
namespace integer {
constexpr ResourceId int1 = 0x7f010000;
}
namespace string {
constexpr ResourceId str1 = 0x7f020000;
constexpr ResourceId str3 = 0x7f020001;
constexpr ResourceId str4 = 0x7f020002;
}
}
namespace R::overlay_shared {
namespace integer {
constexpr ResourceId int1 = 0x00010000;
}
namespace string {
constexpr ResourceId str1 = 0x00020000;
constexpr ResourceId str3 = 0x00020001;
constexpr ResourceId str4 = 0x00020002;
}
}
namespace R::system_overlay::string {
constexpr ResourceId policy_public = 0x7f010000;
constexpr ResourceId policy_system = 0x7f010001;
constexpr ResourceId policy_system_vendor = 0x7f010002;
}
namespace R::system_overlay_invalid::string {
constexpr ResourceId not_overlayable = 0x7f010000;
constexpr ResourceId other = 0x7f010001;
constexpr ResourceId policy_actor = 0x7f010002;
constexpr ResourceId policy_odm = 0x7f010003;
constexpr ResourceId policy_oem = 0x7f010004;
constexpr ResourceId policy_product = 0x7f010005;
constexpr ResourceId policy_public = 0x7f010006;
constexpr ResourceId policy_signature = 0x7f010007;
constexpr ResourceId policy_system = 0x7f010008;
constexpr ResourceId policy_system_vendor = 0x7f010009;
};
// clang-format on
} // namespace android::idmap2
#endif // IDMAP2_TESTS_R_H

View File

@@ -20,14 +20,20 @@
#include <sstream> #include <sstream>
#include <string> #include <string>
#include "TestConstants.h"
#include "TestHelpers.h" #include "TestHelpers.h"
#include "android-base/stringprintf.h"
#include "androidfw/ResourceTypes.h"
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "idmap2/Idmap.h" #include "idmap2/Idmap.h"
#include "idmap2/RawPrintVisitor.h" #include "idmap2/RawPrintVisitor.h"
using android::base::StringPrintf;
using ::testing::NotNull; using ::testing::NotNull;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace android::idmap2 { namespace android::idmap2 {
#define ASSERT_CONTAINS_REGEX(pattern, str) \ #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); std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
ASSERT_THAT(overlay_apk, NotNull()); 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); /* enforce_overlayable */ true);
ASSERT_TRUE(idmap); ASSERT_TRUE(idmap);
@@ -59,8 +65,12 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
#define ADDRESS "[0-9a-f]{8}: " #define ADDRESS "[0-9a-f]{8}: "
ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000003 version\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(
ASSERT_CONTAINS_REGEX(ADDRESS "c054fb26 overlay crc\n", stream.str()); 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 target package id\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS " 7f overlay package id\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS " 7f overlay package id\n", stream.str());
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 target entry count\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000004 target entry count\n", stream.str());

View File

@@ -22,7 +22,9 @@
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "R.h"
#include "TestHelpers.h" #include "TestHelpers.h"
#include "androidfw/ResourceTypes.h"
#include "gmock/gmock.h" #include "gmock/gmock.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "idmap2/LogInfo.h" #include "idmap2/LogInfo.h"
@@ -31,6 +33,8 @@
using android::Res_value; using android::Res_value;
using android::idmap2::utils::ExtractOverlayManifestInfo; using android::idmap2::utils::ExtractOverlayManifestInfo;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace android::idmap2 { namespace android::idmap2 {
#define ASSERT_RESULT(r) \ #define ASSERT_RESULT(r) \
@@ -106,20 +110,20 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsLegacy) {
info.target_name = "TestResources"; info.target_name = "TestResources";
info.resource_mapping = 0U; // no xml info.resource_mapping = 0U; // no xml
auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info, auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
PolicyFlags::POLICY_PUBLIC, PolicyFlags::PUBLIC,
/* enforce_overlayable */ false); /* enforce_overlayable */ false);
ASSERT_TRUE(resources) << resources.GetErrorMessage(); ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources; auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U); ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_REFERENCE, 0x7f010000, ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // integer/int1 R::overlay::integer::int1, false /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x7f020000, ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/str1 R::overlay::string::str1, false /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_REFERENCE, 0x7f020001, ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/str3 R::overlay::string::str3, false /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_REFERENCE, 0x7f020002, ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/str4 R::overlay::string::str4, false /* rewrite */));
} }
TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) { TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) {
@@ -128,18 +132,18 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsNonMatchingNames) {
info.target_name = "TestResources"; info.target_name = "TestResources";
info.resource_mapping = 0x7f030003; // xml/overlays_swap info.resource_mapping = 0x7f030003; // xml/overlays_swap
auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info, auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
PolicyFlags::POLICY_PUBLIC, PolicyFlags::PUBLIC,
/* enforce_overlayable */ false); /* enforce_overlayable */ false);
ASSERT_TRUE(resources) << resources.GetErrorMessage(); ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources; auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U); ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020002, ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_DYNAMIC_REFERENCE,
true /* rewrite */)); // string/str1 -> string/str4 R::overlay::string::str4, true /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020000, ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
true /* rewrite */)); // string/str3 -> string/str1 R::overlay::string::str1, true /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001, ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_DYNAMIC_REFERENCE,
true /* rewrite */)); // string/str4 -> string/str3 R::overlay::string::str3, true /* rewrite */));
} }
TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) { TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) {
@@ -148,17 +152,17 @@ TEST(ResourceMappingTests, DoNotRewriteNonOverlayResourceId) {
info.target_name = "TestResources"; info.target_name = "TestResources";
info.resource_mapping = 0x7f030001; // xml/overlays_different_packages info.resource_mapping = 0x7f030001; // xml/overlays_different_packages
auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info, auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
PolicyFlags::POLICY_PUBLIC, PolicyFlags::PUBLIC,
/* enforce_overlayable */ false); /* enforce_overlayable */ false);
ASSERT_TRUE(resources) << resources.GetErrorMessage(); ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources; auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U); ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
ASSERT_EQ(res.GetOverlayToTargetMap().size(), 1U); ASSERT_EQ(res.GetOverlayToTargetMap().size(), 1U);
ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x0104000a, ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE, 0x0104000a,
false /* rewrite */)); // string/str1 -> android:string/ok false /* rewrite */)); // -> android:string/ok
ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x7f020001, ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_DYNAMIC_REFERENCE,
true /* rewrite */)); // string/str3 -> string/str4 0x7f020001, true /* rewrite */));
} }
TEST(ResourceMappingTests, InlineResources) { TEST(ResourceMappingTests, InlineResources) {
@@ -167,7 +171,7 @@ TEST(ResourceMappingTests, InlineResources) {
info.target_name = "TestResources"; info.target_name = "TestResources";
info.resource_mapping = 0x7f030002; // xml/overlays_inline info.resource_mapping = 0x7f030002; // xml/overlays_inline
auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info, auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay.apk", info,
PolicyFlags::POLICY_PUBLIC, PolicyFlags::PUBLIC,
/* enforce_overlayable */ false); /* enforce_overlayable */ false);
constexpr size_t overlay_string_pool_size = 8U; constexpr size_t overlay_string_pool_size = 8U;
@@ -175,108 +179,120 @@ TEST(ResourceMappingTests, InlineResources) {
auto& res = *resources; auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U); ASSERT_EQ(res.GetTargetToOverlayMap().size(), 2U);
ASSERT_EQ(res.GetOverlayToTargetMap().size(), 0U); 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, overlay_string_pool_size + 0U,
false /* rewrite */)); // string/str1 -> "Hello World" false /* rewrite */)); // -> "Hello World"
ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_INT_DEC, 73U, ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_INT_DEC, 73U,
false /* rewrite */)); // string/str1 -> "Hello World" false /* rewrite */)); // -> 73
} }
TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublic) { TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublic) {
auto resources = auto resources =
TestGetResourceMapping("/target/target.apk", "/system-overlay/system-overlay.apk", TestGetResourceMapping("/target/target.apk", "/system-overlay/system-overlay.apk",
PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC, PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC,
/* enforce_overlayable */ true); /* enforce_overlayable */ true);
ASSERT_TRUE(resources) << resources.GetErrorMessage(); ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources; auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U); ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010000, ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/policy_public R::system_overlay::string::policy_public, false /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010001, ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/policy_system R::system_overlay::string::policy_system, false /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010002, ASSERT_RESULT(
false /* rewrite */)); // string/policy_system_vendor 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 // 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. // overlay does not fulfill must not map to overlay resources.
TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) { TEST(ResourceMappingTests, CreateIdmapFromApkAssetsPolicySystemPublicInvalid) {
auto resources = TestGetResourceMapping( auto resources = TestGetResourceMapping("/target/target.apk",
"/target/target.apk", "/system-overlay-invalid/system-overlay-invalid.apk", "/system-overlay-invalid/system-overlay-invalid.apk",
PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC, PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC,
/* enforce_overlayable */ true); /* enforce_overlayable */ true);
ASSERT_TRUE(resources) << resources.GetErrorMessage(); ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources; auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U); ASSERT_EQ(res.GetTargetToOverlayMap().size(), 3U);
ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005, ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/policy_public R::system_overlay_invalid::string::policy_public,
ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007, false /* rewrite */));
false /* rewrite */)); // string/policy_system ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE,
ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008, R::system_overlay_invalid::string::policy_system,
false /* rewrite */)); // string/policy_system_vendor 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 // 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 // overlay does not fulfilled can map to overlay resources when overlayable enforcement is turned
// off. // off.
TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) { TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnoreOverlayable) {
auto resources = TestGetResourceMapping( auto resources = TestGetResourceMapping("/target/target.apk",
"/target/target.apk", "/system-overlay-invalid/system-overlay-invalid.apk", "/system-overlay-invalid/system-overlay-invalid.apk",
PolicyFlags::POLICY_SYSTEM_PARTITION | PolicyFlags::POLICY_PUBLIC, PolicyFlags::SYSTEM_PARTITION | PolicyFlags::PUBLIC,
/* enforce_overlayable */ false); /* enforce_overlayable */ false);
ASSERT_TRUE(resources) << resources.GetErrorMessage(); ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources; auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 9U); ASSERT_EQ(res.GetTargetToOverlayMap().size(), 10U);
ASSERT_RESULT(MappingExists(res, 0x7f020003, Res_value::TYPE_REFERENCE, 0x7f010000, ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/not_overlayable R::system_overlay_invalid::string::not_overlayable,
ASSERT_RESULT(MappingExists(res, 0x7f020004, Res_value::TYPE_REFERENCE, 0x7f010001, false /* rewrite */));
false /* rewrite */)); // string/other ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE,
ASSERT_RESULT(MappingExists(res, 0x7f020005, Res_value::TYPE_REFERENCE, 0x7f010002, R::system_overlay_invalid::string::other, false /* rewrite */));
false /* rewrite */)); // string/policy_odm ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE,
ASSERT_RESULT(MappingExists(res, 0x7f020006, Res_value::TYPE_REFERENCE, 0x7f010003, R::system_overlay_invalid::string::policy_actor,
false /* rewrite */)); // string/policy_oem false /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f020007, Res_value::TYPE_REFERENCE, 0x7f010004, ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/policy_product R::system_overlay_invalid::string::policy_odm, false /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005, ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/policy_public R::system_overlay_invalid::string::policy_oem, false /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f020009, Res_value::TYPE_REFERENCE, 0x7f010006, ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/policy_signature R::system_overlay_invalid::string::policy_product,
ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007, false /* rewrite */));
false /* rewrite */)); // string/policy_system ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008, R::system_overlay_invalid::string::policy_public,
false /* rewrite */)); // string/policy_system_vendor 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 // Overlays that do not target an <overlayable> tag can overlay resources defined within any
// <overlayable> tag. // <overlayable> tag.
TEST(ResourceMappingTests, ResourcesFromApkAssetsNoDefinedOverlayableAndNoTargetName) { TEST(ResourceMappingTests, ResourcesFromApkAssetsNoDefinedOverlayableAndNoTargetName) {
auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay-no-name.apk", auto resources = TestGetResourceMapping("/target/target.apk", "/overlay/overlay-no-name.apk",
PolicyFlags::POLICY_PUBLIC, PolicyFlags::PUBLIC,
/* enforce_overlayable */ false); /* enforce_overlayable */ false);
ASSERT_TRUE(resources) << resources.GetErrorMessage(); ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources; auto& res = *resources;
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U); ASSERT_EQ(res.GetTargetToOverlayMap().size(), 4U);
ASSERT_RESULT(MappingExists(res, 0x7f010000, Res_value::TYPE_REFERENCE, 0x7f010000, ASSERT_RESULT(MappingExists(res, R::target::integer::int1, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // integer/int1 R::overlay::integer::int1, false /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f02000c, Res_value::TYPE_REFERENCE, 0x7f020000, ASSERT_RESULT(MappingExists(res, R::target::string::str1, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/str1 R::overlay::string::str1, false /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f02000e, Res_value::TYPE_REFERENCE, 0x7f020001, ASSERT_RESULT(MappingExists(res, R::target::string::str3, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/str3 R::overlay::string::str3, false /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f02000f, Res_value::TYPE_REFERENCE, 0x7f020002, ASSERT_RESULT(MappingExists(res, R::target::string::str4, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/str4 R::overlay::string::str4, false /* rewrite */));
} }
// Overlays that are neither pre-installed nor signed with the same signature as the target cannot // Overlays that are neither pre-installed nor signed with the same signature as the target cannot
// overlay packages that have not defined overlayable resources. // overlay packages that have not defined overlayable resources.
TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) { TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) {
auto resources = auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk",
TestGetResourceMapping("/target/target-no-overlayable.apk", "/overlay/overlay-no-name.apk", "/overlay/overlay-no-name.apk", PolicyFlags::PUBLIC,
PolicyFlags::POLICY_PUBLIC, /* enforce_overlayable */ true);
/* enforce_overlayable */ true);
ASSERT_TRUE(resources) << resources.GetErrorMessage(); ASSERT_TRUE(resources) << resources.GetErrorMessage();
ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U); ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U);
@@ -293,33 +309,44 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
ASSERT_TRUE(resources) << resources.GetErrorMessage(); ASSERT_TRUE(resources) << resources.GetErrorMessage();
auto& res = *resources; auto& res = *resources;
ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 9U); ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 10U);
ASSERT_RESULT(MappingExists(res, 0x7f020003, Res_value::TYPE_REFERENCE, 0x7f010000, ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/not_overlayable R::system_overlay_invalid::string::not_overlayable,
ASSERT_RESULT(MappingExists(res, 0x7f020004, Res_value::TYPE_REFERENCE, 0x7f010001, false /* rewrite */));
false /* rewrite */)); // string/other ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE,
ASSERT_RESULT(MappingExists(res, 0x7f020005, Res_value::TYPE_REFERENCE, 0x7f010002, R::system_overlay_invalid::string::other, false /* rewrite */));
false /* rewrite */)); // string/policy_odm ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE,
ASSERT_RESULT(MappingExists(res, 0x7f020006, Res_value::TYPE_REFERENCE, 0x7f010003, R::system_overlay_invalid::string::policy_actor,
false /* rewrite */)); // string/policy_oem false /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f020007, Res_value::TYPE_REFERENCE, 0x7f010004, ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/policy_product R::system_overlay_invalid::string::policy_odm,
ASSERT_RESULT(MappingExists(res, 0x7f020008, Res_value::TYPE_REFERENCE, 0x7f010005, false /* rewrite */));
false /* rewrite */)); // string/policy_public ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE,
ASSERT_RESULT(MappingExists(res, 0x7f020009, Res_value::TYPE_REFERENCE, 0x7f010006, R::system_overlay_invalid::string::policy_oem,
false /* rewrite */)); // string/policy_signature false /* rewrite */));
ASSERT_RESULT(MappingExists(res, 0x7f02000a, Res_value::TYPE_REFERENCE, 0x7f010007, ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE,
false /* rewrite */)); // string/policy_system R::system_overlay_invalid::string::policy_product,
ASSERT_RESULT(MappingExists(res, 0x7f02000b, Res_value::TYPE_REFERENCE, 0x7f010008, false /* rewrite */));
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_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::SIGNATURE);
CheckEntries(PolicyFlags::POLICY_PRODUCT_PARTITION); CheckEntries(PolicyFlags::PRODUCT_PARTITION);
CheckEntries(PolicyFlags::POLICY_SYSTEM_PARTITION); CheckEntries(PolicyFlags::SYSTEM_PARTITION);
CheckEntries(PolicyFlags::POLICY_VENDOR_PARTITION); CheckEntries(PolicyFlags::VENDOR_PARTITION);
CheckEntries(PolicyFlags::POLICY_ODM_PARTITION); CheckEntries(PolicyFlags::ODM_PARTITION);
CheckEntries(PolicyFlags::POLICY_OEM_PARTITION); CheckEntries(PolicyFlags::OEM_PARTITION);
} }
} // namespace android::idmap2 } // namespace android::idmap2

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef IDMAP2_TESTS_TESTCONSTANTS_H
#define IDMAP2_TESTS_TESTCONSTANTS_H
namespace android::idmap2::TestConstants {
constexpr const auto TARGET_CRC = 0x41c60c8c;
constexpr const auto TARGET_CRC_STRING = "41c60c8c";
constexpr const auto OVERLAY_CRC = 0xc054fb26;
constexpr const auto OVERLAY_CRC_STRING = "c054fb26";
} // namespace android::idmap2::TestConstants
#endif // IDMAP2_TESTS_TESTCONSTANTS_H

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -22,6 +22,7 @@
#include <androidfw/Asset.h> #include <androidfw/Asset.h>
#include <androidfw/LocaleData.h> #include <androidfw/LocaleData.h>
#include <androidfw/StringPiece.h>
#include <utils/Errors.h> #include <utils/Errors.h>
#include <utils/String16.h> #include <utils/String16.h>
#include <utils/Vector.h> #include <utils/Vector.h>
@@ -34,6 +35,7 @@
#include <android/configuration.h> #include <android/configuration.h>
#include <array>
#include <memory> #include <memory>
namespace android { namespace android {
@@ -1676,42 +1678,64 @@ struct ResTable_overlayable_header
*/ */
struct ResTable_overlayable_policy_header struct ResTable_overlayable_policy_header
{ {
struct ResChunk_header header; /**
* Flags for a bitmask for all possible overlayable policy options.
*
* Any changes to this set should also update aidl/android/os/OverlayablePolicy.aidl
*/
enum PolicyFlags : uint32_t { enum PolicyFlags : uint32_t {
// Base
NONE = 0x00000000,
// Any overlay can overlay these resources. // 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 // The overlay must reside of the system partition or must have existed on the system partition
// before an upgrade to overlay these resources. // 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 // The overlay must reside of the vendor partition or must have existed on the vendor partition
// before an upgrade to overlay these resources. // 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 // The overlay must reside of the product partition or must have existed on the product
// partition before an upgrade to overlay these resources. // 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, // The overlay must be signed with the same signature as the package containing the target
// which can be separate or the same as the target package with the resource. // resource
POLICY_SIGNATURE = 0x00000010, SIGNATURE = 0x00000010,
// The overlay must reside of the odm partition or must have existed on the odm // The overlay must reside of the odm partition or must have existed on the odm
// partition before an upgrade to overlay these resources. // 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 // The overlay must reside of the oem partition or must have existed on the oem
// partition before an upgrade to overlay these resources. // partition before an upgrade to overlay these resources.
POLICY_OEM_PARTITION = 0x00000040, OEM_PARTITION = 0x00000040,
// The overlay must be signed with the same signature as the actor declared for the target
// resource
ACTOR_SIGNATURE = 0x00000080,
}; };
uint32_t policy_flags;
using PolicyBitmask = uint32_t;
struct ResChunk_header header;
PolicyFlags policy_flags;
// The number of ResTable_ref that follow this header. // The number of ResTable_ref that follow this header.
uint32_t entry_count; 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) #pragma pack(push, 1)
struct Idmap_header { struct Idmap_header {
// Always 0x504D4449 ('IDMP') // Always 0x504D4449 ('IDMP')

View File

@@ -41,6 +41,8 @@ using ::testing::NotNull;
using ::testing::SizeIs; using ::testing::SizeIs;
using ::testing::StrEq; using ::testing::StrEq;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace android { namespace android {
TEST(LoadedArscTest, LoadSinglePackageArsc) { TEST(LoadedArscTest, LoadSinglePackageArsc) {
@@ -240,29 +242,29 @@ TEST(LoadedArscTest, LoadOverlayable) {
ASSERT_THAT(info, NotNull()); ASSERT_THAT(info, NotNull());
EXPECT_THAT(info->name, Eq("OverlayableResources1")); EXPECT_THAT(info->name, Eq("OverlayableResources1"));
EXPECT_THAT(info->actor, Eq("overlay://theme")); 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); info = package->GetOverlayableInfo(overlayable::R::string::overlayable2);
ASSERT_THAT(info, NotNull()); ASSERT_THAT(info, NotNull());
EXPECT_THAT(info->name, Eq("OverlayableResources1")); EXPECT_THAT(info->name, Eq("OverlayableResources1"));
EXPECT_THAT(info->actor, Eq("overlay://theme")); EXPECT_THAT(info->actor, Eq("overlay://theme"));
EXPECT_THAT(info->policy_flags, EXPECT_THAT(info->policy_flags,
Eq(ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION Eq(PolicyFlags::SYSTEM_PARTITION
| ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION)); | PolicyFlags::PRODUCT_PARTITION));
info = package->GetOverlayableInfo(overlayable::R::string::overlayable3); info = package->GetOverlayableInfo(overlayable::R::string::overlayable3);
ASSERT_THAT(info, NotNull()); ASSERT_THAT(info, NotNull());
EXPECT_THAT(info->name, Eq("OverlayableResources2")); EXPECT_THAT(info->name, Eq("OverlayableResources2"));
EXPECT_THAT(info->actor, Eq("overlay://com.android.overlayable")); EXPECT_THAT(info->actor, Eq("overlay://com.android.overlayable"));
EXPECT_THAT(info->policy_flags, EXPECT_THAT(info->policy_flags,
Eq(ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION Eq(PolicyFlags::VENDOR_PARTITION
| ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION)); | PolicyFlags::PRODUCT_PARTITION));
info = package->GetOverlayableInfo(overlayable::R::string::overlayable4); info = package->GetOverlayableInfo(overlayable::R::string::overlayable4);
EXPECT_THAT(info->name, Eq("OverlayableResources1")); EXPECT_THAT(info->name, Eq("OverlayableResources1"));
EXPECT_THAT(info->actor, Eq("overlay://theme")); EXPECT_THAT(info->actor, Eq("overlay://theme"));
ASSERT_THAT(info, NotNull()); 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) { TEST(LoadedArscTest, ResourceIdentifierIterator) {

View File

@@ -127,6 +127,8 @@ java_library_static {
"android.hidl.manager-V1.2-java", "android.hidl.manager-V1.2-java",
"dnsresolver_aidl_interface-V2-java", "dnsresolver_aidl_interface-V2-java",
"netd_event_listener_interface-java", "netd_event_listener_interface-java",
"ike-stubs",
"overlayable_policy_aidl-java",
], ],
plugins: [ plugins: [

View File

@@ -21,17 +21,17 @@ import static com.android.server.om.OverlayManagerService.TAG;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.content.om.OverlayInfo; import android.content.om.OverlayInfo;
import android.content.om.OverlayableInfo;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.os.Build.VERSION_CODES; import android.os.Build.VERSION_CODES;
import android.os.IIdmap2; import android.os.OverlayablePolicy;
import android.os.SystemProperties; import android.os.SystemProperties;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.Slog; import android.util.Slog;
import com.android.server.om.OverlayManagerServiceImpl.PackageManagerHelper;
import java.io.File; import java.io.File;
import java.io.IOException;
/** /**
* Handle the creation and deletion of idmap files. * Handle the creation and deletion of idmap files.
@@ -55,11 +55,11 @@ class IdmapManager {
VENDOR_IS_Q_OR_LATER = isQOrLater; VENDOR_IS_Q_OR_LATER = isQOrLater;
} }
private final PackageManagerHelper mPackageManager; private final OverlayableInfoCallback mOverlayableCallback;
private final IdmapDaemon mIdmapDaemon; private final IdmapDaemon mIdmapDaemon;
IdmapManager(final PackageManagerHelper packageManager) { IdmapManager(final OverlayableInfoCallback verifyCallback) {
mPackageManager = packageManager; mOverlayableCallback = verifyCallback;
mIdmapDaemon = IdmapDaemon.getInstance(); mIdmapDaemon = IdmapDaemon.getInstance();
} }
@@ -148,40 +148,67 @@ class IdmapManager {
private int calculateFulfilledPolicies(@NonNull final PackageInfo targetPackage, private int calculateFulfilledPolicies(@NonNull final PackageInfo targetPackage,
@NonNull final PackageInfo overlayPackage, int userId) { @NonNull final PackageInfo overlayPackage, int userId) {
final ApplicationInfo ai = overlayPackage.applicationInfo; final ApplicationInfo ai = overlayPackage.applicationInfo;
int fulfilledPolicies = IIdmap2.POLICY_PUBLIC; int fulfilledPolicies = OverlayablePolicy.PUBLIC;
// Overlay matches target signature // Overlay matches target signature
if (mPackageManager.signaturesMatching(targetPackage.packageName, if (mOverlayableCallback.signaturesMatching(targetPackage.packageName,
overlayPackage.packageName, userId)) { overlayPackage.packageName, userId)) {
fulfilledPolicies |= IIdmap2.POLICY_SIGNATURE; fulfilledPolicies |= OverlayablePolicy.SIGNATURE;
}
// Overlay matches actor signature
if (matchesActorSignature(targetPackage, overlayPackage, userId)) {
fulfilledPolicies |= OverlayablePolicy.ACTOR_SIGNATURE;
} }
// Vendor partition (/vendor) // Vendor partition (/vendor)
if (ai.isVendor()) { if (ai.isVendor()) {
return fulfilledPolicies | IIdmap2.POLICY_VENDOR_PARTITION; return fulfilledPolicies | OverlayablePolicy.VENDOR_PARTITION;
} }
// Product partition (/product) // Product partition (/product)
if (ai.isProduct()) { if (ai.isProduct()) {
return fulfilledPolicies | IIdmap2.POLICY_PRODUCT_PARTITION; return fulfilledPolicies | OverlayablePolicy.PRODUCT_PARTITION;
} }
// Odm partition (/odm) // Odm partition (/odm)
if (ai.isOdm()) { if (ai.isOdm()) {
return fulfilledPolicies | IIdmap2.POLICY_ODM_PARTITION; return fulfilledPolicies | OverlayablePolicy.ODM_PARTITION;
} }
// Oem partition (/oem) // Oem partition (/oem)
if (ai.isOem()) { if (ai.isOem()) {
return fulfilledPolicies | IIdmap2.POLICY_OEM_PARTITION; return fulfilledPolicies | OverlayablePolicy.OEM_PARTITION;
} }
// System_ext partition (/system_ext) is considered as system // 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. // Check this last since every partition except for data is scanned as system in the PMS.
if (ai.isSystemApp() || ai.isSystemExt()) { if (ai.isSystemApp() || ai.isSystemExt()) {
return fulfilledPolicies | IIdmap2.POLICY_SYSTEM_PARTITION; return fulfilledPolicies | OverlayablePolicy.SYSTEM_PARTITION;
} }
return fulfilledPolicies; return fulfilledPolicies;
} }
private boolean matchesActorSignature(@NonNull PackageInfo targetPackage,
@NonNull PackageInfo overlayPackage, int userId) {
String targetOverlayableName = overlayPackage.targetOverlayableName;
if (targetOverlayableName != null) {
try {
OverlayableInfo overlayableInfo = mOverlayableCallback.getOverlayableForTarget(
targetPackage.packageName, targetOverlayableName, userId);
if (overlayableInfo != null) {
String actorPackageName = OverlayActorEnforcer.getPackageNameForActor(
overlayableInfo.actor, mOverlayableCallback.getNamedActors()).first;
if (mOverlayableCallback.signaturesMatching(actorPackageName,
overlayPackage.packageName, userId)) {
return true;
}
}
} catch (IOException ignored) {
}
}
return false;
}
} }

View File

@@ -17,7 +17,6 @@
package com.android.server.om; package com.android.server.om;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.om.OverlayInfo; import android.content.om.OverlayInfo;
import android.content.om.OverlayableInfo; import android.content.om.OverlayableInfo;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
@@ -46,7 +45,7 @@ public class OverlayActorEnforcer {
// By default, the reason is not logged to prevent leaks of why it failed // By default, the reason is not logged to prevent leaks of why it failed
private static final boolean DEBUG_REASON = false; private static final boolean DEBUG_REASON = false;
private final VerifyCallback mVerifyCallback; private final OverlayableInfoCallback mOverlayableCallback;
/** /**
* @return nullable actor result with {@link ActorState} failure status * @return nullable actor result with {@link ActorState} failure status
@@ -80,8 +79,8 @@ public class OverlayActorEnforcer {
return Pair.create(packageName, ActorState.ALLOWED); return Pair.create(packageName, ActorState.ALLOWED);
} }
public OverlayActorEnforcer(@NonNull VerifyCallback verifyCallback) { public OverlayActorEnforcer(@NonNull OverlayableInfoCallback overlayableCallback) {
mVerifyCallback = verifyCallback; mOverlayableCallback = overlayableCallback;
} }
void enforceActor(@NonNull OverlayInfo overlayInfo, @NonNull String methodName, void enforceActor(@NonNull OverlayInfo overlayInfo, @NonNull String methodName,
@@ -117,7 +116,7 @@ public class OverlayActorEnforcer {
return ActorState.ALLOWED; return ActorState.ALLOWED;
} }
String[] callingPackageNames = mVerifyCallback.getPackagesForUid(callingUid); String[] callingPackageNames = mOverlayableCallback.getPackagesForUid(callingUid);
if (ArrayUtils.isEmpty(callingPackageNames)) { if (ArrayUtils.isEmpty(callingPackageNames)) {
return ActorState.NO_PACKAGES_FOR_UID; return ActorState.NO_PACKAGES_FOR_UID;
} }
@@ -132,12 +131,12 @@ public class OverlayActorEnforcer {
if (TextUtils.isEmpty(targetOverlayableName)) { if (TextUtils.isEmpty(targetOverlayableName)) {
try { try {
if (mVerifyCallback.doesTargetDefineOverlayable(targetPackageName, userId)) { if (mOverlayableCallback.doesTargetDefineOverlayable(targetPackageName, userId)) {
return ActorState.MISSING_TARGET_OVERLAYABLE_NAME; return ActorState.MISSING_TARGET_OVERLAYABLE_NAME;
} else { } else {
// If there's no overlayable defined, fallback to the legacy permission check // If there's no overlayable defined, fallback to the legacy permission check
try { try {
mVerifyCallback.enforcePermission( mOverlayableCallback.enforcePermission(
android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName); android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName);
// If the previous method didn't throw, check passed // If the previous method didn't throw, check passed
@@ -153,7 +152,7 @@ public class OverlayActorEnforcer {
OverlayableInfo targetOverlayable; OverlayableInfo targetOverlayable;
try { try {
targetOverlayable = mVerifyCallback.getOverlayableForTarget(targetPackageName, targetOverlayable = mOverlayableCallback.getOverlayableForTarget(targetPackageName,
targetOverlayableName, userId); targetOverlayableName, userId);
} catch (IOException e) { } catch (IOException e) {
return ActorState.UNABLE_TO_GET_TARGET; return ActorState.UNABLE_TO_GET_TARGET;
@@ -167,7 +166,7 @@ public class OverlayActorEnforcer {
if (TextUtils.isEmpty(actor)) { if (TextUtils.isEmpty(actor)) {
// If there's no actor defined, fallback to the legacy permission check // If there's no actor defined, fallback to the legacy permission check
try { try {
mVerifyCallback.enforcePermission( mOverlayableCallback.enforcePermission(
android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName); android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName);
// If the previous method didn't throw, check passed // If the previous method didn't throw, check passed
@@ -177,7 +176,7 @@ public class OverlayActorEnforcer {
} }
} }
Map<String, Map<String, String>> namedActors = mVerifyCallback.getNamedActors(); Map<String, Map<String, String>> namedActors = mOverlayableCallback.getNamedActors();
Pair<String, ActorState> actorUriPair = getPackageNameForActor(actor, namedActors); Pair<String, ActorState> actorUriPair = getPackageNameForActor(actor, namedActors);
ActorState actorUriState = actorUriPair.second; ActorState actorUriState = actorUriPair.second;
if (actorUriState != ActorState.ALLOWED) { if (actorUriState != ActorState.ALLOWED) {
@@ -185,7 +184,7 @@ public class OverlayActorEnforcer {
} }
String packageName = actorUriPair.first; String packageName = actorUriPair.first;
PackageInfo packageInfo = mVerifyCallback.getPackageInfo(packageName, userId); PackageInfo packageInfo = mOverlayableCallback.getPackageInfo(packageName, userId);
if (packageInfo == null) { if (packageInfo == null) {
return ActorState.MISSING_APP_INFO; return ActorState.MISSING_APP_INFO;
} }
@@ -211,7 +210,7 @@ public class OverlayActorEnforcer {
* For easier logging/debugging, a set of all possible failure/success states when running * For easier logging/debugging, a set of all possible failure/success states when running
* enforcement. * enforcement.
*/ */
enum ActorState { public enum ActorState {
ALLOWED, ALLOWED,
INVALID_ACTOR, INVALID_ACTOR,
MISSING_NAMESPACE, MISSING_NAMESPACE,
@@ -228,53 +227,4 @@ public class OverlayActorEnforcer {
UNABLE_TO_GET_TARGET, UNABLE_TO_GET_TARGET,
MISSING_LEGACY_PERMISSION MISSING_LEGACY_PERMISSION
} }
/**
* Delegate to the system for querying information about packages.
*/
public interface VerifyCallback {
/**
* Read from the APK and AndroidManifest of a package to return the overlayable defined for
* a given name.
*
* @throws IOException if the target can't be read
*/
@Nullable
OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
@Nullable String targetOverlayableName, int userId)
throws IOException;
/**
* @see android.content.pm.PackageManager#getPackagesForUid(int)
*/
@Nullable
String[] getPackagesForUid(int uid);
/**
* @param userId user to filter package visibility by
* @see android.content.pm.PackageManager#getPackageInfo(String, int)
*/
@Nullable
PackageInfo getPackageInfo(@NonNull String packageName, int userId);
/**
* @return map of system pre-defined, uniquely named actors; keys are namespace,
* value maps actor name to package name
*/
@NonNull
Map<String, Map<String, String>> getNamedActors();
/**
* @return true if the target package has declared an overlayable
*/
boolean doesTargetDefineOverlayable(String targetPackageName, int userId)
throws RemoteException, IOException;
/**
* @throws SecurityException containing message if the caller doesn't have the given
* permission
*/
void enforcePermission(String permission, String message) throws SecurityException;
}
} }

View File

@@ -226,7 +226,7 @@ public final class OverlayManagerService extends SystemService {
private final AtomicFile mSettingsFile; private final AtomicFile mSettingsFile;
private final PackageManagerHelper mPackageManager; private final PackageManagerHelperImpl mPackageManager;
private final UserManagerService mUserManager; private final UserManagerService mUserManager;
@@ -244,7 +244,7 @@ public final class OverlayManagerService extends SystemService {
traceBegin(TRACE_TAG_RRO, "OMS#OverlayManagerService"); traceBegin(TRACE_TAG_RRO, "OMS#OverlayManagerService");
mSettingsFile = new AtomicFile( mSettingsFile = new AtomicFile(
new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays"); new File(Environment.getDataSystemDirectory(), "overlays.xml"), "overlays");
mPackageManager = new PackageManagerHelper(context); mPackageManager = new PackageManagerHelperImpl(context);
mUserManager = UserManagerService.getInstance(); mUserManager = UserManagerService.getInstance();
IdmapManager im = new IdmapManager(mPackageManager); IdmapManager im = new IdmapManager(mPackageManager);
mSettings = new OverlayManagerSettings(); mSettings = new OverlayManagerSettings();
@@ -1053,14 +1053,8 @@ public final class OverlayManagerService extends SystemService {
} }
} }
/** private static final class PackageManagerHelperImpl implements PackageManagerHelper,
* Delegate for {@link android.content.pm.PackageManager} and {@link PackageManagerInternal} OverlayableInfoCallback {
* functionality, separated for easy testing.
*
* @hide
*/
public static final class PackageManagerHelper implements
OverlayManagerServiceImpl.PackageManagerHelper, OverlayActorEnforcer.VerifyCallback {
private final Context mContext; private final Context mContext;
private final IPackageManager mPackageManager; private final IPackageManager mPackageManager;
@@ -1073,7 +1067,7 @@ public final class OverlayManagerService extends SystemService {
// behind until all pending intents have been processed. // behind until all pending intents have been processed.
private final SparseArray<HashMap<String, PackageInfo>> mCache = new SparseArray<>(); private final SparseArray<HashMap<String, PackageInfo>> mCache = new SparseArray<>();
PackageManagerHelper(Context context) { PackageManagerHelperImpl(Context context) {
mContext = context; mContext = context;
mPackageManager = getPackageManager(); mPackageManager = getPackageManager();
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class); mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
@@ -1132,7 +1126,7 @@ public final class OverlayManagerService extends SystemService {
@Nullable @Nullable
@Override @Override
public OverlayableInfo getOverlayableForTarget(@NonNull String packageName, public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
@Nullable String targetOverlayableName, int userId) @NonNull String targetOverlayableName, int userId)
throws IOException { throws IOException {
PackageInfo packageInfo = getPackageInfo(packageName, userId); PackageInfo packageInfo = getPackageInfo(packageName, userId);
if (packageInfo == null) { if (packageInfo == null) {

View File

@@ -18,7 +18,6 @@ package com.android.server.om;
import static android.content.om.OverlayInfo.STATE_DISABLED; import static android.content.om.OverlayInfo.STATE_DISABLED;
import static android.content.om.OverlayInfo.STATE_ENABLED; import static android.content.om.OverlayInfo.STATE_ENABLED;
import static android.content.om.OverlayInfo.STATE_ENABLED_IMMUTABLE;
import static android.content.om.OverlayInfo.STATE_MISSING_TARGET; import static android.content.om.OverlayInfo.STATE_MISSING_TARGET;
import static android.content.om.OverlayInfo.STATE_NO_IDMAP; import static android.content.om.OverlayInfo.STATE_NO_IDMAP;
import static android.content.om.OverlayInfo.STATE_OVERLAY_IS_BEING_REPLACED; import static android.content.om.OverlayInfo.STATE_OVERLAY_IS_BEING_REPLACED;
@@ -806,11 +805,4 @@ final class OverlayManagerServiceImpl {
**/ **/
void onOverlaysChanged(@NonNull String targetPackage, int userId); void onOverlaysChanged(@NonNull String targetPackage, int userId);
} }
interface PackageManagerHelper {
PackageInfo getPackageInfo(@NonNull String packageName, int userId);
boolean signaturesMatching(@NonNull String packageName1, @NonNull String packageName2,
int userId);
List<PackageInfo> getOverlayPackages(int userId);
}
} }

View File

@@ -0,0 +1,85 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.om;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.om.OverlayableInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.RemoteException;
import com.android.server.pm.PackageManagerServiceUtils;
import java.io.IOException;
import java.util.Map;
/**
* Delegate to the system for querying information about overlayables and packages.
*/
public interface OverlayableInfoCallback {
/**
* Read from the APK and AndroidManifest of a package to return the overlayable defined for
* a given name.
*
* @throws IOException if the target can't be read
*/
@Nullable
OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
@NonNull String targetOverlayableName, int userId)
throws IOException;
/**
* @see PackageManager#getPackagesForUid(int)
*/
@Nullable
String[] getPackagesForUid(int uid);
/**
* @param userId user to filter package visibility by
* @see PackageManager#getPackageInfo(String, int)
*/
@Nullable
PackageInfo getPackageInfo(@NonNull String packageName, int userId);
/**
* @return map of system pre-defined, uniquely named actors; keys are namespace,
* value maps actor name to package name
*/
@NonNull
Map<String, Map<String, String>> getNamedActors();
/**
* @return true if the target package has declared an overlayable
*/
boolean doesTargetDefineOverlayable(String targetPackageName, int userId)
throws RemoteException, IOException;
/**
* @throws SecurityException containing message if the caller doesn't have the given
* permission
*/
void enforcePermission(String permission, String message) throws SecurityException;
/**
* @return true if {@link PackageManagerServiceUtils#compareSignatures} run on both packages
* in the system returns {@link PackageManager#SIGNATURE_MATCH}
*/
boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId);
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.om;
import android.annotation.NonNull;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import java.util.List;
/**
* Delegate for {@link PackageManager} and {@link PackageManagerInternal} functionality,
* separated for easy testing.
*
* @hide
*/
interface PackageManagerHelper {
PackageInfo getPackageInfo(@NonNull String packageName, int userId);
boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId);
List<PackageInfo> getOverlayPackages(int userId);
}

View File

@@ -24,6 +24,7 @@ import android.os.Process
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.rules.ExpectedException import org.junit.rules.ExpectedException
import java.lang.UnsupportedOperationException
class OverlayActorEnforcerTests { class OverlayActorEnforcerTests {
companion object { companion object {
@@ -159,7 +160,7 @@ class OverlayActorEnforcerTests {
private val hasPermission: Boolean = false, private val hasPermission: Boolean = false,
private val overlayableInfo: OverlayableInfo? = null, private val overlayableInfo: OverlayableInfo? = null,
private vararg val packageNames: String = arrayOf("com.test.actor.one") private vararg val packageNames: String = arrayOf("com.test.actor.one")
) : OverlayActorEnforcer.VerifyCallback { ) : OverlayableInfoCallback {
override fun getNamedActors() = if (isActor) { override fun getNamedActors() = if (isActor) {
mapOf(NAMESPACE to mapOf(ACTOR_NAME to ACTOR_PKG_NAME)) mapOf(NAMESPACE to mapOf(ACTOR_NAME to ACTOR_PKG_NAME))
@@ -169,7 +170,7 @@ class OverlayActorEnforcerTests {
override fun getOverlayableForTarget( override fun getOverlayableForTarget(
packageName: String, packageName: String,
targetOverlayableName: String?, targetOverlayableName: String,
userId: Int userId: Int
) = overlayableInfo ) = overlayableInfo
@@ -193,5 +194,9 @@ class OverlayActorEnforcerTests {
throw SecurityException() throw SecurityException()
} }
} }
override fun signaturesMatching(pkgName1: String, pkgName2: String, userId: Int): Boolean {
throw UnsupportedOperationException()
}
} }
} }

View File

@@ -24,30 +24,16 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.content.om.OverlayInfo; import android.content.om.OverlayInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.util.ArraySet;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import com.android.internal.content.om.OverlayConfig;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase { public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase {

View File

@@ -23,10 +23,13 @@ import static org.mockito.Mockito.when;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.content.om.OverlayInfo; import android.content.om.OverlayInfo;
import android.content.om.OverlayInfo.State; import android.content.om.OverlayInfo.State;
import android.content.om.OverlayableInfo;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.util.ArraySet; import android.util.ArraySet;
import androidx.annotation.Nullable;
import com.android.internal.content.om.OverlayConfig; import com.android.internal.content.om.OverlayConfig;
import org.junit.Before; import org.junit.Before;
@@ -35,6 +38,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -281,8 +285,8 @@ class OverlayManagerServiceImplTestsBase {
} }
} }
static final class DummyPackageManagerHelper implements static final class DummyPackageManagerHelper implements PackageManagerHelper,
OverlayManagerServiceImpl.PackageManagerHelper { OverlayableInfoCallback {
private final DummyDeviceState mState; private final DummyDeviceState mState;
private DummyPackageManagerHelper(DummyDeviceState state) { private DummyPackageManagerHelper(DummyDeviceState state) {
@@ -320,6 +324,35 @@ class OverlayManagerServiceImplTestsBase {
.map(p -> getPackageInfo(p.packageName, p.userId)) .map(p -> getPackageInfo(p.packageName, p.userId))
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
@Nullable
@Override
public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
@NonNull String targetOverlayableName, int userId) {
throw new UnsupportedOperationException();
}
@Nullable
@Override
public String[] getPackagesForUid(int uid) {
throw new UnsupportedOperationException();
}
@NonNull
@Override
public Map<String, Map<String, String>> getNamedActors() {
throw new UnsupportedOperationException();
}
@Override
public boolean doesTargetDefineOverlayable(String targetPackageName, int userId) {
throw new UnsupportedOperationException();
}
@Override
public void enforcePermission(String permission, String message) throws SecurityException {
throw new UnsupportedOperationException();
}
} }
static class DummyIdmapManager extends IdmapManager { static class DummyIdmapManager extends IdmapManager {

View File

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

View File

@@ -32,10 +32,16 @@
#include "text/Printer.h" #include "text/Printer.h"
#include "util/Util.h" #include "util/Util.h"
#include "idmap2/Policies.h"
using ::aapt::text::Printer; using ::aapt::text::Printer;
using ::android::StringPiece; using ::android::StringPiece;
using ::android::base::StringPrintf; using ::android::base::StringPrintf;
using android::idmap2::policy::kPolicyStringToFlag;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace aapt { namespace aapt {
namespace { namespace {
@@ -246,32 +252,25 @@ class ValueBodyPrinter : public ConstValueVisitor {
Printer* printer_; Printer* printer_;
}; };
std::string OverlayablePoliciesToString(OverlayableItem::PolicyFlags policies) { std::string OverlayablePoliciesToString(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 str; 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; continue;
} }
if (!str.empty()) { if (!str.empty()) {
str.append("|"); str.append("|");
} }
str.append(policy.second); str.append(policy.first.data());
policies &= ~policy.first; remaining &= ~policy.second;
} }
if (policies != 0) { if (remaining != 0) {
if (!str.empty()) { if (!str.empty()) {
str.append("|"); str.append("|");
} }
str.append(StringPrintf("0x%08x", policies)); str.append(StringPrintf("0x%08x", remaining));
} }
return !str.empty() ? str : "none"; return !str.empty() ? str : "none";
} }

View File

@@ -32,11 +32,15 @@
#include "util/Util.h" #include "util/Util.h"
#include "xml/XmlPullParser.h" #include "xml/XmlPullParser.h"
#include "idmap2/Policies.h"
using ::aapt::ResourceUtils::StringBuilder; using ::aapt::ResourceUtils::StringBuilder;
using ::aapt::text::Utf8Iterator; using ::aapt::text::Utf8Iterator;
using ::android::ConfigDescription; using ::android::ConfigDescription;
using ::android::StringPiece; using ::android::StringPiece;
using android::idmap2::policy::kPolicyStringToFlag;
namespace aapt { namespace aapt {
constexpr const char* sXliffNamespaceUri = "urn:oasis:names:tc:xliff:document:1.2"; 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; bool error = false;
std::string comment; std::string comment;
OverlayableItem::PolicyFlags current_policies = OverlayableItem::Policy::kNone; PolicyFlags current_policies = PolicyFlags::NONE;
const size_t start_depth = parser->depth(); const size_t start_depth = parser->depth();
while (xml::XmlPullParser::IsGoodEvent(parser->Next())) { while (xml::XmlPullParser::IsGoodEvent(parser->Next())) {
xml::XmlPullParser::Event event = parser->event(); xml::XmlPullParser::Event event = parser->event();
@@ -1073,7 +1077,7 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
} else if (event == xml::XmlPullParser::Event::kEndElement } else if (event == xml::XmlPullParser::Event::kEndElement
&& parser->depth() == start_depth + 1) { && parser->depth() == start_depth + 1) {
// Clear the current policies when exiting the <policy> tags // Clear the current policies when exiting the <policy> tags
current_policies = OverlayableItem::Policy::kNone; current_policies = PolicyFlags::NONE;
continue; continue;
} else if (event == xml::XmlPullParser::Event::kComment) { } else if (event == xml::XmlPullParser::Event::kComment) {
// Retrieve the comment of individual <item> tags // 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_name = parser->element_name();
const std::string& element_namespace = parser->element_namespace(); const std::string& element_namespace = parser->element_namespace();
if (element_namespace.empty() && element_name == "item") { if (element_namespace.empty() && element_name == "item") {
if (current_policies == OverlayableItem::Policy::kNone) { if (current_policies == PolicyFlags::NONE) {
diag_->Error(DiagMessage(element_source) diag_->Error(DiagMessage(element_source)
<< "<item> within an <overlayable> must be inside a <policy> block"); << "<item> within an <overlayable> must be inside a <policy> block");
error = true; error = true;
@@ -1133,7 +1137,7 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
out_resource->child_resources.push_back(std::move(child_resource)); out_resource->child_resources.push_back(std::move(child_resource));
} else if (element_namespace.empty() && element_name == "policy") { } 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 // 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"); diag_->Error(DiagMessage(element_source) << "<policy> blocks cannot be recursively nested");
error = true; error = true;
@@ -1141,21 +1145,14 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource
} else if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) { } else if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) {
// Parse the polices separated by vertical bar characters to allow for specifying multiple // Parse the polices separated by vertical bar characters to allow for specifying multiple
// policies. Items within the policy tag will have the specified policy. // 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(), '|')) { for (const StringPiece& part : util::Tokenize(maybe_type.value(), '|')) {
StringPiece trimmed_part = util::TrimWhitespace(part); StringPiece trimmed_part = util::TrimWhitespace(part);
const auto policy = kPolicyMap.find(trimmed_part); const auto policy = std::find_if(kPolicyStringToFlag.begin(),
if (policy == kPolicyMap.end()) { kPolicyStringToFlag.end(),
[trimmed_part](const auto& it) {
return trimmed_part == it.first;
});
if (policy == kPolicyStringToFlag.end()) {
diag_->Error(DiagMessage(element_source) diag_->Error(DiagMessage(element_source)
<< "<policy> has unsupported type '" << trimmed_part << "'"); << "<policy> has unsupported type '" << trimmed_part << "'");
error = true; error = true;

View File

@@ -41,6 +41,8 @@ using ::testing::Pointee;
using ::testing::SizeIs; using ::testing::SizeIs;
using ::testing::StrEq; using ::testing::StrEq;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace aapt { namespace aapt {
constexpr const char* kXmlPreamble = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; 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(); 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->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme")); 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")); search_result = table_.FindResource(test::ParseNameOrDie("drawable/bar"));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -968,7 +970,7 @@ TEST_F(ResourceParserTest, ParseOverlayable) {
result_overlayable_item = search_result.value().entry->overlayable_item.value(); 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->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme")); 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) { TEST_F(ResourceParserTest, ParseOverlayableRequiresName) {
@@ -1005,6 +1007,9 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
<policy type="oem"> <policy type="oem">
<item type="string" name="buz" /> <item type="string" name="buz" />
</policy> </policy>
<policy type="actor">
<item type="string" name="actor" />
</policy>
</overlayable>)"; </overlayable>)";
ASSERT_TRUE(TestParse(input)); ASSERT_TRUE(TestParse(input));
@@ -1014,7 +1019,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
OverlayableItem result_overlayable_item = search_result.value().entry->overlayable_item.value(); 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->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")); search_result = table_.FindResource(test::ParseNameOrDie("string/fiz"));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -1022,7 +1027,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
result_overlayable_item = search_result.value().entry->overlayable_item.value(); 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->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")); search_result = table_.FindResource(test::ParseNameOrDie("string/fuz"));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -1030,7 +1035,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
result_overlayable_item = search_result.value().entry->overlayable_item.value(); 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->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")); search_result = table_.FindResource(test::ParseNameOrDie("string/faz"));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -1038,7 +1043,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
result_overlayable_item = search_result.value().entry->overlayable_item.value(); 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->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")); search_result = table_.FindResource(test::ParseNameOrDie("string/foz"));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -1046,7 +1051,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
result_overlayable_item = search_result.value().entry->overlayable_item.value(); 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->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")); search_result = table_.FindResource(test::ParseNameOrDie("string/biz"));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -1054,7 +1059,7 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
result_overlayable_item = search_result.value().entry->overlayable_item.value(); 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->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")); search_result = table_.FindResource(test::ParseNameOrDie("string/buz"));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -1062,7 +1067,15 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
result_overlayable_item = search_result.value().entry->overlayable_item.value(); 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->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kOem)); EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::OEM_PARTITION));
search_result = table_.FindResource(test::ParseNameOrDie("string/actor"));
ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull());
ASSERT_TRUE(search_result.value().entry->overlayable_item);
result_overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::ACTOR_SIGNATURE));
} }
TEST_F(ResourceParserTest, ParseOverlayableNoPolicyError) { TEST_F(ResourceParserTest, ParseOverlayableNoPolicyError) {
@@ -1125,8 +1138,8 @@ TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) {
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
OverlayableItem result_overlayable_item = search_result.value().entry->overlayable_item.value(); 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->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kVendor EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::VENDOR_PARTITION
| OverlayableItem::Policy::kPublic)); | PolicyFlags::PUBLIC));
search_result = table_.FindResource(test::ParseNameOrDie("string/bar")); search_result = table_.FindResource(test::ParseNameOrDie("string/bar"));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -1134,8 +1147,8 @@ TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) {
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
result_overlayable_item = search_result.value().entry->overlayable_item.value(); 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->name, Eq("Name"));
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PRODUCT_PARTITION
| OverlayableItem::Policy::kSystem)); | PolicyFlags::SYSTEM_PARTITION));
} }
TEST_F(ResourceParserTest, DuplicateOverlayableIsError) { TEST_F(ResourceParserTest, DuplicateOverlayableIsError) {

View File

@@ -36,6 +36,8 @@
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace aapt { namespace aapt {
// The Public status of a resource. // The Public status of a resource.
@@ -75,36 +77,8 @@ struct Overlayable {
struct OverlayableItem { struct OverlayableItem {
explicit OverlayableItem(const std::shared_ptr<Overlayable>& overlayable) explicit OverlayableItem(const std::shared_ptr<Overlayable>& overlayable)
: 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; std::shared_ptr<Overlayable> overlayable;
PolicyFlags policies = Policy::kNone; PolicyFlags policies = PolicyFlags::NONE;
std::string comment; std::string comment;
Source source; Source source;
}; };

View File

@@ -30,6 +30,8 @@ using ::testing::Eq;
using ::testing::NotNull; using ::testing::NotNull;
using ::testing::StrEq; using ::testing::StrEq;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace aapt { namespace aapt {
TEST(ResourceTableTest, FailToAddResourceWithBadName) { TEST(ResourceTableTest, FailToAddResourceWithBadName) {
@@ -247,8 +249,8 @@ TEST(ResourceTableTest, SetOverlayable) {
auto overlayable = std::make_shared<Overlayable>("Name", "overlay://theme", auto overlayable = std::make_shared<Overlayable>("Name", "overlay://theme",
Source("res/values/overlayable.xml", 40)); Source("res/values/overlayable.xml", 40));
OverlayableItem overlayable_item(overlayable); OverlayableItem overlayable_item(overlayable);
overlayable_item.policies |= OverlayableItem::Policy::kProduct; overlayable_item.policies |= PolicyFlags::PRODUCT_PARTITION;
overlayable_item.policies |= OverlayableItem::Policy::kVendor; overlayable_item.policies |= PolicyFlags::VENDOR_PARTITION;
overlayable_item.comment = "comment"; overlayable_item.comment = "comment";
overlayable_item.source = Source("res/values/overlayable.xml", 42); 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->actor, Eq("overlay://theme"));
EXPECT_THAT(result_overlayable_item.overlayable->source.path, Eq("res/values/overlayable.xml")); 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.overlayable->source.line, 40);
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PRODUCT_PARTITION
| OverlayableItem::Policy::kVendor)); | PolicyFlags::VENDOR_PARTITION));
ASSERT_THAT(result_overlayable_item.comment, StrEq("comment")); 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.path, Eq("res/values/overlayable.xml"));
EXPECT_THAT(result_overlayable_item.source.line, 42); EXPECT_THAT(result_overlayable_item.source.line, 42);
@@ -277,17 +279,17 @@ TEST(ResourceTableTest, SetMultipleOverlayableResources) {
const ResourceName foo = test::ParseNameOrDie("android:string/foo"); const ResourceName foo = test::ParseNameOrDie("android:string/foo");
auto group = std::make_shared<Overlayable>("Name", "overlay://theme"); auto group = std::make_shared<Overlayable>("Name", "overlay://theme");
OverlayableItem overlayable(group); OverlayableItem overlayable(group);
overlayable.policies = OverlayableItem::Policy::kProduct; overlayable.policies = PolicyFlags::PRODUCT_PARTITION;
ASSERT_TRUE(table.SetOverlayable(foo, overlayable, test::GetDiagnostics())); ASSERT_TRUE(table.SetOverlayable(foo, overlayable, test::GetDiagnostics()));
const ResourceName bar = test::ParseNameOrDie("android:string/bar"); const ResourceName bar = test::ParseNameOrDie("android:string/bar");
OverlayableItem overlayable2(group); OverlayableItem overlayable2(group);
overlayable2.policies = OverlayableItem::Policy::kProduct; overlayable2.policies = PolicyFlags::PRODUCT_PARTITION;
ASSERT_TRUE(table.SetOverlayable(bar, overlayable2, test::GetDiagnostics())); ASSERT_TRUE(table.SetOverlayable(bar, overlayable2, test::GetDiagnostics()));
const ResourceName baz = test::ParseNameOrDie("android:string/baz"); const ResourceName baz = test::ParseNameOrDie("android:string/baz");
OverlayableItem overlayable3(group); OverlayableItem overlayable3(group);
overlayable3.policies = OverlayableItem::Policy::kVendor; overlayable3.policies = PolicyFlags::VENDOR_PARTITION;
ASSERT_TRUE(table.SetOverlayable(baz, overlayable3, test::GetDiagnostics())); ASSERT_TRUE(table.SetOverlayable(baz, overlayable3, test::GetDiagnostics()));
} }
@@ -296,12 +298,12 @@ TEST(ResourceTableTest, SetOverlayableDifferentResourcesDifferentName) {
const ResourceName foo = test::ParseNameOrDie("android:string/foo"); const ResourceName foo = test::ParseNameOrDie("android:string/foo");
OverlayableItem overlayable_item(std::make_shared<Overlayable>("Name", "overlay://theme")); 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())); ASSERT_TRUE(table.SetOverlayable(foo, overlayable_item, test::GetDiagnostics()));
const ResourceName bar = test::ParseNameOrDie("android:string/bar"); const ResourceName bar = test::ParseNameOrDie("android:string/bar");
OverlayableItem overlayable_item2(std::make_shared<Overlayable>("Name2", "overlay://theme")); 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())); ASSERT_TRUE(table.SetOverlayable(bar, overlayable_item2, test::GetDiagnostics()));
} }

View File

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

View File

@@ -455,35 +455,6 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) {
const ResTable_overlayable_policy_header* policy_header = const ResTable_overlayable_policy_header* policy_header =
ConvertTo<ResTable_overlayable_policy_header>(parser.chunk()); 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*>( const ResTable_ref* const ref_begin = reinterpret_cast<const ResTable_ref*>(
((uint8_t *)policy_header) + util::DeviceToHost32(policy_header->header.headerSize)); ((uint8_t *)policy_header) + util::DeviceToHost32(policy_header->header.headerSize));
const ResTable_ref* const ref_end = ref_begin const ResTable_ref* const ref_end = ref_begin
@@ -501,7 +472,7 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) {
} }
OverlayableItem overlayable_item(overlayable); OverlayableItem overlayable_item(overlayable);
overlayable_item.policies = policies; overlayable_item.policies = policy_header->policy_flags;
if (!table_->SetOverlayable(iter->second, overlayable_item, diag_)) { if (!table_->SetOverlayable(iter->second, overlayable_item, diag_)) {
return false; return false;
} }

View File

@@ -233,7 +233,7 @@ class MapFlattenVisitor : public ValueVisitor {
struct OverlayableChunk { struct OverlayableChunk {
std::string actor; std::string actor;
Source source; Source source;
std::map<OverlayableItem::PolicyFlags, std::set<ResourceId>> policy_ids; std::map<PolicyFlags, std::set<ResourceId>> policy_ids;
}; };
class PackageFlattener { class PackageFlattener {
@@ -493,35 +493,12 @@ class PackageFlattener {
return false; return false;
} }
uint32_t policy_flags = 0; auto policy = overlayable_chunk->policy_ids.find(item.policies);
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);
if (policy != overlayable_chunk->policy_ids.end()) { if (policy != overlayable_chunk->policy_ids.end()) {
policy->second.insert(id); policy->second.insert(id);
} else { } else {
overlayable_chunk->policy_ids.insert( 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); ChunkWriter policy_writer(buffer);
auto* policy_type = policy_writer.StartChunk<ResTable_overlayable_policy_header>( auto* policy_type = policy_writer.StartChunk<ResTable_overlayable_policy_header>(
RES_TABLE_OVERLAYABLE_POLICY_TYPE); 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_type->entry_count = util::HostToDevice32(static_cast<uint32_t>(
policy_ids.second.size())); policy_ids.second.size()));
// Write the ids after the policy header // Write the ids after the policy header

View File

@@ -32,6 +32,8 @@ using ::testing::Gt;
using ::testing::IsNull; using ::testing::IsNull;
using ::testing::NotNull; using ::testing::NotNull;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace aapt { namespace aapt {
class TableFlattenerTest : public ::testing::Test { class TableFlattenerTest : public ::testing::Test {
@@ -671,9 +673,9 @@ TEST_F(TableFlattenerTest, ObfuscatingResourceNamesWithNameCollapseExemptionsSuc
TEST_F(TableFlattenerTest, FlattenOverlayable) { TEST_F(TableFlattenerTest, FlattenOverlayable) {
OverlayableItem overlayable_item(std::make_shared<Overlayable>("TestName", "overlay://theme")); OverlayableItem overlayable_item(std::make_shared<Overlayable>("TestName", "overlay://theme"));
overlayable_item.policies |= OverlayableItem::Policy::kProduct; overlayable_item.policies |= PolicyFlags::PRODUCT_PARTITION;
overlayable_item.policies |= OverlayableItem::Policy::kSystem; overlayable_item.policies |= PolicyFlags::SYSTEM_PARTITION;
overlayable_item.policies |= OverlayableItem::Policy::kVendor; overlayable_item.policies |= PolicyFlags::VENDOR_PARTITION;
std::string name = "com.app.test:integer/overlayable"; std::string name = "com.app.test:integer/overlayable";
std::unique_ptr<ResourceTable> table = std::unique_ptr<ResourceTable> table =
@@ -691,27 +693,27 @@ TEST_F(TableFlattenerTest, FlattenOverlayable) {
ASSERT_THAT(search_result.value().entry, NotNull()); ASSERT_THAT(search_result.value().entry, NotNull());
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_EQ(result_overlayable_item.policies, OverlayableItem::Policy::kSystem EXPECT_EQ(result_overlayable_item.policies, PolicyFlags::SYSTEM_PARTITION
| OverlayableItem::Policy::kVendor | PolicyFlags::VENDOR_PARTITION
| OverlayableItem::Policy::kProduct); | PolicyFlags::PRODUCT_PARTITION);
} }
TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) { TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) {
auto overlayable = std::make_shared<Overlayable>("TestName", "overlay://theme"); auto overlayable = std::make_shared<Overlayable>("TestName", "overlay://theme");
std::string name_zero = "com.app.test:integer/overlayable_zero_item"; std::string name_zero = "com.app.test:integer/overlayable_zero_item";
OverlayableItem overlayable_item_zero(overlayable); OverlayableItem overlayable_item_zero(overlayable);
overlayable_item_zero.policies |= OverlayableItem::Policy::kProduct; overlayable_item_zero.policies |= PolicyFlags::PRODUCT_PARTITION;
overlayable_item_zero.policies |= OverlayableItem::Policy::kSystem; overlayable_item_zero.policies |= PolicyFlags::SYSTEM_PARTITION;
std::string name_one = "com.app.test:integer/overlayable_one_item"; std::string name_one = "com.app.test:integer/overlayable_one_item";
OverlayableItem overlayable_item_one(overlayable); 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"; std::string name_two = "com.app.test:integer/overlayable_two_item";
OverlayableItem overlayable_item_two(overlayable); OverlayableItem overlayable_item_two(overlayable);
overlayable_item_two.policies |= OverlayableItem::Policy::kProduct; overlayable_item_two.policies |= PolicyFlags::PRODUCT_PARTITION;
overlayable_item_two.policies |= OverlayableItem::Policy::kSystem; overlayable_item_two.policies |= PolicyFlags::SYSTEM_PARTITION;
overlayable_item_two.policies |= OverlayableItem::Policy::kVendor; overlayable_item_two.policies |= PolicyFlags::VENDOR_PARTITION;
std::unique_ptr<ResourceTable> table = std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder() test::ResourceTableBuilder()
@@ -732,47 +734,48 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) {
ASSERT_THAT(search_result.value().entry, NotNull()); ASSERT_THAT(search_result.value().entry, NotNull());
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value(); OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kSystem EXPECT_EQ(overlayable_item.policies, PolicyFlags::SYSTEM_PARTITION
| OverlayableItem::Policy::kProduct); | PolicyFlags::PRODUCT_PARTITION);
search_result = output_table.FindResource(test::ParseNameOrDie(name_one)); search_result = output_table.FindResource(test::ParseNameOrDie(name_one));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull()); ASSERT_THAT(search_result.value().entry, NotNull());
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
overlayable_item = search_result.value().entry->overlayable_item.value(); 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)); search_result = output_table.FindResource(test::ParseNameOrDie(name_two));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
ASSERT_THAT(search_result.value().entry, NotNull()); ASSERT_THAT(search_result.value().entry, NotNull());
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
overlayable_item = search_result.value().entry->overlayable_item.value(); overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kSystem EXPECT_EQ(overlayable_item.policies, PolicyFlags::SYSTEM_PARTITION
| OverlayableItem::Policy::kProduct | PolicyFlags::PRODUCT_PARTITION
| OverlayableItem::Policy::kVendor); | PolicyFlags::VENDOR_PARTITION);
} }
TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) { TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
auto group = std::make_shared<Overlayable>("TestName", "overlay://theme"); auto group = std::make_shared<Overlayable>("TestName", "overlay://theme");
std::string name_zero = "com.app.test:integer/overlayable_zero"; std::string name_zero = "com.app.test:integer/overlayable_zero";
OverlayableItem overlayable_item_zero(group); OverlayableItem overlayable_item_zero(group);
overlayable_item_zero.policies |= OverlayableItem::Policy::kProduct; overlayable_item_zero.policies |= PolicyFlags::PRODUCT_PARTITION;
overlayable_item_zero.policies |= OverlayableItem::Policy::kSystem; overlayable_item_zero.policies |= PolicyFlags::SYSTEM_PARTITION;
auto group_one = std::make_shared<Overlayable>("OtherName", "overlay://customization"); auto group_one = std::make_shared<Overlayable>("OtherName", "overlay://customization");
std::string name_one = "com.app.test:integer/overlayable_one"; std::string name_one = "com.app.test:integer/overlayable_one";
OverlayableItem overlayable_item_one(group_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"; std::string name_two = "com.app.test:integer/overlayable_two";
OverlayableItem overlayable_item_two(group); OverlayableItem overlayable_item_two(group);
overlayable_item_two.policies |= OverlayableItem::Policy::kOdm; overlayable_item_two.policies |= PolicyFlags::ODM_PARTITION;
overlayable_item_two.policies |= OverlayableItem::Policy::kOem; overlayable_item_two.policies |= PolicyFlags::OEM_PARTITION;
overlayable_item_two.policies |= OverlayableItem::Policy::kVendor; overlayable_item_two.policies |= PolicyFlags::VENDOR_PARTITION;
std::string name_three = "com.app.test:integer/overlayable_three"; std::string name_three = "com.app.test:integer/overlayable_three";
OverlayableItem overlayable_item_three(group_one); OverlayableItem overlayable_item_three(group_one);
overlayable_item_three.policies |= OverlayableItem::Policy::kSignature; overlayable_item_three.policies |= PolicyFlags::SIGNATURE;
overlayable_item_three.policies |= PolicyFlags::ACTOR_SIGNATURE;
std::unique_ptr<ResourceTable> table = std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder() test::ResourceTableBuilder()
@@ -796,8 +799,8 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
OverlayableItem& result_overlayable = search_result.value().entry->overlayable_item.value(); OverlayableItem& result_overlayable = search_result.value().entry->overlayable_item.value();
EXPECT_EQ(result_overlayable.overlayable->name, "TestName"); EXPECT_EQ(result_overlayable.overlayable->name, "TestName");
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme"); EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme");
EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSystem EXPECT_EQ(result_overlayable.policies, PolicyFlags::SYSTEM_PARTITION
| OverlayableItem::Policy::kProduct); | PolicyFlags::PRODUCT_PARTITION);
search_result = output_table.FindResource(test::ParseNameOrDie(name_one)); search_result = output_table.FindResource(test::ParseNameOrDie(name_one));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -806,7 +809,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
result_overlayable = search_result.value().entry->overlayable_item.value(); result_overlayable = search_result.value().entry->overlayable_item.value();
EXPECT_EQ(result_overlayable.overlayable->name, "OtherName"); EXPECT_EQ(result_overlayable.overlayable->name, "OtherName");
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization"); 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)); search_result = output_table.FindResource(test::ParseNameOrDie(name_two));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -815,9 +818,9 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
result_overlayable = search_result.value().entry->overlayable_item.value(); result_overlayable = search_result.value().entry->overlayable_item.value();
EXPECT_EQ(result_overlayable.overlayable->name, "TestName"); EXPECT_EQ(result_overlayable.overlayable->name, "TestName");
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme"); EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://theme");
EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kOdm EXPECT_EQ(result_overlayable.policies, PolicyFlags::ODM_PARTITION
| OverlayableItem::Policy::kOem | PolicyFlags::OEM_PARTITION
| OverlayableItem::Policy::kVendor); | PolicyFlags::VENDOR_PARTITION);
search_result = output_table.FindResource(test::ParseNameOrDie(name_three)); search_result = output_table.FindResource(test::ParseNameOrDie(name_three));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -826,7 +829,8 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
result_overlayable = search_result.value().entry->overlayable_item.value(); result_overlayable = search_result.value().entry->overlayable_item.value();
EXPECT_EQ(result_overlayable.overlayable->name, "OtherName"); EXPECT_EQ(result_overlayable.overlayable->name, "OtherName");
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization"); EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization");
EXPECT_EQ(result_overlayable.policies, OverlayableItem::Policy::kSignature); EXPECT_EQ(result_overlayable.policies, PolicyFlags::SIGNATURE
| PolicyFlags::ACTOR_SIGNATURE);
} }
TEST_F(TableFlattenerTest, FlattenOverlayableNoPolicyFails) { TEST_F(TableFlattenerTest, FlattenOverlayableNoPolicyFails) {

View File

@@ -30,6 +30,8 @@ using ::android::ConfigDescription;
using ::android::LocaleValue; using ::android::LocaleValue;
using ::android::ResStringPool; using ::android::ResStringPool;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace aapt { namespace aapt {
namespace { namespace {
@@ -379,25 +381,28 @@ bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable,
for (const int policy : pb_overlayable.policy()) { for (const int policy : pb_overlayable.policy()) {
switch (policy) { switch (policy) {
case pb::OverlayableItem::PUBLIC: case pb::OverlayableItem::PUBLIC:
out_overlayable->policies |= OverlayableItem::Policy::kPublic; out_overlayable->policies |= PolicyFlags::PUBLIC;
break; break;
case pb::OverlayableItem::SYSTEM: case pb::OverlayableItem::SYSTEM:
out_overlayable->policies |= OverlayableItem::Policy::kSystem; out_overlayable->policies |= PolicyFlags::SYSTEM_PARTITION;
break; break;
case pb::OverlayableItem::VENDOR: case pb::OverlayableItem::VENDOR:
out_overlayable->policies |= OverlayableItem::Policy::kVendor; out_overlayable->policies |= PolicyFlags::VENDOR_PARTITION;
break; break;
case pb::OverlayableItem::PRODUCT: case pb::OverlayableItem::PRODUCT:
out_overlayable->policies |= OverlayableItem::Policy::kProduct; out_overlayable->policies |= PolicyFlags::PRODUCT_PARTITION;
break; break;
case pb::OverlayableItem::SIGNATURE: case pb::OverlayableItem::SIGNATURE:
out_overlayable->policies |= OverlayableItem::Policy::kSignature; out_overlayable->policies |= PolicyFlags::SIGNATURE;
break; break;
case pb::OverlayableItem::ODM: case pb::OverlayableItem::ODM:
out_overlayable->policies |= OverlayableItem::Policy::kOdm; out_overlayable->policies |= PolicyFlags::ODM_PARTITION;
break; break;
case pb::OverlayableItem::OEM: case pb::OverlayableItem::OEM:
out_overlayable->policies |= OverlayableItem::Policy::kOem; out_overlayable->policies |= PolicyFlags::OEM_PARTITION;
break;
case pb::OverlayableItem::ACTOR:
out_overlayable->policies |= PolicyFlags::ACTOR_SIGNATURE;
break; break;
default: default:
*out_error = "unknown overlayable policy"; *out_error = "unknown overlayable policy";

View File

@@ -21,6 +21,8 @@
using android::ConfigDescription; using android::ConfigDescription;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace aapt { namespace aapt {
void SerializeStringPoolToPb(const StringPool& pool, pb::StringPool* out_pb_pool, IDiagnostics* diag) { void SerializeStringPoolToPb(const StringPool& pool, pb::StringPool* out_pb_pool, IDiagnostics* diag) {
@@ -299,27 +301,30 @@ static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item
pb::OverlayableItem* pb_overlayable_item = pb_entry->mutable_overlayable_item(); pb::OverlayableItem* pb_overlayable_item = pb_entry->mutable_overlayable_item();
pb_overlayable_item->set_overlayable_idx(i); 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); 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); 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); 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); 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); 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); 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); pb_overlayable_item->add_policy(pb::OverlayableItem::OEM);
} }
if (overlayable_item.policies & PolicyFlags::ACTOR_SIGNATURE) {
pb_overlayable_item->add_policy(pb::OverlayableItem::ACTOR);
}
if (source_pool != nullptr) { if (source_pool != nullptr) {
SerializeSourceToPb(overlayable_item.source, source_pool, SerializeSourceToPb(overlayable_item.source, source_pool,

View File

@@ -28,6 +28,8 @@ using ::testing::NotNull;
using ::testing::SizeIs; using ::testing::SizeIs;
using ::testing::StrEq; using ::testing::StrEq;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace aapt { namespace aapt {
class MockFileCollection : public io::IFileCollection { 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->actor, Eq("overlay://theme"));
EXPECT_THAT(result_overlayable_item.overlayable->source.path, Eq("res/values/overlayable.xml")); 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.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.path, Eq("res/values/overlayable.xml"));
EXPECT_THAT(result_overlayable_item.source.line, Eq(42)); EXPECT_THAT(result_overlayable_item.source.line, Eq(42));
} }
@@ -516,23 +518,28 @@ TEST(ProtoSerializeTest, SerializeDeserializeConfiguration) {
TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
OverlayableItem overlayable_item_foo(std::make_shared<Overlayable>( OverlayableItem overlayable_item_foo(std::make_shared<Overlayable>(
"CustomizableResources", "overlay://customization")); "CustomizableResources", "overlay://customization"));
overlayable_item_foo.policies |= OverlayableItem::Policy::kSystem; overlayable_item_foo.policies |= PolicyFlags::SYSTEM_PARTITION;
overlayable_item_foo.policies |= OverlayableItem::Policy::kProduct; overlayable_item_foo.policies |= PolicyFlags::PRODUCT_PARTITION;
OverlayableItem overlayable_item_bar(std::make_shared<Overlayable>( OverlayableItem overlayable_item_bar(std::make_shared<Overlayable>(
"TaskBar", "overlay://theme")); "TaskBar", "overlay://theme"));
overlayable_item_bar.policies |= OverlayableItem::Policy::kPublic; overlayable_item_bar.policies |= PolicyFlags::PUBLIC;
overlayable_item_bar.policies |= OverlayableItem::Policy::kVendor; overlayable_item_bar.policies |= PolicyFlags::VENDOR_PARTITION;
OverlayableItem overlayable_item_baz(std::make_shared<Overlayable>( OverlayableItem overlayable_item_baz(std::make_shared<Overlayable>(
"FontPack", "overlay://theme")); "FontPack", "overlay://theme"));
overlayable_item_baz.policies |= OverlayableItem::Policy::kPublic; overlayable_item_baz.policies |= PolicyFlags::PUBLIC;
OverlayableItem overlayable_item_boz(std::make_shared<Overlayable>( OverlayableItem overlayable_item_boz(std::make_shared<Overlayable>(
"IconPack", "overlay://theme")); "IconPack", "overlay://theme"));
overlayable_item_boz.policies |= OverlayableItem::Policy::kSignature; overlayable_item_boz.policies |= PolicyFlags::SIGNATURE;
overlayable_item_boz.policies |= OverlayableItem::Policy::kOdm; overlayable_item_boz.policies |= PolicyFlags::ODM_PARTITION;
overlayable_item_boz.policies |= OverlayableItem::Policy::kOem; overlayable_item_boz.policies |= PolicyFlags::OEM_PARTITION;
OverlayableItem overlayable_item_actor_config(std::make_shared<Overlayable>(
"ActorConfig", "overlay://theme"));
overlayable_item_actor_config.policies |= PolicyFlags::SIGNATURE;
overlayable_item_actor_config.policies |= PolicyFlags::ACTOR_SIGNATURE;
OverlayableItem overlayable_item_biz(std::make_shared<Overlayable>( OverlayableItem overlayable_item_biz(std::make_shared<Overlayable>(
"Other", "overlay://customization")); "Other", "overlay://customization"));
@@ -546,6 +553,7 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
.SetOverlayable("com.app.a:bool/baz", overlayable_item_baz) .SetOverlayable("com.app.a:bool/baz", overlayable_item_baz)
.SetOverlayable("com.app.a:bool/boz", overlayable_item_boz) .SetOverlayable("com.app.a:bool/boz", overlayable_item_boz)
.SetOverlayable("com.app.a:bool/biz", overlayable_item_biz) .SetOverlayable("com.app.a:bool/biz", overlayable_item_biz)
.SetOverlayable("com.app.a:bool/actor_config", overlayable_item_actor_config)
.AddValue("com.app.a:bool/fiz", ResourceUtils::TryParseBool("true")) .AddValue("com.app.a:bool/fiz", ResourceUtils::TryParseBool("true"))
.Build(); .Build();
@@ -565,8 +573,8 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value(); OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(overlayable_item.overlayable->name, Eq("CustomizableResources")); EXPECT_THAT(overlayable_item.overlayable->name, Eq("CustomizableResources"));
EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://customization")); EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://customization"));
EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kSystem EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::SYSTEM_PARTITION
| OverlayableItem::Policy::kProduct)); | PolicyFlags::PRODUCT_PARTITION));
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/bar")); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/bar"));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -574,8 +582,8 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
overlayable_item = search_result.value().entry->overlayable_item.value(); overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(overlayable_item.overlayable->name, Eq("TaskBar")); EXPECT_THAT(overlayable_item.overlayable->name, Eq("TaskBar"));
EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme")); 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
| OverlayableItem::Policy::kVendor)); | PolicyFlags::VENDOR_PARTITION));
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/baz")); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/baz"));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -583,7 +591,7 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
overlayable_item = search_result.value().entry->overlayable_item.value(); overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(overlayable_item.overlayable->name, Eq("FontPack")); EXPECT_THAT(overlayable_item.overlayable->name, Eq("FontPack"));
EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme")); 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")); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/boz"));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
@@ -591,16 +599,25 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) {
overlayable_item = search_result.value().entry->overlayable_item.value(); overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(overlayable_item.overlayable->name, Eq("IconPack")); EXPECT_THAT(overlayable_item.overlayable->name, Eq("IconPack"));
EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme")); EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme"));
EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kSignature EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::SIGNATURE
| OverlayableItem::Policy::kOdm | PolicyFlags::ODM_PARTITION
| OverlayableItem::Policy::kOem)); | PolicyFlags::OEM_PARTITION));
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/actor_config"));
ASSERT_TRUE(search_result);
ASSERT_TRUE(search_result.value().entry->overlayable_item);
overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(overlayable_item.overlayable->name, Eq("ActorConfig"));
EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme"));
EXPECT_THAT(overlayable_item.policies, Eq(PolicyFlags::SIGNATURE
| PolicyFlags::ACTOR_SIGNATURE));
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/biz")); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/biz"));
ASSERT_TRUE(search_result); ASSERT_TRUE(search_result);
ASSERT_TRUE(search_result.value().entry->overlayable_item); ASSERT_TRUE(search_result.value().entry->overlayable_item);
overlayable_item = search_result.value().entry->overlayable_item.value(); overlayable_item = search_result.value().entry->overlayable_item.value();
EXPECT_THAT(overlayable_item.overlayable->name, Eq("Other")); 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")); EXPECT_THAT(overlayable_item.comment, Eq("comment"));
search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/fiz")); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/fiz"));

View File

@@ -29,6 +29,8 @@ using ::testing::Pointee;
using ::testing::StrEq; using ::testing::StrEq;
using ::testing::UnorderedElementsAreArray; using ::testing::UnorderedElementsAreArray;
using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
namespace aapt { namespace aapt {
struct TableMergerTest : public ::testing::Test { struct TableMergerTest : public ::testing::Test {
@@ -487,8 +489,8 @@ TEST_F(TableMergerTest, SetOverlayable) {
auto overlayable = std::make_shared<Overlayable>("CustomizableResources", auto overlayable = std::make_shared<Overlayable>("CustomizableResources",
"overlay://customization"); "overlay://customization");
OverlayableItem overlayable_item(overlayable); OverlayableItem overlayable_item(overlayable);
overlayable_item.policies |= OverlayableItem::Policy::kProduct; overlayable_item.policies |= PolicyFlags::PRODUCT_PARTITION;
overlayable_item.policies |= OverlayableItem::Policy::kVendor; overlayable_item.policies |= PolicyFlags::VENDOR_PARTITION;
std::unique_ptr<ResourceTable> table_a = std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder() test::ResourceTableBuilder()
@@ -516,8 +518,8 @@ TEST_F(TableMergerTest, SetOverlayable) {
OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); 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->name, Eq("CustomizableResources"));
EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://customization")); EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://customization"));
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PRODUCT_PARTITION
| OverlayableItem::Policy::kVendor)); | PolicyFlags::VENDOR_PARTITION));
} }
TEST_F(TableMergerTest, SetOverlayableLater) { TEST_F(TableMergerTest, SetOverlayableLater) {
@@ -530,8 +532,8 @@ TEST_F(TableMergerTest, SetOverlayableLater) {
.Build(); .Build();
OverlayableItem overlayable_item(overlayable); OverlayableItem overlayable_item(overlayable);
overlayable_item.policies |= OverlayableItem::Policy::kPublic; overlayable_item.policies |= PolicyFlags::PUBLIC;
overlayable_item.policies |= OverlayableItem::Policy::kSystem; overlayable_item.policies |= PolicyFlags::SYSTEM_PARTITION;
std::unique_ptr<ResourceTable> table_b = std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder() test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f) .SetPackageId("com.app.a", 0x7f)
@@ -552,15 +554,15 @@ TEST_F(TableMergerTest, SetOverlayableLater) {
OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); 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->name, Eq("CustomizableResources"));
EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://customization")); EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://customization"));
EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic EXPECT_THAT(result_overlayable_item.policies, Eq(PolicyFlags::PUBLIC
| OverlayableItem::Policy::kSystem)); | PolicyFlags::SYSTEM_PARTITION));
} }
TEST_F(TableMergerTest, SameResourceDifferentNameFail) { TEST_F(TableMergerTest, SameResourceDifferentNameFail) {
auto overlayable_first = std::make_shared<Overlayable>("CustomizableResources", auto overlayable_first = std::make_shared<Overlayable>("CustomizableResources",
"overlay://customization"); "overlay://customization");
OverlayableItem overlayable_item_first(overlayable_first); 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 = std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder() test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f) .SetPackageId("com.app.a", 0x7f)
@@ -570,7 +572,7 @@ TEST_F(TableMergerTest, SameResourceDifferentNameFail) {
auto overlayable_second = std::make_shared<Overlayable>("ThemeResources", auto overlayable_second = std::make_shared<Overlayable>("ThemeResources",
"overlay://customization"); "overlay://customization");
OverlayableItem overlayable_item_second(overlayable_second); 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 = std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder() test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f) .SetPackageId("com.app.a", 0x7f)
@@ -589,7 +591,7 @@ TEST_F(TableMergerTest, SameResourceDifferentActorFail) {
auto overlayable_first = std::make_shared<Overlayable>("CustomizableResources", auto overlayable_first = std::make_shared<Overlayable>("CustomizableResources",
"overlay://customization"); "overlay://customization");
OverlayableItem overlayable_item_first(overlayable_first); 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 = std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder() test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f) .SetPackageId("com.app.a", 0x7f)
@@ -599,7 +601,7 @@ TEST_F(TableMergerTest, SameResourceDifferentActorFail) {
auto overlayable_second = std::make_shared<Overlayable>("CustomizableResources", auto overlayable_second = std::make_shared<Overlayable>("CustomizableResources",
"overlay://theme"); "overlay://theme");
OverlayableItem overlayable_item_second(overlayable_second); 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 = std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder() test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f) .SetPackageId("com.app.a", 0x7f)
@@ -618,7 +620,7 @@ TEST_F(TableMergerTest, SameResourceDifferentPoliciesFail) {
auto overlayable_first = std::make_shared<Overlayable>("CustomizableResources", auto overlayable_first = std::make_shared<Overlayable>("CustomizableResources",
"overlay://customization"); "overlay://customization");
OverlayableItem overlayable_item_first(overlayable_first); 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 = std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder() test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f) .SetPackageId("com.app.a", 0x7f)
@@ -628,7 +630,7 @@ TEST_F(TableMergerTest, SameResourceDifferentPoliciesFail) {
auto overlayable_second = std::make_shared<Overlayable>("CustomizableResources", auto overlayable_second = std::make_shared<Overlayable>("CustomizableResources",
"overlay://customization"); "overlay://customization");
OverlayableItem overlayable_item_second(overlayable_second); 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 = std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder() test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f) .SetPackageId("com.app.a", 0x7f)
@@ -648,7 +650,7 @@ TEST_F(TableMergerTest, SameResourceSameOverlayable) {
"overlay://customization"); "overlay://customization");
OverlayableItem overlayable_item_first(overlayable); 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 = std::unique_ptr<ResourceTable> table_a =
test::ResourceTableBuilder() test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f) .SetPackageId("com.app.a", 0x7f)
@@ -656,7 +658,7 @@ TEST_F(TableMergerTest, SameResourceSameOverlayable) {
.Build(); .Build();
OverlayableItem overlayable_item_second(overlayable); 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 = std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder() test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f) .SetPackageId("com.app.a", 0x7f)