Add read/write for List<ParcelFileDescriptor> in Java

While ParcelableFileDescriptor is built-in type, it IS a parcelable. So
we can treat it just like defined parcelable types when reading/writing.

Bug: 171229850
Test: aidl_unittests / aidl_integration_test
Change-Id: I2fac70a80a39ce0ccae5c91b09e4d331333ec758
diff --git a/aidl_to_java.cpp b/aidl_to_java.cpp
index c5d3f97..9fa691a 100644
--- a/aidl_to_java.cpp
+++ b/aidl_to_java.cpp
@@ -264,18 +264,14 @@
        [](const CodeGeneratorContext& c) {
          if (c.type.IsGeneric()) {
            const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
-           if (AidlTypenames::IsBuiltinTypename(contained_type)) {
-             if (contained_type == "String") {
-               c.writer << c.parcel << ".writeStringList(" << c.var << ");\n";
-             } else if (contained_type == "IBinder") {
-               c.writer << c.parcel << ".writeBinderList(" << c.var << ");\n";
-             }
+           if (contained_type == "String") {
+             c.writer << c.parcel << ".writeStringList(" << c.var << ");\n";
+           } else if (contained_type == "IBinder") {
+             c.writer << c.parcel << ".writeBinderList(" << c.var << ");\n";
+           } else if (c.typenames.IsParcelable(contained_type)) {
+             c.writer << c.parcel << ".writeTypedList(" << c.var << ");\n";
            } else {
-             const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
-             AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << contained_type;
-             if (t->AsParcelable() != nullptr) {
-               c.writer << c.parcel << ".writeTypedList(" << c.var << ");\n";
-             }
+             AIDL_FATAL(c.type) << "write: NOT IMPLEMENTED for " << contained_type;
            }
          } else {
            c.writer << c.parcel << ".writeList(" << c.var << ");\n";
@@ -492,20 +488,16 @@
        [](const CodeGeneratorContext& c) {
          if (c.type.IsGeneric()) {
            const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
-           if (AidlTypenames::IsBuiltinTypename(contained_type)) {
-             if (contained_type == "String") {
-               c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
-             } else if (contained_type == "IBinder") {
-               c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
-             }
+           if (contained_type == "String") {
+             c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
+           } else if (contained_type == "IBinder") {
+             c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
+           } else if (c.typenames.IsParcelable(contained_type)) {
+             c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
+                      << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
+                      << ".CREATOR);\n";
            } else {
-             const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
-             AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << contained_type;
-             if (t->AsParcelable() != nullptr) {
-               c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
-                        << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
-                        << ".CREATOR);\n";
-             }
+             AIDL_FATAL(c.type) << "create: NOT IMPLEMENTED for " << contained_type;
            }
          } else {
            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
@@ -682,20 +674,16 @@
        [](const CodeGeneratorContext& c) {
          if (c.type.IsGeneric()) {
            const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
-           if (AidlTypenames::IsBuiltinTypename(contained_type)) {
-             if (contained_type == "String") {
-               c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
-             } else if (contained_type == "IBinder") {
-               c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
-             }
+           if (contained_type == "String") {
+             c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
+           } else if (contained_type == "IBinder") {
+             c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
+           } else if (c.typenames.IsParcelable(contained_type)) {
+             c.writer << c.parcel << ".readTypedList(" << c.var << ", "
+                      << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
+                      << ".CREATOR);\n";
            } else {
-             const AidlDefinedType* t = c.typenames.TryGetDefinedType(contained_type);
-             AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << contained_type;
-             if (t->AsParcelable() != nullptr) {
-               c.writer << c.parcel << ".readTypedList(" << c.var << ", "
-                        << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
-                        << ".CREATOR);\n";
-             }
+             AIDL_FATAL(c.type) << "read: NOT IMPLEMENTED for " << contained_type;
            }
          } else {
            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
diff --git a/aidl_typenames.cpp b/aidl_typenames.cpp
index 16afbf6..acad42f 100644
--- a/aidl_typenames.cpp
+++ b/aidl_typenames.cpp
@@ -157,6 +157,16 @@
   return kPrimitiveTypes.find(type_name) != kPrimitiveTypes.end();
 }
 
+bool AidlTypenames::IsParcelable(const string& type_name) const {
+  if (IsBuiltinTypename(type_name)) {
+    return type_name == "ParcelableHolder" || type_name == "ParcelFileDescriptor";
+  }
+  if (auto defined_type = TryGetDefinedType(type_name); defined_type) {
+    return defined_type->AsParcelable() != nullptr;
+  }
+  return false;
+}
+
 const AidlDefinedType* AidlTypenames::TryGetDefinedType(const string& type_name) const {
   return TryGetDefinedTypeImpl(type_name).type;
 }
diff --git a/aidl_typenames.h b/aidl_typenames.h
index 7ae3690..ca41009 100644
--- a/aidl_typenames.h
+++ b/aidl_typenames.h
@@ -60,6 +60,7 @@
   bool AddPreprocessedType(unique_ptr<AidlDefinedType> type);
   static bool IsBuiltinTypename(const string& type_name);
   static bool IsPrimitiveTypename(const string& type_name);
+  bool IsParcelable(const string& type_name) const;
   const AidlDefinedType* TryGetDefinedType(const string& type_name) const;
   std::vector<AidlDefinedType*> AllDefinedTypes() const;
 
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 16356ae..60f99ef 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -120,6 +120,7 @@
     else {
       _aidl_parcel.writeInt(0);
     }
+    _aidl_parcel.writeTypedList(fds);
     int _aidl_end_pos = _aidl_parcel.dataPosition();
     _aidl_parcel.setDataPosition(_aidl_start_pos);
     _aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);
@@ -142,6 +143,7 @@
         fd = null;
       }
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      fds = _aidl_parcel.createTypedArrayList(android.os.ParcelFileDescriptor.CREATOR);
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
     } finally {
       if (_aidl_start_pos > (Integer.MAX_VALUE - _aidl_parcelable_size)) {