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
17ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <vector>
18ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski
19d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski#include "androidfw/StringPiece.h"
20d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski
2159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "Debug.h"
2259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "Diagnostics.h"
2359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "Flags.h"
2464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski#include "io/ZipArchive.h"
2559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "process/IResourceTableConsumer.h"
2659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "proto/ProtoSerialize.h"
275e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski#include "unflatten/BinaryResourceParser.h"
2859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "util/Files.h"
29d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski
30b791721cd1a6154e5582d824f5d20b2c8b8d5ac5Adam Lesinskiusing ::android::StringPiece;
3159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
3259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskinamespace aapt {
3359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
34b791721cd1a6154e5582d824f5d20b2c8b8d5ac5Adam Lesinskibool DumpCompiledFile(const pb::internal::CompiledFile& pb_file, const void* data, size_t len,
35d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                      const Source& source, IAaptContext* context) {
36cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::unique_ptr<ResourceFile> file =
37ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      DeserializeCompiledFileFromPb(pb_file, source, context->GetDiagnostics());
38cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!file) {
39d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    context->GetDiagnostics()->Warn(DiagMessage() << "failed to read compiled file");
40aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne    return false;
41cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
42cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
43cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::cout << "Resource: " << file->name << "\n"
44cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            << "Config:   " << file->config << "\n"
45cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski            << "Source:   " << file->source << "\n";
46aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne  return true;
4759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}
4859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
49aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesnebool TryDumpFile(IAaptContext* context, const std::string& file_path) {
50cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::unique_ptr<ResourceTable> table;
51cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
52cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  std::string err;
53d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(file_path, &err);
54cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (zip) {
55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    io::IFile* file = zip->FindFile("resources.arsc.flat");
56cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (file) {
57ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      std::unique_ptr<io::IData> data = file->OpenAsData();
58cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (!data) {
59d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context->GetDiagnostics()->Error(DiagMessage(file_path)
60d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                         << "failed to open resources.arsc.flat");
61aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne        return false;
62cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
6364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski
64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      pb::ResourceTable pb_table;
65ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!pb_table.ParseFromArray(data->data(), data->size())) {
66d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        context->GetDiagnostics()->Error(DiagMessage(file_path) << "invalid resources.arsc.flat");
67aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne        return false;
68cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
69cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
70d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      table = DeserializeTableFromPb(pb_table, Source(file_path), context->GetDiagnostics());
71cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (!table) {
72aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne        return false;
73cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
7459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
7559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
765e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski    if (!table) {
77ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      file = zip->FindFile("resources.arsc");
78cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      if (file) {
79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        std::unique_ptr<io::IData> data = file->OpenAsData();
80cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        if (!data) {
81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski          context->GetDiagnostics()->Error(DiagMessage(file_path)
82cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski                                           << "failed to open resources.arsc");
83aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne          return false;
845e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski        }
8559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
86cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        table = util::make_unique<ResourceTable>();
87d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        BinaryResourceParser parser(context, table.get(), Source(file_path), data->data(),
88d0f492db038c6210c1138865d816bfb134376538Adam Lesinski                                    data->size());
89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!parser.Parse()) {
90aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne          return false;
91cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        }
92cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
93cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
94cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
95cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
96cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (!table) {
97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Maybe<android::FileMap> file = file::MmapPath(file_path, &err);
98cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!file) {
99ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      context->GetDiagnostics()->Error(DiagMessage(file_path) << err);
100aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne      return false;
101cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
102cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    android::FileMap* file_map = &file.value();
104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    // Try as a compiled table.
106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    pb::ResourceTable pb_table;
107d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    if (pb_table.ParseFromArray(file_map->getDataPtr(), file_map->getDataLength())) {
108d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      table = DeserializeTableFromPb(pb_table, Source(file_path), context->GetDiagnostics());
109cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    }
1105e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski
111cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    if (!table) {
112cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      // Try as a compiled file.
113d0f492db038c6210c1138865d816bfb134376538Adam Lesinski      CompiledFileInputStream input(file_map->getDataPtr(), file_map->getDataLength());
114cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      uint32_t num_files = 0;
116ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      if (!input.ReadLittleEndian32(&num_files)) {
117aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne        return false;
118cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
119cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
120ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski      for (uint32_t i = 0; i < num_files; i++) {
121b791721cd1a6154e5582d824f5d20b2c8b8d5ac5Adam Lesinski        pb::internal::CompiledFile compiled_file;
122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski        if (!input.ReadCompiledFile(&compiled_file)) {
123d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context->GetDiagnostics()->Warn(DiagMessage() << "failed to read compiled file");
124aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne          return false;
1255e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski        }
1265e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski
127cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        uint64_t offset, len;
128cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski        if (!input.ReadDataMetaData(&offset, &len)) {
129d0f492db038c6210c1138865d816bfb134376538Adam Lesinski          context->GetDiagnostics()->Warn(DiagMessage() << "failed to read meta data");
130aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne          return false;
1315e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski        }
13259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
133d0f492db038c6210c1138865d816bfb134376538Adam Lesinski        const void* data = static_cast<const uint8_t*>(file_map->getDataPtr()) + offset;
134aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne        if (!DumpCompiledFile(compiled_file, data, len, Source(file_path), context)) {
135aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne          return false;
136aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne        }
137cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski      }
13859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski    }
139cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
140cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
141cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  if (table) {
142ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    DebugPrintTableOptions options;
143ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    options.show_sources = true;
144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski    Debug::PrintTable(table.get(), options);
145cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
146aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne
147aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne  return true;
14859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}
14959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
15059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskiclass DumpContext : public IAaptContext {
151cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public:
152b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  PackageType GetPackageType() override {
153b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    // Doesn't matter.
154b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski    return PackageType::kApp;
155b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski  }
156b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski
157d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  IDiagnostics* GetDiagnostics() override {
158d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return &diagnostics_;
159d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
16059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  NameMangler* GetNameMangler() override {
162cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    abort();
163cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return nullptr;
164cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
16559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
166ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  const std::string& GetCompilationPackage() override {
167cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    static std::string empty;
168cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return empty;
169cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
17059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
171d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  uint8_t GetPackageId() override {
172d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return 0;
173d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
17459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
175ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  SymbolTable* GetExternalSymbols() override {
176cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    abort();
177cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return nullptr;
178cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
17959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
180d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  bool IsVerbose() override {
181d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return verbose_;
182d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
183355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
184d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  void SetVerbose(bool val) {
185d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    verbose_ = val;
186d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
187355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski
188d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  int GetMinSdkVersion() override {
189d0f492db038c6210c1138865d816bfb134376538Adam Lesinski    return 0;
190d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  }
191fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski
192cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private:
193ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  StdErrDiagnostics diagnostics_;
194ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  bool verbose_ = false;
19559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski};
19659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
19759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski/**
19859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * Entry point for dump command.
19959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski */
200ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiint Dump(const std::vector<StringPiece>& args) {
201cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  bool verbose = false;
202d0f492db038c6210c1138865d816bfb134376538Adam Lesinski  Flags flags = Flags().OptionalSwitch("-v", "increase verbosity of output", &verbose);
203ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  if (!flags.Parse("aapt2 dump", args, &std::cerr)) {
204cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski    return 1;
205cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
206cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
207cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  DumpContext context;
208ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  context.SetVerbose(verbose);
209cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski
210ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski  for (const std::string& arg : flags.GetArgs()) {
211aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne    if (!TryDumpFile(&context, arg)) {
212aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne      return 1;
213aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne    }
214cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  }
215aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne
216cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski  return 0;
21759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}
21859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski
219cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski}  // namespace aapt
220