Merge "Fix resourcesMap to work with shared libraries"
This commit is contained in:
committed by
Android (Google) Code Review
commit
ca445c49b2
@@ -37,6 +37,10 @@ typedef uint16_t EntryId; // eeee in 0xpptteeee
|
||||
|
||||
namespace utils {
|
||||
|
||||
// Returns whether the Res_value::data_type represents a dynamic or regular resource reference.
|
||||
bool IsReference(uint8_t data_type);
|
||||
|
||||
// Converts the Res_value::data_type to a human-readable string representation.
|
||||
StringPiece DataTypeToString(uint8_t data_type);
|
||||
|
||||
struct OverlayManifestInfo {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "idmap2/ResourceUtils.h"
|
||||
|
||||
using android::base::StringPrintf;
|
||||
using android::idmap2::utils::IsReference;
|
||||
using android::idmap2::utils::ResToTypeEntryName;
|
||||
|
||||
namespace android::idmap2 {
|
||||
@@ -200,8 +201,7 @@ Result<ResourceMapping> ResourceMapping::CreateResourceMapping(const AssetManage
|
||||
// Only rewrite resources defined within the overlay package to their corresponding target
|
||||
// resource ids at runtime.
|
||||
bool rewrite_overlay_reference =
|
||||
(overlay_resource->dataType == Res_value::TYPE_REFERENCE ||
|
||||
overlay_resource->dataType == Res_value::TYPE_DYNAMIC_REFERENCE)
|
||||
IsReference(overlay_resource->dataType)
|
||||
? overlay_package_id == EXTRACT_PACKAGE(overlay_resource->data)
|
||||
: false;
|
||||
|
||||
@@ -331,8 +331,13 @@ Result<ResourceMapping> ResourceMapping::FromApkAssets(const ApkAssets& target_a
|
||||
std::unique_ptr<uint8_t[]> string_pool_data;
|
||||
Result<ResourceMapping> resource_mapping = {{}};
|
||||
if (overlay_info.resource_mapping != 0U) {
|
||||
// Use the dynamic reference table to find the assigned resource id of the map xml.
|
||||
const auto& ref_table = overlay_asset_manager.GetDynamicRefTableForCookie(0);
|
||||
uint32_t resource_mapping_id = overlay_info.resource_mapping;
|
||||
ref_table->lookupResourceId(&resource_mapping_id);
|
||||
|
||||
// Load the overlay resource mappings from the file specified using android:resourcesMap.
|
||||
auto asset = OpenNonAssetFromResource(overlay_info.resource_mapping, overlay_asset_manager);
|
||||
auto asset = OpenNonAssetFromResource(resource_mapping_id, overlay_asset_manager);
|
||||
if (!asset) {
|
||||
return Error("failed opening xml for android:resourcesMap: %s",
|
||||
asset.GetErrorMessage().c_str());
|
||||
@@ -404,8 +409,7 @@ Result<Unit> ResourceMapping::AddMapping(ResourceId target_resource,
|
||||
|
||||
target_map_.insert(std::make_pair(target_resource, TargetValue{data_type, data_value}));
|
||||
|
||||
if (rewrite_overlay_reference &&
|
||||
(data_type == Res_value::TYPE_REFERENCE || data_type == Res_value::TYPE_DYNAMIC_REFERENCE)) {
|
||||
if (rewrite_overlay_reference && IsReference(data_type)) {
|
||||
overlay_map_.insert(std::make_pair(data_value, target_resource));
|
||||
}
|
||||
|
||||
@@ -421,8 +425,7 @@ void ResourceMapping::RemoveMapping(ResourceId target_resource) {
|
||||
const TargetValue value = target_iter->second;
|
||||
target_map_.erase(target_iter);
|
||||
|
||||
if (value.data_type != Res_value::TYPE_REFERENCE &&
|
||||
value.data_type != Res_value::TYPE_DYNAMIC_REFERENCE) {
|
||||
if (!IsReference(value.data_type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,10 @@ using android::util::Utf16ToUtf8;
|
||||
|
||||
namespace android::idmap2::utils {
|
||||
|
||||
bool IsReference(uint8_t data_type) {
|
||||
return data_type == Res_value::TYPE_REFERENCE || data_type == Res_value::TYPE_DYNAMIC_REFERENCE;
|
||||
}
|
||||
|
||||
StringPiece DataTypeToString(uint8_t data_type) {
|
||||
switch (data_type) {
|
||||
case Res_value::TYPE_NULL:
|
||||
@@ -133,7 +137,7 @@ Result<OverlayManifestInfo> ExtractOverlayManifestInfo(const std::string& path,
|
||||
}
|
||||
|
||||
if (auto result_value = overlay_it->GetAttributeValue("resourcesMap")) {
|
||||
if ((*result_value).dataType == Res_value::TYPE_REFERENCE) {
|
||||
if (IsReference((*result_value).dataType)) {
|
||||
info.resource_mapping = (*result_value).data;
|
||||
} else {
|
||||
return Error("android:resourcesMap is not a reference in AndroidManifest.xml of %s",
|
||||
|
||||
@@ -56,12 +56,12 @@ TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) {
|
||||
return type == DT_REG && path.size() > 4 && path.compare(path.size() - 4, 4, ".apk") == 0;
|
||||
});
|
||||
ASSERT_THAT(v, NotNull());
|
||||
ASSERT_EQ(v->size(), 10U);
|
||||
ASSERT_EQ(v->size(), 11U);
|
||||
ASSERT_EQ(std::set<std::string>(v->begin(), v->end()),
|
||||
std::set<std::string>(
|
||||
{root + "/target/target.apk", root + "/target/target-no-overlayable.apk",
|
||||
root + "/overlay/overlay.apk", root + "/overlay/overlay-no-name.apk",
|
||||
root + "/overlay/overlay-no-name-static.apk",
|
||||
root + "/overlay/overlay-no-name-static.apk", root + "/overlay/overlay-shared.apk",
|
||||
root + "/overlay/overlay-static-1.apk", root + "/overlay/overlay-static-2.apk",
|
||||
root + "/signature-overlay/signature-overlay.apk",
|
||||
root + "/system-overlay/system-overlay.apk",
|
||||
|
||||
@@ -247,6 +247,43 @@ TEST(IdmapTests, CreateIdmapDataFromApkAssets) {
|
||||
ASSERT_OVERLAY_ENTRY(overlay_entries[3], 0x7f020002, 0x7f02000f);
|
||||
}
|
||||
|
||||
TEST(IdmapTests, CreateIdmapDataFromApkAssetsSharedLibOverlay) {
|
||||
std::string target_apk_path = GetTestDataPath() + "/target/target.apk";
|
||||
std::string overlay_apk_path = GetTestDataPath() + "/overlay/overlay-shared.apk";
|
||||
|
||||
std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
|
||||
ASSERT_THAT(target_apk, NotNull());
|
||||
|
||||
std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
|
||||
ASSERT_THAT(overlay_apk, NotNull());
|
||||
|
||||
auto idmap_result = Idmap::FromApkAssets(*target_apk, *overlay_apk, PolicyFlags::POLICY_PUBLIC,
|
||||
/* enforce_overlayable */ true);
|
||||
ASSERT_TRUE(idmap_result) << idmap_result.GetErrorMessage();
|
||||
auto& idmap = *idmap_result;
|
||||
ASSERT_THAT(idmap, NotNull());
|
||||
|
||||
const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
|
||||
ASSERT_EQ(dataBlocks.size(), 1U);
|
||||
|
||||
const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
|
||||
ASSERT_THAT(data, NotNull());
|
||||
|
||||
const auto& target_entries = data->GetTargetEntries();
|
||||
ASSERT_EQ(target_entries.size(), 4U);
|
||||
ASSERT_TARGET_ENTRY(target_entries[0], 0x7f010000, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00010000);
|
||||
ASSERT_TARGET_ENTRY(target_entries[1], 0x7f02000c, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020000);
|
||||
ASSERT_TARGET_ENTRY(target_entries[2], 0x7f02000e, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020001);
|
||||
ASSERT_TARGET_ENTRY(target_entries[3], 0x7f02000f, Res_value::TYPE_DYNAMIC_REFERENCE, 0x00020002);
|
||||
|
||||
const auto& overlay_entries = data->GetOverlayEntries();
|
||||
ASSERT_EQ(target_entries.size(), 4U);
|
||||
ASSERT_OVERLAY_ENTRY(overlay_entries[0], 0x00010000, 0x7f010000);
|
||||
ASSERT_OVERLAY_ENTRY(overlay_entries[1], 0x00020000, 0x7f02000c);
|
||||
ASSERT_OVERLAY_ENTRY(overlay_entries[2], 0x00020001, 0x7f02000e);
|
||||
ASSERT_OVERLAY_ENTRY(overlay_entries[3], 0x00020002, 0x7f02000f);
|
||||
}
|
||||
|
||||
TEST(IdmapTests, CreateIdmapDataDoNotRewriteNonOverlayResourceId) {
|
||||
OverlayManifestInfo info{};
|
||||
info.target_package = "test.target";
|
||||
|
||||
@@ -51,4 +51,12 @@ aapt2 link \
|
||||
-o overlay-static-2.apk \
|
||||
compiled.flata
|
||||
|
||||
aapt2 link \
|
||||
--no-resource-removal \
|
||||
--shared-lib \
|
||||
-I "$FRAMEWORK_RES_APK" \
|
||||
--manifest AndroidManifest.xml \
|
||||
-o overlay-shared.apk \
|
||||
compiled.flata
|
||||
|
||||
rm compiled.flata
|
||||
|
||||
BIN
cmds/idmap2/tests/data/overlay/overlay-shared.apk
Normal file
BIN
cmds/idmap2/tests/data/overlay/overlay-shared.apk
Normal file
Binary file not shown.
Reference in New Issue
Block a user