From 9c20f729c7ef90da4a5c519326925caae8057392 Mon Sep 17 00:00:00 2001 From: Zoran Jovanovic Date: Tue, 4 Jun 2019 16:20:47 +0200 Subject: [PATCH] idmap2: support Lookup for arrays Lookup of array resource in idmap2 would result in an error. The reason was that on AssetManager2::GetValue call bags were not taken into consideration. Acquire the bag as well and traverse through it to fetch all its values. Bug: 134426097 Test: run `adb exec-out lookup` on a known array resource Change-Id: Ife066154e74d2ee8bd7b273030e75d8448558437 Signed-off-by: Zoran Jovanovic --- cmds/idmap2/idmap2/Lookup.cpp | 89 +++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 26 deletions(-) diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp index c5cf9807b6892..c44170928992e 100644 --- a/cmds/idmap2/idmap2/Lookup.cpp +++ b/cmds/idmap2/idmap2/Lookup.cpp @@ -85,11 +85,42 @@ Result WARN_UNUSED ParseResReference(const AssetManager2& am, const return Error("failed to obtain resource id for %s", res.c_str()); } -Result WARN_UNUSED GetValue(const AssetManager2& am, ResourceId resid) { +void PrintValue(AssetManager2* const am, const Res_value& value, const ApkAssetsCookie& cookie, + std::string* const out) { + switch (value.dataType) { + case Res_value::TYPE_INT_DEC: + out->append(StringPrintf("%d", value.data)); + break; + case Res_value::TYPE_INT_HEX: + out->append(StringPrintf("0x%08x", value.data)); + break; + case Res_value::TYPE_INT_BOOLEAN: + out->append(value.data != 0 ? "true" : "false"); + break; + case Res_value::TYPE_STRING: { + const ResStringPool* pool = am->GetStringPoolForCookie(cookie); + out->append("\""); + size_t len; + if (pool->isUTF8()) { + const char* str = pool->string8At(value.data, &len); + out->append(str, len); + } else { + const char16_t* str16 = pool->stringAt(value.data, &len); + out->append(Utf16ToUtf8(StringPiece16(str16, len))); + } + out->append("\""); + } break; + default: + out->append(StringPrintf("dataType=0x%02x data=0x%08x", value.dataType, value.data)); + break; + } +} + +Result WARN_UNUSED GetValue(AssetManager2* const am, ResourceId resid) { Res_value value; ResTable_config config; uint32_t flags; - ApkAssetsCookie cookie = am.GetResource(resid, false, 0, &value, &config, &flags); + ApkAssetsCookie cookie = am->GetResource(resid, true, 0, &value, &config, &flags); if (cookie == kInvalidCookie) { return Error("no resource 0x%08x in asset manager", resid); } @@ -104,31 +135,37 @@ Result WARN_UNUSED GetValue(const AssetManager2& am, ResourceId res out.append(config.toString().c_str()); out.append("' value="); - switch (value.dataType) { - case Res_value::TYPE_INT_DEC: - out.append(StringPrintf("%d", value.data)); - break; - case Res_value::TYPE_INT_HEX: - out.append(StringPrintf("0x%08x", value.data)); - break; - case Res_value::TYPE_INT_BOOLEAN: - out.append(value.data != 0 ? "true" : "false"); - break; - case Res_value::TYPE_STRING: { - const ResStringPool* pool = am.GetStringPoolForCookie(cookie); - size_t len; - if (pool->isUTF8()) { - const char* str = pool->string8At(value.data, &len); - out.append(str, len); - } else { - const char16_t* str16 = pool->stringAt(value.data, &len); - out += Utf16ToUtf8(StringPiece16(str16, len)); - } - } break; - default: + if (value.dataType == Res_value::TYPE_REFERENCE) { + const android::ResolvedBag* bag = am->GetBag(static_cast(value.data)); + if (bag == nullptr) { out.append(StringPrintf("dataType=0x%02x data=0x%08x", value.dataType, value.data)); - break; + return out; + } + out.append("["); + Res_value bag_val; + ResTable_config selected_config; + uint32_t flags; + uint32_t ref; + ApkAssetsCookie bag_cookie; + for (size_t i = 0; i < bag->entry_count; ++i) { + const android::ResolvedBag::Entry& entry = bag->entries[i]; + bag_val = entry.value; + bag_cookie = am->ResolveReference(entry.cookie, &bag_val, &selected_config, &flags, &ref); + if (bag_cookie == kInvalidCookie) { + out.append( + StringPrintf("Error: dataType=0x%02x data=0x%08x", bag_val.dataType, bag_val.data)); + continue; + } + PrintValue(am, bag_val, bag_cookie, &out); + if (i != bag->entry_count - 1) { + out.append(", "); + } + } + out.append("]"); + } else { + PrintValue(am, value, cookie, &out); } + return out; } @@ -212,7 +249,7 @@ Result Lookup(const std::vector& args) { return Error(resid.GetError(), "failed to parse resource ID"); } - const Result value = GetValue(am, *resid); + const Result value = GetValue(&am, *resid); if (!value) { return Error(value.GetError(), "resource 0x%08x not found", *resid); }