diff options
author | 2022-09-09 15:46:14 -0700 | |
---|---|---|
committer | 2022-11-15 12:12:33 -0800 | |
commit | 368cd19d031f5a0b219ea92531d11ccb0ee66c4d (patch) | |
tree | ea6aa74fa746c043112705fdb08438abf782717b /tools/aapt2/Debug.cpp | |
parent | b0d0974aeba2b0498f5f576ff38012ac94b909a8 (diff) |
androidfw: Add support for compact resource entries
Bug: 237583012
Given the large number of simple resources such as strings in
Android resources, their ResTable_entry and Res_value can be
encoded together in a compact way. This allows a significant
saving in both storage and memory footprint.
The basic observations for simple resources are:
* ResTable_entry.size will always be sizeof(ResTable_entry)
unless it's a complex entry
* ResTable_entry.key is unlikely to exceed 16-bit
* ResTable_entry.flags only uses 3 bits for now
* Res_value.size will always be sizeof(Res_value)
Given the above, we could well encode the information into
a compact/compatible structure.
struct compact {
uint16_t key;
uint16_t flags;
uint32_t data;
};
The layout of this structure will allow maximum backward
compatibility. e.g. the flags will be at the same offset,
and a
`dtohs((ResTable_entry *)entry->flags) & FLAG_COMPACT`
would tell if this entry is a compact one or not. For a
compact entry:
struct compact *entry;
entry_size == sizeof(*entry)
entry_key == static_cast<uint32_t>(dtohs(entry->key))
entry_flags == dtohs(entry->flags) & 0xff // low 8-bit
data_type == dtohs(entry->flags) >> 8 // high 8-bit
data_size == sizeof(Res_value)
data_value == dtohl(entry->data)
To allow minimum code change and backward compatibility,
we change 'struct ResTable_entry' to 'union ResTable_entry',
with an anonymous structure inside that's fully backward
compatible. Thus, any existing reference such as:
ResTable_entry *entry = ...
if (dtohs(entry->flags) & ResTable_entry::FLAG_COMPLEX) ...
would still work.
However, special care needs to be taken after an entry is
obtained, and when value needs to be extracted.
A compact entry will not encode a complex value, and hence
complex entries/values are handled the same way.
Change-Id: I15d97a4f5e85fab28c075496f7f0cf6b1fcd73e3
Diffstat (limited to 'tools/aapt2/Debug.cpp')
-rw-r--r-- | tools/aapt2/Debug.cpp | 39 |
1 files changed, 19 insertions, 20 deletions
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp index f9e52b491413..df878899fa28 100644 --- a/tools/aapt2/Debug.cpp +++ b/tools/aapt2/Debug.cpp @@ -687,32 +687,32 @@ class ChunkPrinter { continue; } - printer_->Print((entry->flags & ResTable_entry::FLAG_COMPLEX) ? "[ResTable_map_entry]" - : "[ResTable_entry]"); + if (entry->is_complex()) { + printer_->Print("[ResTable_map_entry]"); + } else if (entry->is_compact()) { + printer_->Print("[ResTable_entry_compact]"); + } else { + printer_->Print("[ResTable_entry]"); + } + printer_->Print(StringPrintf(" id: 0x%04x", it.index())); printer_->Print(StringPrintf( - " name: %s", - android::util::GetString(key_pool_, android::util::DeviceToHost32(entry->key.index)) - .c_str())); - printer_->Print( - StringPrintf(" keyIndex: %u", android::util::DeviceToHost32(entry->key.index))); - printer_->Print(StringPrintf(" size: %u", android::util::DeviceToHost32(entry->size))); - printer_->Print(StringPrintf(" flags: 0x%04x", android::util::DeviceToHost32(entry->flags))); + " name: %s", android::util::GetString(key_pool_, entry->key()).c_str())); + printer_->Print(StringPrintf(" keyIndex: %u", entry->key())); + printer_->Print(StringPrintf(" size: %zu", entry->size())); + printer_->Print(StringPrintf(" flags: 0x%04x", entry->flags())); printer_->Indent(); - if (entry->flags & ResTable_entry::FLAG_COMPLEX) { - auto map_entry = (const ResTable_map_entry*)entry; - printer_->Print( - StringPrintf(" count: 0x%04x", android::util::DeviceToHost32(map_entry->count))); + if (auto map_entry = entry->map_entry()) { + uint32_t map_entry_count = android::util::DeviceToHost32(map_entry->count); + printer_->Print(StringPrintf(" count: 0x%04x", map_entry_count)); printer_->Print(StringPrintf(" parent: 0x%08x\n", android::util::DeviceToHost32(map_entry->parent.ident))); // Print the name and value mappings - auto maps = (const ResTable_map*)((const uint8_t*)entry + - android::util::DeviceToHost32(entry->size)); - for (size_t i = 0, count = android::util::DeviceToHost32(map_entry->count); i < count; - i++) { + auto maps = (const ResTable_map*)((const uint8_t*)entry + entry->size()); + for (size_t i = 0; i < map_entry_count; i++) { PrintResValue(&(maps[i].value), config, type); printer_->Print(StringPrintf( @@ -725,9 +725,8 @@ class ChunkPrinter { printer_->Print("\n"); // Print the value of the entry - auto value = - (const Res_value*)((const uint8_t*)entry + android::util::DeviceToHost32(entry->size)); - PrintResValue(value, config, type); + Res_value value = entry->value(); + PrintResValue(&value, config, type); } printer_->Undent(); |