diff options
Diffstat (limited to 'cmds/idmap2/idmap2/Lookup.cpp')
-rw-r--r-- | cmds/idmap2/idmap2/Lookup.cpp | 126 |
1 files changed, 70 insertions, 56 deletions
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp index b7ae9d090cee..c44170928992 100644 --- a/cmds/idmap2/idmap2/Lookup.cpp +++ b/cmds/idmap2/idmap2/Lookup.cpp @@ -33,9 +33,10 @@ #include "androidfw/Util.h" #include "idmap2/CommandLineOptions.h" #include "idmap2/Idmap.h" +#include "idmap2/ResourceUtils.h" #include "idmap2/Result.h" #include "idmap2/SysTrace.h" -#include "idmap2/Xml.h" +#include "idmap2/XmlParser.h" #include "idmap2/ZipFile.h" #include "utils/String16.h" #include "utils/String8.h" @@ -57,8 +58,7 @@ using android::idmap2::IdmapHeader; using android::idmap2::ResourceId; using android::idmap2::Result; using android::idmap2::Unit; -using android::idmap2::Xml; -using android::idmap2::ZipFile; +using android::idmap2::utils::ExtractOverlayManifestInfo; using android::util::Utf16ToUtf8; namespace { @@ -85,76 +85,90 @@ Result<ResourceId> WARN_UNUSED ParseResReference(const AssetManager2& am, const return Error("failed to obtain resource id for %s", res.c_str()); } -Result<std::string> WARN_UNUSED GetValue(const AssetManager2& am, ResourceId resid) { - Res_value value; - ResTable_config config; - uint32_t flags; - ApkAssetsCookie cookie = am.GetResource(resid, false, 0, &value, &config, &flags); - if (cookie == kInvalidCookie) { - return Error("no resource 0x%08x in asset manager", resid); - } - - std::string out; - - // TODO(martenkongstad): use optional parameter GetResource(..., std::string* - // stacktrace = NULL) instead - out.append(StringPrintf("cookie=%d ", cookie)); - - out.append("config='"); - out.append(config.toString().c_str()); - out.append("' value="); - +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)); + out->append(StringPrintf("%d", value.data)); break; case Res_value::TYPE_INT_HEX: - out.append(StringPrintf("0x%08x", value.data)); + out->append(StringPrintf("0x%08x", value.data)); break; case Res_value::TYPE_INT_BOOLEAN: - out.append(value.data != 0 ? "true" : "false"); + out->append(value.data != 0 ? "true" : "false"); break; case Res_value::TYPE_STRING: { - const ResStringPool* pool = am.GetStringPoolForCookie(cookie); + 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); + out->append(str, len); } else { const char16_t* str16 = pool->stringAt(value.data, &len); - out += Utf16ToUtf8(StringPiece16(str16, len)); + out->append(Utf16ToUtf8(StringPiece16(str16, len))); } + out->append("\""); } break; default: - out.append(StringPrintf("dataType=0x%02x data=0x%08x", value.dataType, value.data)); + out->append(StringPrintf("dataType=0x%02x data=0x%08x", value.dataType, value.data)); break; } - return out; } -Result<std::string> GetTargetPackageNameFromManifest(const std::string& apk_path) { - const auto zip = ZipFile::Open(apk_path); - if (!zip) { - return Error("failed to open %s as zip", apk_path.c_str()); - } - const auto entry = zip->Uncompress("AndroidManifest.xml"); - if (!entry) { - return Error("failed to uncompress AndroidManifest.xml in %s", apk_path.c_str()); - } - const auto xml = Xml::Create(entry->buf, entry->size); - if (!xml) { - return Error("failed to create XML buffer"); - } - const auto tag = xml->FindTag("overlay"); - if (!tag) { - return Error("failed to find <overlay> tag"); +Result<std::string> WARN_UNUSED GetValue(AssetManager2* const am, ResourceId resid) { + Res_value value; + ResTable_config config; + uint32_t flags; + ApkAssetsCookie cookie = am->GetResource(resid, true, 0, &value, &config, &flags); + if (cookie == kInvalidCookie) { + return Error("no resource 0x%08x in asset manager", resid); } - const auto iter = tag->find("targetPackage"); - if (iter == tag->end()) { - return Error("failed to find targetPackage attribute"); + + std::string out; + + // TODO(martenkongstad): use optional parameter GetResource(..., std::string* + // stacktrace = NULL) instead + out.append(StringPrintf("cookie=%d ", cookie)); + + out.append("config='"); + out.append(config.toString().c_str()); + out.append("' value="); + + if (value.dataType == Res_value::TYPE_REFERENCE) { + const android::ResolvedBag* bag = am->GetBag(static_cast<uint32_t>(value.data)); + if (bag == nullptr) { + out.append(StringPrintf("dataType=0x%02x data=0x%08x", value.dataType, value.data)); + 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 iter->second; + + return out; } + } // namespace Result<Unit> Lookup(const std::vector<std::string>& args) { @@ -202,12 +216,12 @@ Result<Unit> Lookup(const std::vector<std::string>& args) { } apk_assets.push_back(std::move(target_apk)); - const Result<std::string> package_name = - GetTargetPackageNameFromManifest(idmap_header->GetOverlayPath().to_string()); - if (!package_name) { - return Error("failed to parse android:targetPackage from overlay manifest"); + auto manifest_info = ExtractOverlayManifestInfo(idmap_header->GetOverlayPath().to_string(), + true /* assert_overlay */); + if (!manifest_info) { + return manifest_info.GetError(); } - target_package_name = *package_name; + target_package_name = (*manifest_info).target_package; } else if (target_path != idmap_header->GetTargetPath()) { return Error("different target APKs (expected target APK %s but %s has target APK %s)", target_path.c_str(), idmap_path.c_str(), @@ -235,7 +249,7 @@ Result<Unit> Lookup(const std::vector<std::string>& args) { return Error(resid.GetError(), "failed to parse resource ID"); } - const Result<std::string> value = GetValue(am, *resid); + const Result<std::string> value = GetValue(&am, *resid); if (!value) { return Error(value.GetError(), "resource 0x%08x not found", *resid); } |