blob: 7ded9bcf8470af3d25548a60c769b2db3a9d4a97 [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) {
Fabien Sanglard362da822019-03-14 11:39:39 -070035 SetDescription("Dump information about an APK or APC.");
Ryan Mitchell214846d2018-09-19 16:57:01 -070036 }
37
38 text::Printer* GetPrinter() {
39 return printer_;
40 }
41
42 IDiagnostics* GetDiagnostics() {
43 return diag_;
44 }
45
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -070046 Maybe<std::string> GetPackageName(LoadedApk* apk) {
47 xml::Element* manifest_el = apk->GetManifest()->root.get();
48 if (!manifest_el) {
49 GetDiagnostics()->Error(DiagMessage() << "No AndroidManifest.");
50 return Maybe<std::string>();
51 }
52
53 xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
54 if (!attr) {
55 GetDiagnostics()->Error(DiagMessage() << "No package name.");
56 return Maybe<std::string>();
57 }
58 return attr->value;
59 }
60
Ryan Mitchell214846d2018-09-19 16:57:01 -070061 /** Perform the dump operation on the apk. */
62 virtual int Dump(LoadedApk* apk) = 0;
63
64 int Action(const std::vector<std::string>& args) final {
65 if (args.size() < 1) {
66 diag_->Error(DiagMessage() << "No dump apk specified.");
67 return 1;
68 }
69
70 bool error = false;
71 for (auto apk : args) {
72 auto loaded_apk = LoadedApk::LoadApkFromPath(apk, diag_);
73 if (!loaded_apk) {
74 error = true;
75 continue;
76 }
77
78 error |= Dump(loaded_apk.get());
79 }
80
81 return error;
82 }
83
84 private:
85 text::Printer* printer_;
86 IDiagnostics* diag_;
87};
88
89/** Command that prints contents of files generated from the compilation stage. */
Ryan Mitchell5d275512018-07-19 14:29:00 -070090class DumpAPCCommand : public Command {
Ryan Mitchell833a1a62018-07-10 13:51:36 -070091 public:
Ryan Mitchell214846d2018-09-19 16:57:01 -070092 explicit DumpAPCCommand(text::Printer* printer, IDiagnostics* diag)
93 : Command("apc"), printer_(printer), diag_(diag) {
Ryan Mitchell5d275512018-07-19 14:29:00 -070094 SetDescription("Print the contents of the AAPT2 Container (APC) generated fom compilation.");
Ryan Mitchell833a1a62018-07-10 13:51:36 -070095 AddOptionalSwitch("--no-values", "Suppresses output of values when displaying resource tables.",
Ryan Mitchell5d275512018-07-19 14:29:00 -070096 &no_values_);
97 AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
Ryan Mitchell833a1a62018-07-10 13:51:36 -070098 }
99
100 int Action(const std::vector<std::string>& args) override;
101
102 private:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700103 text::Printer* printer_;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700104 IDiagnostics* diag_;
Ryan Mitchell833a1a62018-07-10 13:51:36 -0700105 bool no_values_ = false;
Ryan Mitchell214846d2018-09-19 16:57:01 -0700106 bool verbose_ = false;
Ryan Mitchell833a1a62018-07-10 13:51:36 -0700107};
108
Ryan Mitchell214846d2018-09-19 16:57:01 -0700109/** Easter egg command shown when users enter "badger" instead of "badging". */
110class DumpBadgerCommand : public Command {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700111 public:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700112 explicit DumpBadgerCommand(text::Printer* printer) : Command("badger"), printer_(printer) {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700113 }
114
115 int Action(const std::vector<std::string>& args) override;
116
117 private:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700118 text::Printer* printer_;
119 const static char kBadgerData[2925];
Ryan Mitchell5d275512018-07-19 14:29:00 -0700120};
121
Ryan Mitchell214846d2018-09-19 16:57:01 -0700122class DumpBadgingCommand : public DumpApkCommand {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700123 public:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700124 explicit DumpBadgingCommand(text::Printer* printer, IDiagnostics* diag)
125 : DumpApkCommand("badging", printer, diag) {
126 SetDescription("Print information extracted from the manifest of the APK.");
127 AddOptionalSwitch("--include-meta-data", "Include meta-data information.",
128 &options_.include_meta_data);
129 }
130
131 int Dump(LoadedApk* apk) override {
132 return DumpManifest(apk, options_, GetPrinter(), GetDiagnostics());
133 }
134
135 private:
136 DumpManifestOptions options_;
137};
138
139class DumpConfigsCommand : public DumpApkCommand {
140 public:
141 explicit DumpConfigsCommand(text::Printer* printer, IDiagnostics* diag)
142 : DumpApkCommand("configurations", printer, diag) {
143 SetDescription("Print every configuration used by a resource in the APK.");
144 }
145
146 int Dump(LoadedApk* apk) override;
147};
148
149class DumpPackageNameCommand : public DumpApkCommand {
150 public:
151 explicit DumpPackageNameCommand(text::Printer* printer, IDiagnostics* diag)
152 : DumpApkCommand("packagename", printer, diag) {
153 SetDescription("Print the package name of the APK.");
154 }
155
156 int Dump(LoadedApk* apk) override;
157};
158
159class DumpPermissionsCommand : public DumpApkCommand {
160 public:
161 explicit DumpPermissionsCommand(text::Printer* printer, IDiagnostics* diag)
162 : DumpApkCommand("permissions", printer, diag) {
163 SetDescription("Print the permissions extracted from the manifest of the APK.");
164 }
165
166 int Dump(LoadedApk* apk) override {
167 DumpManifestOptions options;
168 options.only_permissions = true;
169 return DumpManifest(apk, options, GetPrinter(), GetDiagnostics());
170 }
171};
172
173class DumpStringsCommand : public DumpApkCommand {
174 public:
175 explicit DumpStringsCommand(text::Printer* printer, IDiagnostics* diag)
176 : DumpApkCommand("strings", printer, diag) {
177 SetDescription("Print the contents of the resource table string pool in the APK.");
178 }
179
180 int Dump(LoadedApk* apk) override;
181};
182
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -0700183/** Prints the graph of parents of a style in an APK. */
184class DumpStyleParentCommand : public DumpApkCommand {
185 public:
186 explicit DumpStyleParentCommand(text::Printer* printer, IDiagnostics* diag)
187 : DumpApkCommand("styleparents", printer, diag) {
188 SetDescription("Print the parents of a style in an APK.");
189 AddRequiredFlag("--style", "The name of the style to print", &style_);
190 }
191
192 int Dump(LoadedApk* apk) override;
193
194 private:
195 std::string style_;
196};
197
Ryan Mitchell214846d2018-09-19 16:57:01 -0700198class DumpTableCommand : public DumpApkCommand {
199 public:
200 explicit DumpTableCommand(text::Printer* printer, IDiagnostics* diag)
201 : DumpApkCommand("resources", printer, diag) {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700202 SetDescription("Print the contents of the resource table from the APK.");
203 AddOptionalSwitch("--no-values", "Suppresses output of values when displaying resource tables.",
204 &no_values_);
205 AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
206 }
207
Ryan Mitchell214846d2018-09-19 16:57:01 -0700208 int Dump(LoadedApk* apk) override;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700209
210 private:
Ryan Mitchell5d275512018-07-19 14:29:00 -0700211 bool no_values_ = false;
Ryan Mitchell214846d2018-09-19 16:57:01 -0700212 bool verbose_ = false;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700213};
214
Ryan Mitchell214846d2018-09-19 16:57:01 -0700215class DumpXmlStringsCommand : public DumpApkCommand {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700216 public:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700217 explicit DumpXmlStringsCommand(text::Printer* printer, IDiagnostics* diag)
218 : DumpApkCommand("xmlstrings", printer, diag) {
219 SetDescription("Print the string pool of a compiled xml in an APK.");
220 AddRequiredFlagList("--file", "A compiled xml file to print", &files_);
221 }
222
223 int Dump(LoadedApk* apk) override;
224
225 private:
226 std::vector<std::string> files_;
227};
228
229class DumpXmlTreeCommand : public DumpApkCommand {
230 public:
231 explicit DumpXmlTreeCommand(text::Printer* printer, IDiagnostics* diag)
232 : DumpApkCommand("xmltree", printer, diag) {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700233 SetDescription("Print the tree of a compiled xml in an APK.");
234 AddRequiredFlagList("--file", "A compiled xml file to print", &files_);
235 }
236
Ryan Mitchell214846d2018-09-19 16:57:01 -0700237 int Dump(LoadedApk* apk) override;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700238
239 private:
Ryan Mitchell5d275512018-07-19 14:29:00 -0700240 std::vector<std::string> files_;
241};
242
Todd Kennedy908b7fc2018-08-24 10:11:21 -0700243/** The default dump command. Performs no action because a subcommand is required. */
Ryan Mitchell5d275512018-07-19 14:29:00 -0700244class DumpCommand : public Command {
245 public:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700246 explicit DumpCommand(text::Printer* printer, IDiagnostics* diag)
247 : Command("dump", "d"), diag_(diag) {
248 AddOptionalSubcommand(util::make_unique<DumpAPCCommand>(printer, diag_));
249 AddOptionalSubcommand(util::make_unique<DumpBadgingCommand>(printer, diag_));
250 AddOptionalSubcommand(util::make_unique<DumpConfigsCommand>(printer, diag_));
251 AddOptionalSubcommand(util::make_unique<DumpPackageNameCommand>(printer, diag_));
252 AddOptionalSubcommand(util::make_unique<DumpPermissionsCommand>(printer, diag_));
253 AddOptionalSubcommand(util::make_unique<DumpStringsCommand>(printer, diag_));
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -0700254 AddOptionalSubcommand(util::make_unique<DumpStyleParentCommand>(printer, diag_));
Ryan Mitchell214846d2018-09-19 16:57:01 -0700255 AddOptionalSubcommand(util::make_unique<DumpTableCommand>(printer, diag_));
256 AddOptionalSubcommand(util::make_unique<DumpXmlStringsCommand>(printer, diag_));
257 AddOptionalSubcommand(util::make_unique<DumpXmlTreeCommand>(printer, diag_));
258 AddOptionalSubcommand(util::make_unique<DumpBadgerCommand>(printer), /* hidden */ true);
Ryan Mitchell1bb1fe02018-11-16 11:21:41 -0800259 // TODO(b/120609160): Add aapt2 overlayable dump command
Ryan Mitchell5d275512018-07-19 14:29:00 -0700260 }
261
Ryan Mitchell214846d2018-09-19 16:57:01 -0700262 int Action(const std::vector<std::string>& args) override {
263 if (args.size() == 0) {
264 diag_->Error(DiagMessage() << "no subcommand specified");
265 } else {
266 diag_->Error(DiagMessage() << "unknown subcommand '" << args[0] << "'");
267 }
268 Usage(&std::cerr);
269 return 1;
270 }
Ryan Mitchell5d275512018-07-19 14:29:00 -0700271
272 private:
273 IDiagnostics* diag_;
274};
275
Ryan Mitchell214846d2018-09-19 16:57:01 -0700276} // namespace aapt
Ryan Mitchell833a1a62018-07-10 13:51:36 -0700277
Ryan Mitchell214846d2018-09-19 16:57:01 -0700278#endif // AAPT2_DUMP_H