159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski/*
259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * Copyright (C) 2016 The Android Open Source Project
359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski *
459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * you may not use this file except in compliance with the License.
659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * You may obtain a copy of the License at
759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski *
859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski *
1059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * Unless required by applicable law or agreed to in writing, software
1159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
1259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * See the License for the specific language governing permissions and
1459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * limitations under the License.
1559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski */
1659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
1793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski#include <cinttypes>
18ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <vector>
19ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
2093190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski#include "android-base/stringprintf.h"
21d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski#include "androidfw/StringPiece.h"
22d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski
2359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "Debug.h"
2459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "Diagnostics.h"
2559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "Flags.h"
26004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski#include "format/Container.h"
274670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski#include "format/binary/BinaryResourceParser.h"
284670805ea441edb8b280f9312571e7799f1284cfAdam Lesinski#include "format/proto/ProtoDeserialize.h"
29004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski#include "io/FileStream.h"
3064587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski#include "io/ZipArchive.h"
3159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "process/IResourceTableConsumer.h"
3293190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski#include "text/Printer.h"
3359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "util/Files.h"
34d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski
3593190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinskiusing ::aapt::text::Printer;
364ffea040641d3b74ab04b6d2d3e78280bc893d5fAdam Lesinskiusing ::android::StringPiece;
3793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinskiusing ::android::base::StringPrintf;
3859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
3959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskinamespace aapt {
4059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
41da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinskistruct DumpOptions {
42da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski  DebugPrintTableOptions print_options;
43da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski
44da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski  // The path to a file within an APK to dump.
45da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski  Maybe<std::string> file_to_dump_path;
46da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski};
47da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski
48004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskistatic const char* ResourceFileTypeToString(const ResourceFile::Type& type) {
49004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  switch (type) {
50004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    case ResourceFile::Type::kPng:
51004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      return "PNG";
52004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    case ResourceFile::Type::kBinaryXml:
53004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      return "BINARY_XML";
54004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    case ResourceFile::Type::kProtoXml:
55004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      return "PROTO_XML";
56004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    default:
57004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      break;
58004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  }
59004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  return "UNKNOWN";
60004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}
61cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
62004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskistatic void DumpCompiledFile(const ResourceFile& file, const Source& source, off64_t offset,
6393190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski                             size_t len, Printer* printer) {
6493190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  printer->Print("Resource: ");
6593190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  printer->Println(file.name.to_string());
6693190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
6793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  printer->Print("Config:   ");
6893190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  printer->Println(file.config.to_string());
6993190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
7093190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  printer->Print("Source:   ");
7193190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  printer->Println(file.source.to_string());
7293190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
7393190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  printer->Print("Type:     ");
7493190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  printer->Println(ResourceFileTypeToString(file.type));
7593190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
7693190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  printer->Println(StringPrintf("Data:     offset=%" PRIi64 " length=%zd", offset, len));
7759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}
7859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
79da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinskistatic bool DumpXmlFile(IAaptContext* context, io::IFile* file, bool proto,
80da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski                        text::Printer* printer) {
81da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski  std::unique_ptr<xml::XmlResource> doc;
82da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski  if (proto) {
83da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    std::unique_ptr<io::InputStream> in = file->OpenInputStream();
84da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    if (in == nullptr) {
85da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      context->GetDiagnostics()->Error(DiagMessage() << "failed to open file");
86da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      return false;
87da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    }
88da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski
89da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    io::ZeroCopyInputAdaptor adaptor(in.get());
90da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    pb::XmlNode pb_node;
91da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    if (!pb_node.ParseFromZeroCopyStream(&adaptor)) {
92da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      context->GetDiagnostics()->Error(DiagMessage() << "failed to parse file as proto XML");
93da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      return false;
94da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    }
95da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski
96da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    std::string err;
97da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    doc = DeserializeXmlResourceFromPb(pb_node, &err);
98da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    if (doc == nullptr) {
99da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      context->GetDiagnostics()->Error(DiagMessage() << "failed to deserialize proto XML");
100da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      return false;
101da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    }
102da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    printer->Println("Proto XML");
103da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski  } else {
104da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    std::unique_ptr<io::IData> data = file->OpenAsData();
105da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    if (data == nullptr) {
106da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      context->GetDiagnostics()->Error(DiagMessage() << "failed to open file");
107da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      return false;
108da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    }
109da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski
110da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    std::string err;
111da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    doc = xml::Inflate(data->data(), data->size(), &err);
112da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    if (doc == nullptr) {
113da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      context->GetDiagnostics()->Error(DiagMessage() << "failed to parse file as binary XML");
114da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      return false;
115da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    }
116da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    printer->Println("Binary XML");
117da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski  }
118da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski
119da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski  Debug::DumpXml(*doc, printer);
120da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski  return true;
121da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski}
122da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski
12371be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinskistatic bool TryDumpFile(IAaptContext* context, const std::string& file_path,
124da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski                        const DumpOptions& options) {
12593190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  // Use a smaller buffer so that there is less latency for dumping to stdout.
12693190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  constexpr size_t kStdOutBufferSize = 1024u;
12793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  io::FileOutputStream fout(STDOUT_FILENO, kStdOutBufferSize);
12893190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  Printer printer(&fout);
12993190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
130cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::string err;
131d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(file_path, &err);
132cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (zip) {
1338cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    ResourceTable table;
134da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    bool proto = false;
135e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski    if (io::IFile* file = zip->FindFile("resources.pb")) {
136da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      proto = true;
137da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski
138ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::unique_ptr<io::IData> data = file->OpenAsData();
1398cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      if (data == nullptr) {
140e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski        context->GetDiagnostics()->Error(DiagMessage(file_path) << "failed to open resources.pb");
141aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne        return false;
142cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
14364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      pb::ResourceTable pb_table;
145ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!pb_table.ParseFromArray(data->data(), data->size())) {
146e59f0d80ec19249f72c07ae191ad673d040443e3Adam Lesinski        context->GetDiagnostics()->Error(DiagMessage(file_path) << "invalid resources.pb");
147aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne        return false;
148cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
149cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1508780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      if (!DeserializeTableFromPb(pb_table, zip.get(), &table, &err)) {
1518cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        context->GetDiagnostics()->Error(DiagMessage(file_path)
1528cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski                                         << "failed to parse table: " << err);
1538cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        return false;
1548cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      }
1558cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    } else if (io::IFile* file = zip->FindFile("resources.arsc")) {
1568cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      std::unique_ptr<io::IData> data = file->OpenAsData();
1578cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      if (!data) {
1588cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        context->GetDiagnostics()->Error(DiagMessage(file_path) << "failed to open resources.arsc");
159aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne        return false;
160cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
16159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
1628780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      BinaryResourceParser parser(context->GetDiagnostics(), &table, Source(file_path),
1638780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski                                  data->data(), data->size());
1648cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski      if (!parser.Parse()) {
1658cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski        return false;
166cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
167da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    }
16893190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
169da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    if (!options.file_to_dump_path) {
170da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      if (proto) {
171da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski        printer.Println("Proto APK");
172da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      } else {
173da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski        printer.Println("Binary APK");
174da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      }
175da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      Debug::PrintTable(table, options.print_options, &printer);
176da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      return true;
177cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1788cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski
179da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    io::IFile* file = zip->FindFile(options.file_to_dump_path.value());
180da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    if (file == nullptr) {
181da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      context->GetDiagnostics()->Error(DiagMessage(file_path)
182da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski                                       << "file '" << options.file_to_dump_path.value()
183da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski                                       << "' not found in APK");
184da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      return false;
185da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    }
186da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    return DumpXmlFile(context, file, proto, &printer);
187cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
188cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1898cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  err.clear();
190cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
191004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  io::FileInputStream input(file_path);
192004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (input.HadError()) {
193004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    context->GetDiagnostics()->Error(DiagMessage(file_path)
194004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski                                     << "failed to open file: " << input.GetError());
1958cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    return false;
1968cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
197cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
1988cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  // Try as a compiled file.
199004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  ContainerReader reader(&input);
200004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  if (reader.HadError()) {
201004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    context->GetDiagnostics()->Error(DiagMessage(file_path)
202004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski                                     << "failed to read container: " << reader.GetError());
2038cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    return false;
2048cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski  }
205cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
20693190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski  printer.Println("AAPT2 Container (APC)");
207004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  ContainerReaderEntry* entry;
208004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski  while ((entry = reader.Next()) != nullptr) {
209004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    if (entry->Type() == ContainerEntryType::kResTable) {
21093190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      printer.Println("kResTable");
21193190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski
212004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      pb::ResourceTable pb_table;
213004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      if (!entry->GetResTable(&pb_table)) {
214004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski        context->GetDiagnostics()->Error(DiagMessage(file_path)
215004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski                                         << "failed to parse proto table: " << entry->GetError());
216004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski        continue;
217004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      }
218cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
219004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      ResourceTable table;
220004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      err.clear();
2218780eb6e4918ae24fb1ae74d631042c32e41dc3dAdam Lesinski      if (!DeserializeTableFromPb(pb_table, nullptr /*files*/, &table, &err)) {
222004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski        context->GetDiagnostics()->Error(DiagMessage(file_path)
223004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski                                         << "failed to parse table: " << err);
224004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski        continue;
225004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      }
226004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
22793190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      printer.Indent();
228da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski      Debug::PrintTable(table, options.print_options, &printer);
22993190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      printer.Undent();
230004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    } else if (entry->Type() == ContainerEntryType::kResFile) {
23193190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      printer.Println("kResFile");
232004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      pb::internal::CompiledFile pb_compiled_file;
233004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      off64_t offset;
234004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      size_t length;
235004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      if (!entry->GetResFileOffsets(&pb_compiled_file, &offset, &length)) {
236004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski        context->GetDiagnostics()->Error(
237004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski            DiagMessage(file_path) << "failed to parse compiled proto file: " << entry->GetError());
238004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski        continue;
239004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      }
240004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
241004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      ResourceFile file;
242004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      std::string error;
243004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      if (!DeserializeCompiledFileFromPb(pb_compiled_file, &file, &error)) {
244004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski        context->GetDiagnostics()->Warn(DiagMessage(file_path)
245004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski                                        << "failed to parse compiled file: " << error);
246004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski        continue;
247004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski      }
248cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
24993190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      printer.Indent();
25093190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      DumpCompiledFile(file, Source(file_path), offset, length, &printer);
25193190b79d11d874199cfe7258526a48cfc8399fcAdam Lesinski      printer.Undent();
2528cdca1bd722049facf5bbec44ec3ca67cade5288Adam Lesinski    }
253cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
254aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne  return true;
25559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}
25659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
257004511660671511ae88e0e837a6f92db28eadaefAdam Lesinskinamespace {
258004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
25959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskiclass DumpContext : public IAaptContext {
260cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
261b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  PackageType GetPackageType() override {
262b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    // Doesn't matter.
263b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    return PackageType::kApp;
264b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  }
265b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski
266d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  IDiagnostics* GetDiagnostics() override {
267d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return &diagnostics_;
268d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
26959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
270ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  NameMangler* GetNameMangler() override {
271004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    UNIMPLEMENTED(FATAL);
272cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return nullptr;
273cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
27459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
275ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const std::string& GetCompilationPackage() override {
276cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    static std::string empty;
277cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return empty;
278cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
27959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
280d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  uint8_t GetPackageId() override {
281d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return 0;
282d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
28359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
284ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  SymbolTable* GetExternalSymbols() override {
285004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski    UNIMPLEMENTED(FATAL);
286cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return nullptr;
287cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
28859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
289d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool IsVerbose() override {
290d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return verbose_;
291d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
292355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
293d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  void SetVerbose(bool val) {
294d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    verbose_ = val;
295d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
296355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
297d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  int GetMinSdkVersion() override {
298d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return 0;
299d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
300fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
301cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private:
302ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  StdErrDiagnostics diagnostics_;
303ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool verbose_ = false;
30459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski};
30559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
306004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski}  // namespace
307004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski
308004511660671511ae88e0e837a6f92db28eadaefAdam Lesinski// Entry point for dump command.
309ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiint Dump(const std::vector<StringPiece>& args) {
310cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool verbose = false;
31171be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski  bool no_values = false;
312da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski  DumpOptions options;
31371be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski  Flags flags = Flags()
31471be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski                    .OptionalSwitch("--no-values",
31571be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski                                    "Suppresses output of values when displaying resource tables.",
31671be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski                                    &no_values)
317da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski                    .OptionalFlag("--file", "Dumps the specified file from the APK passed as arg.",
318da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski                                  &options.file_to_dump_path)
31971be70507de9cb619b644e55eda1cc181e3f7e90Adam Lesinski                    .OptionalSwitch("-v", "increase verbosity of output", &verbose);
320ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!flags.Parse("aapt2 dump", args, &std::cerr)) {
321cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return 1;
322cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
323cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
324cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  DumpContext context;
325ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  context.SetVerbose(verbose);
326cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
327da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski  options.print_options.show_sources = true;
328da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski  options.print_options.show_values = !no_values;
329ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::string& arg : flags.GetArgs()) {
330da9eba300b0f84505fe094374c14d4bc910880d2Adam Lesinski    if (!TryDumpFile(&context, arg, options)) {
331aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne      return 1;
332aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne    }
333cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
334cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return 0;
33559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}
33659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
337cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace aapt
338