Support array of interface

Interfaces can be an array.

  interface IFoo {}
  IFoo[] getFooArray();

aidl_integration_test will be updated in a follow-up change.

Bug: 151817759
Test: gold_test.sh update
Test: aidl_integration_test / aidl_unittests
  (this ensures the compiler generates compilable code & no regression)
Change-Id: Ice770f2b4e7feab2b8a900cb5fb4ad64cfa91231
diff --git a/Android.bp b/Android.bp
index d4b997d..d22a39e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -277,6 +277,7 @@
 filegroup {
     name: "libaidl-integration-test-files",
     srcs: [
+        "tests/android/aidl/tests/ArrayOfInterfaces.aidl",
         "tests/android/aidl/tests/BackendType.aidl",
         "tests/android/aidl/tests/ByteEnum.aidl",
         "tests/android/aidl/tests/ConstantExpressionEnum.aidl",
diff --git a/aidl_language.cpp b/aidl_language.cpp
index 25a1bdb..3d66a95 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -694,11 +694,6 @@
   }
 
   if (IsArray()) {
-    const auto defined_type = typenames.TryGetDefinedType(GetName());
-    if (defined_type != nullptr && defined_type->AsInterface() != nullptr) {
-      AIDL_ERROR(this) << "Binder type cannot be an array";
-      return false;
-    }
     if (GetName() == "ParcelableHolder" || GetName() == "List" || GetName() == "Map" ||
         GetName() == "CharSequence") {
       AIDL_ERROR(this) << "Arrays of " << GetName() << " are not supported.";
diff --git a/aidl_to_cpp.cpp b/aidl_to_cpp.cpp
index 06abf6c..605707b 100644
--- a/aidl_to_cpp.cpp
+++ b/aidl_to_cpp.cpp
@@ -279,11 +279,6 @@
                         CppNameOf(enum_decl->GetBackingType(), typenames).c_str(),
                         variable_name.c_str());
   }
-
-  if (typenames.GetInterface(type) != nullptr) {
-    return GetRawCppName(type) + "::asBinder(" + variable_name + ")";
-  }
-
   return variable_name;
 }
 
diff --git a/aidl_to_java.cpp b/aidl_to_java.cpp
index 200b99f..d2bf5a2 100644
--- a/aidl_to_java.cpp
+++ b/aidl_to_java.cpp
@@ -384,7 +384,25 @@
     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
     AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
     if (t->AsInterface() != nullptr) {
-      if (!c.type.IsArray()) {
+      if (c.type.IsArray()) {
+        c.writer << "{\n";
+        c.writer.Indent();
+        c.writer << "android.os.IBinder[] _binder_arr = null;\n";
+        c.writer << "if (" << c.var << " != null) {\n";
+        c.writer.Indent();
+        c.writer << "_binder_arr = new android.os.IBinder[" << c.var << ".length];\n";
+        c.writer << "for (int i = 0; i < " << c.var << ".length; i++) {\n";
+        c.writer.Indent();
+        c.writer << "_binder_arr[i] = (" << c.var << "[i] != null) ? " << c.var
+                 << "[i].asBinder() : null;\n";
+        c.writer.Dedent();
+        c.writer << "}\n";
+        c.writer.Dedent();
+        c.writer << "}\n";
+        c.writer << c.parcel << ".writeBinderArray(_binder_arr);\n";
+        c.writer.Dedent();
+        c.writer << "}\n";
+      } else {
         // Why don't we use writeStrongInterface which does the exact same thing?
         // Keeping below code just not to break unit tests.
         c.writer << c.parcel << ".writeStrongBinder((((" << c.var << "!=null))?"
@@ -615,8 +633,29 @@
     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
     AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
     if (t->AsInterface() != nullptr) {
-      if (!c.type.IsArray()) {
-        c.writer << c.var << " = " << c.type.GetName() << ".Stub.asInterface(" << c.parcel
+      auto name = c.type.GetName();
+      if (c.type.IsArray()) {
+        c.writer << "{\n";
+        c.writer.Indent();
+        c.writer << "android.os.IBinder[] _binder_arr = " << c.parcel << ".createBinderArray();\n";
+        c.writer << "if (_binder_arr != null) {\n";
+        c.writer.Indent();
+        c.writer << c.var << " = new " << name << "[_binder_arr.length];\n";
+        c.writer << "for (int i = 0; i < _binder_arr.length; i++) {\n";
+        c.writer.Indent();
+        c.writer << c.var << "[i] = " << name << ".Stub.asInterface(_binder_arr[i]);\n";
+        c.writer.Dedent();
+        c.writer << "}\n";
+        c.writer.Dedent();
+        c.writer << "} else {\n";
+        c.writer.Indent();
+        c.writer << c.var << " = null;\n";
+        c.writer.Dedent();
+        c.writer << "}\n";
+        c.writer.Dedent();
+        c.writer << "}\n";
+      } else {
+        c.writer << c.var << " = " << name << ".Stub.asInterface(" << c.parcel
                  << ".readStrongBinder());\n";
       }
     } else if (t->AsParcelable() != nullptr) {
@@ -765,6 +804,21 @@
         c.writer.Dedent();
         c.writer << "}\n";
       }
+    } else if (t->AsInterface()) {
+      AIDL_FATAL_IF(!c.type.IsArray(), c.type) << "readFromParcel(interface) doesn't make sense.";
+      auto name = c.type.GetName();
+      c.writer << "{\n";
+      c.writer.Indent();
+      c.writer << "android.os.IBinder[] _binder_arr = new android.os.IBinder[" << c.var
+               << ".length];\n";
+      c.writer << c.parcel << ".readBinderArray(_binder_arr);\n";
+      c.writer << "for (int i = 0; i < _binder_arr.length; i++) {\n";
+      c.writer.Indent();
+      c.writer << c.var << "[i] = " << name << ".Stub.asInterface(_binder_arr[i]);\n";
+      c.writer.Dedent();
+      c.writer << "}\n";
+      c.writer.Dedent();
+      c.writer << "}\n";
     }
   }
   return true;
diff --git a/aidl_to_ndk.cpp b/aidl_to_ndk.cpp
index b8e8d12..1fc4718 100644
--- a/aidl_to_ndk.cpp
+++ b/aidl_to_ndk.cpp
@@ -138,14 +138,24 @@
               .read_func = StandardRead(clazz + "::readFromParcel"),
               .write_func = StandardWrite(clazz + "::writeToParcel"),
           },
-      .array = nullptr,
+      .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
+          .cpp_name = "std::vector<std::shared_ptr<" + clazz + ">>",
+          .value_is_cheap = false,
+          .read_func = StandardRead("::ndk::AParcel_readVector"),
+          .write_func = StandardWrite("::ndk::AParcel_writeVector"),
+      }),
       .nullable = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
           .cpp_name = "std::shared_ptr<" + clazz + ">",
           .value_is_cheap = false,
           .read_func = StandardRead(clazz + "::readFromParcel"),
           .write_func = StandardWrite(clazz + "::writeToParcel"),
       }),
-      .nullable_array = nullptr,
+      .nullable_array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
+          .cpp_name = "std::optional<std::vector<std::shared_ptr<" + clazz + ">>>",
+          .value_is_cheap = false,
+          .read_func = StandardRead("::ndk::AParcel_readVector"),
+          .write_func = StandardWrite("::ndk::AParcel_writeVector"),
+      }),
   };
 }
 
diff --git a/aidl_to_rust.cpp b/aidl_to_rust.cpp
index 283b820..236dcc4 100644
--- a/aidl_to_rust.cpp
+++ b/aidl_to_rust.cpp
@@ -127,11 +127,16 @@
     }
     return m[element_type_name];
   }
+  auto name = GetRawRustName(element_type);
   if (TypeIsInterface(element_type, typenames)) {
-    return "binder::Strong<dyn " + GetRawRustName(element_type) + ">";
+    name = "binder::Strong<dyn " + name + ">";
+    if (is_vector && mode == StorageMode::DEFAULT_VALUE) {
+      // Out-arguments of interface arrays need to be Vec<Option<...>> so resize_out_vec
+      // can initialize all elements to None.
+      name = "Option<" + name + ">";
+    }
   }
-
-  return GetRawRustName(element_type);
+  return name;
 }
 }  // namespace
 
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index cb5fa3d..4d961f8 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -186,21 +186,6 @@
   EXPECT_EQ(expected_stderr, GetCapturedStderr()) << file_contents;
 }
 
-TEST_P(AidlTest, RejectsArraysOfBinders) {
-  import_paths_.emplace("");
-  io_delegate_.SetFileContents("bar/IBar.aidl",
-                               "package bar; interface IBar {}");
-  const string path = "foo/IFoo.aidl";
-  const string contents =
-      "package foo;\n"
-      "import bar.IBar;\n"
-      "interface IFoo { void f(in IBar[] input); }";
-  const string expected_stderr = "ERROR: foo/IFoo.aidl:3.27-32: Binder type cannot be an array\n";
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse(path, contents, typenames_, GetLanguage()));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
-}
-
 TEST_P(AidlTest, SupportOnlyOutParameters) {
   const string interface_list = "package a; interface IBar { void f(out List<String> bar); }";
   EXPECT_NE(nullptr, Parse("a/IBar.aidl", interface_list, typenames_, GetLanguage()));
@@ -4896,10 +4881,10 @@
     {"java_ParcelFileDescriptor", {"", ""}},
     {"ndk_ParcelFileDescriptor", {"", ""}},
     {"rust_ParcelFileDescriptor", {"", ""}},
-    {"cpp_interface", {"Binder type cannot be an array", "Binder type cannot be an array"}},
-    {"java_interface", {"Binder type cannot be an array", "Binder type cannot be an array"}},
-    {"ndk_interface", {"Binder type cannot be an array", "Binder type cannot be an array"}},
-    {"rust_interface", {"Binder type cannot be an array", "Binder type cannot be an array"}},
+    {"cpp_interface", {"", ""}},
+    {"java_interface", {"", ""}},
+    {"ndk_interface", {"", ""}},
+    {"rust_interface", {"", ""}},
     {"cpp_parcelable", {"", ""}},
     {"java_parcelable", {"", ""}},
     {"ndk_parcelable", {"", ""}},
diff --git a/tests/android/aidl/tests/ArrayOfInterfaces.aidl b/tests/android/aidl/tests/ArrayOfInterfaces.aidl
new file mode 100644
index 0000000..c95db2a
--- /dev/null
+++ b/tests/android/aidl/tests/ArrayOfInterfaces.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.aidl.tests;
+
+@SuppressWarnings(value={"inout-parameter", "out-array"})
+parcelable ArrayOfInterfaces {
+    interface IEmptyInterface {}
+
+    interface IMyInterface {
+        @nullable IEmptyInterface[] methodWithInterfaces(IEmptyInterface iface,
+                @nullable IEmptyInterface nullable_iface,
+                in IEmptyInterface[] iface_array_in, out IEmptyInterface[] iface_array_out,
+                inout IEmptyInterface[] iface_array_inout,
+                in @nullable IEmptyInterface[] nullable_iface_array_in,
+                out @nullable IEmptyInterface[] nullable_iface_array_out,
+                inout @nullable IEmptyInterface[] nullable_iface_array_inout);
+    }
+
+    @JavaDerive(toString=true, equals=true)
+    parcelable MyParcelable {
+        IEmptyInterface iface;
+        @nullable IEmptyInterface nullable_iface;
+        IEmptyInterface[] iface_array;
+        @nullable IEmptyInterface[] nullable_iface_array;
+    }
+
+    @JavaDerive(toString=true, equals=true)
+    union MyUnion {
+        IEmptyInterface iface;
+        @nullable IEmptyInterface nullable_iface;
+        IEmptyInterface[] iface_array;
+        @nullable IEmptyInterface[] nullable_iface_array;
+    }
+}
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp
new file mode 100644
index 0000000..2116483
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp
@@ -0,0 +1,441 @@
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t ArrayOfInterfaces::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  [[maybe_unused]] size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = _aidl_parcel->readInt32();
+  if (_aidl_parcelable_raw_size < 0) return ::android::BAD_VALUE;
+  [[maybe_unused]] size_t _aidl_parcelable_size = static_cast<size_t>(_aidl_parcelable_raw_size);
+  if (_aidl_start_pos > SIZE_MAX - _aidl_parcelable_size) return ::android::BAD_VALUE;
+  _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+  return _aidl_ret_status;
+}
+::android::status_t ArrayOfInterfaces::writeToParcel(::android::Parcel* _aidl_parcel) const {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  auto _aidl_start_pos = _aidl_parcel->dataPosition();
+  _aidl_parcel->writeInt32(0);
+  auto _aidl_end_pos = _aidl_parcel->dataPosition();
+  _aidl_parcel->setDataPosition(_aidl_start_pos);
+  _aidl_parcel->writeInt32(_aidl_end_pos - _aidl_start_pos);
+  _aidl_parcel->setDataPosition(_aidl_end_pos);
+  return _aidl_ret_status;
+}
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+namespace android {
+namespace aidl {
+namespace tests {
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE(ArrayOfInterfaces, EmptyInterface, "android.aidl.tests.ArrayOfInterfaces.IEmptyInterface")
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+#include <binder/Parcel.h>
+#include <android-base/macros.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+
+ArrayOfInterfaces::BpEmptyInterface::BpEmptyInterface(const ::android::sp<::android::IBinder>& _aidl_impl)
+    : BpInterface<IEmptyInterface>(_aidl_impl){
+}
+
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+
+ArrayOfInterfaces::BnEmptyInterface::BnEmptyInterface()
+{
+  ::android::internal::Stability::markCompilationUnit(this);
+}
+
+::android::status_t ArrayOfInterfaces::BnEmptyInterface::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  switch (_aidl_code) {
+  default:
+  {
+    _aidl_ret_status = ::android::BBinder::onTransact(_aidl_code, _aidl_data, _aidl_reply, _aidl_flags);
+  }
+  break;
+  }
+  if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
+    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeToParcel(_aidl_reply);
+  }
+  return _aidl_ret_status;
+}
+
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+namespace android {
+namespace aidl {
+namespace tests {
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE(ArrayOfInterfaces, MyInterface, "android.aidl.tests.ArrayOfInterfaces.IMyInterface")
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+#include <binder/Parcel.h>
+#include <android-base/macros.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+
+ArrayOfInterfaces::BpMyInterface::BpMyInterface(const ::android::sp<::android::IBinder>& _aidl_impl)
+    : BpInterface<IMyInterface>(_aidl_impl){
+}
+
+::android::binder::Status ArrayOfInterfaces::BpMyInterface::methodWithInterfaces(const ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& iface, const ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& nullable_iface, const ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>& iface_array_in, ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* iface_array_out, ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* iface_array_inout, const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>& nullable_iface_array_in, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* nullable_iface_array_out, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* nullable_iface_array_inout, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* _aidl_return) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markForBinder(remoteStrong());
+  ::android::Parcel _aidl_reply;
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  ::android::binder::Status _aidl_status;
+  _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeStrongBinder(iface);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeStrongBinder(nullable_iface);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeStrongBinderVector(iface_array_in);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeVectorSize(*iface_array_out);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeStrongBinderVector(*iface_array_inout);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeStrongBinderVector(nullable_iface_array_in);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeVectorSize(*nullable_iface_array_out);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeStrongBinderVector(*nullable_iface_array_inout);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(ArrayOfInterfaces::BnMyInterface::TRANSACTION_methodWithInterfaces, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IMyInterface::getDefaultImpl())) {
+     return IMyInterface::getDefaultImpl()->methodWithInterfaces(iface, nullable_iface, iface_array_in, iface_array_out, iface_array_inout, nullable_iface_array_in, nullable_iface_array_out, nullable_iface_array_inout, _aidl_return);
+  }
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  if (!_aidl_status.isOk()) {
+    return _aidl_status;
+  }
+  _aidl_ret_status = _aidl_reply.readStrongBinderVector(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readStrongBinderVector(iface_array_out);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readStrongBinderVector(iface_array_inout);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readStrongBinderVector(nullable_iface_array_out);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readStrongBinderVector(nullable_iface_array_inout);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+
+ArrayOfInterfaces::BnMyInterface::BnMyInterface()
+{
+  ::android::internal::Stability::markCompilationUnit(this);
+}
+
+::android::status_t ArrayOfInterfaces::BnMyInterface::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  switch (_aidl_code) {
+  case BnMyInterface::TRANSACTION_methodWithInterfaces:
+  {
+    ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface> in_iface;
+    ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface> in_nullable_iface;
+    ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>> in_iface_array_in;
+    ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>> out_iface_array_out;
+    ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>> in_iface_array_inout;
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>> in_nullable_iface_array_in;
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>> out_nullable_iface_array_out;
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>> in_nullable_iface_array_inout;
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinder(&in_iface);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readNullableStrongBinder(&in_nullable_iface);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_iface_array_in);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.resizeOutVector(&out_iface_array_out);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_iface_array_inout);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_nullable_iface_array_in);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.resizeOutVector(&out_nullable_iface_array_out);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_nullable_iface_array_inout);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    ::android::binder::Status _aidl_status(methodWithInterfaces(in_iface, in_nullable_iface, in_iface_array_in, &out_iface_array_out, &in_iface_array_inout, in_nullable_iface_array_in, &out_nullable_iface_array_out, &in_nullable_iface_array_inout, &_aidl_return));
+    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (!_aidl_status.isOk()) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeStrongBinderVector(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeStrongBinderVector(out_iface_array_out);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeStrongBinderVector(in_iface_array_inout);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeStrongBinderVector(out_nullable_iface_array_out);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeStrongBinderVector(in_nullable_iface_array_inout);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  default:
+  {
+    _aidl_ret_status = ::android::BBinder::onTransact(_aidl_code, _aidl_data, _aidl_reply, _aidl_flags);
+  }
+  break;
+  }
+  if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
+    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeToParcel(_aidl_reply);
+  }
+  return _aidl_ret_status;
+}
+
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t ArrayOfInterfaces::MyParcelable::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  [[maybe_unused]] size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = _aidl_parcel->readInt32();
+  if (_aidl_parcelable_raw_size < 0) return ::android::BAD_VALUE;
+  [[maybe_unused]] size_t _aidl_parcelable_size = static_cast<size_t>(_aidl_parcelable_raw_size);
+  if (_aidl_start_pos > SIZE_MAX - _aidl_parcelable_size) return ::android::BAD_VALUE;
+  if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {
+    _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->readStrongBinder(&iface);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {
+    _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->readNullableStrongBinder(&nullable_iface);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {
+    _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->readStrongBinderVector(&iface_array);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {
+    _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->readStrongBinderVector(&nullable_iface_array);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+  return _aidl_ret_status;
+}
+::android::status_t ArrayOfInterfaces::MyParcelable::writeToParcel(::android::Parcel* _aidl_parcel) const {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  auto _aidl_start_pos = _aidl_parcel->dataPosition();
+  _aidl_parcel->writeInt32(0);
+  _aidl_ret_status = _aidl_parcel->writeStrongBinder(iface);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeStrongBinder(nullable_iface);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeStrongBinderVector(iface_array);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeStrongBinderVector(nullable_iface_array);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  auto _aidl_end_pos = _aidl_parcel->dataPosition();
+  _aidl_parcel->setDataPosition(_aidl_start_pos);
+  _aidl_parcel->writeInt32(_aidl_end_pos - _aidl_start_pos);
+  _aidl_parcel->setDataPosition(_aidl_end_pos);
+  return _aidl_ret_status;
+}
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t ArrayOfInterfaces::MyUnion::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status;
+  int32_t _aidl_tag;
+  if ((_aidl_ret_status = _aidl_parcel->readInt32(&_aidl_tag)) != ::android::OK) return _aidl_ret_status;
+  switch (_aidl_tag) {
+  case iface: {
+    ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface> _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readStrongBinder(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>) {
+      set<iface>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<iface>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  case nullable_iface: {
+    ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface> _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readNullableStrongBinder(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>) {
+      set<nullable_iface>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<nullable_iface>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  case iface_array: {
+    ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>> _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readStrongBinderVector(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>) {
+      set<iface_array>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<iface_array>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  case nullable_iface_array: {
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>> _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readStrongBinderVector(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>>) {
+      set<nullable_iface_array>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<nullable_iface_array>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  }
+  return ::android::BAD_VALUE;
+}
+::android::status_t ArrayOfInterfaces::MyUnion::writeToParcel(::android::Parcel* _aidl_parcel) const {
+  ::android::status_t _aidl_ret_status = _aidl_parcel->writeInt32(getTag());
+  if (_aidl_ret_status != ::android::OK) return _aidl_ret_status;
+  switch (getTag()) {
+  case iface: return _aidl_parcel->writeStrongBinder(get<iface>());
+  case nullable_iface: return _aidl_parcel->writeStrongBinder(get<nullable_iface>());
+  case iface_array: return _aidl_parcel->writeStrongBinderVector(get<iface_array>());
+  case nullable_iface_array: return _aidl_parcel->writeStrongBinderVector(get<nullable_iface_array>());
+  }
+  __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
+}
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp.d
new file mode 100644
index 0000000..7aaca7f
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/ArrayOfInterfaces.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ITestService.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ITestService.cpp
index 5c67f5b..af0d3ac 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ITestService.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ITestService.cpp
@@ -1096,7 +1096,7 @@
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
   }
-  _aidl_ret_status = _aidl_data.writeStrongBinder(::android::aidl::tests::INamedCallback::asBinder(service));
+  _aidl_ret_status = _aidl_data.writeStrongBinder(service);
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
   }
@@ -3119,7 +3119,7 @@
     if (!_aidl_status.isOk()) {
       break;
     }
-    _aidl_ret_status = _aidl_reply->writeStrongBinder(::android::aidl::tests::INamedCallback::asBinder(_aidl_return));
+    _aidl_ret_status = _aidl_reply->writeStrongBinder(_aidl_return);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
@@ -3760,7 +3760,7 @@
     if (!_aidl_status.isOk()) {
       break;
     }
-    _aidl_ret_status = _aidl_reply->writeStrongBinder(::android::aidl::tests::INamedCallback::asBinder(_aidl_return));
+    _aidl_ret_status = _aidl_reply->writeStrongBinder(_aidl_return);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
@@ -3928,7 +3928,7 @@
     if (!_aidl_status.isOk()) {
       break;
     }
-    _aidl_ret_status = _aidl_reply->writeStrongBinder(::android::aidl::tests::IOldName::asBinder(_aidl_return));
+    _aidl_ret_status = _aidl_reply->writeStrongBinder(_aidl_return);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
@@ -3949,7 +3949,7 @@
     if (!_aidl_status.isOk()) {
       break;
     }
-    _aidl_ret_status = _aidl_reply->writeStrongBinder(::android::aidl::tests::INewName::asBinder(_aidl_return));
+    _aidl_ret_status = _aidl_reply->writeStrongBinder(_aidl_return);
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/INestedService.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/INestedService.cpp
index 3b91ccd..805f67e 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/INestedService.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/INestedService.cpp
@@ -74,7 +74,7 @@
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
   }
-  _aidl_ret_status = _aidl_data.writeStrongBinder(::android::aidl::tests::nested::INestedService::ICallback::asBinder(cb));
+  _aidl_ret_status = _aidl_data.writeStrongBinder(cb);
   if (((_aidl_ret_status) != (::android::OK))) {
     goto _aidl_error;
   }
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ArrayOfInterfaces.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ArrayOfInterfaces.h
new file mode 100644
index 0000000..759e68e
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ArrayOfInterfaces.h
@@ -0,0 +1,265 @@
+#pragma once
+
+#include <android/aidl/tests/ArrayOfInterfaces.h>
+#include <android/binder_to_string.h>
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/Status.h>
+#include <cassert>
+#include <optional>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+#include <variant>
+#include <vector>
+
+#ifndef __BIONIC__
+#define __assert2(a,b,c,d) ((void)0)
+#endif
+
+namespace android {
+namespace aidl {
+namespace tests {
+class ArrayOfInterfaces : public ::android::Parcelable {
+public:
+  inline bool operator!=(const ArrayOfInterfaces&) const {
+    return std::tie() != std::tie();
+  }
+  inline bool operator<(const ArrayOfInterfaces&) const {
+    return std::tie() < std::tie();
+  }
+  inline bool operator<=(const ArrayOfInterfaces&) const {
+    return std::tie() <= std::tie();
+  }
+  inline bool operator==(const ArrayOfInterfaces&) const {
+    return std::tie() == std::tie();
+  }
+  inline bool operator>(const ArrayOfInterfaces&) const {
+    return std::tie() > std::tie();
+  }
+  inline bool operator>=(const ArrayOfInterfaces&) const {
+    return std::tie() >= std::tie();
+  }
+
+  class IEmptyInterface : public ::android::IInterface {
+  public:
+    DECLARE_META_INTERFACE(EmptyInterface)
+  };  // class IEmptyInterface
+
+  class IEmptyInterfaceDefault : public IEmptyInterface {
+  public:
+    ::android::IBinder* onAsBinder() override {
+      return nullptr;
+    }
+  };  // class IEmptyInterfaceDefault
+  class BpEmptyInterface : public ::android::BpInterface<IEmptyInterface> {
+  public:
+    explicit BpEmptyInterface(const ::android::sp<::android::IBinder>& _aidl_impl);
+    virtual ~BpEmptyInterface() = default;
+  };  // class BpEmptyInterface
+  class BnEmptyInterface : public ::android::BnInterface<IEmptyInterface> {
+  public:
+    explicit BnEmptyInterface();
+    ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
+  };  // class BnEmptyInterface
+
+  class IEmptyInterfaceDelegator : public BnEmptyInterface {
+  public:
+    explicit IEmptyInterfaceDelegator(::android::sp<IEmptyInterface> &impl) : _aidl_delegate(impl) {}
+
+  private:
+    ::android::sp<IEmptyInterface> _aidl_delegate;
+  };  // class IEmptyInterfaceDelegator
+  class IMyInterface : public ::android::IInterface {
+  public:
+    DECLARE_META_INTERFACE(MyInterface)
+    virtual ::android::binder::Status methodWithInterfaces(const ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& iface, const ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& nullable_iface, const ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>& iface_array_in, ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* iface_array_out, ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* iface_array_inout, const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>& nullable_iface_array_in, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* nullable_iface_array_out, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* nullable_iface_array_inout, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* _aidl_return) = 0;
+  };  // class IMyInterface
+
+  class IMyInterfaceDefault : public IMyInterface {
+  public:
+    ::android::IBinder* onAsBinder() override {
+      return nullptr;
+    }
+    ::android::binder::Status methodWithInterfaces(const ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>&, const ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>&, const ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>&, ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>*, ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>*, const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>&, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>*, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>*, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>*) override {
+      return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+  };  // class IMyInterfaceDefault
+  class BpMyInterface : public ::android::BpInterface<IMyInterface> {
+  public:
+    explicit BpMyInterface(const ::android::sp<::android::IBinder>& _aidl_impl);
+    virtual ~BpMyInterface() = default;
+    ::android::binder::Status methodWithInterfaces(const ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& iface, const ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& nullable_iface, const ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>& iface_array_in, ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* iface_array_out, ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* iface_array_inout, const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>& nullable_iface_array_in, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* nullable_iface_array_out, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* nullable_iface_array_inout, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* _aidl_return) override;
+  };  // class BpMyInterface
+  class BnMyInterface : public ::android::BnInterface<IMyInterface> {
+  public:
+    static constexpr uint32_t TRANSACTION_methodWithInterfaces = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
+    explicit BnMyInterface();
+    ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
+  };  // class BnMyInterface
+
+  class IMyInterfaceDelegator : public BnMyInterface {
+  public:
+    explicit IMyInterfaceDelegator(::android::sp<IMyInterface> &impl) : _aidl_delegate(impl) {}
+
+    ::android::binder::Status methodWithInterfaces(const ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& iface, const ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& nullable_iface, const ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>& iface_array_in, ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* iface_array_out, ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* iface_array_inout, const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>& nullable_iface_array_in, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* nullable_iface_array_out, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* nullable_iface_array_inout, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* _aidl_return) override {
+      return _aidl_delegate->methodWithInterfaces(iface, nullable_iface, iface_array_in, iface_array_out, iface_array_inout, nullable_iface_array_in, nullable_iface_array_out, nullable_iface_array_inout, _aidl_return);
+    }
+  private:
+    ::android::sp<IMyInterface> _aidl_delegate;
+  };  // class IMyInterfaceDelegator
+  class MyParcelable : public ::android::Parcelable {
+  public:
+    inline bool operator!=(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_array, nullable_iface_array) != std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_array, rhs.nullable_iface_array);
+    }
+    inline bool operator<(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_array, nullable_iface_array) < std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_array, rhs.nullable_iface_array);
+    }
+    inline bool operator<=(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_array, nullable_iface_array) <= std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_array, rhs.nullable_iface_array);
+    }
+    inline bool operator==(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_array, nullable_iface_array) == std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_array, rhs.nullable_iface_array);
+    }
+    inline bool operator>(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_array, nullable_iface_array) > std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_array, rhs.nullable_iface_array);
+    }
+    inline bool operator>=(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_array, nullable_iface_array) >= std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_array, rhs.nullable_iface_array);
+    }
+
+    ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface> iface;
+    ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface> nullable_iface;
+    ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>> iface_array;
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>> nullable_iface_array;
+    ::android::status_t readFromParcel(const ::android::Parcel* _aidl_parcel) final;
+    ::android::status_t writeToParcel(::android::Parcel* _aidl_parcel) const final;
+    static const ::android::String16& getParcelableDescriptor() {
+      static const ::android::StaticString16 DESCIPTOR (u"android.aidl.tests.ArrayOfInterfaces.MyParcelable");
+      return DESCIPTOR;
+    }
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "MyParcelable{";
+      os << "iface: " << ::android::internal::ToString(iface);
+      os << ", nullable_iface: " << ::android::internal::ToString(nullable_iface);
+      os << ", iface_array: " << ::android::internal::ToString(iface_array);
+      os << ", nullable_iface_array: " << ::android::internal::ToString(nullable_iface_array);
+      os << "}";
+      return os.str();
+    }
+  };  // class MyParcelable
+  class MyUnion : public ::android::Parcelable {
+  public:
+    inline bool operator!=(const MyUnion& rhs) const {
+      return _value != rhs._value;
+    }
+    inline bool operator<(const MyUnion& rhs) const {
+      return _value < rhs._value;
+    }
+    inline bool operator<=(const MyUnion& rhs) const {
+      return _value <= rhs._value;
+    }
+    inline bool operator==(const MyUnion& rhs) const {
+      return _value == rhs._value;
+    }
+    inline bool operator>(const MyUnion& rhs) const {
+      return _value > rhs._value;
+    }
+    inline bool operator>=(const MyUnion& rhs) const {
+      return _value >= rhs._value;
+    }
+
+    enum Tag : int32_t {
+      iface = 0,  // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface iface;
+      nullable_iface,  // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface nullable_iface;
+      iface_array,  // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array;
+      nullable_iface_array,  // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array;
+    };
+
+    template<typename _Tp>
+    static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, MyUnion>;
+
+    MyUnion() : _value(std::in_place_index<iface>, ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>()) { }
+
+    template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
+    // NOLINTNEXTLINE(google-explicit-constructor)
+    constexpr MyUnion(_Tp&& _arg)
+        : _value(std::forward<_Tp>(_arg)) {}
+
+    template <size_t _Np, typename... _Tp>
+    constexpr explicit MyUnion(std::in_place_index_t<_Np>, _Tp&&... _args)
+        : _value(std::in_place_index<_Np>, std::forward<_Tp>(_args)...) {}
+
+    template <Tag _tag, typename... _Tp>
+    static MyUnion make(_Tp&&... _args) {
+      return MyUnion(std::in_place_index<_tag>, std::forward<_Tp>(_args)...);
+    }
+
+    template <Tag _tag, typename _Tp, typename... _Up>
+    static MyUnion make(std::initializer_list<_Tp> _il, _Up&&... _args) {
+      return MyUnion(std::in_place_index<_tag>, std::move(_il), std::forward<_Up>(_args)...);
+    }
+
+    Tag getTag() const {
+      return static_cast<Tag>(_value.index());
+    }
+
+    template <Tag _tag>
+    const auto& get() const {
+      if (getTag() != _tag) { __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }
+      return std::get<_tag>(_value);
+    }
+
+    template <Tag _tag>
+    auto& get() {
+      if (getTag() != _tag) { __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }
+      return std::get<_tag>(_value);
+    }
+
+    template <Tag _tag, typename... _Tp>
+    void set(_Tp&&... _args) {
+      _value.emplace<_tag>(std::forward<_Tp>(_args)...);
+    }
+
+    ::android::status_t readFromParcel(const ::android::Parcel* _aidl_parcel) final;
+    ::android::status_t writeToParcel(::android::Parcel* _aidl_parcel) const final;
+    static const ::android::String16& getParcelableDescriptor() {
+      static const ::android::StaticString16 DESCIPTOR (u"android.aidl.tests.ArrayOfInterfaces.MyUnion");
+      return DESCIPTOR;
+    }
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "MyUnion{";
+      switch (getTag()) {
+      case iface: os << "iface: " << ::android::internal::ToString(get<iface>()); break;
+      case nullable_iface: os << "nullable_iface: " << ::android::internal::ToString(get<nullable_iface>()); break;
+      case iface_array: os << "iface_array: " << ::android::internal::ToString(get<iface_array>()); break;
+      case nullable_iface_array: os << "nullable_iface_array: " << ::android::internal::ToString(get<nullable_iface_array>()); break;
+      }
+      os << "}";
+      return os.str();
+    }
+  private:
+    std::variant<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>, ::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>, ::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>> _value;
+  };  // class MyUnion
+  ::android::status_t readFromParcel(const ::android::Parcel* _aidl_parcel) final;
+  ::android::status_t writeToParcel(::android::Parcel* _aidl_parcel) const final;
+  static const ::android::String16& getParcelableDescriptor() {
+    static const ::android::StaticString16 DESCIPTOR (u"android.aidl.tests.ArrayOfInterfaces");
+    return DESCIPTOR;
+  }
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "ArrayOfInterfaces{";
+    os << "}";
+    return os.str();
+  }
+};  // class ArrayOfInterfaces
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnArrayOfInterfaces.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnArrayOfInterfaces.h
new file mode 100644
index 0000000..ce72aa3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnArrayOfInterfaces.h
@@ -0,0 +1 @@
+#error TODO(b/111362593) parcelables do not have bn classes
\ No newline at end of file
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpArrayOfInterfaces.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpArrayOfInterfaces.h
new file mode 100644
index 0000000..27af6b1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpArrayOfInterfaces.h
@@ -0,0 +1 @@
+#error TODO(b/111362593) parcelables do not have bp classes
\ No newline at end of file
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ArrayOfInterfaces.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ArrayOfInterfaces.java
new file mode 100644
index 0000000..c59e83f
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ArrayOfInterfaces.java
@@ -0,0 +1,840 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests;
+public class ArrayOfInterfaces implements android.os.Parcelable
+{
+  public static final android.os.Parcelable.Creator<ArrayOfInterfaces> CREATOR = new android.os.Parcelable.Creator<ArrayOfInterfaces>() {
+    @Override
+    public ArrayOfInterfaces createFromParcel(android.os.Parcel _aidl_source) {
+      ArrayOfInterfaces _aidl_out = new ArrayOfInterfaces();
+      _aidl_out.readFromParcel(_aidl_source);
+      return _aidl_out;
+    }
+    @Override
+    public ArrayOfInterfaces[] newArray(int _aidl_size) {
+      return new ArrayOfInterfaces[_aidl_size];
+    }
+  };
+  @Override public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag)
+  {
+    int _aidl_start_pos = _aidl_parcel.dataPosition();
+    _aidl_parcel.writeInt(0);
+    int _aidl_end_pos = _aidl_parcel.dataPosition();
+    _aidl_parcel.setDataPosition(_aidl_start_pos);
+    _aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);
+    _aidl_parcel.setDataPosition(_aidl_end_pos);
+  }
+  public final void readFromParcel(android.os.Parcel _aidl_parcel)
+  {
+    int _aidl_start_pos = _aidl_parcel.dataPosition();
+    int _aidl_parcelable_size = _aidl_parcel.readInt();
+    try {
+      if (_aidl_parcelable_size < 0) return;
+    } finally {
+      if (_aidl_start_pos > (Integer.MAX_VALUE - _aidl_parcelable_size)) {
+        throw new android.os.BadParcelableException("Overflow in the size of parcelable");
+      }
+      _aidl_parcel.setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+    }
+  }
+  @Override
+  public int describeContents() {
+    int _mask = 0;
+    return _mask;
+  }
+  public interface IEmptyInterface extends android.os.IInterface
+  {
+    /** Default implementation for IEmptyInterface. */
+    public static class Default implements android.aidl.tests.ArrayOfInterfaces.IEmptyInterface
+    {
+      @Override
+      public android.os.IBinder asBinder() {
+        return null;
+      }
+    }
+    /** Local-side IPC implementation stub class. */
+    public static abstract class Stub extends android.os.Binder implements android.aidl.tests.ArrayOfInterfaces.IEmptyInterface
+    {
+      /** Construct the stub at attach it to the interface. */
+      public Stub()
+      {
+        this.attachInterface(this, DESCRIPTOR);
+      }
+      /**
+       * Cast an IBinder object into an android.aidl.tests.ArrayOfInterfaces.IEmptyInterface interface,
+       * generating a proxy if needed.
+       */
+      public static android.aidl.tests.ArrayOfInterfaces.IEmptyInterface asInterface(android.os.IBinder obj)
+      {
+        if ((obj==null)) {
+          return null;
+        }
+        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+        if (((iin!=null)&&(iin instanceof android.aidl.tests.ArrayOfInterfaces.IEmptyInterface))) {
+          return ((android.aidl.tests.ArrayOfInterfaces.IEmptyInterface)iin);
+        }
+        return new android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.Proxy(obj);
+      }
+      @Override public android.os.IBinder asBinder()
+      {
+        return this;
+      }
+      @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
+      {
+        java.lang.String descriptor = DESCRIPTOR;
+        switch (code)
+        {
+          case INTERFACE_TRANSACTION:
+          {
+            reply.writeString(descriptor);
+            return true;
+          }
+        }
+        switch (code)
+        {
+          default:
+          {
+            return super.onTransact(code, data, reply, flags);
+          }
+        }
+      }
+      private static class Proxy implements android.aidl.tests.ArrayOfInterfaces.IEmptyInterface
+      {
+        private android.os.IBinder mRemote;
+        Proxy(android.os.IBinder remote)
+        {
+          mRemote = remote;
+        }
+        @Override public android.os.IBinder asBinder()
+        {
+          return mRemote;
+        }
+        public java.lang.String getInterfaceDescriptor()
+        {
+          return DESCRIPTOR;
+        }
+        public static android.aidl.tests.ArrayOfInterfaces.IEmptyInterface sDefaultImpl;
+      }
+      public static boolean setDefaultImpl(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface impl) {
+        // Only one user of this interface can use this function
+        // at a time. This is a heuristic to detect if two different
+        // users in the same process use this function.
+        if (Stub.Proxy.sDefaultImpl != null) {
+          throw new IllegalStateException("setDefaultImpl() called twice");
+        }
+        if (impl != null) {
+          Stub.Proxy.sDefaultImpl = impl;
+          return true;
+        }
+        return false;
+      }
+      public static android.aidl.tests.ArrayOfInterfaces.IEmptyInterface getDefaultImpl() {
+        return Stub.Proxy.sDefaultImpl;
+      }
+    }
+    public static final java.lang.String DESCRIPTOR = "android$aidl$tests$ArrayOfInterfaces$IEmptyInterface".replace('$', '.');
+  }
+  public interface IMyInterface extends android.os.IInterface
+  {
+    /** Default implementation for IMyInterface. */
+    public static class Default implements android.aidl.tests.ArrayOfInterfaces.IMyInterface
+    {
+      @Override public android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] methodWithInterfaces(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface iface, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface nullable_iface, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array_in, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array_out, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array_inout, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array_in, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array_out, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array_inout) throws android.os.RemoteException
+      {
+        return null;
+      }
+      @Override
+      public android.os.IBinder asBinder() {
+        return null;
+      }
+    }
+    /** Local-side IPC implementation stub class. */
+    public static abstract class Stub extends android.os.Binder implements android.aidl.tests.ArrayOfInterfaces.IMyInterface
+    {
+      /** Construct the stub at attach it to the interface. */
+      public Stub()
+      {
+        this.attachInterface(this, DESCRIPTOR);
+      }
+      /**
+       * Cast an IBinder object into an android.aidl.tests.ArrayOfInterfaces.IMyInterface interface,
+       * generating a proxy if needed.
+       */
+      public static android.aidl.tests.ArrayOfInterfaces.IMyInterface asInterface(android.os.IBinder obj)
+      {
+        if ((obj==null)) {
+          return null;
+        }
+        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+        if (((iin!=null)&&(iin instanceof android.aidl.tests.ArrayOfInterfaces.IMyInterface))) {
+          return ((android.aidl.tests.ArrayOfInterfaces.IMyInterface)iin);
+        }
+        return new android.aidl.tests.ArrayOfInterfaces.IMyInterface.Stub.Proxy(obj);
+      }
+      @Override public android.os.IBinder asBinder()
+      {
+        return this;
+      }
+      @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
+      {
+        java.lang.String descriptor = DESCRIPTOR;
+        if (code >= android.os.IBinder.FIRST_CALL_TRANSACTION && code <= android.os.IBinder.LAST_CALL_TRANSACTION) {
+          data.enforceInterface(descriptor);
+        }
+        switch (code)
+        {
+          case INTERFACE_TRANSACTION:
+          {
+            reply.writeString(descriptor);
+            return true;
+          }
+        }
+        switch (code)
+        {
+          case TRANSACTION_methodWithInterfaces:
+          {
+            android.aidl.tests.ArrayOfInterfaces.IEmptyInterface _arg0;
+            _arg0 = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(data.readStrongBinder());
+            android.aidl.tests.ArrayOfInterfaces.IEmptyInterface _arg1;
+            _arg1 = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(data.readStrongBinder());
+            android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _arg2;
+            {
+              android.os.IBinder[] _binder_arr = data.createBinderArray();
+              if (_binder_arr != null) {
+                _arg2 = new android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[_binder_arr.length];
+                for (int i = 0; i < _binder_arr.length; i++) {
+                  _arg2[i] = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_binder_arr[i]);
+                }
+              } else {
+                _arg2 = null;
+              }
+            }
+            android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _arg3;
+            int _arg3_length = data.readInt();
+            if ((_arg3_length<0)) {
+              _arg3 = null;
+            }
+            else {
+              _arg3 = new android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[_arg3_length];
+            }
+            android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _arg4;
+            {
+              android.os.IBinder[] _binder_arr = data.createBinderArray();
+              if (_binder_arr != null) {
+                _arg4 = new android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[_binder_arr.length];
+                for (int i = 0; i < _binder_arr.length; i++) {
+                  _arg4[i] = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_binder_arr[i]);
+                }
+              } else {
+                _arg4 = null;
+              }
+            }
+            android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _arg5;
+            {
+              android.os.IBinder[] _binder_arr = data.createBinderArray();
+              if (_binder_arr != null) {
+                _arg5 = new android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[_binder_arr.length];
+                for (int i = 0; i < _binder_arr.length; i++) {
+                  _arg5[i] = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_binder_arr[i]);
+                }
+              } else {
+                _arg5 = null;
+              }
+            }
+            android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _arg6;
+            int _arg6_length = data.readInt();
+            if ((_arg6_length<0)) {
+              _arg6 = null;
+            }
+            else {
+              _arg6 = new android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[_arg6_length];
+            }
+            android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _arg7;
+            {
+              android.os.IBinder[] _binder_arr = data.createBinderArray();
+              if (_binder_arr != null) {
+                _arg7 = new android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[_binder_arr.length];
+                for (int i = 0; i < _binder_arr.length; i++) {
+                  _arg7[i] = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_binder_arr[i]);
+                }
+              } else {
+                _arg7 = null;
+              }
+            }
+            android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _result = this.methodWithInterfaces(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7);
+            reply.writeNoException();
+            {
+              android.os.IBinder[] _binder_arr = null;
+              if (_result != null) {
+                _binder_arr = new android.os.IBinder[_result.length];
+                for (int i = 0; i < _result.length; i++) {
+                  _binder_arr[i] = (_result[i] != null) ? _result[i].asBinder() : null;
+                }
+              }
+              reply.writeBinderArray(_binder_arr);
+            }
+            {
+              android.os.IBinder[] _binder_arr = null;
+              if (_arg3 != null) {
+                _binder_arr = new android.os.IBinder[_arg3.length];
+                for (int i = 0; i < _arg3.length; i++) {
+                  _binder_arr[i] = (_arg3[i] != null) ? _arg3[i].asBinder() : null;
+                }
+              }
+              reply.writeBinderArray(_binder_arr);
+            }
+            {
+              android.os.IBinder[] _binder_arr = null;
+              if (_arg4 != null) {
+                _binder_arr = new android.os.IBinder[_arg4.length];
+                for (int i = 0; i < _arg4.length; i++) {
+                  _binder_arr[i] = (_arg4[i] != null) ? _arg4[i].asBinder() : null;
+                }
+              }
+              reply.writeBinderArray(_binder_arr);
+            }
+            {
+              android.os.IBinder[] _binder_arr = null;
+              if (_arg6 != null) {
+                _binder_arr = new android.os.IBinder[_arg6.length];
+                for (int i = 0; i < _arg6.length; i++) {
+                  _binder_arr[i] = (_arg6[i] != null) ? _arg6[i].asBinder() : null;
+                }
+              }
+              reply.writeBinderArray(_binder_arr);
+            }
+            {
+              android.os.IBinder[] _binder_arr = null;
+              if (_arg7 != null) {
+                _binder_arr = new android.os.IBinder[_arg7.length];
+                for (int i = 0; i < _arg7.length; i++) {
+                  _binder_arr[i] = (_arg7[i] != null) ? _arg7[i].asBinder() : null;
+                }
+              }
+              reply.writeBinderArray(_binder_arr);
+            }
+            break;
+          }
+          default:
+          {
+            return super.onTransact(code, data, reply, flags);
+          }
+        }
+        return true;
+      }
+      private static class Proxy implements android.aidl.tests.ArrayOfInterfaces.IMyInterface
+      {
+        private android.os.IBinder mRemote;
+        Proxy(android.os.IBinder remote)
+        {
+          mRemote = remote;
+        }
+        @Override public android.os.IBinder asBinder()
+        {
+          return mRemote;
+        }
+        public java.lang.String getInterfaceDescriptor()
+        {
+          return DESCRIPTOR;
+        }
+        @Override public android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] methodWithInterfaces(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface iface, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface nullable_iface, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array_in, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array_out, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array_inout, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array_in, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array_out, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array_inout) throws android.os.RemoteException
+        {
+          android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+          android.os.Parcel _reply = android.os.Parcel.obtain();
+          android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _result;
+          try {
+            _data.writeInterfaceToken(DESCRIPTOR);
+            _data.writeStrongBinder((((iface!=null))?(iface.asBinder()):(null)));
+            _data.writeStrongBinder((((nullable_iface!=null))?(nullable_iface.asBinder()):(null)));
+            {
+              android.os.IBinder[] _binder_arr = null;
+              if (iface_array_in != null) {
+                _binder_arr = new android.os.IBinder[iface_array_in.length];
+                for (int i = 0; i < iface_array_in.length; i++) {
+                  _binder_arr[i] = (iface_array_in[i] != null) ? iface_array_in[i].asBinder() : null;
+                }
+              }
+              _data.writeBinderArray(_binder_arr);
+            }
+            if ((iface_array_out==null)) {
+              _data.writeInt(-1);
+            }
+            else {
+              _data.writeInt(iface_array_out.length);
+            }
+            {
+              android.os.IBinder[] _binder_arr = null;
+              if (iface_array_inout != null) {
+                _binder_arr = new android.os.IBinder[iface_array_inout.length];
+                for (int i = 0; i < iface_array_inout.length; i++) {
+                  _binder_arr[i] = (iface_array_inout[i] != null) ? iface_array_inout[i].asBinder() : null;
+                }
+              }
+              _data.writeBinderArray(_binder_arr);
+            }
+            {
+              android.os.IBinder[] _binder_arr = null;
+              if (nullable_iface_array_in != null) {
+                _binder_arr = new android.os.IBinder[nullable_iface_array_in.length];
+                for (int i = 0; i < nullable_iface_array_in.length; i++) {
+                  _binder_arr[i] = (nullable_iface_array_in[i] != null) ? nullable_iface_array_in[i].asBinder() : null;
+                }
+              }
+              _data.writeBinderArray(_binder_arr);
+            }
+            if ((nullable_iface_array_out==null)) {
+              _data.writeInt(-1);
+            }
+            else {
+              _data.writeInt(nullable_iface_array_out.length);
+            }
+            {
+              android.os.IBinder[] _binder_arr = null;
+              if (nullable_iface_array_inout != null) {
+                _binder_arr = new android.os.IBinder[nullable_iface_array_inout.length];
+                for (int i = 0; i < nullable_iface_array_inout.length; i++) {
+                  _binder_arr[i] = (nullable_iface_array_inout[i] != null) ? nullable_iface_array_inout[i].asBinder() : null;
+                }
+              }
+              _data.writeBinderArray(_binder_arr);
+            }
+            boolean _status = mRemote.transact(Stub.TRANSACTION_methodWithInterfaces, _data, _reply, 0);
+            if (!_status) {
+              if (getDefaultImpl() != null) {
+                return getDefaultImpl().methodWithInterfaces(iface, nullable_iface, iface_array_in, iface_array_out, iface_array_inout, nullable_iface_array_in, nullable_iface_array_out, nullable_iface_array_inout);
+              }
+            }
+            _reply.readException();
+            {
+              android.os.IBinder[] _binder_arr = _reply.createBinderArray();
+              if (_binder_arr != null) {
+                _result = new android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[_binder_arr.length];
+                for (int i = 0; i < _binder_arr.length; i++) {
+                  _result[i] = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_binder_arr[i]);
+                }
+              } else {
+                _result = null;
+              }
+            }
+            {
+              android.os.IBinder[] _binder_arr = new android.os.IBinder[iface_array_out.length];
+              _reply.readBinderArray(_binder_arr);
+              for (int i = 0; i < _binder_arr.length; i++) {
+                iface_array_out[i] = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_binder_arr[i]);
+              }
+            }
+            {
+              android.os.IBinder[] _binder_arr = new android.os.IBinder[iface_array_inout.length];
+              _reply.readBinderArray(_binder_arr);
+              for (int i = 0; i < _binder_arr.length; i++) {
+                iface_array_inout[i] = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_binder_arr[i]);
+              }
+            }
+            {
+              android.os.IBinder[] _binder_arr = new android.os.IBinder[nullable_iface_array_out.length];
+              _reply.readBinderArray(_binder_arr);
+              for (int i = 0; i < _binder_arr.length; i++) {
+                nullable_iface_array_out[i] = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_binder_arr[i]);
+              }
+            }
+            {
+              android.os.IBinder[] _binder_arr = new android.os.IBinder[nullable_iface_array_inout.length];
+              _reply.readBinderArray(_binder_arr);
+              for (int i = 0; i < _binder_arr.length; i++) {
+                nullable_iface_array_inout[i] = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_binder_arr[i]);
+              }
+            }
+          }
+          finally {
+            _reply.recycle();
+            _data.recycle();
+          }
+          return _result;
+        }
+        public static android.aidl.tests.ArrayOfInterfaces.IMyInterface sDefaultImpl;
+      }
+      static final int TRANSACTION_methodWithInterfaces = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+      public static boolean setDefaultImpl(android.aidl.tests.ArrayOfInterfaces.IMyInterface impl) {
+        // Only one user of this interface can use this function
+        // at a time. This is a heuristic to detect if two different
+        // users in the same process use this function.
+        if (Stub.Proxy.sDefaultImpl != null) {
+          throw new IllegalStateException("setDefaultImpl() called twice");
+        }
+        if (impl != null) {
+          Stub.Proxy.sDefaultImpl = impl;
+          return true;
+        }
+        return false;
+      }
+      public static android.aidl.tests.ArrayOfInterfaces.IMyInterface getDefaultImpl() {
+        return Stub.Proxy.sDefaultImpl;
+      }
+    }
+    public static final java.lang.String DESCRIPTOR = "android$aidl$tests$ArrayOfInterfaces$IMyInterface".replace('$', '.');
+    public android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] methodWithInterfaces(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface iface, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface nullable_iface, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array_in, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array_out, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array_inout, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array_in, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array_out, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array_inout) throws android.os.RemoteException;
+  }
+  public static class MyParcelable implements android.os.Parcelable
+  {
+    public android.aidl.tests.ArrayOfInterfaces.IEmptyInterface iface;
+    public android.aidl.tests.ArrayOfInterfaces.IEmptyInterface nullable_iface;
+    public android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array;
+    public android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array;
+    public static final android.os.Parcelable.Creator<MyParcelable> CREATOR = new android.os.Parcelable.Creator<MyParcelable>() {
+      @Override
+      public MyParcelable createFromParcel(android.os.Parcel _aidl_source) {
+        MyParcelable _aidl_out = new MyParcelable();
+        _aidl_out.readFromParcel(_aidl_source);
+        return _aidl_out;
+      }
+      @Override
+      public MyParcelable[] newArray(int _aidl_size) {
+        return new MyParcelable[_aidl_size];
+      }
+    };
+    @Override public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag)
+    {
+      int _aidl_start_pos = _aidl_parcel.dataPosition();
+      _aidl_parcel.writeInt(0);
+      _aidl_parcel.writeStrongBinder((((iface!=null))?(iface.asBinder()):(null)));
+      _aidl_parcel.writeStrongBinder((((nullable_iface!=null))?(nullable_iface.asBinder()):(null)));
+      {
+        android.os.IBinder[] _binder_arr = null;
+        if (iface_array != null) {
+          _binder_arr = new android.os.IBinder[iface_array.length];
+          for (int i = 0; i < iface_array.length; i++) {
+            _binder_arr[i] = (iface_array[i] != null) ? iface_array[i].asBinder() : null;
+          }
+        }
+        _aidl_parcel.writeBinderArray(_binder_arr);
+      }
+      {
+        android.os.IBinder[] _binder_arr = null;
+        if (nullable_iface_array != null) {
+          _binder_arr = new android.os.IBinder[nullable_iface_array.length];
+          for (int i = 0; i < nullable_iface_array.length; i++) {
+            _binder_arr[i] = (nullable_iface_array[i] != null) ? nullable_iface_array[i].asBinder() : null;
+          }
+        }
+        _aidl_parcel.writeBinderArray(_binder_arr);
+      }
+      int _aidl_end_pos = _aidl_parcel.dataPosition();
+      _aidl_parcel.setDataPosition(_aidl_start_pos);
+      _aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);
+      _aidl_parcel.setDataPosition(_aidl_end_pos);
+    }
+    public final void readFromParcel(android.os.Parcel _aidl_parcel)
+    {
+      int _aidl_start_pos = _aidl_parcel.dataPosition();
+      int _aidl_parcelable_size = _aidl_parcel.readInt();
+      try {
+        if (_aidl_parcelable_size < 0) return;
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        iface = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_aidl_parcel.readStrongBinder());
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        nullable_iface = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_aidl_parcel.readStrongBinder());
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        {
+          android.os.IBinder[] _binder_arr = _aidl_parcel.createBinderArray();
+          if (_binder_arr != null) {
+            iface_array = new android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[_binder_arr.length];
+            for (int i = 0; i < _binder_arr.length; i++) {
+              iface_array[i] = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_binder_arr[i]);
+            }
+          } else {
+            iface_array = null;
+          }
+        }
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        {
+          android.os.IBinder[] _binder_arr = _aidl_parcel.createBinderArray();
+          if (_binder_arr != null) {
+            nullable_iface_array = new android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[_binder_arr.length];
+            for (int i = 0; i < _binder_arr.length; i++) {
+              nullable_iface_array[i] = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_binder_arr[i]);
+            }
+          } else {
+            nullable_iface_array = null;
+          }
+        }
+      } finally {
+        if (_aidl_start_pos > (Integer.MAX_VALUE - _aidl_parcelable_size)) {
+          throw new android.os.BadParcelableException("Overflow in the size of parcelable");
+        }
+        _aidl_parcel.setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
+      }
+    }
+    @Override
+    public String toString() {
+      java.util.StringJoiner _aidl_sj = new java.util.StringJoiner(", ", "{", "}");
+      _aidl_sj.add("iface: " + (java.util.Objects.toString(iface)));
+      _aidl_sj.add("nullable_iface: " + (java.util.Objects.toString(nullable_iface)));
+      _aidl_sj.add("iface_array: " + (java.util.Arrays.toString(iface_array)));
+      _aidl_sj.add("nullable_iface_array: " + (java.util.Arrays.toString(nullable_iface_array)));
+      return "android.aidl.tests.ArrayOfInterfaces.MyParcelable" + _aidl_sj.toString()  ;
+    }
+    @Override
+    public boolean equals(Object other) {
+      if (this == other) return true;
+      if (other == null) return false;
+      if (!(other instanceof MyParcelable)) return false;
+      MyParcelable that = (MyParcelable)other;
+      if (!java.util.Objects.deepEquals(iface, that.iface)) return false;
+      if (!java.util.Objects.deepEquals(nullable_iface, that.nullable_iface)) return false;
+      if (!java.util.Objects.deepEquals(iface_array, that.iface_array)) return false;
+      if (!java.util.Objects.deepEquals(nullable_iface_array, that.nullable_iface_array)) return false;
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return java.util.Arrays.deepHashCode(java.util.Arrays.asList(iface, nullable_iface, iface_array, nullable_iface_array).toArray());
+    }
+    @Override
+    public int describeContents() {
+      int _mask = 0;
+      return _mask;
+    }
+  }
+  public static final class MyUnion implements android.os.Parcelable {
+    // tags for union fields
+    public final static int iface = 0;  // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface iface;
+    public final static int nullable_iface = 1;  // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface nullable_iface;
+    public final static int iface_array = 2;  // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array;
+    public final static int nullable_iface_array = 3;  // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array;
+
+    private int _tag;
+    private Object _value;
+
+    public MyUnion() {
+      android.aidl.tests.ArrayOfInterfaces.IEmptyInterface _value = null;
+      this._tag = iface;
+      this._value = _value;
+    }
+
+    private MyUnion(android.os.Parcel _aidl_parcel) {
+      readFromParcel(_aidl_parcel);
+    }
+
+    private MyUnion(int _tag, Object _value) {
+      this._tag = _tag;
+      this._value = _value;
+    }
+
+    public int getTag() {
+      return _tag;
+    }
+
+    // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface iface;
+
+    public static MyUnion iface(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface _value) {
+      return new MyUnion(iface, _value);
+    }
+
+    public android.aidl.tests.ArrayOfInterfaces.IEmptyInterface getIface() {
+      _assertTag(iface);
+      return (android.aidl.tests.ArrayOfInterfaces.IEmptyInterface) _value;
+    }
+
+    public void setIface(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface _value) {
+      _set(iface, _value);
+    }
+
+    // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface nullable_iface;
+
+    public static MyUnion nullable_iface(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface _value) {
+      return new MyUnion(nullable_iface, _value);
+    }
+
+    public android.aidl.tests.ArrayOfInterfaces.IEmptyInterface getNullable_iface() {
+      _assertTag(nullable_iface);
+      return (android.aidl.tests.ArrayOfInterfaces.IEmptyInterface) _value;
+    }
+
+    public void setNullable_iface(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface _value) {
+      _set(nullable_iface, _value);
+    }
+
+    // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array;
+
+    public static MyUnion iface_array(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _value) {
+      return new MyUnion(iface_array, _value);
+    }
+
+    public android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] getIface_array() {
+      _assertTag(iface_array);
+      return (android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[]) _value;
+    }
+
+    public void setIface_array(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _value) {
+      _set(iface_array, _value);
+    }
+
+    // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array;
+
+    public static MyUnion nullable_iface_array(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _value) {
+      return new MyUnion(nullable_iface_array, _value);
+    }
+
+    public android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] getNullable_iface_array() {
+      _assertTag(nullable_iface_array);
+      return (android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[]) _value;
+    }
+
+    public void setNullable_iface_array(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _value) {
+      _set(nullable_iface_array, _value);
+    }
+
+    public static final android.os.Parcelable.Creator<MyUnion> CREATOR = new android.os.Parcelable.Creator<MyUnion>() {
+      @Override
+      public MyUnion createFromParcel(android.os.Parcel _aidl_source) {
+        return new MyUnion(_aidl_source);
+      }
+      @Override
+      public MyUnion[] newArray(int _aidl_size) {
+        return new MyUnion[_aidl_size];
+      }
+    };
+
+    @Override
+    public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag) {
+      _aidl_parcel.writeInt(_tag);
+      switch (_tag) {
+      case iface:
+        _aidl_parcel.writeStrongBinder((((getIface()!=null))?(getIface().asBinder()):(null)));
+        break;
+      case nullable_iface:
+        _aidl_parcel.writeStrongBinder((((getNullable_iface()!=null))?(getNullable_iface().asBinder()):(null)));
+        break;
+      case iface_array:
+        {
+          android.os.IBinder[] _binder_arr = null;
+          if (getIface_array() != null) {
+            _binder_arr = new android.os.IBinder[getIface_array().length];
+            for (int i = 0; i < getIface_array().length; i++) {
+              _binder_arr[i] = (getIface_array()[i] != null) ? getIface_array()[i].asBinder() : null;
+            }
+          }
+          _aidl_parcel.writeBinderArray(_binder_arr);
+        }
+        break;
+      case nullable_iface_array:
+        {
+          android.os.IBinder[] _binder_arr = null;
+          if (getNullable_iface_array() != null) {
+            _binder_arr = new android.os.IBinder[getNullable_iface_array().length];
+            for (int i = 0; i < getNullable_iface_array().length; i++) {
+              _binder_arr[i] = (getNullable_iface_array()[i] != null) ? getNullable_iface_array()[i].asBinder() : null;
+            }
+          }
+          _aidl_parcel.writeBinderArray(_binder_arr);
+        }
+        break;
+      }
+    }
+
+    public void readFromParcel(android.os.Parcel _aidl_parcel) {
+      int _aidl_tag;
+      _aidl_tag = _aidl_parcel.readInt();
+      switch (_aidl_tag) {
+      case iface: {
+        android.aidl.tests.ArrayOfInterfaces.IEmptyInterface _aidl_value;
+        _aidl_value = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_aidl_parcel.readStrongBinder());
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case nullable_iface: {
+        android.aidl.tests.ArrayOfInterfaces.IEmptyInterface _aidl_value;
+        _aidl_value = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_aidl_parcel.readStrongBinder());
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case iface_array: {
+        android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _aidl_value;
+        {
+          android.os.IBinder[] _binder_arr = _aidl_parcel.createBinderArray();
+          if (_binder_arr != null) {
+            _aidl_value = new android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[_binder_arr.length];
+            for (int i = 0; i < _binder_arr.length; i++) {
+              _aidl_value[i] = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_binder_arr[i]);
+            }
+          } else {
+            _aidl_value = null;
+          }
+        }
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case nullable_iface_array: {
+        android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _aidl_value;
+        {
+          android.os.IBinder[] _binder_arr = _aidl_parcel.createBinderArray();
+          if (_binder_arr != null) {
+            _aidl_value = new android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[_binder_arr.length];
+            for (int i = 0; i < _binder_arr.length; i++) {
+              _aidl_value[i] = android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub.asInterface(_binder_arr[i]);
+            }
+          } else {
+            _aidl_value = null;
+          }
+        }
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      }
+      throw new IllegalArgumentException("union: unknown tag: " + _aidl_tag);
+    }
+
+    @Override
+    public int describeContents() {
+      int _mask = 0;
+      switch (getTag()) {
+      }
+      return _mask;
+    }
+
+    @Override
+    public String toString() {
+      switch (_tag) {
+      case iface: return "android.aidl.tests.ArrayOfInterfaces.MyUnion.iface(" + (java.util.Objects.toString(getIface())) + ")";
+      case nullable_iface: return "android.aidl.tests.ArrayOfInterfaces.MyUnion.nullable_iface(" + (java.util.Objects.toString(getNullable_iface())) + ")";
+      case iface_array: return "android.aidl.tests.ArrayOfInterfaces.MyUnion.iface_array(" + (java.util.Arrays.toString(getIface_array())) + ")";
+      case nullable_iface_array: return "android.aidl.tests.ArrayOfInterfaces.MyUnion.nullable_iface_array(" + (java.util.Arrays.toString(getNullable_iface_array())) + ")";
+      }
+      throw new IllegalStateException("unknown field: " + _tag);
+    }
+    @Override
+    public boolean equals(Object other) {
+      if (this == other) return true;
+      if (other == null) return false;
+      if (!(other instanceof MyUnion)) return false;
+      MyUnion that = (MyUnion)other;
+      if (_tag != that._tag) return false;
+      if (!java.util.Objects.deepEquals(_value, that._value)) return false;
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return java.util.Arrays.deepHashCode(java.util.Arrays.asList(_tag, _value).toArray());
+    }
+
+    private void _assertTag(int tag) {
+      if (getTag() != tag) {
+        throw new IllegalStateException("bad access: " + _tagString(tag) + ", " + _tagString(getTag()) + " is available.");
+      }
+    }
+
+    private String _tagString(int _tag) {
+      switch (_tag) {
+      case iface: return "iface";
+      case nullable_iface: return "nullable_iface";
+      case iface_array: return "iface_array";
+      case nullable_iface_array: return "nullable_iface_array";
+      }
+      throw new IllegalStateException("unknown field: " + _tag);
+    }
+
+    private void _set(int _tag, Object _value) {
+      this._tag = _tag;
+      this._value = _value;
+    }
+  }
+}
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ArrayOfInterfaces.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ArrayOfInterfaces.java.d
new file mode 100644
index 0000000..7605fbe
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ArrayOfInterfaces.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/ArrayOfInterfaces.java : \
+  system/tools/aidl/tests/android/aidl/tests/ArrayOfInterfaces.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp
new file mode 100644
index 0000000..9415983
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp
@@ -0,0 +1,517 @@
+#include "aidl/android/aidl/tests/ArrayOfInterfaces.h"
+
+#include <android/binder_parcel_utils.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* ArrayOfInterfaces::descriptor = "android.aidl.tests.ArrayOfInterfaces";
+
+binder_status_t ArrayOfInterfaces::readFromParcel(const AParcel* _aidl_parcel) {
+  int32_t _aidl_parcelable_size;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  binder_status_t _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  if (_aidl_parcelable_size < 0) return STATUS_BAD_VALUE;
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+  return _aidl_ret_status;
+}
+binder_status_t ArrayOfInterfaces::writeToParcel(AParcel* _aidl_parcel) const {
+  binder_status_t _aidl_ret_status;
+  size_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  _aidl_ret_status = AParcel_writeInt32(_aidl_parcel, 0);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  size_t _aidl_end_pos = AParcel_getDataPosition(_aidl_parcel);
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos);
+  AParcel_writeInt32(_aidl_parcel, _aidl_end_pos - _aidl_start_pos);
+  AParcel_setDataPosition(_aidl_parcel, _aidl_end_pos);
+  return _aidl_ret_status;
+}
+
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+#include <android/binder_parcel_utils.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+static binder_status_t _aidl_android_aidl_tests_ArrayOfInterfaces_IEmptyInterface_onTransact(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, AParcel* _aidl_out) {
+  (void)_aidl_in;
+  (void)_aidl_out;
+  binder_status_t _aidl_ret_status = STATUS_UNKNOWN_TRANSACTION;
+  (void)_aidl_binder;
+  (void)_aidl_code;
+  return _aidl_ret_status;
+}
+
+static AIBinder_Class* _g_aidl_android_aidl_tests_ArrayOfInterfaces_IEmptyInterface_clazz = ::ndk::ICInterface::defineClass(ArrayOfInterfaces::IEmptyInterface::descriptor, _aidl_android_aidl_tests_ArrayOfInterfaces_IEmptyInterface_onTransact);
+
+ArrayOfInterfaces::BpEmptyInterface::BpEmptyInterface(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
+ArrayOfInterfaces::BpEmptyInterface::~BpEmptyInterface() {}
+
+// Source for BnEmptyInterface
+ArrayOfInterfaces::BnEmptyInterface::BnEmptyInterface() {}
+ArrayOfInterfaces::BnEmptyInterface::~BnEmptyInterface() {}
+::ndk::SpAIBinder ArrayOfInterfaces::BnEmptyInterface::createBinder() {
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_tests_ArrayOfInterfaces_IEmptyInterface_clazz, static_cast<void*>(this));
+  #ifdef BINDER_STABILITY_SUPPORT
+  AIBinder_markCompilationUnitStability(binder);
+  #endif  // BINDER_STABILITY_SUPPORT
+  return ::ndk::SpAIBinder(binder);
+}
+// Source for IEmptyInterface
+const char* ArrayOfInterfaces::IEmptyInterface::descriptor = "android.aidl.tests.ArrayOfInterfaces.IEmptyInterface";
+ArrayOfInterfaces::IEmptyInterface::IEmptyInterface() {}
+ArrayOfInterfaces::IEmptyInterface::~IEmptyInterface() {}
+
+
+std::shared_ptr<ArrayOfInterfaces::IEmptyInterface> ArrayOfInterfaces::IEmptyInterface::fromBinder(const ::ndk::SpAIBinder& binder) {
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_tests_ArrayOfInterfaces_IEmptyInterface_clazz)) { return nullptr; }
+  std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
+  if (interface) {
+    return std::static_pointer_cast<IEmptyInterface>(interface);
+  }
+  return ::ndk::SharedRefBase::make<ArrayOfInterfaces::BpEmptyInterface>(binder);
+}
+
+binder_status_t ArrayOfInterfaces::IEmptyInterface::writeToParcel(AParcel* parcel, const std::shared_ptr<IEmptyInterface>& instance) {
+  return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : nullptr);
+}
+binder_status_t ArrayOfInterfaces::IEmptyInterface::readFromParcel(const AParcel* parcel, std::shared_ptr<IEmptyInterface>* instance) {
+  ::ndk::SpAIBinder binder;
+  binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());
+  if (status != STATUS_OK) return status;
+  *instance = IEmptyInterface::fromBinder(binder);
+  return STATUS_OK;
+}
+bool ArrayOfInterfaces::IEmptyInterface::setDefaultImpl(const std::shared_ptr<IEmptyInterface>& impl) {
+  // Only one user of this interface can use this function
+  // at a time. This is a heuristic to detect if two different
+  // users in the same process use this function.
+  assert(!IEmptyInterface::default_impl);
+  if (impl) {
+    IEmptyInterface::default_impl = impl;
+    return true;
+  }
+  return false;
+}
+const std::shared_ptr<ArrayOfInterfaces::IEmptyInterface>& ArrayOfInterfaces::IEmptyInterface::getDefaultImpl() {
+  return IEmptyInterface::default_impl;
+}
+std::shared_ptr<ArrayOfInterfaces::IEmptyInterface> ArrayOfInterfaces::IEmptyInterface::default_impl = nullptr;
+::ndk::SpAIBinder ArrayOfInterfaces::IEmptyInterfaceDefault::asBinder() {
+  return ::ndk::SpAIBinder();
+}
+bool ArrayOfInterfaces::IEmptyInterfaceDefault::isRemote() {
+  return false;
+}
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+#include <android/binder_parcel_utils.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+static binder_status_t _aidl_android_aidl_tests_ArrayOfInterfaces_IMyInterface_onTransact(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, AParcel* _aidl_out) {
+  (void)_aidl_in;
+  (void)_aidl_out;
+  binder_status_t _aidl_ret_status = STATUS_UNKNOWN_TRANSACTION;
+  std::shared_ptr<ArrayOfInterfaces::BnMyInterface> _aidl_impl = std::static_pointer_cast<ArrayOfInterfaces::BnMyInterface>(::ndk::ICInterface::asInterface(_aidl_binder));
+  switch (_aidl_code) {
+    case (FIRST_CALL_TRANSACTION + 0 /*methodWithInterfaces*/): {
+      std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface> in_iface;
+      std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface> in_nullable_iface;
+      std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>> in_iface_array_in;
+      std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>> out_iface_array_out;
+      std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>> in_iface_array_inout;
+      std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>> in_nullable_iface_array_in;
+      std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>> out_nullable_iface_array_out;
+      std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>> in_nullable_iface_array_inout;
+      std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>> _aidl_return;
+
+      _aidl_ret_status = ::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface::readFromParcel(_aidl_in, &in_iface);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface::readFromParcel(_aidl_in, &in_nullable_iface);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_iface_array_in);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_iface_array_out);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_iface_array_inout);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_nullable_iface_array_in);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_nullable_iface_array_out);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_nullable_iface_array_inout);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->methodWithInterfaces(in_iface, in_nullable_iface, in_iface_array_in, &out_iface_array_out, &in_iface_array_inout, in_nullable_iface_array_in, &out_nullable_iface_array_out, &in_nullable_iface_array_inout, &_aidl_return);
+      _aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      if (!AStatus_isOk(_aidl_status.get())) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_iface_array_out);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_iface_array_inout);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_nullable_iface_array_out);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_nullable_iface_array_inout);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+  }
+  return _aidl_ret_status;
+}
+
+static AIBinder_Class* _g_aidl_android_aidl_tests_ArrayOfInterfaces_IMyInterface_clazz = ::ndk::ICInterface::defineClass(ArrayOfInterfaces::IMyInterface::descriptor, _aidl_android_aidl_tests_ArrayOfInterfaces_IMyInterface_onTransact);
+
+ArrayOfInterfaces::BpMyInterface::BpMyInterface(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
+ArrayOfInterfaces::BpMyInterface::~BpMyInterface() {}
+
+::ndk::ScopedAStatus ArrayOfInterfaces::BpMyInterface::methodWithInterfaces(const std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& in_iface, const std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& in_nullable_iface, const std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>& in_iface_array_in, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* out_iface_array_out, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* in_iface_array_inout, const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>& in_nullable_iface_array_in, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* out_nullable_iface_array_out, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* in_nullable_iface_array_inout, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* _aidl_return) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  ::ndk::ScopedAStatus _aidl_status;
+  ::ndk::ScopedAParcel _aidl_in;
+  ::ndk::ScopedAParcel _aidl_out;
+
+  _aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface::writeToParcel(_aidl_in.get(), in_iface);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface::writeToParcel(_aidl_in.get(), in_nullable_iface);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_iface_array_in);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_iface_array_out);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_iface_array_inout);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_nullable_iface_array_in);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_nullable_iface_array_out);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_nullable_iface_array_inout);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 0 /*methodWithInterfaces*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    0
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && IMyInterface::getDefaultImpl()) {
+    _aidl_status = IMyInterface::getDefaultImpl()->methodWithInterfaces(in_iface, in_nullable_iface, in_iface_array_in, out_iface_array_out, in_iface_array_inout, in_nullable_iface_array_in, out_nullable_iface_array_out, in_nullable_iface_array_inout, _aidl_return);
+    goto _aidl_status_return;
+  }
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AParcel_readStatusHeader(_aidl_out.get(), _aidl_status.getR());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
+  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), _aidl_return);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_iface_array_out);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_iface_array_inout);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_nullable_iface_array_out);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_nullable_iface_array_inout);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_error:
+  _aidl_status.set(AStatus_fromStatus(_aidl_ret_status));
+  _aidl_status_return:
+  return _aidl_status;
+}
+// Source for BnMyInterface
+ArrayOfInterfaces::BnMyInterface::BnMyInterface() {}
+ArrayOfInterfaces::BnMyInterface::~BnMyInterface() {}
+::ndk::SpAIBinder ArrayOfInterfaces::BnMyInterface::createBinder() {
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_tests_ArrayOfInterfaces_IMyInterface_clazz, static_cast<void*>(this));
+  #ifdef BINDER_STABILITY_SUPPORT
+  AIBinder_markCompilationUnitStability(binder);
+  #endif  // BINDER_STABILITY_SUPPORT
+  return ::ndk::SpAIBinder(binder);
+}
+// Source for IMyInterface
+const char* ArrayOfInterfaces::IMyInterface::descriptor = "android.aidl.tests.ArrayOfInterfaces.IMyInterface";
+ArrayOfInterfaces::IMyInterface::IMyInterface() {}
+ArrayOfInterfaces::IMyInterface::~IMyInterface() {}
+
+
+std::shared_ptr<ArrayOfInterfaces::IMyInterface> ArrayOfInterfaces::IMyInterface::fromBinder(const ::ndk::SpAIBinder& binder) {
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_tests_ArrayOfInterfaces_IMyInterface_clazz)) { return nullptr; }
+  std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
+  if (interface) {
+    return std::static_pointer_cast<IMyInterface>(interface);
+  }
+  return ::ndk::SharedRefBase::make<ArrayOfInterfaces::BpMyInterface>(binder);
+}
+
+binder_status_t ArrayOfInterfaces::IMyInterface::writeToParcel(AParcel* parcel, const std::shared_ptr<IMyInterface>& instance) {
+  return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : nullptr);
+}
+binder_status_t ArrayOfInterfaces::IMyInterface::readFromParcel(const AParcel* parcel, std::shared_ptr<IMyInterface>* instance) {
+  ::ndk::SpAIBinder binder;
+  binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());
+  if (status != STATUS_OK) return status;
+  *instance = IMyInterface::fromBinder(binder);
+  return STATUS_OK;
+}
+bool ArrayOfInterfaces::IMyInterface::setDefaultImpl(const std::shared_ptr<IMyInterface>& impl) {
+  // Only one user of this interface can use this function
+  // at a time. This is a heuristic to detect if two different
+  // users in the same process use this function.
+  assert(!IMyInterface::default_impl);
+  if (impl) {
+    IMyInterface::default_impl = impl;
+    return true;
+  }
+  return false;
+}
+const std::shared_ptr<ArrayOfInterfaces::IMyInterface>& ArrayOfInterfaces::IMyInterface::getDefaultImpl() {
+  return IMyInterface::default_impl;
+}
+std::shared_ptr<ArrayOfInterfaces::IMyInterface> ArrayOfInterfaces::IMyInterface::default_impl = nullptr;
+::ndk::ScopedAStatus ArrayOfInterfaces::IMyInterfaceDefault::methodWithInterfaces(const std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& /*in_iface*/, const std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& /*in_nullable_iface*/, const std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>& /*in_iface_array_in*/, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* /*out_iface_array_out*/, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* /*in_iface_array_inout*/, const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>& /*in_nullable_iface_array_in*/, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* /*out_nullable_iface_array_out*/, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* /*in_nullable_iface_array_inout*/, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::SpAIBinder ArrayOfInterfaces::IMyInterfaceDefault::asBinder() {
+  return ::ndk::SpAIBinder();
+}
+bool ArrayOfInterfaces::IMyInterfaceDefault::isRemote() {
+  return false;
+}
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+#include "aidl/android/aidl/tests/ArrayOfInterfaces.h"
+
+#include <android/binder_parcel_utils.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* ArrayOfInterfaces::MyParcelable::descriptor = "android.aidl.tests.ArrayOfInterfaces.MyParcelable";
+
+binder_status_t ArrayOfInterfaces::MyParcelable::readFromParcel(const AParcel* _aidl_parcel) {
+  int32_t _aidl_parcelable_size;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  binder_status_t _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  if (_aidl_parcelable_size < 0) return STATUS_BAD_VALUE;
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
+    AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = ::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface::readFromParcel(_aidl_parcel, &iface);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
+    AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = ::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface::readFromParcel(_aidl_parcel, &nullable_iface);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
+    AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_parcel, &iface_array);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
+    AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_parcel, &nullable_iface_array);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+  return _aidl_ret_status;
+}
+binder_status_t ArrayOfInterfaces::MyParcelable::writeToParcel(AParcel* _aidl_parcel) const {
+  binder_status_t _aidl_ret_status;
+  size_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  _aidl_ret_status = AParcel_writeInt32(_aidl_parcel, 0);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface::writeToParcel(_aidl_parcel, iface);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface::writeToParcel(_aidl_parcel, nullable_iface);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_parcel, iface_array);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_parcel, nullable_iface_array);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  size_t _aidl_end_pos = AParcel_getDataPosition(_aidl_parcel);
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos);
+  AParcel_writeInt32(_aidl_parcel, _aidl_end_pos - _aidl_start_pos);
+  AParcel_setDataPosition(_aidl_parcel, _aidl_end_pos);
+  return _aidl_ret_status;
+}
+
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+#include "aidl/android/aidl/tests/ArrayOfInterfaces.h"
+
+#include <android/binder_parcel_utils.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* ArrayOfInterfaces::MyUnion::descriptor = "android.aidl.tests.ArrayOfInterfaces.MyUnion";
+
+binder_status_t ArrayOfInterfaces::MyUnion::readFromParcel(const AParcel* _parcel) {
+  binder_status_t _aidl_ret_status;
+  int32_t _aidl_tag;
+  if ((_aidl_ret_status = AParcel_readInt32(_parcel, &_aidl_tag)) != STATUS_OK) return _aidl_ret_status;
+  switch (_aidl_tag) {
+  case iface: {
+    std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface> _aidl_value;
+    if ((_aidl_ret_status = ::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface::readFromParcel(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>) {
+      set<iface>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<iface>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  case nullable_iface: {
+    std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface> _aidl_value;
+    if ((_aidl_ret_status = ::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface::readFromParcel(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>) {
+      set<nullable_iface>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<nullable_iface>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  case iface_array: {
+    std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>> _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readVector(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>) {
+      set<iface_array>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<iface_array>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  case nullable_iface_array: {
+    std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>> _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readVector(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>>) {
+      set<nullable_iface_array>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<nullable_iface_array>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  }
+  return STATUS_BAD_VALUE;
+}
+binder_status_t ArrayOfInterfaces::MyUnion::writeToParcel(AParcel* _parcel) const {
+  binder_status_t _aidl_ret_status = AParcel_writeInt32(_parcel, getTag());
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+  switch (getTag()) {
+  case iface: return ::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface::writeToParcel(_parcel, get<iface>());
+  case nullable_iface: return ::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface::writeToParcel(_parcel, get<nullable_iface>());
+  case iface_array: return ::ndk::AParcel_writeVector(_parcel, get<iface_array>());
+  case nullable_iface_array: return ::ndk::AParcel_writeVector(_parcel, get<nullable_iface_array>());
+  }
+  __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
+}
+
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp.d
new file mode 100644
index 0000000..d67076b
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/ArrayOfInterfaces.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ArrayOfInterfaces.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ArrayOfInterfaces.h
new file mode 100644
index 0000000..6e43bf0
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ArrayOfInterfaces.h
@@ -0,0 +1,279 @@
+#pragma once
+
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <variant>
+#include <vector>
+#include <android/binder_ibinder.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#include <aidl/android/aidl/tests/ArrayOfInterfaces.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+#ifndef __BIONIC__
+#define __assert2(a,b,c,d) ((void)0)
+#endif
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+class ArrayOfInterfaces {
+public:
+  typedef std::false_type fixed_size;
+  static const char* descriptor;
+
+  class IEmptyInterface : public ::ndk::ICInterface {
+  public:
+    static const char* descriptor;
+    IEmptyInterface();
+    virtual ~IEmptyInterface();
+
+
+    static std::shared_ptr<IEmptyInterface> fromBinder(const ::ndk::SpAIBinder& binder);
+    static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<IEmptyInterface>& instance);
+    static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<IEmptyInterface>* instance);
+    static bool setDefaultImpl(const std::shared_ptr<IEmptyInterface>& impl);
+    static const std::shared_ptr<IEmptyInterface>& getDefaultImpl();
+  private:
+    static std::shared_ptr<IEmptyInterface> default_impl;
+  };
+  class IEmptyInterfaceDefault : public IEmptyInterface {
+  public:
+    ::ndk::SpAIBinder asBinder() override;
+    bool isRemote() override;
+  };
+  class BpEmptyInterface : public ::ndk::BpCInterface<IEmptyInterface> {
+  public:
+    explicit BpEmptyInterface(const ::ndk::SpAIBinder& binder);
+    virtual ~BpEmptyInterface();
+
+  };
+  class BnEmptyInterface : public ::ndk::BnCInterface<IEmptyInterface> {
+  public:
+    BnEmptyInterface();
+    virtual ~BnEmptyInterface();
+  protected:
+    ::ndk::SpAIBinder createBinder() override;
+  private:
+  };
+  class IMyInterface : public ::ndk::ICInterface {
+  public:
+    static const char* descriptor;
+    IMyInterface();
+    virtual ~IMyInterface();
+
+    static constexpr uint32_t TRANSACTION_methodWithInterfaces = FIRST_CALL_TRANSACTION + 0;
+
+    static std::shared_ptr<IMyInterface> fromBinder(const ::ndk::SpAIBinder& binder);
+    static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<IMyInterface>& instance);
+    static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<IMyInterface>* instance);
+    static bool setDefaultImpl(const std::shared_ptr<IMyInterface>& impl);
+    static const std::shared_ptr<IMyInterface>& getDefaultImpl();
+    virtual ::ndk::ScopedAStatus methodWithInterfaces(const std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& in_iface, const std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& in_nullable_iface, const std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>& in_iface_array_in, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* out_iface_array_out, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* in_iface_array_inout, const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>& in_nullable_iface_array_in, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* out_nullable_iface_array_out, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* in_nullable_iface_array_inout, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* _aidl_return) = 0;
+  private:
+    static std::shared_ptr<IMyInterface> default_impl;
+  };
+  class IMyInterfaceDefault : public IMyInterface {
+  public:
+    ::ndk::ScopedAStatus methodWithInterfaces(const std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& in_iface, const std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& in_nullable_iface, const std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>& in_iface_array_in, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* out_iface_array_out, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* in_iface_array_inout, const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>& in_nullable_iface_array_in, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* out_nullable_iface_array_out, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* in_nullable_iface_array_inout, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* _aidl_return) override;
+    ::ndk::SpAIBinder asBinder() override;
+    bool isRemote() override;
+  };
+  class BpMyInterface : public ::ndk::BpCInterface<IMyInterface> {
+  public:
+    explicit BpMyInterface(const ::ndk::SpAIBinder& binder);
+    virtual ~BpMyInterface();
+
+    ::ndk::ScopedAStatus methodWithInterfaces(const std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& in_iface, const std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>& in_nullable_iface, const std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>& in_iface_array_in, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* out_iface_array_out, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>* in_iface_array_inout, const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>& in_nullable_iface_array_in, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* out_nullable_iface_array_out, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* in_nullable_iface_array_inout, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>* _aidl_return) override;
+  };
+  class BnMyInterface : public ::ndk::BnCInterface<IMyInterface> {
+  public:
+    BnMyInterface();
+    virtual ~BnMyInterface();
+  protected:
+    ::ndk::SpAIBinder createBinder() override;
+  private:
+  };
+  class MyParcelable {
+  public:
+    typedef std::false_type fixed_size;
+    static const char* descriptor;
+
+    std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface> iface;
+    std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface> nullable_iface;
+    std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>> iface_array;
+    std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>> nullable_iface_array;
+
+    binder_status_t readFromParcel(const AParcel* parcel);
+    binder_status_t writeToParcel(AParcel* parcel) const;
+
+    inline bool operator!=(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_array, nullable_iface_array) != std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_array, rhs.nullable_iface_array);
+    }
+    inline bool operator<(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_array, nullable_iface_array) < std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_array, rhs.nullable_iface_array);
+    }
+    inline bool operator<=(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_array, nullable_iface_array) <= std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_array, rhs.nullable_iface_array);
+    }
+    inline bool operator==(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_array, nullable_iface_array) == std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_array, rhs.nullable_iface_array);
+    }
+    inline bool operator>(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_array, nullable_iface_array) > std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_array, rhs.nullable_iface_array);
+    }
+    inline bool operator>=(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_array, nullable_iface_array) >= std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_array, rhs.nullable_iface_array);
+    }
+
+    static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "MyParcelable{";
+      os << "iface: " << ::android::internal::ToString(iface);
+      os << ", nullable_iface: " << ::android::internal::ToString(nullable_iface);
+      os << ", iface_array: " << ::android::internal::ToString(iface_array);
+      os << ", nullable_iface_array: " << ::android::internal::ToString(nullable_iface_array);
+      os << "}";
+      return os.str();
+    }
+  };
+  class MyUnion {
+  public:
+    typedef std::false_type fixed_size;
+    static const char* descriptor;
+
+    enum Tag : int32_t {
+      iface = 0,  // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface iface;
+      nullable_iface,  // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface nullable_iface;
+      iface_array,  // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] iface_array;
+      nullable_iface_array,  // android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] nullable_iface_array;
+    };
+
+    template<typename _Tp>
+    static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, MyUnion>;
+
+    MyUnion() : _value(std::in_place_index<iface>, std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>()) { }
+
+    template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
+    // NOLINTNEXTLINE(google-explicit-constructor)
+    constexpr MyUnion(_Tp&& _arg)
+        : _value(std::forward<_Tp>(_arg)) {}
+
+    template <size_t _Np, typename... _Tp>
+    constexpr explicit MyUnion(std::in_place_index_t<_Np>, _Tp&&... _args)
+        : _value(std::in_place_index<_Np>, std::forward<_Tp>(_args)...) {}
+
+    template <Tag _tag, typename... _Tp>
+    static MyUnion make(_Tp&&... _args) {
+      return MyUnion(std::in_place_index<_tag>, std::forward<_Tp>(_args)...);
+    }
+
+    template <Tag _tag, typename _Tp, typename... _Up>
+    static MyUnion make(std::initializer_list<_Tp> _il, _Up&&... _args) {
+      return MyUnion(std::in_place_index<_tag>, std::move(_il), std::forward<_Up>(_args)...);
+    }
+
+    Tag getTag() const {
+      return static_cast<Tag>(_value.index());
+    }
+
+    template <Tag _tag>
+    const auto& get() const {
+      if (getTag() != _tag) { __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }
+      return std::get<_tag>(_value);
+    }
+
+    template <Tag _tag>
+    auto& get() {
+      if (getTag() != _tag) { __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }
+      return std::get<_tag>(_value);
+    }
+
+    template <Tag _tag, typename... _Tp>
+    void set(_Tp&&... _args) {
+      _value.emplace<_tag>(std::forward<_Tp>(_args)...);
+    }
+
+    binder_status_t readFromParcel(const AParcel* _parcel);
+    binder_status_t writeToParcel(AParcel* _parcel) const;
+
+    inline bool operator!=(const MyUnion& rhs) const {
+      return _value != rhs._value;
+    }
+    inline bool operator<(const MyUnion& rhs) const {
+      return _value < rhs._value;
+    }
+    inline bool operator<=(const MyUnion& rhs) const {
+      return _value <= rhs._value;
+    }
+    inline bool operator==(const MyUnion& rhs) const {
+      return _value == rhs._value;
+    }
+    inline bool operator>(const MyUnion& rhs) const {
+      return _value > rhs._value;
+    }
+    inline bool operator>=(const MyUnion& rhs) const {
+      return _value >= rhs._value;
+    }
+
+    static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "MyUnion{";
+      switch (getTag()) {
+      case iface: os << "iface: " << ::android::internal::ToString(get<iface>()); break;
+      case nullable_iface: os << "nullable_iface: " << ::android::internal::ToString(get<nullable_iface>()); break;
+      case iface_array: os << "iface_array: " << ::android::internal::ToString(get<iface_array>()); break;
+      case nullable_iface_array: os << "nullable_iface_array: " << ::android::internal::ToString(get<nullable_iface_array>()); break;
+      }
+      os << "}";
+      return os.str();
+    }
+  private:
+    std::variant<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>, std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ArrayOfInterfaces::IEmptyInterface>>>> _value;
+  };
+
+  binder_status_t readFromParcel(const AParcel* parcel);
+  binder_status_t writeToParcel(AParcel* parcel) const;
+
+  inline bool operator!=(const ArrayOfInterfaces&) const {
+    return std::tie() != std::tie();
+  }
+  inline bool operator<(const ArrayOfInterfaces&) const {
+    return std::tie() < std::tie();
+  }
+  inline bool operator<=(const ArrayOfInterfaces&) const {
+    return std::tie() <= std::tie();
+  }
+  inline bool operator==(const ArrayOfInterfaces&) const {
+    return std::tie() == std::tie();
+  }
+  inline bool operator>(const ArrayOfInterfaces&) const {
+    return std::tie() > std::tie();
+  }
+  inline bool operator>=(const ArrayOfInterfaces&) const {
+    return std::tie() >= std::tie();
+  }
+
+  static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "ArrayOfInterfaces{";
+    os << "}";
+    return os.str();
+  }
+};
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnArrayOfInterfaces.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnArrayOfInterfaces.h
new file mode 100644
index 0000000..4291108
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnArrayOfInterfaces.h
@@ -0,0 +1 @@
+#error TODO(b/111362593) defined_types do not have bn classes
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpArrayOfInterfaces.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpArrayOfInterfaces.h
new file mode 100644
index 0000000..e8a0db3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpArrayOfInterfaces.h
@@ -0,0 +1 @@
+#error TODO(b/111362593) defined_types do not have bp classes
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ArrayOfInterfaces.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ArrayOfInterfaces.rs
new file mode 100644
index 0000000..0d4e879
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ArrayOfInterfaces.rs
@@ -0,0 +1,333 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#[derive(Debug)]
+pub struct ArrayOfInterfaces {
+}
+impl Default for ArrayOfInterfaces {
+  fn default() -> Self {
+    Self {
+    }
+  }
+}
+impl binder::parcel::Parcelable for ArrayOfInterfaces {
+  fn write_to_parcel(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+    parcel.sized_write(|subparcel| {
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::parcel::Parcel) -> binder::Result<()> {
+    parcel.sized_read(|subparcel| {
+      Ok(())
+    })
+  }
+}
+binder::impl_serialize_for_parcelable!(ArrayOfInterfaces);
+binder::impl_deserialize_for_parcelable!(ArrayOfInterfaces);
+impl binder::parcel::ParcelableMetadata for ArrayOfInterfaces {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.ArrayOfInterfaces" }
+}
+pub mod IEmptyInterface {
+  #![allow(non_upper_case_globals)]
+  #![allow(non_snake_case)]
+  #[allow(unused_imports)] use binder::IBinderInternal;
+  use binder::declare_binder_interface;
+  declare_binder_interface! {
+    IEmptyInterface["android.aidl.tests.ArrayOfInterfaces.IEmptyInterface"] {
+      native: BnEmptyInterface(on_transact),
+      proxy: BpEmptyInterface {
+      },
+      async: IEmptyInterfaceAsync,
+    }
+  }
+  pub trait IEmptyInterface: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.ArrayOfInterfaces.IEmptyInterface" }
+    fn getDefaultImpl() -> IEmptyInterfaceDefaultRef where Self: Sized {
+      DEFAULT_IMPL.lock().unwrap().clone()
+    }
+    fn setDefaultImpl(d: IEmptyInterfaceDefaultRef) -> IEmptyInterfaceDefaultRef where Self: Sized {
+      std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+    }
+  }
+  pub trait IEmptyInterfaceAsync<P>: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.ArrayOfInterfaces.IEmptyInterface" }
+  }
+  pub trait IEmptyInterfaceDefault: Send + Sync {
+  }
+  pub mod transactions {
+  }
+  pub type IEmptyInterfaceDefaultRef = Option<std::sync::Arc<dyn IEmptyInterfaceDefault>>;
+  use lazy_static::lazy_static;
+  lazy_static! {
+    static ref DEFAULT_IMPL: std::sync::Mutex<IEmptyInterfaceDefaultRef> = std::sync::Mutex::new(None);
+  }
+  impl BpEmptyInterface {
+  }
+  impl IEmptyInterface for BpEmptyInterface {
+  }
+  impl<P: binder::BinderAsyncPool> IEmptyInterfaceAsync<P> for BpEmptyInterface {
+  }
+  impl IEmptyInterface for binder::Binder<BnEmptyInterface> {
+  }
+  fn on_transact(_aidl_service: &dyn IEmptyInterface, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+    match _aidl_code {
+      _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+    }
+  }
+}
+pub mod IMyInterface {
+  #![allow(non_upper_case_globals)]
+  #![allow(non_snake_case)]
+  #[allow(unused_imports)] use binder::IBinderInternal;
+  use binder::declare_binder_interface;
+  declare_binder_interface! {
+    IMyInterface["android.aidl.tests.ArrayOfInterfaces.IMyInterface"] {
+      native: BnMyInterface(on_transact),
+      proxy: BpMyInterface {
+      },
+      async: IMyInterfaceAsync,
+    }
+  }
+  pub trait IMyInterface: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.ArrayOfInterfaces.IMyInterface" }
+    fn methodWithInterfaces(&self, _arg_iface: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_iface_array_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>], _arg_iface_array_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>, _arg_iface_array_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_array_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_array_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_array_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>) -> binder::public_api::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>>;
+    fn getDefaultImpl() -> IMyInterfaceDefaultRef where Self: Sized {
+      DEFAULT_IMPL.lock().unwrap().clone()
+    }
+    fn setDefaultImpl(d: IMyInterfaceDefaultRef) -> IMyInterfaceDefaultRef where Self: Sized {
+      std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+    }
+  }
+  pub trait IMyInterfaceAsync<P>: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.ArrayOfInterfaces.IMyInterface" }
+    fn methodWithInterfaces<'a>(&'a self, _arg_iface: &'a binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&'a binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_iface_array_in: &'a [binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>], _arg_iface_array_out: &'a mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>, _arg_iface_array_inout: &'a mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_array_in: Option<&'a [Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_array_out: &'a mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_array_inout: &'a mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>) -> binder::BoxFuture<'a, binder::public_api::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>>>;
+  }
+  pub trait IMyInterfaceDefault: Send + Sync {
+    fn methodWithInterfaces(&self, _arg_iface: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_iface_array_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>], _arg_iface_array_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>, _arg_iface_array_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_array_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_array_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_array_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>) -> binder::public_api::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>> {
+      Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+    }
+  }
+  pub mod transactions {
+    pub const methodWithInterfaces: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 0;
+  }
+  pub type IMyInterfaceDefaultRef = Option<std::sync::Arc<dyn IMyInterfaceDefault>>;
+  use lazy_static::lazy_static;
+  lazy_static! {
+    static ref DEFAULT_IMPL: std::sync::Mutex<IMyInterfaceDefaultRef> = std::sync::Mutex::new(None);
+  }
+  impl BpMyInterface {
+    fn build_parcel_methodWithInterfaces(&self, _arg_iface: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_iface_array_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>], _arg_iface_array_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>, _arg_iface_array_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_array_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_array_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_array_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>) -> binder::public_api::Result<binder::OwnedParcel> {
+      let mut aidl_data_owned = self.binder.prepare_transact()?;
+      let mut aidl_data = aidl_data_owned.borrowed();
+      aidl_data.write(_arg_iface)?;
+      aidl_data.write(&_arg_nullable_iface)?;
+      aidl_data.write(_arg_iface_array_in)?;
+      aidl_data.write_slice_size(Some(_arg_iface_array_out))?;
+      aidl_data.write(_arg_iface_array_inout)?;
+      aidl_data.write(&_arg_nullable_iface_array_in)?;
+      aidl_data.write_slice_size(_arg_nullable_iface_array_out.as_deref())?;
+      aidl_data.write(_arg_nullable_iface_array_inout)?;
+      Ok(aidl_data_owned)
+    }
+    fn read_response_methodWithInterfaces(&self, _arg_iface: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_iface_array_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>], _arg_iface_array_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>, _arg_iface_array_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_array_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_array_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_array_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>, _aidl_reply: binder::Result<binder::OwnedParcel>) -> binder::public_api::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>> {
+      if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+        if let Some(_aidl_default_impl) = <Self as IMyInterface>::getDefaultImpl() {
+          return _aidl_default_impl.methodWithInterfaces(_arg_iface, _arg_nullable_iface, _arg_iface_array_in, _arg_iface_array_out, _arg_iface_array_inout, _arg_nullable_iface_array_in, _arg_nullable_iface_array_out, _arg_nullable_iface_array_inout);
+        }
+      }
+      let _aidl_reply = _aidl_reply?.into_parcel();
+      let _aidl_status: binder::Status = _aidl_reply.read()?;
+      if !_aidl_status.is_ok() { return Err(_aidl_status); }
+      let _aidl_return: Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>> = _aidl_reply.read()?;
+      _aidl_reply.read_onto(_arg_iface_array_out)?;
+      _aidl_reply.read_onto(_arg_iface_array_inout)?;
+      _aidl_reply.read_onto(_arg_nullable_iface_array_out)?;
+      _aidl_reply.read_onto(_arg_nullable_iface_array_inout)?;
+      Ok(_aidl_return)
+    }
+  }
+  impl IMyInterface for BpMyInterface {
+    fn methodWithInterfaces(&self, _arg_iface: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_iface_array_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>], _arg_iface_array_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>, _arg_iface_array_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_array_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_array_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_array_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>) -> binder::public_api::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>> {
+      let _aidl_data = self.build_parcel_methodWithInterfaces(_arg_iface, _arg_nullable_iface, _arg_iface_array_in, _arg_iface_array_out, _arg_iface_array_inout, _arg_nullable_iface_array_in, _arg_nullable_iface_array_out, _arg_nullable_iface_array_inout)?;
+      let _aidl_reply = self.binder.submit_transact(transactions::methodWithInterfaces, _aidl_data, binder::FLAG_PRIVATE_LOCAL);
+      self.read_response_methodWithInterfaces(_arg_iface, _arg_nullable_iface, _arg_iface_array_in, _arg_iface_array_out, _arg_iface_array_inout, _arg_nullable_iface_array_in, _arg_nullable_iface_array_out, _arg_nullable_iface_array_inout, _aidl_reply)
+    }
+  }
+  impl<P: binder::BinderAsyncPool> IMyInterfaceAsync<P> for BpMyInterface {
+    fn methodWithInterfaces<'a>(&'a self, _arg_iface: &'a binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&'a binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_iface_array_in: &'a [binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>], _arg_iface_array_out: &'a mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>, _arg_iface_array_inout: &'a mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_array_in: Option<&'a [Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_array_out: &'a mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_array_inout: &'a mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>) -> binder::BoxFuture<'a, binder::public_api::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>>> {
+      let _aidl_data = match self.build_parcel_methodWithInterfaces(_arg_iface, _arg_nullable_iface, _arg_iface_array_in, _arg_iface_array_out, _arg_iface_array_inout, _arg_nullable_iface_array_in, _arg_nullable_iface_array_out, _arg_nullable_iface_array_inout) {
+        Ok(_aidl_data) => _aidl_data,
+        Err(err) => return Box::pin(std::future::ready(Err(err))),
+      };
+      let binder = self.binder.clone();
+      P::spawn(
+        move || binder.submit_transact(transactions::methodWithInterfaces, _aidl_data, binder::FLAG_PRIVATE_LOCAL),
+        move |_aidl_reply| async move {
+          self.read_response_methodWithInterfaces(_arg_iface, _arg_nullable_iface, _arg_iface_array_in, _arg_iface_array_out, _arg_iface_array_inout, _arg_nullable_iface_array_in, _arg_nullable_iface_array_out, _arg_nullable_iface_array_inout, _aidl_reply)
+        }
+      )
+    }
+  }
+  impl IMyInterface for binder::Binder<BnMyInterface> {
+    fn methodWithInterfaces(&self, _arg_iface: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_iface_array_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>], _arg_iface_array_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>, _arg_iface_array_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_array_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_array_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_array_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>) -> binder::public_api::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>> { self.0.methodWithInterfaces(_arg_iface, _arg_nullable_iface, _arg_iface_array_in, _arg_iface_array_out, _arg_iface_array_inout, _arg_nullable_iface_array_in, _arg_nullable_iface_array_out, _arg_nullable_iface_array_inout) }
+  }
+  fn on_transact(_aidl_service: &dyn IMyInterface, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+    match _aidl_code {
+      transactions::methodWithInterfaces => {
+        let _arg_iface: binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface> = _aidl_data.read()?;
+        let _arg_nullable_iface: Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>> = _aidl_data.read()?;
+        let _arg_iface_array_in: Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>> = _aidl_data.read()?;
+        let mut _arg_iface_array_out: Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>> = Default::default();
+        _aidl_data.resize_out_vec(&mut _arg_iface_array_out)?;
+        let mut _arg_iface_array_inout: Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>> = _aidl_data.read()?;
+        let _arg_nullable_iface_array_in: Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>> = _aidl_data.read()?;
+        let mut _arg_nullable_iface_array_out: Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>> = Default::default();
+        _aidl_data.resize_nullable_out_vec(&mut _arg_nullable_iface_array_out)?;
+        let mut _arg_nullable_iface_array_inout: Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>> = _aidl_data.read()?;
+        let _aidl_return = _aidl_service.methodWithInterfaces(&_arg_iface, _arg_nullable_iface.as_ref(), &_arg_iface_array_in, &mut _arg_iface_array_out, &mut _arg_iface_array_inout, _arg_nullable_iface_array_in.as_deref(), &mut _arg_nullable_iface_array_out, &mut _arg_nullable_iface_array_inout);
+        match &_aidl_return {
+          Ok(_aidl_return) => {
+            _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+            _aidl_reply.write(_aidl_return)?;
+            _aidl_reply.write(&_arg_iface_array_out)?;
+            _aidl_reply.write(&_arg_iface_array_inout)?;
+            _aidl_reply.write(&_arg_nullable_iface_array_out)?;
+            _aidl_reply.write(&_arg_nullable_iface_array_inout)?;
+          }
+          Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+        }
+        Ok(())
+      }
+      _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+    }
+  }
+}
+pub mod MyParcelable {
+  #[derive(Debug)]
+  pub struct MyParcelable {
+    pub iface: Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>,
+    pub nullable_iface: Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>,
+    pub iface_array: Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>,
+    pub nullable_iface_array: Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>,
+  }
+  impl Default for MyParcelable {
+    fn default() -> Self {
+      Self {
+        iface: Default::default(),
+        nullable_iface: Default::default(),
+        iface_array: Default::default(),
+        nullable_iface_array: Default::default(),
+      }
+    }
+  }
+  impl binder::parcel::Parcelable for MyParcelable {
+    fn write_to_parcel(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+      parcel.sized_write(|subparcel| {
+        let __field_ref = self.iface.as_ref().ok_or(binder::StatusCode::UNEXPECTED_NULL)?;
+        subparcel.write(__field_ref)?;
+        subparcel.write(&self.nullable_iface)?;
+        subparcel.write(&self.iface_array)?;
+        subparcel.write(&self.nullable_iface_array)?;
+        Ok(())
+      })
+    }
+    fn read_from_parcel(&mut self, parcel: &binder::parcel::Parcel) -> binder::Result<()> {
+      parcel.sized_read(|subparcel| {
+        if subparcel.has_more_data() {
+          self.iface = Some(subparcel.read()?);
+        }
+        if subparcel.has_more_data() {
+          self.nullable_iface = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.iface_array = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.nullable_iface_array = subparcel.read()?;
+        }
+        Ok(())
+      })
+    }
+  }
+  binder::impl_serialize_for_parcelable!(MyParcelable);
+  binder::impl_deserialize_for_parcelable!(MyParcelable);
+  impl binder::parcel::ParcelableMetadata for MyParcelable {
+    fn get_descriptor() -> &'static str { "android.aidl.tests.ArrayOfInterfaces.MyParcelable" }
+  }
+}
+pub mod MyUnion {
+  #[derive(Debug)]
+  pub enum MyUnion {
+    Iface(Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>),
+    Nullable_iface(Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>),
+    Iface_array(Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>),
+    Nullable_iface_array(Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>),
+  }
+  impl Default for MyUnion {
+    fn default() -> Self {
+      Self::Iface(Default::default())
+    }
+  }
+  impl binder::parcel::Parcelable for MyUnion {
+    fn write_to_parcel(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
+      match self {
+        Self::Iface(v) => {
+          parcel.write(&0i32)?;
+          let __field_ref = v.as_ref().ok_or(binder::StatusCode::UNEXPECTED_NULL)?;
+          parcel.write(__field_ref)
+        }
+        Self::Nullable_iface(v) => {
+          parcel.write(&1i32)?;
+          parcel.write(v)
+        }
+        Self::Iface_array(v) => {
+          parcel.write(&2i32)?;
+          parcel.write(v)
+        }
+        Self::Nullable_iface_array(v) => {
+          parcel.write(&3i32)?;
+          parcel.write(v)
+        }
+      }
+    }
+    fn read_from_parcel(&mut self, parcel: &binder::parcel::Parcel) -> binder::Result<()> {
+      let tag: i32 = parcel.read()?;
+      match tag {
+        0 => {
+          let value: Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>> = Some(parcel.read()?);
+          *self = Self::Iface(value);
+          Ok(())
+        }
+        1 => {
+          let value: Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>> = parcel.read()?;
+          *self = Self::Nullable_iface(value);
+          Ok(())
+        }
+        2 => {
+          let value: Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>> = parcel.read()?;
+          *self = Self::Iface_array(value);
+          Ok(())
+        }
+        3 => {
+          let value: Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>> = parcel.read()?;
+          *self = Self::Nullable_iface_array(value);
+          Ok(())
+        }
+        _ => {
+          Err(binder::StatusCode::BAD_VALUE)
+        }
+      }
+    }
+  }
+  binder::impl_serialize_for_parcelable!(MyUnion);
+  binder::impl_deserialize_for_parcelable!(MyUnion);
+  impl binder::parcel::ParcelableMetadata for MyUnion {
+    fn get_descriptor() -> &'static str { "android.aidl.tests.ArrayOfInterfaces.MyUnion" }
+  }
+}
+pub(crate) mod mangled {
+ pub use super::ArrayOfInterfaces as _7_android_4_aidl_5_tests_17_ArrayOfInterfaces;
+ pub use super::IEmptyInterface::IEmptyInterface as _7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface;
+ pub use super::IMyInterface::IMyInterface as _7_android_4_aidl_5_tests_17_ArrayOfInterfaces_12_IMyInterface;
+ pub use super::MyParcelable::MyParcelable as _7_android_4_aidl_5_tests_17_ArrayOfInterfaces_12_MyParcelable;
+ pub use super::MyUnion::MyUnion as _7_android_4_aidl_5_tests_17_ArrayOfInterfaces_7_MyUnion;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ArrayOfInterfaces.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ArrayOfInterfaces.rs.d
new file mode 100644
index 0000000..23e7dc5
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ArrayOfInterfaces.rs.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/ArrayOfInterfaces.rs : \
+  system/tools/aidl/tests/android/aidl/tests/ArrayOfInterfaces.aidl