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