Merge "Store frro configs in idmap file"
This commit is contained in:
@@ -21,42 +21,51 @@
|
||||
* header := magic version target_crc overlay_crc fulfilled_policies
|
||||
* enforce_overlayable target_path overlay_path overlay_name
|
||||
* debug_info
|
||||
* data := data_header target_entry* target_inline_entry* overlay_entry*
|
||||
* string_pool
|
||||
* data_header := target_entry_count target_inline_entry_count overlay_entry_count
|
||||
* data := data_header target_entry* target_inline_entry*
|
||||
target_inline_entry_value* config* overlay_entry* string_pool
|
||||
* data_header := target_entry_count target_inline_entry_count
|
||||
target_inline_entry_value_count config_count overlay_entry_count
|
||||
* string_pool_index
|
||||
* target_entry := target_id overlay_id
|
||||
* target_inline_entry := target_id Res_value::size padding(1) Res_value::type
|
||||
* target_inline_entry := target_id start_value_index value_count
|
||||
* target_inline_entry_value := config_index Res_value::size padding(1) Res_value::type
|
||||
* Res_value::value
|
||||
* config := target_id Res_value::size padding(1) Res_value::type
|
||||
* Res_value::value
|
||||
* overlay_entry := overlay_id target_id
|
||||
*
|
||||
* debug_info := string
|
||||
* enforce_overlayable := <uint32_t>
|
||||
* fulfilled_policies := <uint32_t>
|
||||
* magic := <uint32_t>
|
||||
* overlay_crc := <uint32_t>
|
||||
* overlay_entry_count := <uint32_t>
|
||||
* overlay_id := <uint32_t>
|
||||
* overlay_package_id := <uint8_t>
|
||||
* overlay_name := string
|
||||
* overlay_path := string
|
||||
* padding(n) := <uint8_t>[n]
|
||||
* Res_value::size := <uint16_t>
|
||||
* Res_value::type := <uint8_t>
|
||||
* Res_value::value := <uint32_t>
|
||||
* string := <uint32_t> <uint8_t>+ padding(n)
|
||||
* string_pool := string
|
||||
* string_pool_index := <uint32_t>
|
||||
* string_pool_length := <uint32_t>
|
||||
* target_crc := <uint32_t>
|
||||
* target_entry_count := <uint32_t>
|
||||
* target_inline_entry_count := <uint32_t>
|
||||
* target_id := <uint32_t>
|
||||
* target_package_id := <uint8_t>
|
||||
* target_path := string
|
||||
* value_type := <uint8_t>
|
||||
* value_data := <uint32_t>
|
||||
* version := <uint32_t>
|
||||
* debug_info := string
|
||||
* enforce_overlayable := <uint32_t>
|
||||
* fulfilled_policies := <uint32_t>
|
||||
* magic := <uint32_t>
|
||||
* overlay_crc := <uint32_t>
|
||||
* overlay_entry_count := <uint32_t>
|
||||
* overlay_id := <uint32_t>
|
||||
* overlay_package_id := <uint8_t>
|
||||
* overlay_name := string
|
||||
* overlay_path := string
|
||||
* padding(n) := <uint8_t>[n]
|
||||
* Res_value::size := <uint16_t>
|
||||
* Res_value::type := <uint8_t>
|
||||
* Res_value::value := <uint32_t>
|
||||
* string := <uint32_t> <uint8_t>+ padding(n)
|
||||
* string_pool := string
|
||||
* string_pool_index := <uint32_t>
|
||||
* string_pool_length := <uint32_t>
|
||||
* target_crc := <uint32_t>
|
||||
* target_entry_count := <uint32_t>
|
||||
* target_inline_entry_count := <uint32_t>
|
||||
* target_inline_entry_value_count := <uint32_t>
|
||||
* config_count := <uint32_t>
|
||||
* config_index := <uint32_t>
|
||||
* start_value_index := <uint32_t>
|
||||
* value_count := <uint32_t>
|
||||
* target_id := <uint32_t>
|
||||
* target_package_id := <uint8_t>
|
||||
* target_path := string
|
||||
* value_type := <uint8_t>
|
||||
* value_data := <uint32_t>
|
||||
* version := <uint32_t>
|
||||
*/
|
||||
|
||||
#ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_
|
||||
@@ -70,6 +79,7 @@
|
||||
#include "android-base/macros.h"
|
||||
#include "androidfw/ResourceTypes.h"
|
||||
#include "androidfw/StringPiece.h"
|
||||
#include "androidfw/ConfigDescription.h"
|
||||
#include "idmap2/ResourceContainer.h"
|
||||
#include "idmap2/ResourceMapping.h"
|
||||
|
||||
@@ -165,19 +175,27 @@ class IdmapData {
|
||||
public:
|
||||
static std::unique_ptr<const Header> FromBinaryStream(std::istream& stream);
|
||||
|
||||
inline uint32_t GetTargetEntryCount() const {
|
||||
[[nodiscard]] inline uint32_t GetTargetEntryCount() const {
|
||||
return target_entry_count;
|
||||
}
|
||||
|
||||
inline uint32_t GetTargetInlineEntryCount() const {
|
||||
[[nodiscard]] inline uint32_t GetTargetInlineEntryCount() const {
|
||||
return target_entry_inline_count;
|
||||
}
|
||||
|
||||
inline uint32_t GetOverlayEntryCount() const {
|
||||
[[nodiscard]] inline uint32_t GetTargetInlineEntryValueCount() const {
|
||||
return target_entry_inline_value_count;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline uint32_t GetConfigCount() const {
|
||||
return config_count;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline uint32_t GetOverlayEntryCount() const {
|
||||
return overlay_entry_count;
|
||||
}
|
||||
|
||||
inline uint32_t GetStringPoolIndexOffset() const {
|
||||
[[nodiscard]] inline uint32_t GetStringPoolIndexOffset() const {
|
||||
return string_pool_index_offset;
|
||||
}
|
||||
|
||||
@@ -186,6 +204,8 @@ class IdmapData {
|
||||
private:
|
||||
uint32_t target_entry_count;
|
||||
uint32_t target_entry_inline_count;
|
||||
uint32_t target_entry_inline_value_count;
|
||||
uint32_t config_count;
|
||||
uint32_t overlay_entry_count;
|
||||
uint32_t string_pool_index_offset;
|
||||
Header() = default;
|
||||
@@ -202,7 +222,7 @@ class IdmapData {
|
||||
|
||||
struct TargetInlineEntry {
|
||||
ResourceId target_id;
|
||||
TargetValue value;
|
||||
std::map<ConfigDescription, TargetValue> values;
|
||||
};
|
||||
|
||||
struct OverlayEntry {
|
||||
@@ -227,11 +247,11 @@ class IdmapData {
|
||||
return target_inline_entries_;
|
||||
}
|
||||
|
||||
const std::vector<OverlayEntry>& GetOverlayEntries() const {
|
||||
[[nodiscard]] const std::vector<OverlayEntry>& GetOverlayEntries() const {
|
||||
return overlay_entries_;
|
||||
}
|
||||
|
||||
const std::string& GetStringPoolData() const {
|
||||
[[nodiscard]] const std::string& GetStringPoolData() const {
|
||||
return string_pool_data_;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask;
|
||||
|
||||
namespace android::idmap2 {
|
||||
using TargetResourceMap = std::map<ResourceId, std::variant<ResourceId, TargetValue>>;
|
||||
using ConfigMap = std::unordered_map<std::string, TargetValue>;
|
||||
using TargetResourceMap = std::map<ResourceId, std::variant<ResourceId, ConfigMap>>;
|
||||
using OverlayResourceMap = std::map<ResourceId, ResourceId>;
|
||||
|
||||
class ResourceMapping {
|
||||
|
||||
@@ -46,6 +46,10 @@ struct TargetValue {
|
||||
struct TargetValueWithConfig {
|
||||
TargetValue value;
|
||||
std::string config;
|
||||
|
||||
[[nodiscard]] std::pair<std::string, TargetValue> to_pair() const {
|
||||
return std::make_pair(config, value);
|
||||
}
|
||||
};
|
||||
|
||||
namespace utils {
|
||||
|
||||
@@ -70,12 +70,35 @@ void BinaryStreamVisitor::visit(const IdmapData& data) {
|
||||
}
|
||||
|
||||
static constexpr uint16_t kValueSize = 8U;
|
||||
std::vector<std::pair<ConfigDescription, TargetValue>> target_values;
|
||||
target_values.reserve(data.GetHeader()->GetTargetInlineEntryValueCount());
|
||||
for (const auto& target_entry : data.GetTargetInlineEntries()) {
|
||||
Write32(target_entry.target_id);
|
||||
Write32(target_values.size());
|
||||
Write32(target_entry.values.size());
|
||||
target_values.insert(
|
||||
target_values.end(), target_entry.values.begin(), target_entry.values.end());
|
||||
}
|
||||
|
||||
std::vector<ConfigDescription> configs;
|
||||
configs.reserve(data.GetHeader()->GetConfigCount());
|
||||
for (const auto& target_entry_value : target_values) {
|
||||
auto config_it = find(configs.begin(), configs.end(), target_entry_value.first);
|
||||
if (config_it != configs.end()) {
|
||||
Write32(config_it - configs.begin());
|
||||
} else {
|
||||
Write32(configs.size());
|
||||
configs.push_back(target_entry_value.first);
|
||||
}
|
||||
Write16(kValueSize);
|
||||
Write8(0U); // padding
|
||||
Write8(target_entry.value.data_type);
|
||||
Write32(target_entry.value.data_value);
|
||||
Write8(target_entry_value.second.data_type);
|
||||
Write32(target_entry_value.second.data_value);
|
||||
}
|
||||
|
||||
for( auto& cd : configs) {
|
||||
cd.swapHtoD();
|
||||
stream_.write(reinterpret_cast<char*>(&cd), sizeof(cd));
|
||||
}
|
||||
|
||||
for (const auto& overlay_entry : data.GetOverlayEntries()) {
|
||||
@@ -89,6 +112,8 @@ void BinaryStreamVisitor::visit(const IdmapData& data) {
|
||||
void BinaryStreamVisitor::visit(const IdmapData::Header& header) {
|
||||
Write32(header.GetTargetEntryCount());
|
||||
Write32(header.GetTargetInlineEntryCount());
|
||||
Write32(header.GetTargetInlineEntryValueCount());
|
||||
Write32(header.GetConfigCount());
|
||||
Write32(header.GetOverlayEntryCount());
|
||||
Write32(header.GetStringPoolIndexOffset());
|
||||
}
|
||||
|
||||
@@ -186,6 +186,8 @@ std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std
|
||||
std::unique_ptr<IdmapData::Header> idmap_data_header(new IdmapData::Header());
|
||||
if (!Read32(stream, &idmap_data_header->target_entry_count) ||
|
||||
!Read32(stream, &idmap_data_header->target_entry_inline_count) ||
|
||||
!Read32(stream, &idmap_data_header->target_entry_inline_value_count) ||
|
||||
!Read32(stream, &idmap_data_header->config_count) ||
|
||||
!Read32(stream, &idmap_data_header->overlay_entry_count) ||
|
||||
!Read32(stream, &idmap_data_header->string_pool_index_offset)) {
|
||||
return nullptr;
|
||||
@@ -207,20 +209,59 @@ std::unique_ptr<const IdmapData> IdmapData::FromBinaryStream(std::istream& strea
|
||||
if (!Read32(stream, &target_entry.target_id) || !Read32(stream, &target_entry.overlay_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
data->target_entries_.push_back(target_entry);
|
||||
data->target_entries_.emplace_back(target_entry);
|
||||
}
|
||||
|
||||
// Read the mapping of target resource id to inline overlay values.
|
||||
uint8_t unused1;
|
||||
uint16_t unused2;
|
||||
std::vector<std::tuple<TargetInlineEntry, uint32_t, uint32_t>> target_inline_entries;
|
||||
for (size_t i = 0; i < data->header_->GetTargetInlineEntryCount(); i++) {
|
||||
TargetInlineEntry target_entry{};
|
||||
if (!Read32(stream, &target_entry.target_id) || !Read16(stream, &unused2) ||
|
||||
!Read8(stream, &unused1) || !Read8(stream, &target_entry.value.data_type) ||
|
||||
!Read32(stream, &target_entry.value.data_value)) {
|
||||
uint32_t entry_offset;
|
||||
uint32_t entry_count;
|
||||
if (!Read32(stream, &target_entry.target_id) || !Read32(stream, &entry_offset)
|
||||
|| !Read32(stream, &entry_count)) {
|
||||
return nullptr;
|
||||
}
|
||||
data->target_inline_entries_.push_back(target_entry);
|
||||
target_inline_entries.emplace_back(std::make_tuple(target_entry, entry_offset, entry_count));
|
||||
}
|
||||
|
||||
// Read the inline overlay resource values
|
||||
std::vector<std::pair<uint32_t, TargetValue>> target_values;
|
||||
uint8_t unused1;
|
||||
uint16_t unused2;
|
||||
for (size_t i = 0; i < data->header_->GetTargetInlineEntryValueCount(); i++) {
|
||||
uint32_t config_index;
|
||||
if (!Read32(stream, &config_index)) {
|
||||
return nullptr;
|
||||
}
|
||||
TargetValue value;
|
||||
if (!Read16(stream, &unused2)
|
||||
|| !Read8(stream, &unused1)
|
||||
|| !Read8(stream, &value.data_type)
|
||||
|| !Read32(stream, &value.data_value)) {
|
||||
return nullptr;
|
||||
}
|
||||
target_values.emplace_back(std::make_pair(config_index, value));
|
||||
}
|
||||
|
||||
// Read the configurations
|
||||
std::vector<ConfigDescription> configurations;
|
||||
for (size_t i = 0; i < data->header_->GetConfigCount(); i++) {
|
||||
ConfigDescription cd;
|
||||
if (!stream.read(reinterpret_cast<char*>(&cd), sizeof(ConfigDescription))) {
|
||||
return nullptr;
|
||||
}
|
||||
configurations.emplace_back(cd);
|
||||
}
|
||||
|
||||
// Construct complete target inline entries
|
||||
for (auto [target_entry, entry_offset, entry_count] : target_inline_entries) {
|
||||
for(size_t i = 0; i < entry_count; i++) {
|
||||
const auto& target_value = target_values[entry_offset + i];
|
||||
const auto& config = configurations[target_value.first];
|
||||
target_entry.values[config] = target_value.second;
|
||||
}
|
||||
data->target_inline_entries_.emplace_back(target_entry);
|
||||
}
|
||||
|
||||
// Read the mapping of overlay resource id to target resource id.
|
||||
@@ -278,12 +319,21 @@ Result<std::unique_ptr<const IdmapData>> IdmapData::FromResourceMapping(
|
||||
|
||||
std::unique_ptr<IdmapData> data(new IdmapData());
|
||||
data->string_pool_data_ = resource_mapping.GetStringPoolData().to_string();
|
||||
uint32_t inline_value_count = 0;
|
||||
std::set<std::string> config_set;
|
||||
for (const auto& mapping : resource_mapping.GetTargetToOverlayMap()) {
|
||||
if (auto overlay_resource = std::get_if<ResourceId>(&mapping.second)) {
|
||||
data->target_entries_.push_back({mapping.first, *overlay_resource});
|
||||
} else {
|
||||
data->target_inline_entries_.push_back(
|
||||
{mapping.first, std::get<TargetValue>(mapping.second)});
|
||||
std::map<ConfigDescription, TargetValue> values;
|
||||
for (const auto& [config, value] : std::get<ConfigMap>(mapping.second)) {
|
||||
config_set.insert(config);
|
||||
ConfigDescription cd;
|
||||
ConfigDescription::Parse(config, &cd);
|
||||
values[cd] = value;
|
||||
inline_value_count++;
|
||||
}
|
||||
data->target_inline_entries_.push_back({mapping.first, values});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,6 +345,8 @@ Result<std::unique_ptr<const IdmapData>> IdmapData::FromResourceMapping(
|
||||
data_header->target_entry_count = static_cast<uint32_t>(data->target_entries_.size());
|
||||
data_header->target_entry_inline_count =
|
||||
static_cast<uint32_t>(data->target_inline_entries_.size());
|
||||
data_header->target_entry_inline_value_count = inline_value_count;
|
||||
data_header->config_count = config_set.size();
|
||||
data_header->overlay_entry_count = static_cast<uint32_t>(data->overlay_entries_.size());
|
||||
data_header->string_pool_index_offset = resource_mapping.GetStringPoolOffset();
|
||||
data->header_ = std::move(data_header);
|
||||
|
||||
@@ -94,14 +94,17 @@ void PrettyPrintVisitor::visit(const IdmapData& data) {
|
||||
}
|
||||
|
||||
for (auto& target_entry : data.GetTargetInlineEntries()) {
|
||||
stream_ << TAB << base::StringPrintf("0x%08x -> ", target_entry.target_id)
|
||||
<< utils::DataTypeToString(target_entry.value.data_type);
|
||||
for(auto iter = target_entry.values.begin(); iter != target_entry.values.end(); ++iter) {
|
||||
auto value = iter->second;
|
||||
stream_ << TAB << base::StringPrintf("0x%08x -> ", target_entry.target_id)
|
||||
<< utils::DataTypeToString(value.data_type);
|
||||
|
||||
if (target_entry.value.data_type == Res_value::TYPE_STRING) {
|
||||
auto str = string_pool.stringAt(target_entry.value.data_value - string_pool_offset);
|
||||
stream_ << " \"" << str.value_or(StringPiece16(u"")) << "\"";
|
||||
} else {
|
||||
stream_ << " " << base::StringPrintf("0x%08x", target_entry.value.data_value);
|
||||
if (value.data_type == Res_value::TYPE_STRING) {
|
||||
auto str = string_pool.stringAt(value.data_value - string_pool_offset);
|
||||
stream_ << " \"" << str.value_or(StringPiece16(u"")) << "\"";
|
||||
} else {
|
||||
stream_ << " " << base::StringPrintf("0x%08x", value.data_value);
|
||||
}
|
||||
}
|
||||
|
||||
std::string target_name = kUnknownResourceName;
|
||||
|
||||
@@ -89,22 +89,30 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
|
||||
print(target_entry.target_id, "target id");
|
||||
}
|
||||
|
||||
|
||||
pad(sizeof(Res_value::size) + sizeof(Res_value::res0));
|
||||
|
||||
print(target_entry.value.data_type, "type: %s",
|
||||
utils::DataTypeToString(target_entry.value.data_type).data());
|
||||
for (auto& target_entry_value : target_entry.values) {
|
||||
auto value = target_entry_value.second;
|
||||
|
||||
Result<std::string> overlay_name(Error(""));
|
||||
if (overlay_ != nullptr &&
|
||||
(target_entry.value.data_value == Res_value::TYPE_REFERENCE ||
|
||||
target_entry.value.data_value == Res_value::TYPE_DYNAMIC_REFERENCE)) {
|
||||
overlay_name = overlay_->GetResourceName(target_entry.value.data_value);
|
||||
}
|
||||
print(target_entry_value.first.to_string(), false, "config: %s",
|
||||
target_entry_value.first.toString().string());
|
||||
|
||||
if (overlay_name) {
|
||||
print(target_entry.value.data_value, "data: %s", overlay_name->c_str());
|
||||
} else {
|
||||
print(target_entry.value.data_value, "data");
|
||||
print(value.data_type, "type: %s",
|
||||
utils::DataTypeToString(value.data_type).data());
|
||||
|
||||
Result<std::string> overlay_name(Error(""));
|
||||
if (overlay_ != nullptr &&
|
||||
(value.data_value == Res_value::TYPE_REFERENCE ||
|
||||
value.data_value == Res_value::TYPE_DYNAMIC_REFERENCE)) {
|
||||
overlay_name = overlay_->GetResourceName(value.data_value);
|
||||
}
|
||||
|
||||
if (overlay_name) {
|
||||
print(value.data_value, "data: %s", overlay_name->c_str());
|
||||
} else {
|
||||
print(value.data_value, "data");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +146,8 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
|
||||
void RawPrintVisitor::visit(const IdmapData::Header& header) {
|
||||
print(header.GetTargetEntryCount(), "target entry count");
|
||||
print(header.GetTargetInlineEntryCount(), "target inline entry count");
|
||||
print(header.GetTargetInlineEntryValueCount(), "target inline entry value count");
|
||||
print(header.GetConfigCount(), "config count");
|
||||
print(header.GetOverlayEntryCount(), "overlay entry count");
|
||||
print(header.GetStringPoolIndexOffset(), "string pool index offset");
|
||||
}
|
||||
|
||||
@@ -161,14 +161,13 @@ Result<ResourceMapping> ResourceMapping::FromContainers(const TargetResourceCont
|
||||
Result<Unit> ResourceMapping::AddMapping(
|
||||
ResourceId target_resource,
|
||||
const std::variant<OverlayData::ResourceIdValue, TargetValueWithConfig>& value) {
|
||||
if (target_map_.find(target_resource) != target_map_.end()) {
|
||||
return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource);
|
||||
}
|
||||
|
||||
// TODO(141485591): Ensure that the overlay type is compatible with the target type. If the
|
||||
// runtime types are not compatible, it could cause runtime crashes when the resource is resolved.
|
||||
|
||||
if (auto overlay_resource = std::get_if<OverlayData::ResourceIdValue>(&value)) {
|
||||
if (target_map_.find(target_resource) != target_map_.end()) {
|
||||
return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource);
|
||||
}
|
||||
target_map_.insert(std::make_pair(target_resource, overlay_resource->overlay_id));
|
||||
if (overlay_resource->rewrite_id) {
|
||||
// An overlay resource can override multiple target resources at once. Rewrite the overlay
|
||||
@@ -176,8 +175,18 @@ Result<Unit> ResourceMapping::AddMapping(
|
||||
overlay_map_.insert(std::make_pair(overlay_resource->overlay_id, target_resource));
|
||||
}
|
||||
} else {
|
||||
auto overlay_value = std::get<TargetValueWithConfig>(value);
|
||||
target_map_.insert(std::make_pair(target_resource, overlay_value.value));
|
||||
auto[iter, inserted] = target_map_.try_emplace(target_resource, ConfigMap());
|
||||
auto& resource_value = iter->second;
|
||||
if (!inserted && std::holds_alternative<ResourceId>(resource_value)) {
|
||||
return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource);
|
||||
}
|
||||
auto& config_map = std::get<ConfigMap>(resource_value);
|
||||
const auto& config_value = std::get<TargetValueWithConfig>(value);
|
||||
if (config_map.find(config_value.config) != config_map.end()) {
|
||||
return Error(R"(target resource id "0x%08x" mapped to multiple values with the same config)",
|
||||
target_resource);
|
||||
}
|
||||
config_map.insert(config_value.to_pair());
|
||||
}
|
||||
|
||||
return Unit{};
|
||||
|
||||
@@ -84,8 +84,10 @@ TEST(BinaryStreamVisitorTests, CreateBinaryStreamViaBinaryStreamVisitor) {
|
||||
const auto& target_inline_entries2 = data2->GetTargetInlineEntries();
|
||||
ASSERT_EQ(target_inline_entries1.size(), target_inline_entries2.size());
|
||||
ASSERT_EQ(target_inline_entries1[0].target_id, target_inline_entries2[0].target_id);
|
||||
ASSERT_EQ(target_inline_entries1[0].value.data_type, target_inline_entries2[0].value.data_type);
|
||||
ASSERT_EQ(target_inline_entries1[0].value.data_value, target_inline_entries2[0].value.data_value);
|
||||
ASSERT_EQ(target_inline_entries1[0].values.begin()->second.data_type,
|
||||
target_inline_entries2[0].values.begin()->second.data_type);
|
||||
ASSERT_EQ(target_inline_entries1[0].values.begin()->second.data_value,
|
||||
target_inline_entries2[0].values.begin()->second.data_value);
|
||||
|
||||
const auto& overlay_entries1 = data1->GetOverlayEntries();
|
||||
const auto& overlay_entries2 = data2->GetOverlayEntries();
|
||||
|
||||
@@ -47,10 +47,11 @@ namespace android::idmap2 {
|
||||
ASSERT_EQ((entry).target_id, (target_resid)); \
|
||||
ASSERT_EQ((entry).overlay_id, (overlay_resid))
|
||||
|
||||
#define ASSERT_TARGET_INLINE_ENTRY(entry, target_resid, expected_type, expected_value) \
|
||||
ASSERT_EQ((entry).target_id, target_resid); \
|
||||
ASSERT_EQ((entry).value.data_type, (expected_type)); \
|
||||
ASSERT_EQ((entry).value.data_value, (expected_value))
|
||||
#define ASSERT_TARGET_INLINE_ENTRY(entry, target_resid, ex_config, expected_type, expected_value) \
|
||||
ASSERT_EQ((entry).target_id, target_resid); \
|
||||
ASSERT_EQ((entry).values.begin()->first.to_string(), (ex_config)); \
|
||||
ASSERT_EQ((entry).values.begin()->second.data_type, (expected_type)); \
|
||||
ASSERT_EQ((entry).values.begin()->second.data_value, (expected_value))
|
||||
|
||||
#define ASSERT_OVERLAY_ENTRY(entry, overlay_resid, target_resid) \
|
||||
ASSERT_EQ((entry).overlay_id, (overlay_resid)); \
|
||||
@@ -67,7 +68,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) {
|
||||
std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
|
||||
ASSERT_THAT(header, NotNull());
|
||||
ASSERT_EQ(header->GetMagic(), 0x504d4449U);
|
||||
ASSERT_EQ(header->GetVersion(), 0x08U);
|
||||
ASSERT_EQ(header->GetVersion(), 0x09U);
|
||||
ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
|
||||
ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
|
||||
ASSERT_EQ(header->GetFulfilledPolicies(), 0x11);
|
||||
@@ -122,8 +123,8 @@ TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
|
||||
|
||||
const auto& target_inline_entries = data->GetTargetInlineEntries();
|
||||
ASSERT_EQ(target_inline_entries.size(), 1U);
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, Res_value::TYPE_INT_HEX,
|
||||
0x12345678);
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, "land-xxhdpi-v7",
|
||||
Res_value::TYPE_INT_HEX, 0x12345678);
|
||||
|
||||
const auto& overlay_entries = data->GetOverlayEntries();
|
||||
ASSERT_EQ(target_entries.size(), 3U);
|
||||
@@ -142,7 +143,7 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) {
|
||||
|
||||
ASSERT_THAT(idmap->GetHeader(), NotNull());
|
||||
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x08U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x09U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), kIdmapRawDataPolicies);
|
||||
@@ -165,8 +166,8 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) {
|
||||
|
||||
const auto& target_inline_entries = data->GetTargetInlineEntries();
|
||||
ASSERT_EQ(target_inline_entries.size(), 1U);
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, Res_value::TYPE_INT_HEX,
|
||||
0x12345678);
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, "land-xxhdpi-v7",
|
||||
Res_value::TYPE_INT_HEX, 0x12345678);
|
||||
|
||||
const auto& overlay_entries = data->GetOverlayEntries();
|
||||
ASSERT_EQ(target_entries.size(), 3U);
|
||||
@@ -203,7 +204,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromApkAssets) {
|
||||
|
||||
ASSERT_THAT(idmap->GetHeader(), NotNull());
|
||||
ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x08U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x09U);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), android::idmap2::TestConstants::TARGET_CRC);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), android::idmap2::TestConstants::OVERLAY_CRC);
|
||||
ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), PolicyFlags::PUBLIC);
|
||||
@@ -261,9 +262,9 @@ TEST(IdmapTests, FabricatedOverlay) {
|
||||
|
||||
auto frro = FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "test.target")
|
||||
.SetOverlayable("TestResources")
|
||||
.SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U, "")
|
||||
.SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000, "")
|
||||
.SetResourceValue("string/str2", Res_value::TYPE_STRING, "foobar", "")
|
||||
.SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U, "land-xxhdpi-v7")
|
||||
.SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000, "land")
|
||||
.SetResourceValue("string/str2", Res_value::TYPE_STRING, "foobar", "xxhdpi-v7")
|
||||
.Build();
|
||||
|
||||
ASSERT_TRUE(frro);
|
||||
@@ -295,11 +296,11 @@ TEST(IdmapTests, FabricatedOverlay) {
|
||||
|
||||
const auto& target_inline_entries = data->GetTargetInlineEntries();
|
||||
ASSERT_EQ(target_inline_entries.size(), 3U);
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1,
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1, "land-xxhdpi-v7",
|
||||
Res_value::TYPE_INT_DEC, 2U);
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1,
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1, "land",
|
||||
Res_value::TYPE_REFERENCE, 0x7f010000);
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[2], R::target::string::str2,
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[2], R::target::string::str2, "xxhdpi-v7",
|
||||
Res_value::TYPE_STRING,
|
||||
(uint32_t) (string_pool.indexOfString(u"foobar", 6)).value_or(-1));
|
||||
}
|
||||
@@ -442,9 +443,9 @@ TEST(IdmapTests, CreateIdmapDataInlineResources) {
|
||||
constexpr size_t overlay_string_pool_size = 10U;
|
||||
const auto& target_inline_entries = data->GetTargetInlineEntries();
|
||||
ASSERT_EQ(target_inline_entries.size(), 2U);
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1,
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1, std::string(),
|
||||
Res_value::TYPE_INT_DEC, 73U); // -> 73
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1,
|
||||
ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1, std::string(),
|
||||
Res_value::TYPE_STRING,
|
||||
overlay_string_pool_size + 0U); // -> "Hello World"
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
|
||||
(*idmap)->accept(&visitor);
|
||||
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000008 version\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000009 version\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(
|
||||
StringPrintf(ADDRESS "%s target crc\n", android::idmap2::TestConstants::TARGET_CRC_STRING),
|
||||
stream.str());
|
||||
@@ -75,6 +75,8 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) {
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000001 enforce overlayable\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 target entry count", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000000 target inline entry count", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000000 target inline entry value count", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000000 config count", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 overlay entry count", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "0000000a string pool index offset", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 target id: integer/int1", stream.str());
|
||||
@@ -111,7 +113,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
|
||||
(*idmap)->accept(&visitor);
|
||||
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000008 version\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000009 version\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00001234 target crc\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00005678 overlay crc\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000011 fulfilled policies: public|signature\n", stream.str());
|
||||
@@ -124,17 +126,25 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) {
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "........ overlay name: OverlayName\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000003 target entry count\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000001 target inline entry count\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000001 target inline entry value count", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000001 config count", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000003 overlay entry count\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000000 string pool index offset\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 overlay id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f030000 target id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f030000 overlay id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f030002 target id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f030001 overlay id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f040000 target id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "0000000e config: land-xxhdpi-v7 size\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "........ config: land-xxhdpi-v7\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS " 11 type: integer\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "12345678 data\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 overlay id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "7f030002 target id\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "00000004 string pool size\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX("000000a4: ........ string pool\n", stream.str());
|
||||
ASSERT_CONTAINS_REGEX(ADDRESS "........ string pool\n", stream.str());
|
||||
}
|
||||
|
||||
} // namespace android::idmap2
|
||||
|
||||
@@ -111,19 +111,20 @@ Result<Unit> MappingExists(const ResourceMapping& mapping, const ResourceId& tar
|
||||
return Error("Failed to find mapping for target resource");
|
||||
}
|
||||
|
||||
auto actual_overlay_value = std::get_if<TargetValue>(&entry_map->second);
|
||||
if (actual_overlay_value == nullptr) {
|
||||
auto config_map = std::get_if<ConfigMap>(&entry_map->second);
|
||||
if (config_map == nullptr || config_map->empty()) {
|
||||
return Error("Target resource is not mapped to an inline value");
|
||||
}
|
||||
auto actual_overlay_value = config_map->begin()->second;
|
||||
|
||||
if (actual_overlay_value->data_type != type) {
|
||||
if (actual_overlay_value.data_type != type) {
|
||||
return Error(R"(Expected type: "0x%02x" Actual type: "0x%02x")", type,
|
||||
actual_overlay_value->data_type);
|
||||
actual_overlay_value.data_type);
|
||||
}
|
||||
|
||||
if (actual_overlay_value->data_value != value) {
|
||||
if (actual_overlay_value.data_value != value) {
|
||||
return Error(R"(Expected value: "0x%08x" Actual value: "0x%08x")", type,
|
||||
actual_overlay_value->data_value);
|
||||
actual_overlay_value.data_value);
|
||||
}
|
||||
|
||||
return Result<Unit>({});
|
||||
|
||||
@@ -30,7 +30,7 @@ const unsigned char kIdmapRawData[] = {
|
||||
0x49, 0x44, 0x4d, 0x50,
|
||||
|
||||
// 0x4: version
|
||||
0x08, 0x00, 0x00, 0x00,
|
||||
0x09, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x8: target crc
|
||||
0x34, 0x12, 0x00, 0x00,
|
||||
@@ -76,66 +76,123 @@ const unsigned char kIdmapRawData[] = {
|
||||
// 0x58: target_inline_entry_count
|
||||
0x01, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x5c: overlay_entry_count
|
||||
// 0x5c: target_inline_entry_value_count
|
||||
0x01, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x60: config_count
|
||||
0x01, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x64: overlay_entry_count
|
||||
0x03, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x60: string_pool_offset
|
||||
// 0x68: string_pool_offset
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
// TARGET ENTRIES
|
||||
// 0x64: target id (0x7f020000)
|
||||
// 0x6c: target id (0x7f020000)
|
||||
0x00, 0x00, 0x02, 0x7f,
|
||||
|
||||
// 0x68: overlay_id (0x7f020000)
|
||||
// 0x70: overlay_id (0x7f020000)
|
||||
0x00, 0x00, 0x02, 0x7f,
|
||||
|
||||
// 0x6c: target id (0x7f030000)
|
||||
// 0x74: target id (0x7f030000)
|
||||
0x00, 0x00, 0x03, 0x7f,
|
||||
|
||||
// 0x70: overlay_id (0x7f030000)
|
||||
// 0x78: overlay_id (0x7f030000)
|
||||
0x00, 0x00, 0x03, 0x7f,
|
||||
|
||||
// 0x74: target id (0x7f030002)
|
||||
// 0x7c: target id (0x7f030002)
|
||||
0x02, 0x00, 0x03, 0x7f,
|
||||
|
||||
// 0x78: overlay_id (0x7f030001)
|
||||
// 0x80: overlay_id (0x7f030001)
|
||||
0x01, 0x00, 0x03, 0x7f,
|
||||
|
||||
// INLINE TARGET ENTRIES
|
||||
|
||||
// 0x7c: target_id
|
||||
// 0x84: target_id
|
||||
0x00, 0x00, 0x04, 0x7f,
|
||||
|
||||
// 0x80: Res_value::size (value ignored by idmap)
|
||||
// 0x88: start value index
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x8c: value count
|
||||
0x01, 0x00, 0x00, 0x00,
|
||||
|
||||
// INLINE TARGET ENTRY VALUES
|
||||
|
||||
// 0x90: config index
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0x94: Res_value::size (value ignored by idmap)
|
||||
0x08, 0x00,
|
||||
|
||||
// 0x82: Res_value::res0 (value ignored by idmap)
|
||||
// 0x98: Res_value::res0 (value ignored by idmap)
|
||||
0x00,
|
||||
|
||||
// 0x83: Res_value::dataType (TYPE_INT_HEX)
|
||||
// 0x9c: Res_value::dataType (TYPE_INT_HEX)
|
||||
0x11,
|
||||
|
||||
// 0x84: Res_value::data
|
||||
// 0xa0: Res_value::data
|
||||
0x78, 0x56, 0x34, 0x12,
|
||||
|
||||
// CONFIGURATIONS
|
||||
|
||||
// 0xa4: ConfigDescription
|
||||
// size
|
||||
0x40, 0x00, 0x00, 0x00,
|
||||
// 0xa8: imsi
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// 0xac: locale
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// 0xb0: screenType
|
||||
0x02, 0x00, 0xe0, 0x01,
|
||||
// 0xb4: input
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// 0xb8: screenSize
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// 0xbc: version
|
||||
0x07, 0x00, 0x00, 0x00,
|
||||
// 0xc0: screenConfig
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// 0xc4: screenSizeDp
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// 0xc8: localeScript
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// 0xcc: localVariant(1)
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// 0xd0: localVariant(2)
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// 0xd4: screenConfig2
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// 0xd8: localeScriptWasComputed
|
||||
0x00,
|
||||
// 0xd9: localeNumberingSystem(1)
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
// 0xdd: localeNumberingSystem(2)
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0xe1: padding
|
||||
0x00, 0x00, 0x00,
|
||||
|
||||
|
||||
// OVERLAY ENTRIES
|
||||
// 0x88: 0x7f020000 -> 0x7f020000
|
||||
// 0xe4: 0x7f020000 -> 0x7f020000
|
||||
0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f,
|
||||
|
||||
// 0x90: 0x7f030000 -> 0x7f030000
|
||||
// 0xec: 0x7f030000 -> 0x7f030000
|
||||
0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x03, 0x7f,
|
||||
|
||||
// 0x98: 0x7f030001 -> 0x7f030002
|
||||
// 0xf4: 0x7f030001 -> 0x7f030002
|
||||
0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f,
|
||||
|
||||
// 0xa0: string pool
|
||||
// 0xfc: string pool
|
||||
// string length,
|
||||
0x04, 0x00, 0x00, 0x00,
|
||||
|
||||
// 0xa4 string contents "test"
|
||||
// 0x100 string contents "test"
|
||||
0x74, 0x65, 0x73, 0x74};
|
||||
|
||||
const unsigned int kIdmapRawDataLen = 0xa8;
|
||||
const unsigned int kIdmapRawDataLen = 0x104;
|
||||
const unsigned int kIdmapRawDataOffset = 0x54;
|
||||
const unsigned int kIdmapRawDataTargetCrc = 0x1234;
|
||||
const unsigned int kIdmapRawOverlayCrc = 0x5678;
|
||||
|
||||
@@ -601,10 +601,6 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry(
|
||||
return base::unexpected(result.error());
|
||||
}
|
||||
|
||||
if (type_idx == 0x1c) {
|
||||
LOG(ERROR) << base::StringPrintf("foobar first result %s", result->package_name->c_str());
|
||||
}
|
||||
|
||||
bool overlaid = false;
|
||||
if (!stop_at_first_match && !ignore_configuration && !apk_assets_[result->cookie]->IsLoader()) {
|
||||
for (const auto& id_map : package_group.overlays_) {
|
||||
@@ -615,7 +611,21 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry(
|
||||
}
|
||||
if (overlay_entry.IsInlineValue()) {
|
||||
// The target resource is overlaid by an inline value not represented by a resource.
|
||||
result->entry = overlay_entry.GetInlineValue();
|
||||
ConfigDescription best_frro_config;
|
||||
Res_value best_frro_value;
|
||||
bool frro_found = false;
|
||||
for( const auto& [config, value] : overlay_entry.GetInlineValue()) {
|
||||
if ((!frro_found || config.isBetterThan(best_frro_config, desired_config))
|
||||
&& config.match(*desired_config)) {
|
||||
frro_found = true;
|
||||
best_frro_config = config;
|
||||
best_frro_value = value;
|
||||
}
|
||||
}
|
||||
if (!frro_found) {
|
||||
continue;
|
||||
}
|
||||
result->entry = best_frro_value;
|
||||
result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
|
||||
result->cookie = id_map.cookie;
|
||||
|
||||
|
||||
@@ -56,6 +56,8 @@ struct Idmap_header {
|
||||
struct Idmap_data_header {
|
||||
uint32_t target_entry_count;
|
||||
uint32_t target_inline_entry_count;
|
||||
uint32_t target_inline_entry_value_count;
|
||||
uint32_t configuration_count;
|
||||
uint32_t overlay_entry_count;
|
||||
|
||||
uint32_t string_pool_index_offset;
|
||||
@@ -68,6 +70,12 @@ struct Idmap_target_entry {
|
||||
|
||||
struct Idmap_target_entry_inline {
|
||||
uint32_t target_id;
|
||||
uint32_t start_value_index;
|
||||
uint32_t value_count;
|
||||
};
|
||||
|
||||
struct Idmap_target_entry_inline_value {
|
||||
uint32_t config_index;
|
||||
Res_value value;
|
||||
};
|
||||
|
||||
@@ -138,11 +146,15 @@ status_t OverlayDynamicRefTable::lookupResourceIdNoRewrite(uint32_t* resId) cons
|
||||
IdmapResMap::IdmapResMap(const Idmap_data_header* data_header,
|
||||
const Idmap_target_entry* entries,
|
||||
const Idmap_target_entry_inline* inline_entries,
|
||||
const Idmap_target_entry_inline_value* inline_entry_values,
|
||||
const ConfigDescription* configs,
|
||||
uint8_t target_assigned_package_id,
|
||||
const OverlayDynamicRefTable* overlay_ref_table)
|
||||
: data_header_(data_header),
|
||||
entries_(entries),
|
||||
inline_entries_(inline_entries),
|
||||
inline_entry_values_(inline_entry_values),
|
||||
configurations_(configs),
|
||||
target_assigned_package_id_(target_assigned_package_id),
|
||||
overlay_ref_table_(overlay_ref_table) { }
|
||||
|
||||
@@ -183,7 +195,13 @@ IdmapResMap::Result IdmapResMap::Lookup(uint32_t target_res_id) const {
|
||||
|
||||
if (inline_entry != end_inline_entry &&
|
||||
(0x00FFFFFFU & dtohl(inline_entry->target_id)) == target_res_id) {
|
||||
return Result(inline_entry->value);
|
||||
std::map<ConfigDescription, Res_value> values_map;
|
||||
for (int i = 0; i < inline_entry->value_count; i++) {
|
||||
const auto& value = inline_entry_values_[inline_entry->start_value_index + i];
|
||||
const auto& config = configurations_[value.config_index];
|
||||
values_map[config] = value.value;
|
||||
}
|
||||
return Result(values_map);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
@@ -237,6 +255,8 @@ LoadedIdmap::LoadedIdmap(std::string&& idmap_path,
|
||||
const Idmap_data_header* data_header,
|
||||
const Idmap_target_entry* target_entries,
|
||||
const Idmap_target_entry_inline* target_inline_entries,
|
||||
const Idmap_target_entry_inline_value* inline_entry_values,
|
||||
const ConfigDescription* configs,
|
||||
const Idmap_overlay_entry* overlay_entries,
|
||||
std::unique_ptr<ResStringPool>&& string_pool,
|
||||
std::string_view overlay_apk_path,
|
||||
@@ -245,6 +265,8 @@ LoadedIdmap::LoadedIdmap(std::string&& idmap_path,
|
||||
data_header_(data_header),
|
||||
target_entries_(target_entries),
|
||||
target_inline_entries_(target_inline_entries),
|
||||
inline_entry_values_(inline_entry_values),
|
||||
configurations_(configs),
|
||||
overlay_entries_(overlay_entries),
|
||||
string_pool_(std::move(string_pool)),
|
||||
idmap_path_(std::move(idmap_path)),
|
||||
@@ -303,6 +325,21 @@ std::unique_ptr<LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_path,
|
||||
if (target_inline_entries == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto target_inline_entry_values = ReadType<Idmap_target_entry_inline_value>(
|
||||
&data_ptr, &data_size, "target inline values",
|
||||
dtohl(data_header->target_inline_entry_value_count));
|
||||
if (target_inline_entry_values == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto configurations = ReadType<ConfigDescription>(
|
||||
&data_ptr, &data_size, "configurations",
|
||||
dtohl(data_header->configuration_count));
|
||||
if (configurations == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto overlay_entries = ReadType<Idmap_overlay_entry>(&data_ptr, &data_size, "target inline",
|
||||
dtohl(data_header->overlay_entry_count));
|
||||
if (overlay_entries == nullptr) {
|
||||
@@ -329,8 +366,8 @@ std::unique_ptr<LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_path,
|
||||
// Can't use make_unique because LoadedIdmap constructor is private.
|
||||
return std::unique_ptr<LoadedIdmap>(
|
||||
new LoadedIdmap(idmap_path.to_string(), header, data_header, target_entries,
|
||||
target_inline_entries, overlay_entries, std::move(idmap_string_pool),
|
||||
*target_path, *overlay_path));
|
||||
target_inline_entries, target_inline_entry_values, configurations,
|
||||
overlay_entries, std::move(idmap_string_pool), *target_path, *overlay_path));
|
||||
}
|
||||
|
||||
bool LoadedIdmap::IsUpToDate() const {
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <variant>
|
||||
|
||||
#include "android-base/macros.h"
|
||||
#include "androidfw/ConfigDescription.h"
|
||||
#include "androidfw/StringPiece.h"
|
||||
#include "androidfw/ResourceTypes.h"
|
||||
#include "utils/ByteOrder.h"
|
||||
@@ -35,6 +36,7 @@ struct Idmap_header;
|
||||
struct Idmap_data_header;
|
||||
struct Idmap_target_entry;
|
||||
struct Idmap_target_entry_inline;
|
||||
struct Idmap_target_entry_inline_value;
|
||||
struct Idmap_overlay_entry;
|
||||
|
||||
// A string pool for overlay apk assets. The string pool holds the strings of the overlay resources
|
||||
@@ -91,7 +93,8 @@ class IdmapResMap {
|
||||
public:
|
||||
Result() = default;
|
||||
explicit Result(uint32_t value) : data_(value) {};
|
||||
explicit Result(const Res_value& value) : data_(value) { };
|
||||
explicit Result(const std::map<ConfigDescription, Res_value> &value)
|
||||
: data_(value) { };
|
||||
|
||||
// Returns `true` if the resource is overlaid.
|
||||
explicit operator bool() const {
|
||||
@@ -107,15 +110,16 @@ class IdmapResMap {
|
||||
}
|
||||
|
||||
bool IsInlineValue() const {
|
||||
return std::get_if<Res_value>(&data_) != nullptr;
|
||||
return std::get_if<2>(&data_) != nullptr;
|
||||
}
|
||||
|
||||
const Res_value& GetInlineValue() const {
|
||||
return std::get<Res_value>(data_);
|
||||
const std::map<ConfigDescription, Res_value>& GetInlineValue() const {
|
||||
return std::get<2>(data_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::variant<std::monostate, uint32_t, Res_value> data_;
|
||||
std::variant<std::monostate, uint32_t,
|
||||
std::map<ConfigDescription, Res_value> > data_;
|
||||
};
|
||||
|
||||
// Looks up the value that overlays the target resource id.
|
||||
@@ -129,12 +133,16 @@ class IdmapResMap {
|
||||
explicit IdmapResMap(const Idmap_data_header* data_header,
|
||||
const Idmap_target_entry* entries,
|
||||
const Idmap_target_entry_inline* inline_entries,
|
||||
const Idmap_target_entry_inline_value* inline_entry_values,
|
||||
const ConfigDescription* configs,
|
||||
uint8_t target_assigned_package_id,
|
||||
const OverlayDynamicRefTable* overlay_ref_table);
|
||||
|
||||
const Idmap_data_header* data_header_;
|
||||
const Idmap_target_entry* entries_;
|
||||
const Idmap_target_entry_inline* inline_entries_;
|
||||
const Idmap_target_entry_inline_value* inline_entry_values_;
|
||||
const ConfigDescription* configurations_;
|
||||
const uint8_t target_assigned_package_id_;
|
||||
const OverlayDynamicRefTable* overlay_ref_table_;
|
||||
|
||||
@@ -170,8 +178,8 @@ class LoadedIdmap {
|
||||
// Returns a mapping from target resource ids to overlay values.
|
||||
const IdmapResMap GetTargetResourcesMap(uint8_t target_assigned_package_id,
|
||||
const OverlayDynamicRefTable* overlay_ref_table) const {
|
||||
return IdmapResMap(data_header_, target_entries_, target_inline_entries_,
|
||||
target_assigned_package_id, overlay_ref_table);
|
||||
return IdmapResMap(data_header_, target_entries_, target_inline_entries_, inline_entry_values_,
|
||||
configurations_, target_assigned_package_id, overlay_ref_table);
|
||||
}
|
||||
|
||||
// Returns a dynamic reference table for a loaded overlay package.
|
||||
@@ -191,6 +199,8 @@ class LoadedIdmap {
|
||||
const Idmap_data_header* data_header_;
|
||||
const Idmap_target_entry* target_entries_;
|
||||
const Idmap_target_entry_inline* target_inline_entries_;
|
||||
const Idmap_target_entry_inline_value* inline_entry_values_;
|
||||
const ConfigDescription* configurations_;
|
||||
const Idmap_overlay_entry* overlay_entries_;
|
||||
const std::unique_ptr<ResStringPool> string_pool_;
|
||||
|
||||
@@ -207,6 +217,8 @@ class LoadedIdmap {
|
||||
const Idmap_data_header* data_header,
|
||||
const Idmap_target_entry* target_entries,
|
||||
const Idmap_target_entry_inline* target_inline_entries,
|
||||
const Idmap_target_entry_inline_value* inline_entry_values_,
|
||||
const ConfigDescription* configs,
|
||||
const Idmap_overlay_entry* overlay_entries,
|
||||
std::unique_ptr<ResStringPool>&& string_pool,
|
||||
std::string_view overlay_apk_path,
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
namespace android {
|
||||
|
||||
constexpr const uint32_t kIdmapMagic = 0x504D4449u;
|
||||
constexpr const uint32_t kIdmapCurrentVersion = 0x00000008u;
|
||||
constexpr const uint32_t kIdmapCurrentVersion = 0x00000009u;
|
||||
|
||||
// This must never change.
|
||||
constexpr const uint32_t kFabricatedOverlayMagic = 0x4f525246; // FRRO (big endian)
|
||||
@@ -1098,7 +1098,7 @@ struct ResTable_config
|
||||
SDKVERSION_ANY = 0
|
||||
};
|
||||
|
||||
enum {
|
||||
enum {
|
||||
MINORVERSION_ANY = 0
|
||||
};
|
||||
|
||||
|
||||
Binary file not shown.
@@ -1098,6 +1098,7 @@ public final class OverlayManagerService extends SystemService {
|
||||
private void enforceActor(@NonNull OverlayIdentifier overlay, @NonNull String methodName,
|
||||
int realUserId) throws SecurityException {
|
||||
OverlayInfo overlayInfo = mImpl.getOverlayInfo(overlay, realUserId);
|
||||
|
||||
if (overlayInfo == null) {
|
||||
throw new IllegalArgumentException("Unable to retrieve overlay information for "
|
||||
+ overlay);
|
||||
|
||||
@@ -519,6 +519,7 @@ final class OverlayManagerServiceImpl {
|
||||
throws OperationFailedException {
|
||||
final OverlayIdentifier overlayIdentifier = new OverlayIdentifier(
|
||||
info.packageName, info.overlayName);
|
||||
|
||||
final Set<PackageAndUser> updatedTargets = new ArraySet<>();
|
||||
OverlayInfo oi = mSettings.getNullableOverlayInfo(overlayIdentifier, userId);
|
||||
if (oi != null) {
|
||||
|
||||
Reference in New Issue
Block a user