Add style parents dump command.

This command prints out the parent graph of a given style

Test: out/host/linux-x86/bin/aapt2 dump styleparents \
    --style Widget.MaterialComponents.TextInputLayout.FilledBox \
    out/target/product/generic_x86/system/priv-app/SystemUIGoogle/SystemUIGoogle.apk
Change-Id: Ib2ace7e90bee6f1c4b6a184edc591b1a3993db75
diff --git a/tools/aapt2/cmd/Dump.cpp b/tools/aapt2/cmd/Dump.cpp
index 06e4622..a23a6a4 100644
--- a/tools/aapt2/cmd/Dump.cpp
+++ b/tools/aapt2/cmd/Dump.cpp
@@ -251,19 +251,12 @@
 }
 
 int DumpPackageNameCommand::Dump(LoadedApk* apk) {
-  xml::Element* manifest_el = apk->GetManifest()->root.get();
-  if (!manifest_el) {
-    GetDiagnostics()->Error(DiagMessage() << "No AndroidManifest");
+  Maybe<std::string> package_name = GetPackageName(apk);
+  if (!package_name) {
     return 1;
   }
 
-  xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
-  if (!attr) {
-    GetDiagnostics()->Error(DiagMessage() << "No package name");
-    return 1;
-  }
-
-  GetPrinter()->Println(StringPrintf("%s", attr->value.c_str()));
+  GetPrinter()->Println(package_name.value());
   return 0;
 }
 
@@ -283,6 +276,31 @@
   return 0;
 }
 
+int DumpStyleParentCommand::Dump(LoadedApk* apk) {
+  Maybe<std::string> package_name = GetPackageName(apk);
+  if (!package_name) {
+    return 1;
+  }
+
+  const auto target_style = ResourceName(package_name.value(), ResourceType::kStyle, style_);
+  const auto table = apk->GetResourceTable();
+
+  if (!table) {
+    GetDiagnostics()->Error(DiagMessage() << "Failed to retrieve resource table");
+    return 1;
+  }
+
+  Maybe<ResourceTable::SearchResult> target = table->FindResource(target_style);
+  if (!target) {
+    GetDiagnostics()->Error(
+        DiagMessage() << "Target style \"" << target_style.entry << "\" does not exist");
+    return 1;
+  }
+
+  Debug::PrintStyleGraph(table, target_style);
+  return 0;
+}
+
 int DumpTableCommand::Dump(LoadedApk* apk) {
   if (apk->GetApkFormat() == ApkFormat::kProto) {
     GetPrinter()->Println("Proto APK");
diff --git a/tools/aapt2/cmd/Dump.h b/tools/aapt2/cmd/Dump.h
index cd215b0..89d19cf 100644
--- a/tools/aapt2/cmd/Dump.h
+++ b/tools/aapt2/cmd/Dump.h
@@ -42,6 +42,21 @@
     return diag_;
   }
 
+  Maybe<std::string> GetPackageName(LoadedApk* apk) {
+    xml::Element* manifest_el = apk->GetManifest()->root.get();
+    if (!manifest_el) {
+      GetDiagnostics()->Error(DiagMessage() << "No AndroidManifest.");
+      return Maybe<std::string>();
+    }
+
+    xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
+    if (!attr) {
+      GetDiagnostics()->Error(DiagMessage() << "No package name.");
+      return Maybe<std::string>();
+    }
+    return attr->value;
+  }
+
   /** Perform the dump operation on the apk. */
   virtual int Dump(LoadedApk* apk) = 0;
 
@@ -164,6 +179,21 @@
   int Dump(LoadedApk* apk) override;
 };
 
+/** Prints the graph of parents of a style in an APK. */
+class DumpStyleParentCommand : public DumpApkCommand {
+ public:
+  explicit DumpStyleParentCommand(text::Printer* printer, IDiagnostics* diag)
+      : DumpApkCommand("styleparents", printer, diag) {
+    SetDescription("Print the parents of a style in an APK.");
+    AddRequiredFlag("--style", "The name of the style to print", &style_);
+  }
+
+  int Dump(LoadedApk* apk) override;
+
+ private:
+  std::string style_;
+};
+
 class DumpTableCommand : public DumpApkCommand {
  public:
   explicit DumpTableCommand(text::Printer* printer, IDiagnostics* diag)
@@ -220,6 +250,7 @@
     AddOptionalSubcommand(util::make_unique<DumpPackageNameCommand>(printer, diag_));
     AddOptionalSubcommand(util::make_unique<DumpPermissionsCommand>(printer, diag_));
     AddOptionalSubcommand(util::make_unique<DumpStringsCommand>(printer, diag_));
+    AddOptionalSubcommand(util::make_unique<DumpStyleParentCommand>(printer, diag_));
     AddOptionalSubcommand(util::make_unique<DumpTableCommand>(printer, diag_));
     AddOptionalSubcommand(util::make_unique<DumpXmlStringsCommand>(printer, diag_));
     AddOptionalSubcommand(util::make_unique<DumpXmlTreeCommand>(printer, diag_));