Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f19f5057 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Dump XML files in aapt2 dump"

parents 697c0956 da9eba30
Loading
Loading
Loading
Loading
+35 −24
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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
+79 −11
Original line number Diff line number Diff line
@@ -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,14 +164,28 @@ static bool TryDumpFile(IAaptContext* context, const std::string& file_path,
      if (!parser.Parse()) {
        return false;
      }
    }

    if (!options.file_to_dump_path) {
      if (proto) {
        printer.Println("Proto APK");
      } else {
        printer.Println("Binary APK");
      }

    Debug::PrintTable(table, print_options, &printer);
      Debug::PrintTable(table, options.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();

  io::FileInputStream input(file_path);
@@ -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;
    }
  }