blob: 119a59b283174ab2fa33a974ae7007beb2f6e1d3 [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
Jeremy Meyerb4f83ff2023-11-30 19:29:50 +000020#include <androidfw/FileStream.h>
Ryan Mitchell19b27092018-08-13 11:36:27 -070021#include <io/ZipArchive.h>
22
Ryan Mitchell833a1a62018-07-10 13:51:36 -070023#include "Command.h"
24#include "Debug.h"
Ryan Mitchell214846d2018-09-19 16:57:01 -070025#include "LoadedApk.h"
Ryan Mitchellfc225b22018-08-21 14:52:51 -070026#include "dump/DumpManifest.h"
Ryan Mitchell833a1a62018-07-10 13:51:36 -070027
28namespace aapt {
29
Ryan Mitchell214846d2018-09-19 16:57:01 -070030/**
31 * The base command for dumping information about apks. When the command is executed, the command
32 * performs the DumpApkCommand::Dump() operation on each apk provided as a file argument.
33 **/
34class DumpApkCommand : public Command {
35 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +000036 explicit DumpApkCommand(const std::string&& name, text::Printer* printer,
37 android::IDiagnostics* diag)
Ryan Mitchell214846d2018-09-19 16:57:01 -070038 : Command(name), printer_(printer), diag_(diag) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +000039 SetDescription("Dump information about an APK or APC.");
Ryan Mitchell214846d2018-09-19 16:57:01 -070040 }
41
42 text::Printer* GetPrinter() {
43 return printer_;
44 }
45
Jeremy Meyer56f36e82022-05-20 20:35:42 +000046 android::IDiagnostics* GetDiagnostics() {
Ryan Mitchell214846d2018-09-19 16:57:01 -070047 return diag_;
48 }
49
Ryan Mitchell4382e442021-07-14 12:53:01 -070050 std::optional<std::string> GetPackageName(LoadedApk* apk) {
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -070051 xml::Element* manifest_el = apk->GetManifest()->root.get();
52 if (!manifest_el) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +000053 GetDiagnostics()->Error(android::DiagMessage() << "No AndroidManifest.");
Ryan Mitchell4382e442021-07-14 12:53:01 -070054 return {};
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -070055 }
56
57 xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
58 if (!attr) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +000059 GetDiagnostics()->Error(android::DiagMessage() << "No package name.");
Ryan Mitchell4382e442021-07-14 12:53:01 -070060 return {};
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -070061 }
62 return attr->value;
63 }
64
Ryan Mitchell214846d2018-09-19 16:57:01 -070065 /** Perform the dump operation on the apk. */
66 virtual int Dump(LoadedApk* apk) = 0;
67
68 int Action(const std::vector<std::string>& args) final {
69 if (args.size() < 1) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +000070 diag_->Error(android::DiagMessage() << "No dump apk specified.");
Ryan Mitchell214846d2018-09-19 16:57:01 -070071 return 1;
72 }
73
74 bool error = false;
75 for (auto apk : args) {
76 auto loaded_apk = LoadedApk::LoadApkFromPath(apk, diag_);
77 if (!loaded_apk) {
78 error = true;
79 continue;
80 }
81
82 error |= Dump(loaded_apk.get());
83 }
84
85 return error;
86 }
87
88 private:
89 text::Printer* printer_;
Jeremy Meyer56f36e82022-05-20 20:35:42 +000090 android::IDiagnostics* diag_;
Ryan Mitchell214846d2018-09-19 16:57:01 -070091};
92
93/** Command that prints contents of files generated from the compilation stage. */
Ryan Mitchell5d275512018-07-19 14:29:00 -070094class DumpAPCCommand : public Command {
Ryan Mitchell833a1a62018-07-10 13:51:36 -070095 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +000096 explicit DumpAPCCommand(text::Printer* printer, android::IDiagnostics* diag)
Ryan Mitchell214846d2018-09-19 16:57:01 -070097 : Command("apc"), printer_(printer), diag_(diag) {
Ryan Mitchell5d275512018-07-19 14:29:00 -070098 SetDescription("Print the contents of the AAPT2 Container (APC) generated fom compilation.");
Ryan Mitchell833a1a62018-07-10 13:51:36 -070099 AddOptionalSwitch("--no-values", "Suppresses output of values when displaying resource tables.",
Ryan Mitchell5d275512018-07-19 14:29:00 -0700100 &no_values_);
101 AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
Ryan Mitchell833a1a62018-07-10 13:51:36 -0700102 }
103
104 int Action(const std::vector<std::string>& args) override;
105
106 private:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700107 text::Printer* printer_;
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000108 android::IDiagnostics* diag_;
Ryan Mitchell833a1a62018-07-10 13:51:36 -0700109 bool no_values_ = false;
Ryan Mitchell214846d2018-09-19 16:57:01 -0700110 bool verbose_ = false;
Ryan Mitchell833a1a62018-07-10 13:51:36 -0700111};
112
Ryan Mitchell214846d2018-09-19 16:57:01 -0700113/** Easter egg command shown when users enter "badger" instead of "badging". */
114class DumpBadgerCommand : public Command {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700115 public:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700116 explicit DumpBadgerCommand(text::Printer* printer) : Command("badger"), printer_(printer) {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700117 }
118
119 int Action(const std::vector<std::string>& args) override;
120
121 private:
Ryan Mitchell214846d2018-09-19 16:57:01 -0700122 text::Printer* printer_;
123 const static char kBadgerData[2925];
Ryan Mitchell5d275512018-07-19 14:29:00 -0700124};
125
Ryan Mitchell214846d2018-09-19 16:57:01 -0700126class DumpBadgingCommand : public DumpApkCommand {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700127 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000128 explicit DumpBadgingCommand(text::Printer* printer, android::IDiagnostics* diag)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700129 : DumpApkCommand("badging", printer, diag) {
130 SetDescription("Print information extracted from the manifest of the APK.");
131 AddOptionalSwitch("--include-meta-data", "Include meta-data information.",
132 &options_.include_meta_data);
133 }
134
Iurii Makhnodcead622022-04-13 18:00:03 +0000135 void SetIncludeMetaData(bool value) {
136 options_.include_meta_data = value;
137 }
138
139 void SetOnlyPermissions(bool value) {
140 options_.only_permissions = value;
141 }
142
Ryan Mitchell214846d2018-09-19 16:57:01 -0700143 int Dump(LoadedApk* apk) override {
144 return DumpManifest(apk, options_, GetPrinter(), GetDiagnostics());
145 }
146
147 private:
148 DumpManifestOptions options_;
149};
150
151class DumpConfigsCommand : public DumpApkCommand {
152 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000153 explicit DumpConfigsCommand(text::Printer* printer, android::IDiagnostics* diag)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700154 : DumpApkCommand("configurations", printer, diag) {
155 SetDescription("Print every configuration used by a resource in the APK.");
156 }
157
158 int Dump(LoadedApk* apk) override;
159};
160
161class DumpPackageNameCommand : public DumpApkCommand {
162 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000163 explicit DumpPackageNameCommand(text::Printer* printer, android::IDiagnostics* diag)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700164 : DumpApkCommand("packagename", printer, diag) {
165 SetDescription("Print the package name of the APK.");
166 }
167
168 int Dump(LoadedApk* apk) override;
169};
170
171class DumpPermissionsCommand : public DumpApkCommand {
172 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000173 explicit DumpPermissionsCommand(text::Printer* printer, android::IDiagnostics* diag)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700174 : DumpApkCommand("permissions", printer, diag) {
175 SetDescription("Print the permissions extracted from the manifest of the APK.");
176 }
177
178 int Dump(LoadedApk* apk) override {
179 DumpManifestOptions options;
180 options.only_permissions = true;
181 return DumpManifest(apk, options, GetPrinter(), GetDiagnostics());
182 }
183};
184
185class DumpStringsCommand : public DumpApkCommand {
186 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000187 explicit DumpStringsCommand(text::Printer* printer, android::IDiagnostics* diag)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700188 : DumpApkCommand("strings", printer, diag) {
189 SetDescription("Print the contents of the resource table string pool in the APK.");
190 }
191
192 int Dump(LoadedApk* apk) override;
193};
194
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -0700195/** Prints the graph of parents of a style in an APK. */
196class DumpStyleParentCommand : public DumpApkCommand {
197 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000198 explicit DumpStyleParentCommand(text::Printer* printer, android::IDiagnostics* diag)
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -0700199 : DumpApkCommand("styleparents", printer, diag) {
200 SetDescription("Print the parents of a style in an APK.");
201 AddRequiredFlag("--style", "The name of the style to print", &style_);
202 }
203
204 int Dump(LoadedApk* apk) override;
205
206 private:
207 std::string style_;
208};
209
Ryan Mitchell214846d2018-09-19 16:57:01 -0700210class DumpTableCommand : public DumpApkCommand {
211 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000212 explicit DumpTableCommand(text::Printer* printer, android::IDiagnostics* diag)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700213 : DumpApkCommand("resources", printer, diag) {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700214 SetDescription("Print the contents of the resource table from the APK.");
215 AddOptionalSwitch("--no-values", "Suppresses output of values when displaying resource tables.",
216 &no_values_);
217 AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
218 }
219
Ryan Mitchell214846d2018-09-19 16:57:01 -0700220 int Dump(LoadedApk* apk) override;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700221
222 private:
Ryan Mitchell5d275512018-07-19 14:29:00 -0700223 bool no_values_ = false;
Ryan Mitchell214846d2018-09-19 16:57:01 -0700224 bool verbose_ = false;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700225};
226
Ryan Mitchell214846d2018-09-19 16:57:01 -0700227class DumpXmlStringsCommand : public DumpApkCommand {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700228 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000229 explicit DumpXmlStringsCommand(text::Printer* printer, android::IDiagnostics* diag)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700230 : DumpApkCommand("xmlstrings", printer, diag) {
231 SetDescription("Print the string pool of a compiled xml in an APK.");
232 AddRequiredFlagList("--file", "A compiled xml file to print", &files_);
233 }
234
235 int Dump(LoadedApk* apk) override;
236
237 private:
238 std::vector<std::string> files_;
239};
240
Ryan Mitchell19b27092018-08-13 11:36:27 -0700241class DumpChunks : public DumpApkCommand {
242 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000243 DumpChunks(text::Printer* printer, android::IDiagnostics* diag)
244 : DumpApkCommand("chunks", printer, diag) {
Ryan Mitchell19b27092018-08-13 11:36:27 -0700245 SetDescription("Print the chunk information of the compiled resources.arsc in the APK.");
246 }
247
248 int Dump(LoadedApk* apk) override;
249};
250
251/** Prints the tree of a compiled xml in an APK. */
Ryan Mitchell214846d2018-09-19 16:57:01 -0700252class DumpXmlTreeCommand : public DumpApkCommand {
253 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000254 explicit DumpXmlTreeCommand(text::Printer* printer, android::IDiagnostics* diag)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700255 : DumpApkCommand("xmltree", printer, diag) {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700256 SetDescription("Print the tree of a compiled xml in an APK.");
257 AddRequiredFlagList("--file", "A compiled xml file to print", &files_);
258 }
259
Ryan Mitchell214846d2018-09-19 16:57:01 -0700260 int Dump(LoadedApk* apk) override;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700261
262 private:
Ryan Mitchell5d275512018-07-19 14:29:00 -0700263 std::vector<std::string> files_;
264};
265
Mårten Kongstad1d3b64852019-09-17 13:02:32 +0200266class DumpOverlayableCommand : public DumpApkCommand {
267 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000268 explicit DumpOverlayableCommand(text::Printer* printer, android::IDiagnostics* diag)
Mårten Kongstad1d3b64852019-09-17 13:02:32 +0200269 : DumpApkCommand("overlayable", printer, diag) {
270 SetDescription("Print the <overlayable> resources of an APK.");
271 }
272
273 int Dump(LoadedApk* apk) override;
274};
275
Todd Kennedy908b7fc2018-08-24 10:11:21 -0700276/** The default dump command. Performs no action because a subcommand is required. */
Ryan Mitchell5d275512018-07-19 14:29:00 -0700277class DumpCommand : public Command {
278 public:
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000279 explicit DumpCommand(text::Printer* printer, android::IDiagnostics* diag)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700280 : Command("dump", "d"), diag_(diag) {
281 AddOptionalSubcommand(util::make_unique<DumpAPCCommand>(printer, diag_));
282 AddOptionalSubcommand(util::make_unique<DumpBadgingCommand>(printer, diag_));
283 AddOptionalSubcommand(util::make_unique<DumpConfigsCommand>(printer, diag_));
284 AddOptionalSubcommand(util::make_unique<DumpPackageNameCommand>(printer, diag_));
285 AddOptionalSubcommand(util::make_unique<DumpPermissionsCommand>(printer, diag_));
286 AddOptionalSubcommand(util::make_unique<DumpStringsCommand>(printer, diag_));
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -0700287 AddOptionalSubcommand(util::make_unique<DumpStyleParentCommand>(printer, diag_));
Ryan Mitchell214846d2018-09-19 16:57:01 -0700288 AddOptionalSubcommand(util::make_unique<DumpTableCommand>(printer, diag_));
Ryan Mitchell19b27092018-08-13 11:36:27 -0700289 AddOptionalSubcommand(util::make_unique<DumpChunks>(printer, diag_));
Ryan Mitchell214846d2018-09-19 16:57:01 -0700290 AddOptionalSubcommand(util::make_unique<DumpXmlStringsCommand>(printer, diag_));
291 AddOptionalSubcommand(util::make_unique<DumpXmlTreeCommand>(printer, diag_));
Mårten Kongstad1d3b64852019-09-17 13:02:32 +0200292 AddOptionalSubcommand(util::make_unique<DumpOverlayableCommand>(printer, diag_));
Ryan Mitchell214846d2018-09-19 16:57:01 -0700293 AddOptionalSubcommand(util::make_unique<DumpBadgerCommand>(printer), /* hidden */ true);
Ryan Mitchell5d275512018-07-19 14:29:00 -0700294 }
295
Ryan Mitchell214846d2018-09-19 16:57:01 -0700296 int Action(const std::vector<std::string>& args) override {
297 if (args.size() == 0) {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000298 diag_->Error(android::DiagMessage() << "no subcommand specified");
Ryan Mitchell214846d2018-09-19 16:57:01 -0700299 } else {
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000300 diag_->Error(android::DiagMessage() << "unknown subcommand '" << args[0] << "'");
Ryan Mitchell214846d2018-09-19 16:57:01 -0700301 }
302 Usage(&std::cerr);
303 return 1;
304 }
Ryan Mitchell5d275512018-07-19 14:29:00 -0700305
306 private:
Jeremy Meyer56f36e82022-05-20 20:35:42 +0000307 android::IDiagnostics* diag_;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700308};
309
Ryan Mitchell214846d2018-09-19 16:57:01 -0700310} // namespace aapt
Ryan Mitchell833a1a62018-07-10 13:51:36 -0700311
Ryan Mitchell214846d2018-09-19 16:57:01 -0700312#endif // AAPT2_DUMP_H