diff options
author | 2018-02-13 16:44:10 -0800 | |
---|---|---|
committer | 2018-02-14 10:49:32 -0800 | |
commit | da9eba300b0f84505fe094374c14d4bc910880d2 (patch) | |
tree | 61f967b9c7ea92490db7b309ee3291dd52c32308 | |
parent | 97661735aab95260f68d33896f76d071fe025fcd (diff) |
Dump XML files in aapt2 dump
Test: manual
Change-Id: Id7f656c1385f6d1fec8eaa993c8e2b36bb1ae5b0
-rw-r--r-- | tools/aapt2/Debug.cpp | 59 | ||||
-rw-r--r-- | tools/aapt2/Debug.h | 2 | ||||
-rw-r--r-- | tools/aapt2/cmd/Dump.cpp | 90 |
3 files changed, 115 insertions, 36 deletions
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp index 5831875680ac..249557af921e 100644 --- a/tools/aapt2/Debug.cpp +++ b/tools/aapt2/Debug.cpp @@ -414,59 +414,70 @@ class XmlPrinter : public xml::ConstVisitor { public: using xml::ConstVisitor::Visit; - void Visit(const xml::Element* el) override { - const size_t previous_size = prefix_.size(); + XmlPrinter(Printer* printer) : printer_(printer) { + } + void Visit(const xml::Element* el) override { for (const xml::NamespaceDecl& decl : el->namespace_decls) { - std::cerr << prefix_ << "N: " << decl.prefix << "=" << decl.uri - << " (line=" << decl.line_number << ")\n"; - prefix_ += " "; + printer_->Println(StringPrintf("N: %s=%s (line=%zu)", decl.prefix.c_str(), decl.uri.c_str(), + decl.line_number)); + printer_->Indent(); } - std::cerr << prefix_ << "E: "; + printer_->Print("E: "); if (!el->namespace_uri.empty()) { - std::cerr << el->namespace_uri << ":"; + printer_->Print(el->namespace_uri); + printer_->Print(":"); } - std::cerr << el->name << " (line=" << el->line_number << ")\n"; + printer_->Println(StringPrintf("%s (line=%zu)", el->name.c_str(), el->line_number)); + printer_->Indent(); for (const xml::Attribute& attr : el->attributes) { - std::cerr << prefix_ << " A: "; + printer_->Print("A: "); if (!attr.namespace_uri.empty()) { - std::cerr << attr.namespace_uri << ":"; + printer_->Print(attr.namespace_uri); + printer_->Print(":"); } - std::cerr << attr.name; + printer_->Print(attr.name); if (attr.compiled_attribute) { - std::cerr << "(" << attr.compiled_attribute.value().id.value_or_default(ResourceId(0x0)) - << ")"; + printer_->Print("("); + printer_->Print( + attr.compiled_attribute.value().id.value_or_default(ResourceId(0)).to_string()); + printer_->Print(")"); } - std::cerr << "="; + printer_->Print("="); if (attr.compiled_value != nullptr) { - std::cerr << *attr.compiled_value; + attr.compiled_value->PrettyPrint(printer_); } else { - std::cerr << attr.value; + printer_->Print(attr.value); } - std::cerr << "\n"; + printer_->Println(); } - prefix_ += " "; + printer_->Indent(); xml::ConstVisitor::Visit(el); - prefix_.resize(previous_size); + printer_->Undent(); + printer_->Undent(); + + for (size_t i = 0; i < el->namespace_decls.size(); i++) { + printer_->Undent(); + } } void Visit(const xml::Text* text) override { - std::cerr << prefix_ << "T: '" << text->text << "'\n"; + printer_->Println(StringPrintf("T: '%s'", text->text.c_str())); } private: - std::string prefix_; + Printer* printer_; }; } // namespace -void Debug::DumpXml(const xml::XmlResource& doc) { - XmlPrinter printer; - doc.root->Accept(&printer); +void Debug::DumpXml(const xml::XmlResource& doc, Printer* printer) { + XmlPrinter xml_visitor(printer); + doc.root->Accept(&xml_visitor); } } // namespace aapt diff --git a/tools/aapt2/Debug.h b/tools/aapt2/Debug.h index 6209a04c3c2d..382707e1d4cd 100644 --- a/tools/aapt2/Debug.h +++ b/tools/aapt2/Debug.h @@ -37,7 +37,7 @@ struct Debug { text::Printer* printer); static void PrintStyleGraph(ResourceTable* table, const ResourceName& target_style); static void DumpHex(const void* data, size_t len); - static void DumpXml(const xml::XmlResource& doc); + static void DumpXml(const xml::XmlResource& doc, text::Printer* printer); }; } // namespace aapt diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp index 3d2fb556cf59..8e7e5e59bc31 100644 --- a/tools/aapt2/cmd/Dump.cpp +++ b/tools/aapt2/cmd/Dump.cpp @@ -38,6 +38,13 @@ using ::android::base::StringPrintf; namespace aapt { +struct DumpOptions { + DebugPrintTableOptions print_options; + + // The path to a file within an APK to dump. + Maybe<std::string> file_to_dump_path; +}; + static const char* ResourceFileTypeToString(const ResourceFile::Type& type) { switch (type) { case ResourceFile::Type::kPng: @@ -69,8 +76,52 @@ static void DumpCompiledFile(const ResourceFile& file, const Source& source, off printer->Println(StringPrintf("Data: offset=%" PRIi64 " length=%zd", offset, len)); } +static bool DumpXmlFile(IAaptContext* context, io::IFile* file, bool proto, + text::Printer* printer) { + std::unique_ptr<xml::XmlResource> doc; + if (proto) { + std::unique_ptr<io::InputStream> in = file->OpenInputStream(); + if (in == nullptr) { + context->GetDiagnostics()->Error(DiagMessage() << "failed to open file"); + return false; + } + + io::ZeroCopyInputAdaptor adaptor(in.get()); + pb::XmlNode pb_node; + if (!pb_node.ParseFromZeroCopyStream(&adaptor)) { + context->GetDiagnostics()->Error(DiagMessage() << "failed to parse file as proto XML"); + return false; + } + + std::string err; + doc = DeserializeXmlResourceFromPb(pb_node, &err); + if (doc == nullptr) { + context->GetDiagnostics()->Error(DiagMessage() << "failed to deserialize proto XML"); + return false; + } + printer->Println("Proto XML"); + } else { + std::unique_ptr<io::IData> data = file->OpenAsData(); + if (data == nullptr) { + context->GetDiagnostics()->Error(DiagMessage() << "failed to open file"); + return false; + } + + std::string err; + doc = xml::Inflate(data->data(), data->size(), &err); + if (doc == nullptr) { + context->GetDiagnostics()->Error(DiagMessage() << "failed to parse file as binary XML"); + return false; + } + printer->Println("Binary XML"); + } + + Debug::DumpXml(*doc, printer); + return true; +} + static bool TryDumpFile(IAaptContext* context, const std::string& file_path, - const DebugPrintTableOptions& print_options) { + const DumpOptions& options) { // Use a smaller buffer so that there is less latency for dumping to stdout. constexpr size_t kStdOutBufferSize = 1024u; io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize); @@ -80,7 +131,10 @@ static bool TryDumpFile(IAaptContext* context, const std::string& file_path, std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(file_path, &err); if (zip) { ResourceTable table; + bool proto = false; if (io::IFile* file = zip->FindFile("resources.pb")) { + proto = true; + std::unique_ptr<io::IData> data = file->OpenAsData(); if (data == nullptr) { context->GetDiagnostics()->Error(DiagMessage(file_path) << "failed to open resources.pb"); @@ -98,8 +152,6 @@ static bool TryDumpFile(IAaptContext* context, const std::string& file_path, << "failed to parse table: " << err); return false; } - - printer.Println("Proto APK"); } else if (io::IFile* file = zip->FindFile("resources.arsc")) { std::unique_ptr<io::IData> data = file->OpenAsData(); if (!data) { @@ -112,12 +164,26 @@ static bool TryDumpFile(IAaptContext* context, const std::string& file_path, if (!parser.Parse()) { return false; } + } - printer.Println("Binary APK"); + if (!options.file_to_dump_path) { + if (proto) { + printer.Println("Proto APK"); + } else { + printer.Println("Binary APK"); + } + Debug::PrintTable(table, options.print_options, &printer); + return true; } - Debug::PrintTable(table, print_options, &printer); - return true; + io::IFile* file = zip->FindFile(options.file_to_dump_path.value()); + if (file == nullptr) { + context->GetDiagnostics()->Error(DiagMessage(file_path) + << "file '" << options.file_to_dump_path.value() + << "' not found in APK"); + return false; + } + return DumpXmlFile(context, file, proto, &printer); } err.clear(); @@ -159,7 +225,7 @@ static bool TryDumpFile(IAaptContext* context, const std::string& file_path, } printer.Indent(); - Debug::PrintTable(table, print_options, &printer); + Debug::PrintTable(table, options.print_options, &printer); printer.Undent(); } else if (entry->Type() == ContainerEntryType::kResFile) { printer.Println("kResFile"); @@ -243,10 +309,13 @@ class DumpContext : public IAaptContext { int Dump(const std::vector<StringPiece>& args) { bool verbose = false; bool no_values = false; + DumpOptions options; Flags flags = Flags() .OptionalSwitch("--no-values", "Suppresses output of values when displaying resource tables.", &no_values) + .OptionalFlag("--file", "Dumps the specified file from the APK passed as arg.", + &options.file_to_dump_path) .OptionalSwitch("-v", "increase verbosity of output", &verbose); if (!flags.Parse("aapt2 dump", args, &std::cerr)) { return 1; @@ -255,11 +324,10 @@ int Dump(const std::vector<StringPiece>& args) { DumpContext context; context.SetVerbose(verbose); - DebugPrintTableOptions dump_table_options; - dump_table_options.show_sources = true; - dump_table_options.show_values = !no_values; + options.print_options.show_sources = true; + options.print_options.show_values = !no_values; for (const std::string& arg : flags.GetArgs()) { - if (!TryDumpFile(&context, arg, dump_table_options)) { + if (!TryDumpFile(&context, arg, options)) { return 1; } } |