blob: 5cf056e60640f0f9ccf77e1f74428634802a1c27 [file] [log] [blame]
Ryan Mitchell833a1a62018-07-10 13:51:36 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef AAPT2_DUMP_H
18#define AAPT2_DUMP_H
19
20#include "Command.h"
21#include "Debug.h"
Ryan Mitchell214846d2018-09-19 16:57:01 -070022#include "LoadedApk.h"
Ryan Mitchellfc225b22018-08-21 14:52:51 -070023#include "dump/DumpManifest.h"
Ryan Mitchell833a1a62018-07-10 13:51:36 -070024
25namespace aapt {
26
Ryan Mitchell214846d2018-09-19 16:57:01 -070027/**
28 * The base command for dumping information about apks. When the command is executed, the command
29 * performs the DumpApkCommand::Dump() operation on each apk provided as a file argument.
30 **/
31class DumpApkCommand : public Command {
32 public:
33 explicit DumpApkCommand(const std::string&& name, text::Printer* printer, IDiagnostics* diag)
34 : Command(name), printer_(printer), diag_(diag) {
35 }
36
37 text::Printer* GetPrinter() {
38 return printer_;
39 }
40
41 IDiagnostics* GetDiagnostics() {
42 return diag_;
43 }
44
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -070045 Maybe<std::string> GetPackageName(LoadedApk* apk) {
46 xml::Element* manifest_el = apk->GetManifest()->root.get();
47 if (!manifest_el) {
48 GetDiagnostics()->Error(DiagMessage() << "No AndroidManifest.");
49 return Maybe<std::string>();
50 }
51
52 xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
53 if (!attr) {
54 GetDiagnostics()->Error(DiagMessage() << "No package name.");
55 return Maybe<std::string>();
56 }
57 return attr->value;
58 }
59
Ryan Mitchell214846d2018-09-19 16:57:01 -070060 /** Perform the dump operation on the apk. */
61 virtual int Dump(LoadedApk* apk) = 0;
62
63 int Action(const std::vector<std::string>& args) final {
64 if (args.size() < 1) {
65 diag_->Error(DiagMessage() << "No dump apk specified.");
66 return 1;
67 }
68
69 bool error = false;
70 for (auto apk : args) {
71 auto loaded_apk = LoadedApk::LoadApkFromPath(apk, diag_);
72 if (!loaded_apk) {
73 error = true;
74 continue;
75 }
76
77 error |= Dump(loaded_apk.get());
78 }
79
80 return error;
81 }
82
83 private:
84 text::Printer* printer_;
85 IDiagnostics* diag_;
86};
87
88/** Command that prints contents of files generated from the compilation stage. */
Ryan Mitchell5d275512018-07-19 14:29:00 -070089class DumpAPCCommand : public Command {
Ryan Mitchell833a1a62018-07-10 13:51:36 -070090 public:
Ryan Mitchell214846d2018-09-19 16:57:01 -070091 explicit DumpAPCCommand(text::Printer* printer, IDiagnostics* diag)
92 : Command("apc"), printer_(printer), diag_(diag) {
Ryan Mitchell5d275512018-07-19 14:29:00 -070093 SetDescription("Print the contents of the AAPT2 Container (APC) generated fom compilation.");
Ryan Mitchell833a1a62018-07-10 13:51:36 -070094 AddOptionalSwitch("--no-values", "Suppresses output of values when displaying resource tables.",
Ryan Mitchell5d275512018-07-19 14:29:00 -070095 &no_values_);
96 AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
Ryan Mitchell833a1a62018-07-10 13:51:36 -070097 }
98
99 int Action(const std::vector<std::string>& args) override;
100
101 private:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700102 text::Printer* printer_;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700103 IDiagnostics* diag_;
Ryan Mitchell833a1a62018-07-10 13:51:36 -0700104 bool no_values_ = false;
Ryan Mitchell214846d2018-09-19 16:57:01 -0700105 bool verbose_ = false;
Ryan Mitchell833a1a62018-07-10 13:51:36 -0700106};
107
Ryan Mitchell214846d2018-09-19 16:57:01 -0700108/** Easter egg command shown when users enter "badger" instead of "badging". */
109class DumpBadgerCommand : public Command {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700110 public:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700111 explicit DumpBadgerCommand(text::Printer* printer) : Command("badger"), printer_(printer) {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700112 }
113
114 int Action(const std::vector<std::string>& args) override;
115
116 private:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700117 text::Printer* printer_;
118 const static char kBadgerData[2925];
Ryan Mitchell5d275512018-07-19 14:29:00 -0700119};
120
Ryan Mitchell214846d2018-09-19 16:57:01 -0700121class DumpBadgingCommand : public DumpApkCommand {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700122 public:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700123 explicit DumpBadgingCommand(text::Printer* printer, IDiagnostics* diag)
124 : DumpApkCommand("badging", printer, diag) {
125 SetDescription("Print information extracted from the manifest of the APK.");
126 AddOptionalSwitch("--include-meta-data", "Include meta-data information.",
127 &options_.include_meta_data);
128 }
129
130 int Dump(LoadedApk* apk) override {
131 return DumpManifest(apk, options_, GetPrinter(), GetDiagnostics());
132 }
133
134 private:
135 DumpManifestOptions options_;
136};
137
138class DumpConfigsCommand : public DumpApkCommand {
139 public:
140 explicit DumpConfigsCommand(text::Printer* printer, IDiagnostics* diag)
141 : DumpApkCommand("configurations", printer, diag) {
142 SetDescription("Print every configuration used by a resource in the APK.");
143 }
144
145 int Dump(LoadedApk* apk) override;
146};
147
148class DumpPackageNameCommand : public DumpApkCommand {
149 public:
150 explicit DumpPackageNameCommand(text::Printer* printer, IDiagnostics* diag)
151 : DumpApkCommand("packagename", printer, diag) {
152 SetDescription("Print the package name of the APK.");
153 }
154
155 int Dump(LoadedApk* apk) override;
156};
157
158class DumpPermissionsCommand : public DumpApkCommand {
159 public:
160 explicit DumpPermissionsCommand(text::Printer* printer, IDiagnostics* diag)
161 : DumpApkCommand("permissions", printer, diag) {
162 SetDescription("Print the permissions extracted from the manifest of the APK.");
163 }
164
165 int Dump(LoadedApk* apk) override {
166 DumpManifestOptions options;
167 options.only_permissions = true;
168 return DumpManifest(apk, options, GetPrinter(), GetDiagnostics());
169 }
170};
171
172class DumpStringsCommand : public DumpApkCommand {
173 public:
174 explicit DumpStringsCommand(text::Printer* printer, IDiagnostics* diag)
175 : DumpApkCommand("strings", printer, diag) {
176 SetDescription("Print the contents of the resource table string pool in the APK.");
177 }
178
179 int Dump(LoadedApk* apk) override;
180};
181
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -0700182/** Prints the graph of parents of a style in an APK. */
183class DumpStyleParentCommand : public DumpApkCommand {
184 public:
185 explicit DumpStyleParentCommand(text::Printer* printer, IDiagnostics* diag)
186 : DumpApkCommand("styleparents", printer, diag) {
187 SetDescription("Print the parents of a style in an APK.");
188 AddRequiredFlag("--style", "The name of the style to print", &style_);
189 }
190
191 int Dump(LoadedApk* apk) override;
192
193 private:
194 std::string style_;
195};
196
Ryan Mitchell214846d2018-09-19 16:57:01 -0700197class DumpTableCommand : public DumpApkCommand {
198 public:
199 explicit DumpTableCommand(text::Printer* printer, IDiagnostics* diag)
200 : DumpApkCommand("resources", printer, diag) {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700201 SetDescription("Print the contents of the resource table from the APK.");
202 AddOptionalSwitch("--no-values", "Suppresses output of values when displaying resource tables.",
203 &no_values_);
204 AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
205 }
206
Ryan Mitchell214846d2018-09-19 16:57:01 -0700207 int Dump(LoadedApk* apk) override;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700208
209 private:
Ryan Mitchell5d275512018-07-19 14:29:00 -0700210 bool no_values_ = false;
Ryan Mitchell214846d2018-09-19 16:57:01 -0700211 bool verbose_ = false;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700212};
213
Ryan Mitchell214846d2018-09-19 16:57:01 -0700214class DumpXmlStringsCommand : public DumpApkCommand {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700215 public:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700216 explicit DumpXmlStringsCommand(text::Printer* printer, IDiagnostics* diag)
217 : DumpApkCommand("xmlstrings", printer, diag) {
218 SetDescription("Print the string pool of a compiled xml in an APK.");
219 AddRequiredFlagList("--file", "A compiled xml file to print", &files_);
220 }
221
222 int Dump(LoadedApk* apk) override;
223
224 private:
225 std::vector<std::string> files_;
226};
227
228class DumpXmlTreeCommand : public DumpApkCommand {
229 public:
230 explicit DumpXmlTreeCommand(text::Printer* printer, IDiagnostics* diag)
231 : DumpApkCommand("xmltree", printer, diag) {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700232 SetDescription("Print the tree of a compiled xml in an APK.");
233 AddRequiredFlagList("--file", "A compiled xml file to print", &files_);
234 }
235
Ryan Mitchell214846d2018-09-19 16:57:01 -0700236 int Dump(LoadedApk* apk) override;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700237
238 private:
Ryan Mitchell5d275512018-07-19 14:29:00 -0700239 std::vector<std::string> files_;
240};
241
Todd Kennedy908b7fc2018-08-24 10:11:21 -0700242/** The default dump command. Performs no action because a subcommand is required. */
Ryan Mitchell5d275512018-07-19 14:29:00 -0700243class DumpCommand : public Command {
244 public:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700245 explicit DumpCommand(text::Printer* printer, IDiagnostics* diag)
246 : Command("dump", "d"), diag_(diag) {
247 AddOptionalSubcommand(util::make_unique<DumpAPCCommand>(printer, diag_));
248 AddOptionalSubcommand(util::make_unique<DumpBadgingCommand>(printer, diag_));
249 AddOptionalSubcommand(util::make_unique<DumpConfigsCommand>(printer, diag_));
250 AddOptionalSubcommand(util::make_unique<DumpPackageNameCommand>(printer, diag_));
251 AddOptionalSubcommand(util::make_unique<DumpPermissionsCommand>(printer, diag_));
252 AddOptionalSubcommand(util::make_unique<DumpStringsCommand>(printer, diag_));
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -0700253 AddOptionalSubcommand(util::make_unique<DumpStyleParentCommand>(printer, diag_));
Ryan Mitchell214846d2018-09-19 16:57:01 -0700254 AddOptionalSubcommand(util::make_unique<DumpTableCommand>(printer, diag_));
255 AddOptionalSubcommand(util::make_unique<DumpXmlStringsCommand>(printer, diag_));
256 AddOptionalSubcommand(util::make_unique<DumpXmlTreeCommand>(printer, diag_));
257 AddOptionalSubcommand(util::make_unique<DumpBadgerCommand>(printer), /* hidden */ true);
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800258 // TODO(b/120609160): Add aapt2 overlayable dump command
Ryan Mitchell5d275512018-07-19 14:29:00 -0700259 }
260
Ryan Mitchell214846d2018-09-19 16:57:01 -0700261 int Action(const std::vector<std::string>& args) override {
262 if (args.size() == 0) {
263 diag_->Error(DiagMessage() << "no subcommand specified");
264 } else {
265 diag_->Error(DiagMessage() << "unknown subcommand '" << args[0] << "'");
266 }
267 Usage(&std::cerr);
268 return 1;
269 }
Ryan Mitchell5d275512018-07-19 14:29:00 -0700270
271 private:
272 IDiagnostics* diag_;
273};
274
Ryan Mitchell214846d2018-09-19 16:57:01 -0700275} // namespace aapt
Ryan Mitchell833a1a62018-07-10 13:51:36 -0700276
Ryan Mitchell214846d2018-09-19 16:57:01 -0700277#endif // AAPT2_DUMP_H