dumpapi dumps generic type parameters

dumpapi should dump generic type parameters as well.

Bug: n/a
Test: aidl_unittests
Change-Id: I2d880dc095a91ef580caaa218f78775648992d5a
diff --git a/aidl_dumpapi.cpp b/aidl_dumpapi.cpp
index 6c7ef78..c121f9f 100644
--- a/aidl_dumpapi.cpp
+++ b/aidl_dumpapi.cpp
@@ -34,7 +34,11 @@
 void DumpVisitor::DumpType(const AidlDefinedType& dt, const string& type) {
   DumpComments(dt);
   DumpAnnotations(dt);
-  out << type << " " << dt.GetName() << " {\n";
+  out << type << " " << dt.GetName();
+  if (auto generic_type = dt.AsParameterizable(); generic_type && generic_type->IsGeneric()) {
+    out << "<" << Join(generic_type->GetTypeParameters(), ", ") << ">";
+  }
+  out << " {\n";
   out.Indent();
   DumpMembers(dt);
   out.Dedent();
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 66df51e..196e396 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -1685,6 +1685,25 @@
             actual);
 }
 
+TEST_F(AidlTest, ApiDumpWithGenerics) {
+  io_delegate_.SetFileContents("foo/bar/Foo.aidl",
+                               "package foo.bar;\n"
+                               "parcelable Foo<T, U> {\n"
+                               "}\n");
+
+  vector<string> args = {"aidl", "--dumpapi", "-I . ", "-o dump", "foo/bar/Foo.aidl"};
+  Options options = Options::From(args);
+  CaptureStderr();
+  EXPECT_TRUE(dump_api(options, io_delegate_));
+  EXPECT_EQ("", GetCapturedStderr());
+  string actual;
+  EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/Foo.aidl", &actual));
+  EXPECT_EQ(string(kPreamble).append("package foo.bar;\n"
+                                     "parcelable Foo<T, U> {\n"
+                                     "}\n"),
+            actual);
+}
+
 TEST_F(AidlTest, CheckNumGenericTypeSecifier) {
   const string expected_list_stderr =
       "ERROR: p/IFoo.aidl:1.37-41: List can only have one type parameter, but got: "