Merge SQ1A.220205.002

Bug: 213904741
Merged-In: I7924d7b19ec30e42fd1d17ec913c4a75d51ea6bc
Change-Id: I73618ff8ee69680cdbe3b493d2c06d12f9128502
diff --git a/.clang-format b/.clang-format
new file mode 120000
index 0000000..5f196c3
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1 @@
+../../../build/soong/scripts/system-clang-format-2
\ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 077be21..dbaf05e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -87,8 +87,8 @@
         "aidl_to_rust.cpp",
         "aidl_typenames.cpp",
         "aidl.cpp",
-        "ast_cpp.cpp",
         "ast_java.cpp",
+        "check_valid.cpp",
         "code_writer.cpp",
         "comments.cpp",
         "diagnostics.cpp",
@@ -100,11 +100,12 @@
         "generate_rust.cpp",
         "import_resolver.cpp",
         "io_delegate.cpp",
-        "line_reader.cpp",
         "location.cpp",
         "logging.cpp",
         "options.cpp",
         "parser.cpp",
+        "permission.cpp",
+        "preprocess.cpp",
     ],
     yacc: {
         gen_location_hh: true,
@@ -153,7 +154,6 @@
 
     srcs: [
         "aidl_unittest.cpp",
-        "ast_cpp_unittest.cpp",
         "ast_java_unittest.cpp",
         "code_writer_unittest.cpp",
         "diagnostics_unittest.cpp",
@@ -173,6 +173,10 @@
         "liblog",
     ],
 
+    sanitize: {
+        address: true,
+    },
+
     required: ["aidl-golden-test-build-hook"],
 }
 
@@ -186,10 +190,7 @@
 
     fuzz_config: {
         cc: [
-            "devinmoore@google.com",
-            "smoreland@google.com",
-            "jiyong@google.com",
-            "jeongik@google.com",
+            "aidl-bugs@google.com",
         ],
     },
 
@@ -220,11 +221,17 @@
     test_config: "tests/aidl_integration_test.xml",
     target_required: [
         "aidl_test_client",
+        "aidl_test_client_ndk",
         "aidl_test_service",
         "aidl_test_java_client",
         "aidl_test_java_service",
         "aidl_test_rust_client",
         "aidl_test_rust_service",
+        "aidl_test_rust_service_async",
+        "aidl_test_java_client_sdk1",
+        "aidl_test_java_service_sdk1",
+        "aidl_test_java_client_sdk29",
+        "aidl_test_java_service_sdk29",
     ],
     test_suites: ["general-tests"],
     test_options: {
@@ -272,24 +279,32 @@
 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",
         "tests/android/aidl/tests/DeprecatedEnum.aidl",
         "tests/android/aidl/tests/DeprecatedParcelable.aidl",
         "tests/android/aidl/tests/GenericStructuredParcelable.aidl",
+        "tests/android/aidl/tests/FixedSize.aidl",
         "tests/android/aidl/tests/IDeprecated.aidl",
         "tests/android/aidl/tests/INamedCallback.aidl",
         "tests/android/aidl/tests/INewName.aidl",
         "tests/android/aidl/tests/IOldName.aidl",
         "tests/android/aidl/tests/ITestService.aidl",
         "tests/android/aidl/tests/IntEnum.aidl",
+        "tests/android/aidl/tests/ListOfInterfaces.aidl",
         "tests/android/aidl/tests/LongEnum.aidl",
         "tests/android/aidl/tests/OtherParcelableForToString.aidl",
         "tests/android/aidl/tests/ParcelableForToString.aidl",
+        "tests/android/aidl/tests/RecursiveList.aidl",
         "tests/android/aidl/tests/StructuredParcelable.aidl",
         "tests/android/aidl/tests/Union.aidl",
         "tests/android/aidl/tests/UnionWithFd.aidl",
+        "tests/android/aidl/tests/extension/*.aidl",
+        "tests/android/aidl/tests/nested/*.aidl",
+        "tests/android/aidl/tests/permission/IProtected.aidl",
+        "tests/android/aidl/tests/permission/IProtectedInterface.aidl",
         "tests/android/aidl/tests/unions/*.aidl",
     ],
     path: "tests",
@@ -298,9 +313,17 @@
 filegroup {
     name: "libaidl-integration-cpp-java-test-files",
     srcs: [
+        "tests/android/aidl/tests/BadParcelable.aidl",
         "tests/android/aidl/tests/ICppJavaTests.aidl",
         "tests/android/aidl/tests/SimpleParcelable.aidl",
-        "tests/android/aidl/tests/extension/*.aidl",
+    ],
+    path: "tests",
+}
+
+filegroup {
+    name: "libaidl-integration-platform-test-files",
+    srcs: [
+        "tests/android/aidl/tests/permission/platform/*.aidl",
     ],
     path: "tests",
 }
@@ -330,11 +353,14 @@
         generate_traces: true,
         export_aidl_headers: true,
         local_include_dirs: ["tests"],
-        include_dirs: ["frameworks/native/aidl/binder"],
+        include_dirs: [
+            "frameworks/native/aidl/binder",
+        ],
     },
     srcs: [
         ":libaidl-integration-test-files",
         ":libaidl-integration-cpp-java-test-files",
+        "tests/bad_parcelable.cpp",
         "tests/simple_parcelable.cpp",
     ],
 }
@@ -349,6 +375,7 @@
         // service uses the old version
         "aidl-test-versioned-interface-V1-cpp",
         "aidl_test_loggable_interface-cpp",
+        "aidl-test-fixedsizearray-cpp",
     ],
     srcs: ["tests/aidl_test_service.cpp"],
 }
@@ -362,10 +389,12 @@
         "libgmock",
         //  client uses the latest version
         "aidl-test-versioned-interface-V2-cpp",
-        "aidl_test_loggable_interface-cpp"
+        "aidl_test_loggable_interface-cpp",
+        "aidl-test-fixedsizearray-cpp",
     ],
     srcs: [
         "tests/aidl_test_client.cpp",
+        "tests/aidl_test_client_builtin_transactions.cpp",
         "tests/aidl_test_client_file_descriptors.cpp",
         "tests/aidl_test_client_parcelables.cpp",
         "tests/aidl_test_client_nullables.cpp",
@@ -373,9 +402,11 @@
         "tests/aidl_test_client_utf8_strings.cpp",
         "tests/aidl_test_client_service_exceptions.cpp",
         "tests/aidl_test_client_defaultimpl.cpp",
+        "tests/aidl_test_client_delegate.cpp",
         "tests/aidl_test_client_versioned_interface.cpp",
         "tests/aidl_test_client_renamed_interface.cpp",
         "tests/aidl_test_client_loggable_interface.cpp",
+        "tests/aidl_test_client_nested.cpp",
     ],
 }
 
@@ -386,19 +417,46 @@
         "libcutils",
         "libgmock",
         //  client uses the latest version
-        "aidl-test-versioned-interface-V2-ndk_platform",
-        "aidl-test-interface-ndk_platform",
-        "aidl_test_loggable_interface-ndk_platform"
+        "aidl-test-versioned-interface-V2-ndk",
+        "aidl-test-interface-ndk",
+        "aidl_test_loggable_interface-ndk",
+        "aidl-test-fixedsizearray-ndk",
     ],
     shared_libs: [
         "libbinder_ndk",
     ],
     srcs: [
         "tests/aidl_test_client_ndk_loggable_interface.cpp",
+        "tests/aidl_test_client_ndk_nested.cpp",
+        "tests/aidl_test_client_ndk_nullables.cpp",
+        "tests/aidl_test_client_ndk_parcelables.cpp",
+        "tests/aidl_test_client_ndk_primitives_test.cpp",
+        "tests/aidl_test_client_ndk_strings_test.cpp",
         "tests/aidl_test_client_ndk_versioned_interface.cpp",
     ],
 }
 
+aidl_interface {
+    name: "aidl-test-fixedsizearray",
+    srcs: ["tests/android/aidl/fixedsizearray/FixedSizeArrayExample.aidl"],
+    local_include_dir: "tests",
+    unstable: true,
+    backend: {
+        cpp: {
+            enabled: true,
+        },
+        java: {
+            enabled: true,
+        },
+        ndk: {
+            enabled: true,
+        },
+        rust: {
+            enabled: true,
+        },
+    }
+}
+
 java_defaults {
     name: "aidl_test_java_defaults",
     platform_apis: true,
@@ -415,6 +473,7 @@
         "aidl_test_nonvintf_parcelable-V1-java",
         "aidl_test_unstable_parcelable-java",
         "aidl_test_vintf_parcelable-V1-java",
+        "aidl-test-fixedsizearray-java",
         // TODO: remove once Android migrates to JUnit 4.12,
         // which provides assertThrows
         "testng",
@@ -425,7 +484,9 @@
         "tests/android/aidl/tests/immutable/*.aidl",
         "tests/android/aidl/tests/map/*.aidl",
         "tests/android/aidl/tests/extension/*.aidl",
+        "tests/android/aidl/tests/nested/*.aidl",
         "tests/android/aidl/tests/unions/*.aidl",
+        "tests/java/src/android/aidl/tests/BadParcelable.java",
         "tests/java/src/android/aidl/tests/SimpleParcelable.java",
         "tests/java/src/android/aidl/tests/generic/Pair.java",
     ],
@@ -444,7 +505,7 @@
     defaults: ["aidl_test_java_defaults"],
     static_libs: [
         // client uses the new version
-        "aidl-test-versioned-interface-V2-java",
+        "aidl-test-versioned-interface-V3-java",
     ],
     // tests are included in defaults
     srcs: [
@@ -452,7 +513,10 @@
         "tests/java/src/android/aidl/tests/TestServiceClient.java",
         "tests/java/src/android/aidl/tests/JavaOnlyImmutableAnnotationTests.java",
         "tests/java/src/android/aidl/tests/AidlJavaTests.java",
+        "tests/java/src/android/aidl/tests/BuiltInTests.java",
+        "tests/java/src/android/aidl/tests/DelegatorTests.java",
         "tests/java/src/android/aidl/tests/GenericTests.java",
+        "tests/java/src/android/aidl/tests/NestedTypesTests.java",
         "tests/java/src/android/aidl/tests/TestVersionedInterface.java",
         "tests/java/src/android/aidl/tests/UnionTests.java",
         "tests/java/src/android/aidl/tests/ExtensionTests.java",
@@ -473,6 +537,75 @@
     ],
 }
 
+filegroup {
+    name: "aidl-for-sdkversion-tests",
+    srcs: [
+        "tests/java/src/android/aidl/sdkversion/ITestService.aidl",
+    ],
+    path: "tests/java/src",
+}
+
+java_defaults {
+    name: "aidl_test_java_sdkversion_defaults",
+    platform_apis: true,
+    // Turn off Java optimization tools to speed up our test iterations.
+    optimize: {
+        enabled: false,
+    },
+    dex_preopt: {
+        enabled: false,
+    },
+    static_libs: [
+        "androidx.test.core",
+        "androidx.test.runner",
+    ],
+    srcs: [
+        ":aidl-for-sdkversion-tests",
+    ],
+    aidl: {
+        include_dirs: [
+            "frameworks/native/aidl/binder",
+        ],
+    },
+    test_suites: ["general-tests"],
+}
+
+java_test {
+    name: "aidl_test_java_client_sdk29",
+    defaults: ["aidl_test_java_sdkversion_defaults"],
+    min_sdk_version: "29",
+    srcs: [
+        "tests/java/src/android/aidl/sdkversion/tests/*.java",
+    ],
+}
+
+java_test {
+    name: "aidl_test_java_service_sdk29",
+    defaults: ["aidl_test_java_sdkversion_defaults"],
+    min_sdk_version: "29",
+    srcs: [
+        "tests/java/src/android/aidl/sdkversion/service/*.java",
+    ],
+}
+
+java_test {
+    name: "aidl_test_java_client_sdk1",
+    defaults: ["aidl_test_java_sdkversion_defaults"],
+    min_sdk_version: "1",
+    srcs: [
+        "tests/java/src/android/aidl/sdkversion/tests/*.java",
+    ],
+}
+
+java_test {
+    name: "aidl_test_java_service_sdk1",
+    defaults: ["aidl_test_java_sdkversion_defaults"],
+    min_sdk_version: "1",
+    srcs: [
+        "tests/java/src/android/aidl/sdkversion/service/*.java",
+    ],
+}
+
 //
 // "Golden" test of compiler output
 //
@@ -486,17 +619,22 @@
     name: "aidl-golden-test-build-hook-gen",
     tools: ["aidl-golden-test"],
     cmd: "$(location aidl-golden-test) check && " +
-         "echo 'int main(){return 0;}' > $(genDir)/TODO_b_37575883.cpp",
+        "echo 'int main(){return 0;}' > $(genDir)/TODO_b_37575883.cpp",
     srcs: [
         // warning: keep this list up to date with tests/golden_test.sh
         ":aidl-test-interface-cpp-source",
         ":aidl-test-interface-java-source",
-        ":aidl-test-interface-ndk_platform-source",
+        ":aidl-test-versioned-interface-V2-java-source",
+        ":aidl-test-interface-ndk-source",
         ":aidl-test-interface-rust-source",
         ":aidl_test_loggable_interface-cpp-source",
         ":aidl_test_loggable_interface-java-source",
-        ":aidl_test_loggable_interface-ndk_platform-source",
         ":aidl_test_loggable_interface-ndk-source",
+        ":aidl-test-interface-platform-java-source",
+        ":aidl-test-fixedsizearray-cpp-source",
+        ":aidl-test-fixedsizearray-java-source",
+        ":aidl-test-fixedsizearray-ndk-source",
+        ":aidl-test-fixedsizearray-rust-source",
         "tests/golden_output/**/*",
     ],
     out: ["TODO_b_37575883.cpp"],
@@ -526,24 +664,17 @@
     gen_trace: true,
     backend: {
         cpp: {
-            srcs_available: true,
             gen_log: true,
         },
         ndk: {
-            srcs_available: true,
             gen_log: true,
         },
         java: {
-            srcs_available: true,
             platform_apis: true,
         },
     },
 }
 
-//
-// Rust tests
-//
-
 aidl_interface {
     name: "aidl-test-interface",
     unstable: true,
@@ -552,23 +683,49 @@
     local_include_dir: "tests",
     backend: {
         cpp: {
-            srcs_available: true,
         },
         java: {
             platform_apis: true,
-            srcs_available: true,
+            gen_rpc: true,
         },
         rust: {
             enabled: true,
-            srcs_available: true,
         },
         ndk: {
             apps_enabled: false,
-            srcs_available: true,
         },
     },
 }
 
+aidl_interface {
+    name: "aidl-test-interface-platform",
+    unstable: true,
+    flags: ["-Werror"],
+    srcs: [":libaidl-integration-platform-test-files"],
+    include_dirs: [
+        "frameworks/base/core/java",
+    ],
+    local_include_dir: "tests",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            platform_apis: true,
+        },
+        rust: {
+            enabled: false,
+        },
+        ndk: {
+            enabled: false,
+        },
+    },
+}
+
+//
+// Rust tests
+//
+
 rust_test {
     name: "aidl_test_rust_client",
     srcs: [
@@ -577,7 +734,15 @@
     rustlibs: [
         "aidl-test-interface-rust",
         "aidl-test-versioned-interface-V2-rust",
+        "aidl_test_nonvintf_parcelable-V1-rust",
+        "aidl_test_unstable_parcelable-rust",
+        "aidl_test_vintf_parcelable-V1-rust",
+        "aidl-test-fixedsizearray-rust",
         "liblibc",
+        // We need to import binder_rs directly
+        // for a few internal types like Parcel
+        // and traits like Parcelable
+        "libbinder_rs",
     ],
     prefer_rlib: true,
     compile_multilib: "both",
@@ -601,6 +766,7 @@
     rustlibs: [
         "aidl-test-interface-rust",
         "aidl-test-versioned-interface-V1-rust",
+        "aidl-test-fixedsizearray-rust",
         "liblibc",
     ],
     prefer_rlib: true,
@@ -615,3 +781,30 @@
     },
     test_suites: ["general-tests"],
 }
+
+rust_test {
+    name: "aidl_test_rust_service_async",
+    test_harness: false,
+    srcs: [
+        "tests/rust/test_service_async.rs",
+    ],
+    rustlibs: [
+        "aidl-test-interface-rust",
+        "aidl-test-versioned-interface-V1-rust",
+        "liblibc",
+        "libbinder_tokio_rs",
+        "libtokio",
+    ],
+    proc_macros: ["libasync_trait"],
+    prefer_rlib: true,
+    compile_multilib: "both",
+    multilib: {
+        lib32: {
+            suffix: "32",
+        },
+        lib64: {
+            suffix: "64",
+        },
+    },
+    test_suites: ["general-tests"],
+}
diff --git a/OWNERS b/OWNERS
index fc45550..cc35b11 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,5 +1,6 @@
 elsk@google.com
 jiyong@google.com
+jooyung@google.com
 malchev@google.com
 sadmac@google.com
 smoreland@google.com
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 12545e1..0114731 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -5,3 +5,7 @@
 clang_format = true
 gofmt = true
 aidl_format = true
+rustfmt = true
+
+[Builtin Hooks Options]
+rustfmt = --config-path=rustfmt.toml
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 6b29745..79f49e2 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -7,10 +7,15 @@
       "name": "aidl_integration_test"
     },
     {
-      "name": "CtsNdkBinderTestCases"
+      "name": "aidl_lazy_test"
     },
     {
-      "name": "aidl_lazy_test"
+      "name": "CtsNdkBinderTestCases"
+    }
+  ],
+  "imports": [
+    {
+      "path": "frameworks/native/libs/binder"
     }
   ]
 }
diff --git a/aidl-format.sh b/aidl-format.sh
index 4f2a104..dbf3e2a 100755
--- a/aidl-format.sh
+++ b/aidl-format.sh
@@ -106,7 +106,7 @@
       # "a = 1, b = 2" would match only once and will become "a = 1, b=2".
       gawk -i inplace \
         '/@[^@]+\(.*=.*\)/ { # matches a line having @anno(param = val) \
-              print(gensub(/([^@,=]+) = ([^@,=]+)/, "\\1=\\2", "g", $0)); \
+              print(gensub(/([^@,=]+) = ([^@,=]+|"[^"]*")/, "\\1=\\2", "g", $0)); \
               done=1;\
         } \
         {if (!done) {print($0);} done=0;}' "$1"
diff --git a/aidl.cpp b/aidl.cpp
index 77c5f31..fd63c6a 100644
--- a/aidl.cpp
+++ b/aidl.cpp
@@ -40,6 +40,7 @@
 #include "aidl_dumpapi.h"
 #include "aidl_language.h"
 #include "aidl_typenames.h"
+#include "check_valid.h"
 #include "generate_aidl_mappings.h"
 #include "generate_cpp.h"
 #include "generate_java.h"
@@ -50,6 +51,7 @@
 #include "options.h"
 #include "os.h"
 #include "parser.h"
+#include "preprocess.h"
 
 #ifndef O_BINARY
 #  define O_BINARY  0
@@ -250,7 +252,7 @@
   return result;
 }
 
-bool check_and_assign_method_ids(const std::vector<std::unique_ptr<AidlMethod>>& items) {
+bool CheckAndAssignMethodIDs(const std::vector<std::unique_ptr<AidlMethod>>& items) {
   // Check whether there are any methods with manually assigned id's and any
   // that are not. Either all method id's must be manually assigned or all of
   // them must not. Also, check for uplicates of user set ID's and that the
@@ -302,58 +304,13 @@
   return true;
 }
 
-// TODO: Remove this in favor of using the YACC parser b/25479378
-bool ParsePreprocessedLine(const string& line, string* decl, std::string* package,
-                           string* class_name) {
-  // erase all trailing whitespace and semicolons
-  const size_t end = line.find_last_not_of(" ;\t");
-  if (end == string::npos) {
-    return false;
-  }
-  if (line.rfind(';', end) != string::npos) {
-    return false;
-  }
-
-  decl->clear();
-  string type;
-  vector<string> pieces = Split(line.substr(0, end + 1), " \t");
-  for (const string& piece : pieces) {
-    if (piece.empty()) {
-      continue;
-    }
-    if (decl->empty()) {
-      *decl = std::move(piece);
-    } else if (type.empty()) {
-      type = std::move(piece);
-    } else {
-      return false;
-    }
-  }
-
-  // Note that this logic is absolutely wrong.  Given a parcelable
-  // org.some.Foo.Bar, the class name is Foo.Bar, but this code will claim that
-  // the class is just Bar.  However, this was the way it was done in the past.
-  //
-  // See b/17415692
-  size_t dot_pos = type.rfind('.');
-  if (dot_pos != string::npos) {
-    *class_name = type.substr(dot_pos + 1);
-    *package = type.substr(0, dot_pos);
-  } else {
-    *class_name = type;
-    package->clear();
-  }
-
-  return true;
-}
-
 bool ValidateAnnotationContext(const AidlDocument& doc) {
   struct AnnotationValidator : AidlVisitor {
     bool success = true;
 
     void Check(const AidlAnnotatable& annotatable, AidlAnnotation::TargetContext context) {
       for (const auto& annot : annotatable.GetAnnotations()) {
-        if (!annot.CheckContext(context)) {
+        if (!annot->CheckContext(context)) {
           success = false;
         }
       }
@@ -398,69 +355,38 @@
   return validator.success;
 }
 
+bool ValidateCppHeader(const AidlDocument& doc) {
+  struct CppHeaderVisitor : AidlVisitor {
+    bool success = true;
+    void Visit(const AidlParcelable& p) override {
+      if (p.GetCppHeader().empty()) {
+        AIDL_ERROR(p) << "Unstructured parcelable \"" << p.GetName()
+                      << "\" must have C++ header defined.";
+        success = false;
+      }
+    }
+    void Visit(const AidlTypeSpecifier& m) override {
+      auto type = m.GetDefinedType();
+      if (type) {
+        auto unstructured = type->AsUnstructuredParcelable();
+        if (unstructured && unstructured->GetCppHeader().empty()) {
+          AIDL_ERROR(m) << "Unstructured parcelable \"" << m.GetUnresolvedName()
+                        << "\" must have C++ header defined.";
+          success = false;
+        }
+      }
+    }
+  };
+
+  CppHeaderVisitor validator;
+  VisitTopDown(validator, doc);
+  return validator.success;
+}
+
 }  // namespace
 
 namespace internals {
 
-bool parse_preprocessed_file(const IoDelegate& io_delegate, const string& filename,
-                             AidlTypenames* typenames) {
-  bool success = true;
-  unique_ptr<LineReader> line_reader = io_delegate.GetLineReader(filename);
-  if (!line_reader) {
-    AIDL_ERROR(filename) << "cannot open preprocessed file";
-    success = false;
-    return success;
-  }
-
-  string line;
-  int lineno = 1;
-  for ( ; line_reader->ReadLine(&line); ++lineno) {
-    if (line.empty() || line.compare(0, 2, "//") == 0) {
-      // skip comments and empty lines
-      continue;
-    }
-
-    string decl;
-    std::string package;
-    string class_name;
-    if (!ParsePreprocessedLine(line, &decl, &package, &class_name)) {
-      success = false;
-      break;
-    }
-
-    AidlLocation::Point point = {.line = lineno, .column = 0 /*column*/};
-    AidlLocation location = AidlLocation(filename, point, point, AidlLocation::Source::EXTERNAL);
-
-    if (decl == "parcelable") {
-      // ParcelFileDescriptor is treated as a built-in type, but it's also in the framework.aidl.
-      // So aidl should ignore built-in types in framework.aidl to prevent duplication.
-      // (b/130899491)
-      if (AidlTypenames::IsBuiltinTypename(class_name)) {
-        continue;
-      }
-      AidlParcelable* doc = new AidlParcelable(location, class_name, package, Comments{});
-      typenames->AddPreprocessedType(unique_ptr<AidlParcelable>(doc));
-    } else if (decl == "structured_parcelable") {
-      AidlStructuredParcelable* doc =
-          new AidlStructuredParcelable(location, class_name, package, Comments{}, nullptr, nullptr);
-      typenames->AddPreprocessedType(unique_ptr<AidlStructuredParcelable>(doc));
-    } else if (decl == "interface") {
-      AidlInterface* doc =
-          new AidlInterface(location, class_name, Comments{}, false, package, nullptr);
-      typenames->AddPreprocessedType(unique_ptr<AidlInterface>(doc));
-    } else {
-      success = false;
-      break;
-    }
-  }
-  if (!success) {
-    AIDL_ERROR(filename) << " on line " << lineno << " malformed preprocessed file line: '" << line
-                         << "'";
-  }
-
-  return success;
-}
-
 AidlError load_and_validate_aidl(const std::string& input_file_name, const Options& options,
                                  const IoDelegate& io_delegate, AidlTypenames* typenames,
                                  vector<string>* imported_files) {
@@ -471,12 +397,12 @@
   //////////////////////////////////////////////////////////////////////////
 
   // Parse the main input file
-  std::unique_ptr<Parser> main_parser = Parser::Parse(input_file_name, io_delegate, *typenames);
-  if (main_parser == nullptr) {
+  const AidlDocument* document = Parser::Parse(input_file_name, io_delegate, *typenames);
+  if (document == nullptr) {
     return AidlError::PARSE_ERROR;
   }
   int num_top_level_decls = 0;
-  for (const auto& type : main_parser->ParsedDocument().DefinedTypes()) {
+  for (const auto& type : document->DefinedTypes()) {
     if (type->AsUnstructuredParcelable() == nullptr) {
       num_top_level_decls++;
       if (num_top_level_decls > 1) {
@@ -487,45 +413,34 @@
   }
 
   // Import the preprocessed file
-  for (const string& s : options.PreprocessedFiles()) {
-    if (!parse_preprocessed_file(io_delegate, s, typenames)) {
-      err = AidlError::BAD_PRE_PROCESSED_FILE;
+  for (const string& filename : options.PreprocessedFiles()) {
+    auto preprocessed = Parser::Parse(filename, io_delegate, *typenames, /*is_preprocessed=*/true);
+    if (!preprocessed) {
+      return AidlError::BAD_PRE_PROCESSED_FILE;
     }
   }
-  if (err != AidlError::OK) {
-    return err;
-  }
 
   // Find files to import and parse them
   vector<string> import_paths;
-  ImportResolver import_resolver{io_delegate, input_file_name, options.ImportDirs(),
-                                 options.InputFiles()};
-  for (const auto& import : main_parser->ParsedDocument().Imports()) {
-    if (AidlTypenames::IsBuiltinTypename(import->GetNeededClass())) {
-      continue;
-    }
-    if (typenames->IsIgnorableImport(import->GetNeededClass())) {
+  ImportResolver import_resolver{io_delegate, input_file_name, options.ImportDirs()};
+  for (const auto& import : document->Imports()) {
+    if (typenames->IsIgnorableImport(import)) {
       // There are places in the Android tree where an import doesn't resolve,
       // but we'll pick the type up through the preprocessed types.
       // This seems like an error, but legacy support demands we support it...
       continue;
     }
-    string import_path = import_resolver.FindImportFile(import->GetNeededClass());
+    string import_path = import_resolver.FindImportFile(import);
     if (import_path.empty()) {
-      if (typenames->ResolveTypename(import->GetNeededClass()).is_resolved) {
-        // This could happen when the type is from the preprocessed aidl file.
-        // In that case, use the type from preprocessed aidl file
-        continue;
-      }
-      AIDL_ERROR(input_file_name) << "Couldn't find import for class " << import->GetNeededClass();
+      AIDL_ERROR(input_file_name) << "Couldn't find import for class " << import;
       err = AidlError::BAD_IMPORT;
       continue;
     }
 
     import_paths.emplace_back(import_path);
 
-    std::unique_ptr<Parser> import_parser = Parser::Parse(import_path, io_delegate, *typenames);
-    if (import_parser == nullptr) {
+    auto imported_doc = Parser::Parse(import_path, io_delegate, *typenames);
+    if (imported_doc == nullptr) {
       AIDL_ERROR(import_path) << "error while importing " << import_path << " for " << import;
       err = AidlError::BAD_IMPORT;
       continue;
@@ -535,52 +450,32 @@
     return err;
   }
 
-  for (const auto& imported_file : options.ImportFiles()) {
-    import_paths.emplace_back(imported_file);
-
-    std::unique_ptr<Parser> import_parser = Parser::Parse(imported_file, io_delegate, *typenames);
-    if (import_parser == nullptr) {
-      AIDL_ERROR(imported_file) << "error while importing " << imported_file;
-      err = AidlError::BAD_IMPORT;
-      continue;
+  TypeResolver resolver = [&](const AidlDefinedType* scope, AidlTypeSpecifier* type) {
+    // resolve with already loaded types
+    if (type->Resolve(*typenames, scope)) {
+      return true;
     }
-  }
-  if (err != AidlError::OK) {
-    return err;
-  }
-
-  TypeResolver resolver = [&](const AidlDocument* doc, AidlTypeSpecifier* type) {
-    if (type->Resolve(*typenames)) return true;
-
-    const string unresolved_name = type->GetUnresolvedName();
-    const std::optional<string> canonical_name = doc->ResolveName(unresolved_name);
-    if (!canonical_name) {
-      return false;
-    }
-    const string import_path = import_resolver.FindImportFile(*canonical_name);
+    const string import_path = import_resolver.FindImportFile(scope->ResolveName(type->GetName()));
     if (import_path.empty()) {
       return false;
     }
     import_paths.push_back(import_path);
-
-    std::unique_ptr<Parser> import_parser = Parser::Parse(import_path, io_delegate, *typenames);
-    if (import_parser == nullptr) {
+    auto imported_doc = Parser::Parse(import_path, io_delegate, *typenames);
+    if (imported_doc == nullptr) {
       AIDL_ERROR(import_path) << "error while importing " << import_path << " for " << import_path;
       return false;
     }
-    if (!type->Resolve(*typenames)) {
+
+    // now, try to resolve it again
+    if (!type->Resolve(*typenames, scope)) {
       AIDL_ERROR(type) << "Can't resolve " << type->GetName();
       return false;
     }
     return true;
   };
-  const bool is_check_api = options.GetTask() == Options::Task::CHECK_API;
-  const bool is_dump_api = options.GetTask() == Options::Task::DUMP_API;
 
-  // Resolve the unresolved type references found from the input file
-  if (!is_check_api && !main_parser->Resolve(resolver)) {
-    // Resolution is not need for check api because all typespecs are
-    // using fully qualified names.
+  // Resolve the unresolved references
+  if (!ResolveReferences(*document, resolver)) {
     return AidlError::BAD_TYPE;
   }
 
@@ -592,16 +487,10 @@
   // Validation phase
   //////////////////////////////////////////////////////////////////////////
 
-  // For legacy reasons, by default, compiling an unstructured parcelable (which contains no output)
-  // is allowed. This must not be returned as an error until the very end of this procedure since
-  // this may be considered a success, and we should first check that there are not other, more
-  // serious failures.
-  bool contains_unstructured_parcelable = false;
-
-  const auto& types = main_parser->ParsedDocument().DefinedTypes();
+  const auto& types = document->DefinedTypes();
   const int num_defined_types = types.size();
   for (const auto& defined_type : types) {
-    AIDL_FATAL_IF(defined_type == nullptr, main_parser->FileName());
+    AIDL_FATAL_IF(defined_type == nullptr, document);
 
     // Ensure type is exactly one of the following:
     AidlInterface* interface = defined_type->AsInterface();
@@ -621,17 +510,12 @@
     {
       bool valid_type = true;
 
-      if (!is_check_api) {
-        // Ideally, we could do this for check api, but we can't resolve imports
-        if (!defined_type->CheckValid(*typenames)) {
-          valid_type = false;
-        }
+      if (!defined_type->CheckValid(*typenames)) {
+        valid_type = false;
       }
 
-      if (!is_dump_api && !is_check_api) {
-        if (!defined_type->LanguageSpecificCheckValid(*typenames, options.TargetLanguage())) {
-          valid_type = false;
-        }
+      if (!defined_type->LanguageSpecificCheckValid(options.TargetLanguage())) {
+        valid_type = false;
       }
 
       if (!valid_type) {
@@ -640,21 +524,21 @@
     }
 
     if (unstructured_parcelable != nullptr) {
-      bool isStable = unstructured_parcelable->IsStableApiParcelable(options.TargetLanguage());
+      auto lang = options.TargetLanguage();
+      bool isStable = unstructured_parcelable->IsStableApiParcelable(lang);
       if (options.IsStructured() && !isStable) {
         AIDL_ERROR(unstructured_parcelable)
-            << "Cannot declared parcelable in a --structured interface. Parcelable must be defined "
-               "in AIDL directly.";
+            << "Cannot declare unstructured parcelable in a --structured interface. Parcelable "
+               "must be defined in AIDL directly.";
         return AidlError::NOT_STRUCTURED;
       }
-      if (options.FailOnParcelable()) {
+      if (options.FailOnParcelable() || lang == Options::Language::NDK ||
+          lang == Options::Language::RUST) {
         AIDL_ERROR(unstructured_parcelable)
             << "Refusing to generate code with unstructured parcelables. Declared parcelables "
                "should be in their own file and/or cannot be used with --structured interfaces.";
-        // Continue parsing for more errors
+        return AidlError::FOUND_PARCELABLE;
       }
-
-      contains_unstructured_parcelable = true;
     }
 
     if (defined_type->IsVintfStability()) {
@@ -672,58 +556,78 @@
       if (!success) return AidlError::NOT_STRUCTURED;
     }
 
+    // Verify the var/const declarations.
+    // const expressions should be non-empty when evaluated with the var/const type.
+    for (const auto& constant : defined_type->GetConstantDeclarations()) {
+      if (constant->ValueString(AidlConstantValueDecorator).empty()) {
+        return AidlError::BAD_TYPE;
+      }
+    }
+    for (const auto& var : defined_type->GetFields()) {
+      if (var->GetDefaultValue() && var->ValueString(AidlConstantValueDecorator).empty()) {
+        return AidlError::BAD_TYPE;
+      }
+    }
+  }
+
+  // Add meta methods and assign method IDs to each interface
+  typenames->IterateTypes([&](const AidlDefinedType& type) {
+    auto interface = const_cast<AidlInterface*>(type.AsInterface());
     if (interface != nullptr) {
       // add the meta-method 'int getInterfaceVersion()' if version is specified.
       if (options.Version() > 0) {
-        AidlTypeSpecifier* ret =
-            new AidlTypeSpecifier(AIDL_LOCATION_HERE, "int", false, nullptr, Comments{});
-        ret->Resolve(*typenames);
+        auto ret = typenames->MakeResolvedType(AIDL_LOCATION_HERE, "int", false);
         vector<unique_ptr<AidlArgument>>* args = new vector<unique_ptr<AidlArgument>>();
         auto method = std::make_unique<AidlMethod>(
-            AIDL_LOCATION_HERE, false, ret, "getInterfaceVersion", args, Comments{},
+            AIDL_LOCATION_HERE, false, ret.release(), "getInterfaceVersion", args, Comments{},
             kGetInterfaceVersionId, false /* is_user_defined */);
         interface->AddMethod(std::move(method));
       }
       // add the meta-method 'string getInterfaceHash()' if hash is specified.
       if (!options.Hash().empty()) {
-        AidlTypeSpecifier* ret =
-            new AidlTypeSpecifier(AIDL_LOCATION_HERE, "String", false, nullptr, Comments{});
-        ret->Resolve(*typenames);
+        auto ret = typenames->MakeResolvedType(AIDL_LOCATION_HERE, "String", false);
         vector<unique_ptr<AidlArgument>>* args = new vector<unique_ptr<AidlArgument>>();
         auto method = std::make_unique<AidlMethod>(
-            AIDL_LOCATION_HERE, false, ret, kGetInterfaceHash, args, Comments{},
+            AIDL_LOCATION_HERE, false, ret.release(), kGetInterfaceHash, args, Comments{},
             kGetInterfaceHashId, false /* is_user_defined */);
         interface->AddMethod(std::move(method));
       }
-      if (!check_and_assign_method_ids(interface->GetMethods())) {
-        return AidlError::BAD_METHOD_ID;
+      if (!CheckAndAssignMethodIDs(interface->GetMethods())) {
+        err = AidlError::BAD_METHOD_ID;
       }
     }
-    // Verify the var/const declarations.
-    // const expressions should be non-empty when evaluated with the var/const type.
-    if (!is_check_api) {
-      for (const auto& constant : defined_type->GetConstantDeclarations()) {
-        if (constant->ValueString(AidlConstantValueDecorator).empty()) {
-          return AidlError::BAD_TYPE;
-        }
-      }
-      for (const auto& var : defined_type->GetFields()) {
-        if (var->GetDefaultValue() && var->ValueString(AidlConstantValueDecorator).empty()) {
-          return AidlError::BAD_TYPE;
-        }
-      }
-    }
+  });
+  if (err != AidlError::OK) {
+    return err;
   }
 
-  if (!ValidateAnnotationContext(main_parser->ParsedDocument())) {
+  for (const auto& doc : typenames->AllDocuments()) {
+    VisitTopDown([](const AidlNode& n) { n.MarkVisited(); }, *doc);
+  }
+
+  if (!CheckValid(*document, options)) {
     return AidlError::BAD_TYPE;
   }
 
-  if (!is_check_api && !Diagnose(main_parser->ParsedDocument(), options.GetDiagnosticMapping())) {
+  if (!ValidateAnnotationContext(*document)) {
+    return AidlError::BAD_TYPE;
+  }
+
+  if ((options.TargetLanguage() == Options::Language::CPP ||
+       options.TargetLanguage() == Options::Language::NDK) &&
+      !ValidateCppHeader(*document)) {
+    return AidlError::BAD_TYPE;
+  }
+
+  if (!Diagnose(*document, options.GetDiagnosticMapping())) {
     return AidlError::BAD_TYPE;
   }
 
   typenames->IterateTypes([&](const AidlDefinedType& type) {
+    if (!type.LanguageSpecificCheckValid(options.TargetLanguage())) {
+      err = AidlError::BAD_TYPE;
+    }
+
     if (options.IsStructured() && type.AsUnstructuredParcelable() != nullptr &&
         !type.AsUnstructuredParcelable()->IsStableApiParcelable(options.TargetLanguage())) {
       err = AidlError::NOT_STRUCTURED;
@@ -777,17 +681,12 @@
     *imported_files = import_paths;
   }
 
-  if (contains_unstructured_parcelable) {
-    // Considered a success for the legacy case, so this must be returned last.
-    return AidlError::FOUND_PARCELABLE;
-  }
-
   return AidlError::OK;
 }
 
 } // namespace internals
 
-int compile_aidl(const Options& options, const IoDelegate& io_delegate) {
+bool compile_aidl(const Options& options, const IoDelegate& io_delegate) {
   const Options::Language lang = options.TargetLanguage();
   for (const string& input_file : options.InputFiles()) {
     AidlTypenames typenames;
@@ -796,9 +695,8 @@
 
     AidlError aidl_err = internals::load_and_validate_aidl(input_file, options, io_delegate,
                                                            &typenames, &imported_files);
-    bool allowError = aidl_err == AidlError::FOUND_PARCELABLE && !options.FailOnParcelable();
-    if (aidl_err != AidlError::OK && !allowError) {
-      return 1;
+    if (aidl_err != AidlError::OK) {
+      return false;
     }
 
     for (const auto& defined_type : typenames.MainDocument().DefinedTypes()) {
@@ -809,13 +707,13 @@
       if (output_file_name.empty() && !options.OutputDir().empty()) {
         output_file_name = GetOutputFilePath(options, *defined_type);
         if (output_file_name.empty()) {
-          return 1;
+          return false;
         }
       }
 
       if (!write_dep_file(options, *defined_type, imported_files, io_delegate, input_file,
                           output_file_name)) {
-        return 1;
+        return false;
       }
 
       bool success = false;
@@ -830,21 +728,21 @@
           // Legacy behavior. For parcelable declarations in Java, don't generate output file.
           success = true;
         } else {
-          success = java::generate_java(output_file_name, defined_type.get(), typenames,
-                                        io_delegate, options);
+          java::GenerateJava(output_file_name, options, typenames, *defined_type, io_delegate);
+          success = true;
         }
       } else if (lang == Options::Language::RUST) {
-        success = rust::GenerateRust(output_file_name, defined_type.get(), typenames, io_delegate,
-                                     options);
+        rust::GenerateRust(output_file_name, options, typenames, *defined_type, io_delegate);
+        success = true;
       } else {
         AIDL_FATAL(input_file) << "Should not reach here.";
       }
       if (!success) {
-        return 1;
+        return false;
       }
     }
   }
-  return 0;
+  return true;
 }
 
 bool dump_mappings(const Options& options, const IoDelegate& io_delegate) {
@@ -859,7 +757,7 @@
       return false;
     }
     for (const auto& defined_type : typenames.MainDocument().DefinedTypes()) {
-      auto mappings = mappings::generate_mappings(defined_type.get(), typenames);
+      auto mappings = mappings::generate_mappings(defined_type.get());
       all_mappings.insert(mappings.begin(), mappings.end());
     }
   }
@@ -872,58 +770,56 @@
   return true;
 }
 
-bool preprocess_aidl(const Options& options, const IoDelegate& io_delegate) {
-  unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(options.OutputFile());
+int aidl_entry(const Options& options, const IoDelegate& io_delegate) {
+  AidlErrorLog::clearError();
+  AidlNode::ClearUnvisitedNodes();
 
-  for (const auto& file : options.InputFiles()) {
-    AidlTypenames typenames;
-    std::unique_ptr<Parser> p = Parser::Parse(file, io_delegate, typenames);
-    if (p == nullptr) return false;
+  bool success = false;
+  if (options.Ok()) {
+    switch (options.GetTask()) {
+      case Options::Task::HELP:
+        success = true;
+        break;
+      case Options::Task::COMPILE:
+        success = android::aidl::compile_aidl(options, io_delegate);
+        break;
+      case Options::Task::PREPROCESS:
+        success = android::aidl::Preprocess(options, io_delegate);
+        break;
+      case Options::Task::DUMP_API:
+        success = android::aidl::dump_api(options, io_delegate);
+        break;
+      case Options::Task::CHECK_API:
+        success = android::aidl::check_api(options, io_delegate);
+        break;
+      case Options::Task::DUMP_MAPPINGS:
+        success = android::aidl::dump_mappings(options, io_delegate);
+        break;
+      default:
+        AIDL_FATAL(AIDL_LOCATION_HERE)
+            << "Unrecognized task: " << static_cast<size_t>(options.GetTask());
+    }
+  } else {
+    AIDL_ERROR(options.GetErrorMessage()) << options.GetUsage();
+  }
 
-    for (const auto& defined_type : p->ParsedDocument().DefinedTypes()) {
-      if (!writer->Write("%s %s;\n", defined_type->GetPreprocessDeclarationName().c_str(),
-                         defined_type->GetCanonicalName().c_str())) {
-        return false;
+  const bool reportedError = AidlErrorLog::hadError();
+  AIDL_FATAL_IF(success == reportedError, AIDL_LOCATION_HERE)
+      << "Compiler returned success " << success << " but did" << (reportedError ? "" : " not")
+      << " emit error logs";
+
+  if (success) {
+    auto locations = AidlNode::GetLocationsOfUnvisitedNodes();
+    if (!locations.empty()) {
+      for (const auto& location : locations) {
+        AIDL_ERROR(location) << "AidlNode at location was not visited!";
       }
+      AIDL_FATAL(AIDL_LOCATION_HERE)
+          << "The AIDL AST was not processed fully. Please report an issue.";
     }
   }
 
-  return writer->Close();
-}
-
-int aidl_entry(const Options& options, const IoDelegate& io_delegate) {
-  AidlErrorLog::clearError();
-
-  int ret = 1;
-  switch (options.GetTask()) {
-    case Options::Task::COMPILE:
-      ret = android::aidl::compile_aidl(options, io_delegate);
-      break;
-    case Options::Task::PREPROCESS:
-      ret = android::aidl::preprocess_aidl(options, io_delegate) ? 0 : 1;
-      break;
-    case Options::Task::DUMP_API:
-      ret = android::aidl::dump_api(options, io_delegate) ? 0 : 1;
-      break;
-    case Options::Task::CHECK_API:
-      ret = android::aidl::check_api(options, io_delegate) ? 0 : 1;
-      break;
-    case Options::Task::DUMP_MAPPINGS:
-      ret = android::aidl::dump_mappings(options, io_delegate) ? 0 : 1;
-      break;
-    default:
-      AIDL_FATAL(AIDL_LOCATION_HERE)
-          << "Unrecognized task: " << static_cast<size_t>(options.GetTask());
-  }
-
-  // compiler invariants
-  const bool shouldReportError = ret != 0;
-  const bool reportedError = AidlErrorLog::hadError();
-  AIDL_FATAL_IF(shouldReportError != reportedError, AIDL_LOCATION_HERE)
-      << "Compiler returned error " << ret << " but did" << (reportedError ? "" : " not")
-      << " emit error logs";
-
-  return ret;
+  return success ? 0 : 1;
 }
 
 }  // namespace aidl
diff --git a/aidl.h b/aidl.h
index 1ff8d46..2d15c06 100644
--- a/aidl.h
+++ b/aidl.h
@@ -45,8 +45,7 @@
   OK = 0,
 };
 
-int compile_aidl(const Options& options, const IoDelegate& io_delegate);
-bool preprocess_aidl(const Options& options, const IoDelegate& io_delegate);
+bool compile_aidl(const Options& options, const IoDelegate& io_delegate);
 bool dump_mappings(const Options& options, const IoDelegate& io_delegate);
 
 // main entry point to AIDL
@@ -82,9 +81,6 @@
                                  const IoDelegate& io_delegate, AidlTypenames* typenames,
                                  vector<string>* imported_files);
 
-bool parse_preprocessed_file(const IoDelegate& io_delegate, const std::string& filename,
-                             AidlTypenames* typenames);
-
 } // namespace internals
 
 }  // namespace aidl
diff --git a/aidl_api/aidl-test-versioned-interface/1/.hash b/aidl_api/aidl-test-versioned-interface/1/.hash
index 34d8ec6..dfdb249 100644
--- a/aidl_api/aidl-test-versioned-interface/1/.hash
+++ b/aidl_api/aidl-test-versioned-interface/1/.hash
@@ -1 +1,2 @@
+f211f7823c8279224434f5b9a0b095c1f5ebfc15
 9e7be1859820c59d9d55dd133e71a3687b5d2e5b
diff --git a/aidl_api/aidl-test-versioned-interface/current/android/aidl/versioned/tests/Foo.aidl b/aidl_api/aidl-test-versioned-interface/current/android/aidl/versioned/tests/Foo.aidl
index dad05e6..68364d8 100644
--- a/aidl_api/aidl-test-versioned-interface/current/android/aidl/versioned/tests/Foo.aidl
+++ b/aidl_api/aidl-test-versioned-interface/current/android/aidl/versioned/tests/Foo.aidl
@@ -17,6 +17,7 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.aidl.versioned.tests;
+@JavaSuppressLint(value={"NewApi"})
 parcelable Foo {
-  int intDefault42 = 42;
+    int intDefault42 = 42;
 }
diff --git a/aidl_api/aidl-test-versioned-interface/current/android/aidl/versioned/tests/IFooInterface.aidl b/aidl_api/aidl-test-versioned-interface/current/android/aidl/versioned/tests/IFooInterface.aidl
index 01df310..602c892 100644
--- a/aidl_api/aidl-test-versioned-interface/current/android/aidl/versioned/tests/IFooInterface.aidl
+++ b/aidl_api/aidl-test-versioned-interface/current/android/aidl/versioned/tests/IFooInterface.aidl
@@ -17,10 +17,15 @@
 // later when a module using the interface is updated, e.g., Mainline modules.
 
 package android.aidl.versioned.tests;
+@JavaDelegator
 interface IFooInterface {
-  void originalApi();
-  @utf8InCpp String acceptUnionAndReturnString(in android.aidl.versioned.tests.BazUnion u);
-  @SuppressWarnings(value={"inout-parameter"}) int ignoreParcelablesAndRepeatInt(in android.aidl.versioned.tests.Foo inFoo, inout android.aidl.versioned.tests.Foo inoutFoo, out android.aidl.versioned.tests.Foo outFoo, int value);
-  int returnsLengthOfFooArray(in android.aidl.versioned.tests.Foo[] foos);
-  void newApi();
+    void originalApi();
+    @utf8InCpp String acceptUnionAndReturnString(
+            in android.aidl.versioned.tests.BazUnion u);
+    @SuppressWarnings(value={"inout-parameter"})
+    int ignoreParcelablesAndRepeatInt(in android.aidl.versioned.tests.Foo inFoo,
+            inout android.aidl.versioned.tests.Foo inoutFoo,
+            out android.aidl.versioned.tests.Foo outFoo, int value);
+    int returnsLengthOfFooArray(in android.aidl.versioned.tests.Foo[] foos);
+    void newApi();
 }
diff --git a/aidl_checkapi.cpp b/aidl_checkapi.cpp
index 47733c1..c1d3c66 100644
--- a/aidl_checkapi.cpp
+++ b/aidl_checkapi.cpp
@@ -41,18 +41,10 @@
 using std::string;
 using std::vector;
 
-struct DumpForEqualityVisitor : DumpVisitor {
-  DumpForEqualityVisitor(CodeWriter& out) : DumpVisitor(out) {}
-
-  void DumpConstantValue(const AidlTypeSpecifier&, const AidlConstantValue& c) {
-    out << c.Literal();
-  }
-};
-
 static std::string Dump(const AidlDefinedType& type) {
   string code;
   CodeWriterPtr out = CodeWriter::ForString(&code);
-  DumpForEqualityVisitor visitor(*out);
+  DumpVisitor visitor(*out);
   type.DispatchVisit(visitor);
   out->Close();
   return code;
@@ -86,7 +78,10 @@
       AidlAnnotation::Type::NULLABLE,
       // @JavaDerive doesn't affect read/write
       AidlAnnotation::Type::JAVA_DERIVE,
+      AidlAnnotation::Type::JAVA_DEFAULT,
+      AidlAnnotation::Type::JAVA_DELEGATOR,
       AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
+      AidlAnnotation::Type::JAVA_SUPPRESS_LINT,
       // @Backing for a enum type is checked by the enum checker
       AidlAnnotation::Type::BACKING,
       // @RustDerive doesn't affect read/write
@@ -94,11 +89,11 @@
       AidlAnnotation::Type::SUPPRESS_WARNINGS,
   };
   vector<string> annotations;
-  for (const AidlAnnotation& annotation : node.GetAnnotations()) {
-    if (kIgnoreAnnotations.find(annotation.GetType()) != kIgnoreAnnotations.end()) {
+  for (const auto& annotation : node.GetAnnotations()) {
+    if (kIgnoreAnnotations.find(annotation->GetType()) != kIgnoreAnnotations.end()) {
       continue;
     }
-    auto annotation_string = annotation.ToString();
+    auto annotation_string = annotation->ToString();
     // adding @Deprecated (with optional args) is okay
     if (StartsWith(annotation_string, "@JavaPassthrough(annotation=\"@Deprecated")) {
       continue;
@@ -154,8 +149,8 @@
     const auto new_c = found->second;
     compatible &= are_compatible_types(old_c->GetType(), new_c->GetType());
 
-    const string old_value = old_c->GetValue().Literal();
-    const string new_value = new_c->GetValue().Literal();
+    const string old_value = old_c->ValueString(AidlConstantValueDecorator);
+    const string new_value = new_c->ValueString(AidlConstantValueDecorator);
     if (old_value != new_value) {
       AIDL_ERROR(newer) << "Changed constant value: " << older.GetCanonicalName() << "."
                         << old_c->GetName() << " from " << old_value << " to " << new_value << ".";
@@ -227,21 +222,14 @@
 static bool HasZeroEnumerator(const AidlEnumDeclaration& enum_decl) {
   return std::any_of(enum_decl.GetEnumerators().begin(), enum_decl.GetEnumerators().end(),
                      [&](const unique_ptr<AidlEnumerator>& enumerator) {
-                       return enumerator->GetValue()->Literal() == "0";
+                       return enumerator->GetValue()->ValueString(
+                                  enum_decl.GetBackingType(), AidlConstantValueDecorator) == "0";
                      });
 }
 
-static bool EvaluatesToZero(const AidlEnumDeclaration& enum_decl, const std::string& value) {
-  if (value == "") return true;
-  // Because --check_api runs with "valid" AIDL definitions, we can safely assume that
-  // the value is formatted as <scope>.<enumerator>.
-  auto enumerator_name = value.substr(value.find_last_of('.') + 1);
-  for (const auto& enumerator : enum_decl.GetEnumerators()) {
-    if (enumerator->GetName() == enumerator_name) {
-      return enumerator->GetValue()->Literal() == "0";
-    }
-  }
-  AIDL_FATAL(enum_decl) << "Can't find " << enumerator_name << " in " << enum_decl.GetName();
+static bool EvaluatesToZero(const AidlEnumDeclaration& enum_decl, const AidlConstantValue* value) {
+  if (value == nullptr) return true;
+  return value->ValueString(enum_decl.GetBackingType(), AidlConstantValueDecorator) == "0";
 }
 
 static bool are_compatible_parcelables(const AidlDefinedType& older, const AidlTypenames&,
@@ -277,15 +265,14 @@
     const auto& new_field = new_fields.at(i);
     compatible &= are_compatible_types(old_field->GetType(), new_field->GetType());
 
-    string old_value = old_field->GetDefaultValue() ? old_field->GetDefaultValue()->Literal() : "";
-    string new_value = new_field->GetDefaultValue() ? new_field->GetDefaultValue()->Literal() : "";
-
+    const string old_value = old_field->ValueString(AidlConstantValueDecorator);
+    const string new_value = new_field->ValueString(AidlConstantValueDecorator);
     if (old_value == new_value) {
       continue;
     }
     // For enum type fields, we accept setting explicit default value which is "zero"
     auto enum_decl = new_types.GetEnumDeclaration(new_field->GetType());
-    if (old_value == "" && enum_decl && EvaluatesToZero(*enum_decl, new_value)) {
+    if (old_value == "" && enum_decl && EvaluatesToZero(*enum_decl, new_field->GetDefaultValue())) {
       continue;
     }
 
@@ -390,8 +377,10 @@
       compatible = false;
       continue;
     }
-    const string old_value = old_enum_map[name]->Literal();
-    const string new_value = new_enum_map[name]->Literal();
+    const string old_value =
+        old_enum_map[name]->ValueString(older.GetBackingType(), AidlConstantValueDecorator);
+    const string new_value =
+        new_enum_map[name]->ValueString(newer.GetBackingType(), AidlConstantValueDecorator);
     if (old_value != new_value) {
       AIDL_ERROR(newer) << "Changed enumerator value: " << older.GetCanonicalName() << "::" << name
                         << " from " << old_value << " to " << new_value << ".";
@@ -401,8 +390,8 @@
   return compatible;
 }
 
-static Result<AidlTypenames> load_from_dir(const Options& options, const IoDelegate& io_delegate,
-                                           const std::string& dir) {
+static Result<AidlTypenames> LoadApiDump(const Options& options, const IoDelegate& io_delegate,
+                                         const std::string& dir) {
   Result<std::vector<std::string>> dir_files = io_delegate.ListFiles(dir);
   if (!dir_files.ok()) {
     AIDL_ERROR(dir) << dir_files.error();
@@ -412,7 +401,9 @@
   AidlTypenames typenames;
   for (const auto& file : *dir_files) {
     if (!android::base::EndsWith(file, ".aidl")) continue;
-    if (internals::load_and_validate_aidl(file, options, io_delegate, &typenames,
+    // current "dir" is added to "imports" so that referenced.aidl files in the current
+    // module are available when resolving references.
+    if (internals::load_and_validate_aidl(file, options.PlusImportDir(dir), io_delegate, &typenames,
                                           nullptr /* imported_files */) != AidlError::OK) {
       AIDL_ERROR(file) << "Failed to read.";
       return Error();
@@ -427,19 +418,31 @@
   AIDL_FATAL_IF(options.InputFiles().size() != 2, AIDL_LOCATION_HERE)
       << "--checkapi requires two inputs "
       << "but got " << options.InputFiles().size();
-  auto old_tns = load_from_dir(options, io_delegate, options.InputFiles().at(0));
+  auto old_tns = LoadApiDump(options, io_delegate, options.InputFiles().at(0));
   if (!old_tns.ok()) {
     return false;
   }
-  auto new_tns = load_from_dir(options, io_delegate, options.InputFiles().at(1));
+  auto new_tns = LoadApiDump(options, io_delegate, options.InputFiles().at(1));
   if (!new_tns.ok()) {
     return false;
   }
 
   const Options::CheckApiLevel level = options.GetCheckApiLevel();
 
-  std::vector<AidlDefinedType*> old_types = old_tns->AllDefinedTypes();
-  std::vector<AidlDefinedType*> new_types = new_tns->AllDefinedTypes();
+  // We don't check impoted types.
+  auto get_types_in = [](const AidlTypenames& tns, const std::string& location) {
+    std::vector<const AidlDefinedType*> types;
+    for (const auto& type : tns.AllDefinedTypes()) {
+      if (StartsWith(type->GetLocation().GetFile(), location)) {
+        types.push_back(type);
+      }
+    }
+    return types;
+  };
+  std::vector<const AidlDefinedType*> old_types =
+      get_types_in(*old_tns, options.InputFiles().at(0));
+  std::vector<const AidlDefinedType*> new_types =
+      get_types_in(*new_tns, options.InputFiles().at(1));
 
   bool compatible = true;
 
@@ -458,7 +461,7 @@
     }
   }
 
-  map<string, AidlDefinedType*> new_map;
+  map<string, const AidlDefinedType*> new_map;
   for (const auto t : new_types) {
     new_map.emplace(t->GetCanonicalName(), t);
   }
diff --git a/aidl_const_expressions.cpp b/aidl_const_expressions.cpp
index b9b62ea..eeeb14b 100644
--- a/aidl_const_expressions.cpp
+++ b/aidl_const_expressions.cpp
@@ -242,6 +242,12 @@
   return false;
 }
 
+static bool isValidLiteralChar(char c) {
+  return !(c <= 0x1f ||  // control characters are < 0x20
+           c >= 0x7f ||  // DEL is 0x7f
+           c == '\\');   // Disallow backslashes for future proofing.
+}
+
 bool ParseFloating(std::string_view sv, double* parsed) {
   // float literal should be parsed successfully.
   android::base::ConsumeSuffix(&sv, "f");
@@ -273,6 +279,11 @@
 
 bool AidlBinaryConstExpression::AreCompatibleTypes(Type t1, Type t2) {
   switch (t1) {
+    case Type::ARRAY:
+      if (t2 == Type::ARRAY) {
+        return true;
+      }
+      break;
     case Type::STRING:
       if (t2 == Type::STRING) {
         return true;
@@ -353,6 +364,19 @@
 
 AidlConstantValue* AidlConstantValue::Character(const AidlLocation& location,
                                                 const std::string& value) {
+  static const char* kZeroString = "'\\0'";
+
+  // We should have better supports for escapes in the future, but for now
+  // allow only what is needed for defaults.
+  if (value != kZeroString) {
+    AIDL_FATAL_IF(value.size() != 3 || value[0] != '\'' || value[2] != '\'', location) << value;
+
+    if (!isValidLiteralChar(value[1])) {
+      AIDL_ERROR(location) << "Invalid character literal " << value[1];
+      return new AidlConstantValue(location, Type::ERROR, value);
+    }
+  }
+
   return new AidlConstantValue(location, Type::CHARACTER, value);
 }
 
@@ -371,8 +395,15 @@
     return false;
   }
 
-  const bool isLong = EndsWith(value, 'l') || EndsWith(value, 'L');
-  const std::string value_substr = isLong ? value.substr(0, value.size() - 1) : value;
+  std::string_view value_view = value;
+  const bool is_byte = ConsumeSuffix(&value_view, "u8");
+  const bool is_long = ConsumeSuffix(&value_view, "l") || ConsumeSuffix(&value_view, "L");
+  const std::string value_substr = std::string(value_view);
+
+  *parsed_value = 0;
+  *parsed_type = Type::ERROR;
+
+  if (is_byte && is_long) return false;
 
   if (IsHex(value)) {
     // AIDL considers 'const int foo = 0xffffffff' as -1, but if we want to
@@ -386,28 +417,38 @@
     // Note, for historical consistency, we need to consider small hex values
     // as an integral type. Recognizing them as INT8 could break some files,
     // even though it would simplify this code.
-    if (uint32_t rawValue32;
-        !isLong && android::base::ParseUint<uint32_t>(value_substr, &rawValue32)) {
-      *parsed_value = static_cast<int32_t>(rawValue32);
+    if (is_byte) {
+      uint8_t raw_value8;
+      if (!android::base::ParseUint<uint8_t>(value_substr, &raw_value8)) {
+        return false;
+      }
+      *parsed_value = static_cast<int8_t>(raw_value8);
+      *parsed_type = Type::INT8;
+    } else if (uint32_t raw_value32;
+               !is_long && android::base::ParseUint<uint32_t>(value_substr, &raw_value32)) {
+      *parsed_value = static_cast<int32_t>(raw_value32);
       *parsed_type = Type::INT32;
-    } else if (uint64_t rawValue64; android::base::ParseUint<uint64_t>(value_substr, &rawValue64)) {
-      *parsed_value = static_cast<int64_t>(rawValue64);
+    } else if (uint64_t raw_value64;
+               android::base::ParseUint<uint64_t>(value_substr, &raw_value64)) {
+      *parsed_value = static_cast<int64_t>(raw_value64);
       *parsed_type = Type::INT64;
     } else {
-      *parsed_value = 0;
-      *parsed_type = Type::ERROR;
       return false;
     }
     return true;
   }
 
   if (!android::base::ParseInt<int64_t>(value_substr, parsed_value)) {
-    *parsed_value = 0;
-    *parsed_type = Type::ERROR;
     return false;
   }
 
-  if (isLong) {
+  if (is_byte) {
+    if (*parsed_value > UINT8_MAX || *parsed_value < 0) {
+      return false;
+    }
+    *parsed_value = static_cast<int8_t>(*parsed_value);
+    *parsed_type = Type::INT8;
+  } else if (is_long) {
     *parsed_type = Type::INT64;
   } else {
     // guess literal type.
@@ -438,14 +479,27 @@
 AidlConstantValue* AidlConstantValue::Array(
     const AidlLocation& location, std::unique_ptr<vector<unique_ptr<AidlConstantValue>>> values) {
   AIDL_FATAL_IF(values == nullptr, location);
+  // Reconstruct literal value
   std::vector<std::string> str_values;
   for (const auto& v : *values) {
     str_values.push_back(v->value_);
   }
-  return new AidlConstantValue(location, Type::ARRAY, std::move(values), Join(str_values, ", "));
+  return new AidlConstantValue(location, Type::ARRAY, std::move(values),
+                               "{" + Join(str_values, ", ") + "}");
 }
 
 AidlConstantValue* AidlConstantValue::String(const AidlLocation& location, const string& value) {
+  AIDL_FATAL_IF(value.size() == 0, "If this is unquoted, we need to update the index log");
+  AIDL_FATAL_IF(value[0] != '\"', "If this is unquoted, we need to update the index log");
+
+  for (size_t i = 0; i < value.length(); ++i) {
+    if (!isValidLiteralChar(value[i])) {
+      AIDL_ERROR(location) << "Found invalid character '" << value[i] << "' at index " << i - 1
+                           << " in string constant '" << value << "'";
+      return new AidlConstantValue(location, Type::ERROR, value);
+    }
+  }
+
   return new AidlConstantValue(location, Type::STRING, value);
 }
 
@@ -470,7 +524,7 @@
   }
 
   const AidlDefinedType* defined_type = type.GetDefinedType();
-  if (defined_type && !type.IsArray()) {
+  if (defined_type && final_type_ != Type::ARRAY) {
     const AidlEnumDeclaration* enum_type = defined_type->AsEnumDeclaration();
     if (!enum_type) {
       AIDL_ERROR(this) << "Invalid type (" << defined_type->GetCanonicalName()
@@ -485,7 +539,7 @@
     return decorator(type, value_);
   }
 
-  const string& type_string = type.GetName();
+  const string& type_string = type.Signature();
   int err = 0;
 
   switch (final_type_) {
@@ -534,8 +588,10 @@
       bool success = true;
 
       for (const auto& value : values_) {
-        const AidlTypeSpecifier& array_base = type.ArrayBase();
-        const string value_string = value->ValueString(array_base, decorator);
+        string value_string;
+        type.ViewAsArrayBase([&](const auto& base_type) {
+          value_string = value->ValueString(base_type, decorator);
+        });
         if (value_string.empty()) {
           success = false;
           break;
@@ -546,8 +602,17 @@
         err = -1;
         break;
       }
-
-      return decorator(type, "{" + Join(value_strings, ", ") + "}");
+      if (type.IsFixedSizeArray()) {
+        auto size =
+            std::get<FixedSizeArray>(type.GetArray()).dimensions.front()->EvaluatedValue<int32_t>();
+        if (values_.size() != static_cast<size_t>(size)) {
+          AIDL_ERROR(this) << "Expected an array of " << size << " elements, but found one with "
+                           << values_.size() << " elements";
+          err = -1;
+          break;
+        }
+      }
+      return decorator(type, value_strings);
     }
     case Type::FLOATING: {
       if (type_string == "double") {
@@ -577,7 +642,8 @@
   }
 
   AIDL_FATAL_IF(err == 0, this);
-  AIDL_ERROR(this) << "Invalid type specifier for " << ToString(final_type_) << ": " << type_string;
+  AIDL_ERROR(this) << "Invalid type specifier for " << ToString(final_type_) << ": " << type_string
+                   << " (" << value_ << ")";
   return "";
 }
 
@@ -613,6 +679,14 @@
   return true;
 }
 
+bool AidlConstantValue::Evaluate() const {
+  if (CheckValid()) {
+    return evaluate();
+  } else {
+    return false;
+  }
+}
+
 bool AidlConstantValue::evaluate() const {
   if (is_evaluated_) {
     return is_valid_;
@@ -724,7 +798,8 @@
   if (pos == string::npos) {
     field_name_ = value;
   } else {
-    ref_type_ = std::make_unique<AidlTypeSpecifier>(location, value.substr(0, pos), false, nullptr,
+    ref_type_ = std::make_unique<AidlTypeSpecifier>(location, value.substr(0, pos),
+                                                    /*array=*/std::nullopt, /*type_params=*/nullptr,
                                                     Comments{});
     field_name_ = value.substr(pos + 1);
   }
diff --git a/aidl_dumpapi.cpp b/aidl_dumpapi.cpp
index c121f9f..7d3f19d 100644
--- a/aidl_dumpapi.cpp
+++ b/aidl_dumpapi.cpp
@@ -56,6 +56,9 @@
   for (const auto& constdecl : dt.GetConstantDeclarations()) {
     constdecl->DispatchVisit(*this);
   }
+  for (const auto& nested : dt.GetNestedTypes()) {
+    nested->DispatchVisit(*this);
+  }
 }
 
 // Dumps comment only if its has meaningful tags.
@@ -139,13 +142,6 @@
   out << ";\n";
 }
 
-void DumpVisitor::Visit(const AidlEnumerator& e) {
-  out << e.GetName() << " = ";
-
-  e.GetValue()->DispatchVisit(*this);
-  out << ",\n";
-}
-
 void DumpVisitor::Visit(const AidlTypeSpecifier& t) {
   out << t.ToString();
 }
diff --git a/aidl_dumpapi.h b/aidl_dumpapi.h
index 6d000dd..df8278a 100644
--- a/aidl_dumpapi.h
+++ b/aidl_dumpapi.h
@@ -28,7 +28,7 @@
   void DumpMembers(const AidlDefinedType& dt);
   void DumpComments(const AidlCommentable& c);
   void DumpAnnotations(const AidlAnnotatable& a);
-  virtual void DumpConstantValue(const AidlTypeSpecifier& type, const AidlConstantValue& c);
+  void DumpConstantValue(const AidlTypeSpecifier& type, const AidlConstantValue& c);
 
   void Visit(const AidlInterface& t) override;
   void Visit(const AidlParcelable& t) override;
@@ -38,7 +38,6 @@
   void Visit(const AidlMethod& m) override;
   void Visit(const AidlVariableDeclaration& v) override;
   void Visit(const AidlConstantDeclaration& c) override;
-  void Visit(const AidlEnumerator& e) override;
   void Visit(const AidlTypeSpecifier& t) override;
 };
 
diff --git a/aidl_language.cpp b/aidl_language.cpp
index 5bff95e..e6b4b32 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+
 #include <algorithm>
 #include <iostream>
 #include <set>
@@ -30,13 +31,14 @@
 
 #include <android-base/parsedouble.h>
 #include <android-base/parseint.h>
+#include <android-base/result.h>
 #include <android-base/strings.h>
 
+#include "aidl.h"
 #include "aidl_language_y.h"
 #include "comments.h"
 #include "logging.h"
-
-#include "aidl.h"
+#include "permission.h"
 
 #ifdef _WIN32
 int isatty(int  fd)
@@ -46,7 +48,9 @@
 #endif
 
 using android::aidl::IoDelegate;
+using android::base::Error;
 using android::base::Join;
+using android::base::Result;
 using android::base::Split;
 using std::cerr;
 using std::pair;
@@ -71,6 +75,24 @@
 }
 }  // namespace
 
+AidlNode::~AidlNode() {
+  if (!visited_) {
+    unvisited_locations_.push_back(location_);
+  }
+}
+
+void AidlNode::ClearUnvisitedNodes() {
+  unvisited_locations_.clear();
+}
+
+const std::vector<AidlLocation>& AidlNode::GetLocationsOfUnvisitedNodes() {
+  return unvisited_locations_;
+}
+
+void AidlNode::MarkVisited() const {
+  visited_ = true;
+}
+
 AidlNode::AidlNode(const AidlLocation& location, const Comments& comments)
     : location_(location), comments_(comments) {}
 
@@ -87,18 +109,25 @@
   return ss.str();
 }
 
-static const AidlTypeSpecifier kStringType{AIDL_LOCATION_HERE, "String", false, nullptr,
-                                           Comments{}};
-static const AidlTypeSpecifier kStringArrayType{AIDL_LOCATION_HERE, "String", true, nullptr,
-                                                Comments{}};
-static const AidlTypeSpecifier kIntType{AIDL_LOCATION_HERE, "int", false, nullptr, Comments{}};
-static const AidlTypeSpecifier kLongType{AIDL_LOCATION_HERE, "long", false, nullptr, Comments{}};
-static const AidlTypeSpecifier kBooleanType{AIDL_LOCATION_HERE, "boolean", false, nullptr,
-                                            Comments{}};
+std::vector<AidlLocation> AidlNode::unvisited_locations_;
+
+static const AidlTypeSpecifier kStringType{AIDL_LOCATION_HERE, "String", /*array=*/std::nullopt,
+                                           nullptr, Comments{}};
+static const AidlTypeSpecifier kStringArrayType{AIDL_LOCATION_HERE, "String", DynamicArray{},
+                                                nullptr, Comments{}};
+static const AidlTypeSpecifier kIntType{AIDL_LOCATION_HERE, "int", /*array=*/std::nullopt, nullptr,
+                                        Comments{}};
+static const AidlTypeSpecifier kLongType{AIDL_LOCATION_HERE, "long", /*array=*/std::nullopt,
+                                         nullptr, Comments{}};
+static const AidlTypeSpecifier kBooleanType{AIDL_LOCATION_HERE, "boolean", /*array=*/std::nullopt,
+                                            nullptr, Comments{}};
 
 const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
   static const std::vector<Schema> kSchemas{
-      {AidlAnnotation::Type::NULLABLE, "nullable", CONTEXT_TYPE_SPECIFIER, {}},
+      {AidlAnnotation::Type::NULLABLE,
+       "nullable",
+       CONTEXT_TYPE_SPECIFIER,
+       {{"heap", kBooleanType}}},
       {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", CONTEXT_TYPE_SPECIFIER, {}},
       {AidlAnnotation::Type::SENSITIVE_DATA, "SensitiveData", CONTEXT_TYPE_INTERFACE, {}},
       {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", CONTEXT_TYPE, {}},
@@ -128,12 +157,21 @@
        "JavaDerive",
        CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
        {{"toString", kBooleanType}, {"equals", kBooleanType}}},
+      {AidlAnnotation::Type::JAVA_DEFAULT, "JavaDefault", CONTEXT_TYPE_INTERFACE, {}},
+      {AidlAnnotation::Type::JAVA_DELEGATOR, "JavaDelegator", CONTEXT_TYPE_INTERFACE, {}},
       {AidlAnnotation::Type::JAVA_ONLY_IMMUTABLE,
        "JavaOnlyImmutable",
        CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION |
            CONTEXT_TYPE_UNSTRUCTURED_PARCELABLE,
        {}},
-      {AidlAnnotation::Type::FIXED_SIZE, "FixedSize", CONTEXT_TYPE_STRUCTURED_PARCELABLE, {}},
+      {AidlAnnotation::Type::JAVA_SUPPRESS_LINT,
+       "JavaSuppressLint",
+       CONTEXT_ALL,
+       {{"value", kStringArrayType, /* required= */ true}}},
+      {AidlAnnotation::Type::FIXED_SIZE,
+       "FixedSize",
+       CONTEXT_TYPE_STRUCTURED_PARCELABLE | CONTEXT_TYPE_UNION,
+       {}},
       {AidlAnnotation::Type::DESCRIPTOR,
        "Descriptor",
        CONTEXT_TYPE_INTERFACE,
@@ -152,6 +190,22 @@
        "SuppressWarnings",
        CONTEXT_TYPE | CONTEXT_MEMBER,
        {{"value", kStringArrayType, /* required= */ true}}},
+      {AidlAnnotation::Type::PERMISSION_ENFORCE,
+       "EnforcePermission",
+       CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
+       {{"value", kStringType}, {"anyOf", kStringArrayType}, {"allOf", kStringArrayType}}},
+      {AidlAnnotation::Type::PERMISSION_MANUAL,
+       "PermissionManuallyEnforced",
+       CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
+       {}},
+      {AidlAnnotation::Type::PERMISSION_NONE,
+       "RequiresNoPermission",
+       CONTEXT_TYPE_INTERFACE | CONTEXT_METHOD,
+       {}},
+      {AidlAnnotation::Type::PROPAGATE_ALLOW_BLOCKING,
+       "PropagateAllowBlocking",
+       CONTEXT_METHOD,
+       {}},
   };
   return kSchemas;
 }
@@ -164,9 +218,9 @@
   __builtin_unreachable();
 }
 
-AidlAnnotation* AidlAnnotation::Parse(
+std::unique_ptr<AidlAnnotation> AidlAnnotation::Parse(
     const AidlLocation& location, const string& name,
-    std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list,
+    std::map<std::string, std::shared_ptr<AidlConstantValue>> parameter_list,
     const Comments& comments) {
   const Schema* schema = nullptr;
   for (const Schema& a_schema : AllSchemas()) {
@@ -184,19 +238,16 @@
     }
     stream << ".";
     AIDL_ERROR(location) << stream.str();
-    return nullptr;
-  }
-  if (parameter_list == nullptr) {
-    return new AidlAnnotation(location, *schema, {}, comments);
+    return {};
   }
 
-  return new AidlAnnotation(location, *schema, std::move(*parameter_list), comments);
+  return std::unique_ptr<AidlAnnotation>(
+      new AidlAnnotation(location, *schema, std::move(parameter_list), comments));
 }
 
-AidlAnnotation::AidlAnnotation(
-    const AidlLocation& location, const Schema& schema,
-    std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters,
-    const Comments& comments)
+AidlAnnotation::AidlAnnotation(const AidlLocation& location, const Schema& schema,
+                               std::map<std::string, std::shared_ptr<AidlConstantValue>> parameters,
+                               const Comments& comments)
     : AidlNode(location, comments), schema_(schema), parameters_(std::move(parameters)) {}
 
 struct ConstReferenceFinder : AidlVisitor {
@@ -261,7 +312,34 @@
       success = false;
     }
   }
-  return success;
+  if (!success) {
+    return false;
+  }
+  // For @Enforce annotations, validates the expression.
+  if (schema_.type == AidlAnnotation::Type::PERMISSION_ENFORCE) {
+    auto expr = EnforceExpression();
+    if (!expr.ok()) {
+      AIDL_ERROR(this) << "Unable to parse @EnforcePermission annotation: " << expr.error();
+      return false;
+    }
+  }
+  return true;
+}
+
+Result<unique_ptr<android::aidl::perm::Expression>> AidlAnnotation::EnforceExpression() const {
+  auto single = ParamValue<std::string>("value");
+  auto anyOf = ParamValue<std::vector<std::string>>("anyOf");
+  auto allOf = ParamValue<std::vector<std::string>>("allOf");
+  if (single.has_value()) {
+    return std::make_unique<android::aidl::perm::Expression>(single.value());
+  } else if (anyOf.has_value()) {
+    auto v = android::aidl::perm::AnyOf{anyOf.value()};
+    return std::make_unique<android::aidl::perm::Expression>(v);
+  } else if (allOf.has_value()) {
+    auto v = android::aidl::perm::AllOf{allOf.value()};
+    return std::make_unique<android::aidl::perm::Expression>(v);
+  }
+  return Error() << "No parameter for @EnforcePermission";
 }
 
 // Checks if the annotation is applicable to the current context.
@@ -325,18 +403,31 @@
   }
 }
 
-static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
-                                           AidlAnnotation::Type type) {
+static const AidlAnnotation* GetAnnotation(
+    const vector<std::unique_ptr<AidlAnnotation>>& annotations, AidlAnnotation::Type type) {
   for (const auto& a : annotations) {
-    if (a.GetType() == type) {
-      AIDL_FATAL_IF(a.Repeatable(), a)
+    if (a->GetType() == type) {
+      AIDL_FATAL_IF(a->Repeatable(), a)
           << "Trying to get a single annotation when it is repeatable.";
-      return &a;
+      return a.get();
     }
   }
   return nullptr;
 }
 
+static const AidlAnnotation* GetScopedAnnotation(const AidlDefinedType& defined_type,
+                                                 AidlAnnotation::Type type) {
+  const AidlAnnotation* annotation = GetAnnotation(defined_type.GetAnnotations(), type);
+  if (annotation) {
+    return annotation;
+  }
+  const AidlDefinedType* enclosing_type = defined_type.GetParentType();
+  if (enclosing_type) {
+    return GetScopedAnnotation(*enclosing_type, type);
+  }
+  return nullptr;
+}
+
 AidlAnnotatable::AidlAnnotatable(const AidlLocation& location, const Comments& comments)
     : AidlCommentable(location, comments) {}
 
@@ -344,6 +435,14 @@
   return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
 }
 
+bool AidlAnnotatable::IsHeapNullable() const {
+  auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
+  if (annot) {
+    return annot->ParamValue<bool>("heap").value_or(false);
+  }
+  return false;
+}
+
 bool AidlAnnotatable::IsUtf8InCpp() const {
   return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
 }
@@ -353,7 +452,9 @@
 }
 
 bool AidlAnnotatable::IsVintfStability() const {
-  return GetAnnotation(annotations_, AidlAnnotation::Type::VINTF_STABILITY);
+  auto defined_type = AidlCast<AidlDefinedType>(*this);
+  AIDL_FATAL_IF(!defined_type, *this) << "@VintfStability is not attached to a type";
+  return GetScopedAnnotation(*defined_type, AidlAnnotation::Type::VINTF_STABILITY);
 }
 
 bool AidlAnnotatable::IsJavaOnlyImmutable() const {
@@ -386,6 +487,32 @@
   return {};
 }
 
+// Parses the @Enforce annotation expression.
+std::unique_ptr<android::aidl::perm::Expression> AidlAnnotatable::EnforceExpression() const {
+  auto annot = GetAnnotation(annotations_, AidlAnnotation::Type::PERMISSION_ENFORCE);
+  if (annot) {
+    auto perm_expr = annot->EnforceExpression();
+    if (!perm_expr.ok()) {
+      // This should have been caught during validation.
+      AIDL_FATAL(this) << "Unable to parse @EnforcePermission annotation: " << perm_expr.error();
+    }
+    return std::move(perm_expr.value());
+  }
+  return {};
+}
+
+bool AidlAnnotatable::IsPermissionManual() const {
+  return GetAnnotation(annotations_, AidlAnnotation::Type::PERMISSION_MANUAL);
+}
+
+bool AidlAnnotatable::IsPermissionNone() const {
+  return GetAnnotation(annotations_, AidlAnnotation::Type::PERMISSION_NONE);
+}
+
+bool AidlAnnotatable::IsPropagateAllowBlocking() const {
+  return GetAnnotation(annotations_, AidlAnnotation::Type::PROPAGATE_ALLOW_BLOCKING);
+}
+
 bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
   return lang == Options::Language::JAVA &&
          GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
@@ -403,6 +530,14 @@
   return false;
 }
 
+bool AidlAnnotatable::IsJavaDefault() const {
+  return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DEFAULT);
+}
+
+bool AidlAnnotatable::IsJavaDelegator() const {
+  return GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_DELEGATOR);
+}
+
 std::string AidlAnnotatable::GetDescriptor() const {
   auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::DESCRIPTOR);
   if (annotation != nullptr) {
@@ -413,16 +548,17 @@
 
 bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
   for (const auto& annotation : GetAnnotations()) {
-    if (!annotation.CheckValid()) {
+    if (!annotation->CheckValid()) {
       return false;
     }
   }
 
   std::map<AidlAnnotation::Type, AidlLocation> declared;
   for (const auto& annotation : GetAnnotations()) {
-    const auto& [iter, inserted] = declared.emplace(annotation.GetType(), annotation.GetLocation());
-    if (!inserted && !annotation.Repeatable()) {
-      AIDL_ERROR(this) << "'" << annotation.GetName()
+    const auto& [iter, inserted] =
+        declared.emplace(annotation->GetType(), annotation->GetLocation());
+    if (!inserted && !annotation->Repeatable()) {
+      AIDL_ERROR(this) << "'" << annotation->GetName()
                        << "' is repeated, but not allowed. Previous location: " << iter->second;
       return false;
     }
@@ -434,32 +570,71 @@
 string AidlAnnotatable::ToString() const {
   vector<string> ret;
   for (const auto& a : annotations_) {
-    ret.emplace_back(a.ToString());
+    ret.emplace_back(a->ToString());
   }
   std::sort(ret.begin(), ret.end());
   return Join(ret, " ");
 }
 
 AidlTypeSpecifier::AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
-                                     bool is_array,
+                                     std::optional<ArrayType> array,
                                      vector<unique_ptr<AidlTypeSpecifier>>* type_params,
                                      const Comments& comments)
     : AidlAnnotatable(location, comments),
       AidlParameterizable<unique_ptr<AidlTypeSpecifier>>(type_params),
       unresolved_name_(unresolved_name),
-      is_array_(is_array),
+      array_(std::move(array)),
       split_name_(Split(unresolved_name, ".")) {}
 
-const AidlTypeSpecifier& AidlTypeSpecifier::ArrayBase() const {
-  AIDL_FATAL_IF(!is_array_, this);
+void AidlTypeSpecifier::ViewAsArrayBase(std::function<void(const AidlTypeSpecifier&)> func) const {
+  AIDL_FATAL_IF(!array_.has_value(), this);
   // Declaring array of generic type cannot happen, it is grammar error.
   AIDL_FATAL_IF(IsGeneric(), this);
 
-  if (!array_base_) {
-    array_base_.reset(new AidlTypeSpecifier(*this));
-    array_base_->is_array_ = false;
+  bool is_mutated = mutated_;
+  mutated_ = true;
+  // mutate the array type to its base by removing a single dimension
+  // e.g.) T[] => T, T[N][M] => T[M] (note that, M is removed)
+  if (IsFixedSizeArray() && std::get<FixedSizeArray>(*array_).dimensions.size() > 1) {
+    auto& dimensions = std::get<FixedSizeArray>(*array_).dimensions;
+    auto dim = std::move(dimensions.front());
+    dimensions.erase(dimensions.begin());
+    func(*this);
+    dimensions.insert(dimensions.begin(), std::move(dim));
+  } else {
+    ArrayType array_type = std::move(array_.value());
+    array_ = std::nullopt;
+    func(*this);
+    array_ = std::move(array_type);
   }
-  return *array_base_;
+  mutated_ = is_mutated;
+}
+
+bool AidlTypeSpecifier::MakeArray(ArrayType array_type) {
+  // T becomes T[] or T[N]
+  if (!IsArray()) {
+    array_ = std::move(array_type);
+    return true;
+  }
+  // T[N] becomes T[N][M]
+  if (auto fixed_size_array = std::get_if<FixedSizeArray>(&array_type);
+      fixed_size_array != nullptr && IsFixedSizeArray()) {
+    // concat dimensions
+    for (auto& dim : fixed_size_array->dimensions) {
+      std::get<FixedSizeArray>(*array_).dimensions.push_back(std::move(dim));
+    }
+    return true;
+  }
+  return false;
+}
+
+std::vector<int32_t> AidlTypeSpecifier::GetFixedSizeArrayDimensions() const {
+  AIDL_FATAL_IF(!IsFixedSizeArray(), "not a fixed-size array");
+  std::vector<int32_t> dimensions;
+  for (const auto& dim : std::get<FixedSizeArray>(GetArray()).dimensions) {
+    dimensions.push_back(dim->EvaluatedValue<int32_t>());
+  }
+  return dimensions;
 }
 
 string AidlTypeSpecifier::Signature() const {
@@ -472,7 +647,13 @@
     ret += "<" + Join(arg_names, ",") + ">";
   }
   if (IsArray()) {
-    ret += "[]";
+    if (IsFixedSizeArray()) {
+      for (const auto& dim : GetFixedSizeArrayDimensions()) {
+        ret += "[" + std::to_string(dim) + "]";
+      }
+    } else {
+      ret += "[]";
+    }
   }
   return ret;
 }
@@ -486,9 +667,15 @@
   return ret;
 }
 
-bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames) {
+// When `scope` is specified, name is resolved first based on it.
+// `scope` can be null for built-in types and fully-qualified types.
+bool AidlTypeSpecifier::Resolve(const AidlTypenames& typenames, const AidlScope* scope) {
   AIDL_FATAL_IF(IsResolved(), this);
-  AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(unresolved_name_);
+  std::string name = unresolved_name_;
+  if (scope) {
+    name = scope->ResolveName(name);
+  }
+  AidlTypenames::ResolvedTypename result = typenames.ResolveTypename(name);
   if (result.is_resolved) {
     fully_qualified_name_ = result.canonical_name;
     split_name_ = Split(fully_qualified_name_, ".");
@@ -537,27 +724,19 @@
                          << "'";
         return false;
       }
+      static const char* kListUsage =
+          "List<T> supports interface/parcelable/union, String, IBinder, and ParcelFileDescriptor.";
       const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
       if (contained_type.IsArray()) {
-        AIDL_ERROR(this)
-            << "List of arrays is not supported. List<T> supports parcelable/union, String, "
-               "IBinder, and ParcelFileDescriptor.";
+        AIDL_ERROR(this) << "List of arrays is not supported. " << kListUsage;
         return false;
       }
       const string& contained_type_name = contained_type.GetName();
       if (AidlTypenames::IsBuiltinTypename(contained_type_name)) {
         if (contained_type_name != "String" && contained_type_name != "IBinder" &&
             contained_type_name != "ParcelFileDescriptor") {
-          AIDL_ERROR(this) << "List<" << contained_type_name
-                           << "> is not supported. List<T> supports parcelable/union, String, "
-                              "IBinder, and ParcelFileDescriptor.";
-          return false;
-        }
-      } else {  // Defined types
-        if (typenames.GetInterface(contained_type)) {
-          AIDL_ERROR(this) << "List<" << contained_type_name
-                           << "> is not supported. List<T> supports parcelable/union, String, "
-                              "IBinder, and ParcelFileDescriptor.";
+          AIDL_ERROR(this) << "List<" << contained_type_name << "> is not supported. "
+                           << kListUsage;
           return false;
         }
       }
@@ -604,13 +783,9 @@
   }
 
   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") {
-      AIDL_ERROR(this) << "Arrays of ParcelableHolder are not supported.";
+    if (GetName() == "ParcelableHolder" || GetName() == "List" || GetName() == "Map" ||
+        GetName() == "CharSequence") {
+      AIDL_ERROR(this) << "Arrays of " << GetName() << " are not supported.";
       return false;
     }
   }
@@ -629,22 +804,61 @@
       AIDL_ERROR(this) << "ParcelableHolder cannot be nullable.";
       return false;
     }
+    if (IsHeapNullable()) {
+      if (!defined_type || IsArray() || !defined_type->AsParcelable()) {
+        AIDL_ERROR(this) << "@nullable(heap=true) is available to parcelables.";
+        return false;
+      }
+    }
+  }
+
+  if (IsFixedSizeArray()) {
+    for (const auto& dim : std::get<FixedSizeArray>(GetArray()).dimensions) {
+      if (!dim->Evaluate()) {
+        return false;
+      }
+      if (dim->GetType() > AidlConstantValue::Type::INT32) {
+        AIDL_ERROR(this) << "Array size must be a positive number: " << dim->Literal();
+        return false;
+      }
+      auto value = dim->EvaluatedValue<int32_t>();
+      if (value < 0) {
+        AIDL_ERROR(this) << "Array size must be a positive number: " << value;
+        return false;
+      }
+    }
   }
   return true;
 }
 
-std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type,
-                                       const std::string& raw_value) {
-  if (type.IsArray()) {
-    return raw_value;
+void AidlTypeSpecifier::TraverseChildren(std::function<void(const AidlNode&)> traverse) const {
+  AidlAnnotatable::TraverseChildren(traverse);
+  if (IsGeneric()) {
+    for (const auto& tp : GetTypeParameters()) {
+      traverse(*tp);
+    }
   }
+  if (IsFixedSizeArray()) {
+    for (const auto& dim : std::get<FixedSizeArray>(GetArray()).dimensions) {
+      traverse(*dim);
+    }
+  }
+}
 
+std::string AidlConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value) {
+  if (type.IsArray()) {
+    const auto& values = std::get<std::vector<std::string>>(raw_value);
+    return "{" + Join(values, ", ") + "}";
+  }
+  const std::string& value = std::get<std::string>(raw_value);
   if (auto defined_type = type.GetDefinedType(); defined_type) {
     auto enum_type = defined_type->AsEnumDeclaration();
-    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
-    return type.GetName() + "." + raw_value.substr(raw_value.find_last_of('.') + 1);
+    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << value << "\"";
+    return type.GetName() + "." + value.substr(value.find_last_of('.') + 1);
   }
-  return raw_value;
+  return value;
 }
 
 AidlVariableDeclaration::AidlVariableDeclaration(const AidlLocation& location,
@@ -721,8 +935,8 @@
 void AidlVariableDeclaration::TraverseChildren(
     std::function<void(const AidlNode&)> traverse) const {
   traverse(GetType());
-  if (IsDefaultUserSpecified()) {
-    traverse(*GetDefaultValue());
+  if (auto default_value = GetDefaultValue(); default_value) {
+    traverse(*default_value);
   }
 }
 
@@ -820,7 +1034,7 @@
 }
 
 AidlMember::AidlMember(const AidlLocation& location, const Comments& comments)
-    : AidlCommentable(location, comments) {}
+    : AidlAnnotatable(location, comments) {}
 
 AidlConstantDeclaration::AidlConstantDeclaration(const AidlLocation& location,
                                                  AidlTypeSpecifier* type, const std::string& name,
@@ -897,24 +1111,91 @@
   return ret;
 }
 
+bool AidlMethod::CheckValid(const AidlTypenames& typenames) const {
+  if (!GetType().CheckValid(typenames)) {
+    return false;
+  }
+
+  // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
+  if (GetType().GetName() == "ParcelableHolder") {
+    AIDL_ERROR(this) << "ParcelableHolder cannot be a return type";
+    return false;
+  }
+  if (IsOneway() && GetType().GetName() != "void") {
+    AIDL_ERROR(this) << "oneway method '" << GetName() << "' cannot return a value";
+    return false;
+  }
+
+  set<string> argument_names;
+  for (const auto& arg : GetArguments()) {
+    auto it = argument_names.find(arg->GetName());
+    if (it != argument_names.end()) {
+      AIDL_ERROR(this) << "method '" << GetName() << "' has duplicate argument name '"
+                       << arg->GetName() << "'";
+      return false;
+    }
+    argument_names.insert(arg->GetName());
+
+    if (!arg->CheckValid(typenames)) {
+      return false;
+    }
+
+    if (IsOneway() && arg->IsOut()) {
+      AIDL_ERROR(this) << "oneway method '" << this->GetName() << "' cannot have out parameters";
+      return false;
+    }
+
+    // check that the name doesn't match a keyword
+    if (IsJavaKeyword(arg->GetName().c_str())) {
+      AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
+      return false;
+    }
+
+    // Reserve a namespace for internal use
+    if (android::base::StartsWith(arg->GetName(), "_aidl")) {
+      AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
+      return false;
+    }
+
+    if (arg->GetType().GetName() == "void") {
+      AIDL_ERROR(arg->GetType()) << "'void' is an invalid type for the parameter '"
+                                 << arg->GetName() << "'";
+      return false;
+    }
+  }
+  return true;
+}
+
 AidlDefinedType::AidlDefinedType(const AidlLocation& location, const std::string& name,
                                  const Comments& comments, const std::string& package,
                                  std::vector<std::unique_ptr<AidlMember>>* members)
-    : AidlAnnotatable(location, comments),
-      name_(name),
-      package_(package),
-      split_package_(package.empty() ? std::vector<std::string>()
-                                     : android::base::Split(package, ".")) {
+    : AidlMember(location, comments), AidlScope(this), name_(name), package_(package) {
+  // adjust name/package when name is fully qualified (for preprocessed files)
+  if (package_.empty() && name_.find('.') != std::string::npos) {
+    // Note that this logic is absolutely wrong.  Given a parcelable
+    // org.some.Foo.Bar, the class name is Foo.Bar, but this code will claim that
+    // the class is just Bar.  However, this was the way it was done in the past.
+    //
+    // See b/17415692
+    auto pos = name.rfind('.');
+    // name is the last part.
+    name_ = name.substr(pos + 1);
+    // package is the initial parts (except the last).
+    package_ = name.substr(0, pos);
+  }
   if (members) {
     for (auto& m : *members) {
-      if (auto constant = m->AsConstantDeclaration(); constant) {
+      if (auto constant = AidlCast<AidlConstantDeclaration>(*m); constant) {
         constants_.emplace_back(constant);
-      } else if (auto variable = m->AsVariableDeclaration(); variable) {
+      } else if (auto variable = AidlCast<AidlVariableDeclaration>(*m); variable) {
         variables_.emplace_back(variable);
-      } else if (auto method = m->AsMethod(); method) {
+      } else if (auto method = AidlCast<AidlMethod>(*m); method) {
         methods_.emplace_back(method);
+      } else if (auto type = AidlCast<AidlDefinedType>(*m); type) {
+        type->SetEnclosingScope(this);
+        types_.emplace_back(type);
       } else {
-        AIDL_FATAL(*m);
+        AIDL_FATAL(*m) << "Unknown member type.";
       }
       members_.push_back(m.release());
     }
@@ -933,6 +1214,9 @@
 }
 
 std::string AidlDefinedType::GetCanonicalName() const {
+  if (auto parent = GetParentType(); parent) {
+    return parent->GetCanonicalName() + "." + GetName();
+  }
   if (package_.empty()) {
     return GetName();
   }
@@ -942,6 +1226,44 @@
 bool AidlDefinedType::CheckValidWithMembers(const AidlTypenames& typenames) const {
   bool success = true;
 
+  for (const auto& t : GetNestedTypes()) {
+    success = success && t->CheckValid(typenames);
+  }
+
+  if (auto parameterizable = AsParameterizable();
+      parameterizable && parameterizable->IsGeneric() && !GetNestedTypes().empty()) {
+    AIDL_ERROR(this) << "Generic types can't have nested types.";
+    return false;
+  }
+
+  std::set<std::string> nested_type_names;
+  for (const auto& t : GetNestedTypes()) {
+    bool duplicated = !nested_type_names.emplace(t->GetName()).second;
+    if (duplicated) {
+      AIDL_ERROR(t) << "Redefinition of '" << t->GetName() << "'.";
+      success = false;
+    }
+    // nested type can't have a parent name
+    if (t->GetName() == GetName()) {
+      AIDL_ERROR(t) << "Nested type '" << GetName() << "' has the same name as its parent.";
+      success = false;
+    }
+    // Having unstructured parcelables as nested types doesn't make sense because they are defined
+    // somewhere else in native languages (e.g. C++, Java...).
+    if (AidlCast<AidlParcelable>(*t)) {
+      AIDL_ERROR(t) << "'" << t->GetName()
+                    << "' is nested. Unstructured parcelables should be at the root scope.";
+      return false;
+    }
+  }
+
+  if (!TopologicalVisit(GetNestedTypes(), [](auto&) {})) {
+    AIDL_ERROR(this) << GetName()
+                     << " has nested types with cyclic references. C++ and NDK backends don't "
+                        "support cyclic references.";
+    return false;
+  }
+
   for (const auto& v : GetFields()) {
     const bool field_valid = v->CheckValid(typenames);
     success = success && field_valid;
@@ -995,6 +1317,79 @@
   return success;
 }
 
+const AidlDefinedType* AidlDefinedType::GetParentType() const {
+  AIDL_FATAL_IF(GetEnclosingScope() == nullptr, this) << "Scope is not set.";
+  return AidlCast<AidlDefinedType>(GetEnclosingScope()->GetNode());
+}
+
+const AidlDefinedType* AidlDefinedType::GetRootType() const {
+  const AidlDefinedType* root = this;
+  for (auto parent = root->GetParentType(); parent; parent = parent->GetParentType()) {
+    root = parent;
+  }
+  return root;
+}
+
+// Resolve `name` in the current scope. If not found, delegate to the parent
+std::string AidlDefinedType::ResolveName(const std::string& name) const {
+  // For example, in the following, t1's type Baz means x.Foo.Bar.Baz
+  // while t2's type is y.Baz.
+  // package x;
+  // import y.Baz;
+  // parcelable Foo {
+  //   parcelable Bar {
+  //     enum Baz { ... }
+  //     Baz t1; // -> should be x.Foo.Bar.Baz
+  //   }
+  //   Baz t2; // -> should be y.Baz
+  //   Bar.Baz t3; // -> should be x.Foo.Bar.Baz
+  // }
+  AIDL_FATAL_IF(!GetEnclosingScope(), this)
+      << "Type should have an enclosing scope.(e.g. AidlDocument)";
+  if (AidlTypenames::IsBuiltinTypename(name)) {
+    return name;
+  }
+
+  const auto first_dot = name.find_first_of('.');
+  // For "Outer.Inner", we look up "Outer" in the import list.
+  const std::string class_name =
+      (first_dot == std::string::npos) ? name : name.substr(0, first_dot);
+  // Keep ".Inner", to make a fully-qualified name
+  const std::string nested_type = (first_dot == std::string::npos) ? "" : name.substr(first_dot);
+
+  // check if it is a nested type
+  for (const auto& type : GetNestedTypes()) {
+    if (type->GetName() == class_name) {
+      return type->GetCanonicalName() + nested_type;
+    }
+  }
+
+  return GetEnclosingScope()->ResolveName(name);
+}
+
+template <>
+const AidlDefinedType* AidlCast<AidlDefinedType>(const AidlNode& node) {
+  struct Visitor : AidlVisitor {
+    const AidlDefinedType* defined_type = nullptr;
+    void Visit(const AidlInterface& t) override { defined_type = &t; }
+    void Visit(const AidlEnumDeclaration& t) override { defined_type = &t; }
+    void Visit(const AidlStructuredParcelable& t) override { defined_type = &t; }
+    void Visit(const AidlUnionDecl& t) override { defined_type = &t; }
+    void Visit(const AidlParcelable& t) override { defined_type = &t; }
+  } v;
+  node.DispatchVisit(v);
+  return v.defined_type;
+}
+
+const AidlDocument& AidlDefinedType::GetDocument() const {
+  const AidlDefinedType* root = GetRootType();
+  auto scope = root->GetEnclosingScope();
+  AIDL_FATAL_IF(!scope, this) << "no scope defined.";
+  auto doc = AidlCast<AidlDocument>(scope->GetNode());
+  AIDL_FATAL_IF(!doc, this) << "root scope is not a document.";
+  return *doc;
+}
+
 AidlParcelable::AidlParcelable(const AidlLocation& location, const std::string& name,
                                const std::string& package, const Comments& comments,
                                const std::string& cpp_header, std::vector<std::string>* type_params,
@@ -1007,13 +1402,6 @@
     cpp_header_ = cpp_header_.substr(1, cpp_header_.length() - 2);
   }
 }
-template <typename T>
-AidlParameterizable<T>::AidlParameterizable(const AidlParameterizable& other) {
-  // Copying is not supported if it has type parameters.
-  // It doesn't make a problem because only ArrayBase() makes a copy,
-  // and it can be called only if a type is not generic.
-  AIDL_FATAL_IF(other.IsGeneric(), AIDL_LOCATION_HERE);
-}
 
 template <typename T>
 bool AidlParameterizable<T>::CheckValid() const {
@@ -1041,7 +1429,18 @@
     return false;
   }
 
-  return true;
+  bool success = true;
+  if (IsFixedSize()) {
+    for (const auto& v : GetFields()) {
+      if (!typenames.CanBeFixedSize(v->GetType())) {
+        AIDL_ERROR(v) << "The @FixedSize parcelable '" << this->GetName() << "' has a "
+                      << "non-fixed size field named " << v->GetName() << ".";
+        success = false;
+      }
+    }
+  }
+
+  return success;
 }
 
 AidlStructuredParcelable::AidlStructuredParcelable(
@@ -1057,16 +1456,6 @@
 
   bool success = true;
 
-  if (IsFixedSize()) {
-    for (const auto& v : GetFields()) {
-      if (!typenames.CanBeFixedSize(v->GetType())) {
-        AIDL_ERROR(v) << "The @FixedSize parcelable '" << this->GetName() << "' has a "
-                      << "non-fixed size field named " << v->GetName() << ".";
-        success = false;
-      }
-    }
-  }
-
   if (IsJavaOnlyImmutable()) {
     // Immutable parcelables provide getters
     if (!CheckValidForGetterNames()) {
@@ -1078,73 +1467,12 @@
 }
 
 // TODO: we should treat every backend all the same in future.
-bool AidlTypeSpecifier::LanguageSpecificCheckValid(const AidlTypenames& typenames,
-                                                   Options::Language lang) const {
-  if (IsGeneric()) {
-    const auto& types = GetTypeParameters();
-    for (const auto& arg : types) {
-      if (!arg->LanguageSpecificCheckValid(typenames, lang)) {
-        return false;
-      }
-    }
-  }
-
-  if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
-      GetName() == "IBinder") {
-    AIDL_ERROR(this) << "The " << to_string(lang) << " backend does not support array of IBinder";
-    return false;
-  }
-  if (lang == Options::Language::RUST && GetName() == "ParcelableHolder") {
-    // TODO(b/146611855): Remove it when Rust backend supports ParcelableHolder
-    AIDL_ERROR(this) << "The Rust backend does not support ParcelableHolder yet.";
-    return false;
-  }
-  if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
-      IsNullable()) {
-    if (GetName() == "ParcelFileDescriptor") {
-      AIDL_ERROR(this) << "The " << to_string(lang)
-                       << " backend does not support nullable array of ParcelFileDescriptor";
-      return false;
-    }
-
-    const auto defined_type = typenames.TryGetDefinedType(GetName());
-    if (defined_type != nullptr && defined_type->AsParcelable() != nullptr) {
-      AIDL_ERROR(this) << "The " << to_string(lang)
-                       << " backend does not support nullable array of parcelable";
-      return false;
-    }
-  }
+bool AidlTypeSpecifier::LanguageSpecificCheckValid(Options::Language lang) const {
   if (this->GetName() == "FileDescriptor" &&
       (lang == Options::Language::NDK || lang == Options::Language::RUST)) {
     AIDL_ERROR(this) << "FileDescriptor isn't supported by the " << to_string(lang) << " backend.";
     return false;
   }
-  if (this->IsGeneric()) {
-    if (this->GetName() == "List") {
-      if (lang == Options::Language::NDK) {
-        const AidlTypeSpecifier& contained_type = *GetTypeParameters()[0];
-        const string& contained_type_name = contained_type.GetName();
-        if (typenames.GetInterface(contained_type)) {
-          AIDL_ERROR(this) << "List<" << contained_type_name
-                           << "> is not supported. List in NDK doesn't support interface.";
-          return false;
-        }
-        if (contained_type_name == "IBinder") {
-          AIDL_ERROR(this) << "List<" << contained_type_name
-                           << "> is not supported. List in NDK doesn't support IBinder.";
-          return false;
-        }
-      }
-    }
-  }
-
-  if (this->IsArray()) {
-    if (this->GetName() == "List" || this->GetName() == "Map" ||
-        this->GetName() == "CharSequence") {
-      AIDL_ERROR(this) << this->GetName() << "[] is not supported.";
-      return false;
-    }
-  }
 
   if (lang != Options::Language::JAVA) {
     if (this->GetName() == "List" && !this->IsGeneric()) {
@@ -1161,33 +1489,17 @@
 }
 
 // TODO: we should treat every backend all the same in future.
-bool AidlParcelable::LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
-                                                Options::Language lang) const {
-  if (lang == Options::Language::CPP || lang == Options::Language::NDK) {
-    const AidlParcelable* unstructured_parcelable = this->AsUnstructuredParcelable();
-    if (unstructured_parcelable != nullptr) {
-      if (unstructured_parcelable->GetCppHeader().empty()) {
-        AIDL_ERROR(unstructured_parcelable)
-            << "Unstructured parcelable must have C++ header defined.";
-        return false;
-      }
+bool AidlDefinedType::LanguageSpecificCheckValid(Options::Language lang) const {
+  struct Visitor : AidlVisitor {
+    Visitor(Options::Language lang) : lang(lang) {}
+    void Visit(const AidlTypeSpecifier& type) override {
+      success = success && type.LanguageSpecificCheckValid(lang);
     }
-  }
-  return true;
-}
-
-// TODO: we should treat every backend all the same in future.
-bool AidlStructuredParcelable::LanguageSpecificCheckValid(const AidlTypenames& typenames,
-                                                          Options::Language lang) const {
-  if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
-    return false;
-  }
-  for (const auto& v : this->GetFields()) {
-    if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
-      return false;
-    }
-  }
-  return true;
+    Options::Language lang;
+    bool success = true;
+  } v(lang);
+  VisitTopDown(v, *this);
+  return v.success;
 }
 
 AidlEnumerator::AidlEnumerator(const AidlLocation& location, const std::string& name,
@@ -1252,16 +1564,20 @@
       return false;
     }
     auto type = annot->ParamValue<std::string>("type").value();
-    backing_type_ =
-        std::make_unique<AidlTypeSpecifier>(annot->GetLocation(), type, false, nullptr, Comments{});
+    backing_type_ = typenames.MakeResolvedType(annot->GetLocation(), type, false);
   } else {
     // Default to byte type for enums.
-    backing_type_ =
-        std::make_unique<AidlTypeSpecifier>(AIDL_LOCATION_HERE, "byte", false, nullptr, Comments{});
+    backing_type_ = typenames.MakeResolvedType(GetLocation(), "byte", false);
   }
-  // Autofill() is called after type resolution, we resolve the backing type manually.
-  if (!backing_type_->Resolve(typenames)) {
-    AIDL_ERROR(this) << "Invalid backing type: " << backing_type_->GetName();
+
+  // we only support/test a few backing types, so make sure this is a supported
+  // one (otherwise boolean might work, which isn't supported/tested in all
+  // backends)
+  static std::set<string> kBackingTypes = {"byte", "int", "long"};
+  if (kBackingTypes.find(backing_type_->GetName()) == kBackingTypes.end()) {
+    AIDL_ERROR(this) << "Invalid backing type: " << backing_type_->GetName()
+                     << ". Backing type must be one of: " << Join(kBackingTypes, ", ");
+    return false;
   }
   return true;
 }
@@ -1345,36 +1661,6 @@
   return success;
 }
 
-// TODO: we should treat every backend all the same in future.
-bool AidlUnionDecl::LanguageSpecificCheckValid(const AidlTypenames& typenames,
-                                               Options::Language lang) const {
-  if (!AidlParcelable::LanguageSpecificCheckValid(typenames, lang)) {
-    return false;
-  }
-  for (const auto& v : this->GetFields()) {
-    if (!v->GetType().LanguageSpecificCheckValid(typenames, lang)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-// TODO: we should treat every backend all the same in future.
-bool AidlInterface::LanguageSpecificCheckValid(const AidlTypenames& typenames,
-                                               Options::Language lang) const {
-  for (const auto& m : this->GetMethods()) {
-    if (!m->GetType().LanguageSpecificCheckValid(typenames, lang)) {
-      return false;
-    }
-    for (const auto& arg : m->GetArguments()) {
-      if (!arg->GetType().LanguageSpecificCheckValid(typenames, lang)) {
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
 AidlInterface::AidlInterface(const AidlLocation& location, const std::string& name,
                              const Comments& comments, bool oneway, const std::string& package,
                              std::vector<std::unique_ptr<AidlMember>>* members)
@@ -1391,52 +1677,10 @@
   // Has to be a pointer due to deleting copy constructor. No idea why.
   map<string, const AidlMethod*> method_names;
   for (const auto& m : GetMethods()) {
-    if (!m->GetType().CheckValid(typenames)) {
+    if (!m->CheckValid(typenames)) {
       return false;
     }
 
-    // TODO(b/156872582): Support it when ParcelableHolder supports every backend.
-    if (m->GetType().GetName() == "ParcelableHolder") {
-      AIDL_ERROR(m) << "ParcelableHolder cannot be a return type";
-      return false;
-    }
-    if (m->IsOneway() && m->GetType().GetName() != "void") {
-      AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot return a value";
-      return false;
-    }
-
-    set<string> argument_names;
-    for (const auto& arg : m->GetArguments()) {
-      auto it = argument_names.find(arg->GetName());
-      if (it != argument_names.end()) {
-        AIDL_ERROR(m) << "method '" << m->GetName() << "' has duplicate argument name '"
-                      << arg->GetName() << "'";
-        return false;
-      }
-      argument_names.insert(arg->GetName());
-
-      if (!arg->CheckValid(typenames)) {
-        return false;
-      }
-
-      if (m->IsOneway() && arg->IsOut()) {
-        AIDL_ERROR(m) << "oneway method '" << m->GetName() << "' cannot have out parameters";
-        return false;
-      }
-
-      // check that the name doesn't match a keyword
-      if (IsJavaKeyword(arg->GetName().c_str())) {
-        AIDL_ERROR(arg) << "Argument name is a Java or aidl keyword";
-        return false;
-      }
-
-      // Reserve a namespace for internal use
-      if (android::base::StartsWith(arg->GetName(), "_aidl")) {
-        AIDL_ERROR(arg) << "Argument name cannot begin with '_aidl'";
-        return false;
-      }
-    }
-
     auto it = method_names.find(m->GetName());
     // prevent duplicate methods
     if (it == method_names.end()) {
@@ -1454,6 +1698,10 @@
       AIDL_ERROR(m) << " method " << m->Signature() << " is reserved for internal use.";
       return false;
     }
+
+    if (!CheckValidPermissionAnnotations(*m.get())) {
+      return false;
+    }
   }
 
   bool success = true;
@@ -1469,6 +1717,31 @@
   return success;
 }
 
+bool AidlInterface::CheckValidPermissionAnnotations(const AidlMethod& m) const {
+  if (IsPermissionNone() || IsPermissionManual()) {
+    if (m.GetType().IsPermissionNone() || m.GetType().IsPermissionManual() ||
+        m.GetType().EnforceExpression()) {
+      std::string interface_annotation = IsPermissionNone()
+                                             ? "requiring no permission"
+                                             : "manually implementing permission checks";
+      AIDL_ERROR(m) << "The interface " << GetName() << " is annotated as " << interface_annotation
+                    << " but the method " << m.GetName() << " is also annotated.\n"
+                    << "Consider distributing the annotation to each method.";
+      return false;
+    }
+  } else if (EnforceExpression()) {
+    if (m.GetType().IsPermissionNone() || m.GetType().IsPermissionManual()) {
+      AIDL_ERROR(m) << "The interface " << GetName()
+                    << " enforces permissions using annotations"
+                       " but the method "
+                    << m.GetName() << " is also annotated.\n"
+                    << "Consider distributing the annotation to each method.";
+      return false;
+    }
+  }
+  return true;
+}
+
 std::string AidlInterface::GetDescriptor() const {
   std::string annotatedDescriptor = AidlAnnotatable::GetDescriptor();
   if (annotatedDescriptor != "") {
@@ -1477,35 +1750,49 @@
   return GetCanonicalName();
 }
 
-AidlImport::AidlImport(const AidlLocation& location, const std::string& needed_class,
-                       const Comments& comments)
-    : AidlNode(location, comments), needed_class_(needed_class) {}
+AidlDocument::AidlDocument(const AidlLocation& location, const Comments& comments,
+                           std::vector<string> imports,
+                           std::vector<std::unique_ptr<AidlDefinedType>> defined_types,
+                           bool is_preprocessed)
+    : AidlCommentable(location, comments),
+      AidlScope(this),
+      imports_(std::move(imports)),
+      defined_types_(std::move(defined_types)),
+      is_preprocessed_(is_preprocessed) {
+  for (const auto& t : defined_types_) {
+    t->SetEnclosingScope(this);
+  }
+}
 
-// Resolves unresolved type name to fully qualified typename to import
-// case #1: SimpleName --> import p.SimpleName
-// case #2: Outer.Inner --> import p.Outer
-// case #3: p.SimpleName --> (as is)
-std::optional<std::string> AidlDocument::ResolveName(const std::string& unresolved_name) const {
-  std::string canonical_name;
-  const auto first_dot = unresolved_name.find_first_of('.');
+// Resolves type name in the current document.
+// - built-in types
+// - imported types
+// - top-level type
+std::string AidlDocument::ResolveName(const std::string& name) const {
+  if (AidlTypenames::IsBuiltinTypename(name)) {
+    return name;
+  }
+
+  const auto first_dot = name.find_first_of('.');
+  // For "Outer.Inner", we look up "Outer" in the import list.
   const std::string class_name =
-      (first_dot == std::string::npos) ? unresolved_name : unresolved_name.substr(0, first_dot);
+      (first_dot == std::string::npos) ? name : name.substr(0, first_dot);
+  // Keep ".Inner", to make a fully-qualified name
+  const std::string nested_type = (first_dot == std::string::npos) ? "" : name.substr(first_dot);
+
   for (const auto& import : Imports()) {
-    const auto& fq_name = import->GetNeededClass();
-    const auto last_dot = fq_name.find_last_of('.');
-    const std::string imported_type_name =
-        (last_dot == std::string::npos) ? fq_name : fq_name.substr(last_dot + 1);
-    if (imported_type_name == class_name) {
-      if (canonical_name != "" && canonical_name != fq_name) {
-        AIDL_ERROR(import) << "Ambiguous type: " << canonical_name << " vs. " << fq_name;
-        return {};
-      }
-      canonical_name = fq_name;
+    if (SimpleName(import) == class_name) {
+      return import + nested_type;
     }
   }
-  // if not found, use unresolved_name as it is
-  if (canonical_name == "") {
-    return unresolved_name;
+
+  // check if it is a top-level type.
+  for (const auto& type : DefinedTypes()) {
+    if (type->GetName() == class_name) {
+      return type->GetCanonicalName() + nested_type;
+    }
   }
-  return canonical_name;
+
+  // name itself might be fully-qualified name.
+  return name;
 }
diff --git a/aidl_language.h b/aidl_language.h
index 931c606..c73618f 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -20,8 +20,10 @@
 #include <regex>
 #include <string>
 #include <unordered_set>
+#include <variant>
 #include <vector>
 
+#include <android-base/result.h>
 #include <android-base/strings.h>
 
 #include "aidl_typenames.h"
@@ -32,11 +34,13 @@
 #include "location.h"
 #include "logging.h"
 #include "options.h"
+#include "permission.h"
 
 using android::aidl::AidlTypenames;
 using android::aidl::CodeWriter;
 using android::aidl::Comments;
 using android::aidl::Options;
+using android::base::Result;
 using std::shared_ptr;
 using std::string;
 using std::unique_ptr;
@@ -78,8 +82,6 @@
 bool ParseFloating(std::string_view sv, float* parsed);
 
 class AidlDocument;
-class AidlPackage;
-class AidlImport;
 class AidlInterface;
 class AidlParcelable;
 class AidlStructuredParcelable;
@@ -117,8 +119,23 @@
   virtual void Visit(const AidlUnaryConstExpression&) {}
   virtual void Visit(const AidlBinaryConstExpression&) {}
   virtual void Visit(const AidlAnnotation&) {}
-  virtual void Visit(const AidlImport&) {}
-  virtual void Visit(const AidlPackage&) {}
+};
+
+class AidlScope {
+ public:
+  AidlScope(const AidlNode* self) : self_(self) {}
+  virtual ~AidlScope() = default;
+  virtual std::string ResolveName(const std::string& name) const = 0;
+  void SetEnclosingScope(const AidlScope* enclosing) {
+    AIDL_FATAL_IF(enclosing_, AIDL_LOCATION_HERE) << "SetEnclosingScope can be set only once.";
+    enclosing_ = enclosing;
+  }
+  const AidlScope* GetEnclosingScope() const { return enclosing_; }
+  const AidlNode& GetNode() const { return *self_; }
+
+ private:
+  const AidlNode* self_;
+  const AidlScope* enclosing_ = nullptr;
 };
 
 // Anything that is locatable in a .aidl file.
@@ -126,9 +143,10 @@
  public:
   AidlNode(const AidlLocation& location, const Comments& comments = {});
 
-  AidlNode(const AidlNode&) = default;
-  virtual ~AidlNode() = default;
+  virtual ~AidlNode();
 
+  AidlNode(AidlNode&) = delete;
+  AidlNode& operator=(AidlNode&) = delete;
   AidlNode(AidlNode&&) = delete;
   AidlNode& operator=(AidlNode&&) = delete;
 
@@ -144,11 +162,19 @@
   const Comments& GetComments() const { return comments_; }
   void SetComments(const Comments& comments) { comments_ = comments; }
 
+  static void ClearUnvisitedNodes();
+  static const std::vector<AidlLocation>& GetLocationsOfUnvisitedNodes();
+  void MarkVisited() const;
+
  private:
   std::string PrintLine() const;
   std::string PrintLocation() const;
   const AidlLocation location_;
   Comments comments_;
+
+  // make sure we are able to abort if types are not visited
+  mutable bool visited_ = false;
+  static std::vector<AidlLocation> unvisited_locations_;
 };
 
 // unique_ptr<AidlTypeSpecifier> for type arugment,
@@ -170,9 +196,6 @@
 
   virtual const AidlNode& AsAidlNode() const = 0;
 
- protected:
-  AidlParameterizable(const AidlParameterizable&);
-
  private:
   unique_ptr<std::vector<T>> type_params_;
   static_assert(std::is_same<T, unique_ptr<AidlTypeSpecifier>>::value ||
@@ -193,8 +216,9 @@
 
 // Transforms a value string into a language specific form. Raw value as produced by
 // AidlConstantValue.
-using ConstantValueDecorator =
-    std::function<std::string(const AidlTypeSpecifier& type, const std::string& raw_value)>;
+using ConstantValueDecorator = std::function<std::string(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value)>;
 
 class AidlAnnotation : public AidlNode {
  public:
@@ -209,11 +233,18 @@
     SENSITIVE_DATA,
     JAVA_PASSTHROUGH,
     JAVA_DERIVE,
+    JAVA_DEFAULT,
+    JAVA_DELEGATOR,
     JAVA_ONLY_IMMUTABLE,
+    JAVA_SUPPRESS_LINT,
     FIXED_SIZE,
     DESCRIPTOR,
     RUST_DERIVE,
     SUPPRESS_WARNINGS,
+    PERMISSION_ENFORCE,
+    PERMISSION_NONE,
+    PERMISSION_MANUAL,
+    PROPAGATE_ALLOW_BLOCKING,
   };
 
   using TargetContext = uint16_t;
@@ -235,12 +266,11 @@
 
   static std::string TypeToString(Type type);
 
-  static AidlAnnotation* Parse(
+  static std::unique_ptr<AidlAnnotation> Parse(
       const AidlLocation& location, const string& name,
-      std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list,
+      std::map<std::string, std::shared_ptr<AidlConstantValue>> parameter_list,
       const Comments& comments);
 
-  AidlAnnotation(const AidlAnnotation&) = default;
   AidlAnnotation(AidlAnnotation&&) = default;
   virtual ~AidlAnnotation() = default;
   bool CheckValid() const;
@@ -262,6 +292,8 @@
   void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override;
   void DispatchVisit(AidlVisitor& v) const override { v.Visit(*this); }
 
+  Result<unique_ptr<android::aidl::perm::Expression>> EnforceExpression() const;
+
  private:
   struct ParamType {
     std::string name;
@@ -289,7 +321,7 @@
   static const std::vector<Schema>& AllSchemas();
 
   AidlAnnotation(const AidlLocation& location, const Schema& schema,
-                 std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters,
+                 std::map<std::string, std::shared_ptr<AidlConstantValue>> parameters,
                  const Comments& comments);
 
   const Schema& schema_;
@@ -307,16 +339,15 @@
  public:
   AidlAnnotatable(const AidlLocation& location, const Comments& comments);
 
-  AidlAnnotatable(const AidlAnnotatable&) = default;
-  AidlAnnotatable(AidlAnnotatable&&) = default;
   virtual ~AidlAnnotatable() = default;
 
-  void Annotate(vector<AidlAnnotation>&& annotations) {
+  void Annotate(vector<std::unique_ptr<AidlAnnotation>>&& annotations) {
     for (auto& annotation : annotations) {
       annotations_.emplace_back(std::move(annotation));
     }
   }
   bool IsNullable() const;
+  bool IsHeapNullable() const;
   bool IsUtf8InCpp() const;
   bool IsSensitiveData() const;
   bool IsVintfStability() const;
@@ -325,41 +356,61 @@
   bool IsStableApiParcelable(Options::Language lang) const;
   bool IsHide() const;
   bool JavaDerive(const std::string& method) const;
+  bool IsJavaDefault() const;
+  bool IsJavaDelegator() const;
   std::string GetDescriptor() const;
 
   const AidlAnnotation* UnsupportedAppUsage() const;
   const AidlAnnotation* RustDerive() const;
   const AidlAnnotation* BackingType() const;
   std::vector<std::string> SuppressWarnings() const;
+  std::unique_ptr<android::aidl::perm::Expression> EnforceExpression() const;
+  bool IsPermissionManual() const;
+  bool IsPermissionNone() const;
+  bool IsPropagateAllowBlocking() const;
 
   // ToString is for dumping AIDL.
   // Returns string representation of annotations.
   // e.g) "@JavaDerive(toString=true) @RustDerive(Clone=true, Copy=true)"
   std::string ToString() const;
 
-  const vector<AidlAnnotation>& GetAnnotations() const { return annotations_; }
+  const vector<std::unique_ptr<AidlAnnotation>>& GetAnnotations() const { return annotations_; }
   bool CheckValid(const AidlTypenames&) const;
   void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override {
     for (const auto& annot : GetAnnotations()) {
-      traverse(annot);
+      traverse(*annot);
     }
   }
 
  private:
-  vector<AidlAnnotation> annotations_;
+  vector<std::unique_ptr<AidlAnnotation>> annotations_;
 };
 
+// Represents `[]`
+struct DynamicArray {};
+// Represents `[N][M]..`
+struct FixedSizeArray {
+  FixedSizeArray(std::unique_ptr<AidlConstantValue> dim) { dimensions.push_back(std::move(dim)); }
+  std::vector<std::unique_ptr<AidlConstantValue>> dimensions;
+};
+// Represents `[]` or `[N]` part of type specifier
+using ArrayType = std::variant<DynamicArray, FixedSizeArray>;
+
 // AidlTypeSpecifier represents a reference to either a built-in type,
 // a defined type, or a variant (e.g., array of generic) of a type.
 class AidlTypeSpecifier final : public AidlAnnotatable,
                                 public AidlParameterizable<unique_ptr<AidlTypeSpecifier>> {
  public:
-  AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name, bool is_array,
+  AidlTypeSpecifier(const AidlLocation& location, const string& unresolved_name,
+                    std::optional<ArrayType> array,
                     vector<unique_ptr<AidlTypeSpecifier>>* type_params, const Comments& comments);
   virtual ~AidlTypeSpecifier() = default;
 
-  // Copy of this type which is not an array.
-  const AidlTypeSpecifier& ArrayBase() const;
+  // View of this type which has one-less dimension(s).
+  // e.g.) T[] => T, T[N][M] => T[M]
+  void ViewAsArrayBase(std::function<void(const AidlTypeSpecifier&)> func) const;
+  // ViewAsArrayBase passes "mutated" type to its callback.
+  bool IsMutated() const { return mutated_; }
 
   // Returns the full-qualified name of the base type.
   // int -> int
@@ -392,48 +443,54 @@
 
   bool IsResolved() const { return fully_qualified_name_ != ""; }
 
-  bool IsArray() const { return is_array_; }
-
-  __attribute__((warn_unused_result)) bool SetArray() {
-    if (is_array_) return false;
-    is_array_ = true;
-    return true;
+  bool IsArray() const { return array_.has_value(); }
+  bool IsDynamicArray() const {
+    return array_.has_value() && std::get_if<DynamicArray>(&*array_) != nullptr;
   }
+  bool IsFixedSizeArray() const {
+    return array_.has_value() && std::get_if<FixedSizeArray>(&*array_) != nullptr;
+  }
+  std::vector<int32_t> GetFixedSizeArrayDimensions() const;
+
+  const ArrayType& GetArray() const {
+    AIDL_FATAL_IF(!array_.has_value(), this) << "GetArray() for non-array type";
+    return array_.value();
+  }
+
+  // Accept transitions from
+  //    T    to T[]
+  // or T    to T[N]
+  // or T[N] to T[N][M]
+  __attribute__((warn_unused_result)) bool MakeArray(ArrayType array_type);
 
   // Resolve the base type name to a fully-qualified name. Return false if the
   // resolution fails.
-  bool Resolve(const AidlTypenames& typenames);
+  bool Resolve(const AidlTypenames& typenames, const AidlScope* scope);
 
   bool CheckValid(const AidlTypenames& typenames) const;
-  bool LanguageSpecificCheckValid(const AidlTypenames& typenames, Options::Language lang) const;
+  bool LanguageSpecificCheckValid(Options::Language lang) const;
   const AidlNode& AsAidlNode() const override { return *this; }
 
   const AidlDefinedType* GetDefinedType() const;
-  void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override {
-    AidlAnnotatable::TraverseChildren(traverse);
-    if (IsGeneric()) {
-      for (const auto& tp : GetTypeParameters()) {
-        traverse(*tp);
-      }
-    }
-  }
+  void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override;
   void DispatchVisit(AidlVisitor& v) const override { v.Visit(*this); }
 
  private:
-  AidlTypeSpecifier(const AidlTypeSpecifier&) = default;
-
   const string unresolved_name_;
   string fully_qualified_name_;
-  bool is_array_;
+  mutable std::optional<ArrayType> array_;
+  mutable bool mutated_ = false;  // ViewAsArrayBase() sets this as true to distinguish mutated one
+                                  // from the original type
   vector<string> split_name_;
   const AidlDefinedType* defined_type_ = nullptr;  // set when Resolve() for defined types
-  mutable shared_ptr<AidlTypeSpecifier> array_base_;
 };
 
 // Returns the universal value unaltered.
-std::string AidlConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value);
+std::string AidlConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value);
 
-class AidlMember : public AidlCommentable {
+class AidlMember : public AidlAnnotatable {
  public:
   AidlMember(const AidlLocation& location, const Comments& comments);
   virtual ~AidlMember() = default;
@@ -443,22 +500,6 @@
   AidlMember(AidlMember&&) = delete;
   AidlMember& operator=(const AidlMember&) = delete;
   AidlMember& operator=(AidlMember&&) = delete;
-
-  virtual const AidlMethod* AsMethod() const { return nullptr; }
-  virtual const AidlConstantDeclaration* AsConstantDeclaration() const { return nullptr; }
-  virtual const AidlVariableDeclaration* AsVariableDeclaration() const { return nullptr; }
-
-  AidlMethod* AsMethod() {
-    return const_cast<AidlMethod*>(const_cast<const AidlMember*>(this)->AsMethod());
-  }
-  AidlConstantDeclaration* AsConstantDeclaration() {
-    return const_cast<AidlConstantDeclaration*>(
-        const_cast<const AidlMember*>(this)->AsConstantDeclaration());
-  }
-  AidlVariableDeclaration* AsVariableDeclaration() {
-    return const_cast<AidlVariableDeclaration*>(
-        const_cast<const AidlMember*>(this)->AsVariableDeclaration());
-  }
 };
 
 // TODO: This class is used for method arguments and also parcelable fields,
@@ -478,8 +519,6 @@
   AidlVariableDeclaration& operator=(const AidlVariableDeclaration&) = delete;
   AidlVariableDeclaration& operator=(AidlVariableDeclaration&&) = delete;
 
-  const AidlVariableDeclaration* AsVariableDeclaration() const override { return this; }
-
   std::string GetName() const { return name_; }
   std::string GetCapitalizedName() const;
   const AidlTypeSpecifier& GetType() const { return *type_; }
@@ -546,9 +585,6 @@
   // e.g) "in @utf8InCpp String[] names"
   std::string ToString() const;
 
-  void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override {
-    traverse(GetType());
-  }
   void DispatchVisit(AidlVisitor& v) const override { v.Visit(*this); }
 
  private:
@@ -645,6 +681,7 @@
   Type GetType() const { return final_type_; }
   const std::string& Literal() const { return value_; }
 
+  bool Evaluate() const;
   virtual bool CheckValid() const;
 
   // Raw value of type (currently valid in C++ and Java). Empty string on error.
@@ -700,8 +737,10 @@
   const std::string& GetFieldName() const { return field_name_; }
 
   bool CheckValid() const override;
-  void TraverseChildren(std::function<void(const AidlNode&)>) const override {
-    // resolved_ is not my child.
+  void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override {
+    if (ref_type_) {
+      traverse(*ref_type_);
+    }
   }
   void DispatchVisit(AidlVisitor& v) const override { v.Visit(*this); }
   const AidlConstantValue* Resolve(const AidlDefinedType* scope) const;
@@ -798,8 +837,6 @@
     return value_->ValueString(GetType(), decorator);
   }
 
-  const AidlConstantDeclaration* AsConstantDeclaration() const override { return this; }
-
   void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override {
     traverse(GetType());
     traverse(GetValue());
@@ -827,7 +864,7 @@
   AidlMethod& operator=(const AidlMethod&) = delete;
   AidlMethod& operator=(AidlMethod&&) = delete;
 
-  const AidlMethod* AsMethod() const override { return this; }
+  bool CheckValid(const AidlTypenames&) const;
   const AidlTypeSpecifier& GetType() const { return *type_; }
   AidlTypeSpecifier* GetMutableType() { return type_.get(); }
 
@@ -888,7 +925,7 @@
 
 // AidlDefinedType represents either an interface, parcelable, or enum that is
 // defined in the source file.
-class AidlDefinedType : public AidlAnnotatable {
+class AidlDefinedType : public AidlMember, public AidlScope {
  public:
   AidlDefinedType(const AidlLocation& location, const std::string& name, const Comments& comments,
                   const std::string& package, std::vector<std::unique_ptr<AidlMember>>* members);
@@ -902,11 +939,17 @@
 
   const std::string& GetName() const { return name_; };
 
+  std::string ResolveName(const std::string& name) const override;
+
   /* dot joined package, example: "android.package.foo" */
   std::string GetPackage() const { return package_; }
   /* dot joined package and name, example: "android.package.foo.IBar" */
   std::string GetCanonicalName() const;
-  const std::vector<std::string>& GetSplitPackage() const { return split_package_; }
+  std::vector<std::string> GetSplitPackage() const {
+    if (package_.empty()) return std::vector<std::string>();
+    return android::base::Split(package_, ".");
+  }
+  const AidlDocument& GetDocument() const;
 
   virtual std::string GetPreprocessDeclarationName() const = 0;
 
@@ -917,8 +960,7 @@
   virtual const AidlInterface* AsInterface() const { return nullptr; }
   virtual const AidlParameterizable<std::string>* AsParameterizable() const { return nullptr; }
   virtual bool CheckValid(const AidlTypenames& typenames) const;
-  virtual bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
-                                          Options::Language lang) const = 0;
+  bool LanguageSpecificCheckValid(Options::Language lang) const;
   AidlStructuredParcelable* AsStructuredParcelable() {
     return const_cast<AidlStructuredParcelable*>(
         const_cast<const AidlDefinedType*>(this)->AsStructuredParcelable());
@@ -952,7 +994,9 @@
     return const_cast<AidlParcelable*>(
         const_cast<const AidlDefinedType*>(this)->AsUnstructuredParcelable());
   }
-
+  const AidlDefinedType* GetParentType() const;
+  const AidlDefinedType* GetRootType() const;
+  const std::vector<std::unique_ptr<AidlDefinedType>>& GetNestedTypes() const { return types_; }
   const std::vector<std::unique_ptr<AidlVariableDeclaration>>& GetFields() const {
     return variables_;
   }
@@ -960,7 +1004,10 @@
     return constants_;
   }
   const std::vector<std::unique_ptr<AidlMethod>>& GetMethods() const { return methods_; }
-  void AddMethod(std::unique_ptr<AidlMethod> method) { methods_.push_back(std::move(method)); }
+  void AddMethod(std::unique_ptr<AidlMethod> method) {
+    members_.push_back(method.get());
+    methods_.push_back(std::move(method));
+  }
   const std::vector<const AidlMember*>& GetMembers() const { return members_; }
   void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override {
     AidlAnnotatable::TraverseChildren(traverse);
@@ -977,11 +1024,11 @@
   bool CheckValidWithMembers(const AidlTypenames& typenames) const;
 
   std::string name_;
-  const std::string package_;
-  const std::vector<std::string> split_package_;
+  std::string package_;
   std::vector<std::unique_ptr<AidlVariableDeclaration>> variables_;
   std::vector<std::unique_ptr<AidlConstantDeclaration>> constants_;
   std::vector<std::unique_ptr<AidlMethod>> methods_;
+  std::vector<std::unique_ptr<AidlDefinedType>> types_;
   std::vector<const AidlMember*> members_;  // keep members in order of appearance.
 };
 
@@ -1002,8 +1049,6 @@
   std::string GetCppHeader() const { return cpp_header_; }
 
   bool CheckValid(const AidlTypenames& typenames) const override;
-  bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
-                                  Options::Language lang) const override;
   const AidlParcelable* AsParcelable() const override { return this; }
   const AidlParameterizable<std::string>* AsParameterizable() const override { return this; }
   const AidlNode& AsAidlNode() const override { return *this; }
@@ -1033,9 +1078,6 @@
   std::string GetPreprocessDeclarationName() const override { return "structured_parcelable"; }
 
   bool CheckValid(const AidlTypenames& typenames) const override;
-  bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
-                                  Options::Language lang) const override;
-
   void DispatchVisit(AidlVisitor& v) const override { v.Visit(*this); }
 };
 
@@ -1091,16 +1133,15 @@
     return enumerators_;
   }
   bool CheckValid(const AidlTypenames& typenames) const override;
-  bool LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
-                                  Options::Language) const override {
-    return true;
-  }
   std::string GetPreprocessDeclarationName() const override { return "enum"; }
 
   const AidlEnumDeclaration* AsEnumDeclaration() const override { return this; }
 
   void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override {
     AidlDefinedType::TraverseChildren(traverse);
+    if (backing_type_) {
+      traverse(*backing_type_);
+    }
     for (const auto& c : GetEnumerators()) {
       traverse(*c);
     }
@@ -1130,8 +1171,6 @@
 
   const AidlNode& AsAidlNode() const override { return *this; }
   bool CheckValid(const AidlTypenames& typenames) const override;
-  bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
-                                  Options::Language lang) const override;
   std::string GetPreprocessDeclarationName() const override { return "union"; }
 
   const AidlUnionDecl* AsUnionDeclaration() const override { return this; }
@@ -1141,7 +1180,7 @@
 class AidlInterface final : public AidlDefinedType {
  public:
   AidlInterface(const AidlLocation& location, const std::string& name, const Comments& comments,
-                bool oneway_, const std::string& package,
+                bool oneway, const std::string& package,
                 std::vector<std::unique_ptr<AidlMember>>* members);
   virtual ~AidlInterface() = default;
 
@@ -1155,51 +1194,21 @@
   std::string GetPreprocessDeclarationName() const override { return "interface"; }
 
   bool CheckValid(const AidlTypenames& typenames) const override;
-  bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
-                                  Options::Language lang) const override;
-
+  bool CheckValidPermissionAnnotations(const AidlMethod& m) const;
   std::string GetDescriptor() const;
   void DispatchVisit(AidlVisitor& v) const override { v.Visit(*this); }
 };
 
-class AidlPackage : public AidlNode {
- public:
-  AidlPackage(const AidlLocation& location, const Comments& comments)
-      : AidlNode(location, comments) {}
-  virtual ~AidlPackage() = default;
-  void TraverseChildren(std::function<void(const AidlNode&)>) const {}
-  void DispatchVisit(AidlVisitor& v) const { v.Visit(*this); }
-};
-
-class AidlImport : public AidlNode {
- public:
-  AidlImport(const AidlLocation& location, const std::string& needed_class,
-             const Comments& comments);
-  virtual ~AidlImport() = default;
-
-  // non-copyable, non-movable
-  AidlImport(const AidlImport&) = delete;
-  AidlImport(AidlImport&&) = delete;
-  AidlImport& operator=(const AidlImport&) = delete;
-  AidlImport& operator=(AidlImport&&) = delete;
-
-  const std::string& GetNeededClass() const { return needed_class_; }
-  void TraverseChildren(std::function<void(const AidlNode&)>) const {}
-  void DispatchVisit(AidlVisitor& v) const { v.Visit(*this); }
-
- private:
-  std::string needed_class_;
-};
+inline std::string SimpleName(const std::string& qualified_name) {
+  return qualified_name.substr(qualified_name.rfind('.') + 1);
+}
 
 // AidlDocument models an AIDL file
-class AidlDocument : public AidlCommentable {
+class AidlDocument : public AidlCommentable, public AidlScope {
  public:
   AidlDocument(const AidlLocation& location, const Comments& comments,
-               std::vector<std::unique_ptr<AidlImport>> imports,
-               std::vector<std::unique_ptr<AidlDefinedType>> defined_types)
-      : AidlCommentable(location, comments),
-        imports_(std::move(imports)),
-        defined_types_(std::move(defined_types)) {}
+               std::vector<std::string> imports,
+               std::vector<std::unique_ptr<AidlDefinedType>> defined_types, bool is_preprocessed);
   ~AidlDocument() = default;
 
   // non-copyable, non-movable
@@ -1208,16 +1217,14 @@
   AidlDocument& operator=(const AidlDocument&) = delete;
   AidlDocument& operator=(AidlDocument&&) = delete;
 
-  std::optional<std::string> ResolveName(const std::string& unresolved_type) const;
-  const std::vector<std::unique_ptr<AidlImport>>& Imports() const { return imports_; }
+  std::string ResolveName(const std::string& name) const override;
+  const std::vector<std::string>& Imports() const { return imports_; }
   const std::vector<std::unique_ptr<AidlDefinedType>>& DefinedTypes() const {
     return defined_types_;
   }
+  bool IsPreprocessed() const { return is_preprocessed_; }
 
   void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override {
-    for (const auto& i : Imports()) {
-      traverse(*i);
-    }
     for (const auto& t : DefinedTypes()) {
       traverse(*t);
     }
@@ -1225,8 +1232,9 @@
   void DispatchVisit(AidlVisitor& v) const override { v.Visit(*this); }
 
  private:
-  const std::vector<std::unique_ptr<AidlImport>> imports_;
+  const std::vector<std::string> imports_;
   const std::vector<std::unique_ptr<AidlDefinedType>> defined_types_;
+  bool is_preprocessed_;
 };
 
 template <typename T>
@@ -1238,15 +1246,114 @@
   return it->second->EvaluatedValue<T>();
 }
 
-// Utility to make a visitor to visit AST tree in top-down order
+// Utilities to make a visitor to visit AST tree in top-down order
 // Given:       foo
 //              / \
 //            bar baz
 // VisitTopDown(v, foo) makes v visit foo -> bar -> baz.
-inline void VisitTopDown(AidlVisitor& v, const AidlNode& node) {
+inline void VisitTopDown(std::function<void(const AidlNode&)> v, const AidlNode& node) {
   std::function<void(const AidlNode&)> top_down = [&](const AidlNode& n) {
-    n.DispatchVisit(v);
+    v(n);
     n.TraverseChildren(top_down);
   };
   top_down(node);
-}
\ No newline at end of file
+}
+inline void VisitTopDown(AidlVisitor& v, const AidlNode& node) {
+  VisitTopDown([&](const AidlNode& n) { n.DispatchVisit(v); }, node);
+}
+
+// Utility to make a visitor to visit AST tree in bottom-up order
+// Given:       foo
+//              / \
+//            bar baz
+// VisitBottomUp(v, foo) makes v visit bar -> baz -> foo.
+inline void VisitBottomUp(AidlVisitor& v, const AidlNode& node) {
+  std::function<void(const AidlNode&)> bottom_up = [&](const AidlNode& n) {
+    n.TraverseChildren(bottom_up);
+    n.DispatchVisit(v);
+  };
+  bottom_up(node);
+}
+
+template <typename T>
+const T* AidlCast(const AidlNode& node) {
+  struct CastVisitor : AidlVisitor {
+    const T* cast = nullptr;
+    void Visit(const T& t) override { cast = &t; }
+  } visitor;
+  node.DispatchVisit(visitor);
+  return visitor.cast;
+}
+
+template <>
+const AidlDefinedType* AidlCast<AidlDefinedType>(const AidlNode& node);
+
+template <typename T>
+T* AidlCast(AidlNode& node) {
+  return const_cast<T*>(AidlCast<T>(const_cast<const AidlNode&>(node)));
+}
+
+template <typename AidlNodeType>
+vector<const AidlNodeType*> Collect(const AidlNode& root) {
+  vector<const AidlNodeType*> result;
+  std::function<void(const AidlNode&)> top_down = [&](const AidlNode& n) {
+    if (auto cast = AidlCast<AidlNodeType>(n); cast) {
+      result.push_back(cast);
+    }
+    n.TraverseChildren(top_down);
+  };
+  top_down(root);
+  return result;
+}
+
+template <typename VisitFn>
+bool TopologicalVisit(const vector<unique_ptr<AidlDefinedType>>& nested_types, VisitFn visit) {
+  // 1. Maps deeply nested types to one of nested_types
+  map<const AidlDefinedType*, const AidlDefinedType*> roots;
+  for (const auto& nested : nested_types) {
+    for (const auto& t : Collect<AidlDefinedType>(*nested)) {
+      roots[t] = nested.get();
+    }
+  }
+  // 2. Collect sibling types referenced within each nested type.
+  map<const AidlDefinedType*, vector<const AidlDefinedType*>> required_types;
+  for (const auto& nested : nested_types) {
+    for (const auto& t : Collect<AidlTypeSpecifier>(*nested)) {
+      if (auto defined_type = t->GetDefinedType(); defined_type) {
+        auto sibling = roots[defined_type];
+        if (sibling && sibling != nested.get()) {
+          required_types[nested.get()].push_back(sibling);
+        }
+      }
+    }
+  };
+  // 3. Run DFS
+  enum { NOT_STARTED = 0, STARTED = 1, FINISHED = 2 };
+  map<const AidlDefinedType*, int> visited;
+  std::function<bool(const AidlDefinedType&)> dfs = [&](const AidlDefinedType& type) {
+    if (visited[&type] == FINISHED) {
+      return true;
+    } else if (visited[&type] == STARTED) {
+      return false;
+    } else {
+      visited[&type] = STARTED;
+      // Visit every required dep first
+      for (const auto& dep_type : required_types[&type]) {
+        if (!dfs(*dep_type)) {
+          return false;
+        }
+      }
+      visited[&type] = FINISHED;
+      visit(type);
+      return true;
+    }
+  };
+
+  for (const auto& type : nested_types) {
+    if (!dfs(*type)) {
+      return false;
+    }
+  }
+
+  return true;
+}
diff --git a/aidl_language_l.ll b/aidl_language_l.ll
index 2b63b82..33054a3 100644
--- a/aidl_language_l.ll
+++ b/aidl_language_l.ll
@@ -36,8 +36,8 @@
 
 identifier  [_a-zA-Z][_a-zA-Z0-9]*
 whitespace  ([ \t\r]+)
-intvalue    [0-9]+[lL]?
-hexvalue    0[x|X][0-9a-fA-F]+[lL]?
+intvalue    [0-9]+[lL]?(u8)?
+hexvalue    0[x|X][0-9a-fA-F]+[lL]?(u8)?
 floatvalue  [0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?f?
 
 %%
@@ -58,7 +58,7 @@
 <LONG_COMMENT>\n+     { extra_text += yytext; yylloc->lines(yyleng); }
 <LONG_COMMENT>[^*\n]+ { extra_text += yytext; }
 
-\"[^\"]*\"            { yylval->token = new AidlToken(yytext, comments);
+\"([^\"]|\\.)*\"      { yylval->token = new AidlToken(yytext, comments);
                         return yy::parser::token::C_STR; }
 
 \/\/.*                { extra_text += yytext; extra_text += "\n";
diff --git a/aidl_language_y.yy b/aidl_language_y.yy
index 079bda6..11ab29e 100644
--- a/aidl_language_y.yy
+++ b/aidl_language_y.yy
@@ -71,10 +71,11 @@
     AidlToken* token;
     char character;
     std::string *str;
+    std::vector<std::unique_ptr<AidlToken>> *token_list;
     AidlAnnotation* annotation;
     AidlAnnotationParameter* param;
     std::map<std::string, std::shared_ptr<AidlConstantValue>>* param_list;
-    std::vector<AidlAnnotation>* annotation_list;
+    std::vector<std::unique_ptr<AidlAnnotation>>* annotation_list;
     AidlTypeSpecifier* type;
     AidlArgument* arg;
     AidlArgument::Direction direction;
@@ -90,9 +91,6 @@
     AidlDefinedType* declaration;
     std::vector<std::unique_ptr<AidlTypeSpecifier>>* type_args;
     std::vector<std::string>* type_params;
-    std::vector<std::unique_ptr<AidlImport>>* imports;
-    AidlImport* import;
-    AidlPackage* package;
     std::vector<std::unique_ptr<AidlDefinedType>>* declarations;
 }
 
@@ -175,23 +173,25 @@
 %type<const_expr> const_expr
 %type<constant_value_list> constant_value_list
 %type<constant_value_list> constant_value_non_empty_list
-%type<imports> imports
-%type<import> import
-%type<package> package
+%type<token_list> imports
 %type<declarations> decls
-%type<token> identifier error qualified_name
+%type<token> import identifier error qualified_name optional_package
 
 %%
 
 document
- : package imports decls {
+ : optional_package imports decls {
     Comments comments;
     if ($1) {
       comments = $1->GetComments();
     } else if (!$2->empty()) {
       comments = $2->front()->GetComments();
     }
-    ps->SetDocument(std::make_unique<AidlDocument>(loc(@1), comments, std::move(*$2), std::move(*$3)));
+    std::vector<std::string> imports;
+    for (const auto& import : *$2) {
+      imports.push_back(import->GetText());
+    }
+    ps->MakeDocument(loc(@1), comments, std::move(imports), std::move(*$3));
     delete $1;
     delete $2;
     delete $3;
@@ -208,36 +208,29 @@
  | CPP_HEADER
  ;
 
-package
+optional_package
  : {
     $$ = nullptr;
  }
  | PACKAGE qualified_name ';' {
-    $$ = new AidlPackage(loc(@1, @3), $1->GetComments());
     ps->SetPackage($2->GetText());
-    delete $1;
+    $$ = $1; // for comments
     delete $2;
   }
  ;
 
 imports
- : { $$ = new std::vector<std::unique_ptr<AidlImport>>(); }
+ : { $$ = new std::vector<std::unique_ptr<AidlToken>>(); }
  | imports import
   {
     $$ = $1;
-    auto it = std::find_if($$->begin(), $$->end(), [&](const auto& i) {
-      return $2->GetNeededClass() == i->GetNeededClass();
-    });
-    if (it == $$->end()) {
-      $$->emplace_back($2);
-    } else {
-      delete $2;
-    }
+    $$->emplace_back($2);
   }
 
 import
  : IMPORT qualified_name ';' {
-    $$ = new AidlImport(loc(@2), $2->GetText(), $1->GetComments());
+    // carry the comments before "import" token
+    $$ = new AidlToken($2->GetText(), $1->GetComments());
     delete $1;
     delete $2;
   };
@@ -274,7 +267,7 @@
 
     if ($1->size() > 0 && $$ != nullptr) {
       // copy comments from annotation to decl
-      $$->SetComments($1->begin()->GetComments());
+      $$->SetComments($1->begin()->get()->GetComments());
       $$->Annotate(std::move(*$1));
     }
 
@@ -309,16 +302,19 @@
 
 parcelable_decl
  : PARCELABLE qualified_name optional_type_params ';' {
+    // No check for type name here. We allow nested types for unstructured parcelables.
     $$ = new AidlParcelable(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), "", $3);
     delete $1;
     delete $2;
  }
  | PARCELABLE qualified_name optional_type_params '{' parcelable_members '}' {
+    ps->CheckValidTypeName(*$2, loc(@2));
     $$ = new AidlStructuredParcelable(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), $3, $5);
     delete $1;
     delete $2;
  }
  | PARCELABLE qualified_name CPP_HEADER C_STR ';' {
+    // No check for type name here. We allow nested types for unstructured parcelables.
     $$ = new AidlParcelable(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), $4->GetText());
     delete $1;
     delete $2;
@@ -343,6 +339,10 @@
     $1->emplace_back($2);
     $$ = $1;
   }
+ | parcelable_members decl {
+    if ($2) $1->emplace_back($2);  // decl may be nullptr on error
+    $$ = $1;
+  }
  | parcelable_members error ';' {
     ps->AddError();
     $$ = $1;
@@ -361,13 +361,21 @@
  ;
 
 interface_decl
- : INTERFACE identifier '{' interface_members '}' {
+ : INTERFACE qualified_name ';' {
+    ps->CheckValidTypeName(*$2, loc(@2));
+    $$ = new AidlInterface(loc(@1), $2->GetText(), $1->GetComments(), false, ps->Package(), nullptr);
+    delete $1;
+    delete $2;
+  }
+ | INTERFACE qualified_name '{' interface_members '}' {
+    ps->CheckValidTypeName(*$2, loc(@2));
     $$ = new AidlInterface(loc(@1), $2->GetText(), $1->GetComments(), false, ps->Package(), $4);
     delete $1;
     delete $2;
   }
- | ONEWAY INTERFACE identifier '{' interface_members '}' {
-    $$ = new AidlInterface(loc(@2), $3->GetText(),  $1->GetComments(), true, ps->Package(), $5);
+ | ONEWAY INTERFACE qualified_name '{' interface_members '}' {
+    ps->CheckValidTypeName(*$3, loc(@3));
+    $$ = new AidlInterface(loc(@2), $3->GetText(), $1->GetComments(), true, ps->Package(), $5);
     delete $1;
     delete $2;
     delete $3;
@@ -386,6 +394,11 @@
   { $1->push_back(std::unique_ptr<AidlMember>($2)); $$ = $1; }
  | interface_members constant_decl
   { $1->push_back(std::unique_ptr<AidlMember>($2)); $$ = $1; }
+ | interface_members decl
+  {
+    if ($2) $1->emplace_back($2);  // decl may be nullptr on error
+    $$ = $1;
+  }
  | interface_members error ';' {
     ps->AddError();
     $$ = $1;
@@ -538,7 +551,7 @@
 constant_decl
  : annotation_list CONST type identifier '=' const_expr ';' {
     if ($1->size() > 0) {
-      $3->SetComments($1->begin()->GetComments());
+      $3->SetComments($1->begin()->get()->GetComments());
     } else {
       $3->SetComments($2->GetComments());
     }
@@ -579,7 +592,8 @@
  ;
 
 enum_decl
- : ENUM identifier enum_decl_body {
+ : ENUM qualified_name enum_decl_body {
+    ps->CheckValidTypeName(*$2, loc(@2));
     $$ = new AidlEnumDeclaration(loc(@2), $2->GetText(), $3, ps->Package(), $1->GetComments());
     delete $1;
     delete $2;
@@ -589,6 +603,7 @@
 
 union_decl
  : UNION qualified_name optional_type_params '{' parcelable_members '}' {
+    ps->CheckValidTypeName(*$2, loc(@2));
     $$ = new AidlUnionDecl(loc(@2), $2->GetText(), ps->Package(), $1->GetComments(), $3, $5);
     delete $1;
     delete $2;
@@ -601,7 +616,7 @@
     delete $2;
   }
  | annotation_list ONEWAY type identifier '(' arg_list ')' ';' {
-    const auto& comments = ($1->size() > 0) ? $1->begin()->GetComments() : $2->GetComments();
+    const auto& comments = ($1->size() > 0) ? $1->begin()->get()->GetComments() : $2->GetComments();
     $$ = new AidlMethod(loc(@4), true, $3, $4->GetText(), $6, comments);
     $3->Annotate(std::move(*$1));
     delete $1;
@@ -619,7 +634,7 @@
     delete $7;
   }
  | annotation_list ONEWAY type identifier '(' arg_list ')' '=' INTVALUE ';' {
-    const auto& comments = ($1->size() > 0) ? $1->begin()->GetComments() : $2->GetComments();
+    const auto& comments = ($1->size() > 0) ? $1->begin()->get()->GetComments() : $2->GetComments();
     int32_t serial = 0;
     if (!android::base::ParseInt($9->GetText(), &serial)) {
         AIDL_ERROR(loc(@9)) << "Could not parse int value: " << $9->GetText();
@@ -661,10 +676,9 @@
 
 non_array_type
  : annotation_list qualified_name {
-    $$ = new AidlTypeSpecifier(loc(@2), $2->GetText(), false, nullptr, $2->GetComments());
-    ps->DeferResolution($$);
+    $$ = new AidlTypeSpecifier(loc(@2), $2->GetText(), /*array=*/std::nullopt, nullptr, $2->GetComments());
     if (!$1->empty()) {
-      $$->SetComments($1->begin()->GetComments());
+      $$->SetComments($1->begin()->get()->GetComments());
       $$->Annotate(std::move(*$1));
     }
     delete $1;
@@ -695,8 +709,20 @@
       AIDL_ERROR(loc(@2)) << "Annotations for arrays are not supported.";
       ps->AddError();
     }
-    if (!$1->SetArray()) {
-      AIDL_ERROR(loc(@1)) << "Can only have one dimensional arrays.";
+    if (!$1->MakeArray(DynamicArray{})) {
+      AIDL_ERROR(loc(@1)) << "Multi-dimensional arrays must be fixed size.";
+      ps->AddError();
+    }
+    $$ = $1;
+    delete $2;
+  }
+ | type annotation_list '[' const_expr ']' {
+    if (!$2->empty()) {
+      AIDL_ERROR(loc(@2)) << "Annotations for arrays are not supported.";
+      ps->AddError();
+    }
+    if (!$1->MakeArray(FixedSizeArray{std::unique_ptr<AidlConstantValue>($4)})) {
+      AIDL_ERROR(loc(@1)) << "Multi-dimensional arrays must be fixed size.";
       ps->AddError();
     }
     $$ = $1;
@@ -720,12 +746,11 @@
 
 annotation_list
  :
-  { $$ = new std::vector<AidlAnnotation>(); }
+  { $$ = new std::vector<std::unique_ptr<AidlAnnotation>>(); }
  | annotation_list annotation
   {
     if ($2 != nullptr) {
-      $1->emplace_back(std::move(*$2));
-      delete $2;
+      $1->emplace_back(std::unique_ptr<AidlAnnotation>($2));
     }
     $$ = $1;
   };
@@ -762,14 +787,25 @@
 
 annotation
  : ANNOTATION {
-    $$ = AidlAnnotation::Parse(loc(@1), $1->GetText(), nullptr, $1->GetComments());
+    // release() returns nullptr if unique_ptr is empty.
+    $$ = AidlAnnotation::Parse(loc(@1), $1->GetText(), {}, $1->GetComments()).release();
+    if (!$$) {
+      ps->AddError();
+    }
+    delete $1;
+  }
+ | ANNOTATION '(' const_expr ')' {
+    auto value = std::shared_ptr<AidlConstantValue>($3);
+    std::map<std::string, std::shared_ptr<AidlConstantValue>> parameter_list {{"value" , value}};
+    $$ = AidlAnnotation::Parse(loc(@1, @4), $1->GetText(), std::move(parameter_list), $1->GetComments()).release();
     if (!$$) {
       ps->AddError();
     }
     delete $1;
   }
  | ANNOTATION '(' parameter_list ')' {
-    $$ = AidlAnnotation::Parse(loc(@1, @4), $1->GetText(), $3, $1->GetComments());
+    // release() returns nullptr if unique_ptr is empty.
+    $$ = AidlAnnotation::Parse(loc(@1, @4), $1->GetText(), std::move(*$3), $1->GetComments()).release();
     if (!$$) {
       ps->AddError();
     }
diff --git a/aidl_to_cpp.cpp b/aidl_to_cpp.cpp
index 40552c8..987aba5 100644
--- a/aidl_to_cpp.cpp
+++ b/aidl_to_cpp.cpp
@@ -35,6 +35,7 @@
 namespace cpp {
 
 namespace {
+
 std::string RawParcelMethod(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
                             bool readMethod) {
   static map<string, string> kBuiltin = {
@@ -70,6 +71,10 @@
   const bool isVector = type.IsArray() || typenames.IsList(type);
   const bool utf8 = type.IsUtf8InCpp();
 
+  if (type.IsFixedSizeArray()) {
+    return "FixedArray";
+  }
+
   if (auto enum_decl = typenames.GetEnumDeclaration(type); enum_decl != nullptr) {
     if (isVector) {
       return "EnumVector";
@@ -147,6 +152,9 @@
 
   if (raw_type.IsNullable() && !AidlTypenames::IsPrimitiveTypename(type.GetName()) &&
       type.GetName() != "IBinder" && typenames.GetEnumDeclaration(type) == nullptr) {
+    if (raw_type.IsHeapNullable()) {
+      return "::std::unique_ptr<" + type_str + ">";
+    }
     return "::std::optional<" + type_str + ">";
   }
   return type_str;
@@ -186,52 +194,50 @@
   if (definedType != nullptr && definedType->AsInterface() != nullptr) {
     return "::android::sp<" + GetRawCppName(type) + ">";
   }
-
-  return WrapIfNullable(GetRawCppName(type), raw_type, typenames);
-}
-}  // namespace
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
-  if (type.IsArray()) {
-    return raw_value;
-  }
-
-  if (type.GetName() == "long") {
-    return raw_value + "L";
-  }
-
-  if (type.GetName() == "String" && !type.IsUtf8InCpp()) {
-    return "::android::String16(" + raw_value + ")";
-  }
-
-  if (auto defined_type = type.GetDefinedType(); defined_type) {
-    auto enum_type = defined_type->AsEnumDeclaration();
-    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
-    return GetRawCppName(type) + "::" + raw_value.substr(raw_value.find_last_of('.') + 1);
-  }
-
-  return raw_value;
-};
-
-std::string GetTransactionIdFor(const AidlInterface& iface, const AidlMethod& method) {
-  return ClassName(iface, ClassNames::SERVER) + "::TRANSACTION_" + method.GetName();
-}
-
-std::string CppNameOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
-  if (type.IsArray() || typenames.IsList(type)) {
-    std::string cpp_name = GetCppName(type, typenames);
-    if (type.IsNullable()) {
-      return "::std::optional<::std::vector<" + cpp_name + ">>";
-    }
-    return "::std::vector<" + cpp_name + ">";
-  } else if (type.IsGeneric()) {
+  auto cpp_name = GetRawCppName(type);
+  if (type.IsGeneric()) {
     std::vector<std::string> type_params;
     for (const auto& parameter : type.GetTypeParameters()) {
       type_params.push_back(CppNameOf(*parameter, typenames));
     }
-    return StringPrintf("%s<%s>", GetCppName(type, typenames).c_str(),
-                        base::Join(type_params, ", ").c_str());
+    cpp_name += "<" + base::Join(type_params, ", ") + ">";
   }
-  return GetCppName(type, typenames);
+  return WrapIfNullable(cpp_name, raw_type, typenames);
+}
+}  // namespace
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value) {
+  return CppConstantValueDecorator(type, raw_value, /*is_ndk=*/false);
+};
+
+std::string GetTransactionIdFor(const std::string& clazz, const AidlMethod& method) {
+  return clazz + "::TRANSACTION_" + method.GetName();
+}
+
+std::string CppNameOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
+  // get base type's cpp_name with nullable processed.
+  std::string cpp_name = GetCppName(type, typenames);
+
+  if (type.IsArray() || typenames.IsList(type)) {
+    if (type.IsFixedSizeArray()) {
+      auto dimensions = type.GetFixedSizeArrayDimensions();
+      for (auto it = rbegin(dimensions), end = rend(dimensions); it != end; it++) {
+        cpp_name = "std::array<" + cpp_name + ", " + std::to_string(*it) + ">";
+      }
+    } else {
+      cpp_name = "::std::vector<" + cpp_name + ">";
+    }
+
+    // wrap nullable again because @nullable applies to BOTH array type(outermost type) AND base
+    // type(innermost type)
+    if (type.IsHeapNullable()) {
+      cpp_name = "::std::unique_ptr<" + cpp_name + ">";
+    } else if (type.IsNullable()) {
+      cpp_name = "::std::optional<" + cpp_name + ">";
+    }
+  }
+  return cpp_name;
 }
 
 bool IsNonCopyableType(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
@@ -274,40 +280,34 @@
                         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;
 }
 
+// Add includes for a type ref. Note that this is non-recursive.
 void AddHeaders(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
                 std::set<std::string>* headers) {
-  AIDL_FATAL_IF(typenames.IsList(type) && type.GetTypeParameters().size() != 1, type);
-  bool isVector = type.IsArray() || typenames.IsList(type);
-  bool isNullable = type.IsNullable();
-  bool utf8 = type.IsUtf8InCpp();
-
-  if (isVector) {
-    headers->insert("vector");
-  }
-  if (type.IsGeneric()) {
-    for (const auto& parameter : type.GetTypeParameters()) {
-      AddHeaders(*parameter, typenames, headers);
+  if (type.IsArray()) {
+    if (type.IsFixedSizeArray()) {
+      headers->insert("array");
+    } else {
+      headers->insert("vector");
     }
   }
-  if (isNullable) {
+  if (type.IsNullable()) {
     if (type.GetName() != "IBinder") {
       headers->insert("optional");
     }
   }
   if (typenames.IsList(type)) {
-    // Nothing else to do for List.
+    headers->insert("vector");
     return;
   }
   if (type.GetName() == "String") {
-    headers->insert(utf8 ? "string" : "utils/String16.h");
+    if (type.IsUtf8InCpp()) {
+      headers->insert("string");
+    } else {
+      headers->insert("utils/String16.h");
+    }
     return;
   }
   if (type.GetName() == "IBinder") {
@@ -337,26 +337,21 @@
     return;
   }
 
-  auto definedType = typenames.TryGetDefinedType(type.GetName());
-  AIDL_FATAL_IF(definedType == nullptr, type) << "Unexpected type: " << type.GetName();
+  auto defined_type = typenames.TryGetDefinedType(type.GetName());
+  AIDL_FATAL_IF(defined_type == nullptr, type) << "Unexpected type: " << type.GetName();
 
-  if (definedType->AsInterface() != nullptr || definedType->AsStructuredParcelable() != nullptr ||
-      definedType->AsEnumDeclaration() != nullptr || definedType->AsUnionDeclaration() != nullptr) {
-    AddHeaders(*definedType, headers);
-  } else if (definedType->AsParcelable() != nullptr) {
-    const std::string cpp_header = definedType->AsParcelable()->GetCppHeader();
-    AIDL_FATAL_IF(cpp_header.empty(), definedType->AsParcelable())
-        << "Parcelable " << definedType->AsParcelable()->GetCanonicalName()
-        << " has no C++ header defined.";
-    headers->insert(cpp_header);
-  }
+  headers->insert(CppHeaderForType(*defined_type));
 }
 
-void AddHeaders(const AidlDefinedType& definedType, std::set<std::string>* headers) {
-  vector<string> name = definedType.GetSplitPackage();
-  name.push_back(definedType.GetName());
-  const std::string cpp_header = Join(name, '/') + ".h";
-  headers->insert(cpp_header);
+std::string CppHeaderForType(const AidlDefinedType& defined_type) {
+  // Unstructured parcelable should set its cpp_header. use it.
+  if (auto unstructured = AidlCast<AidlParcelable>(defined_type); unstructured) {
+    const std::string cpp_header = unstructured->GetCppHeader();
+    AIDL_FATAL_IF(cpp_header.empty(), unstructured)
+        << "Parcelable " << unstructured->GetCanonicalName() << " has no C++ header defined.";
+    return cpp_header;
+  }
+  return HeaderFile(defined_type, ClassNames::RAW, /*use_os_sep=*/false);
 }
 
 }  // namespace cpp
diff --git a/aidl_to_cpp.h b/aidl_to_cpp.h
index f6974f5..73b79bb 100644
--- a/aidl_to_cpp.h
+++ b/aidl_to_cpp.h
@@ -23,7 +23,9 @@
 
 // This header provides functions that translate AIDL things to cpp things.
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value);
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value);
 
 struct CodeGeneratorContext {
   CodeWriter& writer;
@@ -34,7 +36,7 @@
   const bool isPointer;           // whether the variable 'name' is a pointer or not
 };
 
-std::string GetTransactionIdFor(const AidlInterface& iface, const AidlMethod& method);
+std::string GetTransactionIdFor(const std::string& clazz, const AidlMethod& method);
 
 std::string CppNameOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames);
 
@@ -61,7 +63,7 @@
 void AddHeaders(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
                 std::set<std::string>* headers);
 
-void AddHeaders(const AidlDefinedType& parcelable, std::set<std::string>* headers);
+std::string CppHeaderForType(const AidlDefinedType& defined_type);
 }  // namespace cpp
 }  // namespace aidl
 }  // namespace android
diff --git a/aidl_to_cpp_common.cpp b/aidl_to_cpp_common.cpp
index f0bf1dc..f0df305 100644
--- a/aidl_to_cpp_common.cpp
+++ b/aidl_to_cpp_common.cpp
@@ -19,15 +19,16 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
+#include <limits>
 #include <set>
 #include <unordered_map>
 
-#include "ast_cpp.h"
 #include "comments.h"
 #include "logging.h"
 #include "os.h"
 
 using ::android::base::Join;
+using ::android::base::Split;
 
 namespace android {
 namespace aidl {
@@ -66,6 +67,8 @@
       return "I" + base_name + "Default";
     case ClassNames::BASE:
       return base_name;
+    case ClassNames::DELEGATOR_IMPL:
+      return "I" + base_name + "Delegator";
     case ClassNames::RAW:
       [[fallthrough]];
     default:
@@ -75,19 +78,21 @@
 
 std::string HeaderFile(const AidlDefinedType& defined_type, ClassNames class_type,
                        bool use_os_sep) {
-  std::string file_path = defined_type.GetPackage();
-  for (char& c : file_path) {
-    if (c == '.') {
-      c = (use_os_sep) ? OS_PATH_SEPARATOR : '/';
-    }
+  // For a nested type, we need to include its top-most parent type's header.
+  const AidlDefinedType* toplevel = &defined_type;
+  for (auto parent = toplevel->GetParentType(); parent;) {
+    // When including the parent's header, it should be always RAW
+    class_type = ClassNames::RAW;
+    toplevel = parent;
+    parent = toplevel->GetParentType();
   }
-  if (!file_path.empty()) {
-    file_path += (use_os_sep) ? OS_PATH_SEPARATOR : '/';
-  }
-  file_path += ClassName(defined_type, class_type);
-  file_path += ".h";
+  AIDL_FATAL_IF(toplevel->GetParentType() != nullptr, defined_type)
+      << "Can't find a top-level decl";
 
-  return file_path;
+  char separator = (use_os_sep) ? OS_PATH_SEPARATOR : '/';
+  vector<string> paths = toplevel->GetSplitPackage();
+  paths.push_back(ClassName(*toplevel, class_type));
+  return Join(paths, separator) + ".h";
 }
 
 void EnterNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
@@ -196,11 +201,38 @@
   return code;
 }
 
+// Returns Parent1::Parent2::Self. Namespaces are not included.
+string GetQualifiedName(const AidlDefinedType& type, ClassNames class_names) {
+  string q_name = ClassName(type, class_names);
+  for (auto parent = type.GetParentType(); parent; parent = parent->GetParentType()) {
+    q_name = parent->GetName() + "::" + q_name;
+  }
+  return q_name;
+}
+
+// Generates enum's class declaration. This should be called in a proper scope. For example, in its
+// namespace or parent type.
+void GenerateEnumClassDecl(CodeWriter& out, const AidlEnumDeclaration& enum_decl,
+                           const std::string& backing_type, ConstantValueDecorator decorator) {
+  out << "enum class";
+  GenerateDeprecated(out, enum_decl);
+  out << " " << enum_decl.GetName() << " : " << backing_type << " {\n";
+  out.Indent();
+  for (const auto& enumerator : enum_decl.GetEnumerators()) {
+    out << enumerator->GetName() << " = "
+        << enumerator->ValueString(enum_decl.GetBackingType(), decorator) << ",\n";
+  }
+  out.Dedent();
+  out << "};\n";
+}
+
+// enum_values template value is defined in its own namespace (android::internal or ndk::internal),
+// so the enum_decl type should be fully qualified.
 std::string GenerateEnumValues(const AidlEnumDeclaration& enum_decl,
                                const std::vector<std::string>& enclosing_namespaces_of_enum_decl) {
   const auto fq_name =
       Join(Append(enclosing_namespaces_of_enum_decl, enum_decl.GetSplitPackage()), "::") +
-      "::" + enum_decl.GetName();
+      "::" + GetQualifiedName(enum_decl);
   const auto size = enum_decl.GetEnumerators().size();
   std::ostringstream code;
   code << "#pragma clang diagnostic push\n";
@@ -217,6 +249,41 @@
   return code.str();
 }
 
+// toString(enum_type) is defined in the same namespace of the type.
+// So, if enum_decl is nested in parent type(s), it should be qualified with parent type(s).
+std::string GenerateEnumToString(const AidlEnumDeclaration& enum_decl,
+                                 const std::string& backing_type) {
+  const auto q_name = GetQualifiedName(enum_decl);
+  std::ostringstream code;
+  const std::string signature =
+      "[[nodiscard]] static inline std::string toString(" + q_name + " val)";
+  if (enum_decl.IsDeprecated()) {
+    code << signature;
+    GenerateDeprecated(code, enum_decl);
+    code << ";\n";
+  }
+  code << signature << " {\n";
+  code << "  switch(val) {\n";
+  std::set<std::string> unique_cases;
+  for (const auto& enumerator : enum_decl.GetEnumerators()) {
+    std::string c = enumerator->ValueString(enum_decl.GetBackingType(), AidlConstantValueDecorator);
+    // Only add a case if its value has not yet been used in the switch
+    // statement. C++ does not allow multiple cases with the same value, but
+    // enums does allow this. In this scenario, the first declared
+    // enumerator with the given value is printed.
+    if (unique_cases.count(c) == 0) {
+      unique_cases.insert(c);
+      code << "  case " << q_name << "::" << enumerator->GetName() << ":\n";
+      code << "    return \"" << enumerator->GetName() << "\";\n";
+    }
+  }
+  code << "  default:\n";
+  code << "    return std::to_string(static_cast<" << backing_type << ">(val));\n";
+  code << "  }\n";
+  code << "}\n";
+  return code.str();
+}
+
 std::string TemplateDecl(const AidlParcelable& defined_type) {
   std::string decl = "";
   if (defined_type.IsGeneric()) {
@@ -232,6 +299,39 @@
 
 void GenerateParcelableComparisonOperators(CodeWriter& out, const AidlParcelable& parcelable) {
   std::set<string> operators{"<", ">", "==", ">=", "<=", "!="};
+
+  if (parcelable.AsUnionDeclaration() && parcelable.IsFixedSize()) {
+    auto name = parcelable.GetName();
+    auto max_tag = parcelable.GetFields().back()->GetName();
+    auto min_tag = parcelable.GetFields().front()->GetName();
+    auto tmpl = R"--(static int _cmp(const {name}& _lhs, const {name}& _rhs) {{
+  return _cmp_value(_lhs.getTag(), _rhs.getTag()) || _cmp_value_at<{max_tag}>(_lhs, _rhs);
+}}
+template <Tag _Tag>
+static int _cmp_value_at(const {name}& _lhs, const {name}& _rhs) {{
+  if constexpr (_Tag == {min_tag}) {{
+    return _cmp_value(_lhs.get<_Tag>(), _rhs.get<_Tag>());
+  }} else {{
+    return (_lhs.getTag() == _Tag)
+      ? _cmp_value(_lhs.get<_Tag>(), _rhs.get<_Tag>())
+      : _cmp_value_at<(Tag)(_Tag-1)>(_lhs, _rhs);
+  }}
+}}
+template <typename _Type>
+static int _cmp_value(const _Type& _lhs, const _Type& _rhs) {{
+  return (_lhs == _rhs) ? 0 : (_lhs < _rhs) ? -1 : 1;
+}}
+)--";
+    out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("min_tag", min_tag),
+                       fmt::arg("max_tag", max_tag));
+    for (const auto& op : operators) {
+      out << "inline bool operator" << op << "(const " << name << "&_rhs) const {\n";
+      out << "  return _cmp(*this, _rhs) " << op << " 0;\n";
+      out << "}\n";
+    }
+    return;
+  }
+
   bool is_empty = false;
 
   auto comparable = [&](const string& prefix) {
@@ -330,27 +430,96 @@
   return "";
 }
 
-const vector<string> UnionWriter::headers{
-    "cassert",      // __assert for logging
-    "type_traits",  // std::is_same_v
-    "utility",      // std::mode/forward for value
-    "variant",      // std::variant for value
-};
+size_t AlignmentOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
+  static map<string, size_t> alignment = {
+      {"boolean", 1}, {"byte", 1}, {"char", 2}, {"double", 8},
+      {"float", 4},   {"int", 4},  {"long", 8},
+  };
+
+  string name = type.GetName();
+  if (auto enum_decl = typenames.GetEnumDeclaration(type); enum_decl) {
+    name = enum_decl->GetBackingType().GetName();
+  }
+  // default to 0 for parcelable types
+  return alignment[name];
+}
+
+std::set<std::string> UnionWriter::GetHeaders(const AidlUnionDecl& decl) {
+  std::set<std::string> union_headers = {
+      "cassert",      // __assert for logging
+      "type_traits",  // std::is_same_v
+      "utility",      // std::mode/forward for value
+      "variant",      // union's impl
+  };
+  if (decl.IsFixedSize()) {
+    union_headers.insert("tuple");  // fixed-sized union's typelist
+  }
+  return union_headers;
+}
+
+// fixed-sized union class looks like:
+// class Union {
+// public:
+//   enum Tag : uint8_t {
+//     field1 = 0,
+//     field2,
+//   };
+//  ... methods ...
+// private:
+//   Tag _tag;
+//   union {
+//     type1 field1;
+//     type2 field2;
+//   } _value;
+// };
 
 void UnionWriter::PrivateFields(CodeWriter& out) const {
-  vector<string> field_types;
-  for (const auto& f : decl.GetFields()) {
-    field_types.push_back(name_of(f->GetType(), typenames));
+  if (decl.IsFixedSize()) {
+    AIDL_FATAL_IF(decl.GetFields().empty(), decl) << "Union '" << decl.GetName() << "' is empty.";
+    const auto& first_field = decl.GetFields()[0];
+    const auto& default_name = first_field->GetName();
+    const auto& default_value = name_of(first_field->GetType(), typenames) + "(" +
+                                first_field->ValueString(decorator) + ")";
+
+    out << "Tag _tag __attribute__((aligned (1))) = " << default_name << ";\n";
+    out << "union _value_t {\n";
+    out.Indent();
+    out << "_value_t() {}\n";
+    out << "~_value_t() {}\n";
+    for (const auto& f : decl.GetFields()) {
+      const auto& fn = f->GetName();
+      out << name_of(f->GetType(), typenames) << " " << fn;
+      if (decl.IsFixedSize()) {
+        int alignment = AlignmentOf(f->GetType(), typenames);
+        if (alignment > 0) {
+          out << " __attribute__((aligned (" << std::to_string(alignment) << ")))";
+        }
+      }
+      if (fn == default_name) {
+        out << " = " << default_value;
+      }
+      out << ";\n";
+    }
+    out.Dedent();
+    out << "} _value;\n";
+  } else {
+    vector<string> field_types;
+    for (const auto& f : decl.GetFields()) {
+      field_types.push_back(name_of(f->GetType(), typenames));
+    }
+    out << "std::variant<" + Join(field_types, ", ") + "> _value;\n";
   }
-  out << "std::variant<" + Join(field_types, ", ") + "> _value;\n";
 }
 
 void UnionWriter::PublicFields(CodeWriter& out) const {
-  AidlTypeSpecifier tag_type(AIDL_LOCATION_HERE, "int", /* is_array= */ false,
-                             /* type_params= */ nullptr, Comments{});
-  tag_type.Resolve(typenames);
-
-  out << "enum Tag : " << name_of(tag_type, typenames) << " {\n";
+  std::string tag_type = "int32_t";
+  if (decl.IsFixedSize()) {
+    // For @FixedSize union, we use a smaller type for a tag to minimize the size overhead.
+    AIDL_FATAL_IF(decl.GetFields().size() > std::numeric_limits<uint8_t>::max(), decl)
+        << "Too many fields for @FixedSize";
+    tag_type = "uint8_t";
+  }
+  out << "enum Tag : " << tag_type << " {\n";
   bool is_first = true;
   for (const auto& f : decl.GetFields()) {
     out << "  " << f->GetName();
@@ -363,21 +532,53 @@
 
   const auto& name = decl.GetName();
 
-  AIDL_FATAL_IF(decl.GetFields().empty(), decl) << "Union '" << name << "' is empty.";
-  const auto& first_field = decl.GetFields()[0];
-  const auto& default_name = first_field->GetName();
-  const auto& default_value =
-      name_of(first_field->GetType(), typenames) + "(" + first_field->ValueString(decorator) + ")";
+  if (decl.IsFixedSize()) {
+    vector<string> field_types;
+    for (const auto& f : decl.GetFields()) {
+      field_types.push_back(name_of(f->GetType(), typenames));
+    }
+    auto typelist = Join(field_types, ", ");
+    auto tmpl = R"--(
+template <Tag _Tag>
+using _at = typename std::tuple_element<_Tag, std::tuple<{typelist}>>::type;
+template <Tag _Tag, typename _Type>
+static {name} make(_Type&& _arg) {{
+  {name} _inst;
+  _inst.set<_Tag>(std::forward<_Type>(_arg));
+  return _inst;
+}}
+constexpr Tag getTag() const {{
+  return _tag;
+}}
+template <Tag _Tag>
+const _at<_Tag>& get() const {{
+  if (_Tag != _tag) {{ __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }}
+  return *(_at<_Tag>*)(&_value);
+}}
+template <Tag _Tag>
+_at<_Tag>& get() {{
+  if (_Tag != _tag) {{ __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }}
+  return *(_at<_Tag>*)(&_value);
+}}
+template <Tag _Tag, typename _Type>
+void set(_Type&& _arg) {{
+  _tag = _Tag;
+  get<_Tag>() = std::forward<_Type>(_arg);
+}}
+)--";
+    out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("typelist", typelist));
+  } else {
+    AIDL_FATAL_IF(decl.GetFields().empty(), decl) << "Union '" << name << "' is empty.";
+    const auto& first_field = decl.GetFields()[0];
+    const auto& default_name = first_field->GetName();
+    const auto& default_value = name_of(first_field->GetType(), typenames) + "(" +
+                                first_field->ValueString(decorator) + ")";
 
-  auto tmpl = R"--(
+    auto tmpl = R"--(
 template<typename _Tp>
 static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, {name}>;
 
 {name}() : _value(std::in_place_index<{default_name}>, {default_value}) {{ }}
-{name}(const {name}&) = default;
-{name}({name}&&) = default;
-{name}& operator=(const {name}&) = default;
-{name}& operator=({name}&&) = default;
 
 template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
 // NOLINTNEXTLINE(google-explicit-constructor)
@@ -420,14 +621,15 @@
 }}
 
 )--";
-  out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("default_name", default_name),
-                     fmt::arg("default_value", default_value));
+    out << fmt::format(tmpl, fmt::arg("name", name), fmt::arg("default_name", default_name),
+                       fmt::arg("default_value", default_value));
+  }
 }
 
 void UnionWriter::ReadFromParcel(CodeWriter& out, const ParcelWriterContext& ctx) const {
-  AidlTypeSpecifier tag_type(AIDL_LOCATION_HERE, "int", /* is_array= */ false,
-                             /* type_params= */ nullptr, Comments{});
-  tag_type.Resolve(typenames);
+  // Even though @FixedSize union may use a smaller type than int32_t, we need to read/write it
+  // as if it is int32_t for compatibility with other bckends.
+  auto tag_type = typenames.MakeResolvedType(AIDL_LOCATION_HERE, "int", /* is_array= */ false);
 
   const string tag = "_aidl_tag";
   const string value = "_aidl_value";
@@ -441,7 +643,7 @@
   };
 
   out << fmt::format("{} {};\n", ctx.status_type, status);
-  read_var(tag, tag_type);
+  read_var(tag, *tag_type);
   out << fmt::format("switch ({}) {{\n", tag);
   for (const auto& variable : decl.GetFields()) {
     out << fmt::format("case {}: {{\n", variable->GetName());
@@ -469,16 +671,16 @@
 }
 
 void UnionWriter::WriteToParcel(CodeWriter& out, const ParcelWriterContext& ctx) const {
-  AidlTypeSpecifier tag_type(AIDL_LOCATION_HERE, "int", /* is_array= */ false,
-                             /* type_params= */ nullptr, Comments{});
-  tag_type.Resolve(typenames);
+  // Even though @FixedSize union may use a smaller type than int32_t, we need to read/write it
+  // as if it is int32_t for compatibility with other bckends.
+  auto tag_type = typenames.MakeResolvedType(AIDL_LOCATION_HERE, "int", /* is_array= */ false);
 
   const string tag = "_aidl_tag";
   const string value = "_aidl_value";
   const string status = "_aidl_ret_status";
 
   out << fmt::format("{} {} = ", ctx.status_type, status);
-  ctx.write_func(out, "getTag()", tag_type);
+  ctx.write_func(out, "getTag()", *tag_type);
   out << ";\n";
   out << fmt::format("if ({} != {}) return {};\n", status, ctx.status_ok, status);
   out << "switch (getTag()) {\n";
@@ -491,6 +693,77 @@
   out << "__assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, \"can't reach here\");\n";
 }
 
+std::string CppConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value, bool is_ndk) {
+  if (type.IsArray()) {
+    auto values = std::get<std::vector<std::string>>(raw_value);
+    // Hexadecimal literals for byte arrays should be casted to uint8_t
+    if (type.GetName() == "byte" &&
+        std::any_of(values.begin(), values.end(),
+                    [](const auto& value) { return !value.empty() && value[0] == '-'; })) {
+      for (auto& value : values) {
+        // cast only if necessary
+        if (value[0] == '-') {
+          value = "uint8_t(" + value + ")";
+        }
+      }
+    }
+    std::string value = "{" + Join(values, ", ") + "}";
+
+    if (type.IsFixedSizeArray()) {
+      // For arrays, use double braces because arrays can be nested.
+      //  e.g.) array<array<int, 2>, 3> ints = {{ {{1,2}}, {{3,4}}, {{5,6}} }};
+      // Vectors might need double braces, but since we don't have nested vectors (yet)
+      // single brace would work even for optional vectors.
+      value = "{" + value + "}";
+    }
+
+    if (!type.IsMutated() && type.IsNullable()) {
+      // For outermost std::optional<>, we need an additional brace pair to initialize its value.
+      value = "{" + value + "}";
+    }
+    return value;
+  }
+
+  const std::string& value = std::get<std::string>(raw_value);
+  if (AidlTypenames::IsBuiltinTypename(type.GetName())) {
+    if (type.GetName() == "boolean") {
+      return value;
+    } else if (type.GetName() == "byte") {
+      return value;
+    } else if (type.GetName() == "char") {
+      // TODO: consider 'L'-prefix for wide char literal
+      return value;
+    } else if (type.GetName() == "double") {
+      return value;
+    } else if (type.GetName() == "float") {
+      return value;  // value has 'f' suffix
+    } else if (type.GetName() == "int") {
+      return value;
+    } else if (type.GetName() == "long") {
+      return value + "L";
+    } else if (type.GetName() == "String") {
+      if (is_ndk || type.IsUtf8InCpp()) {
+        return value;
+      } else {
+        return "::android::String16(" + value + ")";
+      }
+    }
+    AIDL_FATAL(type) << "Unknown built-in type: " << type.GetName();
+  }
+
+  auto defined_type = type.GetDefinedType();
+  AIDL_FATAL_IF(!defined_type, type) << "Invalid type for \"" << value << "\"";
+  auto enum_type = defined_type->AsEnumDeclaration();
+  AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << value << "\"";
+
+  auto cpp_type_name = "::" + Join(Split(enum_type->GetCanonicalName(), "."), "::");
+  if (is_ndk) {
+    cpp_type_name = "::aidl" + cpp_type_name;
+  }
+  return cpp_type_name + "::" + value.substr(value.find_last_of('.') + 1);
+}
 }  // namespace cpp
 }  // namespace aidl
 }  // namespace android
diff --git a/aidl_to_cpp_common.h b/aidl_to_cpp_common.h
index f9fe80b..e6733b6 100644
--- a/aidl_to_cpp_common.h
+++ b/aidl_to_cpp_common.h
@@ -33,16 +33,23 @@
 
 // These roughly correspond to the various class names in the C++ hierarchy:
 enum class ClassNames {
-  BASE,          // Foo (not a real class, but useful in some circumstances).
-  CLIENT,        // BpFoo
-  SERVER,        // BnFoo
-  INTERFACE,     // IFoo
-  DEFAULT_IMPL,  // IFooDefault
-  RAW,           // (as shown in the file)
+  BASE,            // Foo (not a real class, but useful in some circumstances).
+  CLIENT,          // BpFoo
+  SERVER,          // BnFoo
+  INTERFACE,       // IFoo
+  DEFAULT_IMPL,    // IFooDefault
+  RAW,             // (as shown in the file)
+  DELEGATOR_IMPL,  // IFooDelegator
 };
 
 string ClassName(const AidlDefinedType& defined_type, ClassNames type);
 
+// Return the alignment of known types and enum backing types.
+// If the alignment is unknown, or it is a FizedSize parcelable with its
+// own guaranteed alignment(so it does not need to be specified), 0 will be
+// returned.
+size_t AlignmentOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames);
+
 // Generate the relative path to a header file.  If |use_os_sep| we'll use the
 // operating system specific path separator rather than C++'s expected '/' when
 // including headers.
@@ -73,6 +80,13 @@
   return appended;
 }
 
+// Returns Parent1::Parent2::Self. Namespaces are not included.
+std::string GetQualifiedName(const AidlDefinedType& type, ClassNames name = ClassNames::RAW);
+
+void GenerateEnumClassDecl(CodeWriter& out, const AidlEnumDeclaration& enum_decl,
+                           const std::string& backing_type, ::ConstantValueDecorator decorator);
+std::string GenerateEnumToString(const AidlEnumDeclaration& enum_decl,
+                                 const std::string& backing_type);
 std::string GenerateEnumValues(const AidlEnumDeclaration& enum_decl,
                                const std::vector<std::string>& enclosing_namespaces_of_enum_decl);
 std::string TemplateDecl(const AidlParcelable& defined_type);
@@ -106,7 +120,8 @@
   const AidlTypenames& typenames;
   const std::function<std::string(const AidlTypeSpecifier&, const AidlTypenames&)> name_of;
   const ::ConstantValueDecorator& decorator;
-  static const std::vector<std::string> headers;
+
+  static std::set<std::string> GetHeaders(const AidlUnionDecl&);
 
   void PrivateFields(CodeWriter& out) const;
   void PublicFields(CodeWriter& out) const;
@@ -114,6 +129,9 @@
   void WriteToParcel(CodeWriter& out, const ParcelWriterContext&) const;
 };
 
+std::string CppConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value, bool is_ndk);
 }  // namespace cpp
 }  // namespace aidl
 }  // namespace android
diff --git a/aidl_to_java.cpp b/aidl_to_java.cpp
index 04888fd..d60362b 100644
--- a/aidl_to_java.cpp
+++ b/aidl_to_java.cpp
@@ -38,23 +38,27 @@
 using std::string;
 using std::vector;
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value) {
   if (type.IsArray()) {
-    return raw_value;
+    const auto& values = std::get<std::vector<std::string>>(raw_value);
+    return "{" + Join(values, ", ") + "}";
   }
+  const std::string& value = std::get<std::string>(raw_value);
   if (type.GetName() == "long") {
-    return raw_value + "L";
+    return value + "L";
   }
   if (auto defined_type = type.GetDefinedType(); defined_type) {
     auto enum_type = defined_type->AsEnumDeclaration();
-    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
-    return type.GetName() + "." + raw_value.substr(raw_value.find_last_of('.') + 1);
+    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << value << "\"";
+    return type.GetName() + "." + value.substr(value.find_last_of('.') + 1);
   }
-  return raw_value;
+  return value;
 };
 
-const string& JavaNameOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames,
-                         bool instantiable = false, bool boxing = false) {
+const string& JavaNameOf(const AidlTypeSpecifier& aidl, bool instantiable = false,
+                         bool boxing = false) {
   AIDL_FATAL_IF(!aidl.IsResolved(), aidl) << aidl.ToString();
 
   if (instantiable) {
@@ -102,8 +106,9 @@
 
   // Enums in Java are represented by their backing type when
   // referenced in parcelables, methods, etc.
-  if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(aidl);
-      enum_decl != nullptr) {
+  const auto defined_type = aidl.GetDefinedType();
+  if (defined_type && defined_type->AsEnumDeclaration()) {
+    const auto enum_decl = defined_type->AsEnumDeclaration();
     const string& backing_type_name = enum_decl->GetBackingType().GetName();
     AIDL_FATAL_IF(m.find(backing_type_name) == m.end(), enum_decl);
     AIDL_FATAL_IF(!AidlTypenames::IsBuiltinTypename(backing_type_name), enum_decl);
@@ -131,58 +136,69 @@
 
 namespace {
 string JavaSignatureOfInternal(
-    const AidlTypeSpecifier& aidl, const AidlTypenames& typenames, bool instantiable,
-    bool omit_array, bool boxing = false /* boxing can be true only if it is a type parameter */) {
-  string ret = JavaNameOf(aidl, typenames, instantiable, boxing && !aidl.IsArray());
+    const AidlTypeSpecifier& aidl, bool instantiable, bool omit_array,
+    bool boxing = false /* boxing can be true only if it is a type parameter */) {
+  string ret = JavaNameOf(aidl, instantiable, boxing && !aidl.IsArray());
   if (aidl.IsGeneric()) {
     vector<string> arg_names;
     for (const auto& ta : aidl.GetTypeParameters()) {
-      arg_names.emplace_back(
-          JavaSignatureOfInternal(*ta, typenames, false, false, true /* boxing */));
+      arg_names.emplace_back(JavaSignatureOfInternal(*ta, false, false, true /* boxing */));
     }
     ret += "<" + Join(arg_names, ",") + ">";
   }
   if (aidl.IsArray() && !omit_array) {
-    ret += "[]";
+    if (aidl.IsFixedSizeArray()) {
+      ret += Join(std::vector<std::string>(aidl.GetFixedSizeArrayDimensions().size(), "[]"), "");
+    } else {
+      ret += "[]";
+    }
   }
   return ret;
 }
 
-// Returns the name of the backing type for the specified type. Note: this
-// returns type names as used in AIDL, not a Java signature.
+// Returns the name of the backing type for the specified type.
+// Note: Do not use the result in the generated code! It's supposed to be used as a key.
+// This returns type names as used in AIDL, not a Java signature.
 // For enums, this is the enum's backing type.
 // For all other types, this is the type itself.
-string AidlBackingTypeName(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
+string AidlBackingTypeName(const AidlTypeSpecifier& type) {
   string type_name;
-  if (const AidlEnumDeclaration* enum_decl = typenames.GetEnumDeclaration(type);
-      enum_decl != nullptr) {
+  const auto defined_type = type.GetDefinedType();
+  if (defined_type && defined_type->AsEnumDeclaration()) {
+    const AidlEnumDeclaration* enum_decl = defined_type->AsEnumDeclaration();
     type_name = enum_decl->GetBackingType().GetName();
   } else {
     type_name = type.GetName();
   }
   if (type.IsArray()) {
-    type_name += "[]";
+    if (type.IsFixedSizeArray()) {
+      for (const auto& dim : type.GetFixedSizeArrayDimensions()) {
+        type_name += "[" + std::to_string(dim) + "]";
+      }
+    } else {
+      type_name += "[]";
+    }
   }
   return type_name;
 }
 
 }  // namespace
 
-string JavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
-  return JavaSignatureOfInternal(aidl, typenames, false, false);
+string JavaSignatureOf(const AidlTypeSpecifier& aidl) {
+  return JavaSignatureOfInternal(aidl, false, false);
 }
 
-string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
-  return JavaSignatureOfInternal(aidl, typenames, true, true);
+string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl) {
+  return JavaSignatureOfInternal(aidl, true, true);
 }
 
-string DefaultJavaValueOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames) {
+string DefaultJavaValueOf(const AidlTypeSpecifier& aidl) {
   static map<string, string> m = {
       {"boolean", "false"}, {"byte", "0"},     {"char", R"('\u0000')"}, {"int", "0"},
       {"long", "0L"},       {"float", "0.0f"}, {"double", "0.0d"},
   };
 
-  const string name = AidlBackingTypeName(aidl, typenames);
+  const string name = AidlBackingTypeName(aidl);
   AIDL_FATAL_IF(name == "void", aidl);
 
   if (!aidl.IsArray() && m.find(name) != m.end()) {
@@ -201,11 +217,94 @@
   }
 }
 
-bool WriteToParcelFor(const CodeGeneratorContext& c) {
+typedef void (*ParcelHelperGenerator)(CodeWriter&, const Options&);
+
+static void GenerateTypedObjectHelper(CodeWriter& out, const Options&) {
+  // Note that the name is inconsistent here because Parcel.java defines readTypedObject as if it
+  // "creates" a new value from a parcel. "in-place" read function is not necessary because
+  // user-defined parcelable defines its readFromParcel.
+  out << R"(static private <T> T readTypedObject(
+    android.os.Parcel parcel,
+    android.os.Parcelable.Creator<T> c) {
+  if (parcel.readInt() != 0) {
+      return c.createFromParcel(parcel);
+  } else {
+      return null;
+  }
+}
+static private <T extends android.os.Parcelable> void writeTypedObject(
+    android.os.Parcel parcel, T value, int parcelableFlags) {
+  if (value != null) {
+    parcel.writeInt(1);
+    value.writeToParcel(parcel, parcelableFlags);
+  } else {
+    parcel.writeInt(0);
+  }
+}
+)";
+}
+
+void GenerateParcelHelpers(CodeWriter& out, const AidlDefinedType& defined_type,
+                           const Options& options) {
+  // root-level type contains all necessary helpers
+  if (defined_type.GetParentType()) {
+    return;
+  }
+  // visits method parameters and parcelable fields to collect types which
+  // requires read/write/create helpers.
+  struct Visitor : AidlVisitor {
+    const Options& options;
+    set<ParcelHelperGenerator> helpers;
+    Visitor(const Options& options) : options(options) {}
+    void Visit(const AidlTypeSpecifier& type) override {
+      auto name = type.GetName();
+      if (auto defined_type = type.GetDefinedType(); defined_type) {
+        if (defined_type->AsParcelable() != nullptr && !type.IsArray()) {
+          // TypedObjects are supported since 23. So we don't need helpers.
+          if (options.GetMinSdkVersion() < 23u) {
+            helpers.insert(&GenerateTypedObjectHelper);
+          }
+        }
+      } else {
+        // There's parcelable-like built-in types as well.
+        if (name == "ParcelFileDescriptor" || name == "CharSequence") {
+          if (!type.IsArray()) {
+            // TypedObjects are supported since 23. So we don't need helpers.
+            if (options.GetMinSdkVersion() < 23u) {
+              helpers.insert(&GenerateTypedObjectHelper);
+            }
+          }
+        }
+      }
+    }
+  } v{options};
+
+  VisitTopDown(v, defined_type);
+  if (!v.helpers.empty()) {
+    // Nested class (_Parcel) is used to contain static helper methods because some targets are
+    // still using Java 7 which doesn't allow interfaces to have static methods.
+    // Helpers shouldn't bother API checks, but in case where AIDL types are not marked `@hide`
+    // explicitly marks the helper class as @hide.
+    out << "/** @hide */\n";
+    out << "static class _Parcel {\n";
+    out.Indent();
+    for (const auto& helper : v.helpers) {
+      helper(out, options);
+    }
+    out.Dedent();
+    out << "}\n";
+  }
+}
+
+void WriteToParcelFor(const CodeGeneratorContext& c) {
   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
       {"boolean",
        [](const CodeGeneratorContext& c) {
-         c.writer << c.parcel << ".writeInt(((" << c.var << ")?(1):(0)));\n";
+         if (c.min_sdk_version >= 29u) {
+           c.writer << c.parcel << ".writeBoolean(" << c.var << ");\n";
+         } else {
+           c.writer << c.parcel << ".writeInt(((" << c.var << ")?(1):(0)));\n";
+         }
        }},
       {"boolean[]",
        [](const CodeGeneratorContext& c) {
@@ -270,15 +369,19 @@
       {"List",
        [](const CodeGeneratorContext& c) {
          if (c.type.IsGeneric()) {
-           const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
-           if (contained_type == "String") {
+           AIDL_FATAL_IF(c.type.GetTypeParameters().size() != 1, c.type);
+           const auto& element_type = *c.type.GetTypeParameters().at(0);
+           const auto& element_type_name = element_type.GetName();
+           if (element_type_name == "String") {
              c.writer << c.parcel << ".writeStringList(" << c.var << ");\n";
-           } else if (contained_type == "IBinder") {
+           } else if (element_type_name == "IBinder") {
              c.writer << c.parcel << ".writeBinderList(" << c.var << ");\n";
-           } else if (c.typenames.IsParcelable(contained_type)) {
+           } else if (c.typenames.IsParcelable(element_type_name)) {
              c.writer << c.parcel << ".writeTypedList(" << c.var << ");\n";
+           } else if (c.typenames.GetInterface(element_type)) {
+             c.writer << c.parcel << ".writeInterfaceList(" << c.var << ");\n";
            } else {
-             AIDL_FATAL(c.type) << "write: NOT IMPLEMENTED for " << contained_type;
+             AIDL_FATAL(c.type) << "write: NOT IMPLEMENTED for " << element_type_name;
            }
          } else {
            c.writer << c.parcel << ".writeList(" << c.var << ");\n";
@@ -304,6 +407,7 @@
                *c.type.GetTypeParameters()[1].get(),
                c.parcel,
                "v",
+               c.min_sdk_version,
                c.is_return_value,
                c.is_classloader_created,
                c.filename,
@@ -336,19 +440,12 @@
        }},
       {"ParcelFileDescriptor",
        [](const CodeGeneratorContext& c) {
-         // This is same as writeTypedObject which was introduced with SDK 23.
-         // Keeping below code so that the generated code is buildable with older SDK.
-         c.writer << "if ((" << c.var << "!=null)) {\n";
-         c.writer.Indent();
-         c.writer << c.parcel << ".writeInt(1);\n";
-         c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
-         c.writer.Dedent();
-         c.writer << "}\n";
-         c.writer << "else {\n";
-         c.writer.Indent();
-         c.writer << c.parcel << ".writeInt(0);\n";
-         c.writer.Dedent();
-         c.writer << "}\n";
+         if (c.min_sdk_version >= 23u) {
+           c.writer << c.parcel << ".writeTypedObject(" << c.var << ", " << GetFlagFor(c) << ");\n";
+         } else {
+           c.writer << "_Parcel.writeTypedObject(" << c.parcel << ", " << c.var << ", "
+                    << GetFlagFor(c) << ");\n";
+         }
        }},
       {"ParcelFileDescriptor[]",
        [](const CodeGeneratorContext& c) {
@@ -376,41 +473,38 @@
          c.writer << c.parcel << ".writeTypedObject(" << c.var << ", 0);\n";
        }},
   };
-  const string type_name = AidlBackingTypeName(c.type, c.typenames);
+  const string type_name = AidlBackingTypeName(c.type);
   const auto found = method_map.find(type_name);
   if (found != method_map.end()) {
     found->second(c);
+  } else if (c.type.IsFixedSizeArray()) {
+    std::vector<std::string> args = {c.var, GetFlagFor(c)};
+    for (auto dim : c.type.GetFixedSizeArrayDimensions()) {
+      args.push_back(std::to_string(dim));
+    }
+    c.writer << c.parcel << ".writeFixedArray(" << Join(args, ", ") << ");\n";
   } else {
     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()) {
-        // 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))?"
-                 << "(" << c.var << ".asBinder()):(null)));\n";
+      if (c.type.IsArray()) {
+        c.writer << c.parcel << ".writeInterfaceArray(" << c.var << ");\n";
+      } else {
+        c.writer << c.parcel << ".writeStrongInterface(" << c.var << ");\n";
       }
     } else if (t->AsParcelable() != nullptr) {
       if (c.type.IsArray()) {
         c.writer << c.parcel << ".writeTypedArray(" << c.var << ", " << GetFlagFor(c) << ");\n";
       } else {
-        // This is same as writeTypedObject.
-        // Keeping below code just not to break tests.
-        c.writer << "if ((" << c.var << "!=null)) {\n";
-        c.writer.Indent();
-        c.writer << c.parcel << ".writeInt(1);\n";
-        c.writer << c.var << ".writeToParcel(" << c.parcel << ", " << GetFlagFor(c) << ");\n";
-        c.writer.Dedent();
-        c.writer << "}\n";
-        c.writer << "else {\n";
-        c.writer.Indent();
-        c.writer << c.parcel << ".writeInt(0);\n";
-        c.writer.Dedent();
-        c.writer << "}\n";
+        if (c.min_sdk_version >= 23u) {
+          c.writer << c.parcel << ".writeTypedObject(" << c.var << ", " << GetFlagFor(c) << ");\n";
+        } else {
+          c.writer << "_Parcel.writeTypedObject(" << c.parcel << ", " << c.var << ", "
+                   << GetFlagFor(c) << ");\n";
+        }
       }
     }
   }
-  return true;
 }
 
 // Ensures that a variable is initialized to refer to the classloader
@@ -429,7 +523,11 @@
   static map<string, function<void(const CodeGeneratorContext&)>> method_map{
       {"boolean",
        [](const CodeGeneratorContext& c) {
-         c.writer << c.var << " = (0!=" << c.parcel << ".readInt());\n";
+         if (c.min_sdk_version >= 29u) {
+           c.writer << c.var << " = " << c.parcel << ".readBoolean();\n";
+         } else {
+           c.writer << c.var << " = (0!=" << c.parcel << ".readInt());\n";
+         }
        }},
       {"boolean[]",
        [](const CodeGeneratorContext& c) {
@@ -494,17 +592,22 @@
       {"List",
        [](const CodeGeneratorContext& c) {
          if (c.type.IsGeneric()) {
-           const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
-           if (contained_type == "String") {
+           AIDL_FATAL_IF(c.type.GetTypeParameters().size() != 1, c.type);
+           const auto& element_type = *c.type.GetTypeParameters().at(0);
+           const auto& element_type_name = element_type.GetName();
+           if (element_type_name == "String") {
              c.writer << c.var << " = " << c.parcel << ".createStringArrayList();\n";
-           } else if (contained_type == "IBinder") {
+           } else if (element_type_name == "IBinder") {
              c.writer << c.var << " = " << c.parcel << ".createBinderArrayList();\n";
-           } else if (c.typenames.IsParcelable(contained_type)) {
+           } else if (c.typenames.IsParcelable(element_type_name)) {
              c.writer << c.var << " = " << c.parcel << ".createTypedArrayList("
-                      << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
-                      << ".CREATOR);\n";
+                      << JavaNameOf(element_type) << ".CREATOR);\n";
+           } else if (c.typenames.GetInterface(element_type)) {
+             auto as_interface = element_type_name + ".Stub::asInterface";
+             c.writer << c.var << " = " << c.parcel << ".createInterfaceArrayList(" << as_interface
+                      << ");\n";
            } else {
-             AIDL_FATAL(c.type) << "create: NOT IMPLEMENTED for " << contained_type;
+             AIDL_FATAL(c.type) << "create: NOT IMPLEMENTED for " << element_type_name;
            }
          } else {
            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
@@ -519,17 +622,18 @@
            c.writer << "int N = " << c.parcel << ".readInt();\n";
            c.writer << c.var << " = N < 0 ? null : new java.util.HashMap<>();\n";
 
-           auto creator = JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) + ".CREATOR";
+           auto creator = JavaNameOf(*(c.type.GetTypeParameters().at(1))) + ".CREATOR";
            c.writer << "java.util.stream.IntStream.range(0, N).forEach(i -> {\n";
            c.writer.Indent();
            c.writer << "String k = " << c.parcel << ".readString();\n";
-           c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
+           c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1))) << " v;\n";
            CodeGeneratorContext value_context{
                c.writer,
                c.typenames,
                *c.type.GetTypeParameters()[1].get(),
                c.parcel,
                "v",
+               c.min_sdk_version,
                c.is_return_value,
                c.is_classloader_created,
                c.filename,
@@ -565,19 +669,13 @@
        }},
       {"ParcelFileDescriptor",
        [](const CodeGeneratorContext& c) {
-         // This is same as readTypedObject which was introduced with SDK 23.
-         // Keeping below code so that the generated code is buildable with older SDK.
-         c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
-         c.writer.Indent();
-         c.writer << c.var << " = " << "android.os.ParcelFileDescriptor.CREATOR.createFromParcel(" << c.parcel
-                  << ");\n";
-         c.writer.Dedent();
-         c.writer << "}\n";
-         c.writer << "else {\n";
-         c.writer.Indent();
-         c.writer << c.var << " = null;\n";
-         c.writer.Dedent();
-         c.writer << "}\n";
+         if (c.min_sdk_version >= 23u) {
+           c.writer << c.var << " = " << c.parcel
+                    << ".readTypedObject(android.os.ParcelFileDescriptor.CREATOR);\n";
+         } else {
+           c.writer << c.var << " = _Parcel.readTypedObject(" << c.parcel
+                    << ", android.os.ParcelFileDescriptor.CREATOR);\n";
+         }
        }},
       {"ParcelFileDescriptor[]",
        [](const CodeGeneratorContext& c) {
@@ -586,18 +684,13 @@
        }},
       {"CharSequence",
        [](const CodeGeneratorContext& c) {
-         // We have written 0 for null CharSequence.
-         c.writer << "if (0!=" << c.parcel << ".readInt()) {\n";
-         c.writer.Indent();
-         c.writer << c.var << " = android.text.TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel("
-                  << c.parcel << ");\n";
-         c.writer.Dedent();
-         c.writer << "}\n";
-         c.writer << "else {\n";
-         c.writer.Indent();
-         c.writer << c.var << " = null;\n";
-         c.writer.Dedent();
-         c.writer << "}\n";
+         if (c.min_sdk_version >= 23u) {
+           c.writer << c.var << " = " << c.parcel
+                    << ".readTypedObject(android.text.TextUtils.CHAR_SEQUENCE_CREATOR);\n";
+         } else {
+           c.writer << c.var << " = _Parcel.readTypedObject(" << c.parcel
+                    << ", android.text.TextUtils.CHAR_SEQUENCE_CREATOR);\n";
+         }
        }},
       {"ParcelableHolder",
        [](const CodeGeneratorContext& c) {
@@ -608,35 +701,46 @@
          c.writer << "}\n";
        }},
   };
-  const auto found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
+  const auto found = method_map.find(AidlBackingTypeName(c.type));
   if (found != method_map.end()) {
     found->second(c);
+  } else if (c.type.IsFixedSizeArray()) {
+    std::vector<std::string> args = {JavaSignatureOf(c.type) + ".class"};
+    if (c.typenames.IsParcelable(c.type.GetName())) {
+      args.push_back(JavaNameOf(c.type) + ".CREATOR");
+    } else if (c.typenames.GetInterface(c.type)) {
+      args.push_back(c.type.GetName() + ".Stub::asInterface");
+    }
+    for (auto dim : c.type.GetFixedSizeArrayDimensions()) {
+      args.push_back(std::to_string(dim));
+    }
+    c.writer << c.var << " = " << c.parcel << ".createFixedArray(" << Join(args, ", ") << ");\n";
   } else {
     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()) {
+        auto new_array = name + "[]::new";
+        auto as_interface = name + ".Stub::asInterface";
+        c.writer << c.var << " = " << c.parcel << ".createInterfaceArray(" << new_array << ", "
+                 << as_interface << ");\n";
+      } else {
+        c.writer << c.var << " = " << name << ".Stub.asInterface(" << c.parcel
                  << ".readStrongBinder());\n";
       }
     } else if (t->AsParcelable() != nullptr) {
       if (c.type.IsArray()) {
-        c.writer << c.var << " = " << c.parcel << ".createTypedArray("
-                 << JavaNameOf(c.type, c.typenames) << ".CREATOR);\n";
+        c.writer << c.var << " = " << c.parcel << ".createTypedArray(" << JavaNameOf(c.type)
+                 << ".CREATOR);\n";
       } else {
-        // This is same as readTypedObject.
-        // Keeping below code just not to break unit tests.
-        c.writer << "if ((0!=" << c.parcel << ".readInt())) {\n";
-        c.writer.Indent();
-        c.writer << c.var << " = " << c.type.GetName() << ".CREATOR.createFromParcel(" << c.parcel
-                 << ");\n";
-        c.writer.Dedent();
-        c.writer << "}\n";
-        c.writer << "else {\n";
-        c.writer.Indent();
-        c.writer << c.var << " = null;\n";
-        c.writer.Dedent();
-        c.writer << "}\n";
+        if (c.min_sdk_version >= 23u) {
+          c.writer << c.var << " = " << c.parcel << ".readTypedObject(" << c.type.GetName()
+                   << ".CREATOR);\n";
+        } else {
+          c.writer << c.var << " = _Parcel.readTypedObject(" << c.parcel << ", " << c.type.GetName()
+                   << ".CREATOR);\n";
+        }
       }
     }
   }
@@ -680,17 +784,22 @@
       {"List",
        [](const CodeGeneratorContext& c) {
          if (c.type.IsGeneric()) {
-           const string& contained_type = c.type.GetTypeParameters().at(0)->GetName();
-           if (contained_type == "String") {
+           AIDL_FATAL_IF(c.type.GetTypeParameters().size() != 1, c.type);
+           const auto& element_type = *c.type.GetTypeParameters().at(0);
+           const auto& element_type_name = element_type.GetName();
+           if (element_type_name == "String") {
              c.writer << c.parcel << ".readStringList(" << c.var << ");\n";
-           } else if (contained_type == "IBinder") {
+           } else if (element_type_name == "IBinder") {
              c.writer << c.parcel << ".readBinderList(" << c.var << ");\n";
-           } else if (c.typenames.IsParcelable(contained_type)) {
+           } else if (c.typenames.IsParcelable(element_type_name)) {
              c.writer << c.parcel << ".readTypedList(" << c.var << ", "
-                      << JavaNameOf(*(c.type.GetTypeParameters().at(0)), c.typenames)
-                      << ".CREATOR);\n";
+                      << JavaNameOf(*(c.type.GetTypeParameters().at(0))) << ".CREATOR);\n";
+           } else if (c.typenames.GetInterface(element_type)) {
+             auto as_interface = element_type_name + ".Stub::asInterface";
+             c.writer << c.parcel << ".readInterfaceList(" << c.var << ", " << as_interface
+                      << ");\n";
            } else {
-             AIDL_FATAL(c.type) << "read: NOT IMPLEMENTED for " << contained_type;
+             AIDL_FATAL(c.type) << "read: NOT IMPLEMENTED for " << element_type_name;
            }
          } else {
            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
@@ -705,13 +814,14 @@
                     << ".readInt()).forEach(i -> {\n";
            c.writer.Indent();
            c.writer << "String k = " << c.parcel << ".readString();\n";
-           c.writer << JavaNameOf(*(c.type.GetTypeParameters().at(1)), c.typenames) << " v;\n";
+           c.writer << JavaSignatureOf(*(c.type.GetTypeParameters().at(1))) << " v;\n";
            CodeGeneratorContext value_context{
                c.writer,
                c.typenames,
                *c.type.GetTypeParameters()[1].get(),
                c.parcel,
                "v",
+               c.min_sdk_version,
                c.is_return_value,
                c.is_classloader_created,
                c.filename,
@@ -721,9 +831,6 @@
 
            c.writer.Dedent();
            c.writer << "});\n";
-
-           c.writer.Dedent();
-           c.writer << "}\n";
          } else {
            const string classloader = EnsureAndGetClassloader(const_cast<CodeGeneratorContext&>(c));
            c.writer << c.var << " = " << c.parcel << ".readHashMap(" << classloader << ");\n";
@@ -751,9 +858,17 @@
                   << ", android.os.ParcelFileDescriptor.CREATOR);\n";
        }},
   };
-  const auto& found = method_map.find(AidlBackingTypeName(c.type, c.typenames));
+  const auto& found = method_map.find(AidlBackingTypeName(c.type));
   if (found != method_map.end()) {
     found->second(c);
+  } else if (c.type.IsFixedSizeArray()) {
+    std::vector<std::string> args = {c.var};
+    if (c.typenames.IsParcelable(c.type.GetName())) {
+      args.push_back(c.type.GetName() + ".CREATOR");
+    } else if (c.typenames.GetInterface(c.type)) {
+      args.push_back(c.type.GetName() + ".Stub::asInterface");
+    }
+    c.writer << c.parcel << ".readFixedArray(" << Join(args, ", ") << ");\n";
   } else {
     const AidlDefinedType* t = c.typenames.TryGetDefinedType(c.type.GetName());
     AIDL_FATAL_IF(t == nullptr, c.type) << "Unknown type: " << c.type.GetName();
@@ -768,6 +883,10 @@
         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 as_interface = c.type.GetName() + ".Stub::asInterface";
+      c.writer << c.parcel << ".readInterfaceArray(" << c.var << ", " << as_interface << ");\n";
     }
   }
   return true;
diff --git a/aidl_to_java.h b/aidl_to_java.h
index 2ebe2c3..5a4632c 100644
--- a/aidl_to_java.h
+++ b/aidl_to_java.h
@@ -39,18 +39,20 @@
 
 // This header provides functions that translate AIDL things to Java things.
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value);
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value);
 
 // Returns the Java type signature of the AIDL type spec
 // This includes generic type parameters with array modifiers.
-string JavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames);
+string JavaSignatureOf(const AidlTypeSpecifier& aidl);
 
 // Returns the instantiable Jva type signature of the AIDL type spec
 // This includes generic type parameters, but excludes array modifiers.
-string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames);
+string InstantiableJavaSignatureOf(const AidlTypeSpecifier& aidl);
 
 // Returns the default Java value of the AIDL type spec
-string DefaultJavaValueOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames);
+string DefaultJavaValueOf(const AidlTypeSpecifier& aidl);
 
 // This carries information that is required to generate code for
 // marshalling and unmarshalling a method argument or a parcelable field
@@ -60,7 +62,7 @@
   const AidlTypeSpecifier& type;
   const string parcel;
   const string var;
-
+  const uint32_t min_sdk_version;
   // Set to true when the marshalled data will be returned to the client
   // This is given as a hint to the Parcelable that is being marshalled
   // so that the Parcelable can release its resource after the marshalling
@@ -89,7 +91,7 @@
 };
 
 // Writes code fragment that writes a variable to the parcel.
-bool WriteToParcelFor(const CodeGeneratorContext& c);
+void WriteToParcelFor(const CodeGeneratorContext& c);
 
 // Writes code fragment that reads data from the parcel into a variable. When
 // the variable type is array or List, the array or List is created.
@@ -103,6 +105,10 @@
 // in a parcelable
 void ToStringFor(const CodeGeneratorContext& c);
 
+// Generates create/read/write helper functions which are missing in Parcel.
+void GenerateParcelHelpers(CodeWriter& out, const AidlDefinedType& defined_type,
+                           const Options& options);
+
 }  // namespace java
 }  // namespace aidl
 }  // namespace android
diff --git a/aidl_to_ndk.cpp b/aidl_to_ndk.cpp
index 9d1b794..adcd451 100644
--- a/aidl_to_ndk.cpp
+++ b/aidl_to_ndk.cpp
@@ -24,11 +24,15 @@
 #include <functional>
 
 using ::android::base::Join;
+using ::android::base::Split;
 
 namespace android {
 namespace aidl {
 namespace ndk {
 
+static const AidlTypeSpecifier kIntType{AIDL_LOCATION_HERE, "int", /*array=*/std::nullopt, nullptr,
+                                        Comments{}};
+
 std::string NdkHeaderFile(const AidlDefinedType& defined_type, cpp::ClassNames name,
                           bool use_os_sep) {
   char seperator = (use_os_sep) ? OS_PATH_SEPARATOR : '/';
@@ -37,392 +41,162 @@
 
 // This represents a type in AIDL (e.g. 'String' which can be referenced in multiple ways)
 struct TypeInfo {
-  struct Aspect {
-    // name of the type in C++ output
-    std::string cpp_name;
-    // whether to prefer 'value type' over 'const&'
-    bool value_is_cheap;
-
-    std::function<void(const CodeGeneratorContext& c)> read_func;
-    std::function<void(const CodeGeneratorContext& c)> write_func;
-  };
-
-  // e.g. 'String'
-  Aspect raw;
-
-  // e.g. 'String[]'
-  std::shared_ptr<Aspect> array;
-
-  // note: Nullable types do not exist in Java. For most Java types, the type is split into a
-  // nullable and non-nullable variant. This is because C++ types are more usually non-nullable, but
-  // everything in Java is non-nullable. This does mean that some Java interfaces may have to have
-  // '@nullable' added to them in order to function as expected w/ the NDK. It also means that some
-  // transactions will be allowed in Java which are not allowed in C++. However, in Java, if a null
-  // is ignored, it will just result in a NullPointerException and be delivered to the other side.
-  // C++ does not have this same capacity (in Android), and so instead, we distinguish nullability
-  // in the type system.
-
-  // e.g. '@nullable String'
-  std::shared_ptr<Aspect> nullable;
-
-  // e.g. '@nullable String[]'
-  std::shared_ptr<Aspect> nullable_array;
+  // name of the type in C++ output
+  std::string cpp_name;
+  // whether to prefer 'value type' over 'const&'
+  bool value_is_cheap = false;
 };
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
-  if (type.IsArray()) {
-    return raw_value;
-  }
-
-  if (type.GetName() == "long" && !type.IsArray()) {
-    return raw_value + "L";
-  }
-
-  if (auto defined_type = type.GetDefinedType(); defined_type) {
-    auto enum_type = defined_type->AsEnumDeclaration();
-    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
-    return NdkFullClassName(*enum_type, cpp::ClassNames::RAW) +
-           "::" + raw_value.substr(raw_value.find_last_of('.') + 1);
-  }
-
-  return raw_value;
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value) {
+  return cpp::CppConstantValueDecorator(type, raw_value, /*is_ndk=*/true);
 };
 
-static std::function<void(const CodeGeneratorContext& c)> StandardRead(const std::string& name) {
-  return [name](const CodeGeneratorContext& c) {
-    c.writer << name << "(" << c.parcel << ", " << c.var << ")";
-  };
-}
-static std::function<void(const CodeGeneratorContext& c)> StandardWrite(const std::string& name) {
-  return [name](const CodeGeneratorContext& c) {
-    c.writer << name << "(" << c.parcel << ", " << c.var << ")";
-  };
-}
-
-TypeInfo PrimitiveType(const std::string& cpp_name, const std::string& pretty_name,
-                       const std::optional<std::string>& cpp_name_for_array_opt = std::nullopt) {
-  std::string cpp_name_for_array = cpp_name_for_array_opt.value_or(cpp_name);
-  return TypeInfo{
-      .raw =
-          TypeInfo::Aspect{
-              .cpp_name = cpp_name,
-              .value_is_cheap = true,
-              .read_func = StandardRead("AParcel_read" + pretty_name),
-              .write_func = StandardWrite("AParcel_write" + pretty_name),
-          },
-      .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::vector<" + cpp_name_for_array + ">",
-          .value_is_cheap = false,
-          .read_func = StandardRead("::ndk::AParcel_readVector"),
-          .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-      }),
-      .nullable = nullptr,
-      .nullable_array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::optional<std::vector<" + cpp_name_for_array + ">>",
-          .value_is_cheap = false,
-          .read_func = StandardRead("::ndk::AParcel_readVector"),
-          .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-      }),
-  };
-}
-
-TypeInfo InterfaceTypeInfo(const AidlInterface& type) {
-  const std::string clazz = NdkFullClassName(type, cpp::ClassNames::INTERFACE);
-
-  return TypeInfo{
-      .raw =
-          TypeInfo::Aspect{
-              .cpp_name = "std::shared_ptr<" + clazz + ">",
-              .value_is_cheap = false,
-              .read_func = StandardRead(clazz + "::readFromParcel"),
-              .write_func = StandardWrite(clazz + "::writeToParcel"),
-          },
-      .array = nullptr,
-      .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,
-  };
-}
-
-TypeInfo ParcelableTypeInfo(const AidlParcelable& type, const AidlTypeSpecifier& typeSpec,
-                            const AidlTypenames& types) {
-  std::string clazz = NdkFullClassName(type, cpp::ClassNames::RAW);
-  std::string template_params = "";
-  if (typeSpec.IsGeneric()) {
-    std::vector<std::string> type_params;
-    for (const auto& parameter : typeSpec.GetTypeParameters()) {
-      type_params.push_back(NdkNameOf(types, *parameter, StorageMode::STACK));
-    }
-    clazz += base::StringPrintf("<%s>", base::Join(type_params, ", ").c_str());
-  }
-  return TypeInfo{
-      .raw =
-          TypeInfo::Aspect{
-              .cpp_name = clazz,
-              .value_is_cheap = false,
-              .read_func = StandardRead("::ndk::AParcel_readParcelable"),
-              .write_func = StandardWrite("::ndk::AParcel_writeParcelable"),
-          },
-      .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::vector<" + 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::optional<" + clazz + ">",
-          .value_is_cheap = false,
-          .read_func = StandardRead("::ndk::AParcel_readNullableParcelable"),
-          .write_func = StandardWrite("::ndk::AParcel_writeNullableParcelable"),
-      }),
-      .nullable_array = nullptr,
-  };
-}
-
-TypeInfo EnumDeclarationTypeInfo(const AidlEnumDeclaration& enum_decl) {
-  const std::string clazz = NdkFullClassName(enum_decl, cpp::ClassNames::RAW);
-
-  static map<std::string, std::string> kAParcelTypeNameMap = {
-      {"byte", "Byte"},
-      {"int", "Int32"},
-      {"long", "Int64"},
-  };
-  auto aparcel_name_it = kAParcelTypeNameMap.find(enum_decl.GetBackingType().GetName());
-  AIDL_FATAL_IF(aparcel_name_it == kAParcelTypeNameMap.end(), enum_decl);
-  const std::string aparcel_name = aparcel_name_it->second;
-
-  const std::string backing_type_name =
-      NdkNameOf(AidlTypenames(), enum_decl.GetBackingType(), StorageMode::STACK);
-
-  return TypeInfo{
-      .raw = TypeInfo::Aspect{
-          .cpp_name = clazz,
-          .value_is_cheap = true,
-          .read_func =
-              [aparcel_name, backing_type_name](const CodeGeneratorContext& c) {
-                c.writer << "AParcel_read" << aparcel_name << "(" << c.parcel
-                         << ", reinterpret_cast<" << backing_type_name << "*>(" << c.var << "))";
-              },
-          .write_func =
-              [aparcel_name, backing_type_name](const CodeGeneratorContext& c) {
-                c.writer << "AParcel_write" << aparcel_name << "(" << c.parcel << ", static_cast<"
-                         << backing_type_name << ">(" << c.var << "))";
-              },
-      },
-      .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::vector<" + clazz + ">",
-          .value_is_cheap = false,
-          .read_func =
-              [aparcel_name, backing_type_name](const CodeGeneratorContext& c) {
-                c.writer << "AParcel_read" << aparcel_name << "Array(" << c.parcel
-                         << ", static_cast<void*>(" << c.var
-                         << "), ndk::AParcel_stdVectorAllocator<" << backing_type_name << ">)";
-              },
-          .write_func =
-              [aparcel_name, backing_type_name](const CodeGeneratorContext& c) {
-                c.writer << "AParcel_write" << aparcel_name << "Array(" << c.parcel
-                         << ", reinterpret_cast<const " << backing_type_name << "*>(" << c.var
-                         << ".data()), " << c.var << ".size())";
-              },
-      }),
-      .nullable = nullptr,
-      .nullable_array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::optional<std::vector<" + clazz + ">>",
-          .value_is_cheap = false,
-          .read_func =
-              [aparcel_name, backing_type_name](const CodeGeneratorContext& c) {
-                c.writer << "AParcel_read" << aparcel_name << "Array(" << c.parcel
-                         << ", static_cast<void*>(" << c.var
-                         << "), ndk::AParcel_nullableStdVectorAllocator<" << backing_type_name
-                         << ">)";
-              },
-          .write_func =
-              [aparcel_name, backing_type_name](const CodeGeneratorContext& c) {
-                // If the var exists, use writeArray with data() and size().
-                // Otherwise, use nullptr and -1.
-                c.writer << "AParcel_write" << aparcel_name << "Array(" << c.parcel << ", ("
-                         << c.var << " ? reinterpret_cast<const " << backing_type_name << "*>("
-                         << c.var << "->data()) : nullptr)"
-                         << ", (" << c.var << " ? " << c.var << "->size() : -1))";
-              },
-      }),
-  };
-}
-
 // map from AIDL built-in type name to the corresponding Ndk type info
 static map<std::string, TypeInfo> kNdkTypeInfoMap = {
-    {"void", TypeInfo{{"void", true, nullptr, nullptr}, nullptr, nullptr, nullptr}},
-    {"boolean", PrimitiveType("bool", "Bool")},
-    {"byte", PrimitiveType("int8_t", "Byte", "uint8_t")},
-    {"char", PrimitiveType("char16_t", "Char")},
-    {"int", PrimitiveType("int32_t", "Int32")},
-    {"long", PrimitiveType("int64_t", "Int64")},
-    {"float", PrimitiveType("float", "Float")},
-    {"double", PrimitiveType("double", "Double")},
-    {"String",
-     TypeInfo{
-         .raw =
-             TypeInfo::Aspect{
-                 .cpp_name = "std::string",
-                 .value_is_cheap = false,
-                 .read_func = StandardRead("::ndk::AParcel_readString"),
-                 .write_func = StandardWrite("::ndk::AParcel_writeString"),
-             },
-         .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-             .cpp_name = "std::vector<std::string>",
-             .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::optional<std::string>",
-             .value_is_cheap = false,
-             .read_func = StandardRead("::ndk::AParcel_readString"),
-             .write_func = StandardWrite("::ndk::AParcel_writeString"),
-         }),
-         .nullable_array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-             .cpp_name = "std::optional<std::vector<std::optional<std::string>>>",
-             .value_is_cheap = false,
-             .read_func = StandardRead("::ndk::AParcel_readVector"),
-             .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-         }),
-     }},
+    {"void", {"void", true}},
+    {"boolean", {"bool", true}},
+    {"byte", {"int8_t", true}},
+    {"char", {"char16_t", true}},
+    {"int", {"int32_t", true}},
+    {"long", {"int64_t", true}},
+    {"float", {"float", true}},
+    {"double", {"double", true}},
+    {"String", {"std::string"}},
     // TODO(b/136048684) {"Map", ""},
-    {"IBinder",
-     TypeInfo{
-         .raw =
-             TypeInfo::Aspect{
-                 .cpp_name = "::ndk::SpAIBinder",
-                 .value_is_cheap = false,
-                 .read_func = StandardRead("::ndk::AParcel_readRequiredStrongBinder"),
-                 .write_func = StandardRead("::ndk::AParcel_writeRequiredStrongBinder"),
-             },
-         .array = nullptr,
-         .nullable = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-             .cpp_name = "::ndk::SpAIBinder",
-             .value_is_cheap = false,
-             .read_func = StandardRead("::ndk::AParcel_readNullableStrongBinder"),
-             .write_func = StandardRead("::ndk::AParcel_writeNullableStrongBinder"),
-         }),
-         .nullable_array = nullptr,
-     }},
-    {"ParcelFileDescriptor",
-     TypeInfo{
-         .raw =
-             TypeInfo::Aspect{
-                 .cpp_name = "::ndk::ScopedFileDescriptor",
-                 .value_is_cheap = false,
-                 .read_func = StandardRead("::ndk::AParcel_readRequiredParcelFileDescriptor"),
-                 .write_func = StandardRead("::ndk::AParcel_writeRequiredParcelFileDescriptor"),
-             },
-         .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-             .cpp_name = "std::vector<::ndk::ScopedFileDescriptor>",
-             .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 = "::ndk::ScopedFileDescriptor",
-             .value_is_cheap = false,
-             .read_func = StandardRead("::ndk::AParcel_readNullableParcelFileDescriptor"),
-             .write_func = StandardRead("::ndk::AParcel_writeNullableParcelFileDescriptor"),
-         }),
-         .nullable_array = nullptr,
-     }},
-    {"ParcelableHolder",
-     TypeInfo{
-         .raw =
-             TypeInfo::Aspect{
-                 .cpp_name = "::ndk::AParcelableHolder",
-                 .value_is_cheap = false,
-                 .read_func = StandardRead("::ndk::AParcel_readParcelable"),
-                 .write_func = StandardWrite("::ndk::AParcel_writeParcelable"),
-             },
-         .array = nullptr,
-         .nullable = nullptr,
-         .nullable_array = nullptr,
-     }},
+    {"IBinder", {"::ndk::SpAIBinder"}},
+    {"ParcelFileDescriptor", {"::ndk::ScopedFileDescriptor"}},
+    {"ParcelableHolder", {"::ndk::AParcelableHolder"}},
 };
 
-static TypeInfo::Aspect GetTypeAspect(const AidlTypenames& types, const AidlTypeSpecifier& aidl) {
-  AIDL_FATAL_IF(!aidl.IsResolved(), aidl) << aidl.ToString();
+static TypeInfo GetBaseTypeInfo(const AidlTypenames& types, const AidlTypeSpecifier& aidl) {
   auto& aidl_name = aidl.GetName();
 
-  TypeInfo info;
-
-  // TODO(b/136048684): For now, List<T> is converted to T[].(Both are using vector<T>)
-  if (aidl_name == "List") {
-    AIDL_FATAL_IF(!aidl.IsGeneric(), aidl) << "List must be generic type.";
-    AIDL_FATAL_IF(aidl.GetTypeParameters().size() != 1, aidl)
-        << "List can accept only one type parameter.";
-    const auto& type_param = aidl.GetTypeParameters()[0];
-    // TODO(b/136048684) AIDL doesn't support nested type parameter yet.
-    AIDL_FATAL_IF(type_param->IsGeneric(), aidl) << "AIDL doesn't support nested type parameter";
-
-    AidlTypeSpecifier array_type =
-        AidlTypeSpecifier(AIDL_LOCATION_HERE, type_param->GetUnresolvedName(), true /* isArray */,
-                          nullptr /* type_params */, aidl.GetComments());
-    if (!(array_type.Resolve(types) && array_type.CheckValid(types))) {
-      AIDL_FATAL(aidl) << "The type parameter is wrong.";
-    }
-    return GetTypeAspect(types, array_type);
-  }
-
   if (AidlTypenames::IsBuiltinTypename(aidl_name)) {
     auto it = kNdkTypeInfoMap.find(aidl_name);
     AIDL_FATAL_IF(it == kNdkTypeInfoMap.end(), aidl_name);
-    info = it->second;
+    return it->second;
+  }
+  const AidlDefinedType* type = types.TryGetDefinedType(aidl_name);
+  AIDL_FATAL_IF(type == nullptr, aidl_name) << "Unrecognized type.";
+
+  if (const AidlInterface* intf = type->AsInterface(); intf != nullptr) {
+    const std::string clazz = NdkFullClassName(*intf, cpp::ClassNames::INTERFACE);
+    return TypeInfo{"std::shared_ptr<" + clazz + ">"};
+  } else if (const AidlParcelable* parcelable = type->AsParcelable(); parcelable != nullptr) {
+    std::string clazz = NdkFullClassName(*parcelable, cpp::ClassNames::RAW);
+    std::string template_params = "";
+    if (aidl.IsGeneric()) {
+      std::vector<std::string> type_params;
+      for (const auto& parameter : aidl.GetTypeParameters()) {
+        type_params.push_back(NdkNameOf(types, *parameter, StorageMode::STACK));
+      }
+      clazz += base::StringPrintf("<%s>", base::Join(type_params, ", ").c_str());
+    }
+    return TypeInfo{clazz};
+  } else if (const AidlEnumDeclaration* enum_decl = type->AsEnumDeclaration();
+             enum_decl != nullptr) {
+    const std::string clazz = NdkFullClassName(*enum_decl, cpp::ClassNames::RAW);
+    return TypeInfo{clazz, true};
   } else {
-    const AidlDefinedType* type = types.TryGetDefinedType(aidl_name);
-    AIDL_FATAL_IF(type == nullptr, aidl_name) << "Unrecognized type.";
+    AIDL_FATAL(aidl_name) << "Unrecognized type";
+  }
+}
 
-    if (const AidlInterface* intf = type->AsInterface(); intf != nullptr) {
-      info = InterfaceTypeInfo(*intf);
-    } else if (const AidlParcelable* parcelable = type->AsParcelable(); parcelable != nullptr) {
-      info = ParcelableTypeInfo(*parcelable, aidl, types);
-    } else if (const AidlEnumDeclaration* enum_decl = type->AsEnumDeclaration();
-               enum_decl != nullptr) {
-      info = EnumDeclarationTypeInfo(*enum_decl);
-    } else {
-      AIDL_FATAL(aidl_name) << "Unrecognized type";
+static TypeInfo WrapNullableType(TypeInfo info, bool is_heap) {
+  if (is_heap) {
+    info.cpp_name = "std::unique_ptr<" + info.cpp_name + ">";
+  } else {
+    info.cpp_name = "std::optional<" + info.cpp_name + ">";
+  }
+  info.value_is_cheap = false;
+  return info;
+}
+
+static TypeInfo WrapArrayType(TypeInfo info, const ArrayType* array) {
+  AIDL_FATAL_IF(!array, AIDL_LOCATION_HERE) << "not an array";
+  // When "byte"(AIDL) is used in an array, use "uint8_t" because it's more C++ idiomatic.
+  if (info.cpp_name == "int8_t") {
+    info.cpp_name = "uint8_t";
+  }
+  if (std::get_if<DynamicArray>(array)) {
+    info.cpp_name = "std::vector<" + info.cpp_name + ">";
+  } else {
+    const auto& dimensions = std::get<FixedSizeArray>(*array).dimensions;
+    for (auto it = rbegin(dimensions), end = rend(dimensions); it != end; it++) {
+      info.cpp_name = "std::array<" + info.cpp_name + ", " +
+                      (*it)->ValueString(kIntType, ConstantValueDecorator) + ">";
     }
   }
+  info.value_is_cheap = false;
+  return info;
+}
 
-  if (aidl.IsArray()) {
-    if (aidl.IsNullable()) {
-      AIDL_FATAL_IF(info.nullable_array == nullptr, aidl)
-          << "Unsupported type in NDK Backend: " << aidl.ToString();
-      return *info.nullable_array;
+static bool ShouldWrapNullable(const AidlTypenames& types, const std::string& aidl_name) {
+  if (AidlTypenames::IsPrimitiveTypename(aidl_name) || aidl_name == "ParcelableHolder" ||
+      aidl_name == "IBinder" || aidl_name == "ParcelFileDescriptor") {
+    return false;
+  }
+  if (auto defined_type = types.TryGetDefinedType(aidl_name); defined_type) {
+    if (defined_type->AsEnumDeclaration() || defined_type->AsInterface()) {
+      return false;
     }
-    AIDL_FATAL_IF(info.array == nullptr, aidl)
-        << "Unsupported type in NDK Backend: " << aidl.ToString();
-    return *info.array;
+  }
+  return true;
+}
+
+static TypeInfo GetTypeInfo(const AidlTypenames& types, const AidlTypeSpecifier& aidl) {
+  AIDL_FATAL_IF(!aidl.IsResolved(), aidl) << aidl.ToString();
+  // Keep original @nullable to handle the case of List<T>. "@nullable" is attached to "List" not
+  // "T"
+  bool is_nullable = aidl.IsNullable();
+  const ArrayType* array = nullptr;
+  const AidlTypeSpecifier* element_type = &aidl;
+
+  // List<T> is converted to T[].
+  if (aidl.GetName() == "List") {
+    static const ArrayType kDynamicArray{DynamicArray{}};
+
+    AIDL_FATAL_IF(!aidl.IsGeneric(), aidl) << "List must be generic type.";
+    AIDL_FATAL_IF(aidl.GetTypeParameters().size() != 1, aidl)
+        << "List can accept only one type parameter.";
+    const auto& type_param = *aidl.GetTypeParameters()[0];
+    // TODO(b/136048684) AIDL doesn't support nested type parameter yet.
+    AIDL_FATAL_IF(type_param.IsGeneric(), aidl) << "AIDL doesn't support nested type parameter";
+    // Treat "List<T>" as an array of T.
+    array = &kDynamicArray;
+    element_type = &type_param;
+  } else if (aidl.IsArray()) {
+    array = &aidl.GetArray();
   }
 
-  if (aidl.IsNullable()) {
-    AIDL_FATAL_IF(info.nullable == nullptr, aidl)
-        << "Unsupported type in NDK Backend: " << aidl.ToString();
-    return *info.nullable;
-  }
+  TypeInfo info = GetBaseTypeInfo(types, *element_type);
 
-  return info.raw;
+  if (is_nullable && ShouldWrapNullable(types, element_type->GetName())) {
+    info = WrapNullableType(info, aidl.IsHeapNullable());
+  }
+  if (array) {
+    info = WrapArrayType(info, array);
+    if (is_nullable) {
+      AIDL_FATAL_IF(aidl.IsHeapNullable(), aidl) << "Array/List can't be @nullable(heap=true)";
+      info = WrapNullableType(info, /*is_heap=*/false);
+    }
+  }
+  return info;
 }
 
 std::string NdkFullClassName(const AidlDefinedType& type, cpp::ClassNames name) {
   std::vector<std::string> pieces = {"::aidl"};
-  std::vector<std::string> package = type.GetSplitPackage();
-  pieces.insert(pieces.end(), package.begin(), package.end());
-  pieces.push_back(cpp::ClassName(type, name));
-
+  std::vector<std::string> split_name = Split(type.GetCanonicalName(), ".");
+  pieces.insert(pieces.end(), split_name.begin(), split_name.end());
+  // Override name part with cpp::ClassName(type, name)
+  pieces.back() = cpp::ClassName(type, name);
   return Join(pieces, "::");
 }
 
 std::string NdkNameOf(const AidlTypenames& types, const AidlTypeSpecifier& aidl, StorageMode mode) {
-  TypeInfo::Aspect aspect = GetTypeAspect(types, aidl);
+  TypeInfo aspect = GetTypeInfo(types, aidl);
 
   switch (mode) {
     case StorageMode::STACK:
@@ -440,34 +214,20 @@
   }
 }
 
-size_t NdkAlignmentOf(const AidlTypenames& types, const AidlTypeSpecifier& aidl) {
-  // map from NDK type name to the corresponding alignment size
-  static map<string, int> alignment = {
-      {"bool", 1},  {"int8_t", 1},  {"char16_t", 2}, {"double", 8},
-      {"float", 4}, {"int32_t", 4}, {"int64_t", 8},
-  };
-
-  const string& name = NdkNameOf(types, aidl, StorageMode::STACK);
-  if (alignment.find(name) != alignment.end()) {
-    return alignment[name];
-  } else {
-    const auto& definedType = types.TryGetDefinedType(aidl.GetName());
-    AIDL_FATAL_IF(definedType == nullptr, aidl) << "Failed to resolve type.";
-    if (const auto& enumType = definedType->AsEnumDeclaration(); enumType != nullptr) {
-      return NdkAlignmentOf(types, enumType->GetBackingType());
-    }
-  }
-  return 0;
-}
-
 void WriteToParcelFor(const CodeGeneratorContext& c) {
-  TypeInfo::Aspect aspect = GetTypeAspect(c.types, c.type);
-  aspect.write_func(c);
+  if (c.type.IsNullable()) {
+    c.writer << "::ndk::AParcel_writeNullableData(" << c.parcel << ", " << c.var << ")";
+  } else {
+    c.writer << "::ndk::AParcel_writeData(" << c.parcel << ", " << c.var << ")";
+  }
 }
 
 void ReadFromParcelFor(const CodeGeneratorContext& c) {
-  TypeInfo::Aspect aspect = GetTypeAspect(c.types, c.type);
-  aspect.read_func(c);
+  if (c.type.IsNullable()) {
+    c.writer << "::ndk::AParcel_readNullableData(" << c.parcel << ", " << c.var << ")";
+  } else {
+    c.writer << "::ndk::AParcel_readData(" << c.parcel << ", " << c.var << ")";
+  }
 }
 
 std::string NdkArgList(
diff --git a/aidl_to_ndk.h b/aidl_to_ndk.h
index 370d07b..7d815c5 100644
--- a/aidl_to_ndk.h
+++ b/aidl_to_ndk.h
@@ -31,7 +31,9 @@
 std::string NdkHeaderFile(const AidlDefinedType& defined_type, cpp::ClassNames name,
                           bool use_os_sep = true);
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value);
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value);
 
 // Returns ::aidl::some_package::some_sub_package::foo::IFoo/BpFoo/BnFoo
 std::string NdkFullClassName(const AidlDefinedType& type, cpp::ClassNames name);
@@ -40,12 +42,6 @@
 // array modifiers.
 std::string NdkNameOf(const AidlTypenames& types, const AidlTypeSpecifier& aidl, StorageMode mode);
 
-// Return the alignment of known types and enum backing types.
-// If the alignment is unknown, or it is a FizedSize parcelable with its
-// own guaranteed alignment(so it does not need to be specified), 0 will be
-// returned.
-size_t NdkAlignmentOf(const AidlTypenames& types, const AidlTypeSpecifier& aidl);
-
 struct CodeGeneratorContext {
   CodeWriter& writer;
 
diff --git a/aidl_to_rust.cpp b/aidl_to_rust.cpp
index 4121ff4..3213266 100644
--- a/aidl_to_rust.cpp
+++ b/aidl_to_rust.cpp
@@ -39,40 +39,54 @@
 namespace {
 std::string GetRawRustName(const AidlTypeSpecifier& type);
 
-std::string ConstantValueDecoratorInternal(const AidlTypeSpecifier& type,
-                                           const std::string& raw_value, bool by_ref) {
+std::string ConstantValueDecoratorInternal(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value, bool by_ref) {
   if (type.IsArray()) {
-    // Convert `{ ... }` to `vec!{ ... }`
-    return "vec!" + raw_value;
+    const auto& values = std::get<std::vector<std::string>>(raw_value);
+    std::string value = "[" + Join(values, ", ") + "]";
+    if (type.IsDynamicArray()) {
+      value = "vec!" + value;
+    }
+    if (!type.IsMutated() && type.IsNullable()) {
+      value = "Some(" + value + ")";
+    }
+    return value;
   }
 
+  std::string value = std::get<std::string>(raw_value);
+
   const auto& aidl_name = type.GetName();
   if (aidl_name == "char") {
-    return raw_value + " as u16";
+    return value + " as u16";
   }
 
   if (aidl_name == "float") {
-    // raw_value already ends in `f`, so just add `32`
-    return raw_value + "32";
+    // value already ends in `f`, so just add `32`
+    return value + "32";
   }
 
   if (aidl_name == "double") {
-    return raw_value + "f64";
+    return value + "f64";
+  }
+
+  if (auto defined_type = type.GetDefinedType(); defined_type) {
+    auto enum_type = defined_type->AsEnumDeclaration();
+    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << value << "\"";
+    return GetRawRustName(type) + "::" + value.substr(value.find_last_of('.') + 1);
   }
 
   if (aidl_name == "String" && !by_ref) {
     // The actual type might be String or &str,
     // and .into() transparently converts into either one
-    return raw_value + ".into()";
+    value = value + ".into()";
   }
 
-  if (auto defined_type = type.GetDefinedType(); defined_type) {
-    auto enum_type = defined_type->AsEnumDeclaration();
-    AIDL_FATAL_IF(!enum_type, type) << "Invalid type for \"" << raw_value << "\"";
-    return GetRawRustName(type) + "::" + raw_value.substr(raw_value.find_last_of('.') + 1);
+  if (type.IsNullable()) {
+    value = "Some(" + value + ")";
   }
 
-  return raw_value;
+  return value;
 }
 
 std::string GetRawRustName(const AidlTypeSpecifier& type) {
@@ -100,9 +114,10 @@
       {"double", "f64"},
       {"String", "String"},
       {"IBinder", "binder::SpIBinder"},
-      {"ParcelFileDescriptor", "binder::parcel::ParcelFileDescriptor"},
+      {"ParcelFileDescriptor", "binder::ParcelFileDescriptor"},
+      {"ParcelableHolder", "binder::ParcelableHolder"},
   };
-
+  const bool is_vector = type.IsArray() || typenames.IsList(type);
   // If the type is an array/List<T>, get the inner element type
   AIDL_FATAL_IF(typenames.IsList(type) && type.GetTypeParameters().size() != 1, type);
   const auto& element_type = type.IsGeneric() ? (*type.GetTypeParameters().at(0)) : type;
@@ -113,8 +128,8 @@
       return "u8";
     } else if (element_type_name == "String" && mode == StorageMode::UNSIZED_ARGUMENT) {
       return "str";
-    } else if (element_type_name == "ParcelFileDescriptor") {
-      if (type.IsArray() && mode == StorageMode::DEFAULT_VALUE) {
+    } else if (element_type_name == "ParcelFileDescriptor" || element_type_name == "IBinder") {
+      if (is_vector && mode == StorageMode::DEFAULT_VALUE) {
         // Out-arguments of ParcelFileDescriptors arrays need to
         // be Vec<Option<ParcelFileDescriptor>> so resize_out_vec
         // can initialize all elements to None (it requires Default
@@ -126,50 +141,108 @@
     }
     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
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value) {
-  auto rust_value = ConstantValueDecoratorInternal(type, raw_value, false);
-  if (type.IsNullable()) {
-    return "Some(" + rust_value + ")";
-  }
-  return rust_value;
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value) {
+  return ConstantValueDecoratorInternal(type, raw_value, false);
 }
 
-std::string ConstantValueDecoratorRef(const AidlTypeSpecifier& type, const std::string& raw_value) {
-  auto rust_value = ConstantValueDecoratorInternal(type, raw_value, true);
-  if (type.IsNullable()) {
-    return "Some(" + rust_value + ")";
+std::string ConstantValueDecoratorRef(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value) {
+  return ConstantValueDecoratorInternal(type, raw_value, true);
+}
+
+// Returns default value for array.
+std::string ArrayDefaultValue(const AidlTypeSpecifier& type) {
+  AIDL_FATAL_IF(!type.IsFixedSizeArray(), type) << "not a fixed-size array";
+  auto dimensions = type.GetFixedSizeArrayDimensions();
+  std::string value = "Default::default()";
+  for (auto it = rbegin(dimensions), end = rend(dimensions); it != end; it++) {
+    value = "[" + Join(std::vector<std::string>(*it, value), ", ") + "]";
   }
-  return rust_value;
+  return value;
+}
+
+// Returns true if @nullable T[] should be mapped Option<Vec<Option<T>>
+bool UsesOptionInNullableVector(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
+  AIDL_FATAL_IF(!type.IsArray() && !typenames.IsList(type), type) << "not a vector";
+  AIDL_FATAL_IF(typenames.IsList(type) && type.GetTypeParameters().size() != 1, type)
+      << "List should have a single type arg.";
+
+  const auto& element_type = type.IsArray() ? type : *type.GetTypeParameters().at(0);
+  if (typenames.IsPrimitiveTypename(element_type.GetName())) {
+    return false;
+  }
+  if (typenames.GetEnumDeclaration(element_type)) {
+    return false;
+  }
+  return true;
+}
+
+std::string RustLifetimeName(Lifetime lifetime) {
+  switch (lifetime) {
+    case Lifetime::NONE:
+      return "";
+    case Lifetime::A:
+      return "'a ";
+  }
+}
+
+std::string RustLifetimeGeneric(Lifetime lifetime) {
+  switch (lifetime) {
+    case Lifetime::NONE:
+      return "";
+    case Lifetime::A:
+      return "<'a>";
+  }
 }
 
 std::string RustNameOf(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
-                       StorageMode mode) {
+                       StorageMode mode, Lifetime lifetime) {
   std::string rust_name;
   if (type.IsArray() || typenames.IsList(type)) {
     StorageMode element_mode;
-    if (mode == StorageMode::OUT_ARGUMENT || mode == StorageMode::DEFAULT_VALUE) {
+    if (type.IsFixedSizeArray() && mode == StorageMode::PARCELABLE_FIELD) {
+      // Elements of fixed-size array field need to have Default.
+      element_mode = StorageMode::DEFAULT_VALUE;
+    } else if (mode == StorageMode::OUT_ARGUMENT || mode == StorageMode::DEFAULT_VALUE) {
       // Elements need to have Default for resize_out_vec()
       element_mode = StorageMode::DEFAULT_VALUE;
     } else {
       element_mode = StorageMode::VALUE;
     }
     rust_name = GetRustName(type, typenames, element_mode);
-    if (type.IsNullable() && rust_name == "String") {
+    if (type.IsNullable() && UsesOptionInNullableVector(type, typenames)) {
       // The mapping for nullable string arrays is
       // optional<vector<optional<string>>> in the NDK,
       // so we do the same
-      rust_name = "Option<" + rust_name + ">";
+      // However, we don't need to when GetRustName() already wraps it with Option.
+      if (!base::StartsWith(rust_name, "Option<")) {
+        rust_name = "Option<" + rust_name + ">";
+      }
     }
     if (mode == StorageMode::UNSIZED_ARGUMENT) {
       rust_name = "[" + rust_name + "]";
+    } else if (type.IsFixedSizeArray()) {
+      auto dimensions = type.GetFixedSizeArrayDimensions();
+      // T[N][M] => [[T; M]; N]
+      for (auto it = rbegin(dimensions), end = rend(dimensions); it != end; it++) {
+        rust_name = "[" + rust_name + "; " + std::to_string(*it) + "]";
+      }
     } else {
       rust_name = "Vec<" + rust_name + ">";
     }
@@ -180,20 +253,24 @@
   if (mode == StorageMode::IN_ARGUMENT || mode == StorageMode::UNSIZED_ARGUMENT) {
     // If this is a nullable input argument, put the reference inside the option,
     // e.g., `Option<&str>` instead of `&Option<str>`
-    rust_name = "&" + rust_name;
+    rust_name = "&" + RustLifetimeName(lifetime) + rust_name;
   }
 
   if (type.IsNullable() ||
       // Some types don't implement Default, so we wrap them
       // in Option, which defaults to None
-      (!TypeHasDefault(type, typenames) &&
+      (TypeNeedsOption(type, typenames) &&
        (mode == StorageMode::DEFAULT_VALUE || mode == StorageMode::OUT_ARGUMENT ||
         mode == StorageMode::PARCELABLE_FIELD))) {
-    rust_name = "Option<" + rust_name + ">";
+    if (type.IsHeapNullable()) {
+      rust_name = "Option<Box<" + rust_name + ">>";
+    } else {
+      rust_name = "Option<" + rust_name + ">";
+    }
   }
 
   if (mode == StorageMode::OUT_ARGUMENT || mode == StorageMode::INOUT_ARGUMENT) {
-    rust_name = "&mut " + rust_name;
+    rust_name = "&" + RustLifetimeName(lifetime) + "mut " + rust_name;
   }
 
   return rust_name;
@@ -209,9 +286,9 @@
 
   const bool isEnum = definedType && definedType->AsEnumDeclaration() != nullptr;
   const bool isPrimitive = AidlTypenames::IsPrimitiveTypename(typeName);
-  if (typeName == "String" || arg.GetType().IsArray() || typenames.IsList(arg.GetType())) {
+  if (typeName == "String" || arg.GetType().IsDynamicArray() || typenames.IsList(arg.GetType())) {
     return StorageMode::UNSIZED_ARGUMENT;
-  } else if (!(isPrimitive || isEnum)) {
+  } else if (!(isPrimitive || isEnum) || arg.GetType().IsFixedSizeArray()) {
     return StorageMode::IN_ARGUMENT;
   } else {
     return StorageMode::VALUE;
@@ -271,30 +348,35 @@
   return definedType != nullptr && definedType->AsInterface() != nullptr;
 }
 
-bool TypeHasDefault(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
+bool TypeNeedsOption(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
   if (type.IsArray() || typenames.IsList(type)) {
-    return true;
+    return false;
   }
 
   // Already an Option<T>
   if (type.IsNullable()) {
-    return true;
+    return false;
   }
 
   const string& aidl_name = type.GetName();
   if (aidl_name == "IBinder") {
-    return false;
+    return true;
   }
   if (aidl_name == "ParcelFileDescriptor") {
+    return true;
+  }
+  if (aidl_name == "ParcelableHolder") {
+    // ParcelableHolder never needs an Option because we always
+    // call its new() constructor directly instead of default()
     return false;
   }
 
   // Strong<dyn IFoo> values don't implement Default
   if (TypeIsInterface(type, typenames)) {
-    return false;
+    return true;
   }
 
-  return true;
+  return false;
 }
 
 }  // namespace rust
diff --git a/aidl_to_rust.h b/aidl_to_rust.h
index 292e4df..8a49a56 100644
--- a/aidl_to_rust.h
+++ b/aidl_to_rust.h
@@ -42,6 +42,11 @@
   AS_DEREF,
 };
 
+enum class Lifetime {
+  NONE,
+  A,
+};
+
 inline bool IsReference(ReferenceMode ref_mode) {
   switch (ref_mode) {
     case ReferenceMode::REF:
@@ -53,14 +58,29 @@
   }
 }
 
-std::string ConstantValueDecorator(const AidlTypeSpecifier& type, const std::string& raw_value);
+std::string ConstantValueDecorator(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value);
 
-std::string ConstantValueDecoratorRef(const AidlTypeSpecifier& type, const std::string& raw_value);
+std::string ConstantValueDecoratorRef(
+    const AidlTypeSpecifier& type,
+    const std::variant<std::string, std::vector<std::string>>& raw_value);
+
+std::string ArrayDefaultValue(const AidlTypeSpecifier& type);
+
+// Returns "'lifetime_name " including the initial apostrophe and the trailing space.
+// Returns empty string for NONE.
+std::string RustLifetimeName(Lifetime lifetime);
+
+// Returns "<'lifetime_name>" or empty string for NONE.
+std::string RustLifetimeGeneric(Lifetime lifetime);
 
 // Returns the Rust type signature of the AIDL type spec
 // This includes generic type parameters with array modifiers.
+//
+// The lifetime argument is used to annotate all references.
 std::string RustNameOf(const AidlTypeSpecifier& aidl, const AidlTypenames& typenames,
-                       StorageMode mode);
+                       StorageMode mode, Lifetime lifetime);
 
 StorageMode ArgumentStorageMode(const AidlArgument& arg, const AidlTypenames& typenames);
 
@@ -70,7 +90,7 @@
 
 bool TypeIsInterface(const AidlTypeSpecifier& type, const AidlTypenames& typenames);
 
-bool TypeHasDefault(const AidlTypeSpecifier& type, const AidlTypenames& typenames);
+bool TypeNeedsOption(const AidlTypeSpecifier& type, const AidlTypenames& typenames);
 
 }  // namespace rust
 }  // namespace aidl
diff --git a/aidl_typenames.cpp b/aidl_typenames.cpp
index 8440463..67da4e7 100644
--- a/aidl_typenames.cpp
+++ b/aidl_typenames.cpp
@@ -18,6 +18,7 @@
 #include "aidl_language.h"
 #include "logging.h"
 
+#include <android-base/file.h>
 #include <android-base/strings.h>
 
 #include <map>
@@ -103,43 +104,87 @@
 }
 
 bool AidlTypenames::IsIgnorableImport(const string& import) const {
+  if (IsBuiltinTypename(import)) return true;
+
   static set<string> ignore_import = {
       "android.os.IInterface",   "android.os.IBinder", "android.os.Parcelable", "android.os.Parcel",
       "android.content.Context", "java.lang.String",   "java.lang.CharSequence"};
   // these known built-in types don't need to be imported
-  const bool in_ignore_import = ignore_import.find(import) != ignore_import.end();
-  // an already defined type doesn't need to be imported again unless it is from
-  // the preprocessed file
-  auto ret = TryGetDefinedTypeImpl(import);
-  const bool defined_type_not_from_preprocessed = ret.type != nullptr && !ret.from_preprocessed;
-  return in_ignore_import || defined_type_not_from_preprocessed;
+  if (ignore_import.find(import) != ignore_import.end()) return true;
+
+  if (TryGetDefinedType(import)) return true;
+
+  return false;
 }
 
+// Add a parsed document and populate type names in it.
+// Name conflict is an error unless one of them is from preprocessed.
+// For legacy, we populate unqualified names from preprocessed unstructured parcelable types
+// so that they can be referenced via a simple name.
 bool AidlTypenames::AddDocument(std::unique_ptr<AidlDocument> doc) {
-  for (const auto& type : doc->DefinedTypes()) {
-    if (defined_types_.find(type->GetCanonicalName()) != defined_types_.end()) {
-      return false;
-    }
-    if (!HasValidNameComponents(*type)) {
-      return false;
-    }
-  }
-  documents_.push_back(std::move(doc));
-  for (const auto& type : documents_.back()->DefinedTypes()) {
-    defined_types_.emplace(type->GetCanonicalName(), type.get());
-  }
-  return true;
-}
+  bool is_preprocessed = doc->IsPreprocessed();
+  std::vector<AidlDefinedType*> types_to_add;
+  // Add types in two steps to avoid adding a type while the doc is rejected.
+  // 1. filter types to add
+  // 2. add types
 
-const AidlDocument* AidlTypenames::GetDocumentFor(const AidlDefinedType* type) const {
-  for (const auto& doc : AllDocuments()) {
-    for (const auto& defined_type : doc->DefinedTypes()) {
-      if (defined_type.get() == type) {
-        return doc.get();
+  std::function<bool(const std::vector<std::unique_ptr<AidlDefinedType>>&)> collect_types_to_add;
+  collect_types_to_add = [&](auto& types) {
+    for (const auto& type : types) {
+      if (IsBuiltinTypename(type->GetName())) {
+        // ParcelFileDescriptor is treated as a built-in type, but it's also in the framework.aidl.
+        // So aidl should ignore built-in types in framework.aidl to prevent duplication.
+        // (b/130899491)
+        if (is_preprocessed) {
+          continue;
+        }
+        // HasValidNameComponents handles name conflicts with built-in types
+      }
+
+      if (auto prev_definition = defined_types_.find(type->GetCanonicalName());
+          prev_definition != defined_types_.end()) {
+        // Skip duplicate type in preprocessed document
+        if (is_preprocessed) {
+          continue;
+        }
+        // Overwrite duplicate type which is already added via preprocessed with a new one
+        if (!prev_definition->second->GetDocument().IsPreprocessed()) {
+          AIDL_ERROR(type) << "redefinition: " << type->GetCanonicalName() << " is defined "
+                           << prev_definition->second->GetLocation();
+          return false;
+        }
+      }
+
+      if (!HasValidNameComponents(*type)) {
+        return false;
+      }
+
+      types_to_add.push_back(type.get());
+
+      // recursively check nested types
+      if (!collect_types_to_add(type->GetNestedTypes())) {
+        return false;
       }
     }
+    return true;
+  };
+
+  if (!collect_types_to_add(doc->DefinedTypes())) {
+    return false;
   }
-  return nullptr;
+
+  for (const auto& type : types_to_add) {
+    // populate global 'type' namespace with fully-qualified names
+    defined_types_.emplace(type->GetCanonicalName(), type);
+    // preprocessed unstructured parcelable types can be referenced without qualification
+    if (is_preprocessed && type->AsUnstructuredParcelable()) {
+      defined_types_.emplace(type->GetName(), type);
+    }
+  }
+
+  // transfer ownership of document
+  documents_.push_back(std::move(doc));
+  return true;
 }
 
 const AidlDocument& AidlTypenames::MainDocument() const {
@@ -147,18 +192,6 @@
   return *(documents_[0]);
 }
 
-bool AidlTypenames::AddPreprocessedType(unique_ptr<AidlDefinedType> type) {
-  const string name = type->GetCanonicalName();
-  if (preprocessed_types_.find(name) != preprocessed_types_.end()) {
-    return false;
-  }
-  if (!HasValidNameComponents(*type)) {
-    return false;
-  }
-  preprocessed_types_.insert(make_pair(name, std::move(type)));
-  return true;
-}
-
 bool AidlTypenames::IsBuiltinTypename(const string& type_name) {
   return kBuiltinTypes.find(type_name) != kBuiltinTypes.end() ||
       kJavaLikeTypeToAidlType.find(type_name) != kJavaLikeTypeToAidlType.end();
@@ -179,45 +212,23 @@
 }
 
 const AidlDefinedType* AidlTypenames::TryGetDefinedType(const string& type_name) const {
-  return TryGetDefinedTypeImpl(type_name).type;
-}
-
-AidlTypenames::DefinedImplResult AidlTypenames::TryGetDefinedTypeImpl(
-    const string& type_name) const {
-  // Do the exact match first.
   auto found_def = defined_types_.find(type_name);
   if (found_def != defined_types_.end()) {
-    return DefinedImplResult(found_def->second, false);
+    return found_def->second;
   }
-
-  auto found_prep = preprocessed_types_.find(type_name);
-  if (found_prep != preprocessed_types_.end()) {
-    return DefinedImplResult(found_prep->second.get(), true);
-  }
-
-  // Then match with the class name. Defined types has higher priority than
-  // types from the preprocessed file.
-  for (auto it = defined_types_.begin(); it != defined_types_.end(); it++) {
-    if (it->second->GetName() == type_name) {
-      return DefinedImplResult(it->second, false);
-    }
-  }
-
-  for (auto it = preprocessed_types_.begin(); it != preprocessed_types_.end(); it++) {
-    if (it->second->GetName() == type_name) {
-      return DefinedImplResult(it->second.get(), true);
-    }
-  }
-
-  return DefinedImplResult(nullptr, false);
+  return nullptr;
 }
 
-std::vector<AidlDefinedType*> AidlTypenames::AllDefinedTypes() const {
-  std::vector<AidlDefinedType*> res;
-  for (const auto& d : AllDocuments()) {
-    for (const auto& t : d->DefinedTypes()) {
-      res.push_back(t.get());
-    }
+std::vector<const AidlDefinedType*> AidlTypenames::AllDefinedTypes() const {
+  std::vector<const AidlDefinedType*> res;
+  for (const auto& doc : AllDocuments()) {
+    VisitTopDown(
+        [&](const AidlNode& node) {
+          if (auto defined_type = AidlCast<AidlDefinedType>(node); defined_type) {
+            res.push_back(defined_type);
+          }
+        },
+        *doc);
   }
   return res;
 }
@@ -238,6 +249,20 @@
   }
 }
 
+std::unique_ptr<AidlTypeSpecifier> AidlTypenames::MakeResolvedType(const AidlLocation& location,
+                                                                   const string& name,
+                                                                   bool is_array) const {
+  std::optional<ArrayType> array;
+  if (is_array) {
+    array = DynamicArray{};
+  }
+  std::unique_ptr<AidlTypeSpecifier> type(
+      new AidlTypeSpecifier(location, name, std::move(array), nullptr, {}));
+  AIDL_FATAL_IF(!type->Resolve(*this, nullptr), type) << "Can't make unknown type: " << name;
+  type->MarkVisited();
+  return type;
+}
+
 // Only immutable Parcelable, primitive type, and String, and List, Map, array of the types can be
 // immutable.
 bool AidlTypenames::CanBeJavaOnlyImmutable(const AidlTypeSpecifier& type) const {
@@ -266,10 +291,16 @@
   return t->IsJavaOnlyImmutable();
 }
 
-// Only FixedSize Parcelable, primitive types, and enum types can be FixedSize.
+// Followings can be FixedSize:
+// - @FixedSize parcelables
+// - primitive types and enum types
+// - fixed-size arrays of FixedSize types
 bool AidlTypenames::CanBeFixedSize(const AidlTypeSpecifier& type) const {
   const string& name = type.GetName();
-  if (type.IsGeneric() || type.IsArray()) {
+  if (type.IsGeneric() || type.IsNullable()) {
+    return false;
+  }
+  if (type.IsArray() && !type.IsFixedSizeArray()) {
     return false;
   }
   if (IsPrimitiveTypename(name)) {
@@ -363,9 +394,6 @@
   for (const auto& kv : defined_types_) {
     body(*kv.second);
   }
-  for (const auto& kv : preprocessed_types_) {
-    body(*kv.second);
-  }
 }
 
 bool AidlTypenames::Autofill() const {
diff --git a/aidl_typenames.h b/aidl_typenames.h
index f86f158..9ae851d 100644
--- a/aidl_typenames.h
+++ b/aidl_typenames.h
@@ -35,6 +35,7 @@
 class AidlDefinedType;
 class AidlEnumDeclaration;
 class AidlInterface;
+class AidlLocation;
 class AidlParcelable;
 class AidlTypeSpecifier;
 class AidlDocument;
@@ -58,15 +59,13 @@
  public:
   AidlTypenames() = default;
   bool AddDocument(std::unique_ptr<AidlDocument> doc);
-  const AidlDocument* GetDocumentFor(const AidlDefinedType* type) const;
   const std::vector<std::unique_ptr<AidlDocument>>& AllDocuments() const { return documents_; }
   const AidlDocument& MainDocument() const;
-  bool AddPreprocessedType(unique_ptr<AidlDefinedType> type);
   static bool IsBuiltinTypename(const string& type_name);
   static bool IsPrimitiveTypename(const string& type_name);
   bool IsParcelable(const string& type_name) const;
   const AidlDefinedType* TryGetDefinedType(const string& type_name) const;
-  std::vector<AidlDefinedType*> AllDefinedTypes() const;
+  std::vector<const AidlDefinedType*> AllDefinedTypes() const;
 
   struct ResolvedTypename {
     std::string canonical_name;
@@ -74,6 +73,8 @@
     const AidlDefinedType* defined_type;
   };
   ResolvedTypename ResolveTypename(const string& type_name) const;
+  std::unique_ptr<AidlTypeSpecifier> MakeResolvedType(const AidlLocation& location,
+                                                      const string& name, bool is_array) const;
   ArgumentAspect GetArgumentAspect(const AidlTypeSpecifier& type) const;
   bool CanBeJavaOnlyImmutable(const AidlTypeSpecifier& type) const;
   bool CanBeFixedSize(const AidlTypeSpecifier& type) const;
@@ -89,21 +90,13 @@
   // Returns the AidlParcelable of the given type, or nullptr if the type
   // is not an AidlParcelable;
   const AidlParcelable* GetParcelable(const AidlTypeSpecifier& type) const;
-  // Iterates over all defined and then preprocessed types
+  // Iterates over all defined types
   void IterateTypes(const std::function<void(const AidlDefinedType&)>& body) const;
   // Fixes AST after type/ref resolution before validation
   bool Autofill() const;
 
  private:
-  struct DefinedImplResult {
-    DefinedImplResult(const AidlDefinedType* type, const bool from_preprocessed)
-        : type(type), from_preprocessed(from_preprocessed) {}
-    const AidlDefinedType* type;
-    const bool from_preprocessed;
-  };
-  DefinedImplResult TryGetDefinedTypeImpl(const string& type_name) const;
   map<string, AidlDefinedType*> defined_types_;
-  map<string, unique_ptr<AidlDefinedType>> preprocessed_types_;
   std::vector<std::unique_ptr<AidlDocument>> documents_;
 };
 
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index f825cfd..5a975fe 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -25,26 +25,31 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <variant>
 #include <vector>
 
 #include "aidl_checkapi.h"
 #include "aidl_dumpapi.h"
 #include "aidl_language.h"
 #include "aidl_to_cpp.h"
+#include "aidl_to_cpp_common.h"
 #include "aidl_to_java.h"
 #include "aidl_to_ndk.h"
+#include "aidl_to_rust.h"
 #include "comments.h"
 #include "logging.h"
 #include "options.h"
+#include "parser.h"
+#include "preprocess.h"
 #include "tests/fake_io_delegate.h"
 
-using android::aidl::internals::parse_preprocessed_file;
 using android::aidl::test::FakeIoDelegate;
 using android::base::StringPrintf;
 using std::map;
 using std::set;
 using std::string;
 using std::unique_ptr;
+using std::variant;
 using std::vector;
 using testing::HasSubstr;
 using testing::TestParamInfo;
@@ -91,6 +96,7 @@
     io_delegate_.SetFileContents(path, contents);
     vector<string> args;
     args.emplace_back("aidl");
+    args.emplace_back("--min_sdk_version=current");
     args.emplace_back("--lang=" + to_string(lang));
     for (const string& s : additional_arguments) {
       args.emplace_back(s);
@@ -104,7 +110,7 @@
     args.emplace_back(path);
     Options options = Options::From(args);
     vector<string> imported_files;
-    ImportResolver import_resolver{io_delegate_, path, import_paths_, {}};
+    ImportResolver import_resolver{io_delegate_, path, import_paths_};
     AidlError actual_error = ::android::aidl::internals::load_and_validate_aidl(
         path, options, io_delegate_, &typenames_, &imported_files);
 
@@ -183,21 +189,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()));
@@ -257,6 +248,63 @@
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
+TEST_P(AidlTest, RejectRecursiveParcelable) {
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("Foo.aidl", "parcelable Foo { Foo foo; }", typenames_, GetLanguage()));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Foo is a recursive parcelable"));
+}
+
+TEST_P(AidlTest, RejectIndirectRecursiveParcelable) {
+  io_delegate_.SetFileContents("Bar.aidl", "parcelable Bar { Foo foo; }");
+  import_paths_.emplace("");
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("Foo.aidl", "parcelable Foo { Bar bar; }", typenames_, GetLanguage()));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Foo is a recursive parcelable"));
+}
+
+TEST_P(AidlTest, RejectRecursiveTypeEvenIfNullable) {
+  // Note: in native backends @nullable is mapped to non-heap wrapper like std::optional/Option<T>
+  io_delegate_.SetFileContents("Bar.aidl", "parcelable Bar { @nullable Foo foo; }");
+  import_paths_.emplace("");
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("Foo.aidl", "parcelable Foo { Bar bar; }", typenames_, GetLanguage()));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Foo is a recursive parcelable"));
+}
+
+TEST_P(AidlTest, OkayIfRecursionInvolvesHeapType) {
+  CaptureStderr();
+  std::string java_only_map_field;
+  if (GetLanguage() == Options::Language::JAVA) {
+    java_only_map_field = "  Map<String, Foo> map;\n";
+  }
+  EXPECT_NE(nullptr, Parse("Foo.aidl",
+                           "parcelable Foo {\n"
+                           "  List<Foo> list;\n" +
+                               java_only_map_field +
+                               "  Foo[] arr;\n"
+                               "  @nullable(heap=true) Foo heap_nullable;\n"
+                               "}\n",
+                           typenames_, GetLanguage()));
+  EXPECT_THAT(GetCapturedStderr(), "");
+}
+
+TEST_P(AidlTest, InterfaceCanReferenceItself) {
+  CaptureStderr();
+  EXPECT_NE(nullptr, Parse("IFoo.aidl", "interface IFoo { void foo(in IFoo self); }", typenames_,
+                           GetLanguage()));
+  EXPECT_THAT(GetCapturedStderr(), "");
+}
+
+TEST_P(AidlTest, HeapNullableCantApplyToOtherThanParcelables) {
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("Foo.aidl",
+                           "parcelable Foo {\n"
+                           "  @nullable(heap=true) String s;\n"
+                           "}",
+                           typenames_, GetLanguage()));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("@nullable(heap=true) is available to parcelables"));
+}
+
 TEST_P(AidlTest, RejectsDuplicatedArgumentNames) {
   const string method = "package a; interface IFoo { void f(int a, int a); }";
   const string expected_stderr =
@@ -316,20 +364,11 @@
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
 
-TEST_P(AidlTest, RejectUnsupportedParcelableAnnotations) {
-  AidlError error;
-  const string method = "package a; @nullable parcelable IFoo cpp_header \"IFoo.h\";";
-  CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, GetLanguage(), &error));
-  EXPECT_THAT(GetCapturedStderr(), HasSubstr("@nullable is not available."));
-  EXPECT_EQ(AidlError::BAD_TYPE, error);
-}
-
 TEST_P(AidlTest, RejectUnsupportedParcelableDefineAnnotations) {
   AidlError error;
-  const string method = "package a; @nullable parcelable IFoo { String a; String b; }";
+  const string method = "package a; @nullable parcelable Foo { String a; String b; }";
   CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", method, typenames_, GetLanguage(), &error));
+  EXPECT_EQ(nullptr, Parse("a/Foo.aidl", method, typenames_, GetLanguage(), &error));
   EXPECT_THAT(GetCapturedStderr(), HasSubstr("@nullable is not available."));
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
@@ -423,6 +462,28 @@
   ASSERT_TRUE(interface->IsVintfStability());
 }
 
+TEST_P(AidlTest, TypesShouldHaveVintfStabilityWhenCompilingWithTheVintfFlag) {
+  CaptureStderr();
+  string code =
+      "@VintfStability\n"
+      "parcelable Foo {\n"
+      "  interface INested {}"
+      "}";
+  EXPECT_NE(nullptr, Parse("Foo.aidl", code, typenames_, GetLanguage(), nullptr,
+                           {"--structured", "--stability", "vintf"}));
+  EXPECT_EQ(GetCapturedStderr(), "");
+  auto nested = typenames_.TryGetDefinedType("Foo.INested");
+  ASSERT_NE(nullptr, nested);
+  ASSERT_TRUE(nested->IsVintfStability());
+}
+
+TEST_P(AidlTest, VintfStabilityAppliesToNestedTypesAsWell) {
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("Foo.aidl", "parcelable Foo {}", typenames_, GetLanguage(), nullptr,
+                           {"--structured", "--stability", "vintf"}));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Foo does not have VINTF level stability"));
+}
+
 TEST_F(AidlTest, ParsesJavaOnlyStableParcelable) {
   Options java_options = Options::From("aidl -o out --structured a/Foo.aidl");
   Options cpp_options = Options::From("aidl --lang=cpp -o out -h out/include a/Foo.aidl");
@@ -433,25 +494,23 @@
       "a/Foo.aidl",
       StringPrintf("package a; @JavaOnlyStableParcelable parcelable Foo cpp_header \"Foo.h\" ;"));
 
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(cpp_options, io_delegate_));
-  const string expected_stderr =
-      "ERROR: a/Foo.aidl:1.48-52: Cannot declared parcelable in a --structured interface. "
-      "Parcelable must be defined in AIDL directly.\n";
-  CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(cpp_structured_options, io_delegate_));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+  EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(cpp_options, io_delegate_));
 
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(rust_options, io_delegate_));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+  EXPECT_FALSE(compile_aidl(cpp_structured_options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Cannot declare unstructured"));
+
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(rust_options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Cannot declare unstructured"));
 }
 
 TEST_F(AidlTest, ParcelableSupportJavaDeriveToString) {
   io_delegate_.SetFileContents("a/Foo.aidl", R"(package a;
     @JavaDerive(toString=true) parcelable Foo { int a; float b; })");
   Options java_options = Options::From("aidl --lang=java -o out a/Foo.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
 
   string java_out;
   EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/Foo.java", &java_out));
@@ -459,10 +518,10 @@
 
   // Other backends shouldn't be bothered
   Options cpp_options = Options::From("aidl --lang=cpp -o out -h out a/Foo.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(cpp_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(cpp_options, io_delegate_));
 
   Options ndk_options = Options::From("aidl --lang=ndk -o out -h out a/Foo.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(ndk_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(ndk_options, io_delegate_));
 }
 
 TEST_F(AidlTest, UnionSupportJavaDeriveToString) {
@@ -470,7 +529,7 @@
     @JavaDerive(toString=true) union Foo { int a; int[] b; })");
   CaptureStderr();
   Options java_options = Options::From("aidl --lang=java -o out a/Foo.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
   EXPECT_EQ("", GetCapturedStderr());
 
   const string expected_to_string_method = R"--(
@@ -494,7 +553,7 @@
     @JavaDerive(equals=true) parcelable Foo { int a; float b; })");
   CaptureStderr();
   Options java_options = Options::From("aidl --lang=java -o out a/Foo.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
   EXPECT_EQ("", GetCapturedStderr());
 
   const std::string expected = R"--(
@@ -525,7 +584,7 @@
     @JavaDerive(equals=true) union Foo { int a; int[] b; })");
   CaptureStderr();
   Options java_options = Options::From("aidl --lang=java -o out a/Foo.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
   EXPECT_EQ("", GetCapturedStderr());
 
   const std::string expected = R"--(
@@ -557,7 +616,7 @@
                                  "package a; @JavaDerive(blah=true) parcelable Foo{}");
     Options java_options = Options::From("aidl --lang=java -o out a/Foo.aidl");
     CaptureStderr();
-    EXPECT_NE(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
+    EXPECT_FALSE(compile_aidl(java_options, io_delegate_));
     const std::string expected_stderr =
         "ERROR: a/Foo.aidl:1.11-34: Parameter blah not supported for annotation JavaDerive.";
     EXPECT_THAT(GetCapturedStderr(),
@@ -568,7 +627,7 @@
     io_delegate_.SetFileContents("a/IFoo.aidl", "package a; @JavaDerive interface IFoo{}");
     Options java_options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
     CaptureStderr();
-    EXPECT_NE(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
+    EXPECT_FALSE(compile_aidl(java_options, io_delegate_));
     EXPECT_THAT(GetCapturedStderr(), HasSubstr("@JavaDerive is not available."));
   }
 
@@ -576,7 +635,7 @@
     io_delegate_.SetFileContents("a/IFoo.aidl", "package a; @JavaDerive enum IFoo { A=1, }");
     Options java_options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
     CaptureStderr();
-    EXPECT_NE(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
+    EXPECT_FALSE(compile_aidl(java_options, io_delegate_));
     EXPECT_THAT(GetCapturedStderr(), HasSubstr("@JavaDerive is not available."));
   }
 }
@@ -592,6 +651,18 @@
   ASSERT_EQ("IBar", interface->GetDescriptor());
 }
 
+TEST_P(AidlTest, UnknownAnnotation) {
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", "package a; @Unknown interface IFoo { }", typenames_,
+                           GetLanguage()));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("not a recognized annotation"));
+
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("a/IFoo.aidl", "package a; @Unknown(param=true) interface IFoo { }",
+                           typenames_, GetLanguage()));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("not a recognized annotation"));
+}
+
 TEST_P(AidlTest, AcceptsOnewayMethod) {
   const string oneway_method = "package a; interface IFoo { oneway void f(int a); }";
   EXPECT_NE(nullptr, Parse("a/IFoo.aidl", oneway_method, typenames_, GetLanguage()));
@@ -626,6 +697,28 @@
   ASSERT_TRUE(ret_type.IsHide());
 }
 
+TEST_P(AidlTest, AnnotationValueAttribute) {
+  const string content =
+      "package a; @Descriptor(\"descriptor_value\") interface IFoo { void f(int a); }";
+  const AidlDefinedType* defined = Parse("a/IFoo.aidl", content, typenames_, GetLanguage());
+  ASSERT_NE(nullptr, defined);
+  const AidlInterface* iface = defined->AsInterface();
+  ASSERT_NE(nullptr, iface);
+
+  ASSERT_EQ("descriptor_value", iface->GetDescriptor());
+}
+
+TEST_F(AidlTest, CheckApiForAnnotationValueAttribute) {
+  Options options = Options::From("aidl --checkapi=equal old new");
+
+  io_delegate_.SetFileContents("old/p/IFoo.aidl",
+                               "package p; @Descriptor(value=\"v1\") interface IFoo{ void foo();}");
+  io_delegate_.SetFileContents("new/p/IFoo.aidl",
+                               "package p; @Descriptor(\"v1\") interface IFoo{ void foo();}");
+
+  EXPECT_TRUE(::android::aidl::check_api(options, io_delegate_));
+}
+
 TEST_P(AidlTest, WritesComments) {
   string foo_interface =
       R"(package a;
@@ -672,11 +765,28 @@
   EXPECT_EQ((Comments{{"// get bar\n"}}), interface->GetMethods()[0]->GetComments());
 }
 
+TEST_F(AidlTest, RejectsIfCppHeaderIsMissing) {
+  io_delegate_.SetFileContents("Foo.aidl", "parcelable Foo;");
+  Options options = Options::From("aidl --lang cpp -h h -o o Foo.aidl");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("must have C++ header defined"));
+}
+
+TEST_F(AidlTest, RejectsIfTypeRefsCppHeaderIsMissing) {
+  io_delegate_.SetFileContents("Foo.aidl", "parcelable Foo;");
+  io_delegate_.SetFileContents("IBar.aidl", "interface IBar { void bar(in Foo foo); }");
+  Options options = Options::From("aidl -I . --lang cpp -h h -o o IBar.aidl");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("must have C++ header defined"));
+}
+
 TEST_F(AidlTest, ParsesPreprocessedFile) {
   string simple_content = "parcelable a.Foo;\ninterface b.IBar;";
   io_delegate_.SetFileContents("path", simple_content);
   EXPECT_FALSE(typenames_.ResolveTypename("a.Foo").is_resolved);
-  EXPECT_TRUE(parse_preprocessed_file(io_delegate_, "path", &typenames_));
+  EXPECT_TRUE(Parser::Parse("path", io_delegate_, typenames_, /*is_preprocessed=*/true));
   EXPECT_TRUE(typenames_.ResolveTypename("a.Foo").is_resolved);
   EXPECT_TRUE(typenames_.ResolveTypename("b.IBar").is_resolved);
 }
@@ -686,7 +796,7 @@
   io_delegate_.SetFileContents("path", simple_content);
 
   EXPECT_FALSE(typenames_.ResolveTypename("a.Foo").is_resolved);
-  EXPECT_TRUE(parse_preprocessed_file(io_delegate_, "path", &typenames_));
+  EXPECT_TRUE(Parser::Parse("path", io_delegate_, typenames_, /*is_preprocessed=*/true));
   EXPECT_TRUE(typenames_.ResolveTypename("a.Foo").is_resolved);
   EXPECT_TRUE(typenames_.ResolveTypename("b.IBar").is_resolved);
 }
@@ -705,8 +815,8 @@
   EXPECT_TRUE(typenames_.ResolveTypename("one.IBar").is_resolved);
   EXPECT_TRUE(typenames_.ResolveTypename("another.IBar").is_resolved);
   // But if we request just "IBar" we should get our imported one.
-  AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", false, nullptr, {});
-  ambiguous_type.Resolve(typenames_);
+  AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", /*array=*/std::nullopt, nullptr, {});
+  ambiguous_type.Resolve(typenames_, parse_result);
   EXPECT_EQ("one.IBar", ambiguous_type.GetName());
 }
 
@@ -727,8 +837,8 @@
   EXPECT_TRUE(typenames_.ResolveTypename("one.IBar").is_resolved);
   EXPECT_TRUE(typenames_.ResolveTypename("another.IBar").is_resolved);
   // But if we request just "IBar" we should get our imported one.
-  AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", false, nullptr, {});
-  ambiguous_type.Resolve(typenames_);
+  AidlTypeSpecifier ambiguous_type(AIDL_LOCATION_HERE, "IBar", /*array=*/std::nullopt, nullptr, {});
+  ambiguous_type.Resolve(typenames_, parse_result);
   EXPECT_EQ("one.IBar", ambiguous_type.GetName());
 }
 
@@ -738,18 +848,165 @@
   io_delegate_.SetFileContents("one/IBar.aidl", "package one; import p.Outer;"
                                                 "interface IBar {}");
 
-  vector<string> args {
-    "aidl",
-    "--preprocess",
-    "preprocessed",
-    "p/Outer.aidl",
-    "one/IBar.aidl"};
+  vector<string> args{"aidl", "--preprocess", "preprocessed",
+                      "-I.",  "p/Outer.aidl", "one/IBar.aidl"};
   Options options = Options::From(args);
-  EXPECT_TRUE(::android::aidl::preprocess_aidl(options, io_delegate_));
+  EXPECT_TRUE(::android::aidl::Preprocess(options, io_delegate_));
 
-  string output;
-  EXPECT_TRUE(io_delegate_.GetWrittenContents("preprocessed", &output));
-  EXPECT_EQ("parcelable p.Outer.Inner;\ninterface one.IBar;\n", output);
+  std::map<std::string, std::string> expected = {{"preprocessed",
+                                                  "parcelable p.Outer.Inner;\n"
+                                                  "interface one.IBar {\n"
+                                                  "}\n"}};
+  EXPECT_THAT(io_delegate_.OutputFiles(), testing::Eq(expected));
+}
+
+TEST_F(AidlTest, PreprocessVariousThings) {
+  io_delegate_.SetFileContents("foo/bar/IFoo.aidl",
+                               "package foo.bar;\n"
+                               "interface IFoo {\n"
+                               "    int foo();\n"
+                               "    const int FOO = foo.bar.Bar.BAR + 1; // should be 44\n"
+                               "}\n");
+  io_delegate_.SetFileContents("foo/bar/Bar.aidl",
+                               "package foo.bar;\n"
+                               "parcelable Bar {\n"
+                               "    const int BAR = imported.Foo.FOO + 1; // should be 43\n"
+                               "    imported.Foo foo;\n"
+                               "}\n");
+  io_delegate_.SetFileContents("foo/bar/Gen.aidl",
+                               "package foo.bar;\n"
+                               "parcelable Gen<T> {\n"
+                               "}\n");
+  io_delegate_.SetFileContents("foo/bar/Enum.aidl",
+                               "package foo.bar;\n"
+                               "enum Enum {\n"
+                               "    FOO = 3, BAR = FOO + 3, // should be 3, 6\n"
+                               "}\n");
+  io_delegate_.SetFileContents("sub/imported/Foo.aidl",
+                               "package imported;\n"
+                               "parcelable Foo {\n"
+                               "    const int FOO = 42;\n"
+                               "}\n");
+
+  vector<string> args = {
+      "aidl",
+      "--preprocess",
+      "preprocessed",
+      "-Isub",
+      "-I.",
+      "foo/bar/IFoo.aidl",
+      "foo/bar/Bar.aidl",
+      "foo/bar/Gen.aidl",
+      "foo/bar/Enum.aidl",
+  };
+  ASSERT_TRUE(Preprocess(Options::From(args), io_delegate_));
+  std::string preprocessed =
+      "interface foo.bar.IFoo {\n"
+      "  const int FOO = 44;\n"
+      "}\n"
+      "parcelable foo.bar.Bar {\n"
+      "  const int BAR = 43;\n"
+      "}\n"
+      "parcelable foo.bar.Gen<T> {\n"
+      "}\n"
+      "enum foo.bar.Enum {\n"
+      "  FOO = 3,\n"
+      "  BAR = 6,\n"
+      "}\n";
+  std::map<std::string, std::string> expected = {{"preprocessed", preprocessed}};
+  EXPECT_THAT(io_delegate_.OutputFiles(), testing::Eq(expected));
+
+  // use preprocessed
+  io_delegate_.SetFileContents("a/Foo.aidl",
+                               "package a; parcelable Foo { const int y = foo.bar.Bar.BAR; }");
+  io_delegate_.SetFileContents("preprocessed", preprocessed);
+  CaptureStderr();
+  auto options = Options::From("aidl --lang java -o out a/Foo.aidl -ppreprocessed");
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+  EXPECT_EQ("", GetCapturedStderr());
+  string code;
+  EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/Foo.java", &code));
+  EXPECT_THAT(code, testing::HasSubstr("public static final int y = 43;"));
+}
+
+TEST_F(AidlTest, AllowMultipleUnstructuredNestedParcelablesInASingleDocument) {
+  io_delegate_.SetFileContents("p/IFoo.aidl",
+                               "package p;\n"
+                               "import x.Outer;\n"
+                               "interface IFoo {\n"
+                               "  void foo(in Outer.Inner1 in1, in Outer.Inner2 in2);\n"
+                               "}");
+  io_delegate_.SetFileContents("imported/x/Outer.aidl",
+                               "package x;\n"
+                               "parcelable Outer.Inner1;\n"
+                               "parcelable Outer.Inner2;\n");
+  auto opt = Options::From("aidl -Iimported --lang=java p/IFoo.aidl");
+  CaptureStderr();
+  EXPECT_TRUE(compile_aidl(opt, io_delegate_));
+  EXPECT_EQ("", GetCapturedStderr());
+}
+
+TEST_F(AidlTest,
+       StubsSourceIsGeneratedFromDuplicateDefinitionWithFrameworkAidl_FrameworkAidlLater) {
+  // Main doc(Foo.aidl) is loaded
+  // And then framework.aidl is loaded as preprocessed. (conflict)
+  io_delegate_.SetFileContents("sdk/framework.aidl", "parcelable x.Foo.Inner;\n");
+  io_delegate_.SetFileContents("x/Foo.aidl",
+                               "package x;\n"
+                               "parcelable Foo.Inner;\n");
+  auto opt = Options::From("aidl -psdk/framework.aidl -I. x/Foo.aidl");
+  CaptureStderr();
+  EXPECT_TRUE(compile_aidl(opt, io_delegate_));
+  EXPECT_EQ("", GetCapturedStderr());
+}
+
+TEST_F(AidlTest,
+       StubsSourceIsGeneratedFromDuplicateDefinitionWithFrameworkAidl_FrameworkAidlFirst) {
+  // Main doc(IBar.aidl) is loaded first.
+  // Framework.aidl is loaded as preprocessed.
+  // And then import(Foo.aidl) is loaded. (conflict)
+  io_delegate_.SetFileContents("sdk/framework.aidl", "parcelable x.Foo.Inner;\n");
+  io_delegate_.SetFileContents("x/IBar.aidl",
+                               "package x;\n"
+                               "import x.Foo;\n"
+                               "interface IBar {\n"
+                               "  void bar(in Foo.Inner inner);\n"
+                               "}");
+  io_delegate_.SetFileContents("x/Foo.aidl",
+                               "package x;\n"
+                               "parcelable Foo.Inner;\n");
+  auto opt = Options::From("aidl -psdk/framework.aidl -I. x/IBar.aidl");
+  CaptureStderr();
+  EXPECT_TRUE(compile_aidl(opt, io_delegate_));
+  EXPECT_EQ("", GetCapturedStderr());
+}
+
+TEST_F(AidlTest, PreprocessedFileCantDeclarePackage) {
+  string simple_content = "package xxx; parcelable a.Foo;";
+  io_delegate_.SetFileContents("path", simple_content);
+  CaptureStderr();
+  EXPECT_FALSE(Parser::Parse("path", io_delegate_, typenames_, /*is_preprocessed=*/true));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Preprocessed file can't declare package."));
+}
+
+TEST_F(AidlTest, RejectQualifiedTypeNameUnlessPreprocessed) {
+  string simple_content = "parcelable a.Foo {}";
+  io_delegate_.SetFileContents("path", simple_content);
+  CaptureStderr();
+  EXPECT_FALSE(Parser::Parse("path", io_delegate_, typenames_, /*is_preprocessed=*/false));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Type name can't be qualified"));
+}
+
+TEST_P(AidlTest, PreprocessedCanDeclareJavaStyleBuiltinTypes) {
+  string contents = R"(
+    interface android.os.IBinder;
+    interface android.os.IInterface;
+    parcelable android.os.ParcelFileDescriptor;
+  )";
+  io_delegate_.SetFileContents("path", contents);
+  CaptureStderr();
+  EXPECT_TRUE(Parser::Parse("path", io_delegate_, typenames_, /*is_preprocessed=*/true));
+  EXPECT_THAT(GetCapturedStderr(), "");
 }
 
 TEST_P(AidlTest, SupportDeprecated) {
@@ -764,7 +1021,7 @@
 
     auto options = Options::From("aidl --lang=" + to_string(GetLanguage()) + " " + filename +
                                  " --out=out --header_out=out");
-    EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+    EXPECT_TRUE(compile_aidl(options, io_delegate_));
     for (const auto& [lang, test_case] : expectations) {
       if (lang != GetLanguage()) continue;
       string output;
@@ -896,8 +1153,7 @@
                       {Options::Language::JAVA, {"out/Foo.java", "@Deprecated"}},
                       {Options::Language::CPP, {"out/Foo.h", "__attribute__((deprecated"}},
                       {Options::Language::NDK, {"out/aidl/Foo.h", "__attribute__((deprecated"}},
-                      // TODO(b/177860423) support "deprecated" in Rust enum
-                      // {Options::Language::RUST, {"out/Foo.rs", "#[deprecated"}},
+                      {Options::Language::RUST, {"out/Foo.rs", "#[deprecated"}},
                   });
 }
 
@@ -914,17 +1170,23 @@
 }
 
 TEST_P(AidlTest, ParseCompoundParcelableFromPreprocess) {
-  io_delegate_.SetFileContents("preprocessed",
-                               "parcelable p.Outer.Inner;");
+  io_delegate_.SetFileContents("preprocessed", "parcelable p.Outer.Inner cpp_header \"inner.h\";");
   preprocessed_files_.push_back("preprocessed");
   auto parse_result = Parse("p/IFoo.aidl", "package p; interface IFoo { void f(in Inner c); }",
                             typenames_, GetLanguage());
-  // TODO(wiley): This should actually return nullptr because we require
-  //              the outer class name.  However, for legacy reasons,
-  //              this behavior must be maintained.  b/17415692
+  // Require legacy behavior - inner class name can be used without outer class name.
   EXPECT_NE(nullptr, parse_result);
 }
 
+TEST_F(AidlTest, ApiMappingAcceptsUnstructuredParcelables) {
+  io_delegate_.SetFileContents("p/Foo.aidl", "package p; parcelable Foo;");
+
+  Options options1 = Options::From("aidl --apimapping mapping.txt p/Foo.aidl");
+  CaptureStderr();
+  EXPECT_EQ(0, aidl_entry(options1, io_delegate_));
+  EXPECT_EQ("", GetCapturedStderr());
+}
+
 TEST_F(AidlTest, FailOnParcelable) {
   const string expected_foo_stderr =
       "ERROR: p/IFoo.aidl:1.22-27: Refusing to generate code with unstructured parcelables. "
@@ -935,13 +1197,13 @@
   // By default, we shouldn't fail on parcelable.
   Options options1 = Options::From("aidl p/IFoo.aidl");
   CaptureStderr();
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options1, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options1, io_delegate_));
   EXPECT_EQ("", GetCapturedStderr());
 
   // -b considers this an error
   Options options2 = Options::From("aidl -b p/IFoo.aidl");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options2, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options2, io_delegate_));
   EXPECT_EQ(expected_foo_stderr, GetCapturedStderr());
 
   const string expected_bar_stderr =
@@ -953,19 +1215,31 @@
   // With '-b' option, a parcelable and an interface should fail.
   Options options3 = Options::From("aidl p/IBar.aidl");
   CaptureStderr();
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options3, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options3, io_delegate_));
   EXPECT_EQ("", GetCapturedStderr());
   Options options4 = Options::From("aidl -b p/IBar.aidl");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options4, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options4, io_delegate_));
   EXPECT_EQ(expected_bar_stderr, GetCapturedStderr());
 }
 
+TEST_P(AidlTest, ImportingJavaStyleBuiltinTypesIsAllowed) {
+  string contents = R"(
+    import android.os.IBinder;
+    import android.os.IInterface;
+    interface IFoo {
+      void foo(in IBinder b);
+    }
+  )";
+  EXPECT_NE(nullptr, Parse("IFoo.aidl", contents, typenames_, GetLanguage()));
+}
+
 TEST_P(AidlTest, StructuredFailOnUnstructuredParcelable) {
   const string expected_stderr =
-      "ERROR: ./o/WhoKnowsWhat.aidl:1.22-35: o.WhoKnowsWhat is not structured, but this is a "
+      "ERROR: o/WhoKnowsWhat.aidl:1.22-35: o.WhoKnowsWhat is not structured, but this is a "
       "structured interface.\n";
-  io_delegate_.SetFileContents("o/WhoKnowsWhat.aidl", "package o; parcelable WhoKnowsWhat;");
+  io_delegate_.SetFileContents("o/WhoKnowsWhat.aidl",
+                               "package o; parcelable WhoKnowsWhat cpp_header \"who_knows.h\";");
   import_paths_.emplace("");
   AidlError error;
   CaptureStderr();
@@ -995,10 +1269,46 @@
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
 
+TEST_P(AidlTest, InvalidConstString) {
+  AidlError error;
+  const string expected_stderr =
+      "ERROR: p/IFoo.aidl:3.47-60: Found invalid character '\\' at index 4 in string constant "
+      "'\"test\\\"test\"'\n";
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
+                           R"(package p;
+                      interface IFoo {
+                        const String someVar = "test\"test";
+                      }
+                   )",
+                           typenames_, GetLanguage(), &error));
+  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+  EXPECT_EQ(AidlError::BAD_TYPE, error);
+}
+
+TEST_P(AidlTest, RejectUnstructuredParcelablesInNDKandRust) {
+  io_delegate_.SetFileContents("o/Foo.aidl", "package o; parcelable Foo cpp_header \"cpp/Foo.h\";");
+  const auto options =
+      Options::From("aidl --lang=" + to_string(GetLanguage()) + " -o out -h out -I. o/Foo.aidl");
+  const bool reject_unstructured_parcelables =
+      GetLanguage() == Options::Language::NDK || GetLanguage() == Options::Language::RUST;
+  const string expected_err = reject_unstructured_parcelables
+                                  ? "Refusing to generate code with unstructured parcelables"
+                                  : "";
+  CaptureStderr();
+  EXPECT_EQ(compile_aidl(options, io_delegate_), !reject_unstructured_parcelables);
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr(expected_err));
+}
+
+TEST_F(AidlTest, CosntantValueType) {
+  unique_ptr<AidlConstantValue> num{AidlConstantValue::Integral(AIDL_LOCATION_HERE, "1")};
+  EXPECT_EQ(num->GetType(), AidlConstantValue::Type::INT8);
+}
+
 TEST_P(AidlTest, FailOnTooBigConstant) {
   AidlError error;
   const string expected_stderr =
-      "ERROR: p/IFoo.aidl:3.48-52: Invalid type specifier for an int32 literal: byte\n";
+      "ERROR: p/IFoo.aidl:3.48-52: Invalid type specifier for an int32 literal: byte (256)\n";
   CaptureStderr();
   EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
                            R"(package p;
@@ -1015,7 +1325,7 @@
   io_delegate_.SetFileContents("a/Foo.aidl", "package a; parcelable Foo { const int y = true; }");
   CaptureStderr();
   auto options = Options::From("aidl --lang java -o out a/Foo.aidl");
-  EXPECT_EQ(0, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   EXPECT_EQ("", GetCapturedStderr());
   string code;
   EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/Foo.java", &code));
@@ -1045,11 +1355,11 @@
 }
 
 TEST_F(AidlTest, AidlConstantCharacterDefault) {
-  AidlTypeSpecifier char_type(AIDL_LOCATION_HERE, "char", false, nullptr, {});
-  auto default_value = unique_ptr<AidlConstantValue>(AidlConstantValue::Default(char_type));
-  EXPECT_EQ("'\\0'", default_value->ValueString(char_type, cpp::ConstantValueDecorator));
-  EXPECT_EQ("'\\0'", default_value->ValueString(char_type, ndk::ConstantValueDecorator));
-  EXPECT_EQ("'\\0'", default_value->ValueString(char_type, java::ConstantValueDecorator));
+  auto char_type = typenames_.MakeResolvedType(AIDL_LOCATION_HERE, "char", false);
+  auto default_value = unique_ptr<AidlConstantValue>(AidlConstantValue::Default(*char_type));
+  EXPECT_EQ("'\\0'", default_value->ValueString(*char_type, cpp::ConstantValueDecorator));
+  EXPECT_EQ("'\\0'", default_value->ValueString(*char_type, ndk::ConstantValueDecorator));
+  EXPECT_EQ("'\\0'", default_value->ValueString(*char_type, java::ConstantValueDecorator));
 }
 
 TEST_P(AidlTest, FailOnManyDefinedTypes) {
@@ -1171,10 +1481,47 @@
   EXPECT_EQ("-1", cpp_constants[0]->ValueString(cpp::ConstantValueDecorator));
 }
 
-TEST_P(AidlTest, UnderstandsNestedParcelables) {
-  io_delegate_.SetFileContents(
-      "p/Outer.aidl",
-      "package p; parcelable Outer.Inner cpp_header \"baz/header\";");
+TEST_F(AidlTest, ByteAndByteArrayDifferInCpp) {
+  auto type = Parse("p/Foo.aidl",
+                    R"(
+                      package p;
+                      parcelable Foo {
+                        byte a = -1;
+                        byte[] b = {-1, 1};
+                        @nullable byte[] c = {-1, 1};
+                      }
+                    )",
+                    typenames_, Options::Language::CPP);
+  ASSERT_NE(nullptr, type);
+  auto& fields = type->GetFields();
+  ASSERT_EQ(3ul, fields.size());
+  EXPECT_EQ("-1", fields[0]->ValueString(cpp::ConstantValueDecorator));
+  EXPECT_EQ("{uint8_t(-1), 1}", fields[1]->ValueString(cpp::ConstantValueDecorator));
+  EXPECT_EQ("{{uint8_t(-1), 1}}", fields[2]->ValueString(cpp::ConstantValueDecorator));
+}
+
+TEST_F(AidlTest, ByteAndByteArrayDifferInNdk) {
+  auto type = Parse("p/Foo.aidl",
+                    R"(
+                      package p;
+                      parcelable Foo {
+                        byte a = -1;
+                        byte[] b = {-1, 1};
+                        @nullable byte[] c = {-1, 1};
+                      }
+                    )",
+                    typenames_, Options::Language::NDK);
+  ASSERT_NE(nullptr, type);
+  auto& fields = type->GetFields();
+  ASSERT_EQ(3ul, fields.size());
+  EXPECT_EQ("-1", fields[0]->ValueString(ndk::ConstantValueDecorator));
+  EXPECT_EQ("{uint8_t(-1), 1}", fields[1]->ValueString(ndk::ConstantValueDecorator));
+  EXPECT_EQ("{{uint8_t(-1), 1}}", fields[2]->ValueString(ndk::ConstantValueDecorator));
+}
+
+TEST_P(AidlTest, UnderstandsNestedUnstructuredParcelables) {
+  io_delegate_.SetFileContents("p/Outer.aidl",
+                               "package p; parcelable Outer.Inner cpp_header \"baz/header\";");
   import_paths_.emplace("");
   const string input_path = "p/IFoo.aidl";
   const string input = "package p; import p.Outer; interface IFoo"
@@ -1185,10 +1532,482 @@
 
   EXPECT_TRUE(typenames_.ResolveTypename("p.Outer.Inner").is_resolved);
   // C++ uses "::" instead of "." to refer to a inner class.
-  AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.Outer.Inner", false, nullptr, {});
+  AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.Outer.Inner", /*array=*/std::nullopt,
+                                nullptr, {});
   EXPECT_EQ("::p::Outer::Inner", cpp::CppNameOf(nested_type, typenames_));
 }
 
+TEST_P(AidlTest, UnderstandsNestedUnstructuredParcelablesWithoutImports) {
+  io_delegate_.SetFileContents("p/Outer.aidl",
+                               "package p; parcelable Outer.Inner cpp_header \"baz/header\";");
+  import_paths_.emplace("");
+  const string input_path = "p/IFoo.aidl";
+  const string input = "package p; interface IFoo { p.Outer.Inner get(); }";
+
+  auto parse_result = Parse(input_path, input, typenames_, GetLanguage());
+  EXPECT_NE(nullptr, parse_result);
+
+  EXPECT_TRUE(typenames_.ResolveTypename("p.Outer.Inner").is_resolved);
+  // C++ uses "::" instead of "." to refer to a inner class.
+  AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.Outer.Inner", /*array=*/std::nullopt,
+                                nullptr, {});
+  EXPECT_EQ("::p::Outer::Inner", cpp::CppNameOf(nested_type, typenames_));
+}
+
+TEST_F(AidlTest, UnderstandsNestedTypes) {
+  io_delegate_.SetFileContents("p/IOuter.aidl",
+                               "package p;\n"
+                               "interface IOuter {\n"
+                               "  parcelable Inner {}\n"
+                               "}");
+  import_paths_.emplace("");
+  const string input_path = "p/IFoo.aidl";
+  const string input =
+      "package p;\n"
+      "import p.IOuter;\n"
+      "interface IFoo {\n"
+      "  IOuter.Inner get();\n"
+      "}";
+  CaptureStderr();
+  EXPECT_NE(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
+  EXPECT_EQ(GetCapturedStderr(), "");
+
+  EXPECT_TRUE(typenames_.ResolveTypename("p.IOuter.Inner").is_resolved);
+  // C++ uses "::" instead of "." to refer to a inner class.
+  AidlTypeSpecifier nested_type(AIDL_LOCATION_HERE, "p.IOuter.Inner", /*array=*/std::nullopt,
+                                nullptr, {});
+  EXPECT_EQ("::p::IOuter::Inner", cpp::CppNameOf(nested_type, typenames_));
+}
+
+TEST_F(AidlTest, DefinedTypeKnowsItsParentScope) {
+  const string input_path = "p/IFoo.aidl";
+  const string input =
+      "package p;\n"
+      "interface IFoo {\n"
+      "  parcelable Inner {\n"
+      "    enum Enum { A }\n"
+      "  }\n"
+      "}";
+  CaptureStderr();
+  EXPECT_NE(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
+  EXPECT_EQ(GetCapturedStderr(), "");
+
+  auto enum_type = typenames_.ResolveTypename("p.IFoo.Inner.Enum");
+  auto inner_type = typenames_.ResolveTypename("p.IFoo.Inner");
+  auto ifoo_type = typenames_.ResolveTypename("p.IFoo");
+  EXPECT_TRUE(enum_type.is_resolved);
+  EXPECT_TRUE(inner_type.is_resolved);
+  EXPECT_TRUE(ifoo_type.is_resolved);
+  // GetParentType()
+  EXPECT_EQ(inner_type.defined_type, enum_type.defined_type->GetParentType());
+  EXPECT_EQ(ifoo_type.defined_type, inner_type.defined_type->GetParentType());
+  EXPECT_EQ(nullptr, ifoo_type.defined_type->GetParentType());
+  // GetRootType()
+  EXPECT_EQ(ifoo_type.defined_type, enum_type.defined_type->GetRootType());
+  EXPECT_EQ(ifoo_type.defined_type, inner_type.defined_type->GetRootType());
+  EXPECT_EQ(ifoo_type.defined_type, ifoo_type.defined_type->GetRootType());
+  // GetDocument()
+  auto main_document = &typenames_.MainDocument();
+  EXPECT_EQ(main_document, &enum_type.defined_type->GetDocument());
+  EXPECT_EQ(main_document, &inner_type.defined_type->GetDocument());
+  EXPECT_EQ(main_document, &ifoo_type.defined_type->GetDocument());
+}
+
+TEST_F(AidlTest, UnderstandsNestedTypesViaFullyQualifiedName) {
+  io_delegate_.SetFileContents("p/IOuter.aidl",
+                               "package p;\n"
+                               "interface IOuter {\n"
+                               "  parcelable Inner {}\n"
+                               "}");
+  import_paths_.emplace("");
+  const string input_path = "p/IFoo.aidl";
+  const string input =
+      "package p;\n"
+      "interface IFoo {\n"
+      "  p.IOuter.Inner get();\n"
+      "}";
+  CaptureStderr();
+  EXPECT_NE(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
+  EXPECT_EQ(GetCapturedStderr(), "");
+
+  EXPECT_TRUE(typenames_.ResolveTypename("p.IOuter.Inner").is_resolved);
+}
+
+TEST_F(AidlTest, IncludeParentsRawHeaderForNestedInterface) {
+  CaptureStderr();
+  EXPECT_NE(nullptr, Parse("p/Outer.aidl",
+                           "package p;\n"
+                           "parcelable Outer {\n"
+                           "  interface IInner {}\n"
+                           "}",
+                           typenames_, Options::Language::CPP));
+
+  EXPECT_EQ(GetCapturedStderr(), "");
+  auto resolved = typenames_.ResolveTypename("p.Outer.IInner");
+  ASSERT_TRUE(resolved.defined_type);
+  EXPECT_EQ(cpp::HeaderFile(*resolved.defined_type, cpp::ClassNames::CLIENT), "p/Outer.h");
+}
+
+TEST_F(AidlTest, UnderstandsNestedTypesViaFullyQualifiedImport) {
+  io_delegate_.SetFileContents("p/IOuter.aidl",
+                               "package p;\n"
+                               "interface IOuter {\n"
+                               "  parcelable Inner {}\n"
+                               "}");
+  import_paths_.emplace("");
+  const string input_path = "p/IFoo.aidl";
+  const string input =
+      "package p;\n"
+      "import p.IOuter.Inner;"
+      "interface IFoo {\n"
+      "  Inner get();\n"
+      "}";
+  CaptureStderr();
+  EXPECT_NE(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
+  EXPECT_EQ(GetCapturedStderr(), "");
+
+  EXPECT_TRUE(typenames_.ResolveTypename("p.IOuter.Inner").is_resolved);
+}
+
+TEST_F(AidlTest, UnderstandsNestedTypesInTheSameScope) {
+  const string input_path = "p/IFoo.aidl";
+  const string input =
+      "package p;\n"
+      "interface IFoo {\n"
+      "  parcelable Result {}\n"
+      "  Result get();\n"
+      "}";
+  CaptureStderr();
+  EXPECT_NE(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
+  EXPECT_EQ(GetCapturedStderr(), "");
+
+  EXPECT_TRUE(typenames_.ResolveTypename("p.IFoo.Result").is_resolved);
+}
+
+// Finding the type of nested named member.
+struct TypeFinder : AidlVisitor {
+  string name;
+  const AidlTypeSpecifier* type = nullptr;
+  TypeFinder(std::string name) : name(name) {}
+  void Visit(const AidlVariableDeclaration& v) override {
+    if (v.GetName() == name) {
+      type = &v.GetType();
+    }
+  }
+  void Visit(const AidlMethod& m) override {
+    if (m.GetName() == name) {
+      type = &m.GetType();
+    }
+  }
+  static string Get(const AidlDefinedType& type, const string& name) {
+    TypeFinder v(name);
+    VisitTopDown(v, type);
+    return v.type ? v.type->Signature() : "(null)";
+  };
+};
+
+TEST_F(AidlTest, UnderstandsNestedTypesViaQualifiedInTheSameScope) {
+  io_delegate_.SetFileContents("q/IBar.aidl",
+                               "package q;\n"
+                               "interface IBar {\n"
+                               "  parcelable Baz {}\n"
+                               "}");
+  import_paths_.emplace("");
+  const string input_path = "p/IFoo.aidl";
+  const string input =
+      "package p;\n"
+      "import q.IBar;\n"
+      "interface IFoo {\n"
+      "  parcelable Nested {\n"
+      "    Baz t1;\n"
+      "  }\n"
+      "  parcelable Baz { }\n"
+      "  IBar.Baz t2();\n"
+      "  Baz t3();\n"
+      "}";
+  CaptureStderr();
+  auto foo = Parse(input_path, input, typenames_, Options::Language::CPP);
+  EXPECT_EQ(GetCapturedStderr(), "");
+  ASSERT_NE(nullptr, foo);
+
+  EXPECT_EQ(TypeFinder::Get(*foo, "t1"), "p.IFoo.Baz");
+  EXPECT_EQ(TypeFinder::Get(*foo, "t2"), "q.IBar.Baz");
+  EXPECT_EQ(TypeFinder::Get(*foo, "t3"), "p.IFoo.Baz");
+}
+
+TEST_F(AidlTest, NestedTypeResolutionWithNoPackage) {
+  const string input_path = "Foo.aidl";
+  const string input =
+      "parcelable Foo {\n"
+      "  parcelable Bar {\n"
+      "    enum Baz { BAZ }\n"
+      "    Baz baz = Baz.BAZ;\n"
+      "  }\n"
+      "  Bar bar;\n"
+      "}";
+  CaptureStderr();
+  auto foo = Parse(input_path, input, typenames_, Options::Language::CPP);
+  EXPECT_EQ(GetCapturedStderr(), "");
+  ASSERT_NE(nullptr, foo);
+
+  EXPECT_EQ(TypeFinder::Get(*foo, "bar"), "Foo.Bar");
+  EXPECT_EQ(TypeFinder::Get(*foo, "baz"), "Foo.Bar.Baz");
+}
+
+TEST_F(AidlTest, RejectsNestedTypesWithParentsName) {
+  const string input_path = "p/Foo.aidl";
+  const string input =
+      "package p;\n"
+      "parcelable Foo {\n"
+      "  parcelable Foo {}\n"
+      "}";
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Nested type 'Foo' has the same name as its parent."));
+}
+
+TEST_F(AidlTest, RejectUnstructuredParcelableAsNestedTypes) {
+  const string input_path = "p/IFoo.aidl";
+  const string input =
+      "package p;\n"
+      "interface IFoo {\n"
+      "  parcelable Bar cpp_header \"Bar.h\";\n"
+      "}";
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
+  EXPECT_THAT(GetCapturedStderr(),
+              HasSubstr("Unstructured parcelables should be at the root scope"));
+}
+
+TEST_F(AidlTest, RejectGenericTypeWithNestedTypes) {
+  const string input_path = "p/Foo.aidl";
+  const string input =
+      "package p;\n"
+      "parcelable Foo<T> {\n"
+      "  parcelable Bar {}\n"
+      "}";
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Generic types can't have nested types."));
+}
+
+TEST_F(AidlTest, HandleSyntaxErrorsInNestedDecl) {
+  const string input_path = "p/IFoo.aidl";
+  const string input =
+      "package p;\n"
+      "interface IFoo {\n"
+      "  parcelable;\n"  // missing identifier
+      "}";
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("expecting identifier"));
+}
+
+TEST_F(AidlTest, RejectsNestedTypesWithDuplicateNames) {
+  const string input_path = "p/Foo.aidl";
+  const string input =
+      "package p;\n"
+      "interface Foo {\n"
+      "  parcelable Bar {}\n"
+      "  parcelable Bar {}\n"
+      "}";
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse(input_path, input, typenames_, Options::Language::CPP));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Redefinition of 'Bar'"));
+}
+
+TEST_F(AidlTest, TypeResolutionWithMultipleLevelsOfNesting) {
+  struct Failure {
+    string err;
+  };
+  struct TestCase {
+    string type;
+    variant<string, Failure> expected;  // success<0> or failure<1>
+  };
+  vector<TestCase> cases = {
+      {"foo.A", "foo.A"},
+      {"foo.A.B", "foo.A.B"},
+      {"@nullable(heap=true) A", "foo.A.B.A"},
+      // In the scope of foo.A.B.A, B is resolved to A.B.A.B first.
+      {"B.A", Failure{"Failed to resolve 'B.A'"}},
+      {"B", "foo.A.B.A.B"},
+      {"A.B", "foo.A.B.A.B"},
+  };
+  const string input_path = "foo/A.aidl";
+  for (auto& [type, expected] : cases) {
+    AidlTypenames typenames;
+    // clang-format off
+    const string input =
+        "package foo;\n"
+        "parcelable A {\n"
+        "  parcelable B {\n"
+        "    parcelable A {\n"
+        "      parcelable B {\n"
+        "      }\n"
+        "      " + type + " m;\n"
+        "    }\n"
+        "  }\n"
+        "}";
+    // clang-format on
+    CaptureStderr();
+    auto foo = Parse(input_path, input, typenames, Options::Language::CPP);
+    if (auto failure = std::get_if<Failure>(&expected); failure) {
+      ASSERT_EQ(nullptr, foo);
+      EXPECT_THAT(GetCapturedStderr(), HasSubstr(failure->err));
+    } else {
+      EXPECT_EQ(GetCapturedStderr(), "");
+      ASSERT_NE(nullptr, foo);
+      EXPECT_EQ(TypeFinder::Get(*foo, "m"), std::get<string>(expected));
+    }
+  }
+}
+
+TEST_F(AidlTest, HeaderForNestedTypeShouldPointToTopMostParent) {
+  const string input_path = "p/IFoo.aidl";
+  const string input =
+      "package p;\n"
+      "interface IFoo {\n"
+      "  parcelable Result {}\n"
+      "}";
+  CaptureStderr();
+  auto foo = Parse(input_path, input, typenames_, Options::Language::CPP);
+  ASSERT_NE(nullptr, foo);
+  EXPECT_EQ(GetCapturedStderr(), "");
+
+  auto result = typenames_.ResolveTypename("p.IFoo.Result").defined_type;
+  ASSERT_NE(nullptr, result);
+  EXPECT_EQ("p/IFoo.h", cpp::CppHeaderForType(*result));
+}
+
+TEST_F(AidlTest, ReorderNestedTypesForCppOutput) {
+  const string input_path = "p/IFoo.aidl";
+  const string input = R"(
+    package p;
+    interface IFoo {
+      // partial orderings for [A, D, G]:
+      //   D - A
+      //   A - G
+      parcelable A {
+        // partial orderings for [B, C]:
+        //   C - B
+        parcelable B {
+          C c;
+          D.E d;
+        }
+        parcelable C {}
+      }
+      parcelable D {
+        // partial orderings for [E, F]:
+        //   F - E
+        parcelable E {
+          F f;
+        }
+        parcelable F {}
+      }
+      parcelable G {
+        A.B b;
+      }
+    }
+  )";
+  Options options = Options::From("aidl --lang cpp -I. -oout -hout p/IFoo.aidl");
+  io_delegate_.SetFileContents(input_path, input);
+  CaptureStderr();
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+  EXPECT_EQ(GetCapturedStderr(), "");
+
+  string code;
+  EXPECT_TRUE(io_delegate_.GetWrittenContents("out/p/IFoo.h", &code));
+  // check partial orderings: a should comes before b
+  EXPECT_LE(code.find("class D"), code.find("class A"));
+  EXPECT_LE(code.find("class A"), code.find("class G"));
+  EXPECT_LE(code.find("class C"), code.find("class B"));
+  EXPECT_LE(code.find("class F"), code.find("class E"));
+}
+
+TEST_F(AidlTest, RejectsNestedTypesWithCyclicDeps) {
+  const string input_path = "p/IFoo.aidl";
+  const string input = R"(
+    package p;
+    interface IFoo {
+      // Cycles:
+      //   D - A
+      //   A - G
+      //   G - D
+      parcelable A {
+        parcelable B {
+          C c;
+        }
+      }
+      parcelable C {
+        parcelable D {
+          E e;
+        }
+      }
+      parcelable E {
+        parcelable F {
+          A a;
+        }
+      }
+    }
+  )";
+  Options options = Options::From("aidl --lang cpp -I. -oout -hout p/IFoo.aidl");
+  io_delegate_.SetFileContents(input_path, input);
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("IFoo has nested types with cyclic references."));
+}
+
+TEST_F(AidlTest, CppNameOf_GenericType) {
+  const string input_path = "p/Wrapper.aidl";
+  const string input = "package p; parcelable Wrapper<T> {}";
+
+  auto parse_result = Parse(input_path, input, typenames_, Options::Language::CPP);
+  EXPECT_NE(nullptr, parse_result);
+
+  auto type = [](std::string name, auto&&... type_params) -> std::unique_ptr<AidlTypeSpecifier> {
+    auto params = new std::vector<std::unique_ptr<AidlTypeSpecifier>>;
+    (..., params->emplace_back(std::move(type_params)));
+    return std::make_unique<AidlTypeSpecifier>(AIDL_LOCATION_HERE, name, std::nullopt, params,
+                                               Comments{});
+  };
+
+  auto set_nullable = [](std::unique_ptr<AidlTypeSpecifier>&& type) {
+    std::vector<std::unique_ptr<AidlAnnotation>> annotations;
+    annotations.emplace_back(std::unique_ptr<AidlAnnotation>(
+        AidlAnnotation::Parse(AIDL_LOCATION_HERE, "nullable", {}, {})));
+    type->Annotate(std::move(annotations));
+    return std::move(type);
+  };
+
+  auto set_array = [](std::unique_ptr<AidlTypeSpecifier>&& type) {
+    (void)type->MakeArray(DynamicArray{});
+    return std::move(type);
+  };
+
+  auto w = type("p.Wrapper", type("String"));
+  EXPECT_EQ("::p::Wrapper<::android::String16>", cpp::CppNameOf(*w, typenames_));
+
+  auto nullable_w = set_nullable(type("p.Wrapper", type("String")));
+  EXPECT_EQ("::std::optional<::p::Wrapper<::android::String16>>",
+            cpp::CppNameOf(*nullable_w, typenames_));
+
+  auto array_w = set_array(type("p.Wrapper", type("String")));
+  EXPECT_EQ("::std::vector<::p::Wrapper<::android::String16>>",
+            cpp::CppNameOf(*array_w, typenames_));
+
+  auto nullable_array_w = set_nullable(set_array(type("p.Wrapper", type("String"))));
+  EXPECT_EQ("::std::optional<::std::vector<::std::optional<::p::Wrapper<::android::String16>>>>",
+            cpp::CppNameOf(*nullable_array_w, typenames_));
+
+  auto list_w = type("List", type("p.Wrapper", type("String")));
+  EXPECT_EQ("::std::vector<::p::Wrapper<::android::String16>>",
+            cpp::CppNameOf(*list_w, typenames_));
+
+  auto nullable_list_w = set_nullable(type("List", type("p.Wrapper", type("String"))));
+  EXPECT_EQ("::std::optional<::std::vector<::std::optional<::p::Wrapper<::android::String16>>>>",
+            cpp::CppNameOf(*nullable_list_w, typenames_));
+}
+
 TEST_P(AidlTest, UnderstandsNativeParcelables) {
   io_delegate_.SetFileContents(
       "p/Bar.aidl",
@@ -1199,10 +2018,10 @@
   auto parse_result = Parse(input_path, input, typenames_, GetLanguage());
   EXPECT_NE(nullptr, parse_result);
   EXPECT_TRUE(typenames_.ResolveTypename("p.Bar").is_resolved);
-  AidlTypeSpecifier native_type(AIDL_LOCATION_HERE, "p.Bar", false, nullptr, {});
-  native_type.Resolve(typenames_);
+  AidlTypeSpecifier native_type(AIDL_LOCATION_HERE, "p.Bar", /*array=*/std::nullopt, nullptr, {});
+  native_type.Resolve(typenames_, parse_result);
 
-  EXPECT_EQ("p.Bar", java::InstantiableJavaSignatureOf(native_type, typenames_));
+  EXPECT_EQ("p.Bar", java::InstantiableJavaSignatureOf(native_type));
   // C++ understands C++ specific stuff
   EXPECT_EQ("::p::Bar", cpp::CppNameOf(native_type, typenames_));
   set<string> headers;
@@ -1222,7 +2041,7 @@
     "p/IFoo.aidl"};
   Options options = Options::From(args);
   io_delegate_.SetFileContents(options.InputFiles().front(), "package p; interface IFoo {}");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   string actual_dep_file_contents;
   EXPECT_TRUE(io_delegate_.GetWrittenContents(options.DependencyFile(), &actual_dep_file_contents));
   EXPECT_EQ(actual_dep_file_contents, kExpectedDepFileContents);
@@ -1240,7 +2059,7 @@
     "p/IFoo.aidl"};
   Options options = Options::From(args);
   io_delegate_.SetFileContents(options.InputFiles().front(), "package p; interface IFoo {}");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   string actual_dep_file_contents;
   EXPECT_TRUE(io_delegate_.GetWrittenContents(options.DependencyFile(), &actual_dep_file_contents));
   EXPECT_EQ(actual_dep_file_contents, kExpectedNinjaDepFileContents);
@@ -1259,7 +2078,7 @@
     "p/Foo.aidl"};
   Options options = Options::From(args);
   io_delegate_.SetFileContents(options.InputFiles().front(), "package p; parcelable Foo;");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   string actual_dep_file_contents;
   EXPECT_TRUE(io_delegate_.GetWrittenContents(options.DependencyFile(), &actual_dep_file_contents));
   EXPECT_EQ(actual_dep_file_contents, kExpectedParcelableDeclarationDepFileContents);
@@ -1274,7 +2093,7 @@
     "p/Foo.aidl"};
   Options options = Options::From(args);
   io_delegate_.SetFileContents(options.InputFiles().front(), "package p; parcelable Foo {int a;}");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   string actual_dep_file_contents;
   EXPECT_TRUE(io_delegate_.GetWrittenContents(options.DependencyFile(), &actual_dep_file_contents));
   EXPECT_EQ(actual_dep_file_contents, kExpectedStructuredParcelableDepFileContents);
@@ -1288,19 +2107,16 @@
     "p/Foo.aidl"};
   Options options = Options::From(args);
   io_delegate_.SetFileContents(options.InputFiles().front(), "package p; parcelable Foo;");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   string output_file_contents;
   EXPECT_FALSE(io_delegate_.GetWrittenContents(options.OutputFile(), &output_file_contents));
 }
 
 TEST_P(AidlTest, RejectsListArray) {
-  const string expected_stderr = "ERROR: a/Foo.aidl:2.1-7: List[] is not supported.\n";
-  const string list_array_parcelable =
-      "package a; parcelable Foo {\n"
-      "  List[] lists; }";
+  const string input = "package a; parcelable Foo { List<String>[] lists; }";
   CaptureStderr();
-  EXPECT_EQ(nullptr, Parse("a/Foo.aidl", list_array_parcelable, typenames_, GetLanguage()));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+  EXPECT_EQ(nullptr, Parse("a/Foo.aidl", input, typenames_, GetLanguage()));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Arrays of List are not supported"));
 }
 
 TEST_P(AidlTest, RejectsPrimitiveListInStableAidl) {
@@ -1342,17 +2158,10 @@
       "  ParcelableHolder extension;\n"
       "  ParcelableHolder extension2;\n"
       "}";
-  if (GetLanguage() == Options::Language::RUST) {
-    EXPECT_EQ(nullptr, Parse("a/Data.aidl", extendable_parcelable, typenames_, GetLanguage()));
-    EXPECT_EQ(
-        "ERROR: a/Data.aidl:2.1-19: The Rust backend does not support ParcelableHolder "
-        "yet.\n",
-        GetCapturedStderr());
-  } else {
-    EXPECT_NE(nullptr, Parse("a/Data.aidl", extendable_parcelable, typenames_, GetLanguage()));
-    EXPECT_EQ("", GetCapturedStderr());
-  }
+  EXPECT_NE(nullptr, Parse("a/Data.aidl", extendable_parcelable, typenames_, GetLanguage()));
+  EXPECT_EQ("", GetCapturedStderr());
 }
+
 TEST_P(AidlTest, ParcelableHolderAsReturnType) {
   CaptureStderr();
   string parcelableholder_return_interface =
@@ -1362,14 +2171,6 @@
   EXPECT_EQ(nullptr,
             Parse("a/IFoo.aidl", parcelableholder_return_interface, typenames_, GetLanguage()));
 
-  if (GetLanguage() == Options::Language::RUST) {
-    EXPECT_EQ(
-        "ERROR: a/IFoo.aidl:2.19-23: ParcelableHolder cannot be a return type\n"
-        "ERROR: a/IFoo.aidl:2.1-19: The Rust backend does not support ParcelableHolder "
-        "yet.\n",
-        GetCapturedStderr());
-    return;
-  }
   EXPECT_EQ("ERROR: a/IFoo.aidl:2.19-23: ParcelableHolder cannot be a return type\n",
             GetCapturedStderr());
 }
@@ -1383,14 +2184,6 @@
   EXPECT_EQ(nullptr,
             Parse("a/IFoo.aidl", extendable_parcelable_arg_interface, typenames_, GetLanguage()));
 
-  if (GetLanguage() == Options::Language::RUST) {
-    EXPECT_EQ(
-        "ERROR: a/IFoo.aidl:2.31-34: ParcelableHolder cannot be an argument type\n"
-        "ERROR: a/IFoo.aidl:2.14-31: The Rust backend does not support ParcelableHolder "
-        "yet.\n",
-        GetCapturedStderr());
-    return;
-  }
   EXPECT_EQ("ERROR: a/IFoo.aidl:2.31-34: ParcelableHolder cannot be an argument type\n",
             GetCapturedStderr());
 }
@@ -1400,15 +2193,7 @@
   Options options = Options::From("aidl Foo.aidl --lang=" + to_string(GetLanguage()));
   const string expected_stderr = "ERROR: Foo.aidl:1.27-44: ParcelableHolder cannot be nullable.\n";
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
-  if (GetLanguage() == Options::Language::RUST) {
-    EXPECT_EQ(
-        "ERROR: Foo.aidl:1.27-44: ParcelableHolder cannot be nullable.\n"
-        "ERROR: Foo.aidl:1.27-44: The Rust backend does not support ParcelableHolder "
-        "yet.\n",
-        GetCapturedStderr());
-    return;
-  }
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -1416,7 +2201,7 @@
   io_delegate_.SetFileContents("Foo.aidl", "parcelable Foo { const int BIT = 0x1 << 3; }");
   Options options = Options::From("aidl Foo.aidl --lang=" + to_string(GetLanguage()));
   CaptureStderr();
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   EXPECT_EQ("", GetCapturedStderr());
 }
 
@@ -1424,7 +2209,7 @@
   io_delegate_.SetFileContents("Foo.aidl", "union Foo { const int BIT = 0x1 << 3; int n; }");
   Options options = Options::From("aidl Foo.aidl --lang=" + to_string(GetLanguage()));
   CaptureStderr();
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   EXPECT_EQ("", GetCapturedStderr());
 }
 
@@ -1436,7 +2221,7 @@
                                "}");
   Options options = Options::From("aidl IFoo.aidl --lang=java -o out");
   CaptureStderr();
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   EXPECT_EQ("", GetCapturedStderr());
   string code;
   EXPECT_TRUE(io_delegate_.GetWrittenContents("out/IFoo.java", &code));
@@ -1447,6 +2232,7 @@
 TEST_F(AidlTest, ApiDump) {
   io_delegate_.SetFileContents(
       "foo/bar/IFoo.aidl",
+      "// comment\n"
       "package foo.bar;\n"
       "import foo.bar.Data;\n"
       "// commented /* @hide */\n"
@@ -1456,6 +2242,7 @@
       "    int foo(out int[] a, String b, boolean c, inout List<String> d);\n"
       "    int foo2(@utf8InCpp String x, inout List<String> y);\n"
       "    IFoo foo3(IFoo foo);\n"
+      "    void foo4(in int[2][3] fixedArray);\n"
       "    Data getData();\n"
       "    // @hide not applied\n"
       "    /** blahblah\n"
@@ -1466,6 +2253,7 @@
       "    const String STR = \"Hello\";\n"
       "}\n");
   io_delegate_.SetFileContents("foo/bar/Data.aidl",
+                               "// comment\n"
                                "package foo.bar;\n"
                                "import foo.bar.IFoo;\n"
                                "/* @hide*/\n"
@@ -1487,7 +2275,7 @@
   ASSERT_TRUE(result);
   string actual;
   EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/IFoo.aidl", &actual));
-  EXPECT_EQ(string(kPreamble).append(R"(package foo.bar;
+  EXPECT_EQ(string("// comment\n").append(string(kPreamble)).append(R"(package foo.bar;
 interface IFoo {
   /**
    * @hide
@@ -1496,6 +2284,7 @@
   int foo(out int[] a, String b, boolean c, inout List<String> d);
   int foo2(@utf8InCpp String x, inout List<String> y);
   foo.bar.IFoo foo3(foo.bar.IFoo foo);
+  void foo4(in int[2][3] fixedArray);
   foo.bar.Data getData();
   /**
    * @deprecated reason why...
@@ -1507,7 +2296,7 @@
             actual);
 
   EXPECT_TRUE(io_delegate_.GetWrittenContents("dump/foo/bar/Data.aidl", &actual));
-  EXPECT_EQ(string(kPreamble).append(R"(package foo.bar;
+  EXPECT_EQ(string("// comment\n").append(string(kPreamble)).append(R"(package foo.bar;
 /* @hide */
 parcelable Data {
   int x = 10;
@@ -1657,6 +2446,17 @@
             actual);
 }
 
+TEST_F(AidlTest, ImportedDocumentHasDuplicateDefinitions) {
+  io_delegate_.SetFileContents("IFoo.aidl", "interface IFoo; interface IFoo;\n");
+  io_delegate_.SetFileContents("Bar.aidl", "enum Bar { CONST = IFoo.NONE }\n");
+
+  vector<string> args = {"aidl", "--dumpapi", "-I.", "-o out", "Bar.aidl"};
+  Options options = Options::From(args);
+  CaptureStderr();
+  EXPECT_FALSE(dump_api(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Can't find NONE in IFoo"));
+}
+
 TEST_F(AidlTest, CheckNumGenericTypeSecifier) {
   const string expected_list_stderr =
       "ERROR: p/IFoo.aidl:1.37-41: List can only have one type parameter, but got: "
@@ -1668,44 +2468,44 @@
                                "package p; interface IFoo {"
                                "void foo(List<String, String> a);}");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_list_stderr, GetCapturedStderr());
 
   io_delegate_.SetFileContents(options.InputFiles().front(),
                                "package p; interface IFoo {"
                                "void foo(Map<String> a);}");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_map_stderr, GetCapturedStderr());
 }
 
 TEST_F(AidlTest, CheckTypeParameterInMapType) {
   const string expected_stderr =
       "ERROR: p/IFoo.aidl:1.28-31: The type of key in map must be String, but it is 'p.Bar'\n";
-  Options options = Options::From("aidl -I p p/IFoo.aidl");
+  Options options = Options::From("aidl -I . p/IFoo.aidl");
   io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar { String s; }");
 
   io_delegate_.SetFileContents("p/IFoo.aidl",
                                "package p; interface IFoo {"
-                               "Map<String, Bar> foo();}");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+                               "Map<String, p.Bar> foo();}");
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 
   io_delegate_.SetFileContents("p/IFoo.aidl",
                                "package p; interface IFoo {"
-                               "Map<Bar, Bar> foo();}");
+                               "Map<p.Bar, p.Bar> foo();}");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 
   io_delegate_.SetFileContents("p/IFoo.aidl",
                                "package p; interface IFoo {"
                                "Map<String, String> foo();}");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 
   io_delegate_.SetFileContents("p/IFoo.aidl",
                                "package p; interface IFoo {"
                                "Map<String, ParcelFileDescriptor> foo();}");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 }
 
 TEST_F(AidlTest, WrongGenericType) {
@@ -1715,47 +2515,46 @@
                                "package p; interface IFoo {"
                                "String<String> foo(); }");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
 TEST_F(AidlTest, UserDefinedUnstructuredGenericParcelableType) {
-  Options optionsForParcelable = Options::From("aidl -I p p/Bar.aidl");
+  Options optionsForParcelable = Options::From("aidl -I . p/Bar.aidl");
   io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar<T, T>;");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(optionsForParcelable, io_delegate_));
+  EXPECT_FALSE(compile_aidl(optionsForParcelable, io_delegate_));
   EXPECT_EQ("ERROR: p/Bar.aidl:1.22-26: Every type parameter should be unique.\n",
             GetCapturedStderr());
 
-  Options options = Options::From("aidl -I p p/IFoo.aidl");
+  Options options = Options::From("aidl -I . p/IFoo.aidl");
   io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar;");
   io_delegate_.SetFileContents("p/IFoo.aidl",
                                "package p; interface IFoo {"
-                               "Bar<String, String> foo();}");
+                               "p.Bar<String, String> foo();}");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
-  EXPECT_EQ("ERROR: p/IFoo.aidl:1.28-31: p.Bar is not a generic type.\n", GetCapturedStderr());
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("p.Bar is not a generic type"));
   io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar<T>;");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
-  EXPECT_EQ("ERROR: p/IFoo.aidl:1.28-31: p.Bar must have 1 type parameters, but got 2\n",
-            GetCapturedStderr());
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("p.Bar must have 1 type parameters, but got 2"));
   io_delegate_.SetFileContents("p/Bar.aidl", "package p; parcelable Bar<T, V>;");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   io_delegate_.SetFileContents("p/IFoo.aidl",
                                "package p; interface IFoo {"
-                               "Bar<String, ParcelFileDescriptor> foo();}");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+                               "p.Bar<String, ParcelFileDescriptor> foo();}");
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 
   io_delegate_.SetFileContents("p/IFoo.aidl",
                                "package p; interface IFoo {"
-                               "Bar<int, long> foo();}");
+                               "p.Bar<int, long> foo();}");
 
   io_delegate_.SetFileContents("p/IFoo.aidl",
                                "package p; interface IFoo {"
-                               "Bar<int[], long[]> foo();}");
+                               "p.Bar<int[], long[]> foo();}");
 
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 }
 
 TEST_F(AidlTest, FailOnMultipleTypesInSingleFile) {
@@ -1773,7 +2572,7 @@
                                  "parcelable Data1 { int a; int b;}\n"
                                  "parcelable Data2 { int a; int b;}\n");
     CaptureStderr();
-    EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+    EXPECT_FALSE(compile_aidl(options, io_delegate_));
     EXPECT_EQ(expected_stderr, GetCapturedStderr());
 
     io_delegate_.SetFileContents(options.InputFiles().front(),
@@ -1781,7 +2580,7 @@
                                  "interface IFoo1 { int foo(); }\n"
                                  "interface IFoo2 { int foo(); }\n");
     CaptureStderr();
-    EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+    EXPECT_FALSE(compile_aidl(options, io_delegate_));
     EXPECT_EQ(expected_stderr, GetCapturedStderr());
 
     expected_stderr = "ERROR: foo/bar/Foo.aidl:3.11-17: You must declare only one type per file.\n";
@@ -1790,7 +2589,7 @@
                                  "parcelable Data1 { int a; int b;}\n"
                                  "parcelable Data2 { int a; int b;}\n");
     CaptureStderr();
-    EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+    EXPECT_FALSE(compile_aidl(options, io_delegate_));
     EXPECT_EQ(expected_stderr, GetCapturedStderr());
   }
 }
@@ -1817,7 +2616,7 @@
         "import foo.bar.IFoo;\n"
         "parcelable Data { IFoo foo; }\n");
 
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 
   string content;
   for (const auto file : {
@@ -1842,7 +2641,7 @@
         "import foo.bar.IFoo;\n"
         "parcelable Data { IFoo foo; }\n");
 
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 
   string content;
   for (const auto file : {
@@ -1870,7 +2669,7 @@
                                "import foo.bar.IFoo;\n"
                                "parcelable Data { IFoo foo; }\n");
 
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 
   string content;
   for (const auto file : {"out/foo/bar/IFoo.rs", "out/foo/bar/Data.rs"}) {
@@ -1889,7 +2688,7 @@
                                "package p; interface IFoo {"
                                "int getInterfaceVersion(); }");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -1903,7 +2702,7 @@
                                "package p; interface IFoo {"
                                "boolean getInterfaceVersion(); }");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -1916,14 +2715,14 @@
                                "package p; interface IFoo {"
                                "String getTransactionName(int code); }");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 
   // this is not a meta interface method as it differs type arguments
   io_delegate_.SetFileContents(options.InputFiles().front(),
                                "package p; interface IFoo {"
                                "String getTransactionName(); }");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 }
 
 TEST_F(AidlTest, CheckApiForEquality) {
@@ -1969,6 +2768,17 @@
   EXPECT_TRUE(::android::aidl::check_api(options, io_delegate_));
 }
 
+TEST_F(AidlTest, CheckApi_EnumFieldsFromImported) {
+  Options options = Options::From("aidl --checkapi old new -I import");
+
+  io_delegate_.SetFileContents("old/p/Foo.aidl", "package p; parcelable Foo{ other.Enum e; }");
+  io_delegate_.SetFileContents("new/p/Foo.aidl",
+                               "package p; parcelable Foo{ other.Enum e = other.Enum.FOO; }");
+  io_delegate_.SetFileContents("import/other/Enum.aidl", "package other; enum Enum { FOO }");
+
+  EXPECT_TRUE(::android::aidl::check_api(options, io_delegate_));
+}
+
 TEST_F(AidlTest, CheckApiEqual_EnumFieldsWithDefaultValues) {
   Options options = Options::From("aidl --checkapi=equal old new");
   const string foo_definition = "package p; parcelable Foo{ p.Enum e = p.Enum.FOO; }";
@@ -2017,7 +2827,7 @@
                                "interface IFoo {"
                                "  void foo(int a);"
                                "  void bar();"
-                               "  void baz(in List<IFoo> arg);"
+                               "  void baz(in List<String> arg);"
                                "}");
   EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
 }
@@ -2238,6 +3048,37 @@
   EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
 }
 
+TEST_F(AidlTestCompatibleChanges, NewNestedTypes) {
+  io_delegate_.SetFileContents("old/p/Data.aidl",
+                               "package p;\n"
+                               "parcelable Data {\n"
+                               "  int n;\n"
+                               "}");
+  io_delegate_.SetFileContents("new/p/Data.aidl",
+                               "package p;\n"
+                               "parcelable Data {\n"
+                               "  enum NewEnum { N = 3 }\n"
+                               "  int n;\n"
+                               "  NewEnum e = NewEnum.N;\n"
+                               "}");
+  EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
+}
+
+TEST_F(AidlTestCompatibleChanges, NewJavaSuppressLint) {
+  io_delegate_.SetFileContents("old/p/IFoo.aidl",
+                               "package p;"
+                               "interface IFoo {"
+                               "  void foo(int a);"
+                               "}");
+  io_delegate_.SetFileContents("new/p/IFoo.aidl",
+                               "package p;"
+                               "@JavaSuppressLint({\"NewApi\"})"
+                               "interface IFoo {"
+                               "  void foo(int a);"
+                               "}");
+  EXPECT_TRUE(::android::aidl::check_api(options_, io_delegate_));
+}
+
 class AidlTestIncompatibleChanges : public AidlTest {
  protected:
   Options options_ = Options::From("aidl --checkapi old new");
@@ -2746,36 +3587,105 @@
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
+TEST_F(AidlTestIncompatibleChanges, IncompatibleChangesInNestedType) {
+  const string expected_stderr =
+      "ERROR: new/p/Foo.aidl:1.33-37: Number of fields in p.Foo is reduced from 2 to 1.\n";
+  io_delegate_.SetFileContents("old/p/Foo.aidl",
+                               "package p;\n"
+                               "parcelable Foo {\n"
+                               "  interface IBar {\n"
+                               "    void foo();"
+                               "  }\n"
+                               "}");
+  io_delegate_.SetFileContents("new/p/Foo.aidl",
+                               "package p;\n"
+                               "parcelable Foo {\n"
+                               "  interface IBar {\n"
+                               "    void foo(int n);"  // incompatible: signature changed
+                               "  }\n"
+                               "}");
+  CaptureStderr();
+  EXPECT_FALSE(::android::aidl::check_api(options_, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Removed or changed method: p.Foo.IBar.foo()"));
+}
+
 TEST_P(AidlTest, RejectNonFixedSizeFromFixedSize) {
   const string expected_stderr =
-      "ERROR: Foo.aidl:1.36-38: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "ERROR: Foo.aidl:2.8-10: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
       "a.\n"
-      "ERROR: Foo.aidl:1.44-46: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
-      "b.\n"
-      "ERROR: Foo.aidl:1.55-57: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "ERROR: Foo.aidl:3.6-8: The @FixedSize parcelable 'Foo' has a non-fixed size field named b.\n"
+      "ERROR: Foo.aidl:4.9-11: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
       "c.\n"
-      "ERROR: Foo.aidl:1.80-82: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "ERROR: Foo.aidl:5.23-25: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
       "d.\n"
-      "ERROR: Foo.aidl:1.92-94: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "ERROR: Foo.aidl:6.10-12: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
       "e.\n"
-      "ERROR: Foo.aidl:1.109-111: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
-      "f.\n";
+      "ERROR: Foo.aidl:7.15-17: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "f.\n"
+      "ERROR: Foo.aidl:9.23-33: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "nullable1.\n"
+      "ERROR: Foo.aidl:10.34-44: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "nullable2.\n";
 
   io_delegate_.SetFileContents("Foo.aidl",
-                               "@FixedSize parcelable Foo { "
-                               "  int[] a;"
-                               "  Bar b;"
-                               "  String c;"
-                               "  ParcelFileDescriptor d;"
-                               "  IBinder e;"
-                               "  List<String> f;"
-                               "  int isFixedSize;"
+                               "@FixedSize parcelable Foo {\n"
+                               "  int[] a;\n"
+                               "  Bar b;\n"
+                               "  String c;\n"
+                               "  ParcelFileDescriptor d;\n"
+                               "  IBinder e;\n"
+                               "  List<String> f;\n"
+                               "  int isFixedSize;\n"
+                               "  @nullable OtherFixed nullable1;\n"
+                               "  @nullable(heap=true) OtherFixed nullable2;\n"
+                               "  float[16] floats;\n"
                                "}");
   io_delegate_.SetFileContents("Bar.aidl", "parcelable Bar { int a; }");
+  io_delegate_.SetFileContents("OtherFixed.aidl", "@FixedSize parcelable OtherFixed { int a; }");
   Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(GetLanguage()));
 
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+}
+
+TEST_P(AidlTest, RejectNonFixedSizeFromFixedSize_Union) {
+  const string expected_stderr =
+      "ERROR: Foo.aidl:2.8-10: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "a.\n"
+      "ERROR: Foo.aidl:3.6-8: The @FixedSize parcelable 'Foo' has a non-fixed size field named b.\n"
+      "ERROR: Foo.aidl:4.9-11: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "c.\n"
+      "ERROR: Foo.aidl:5.23-25: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "d.\n"
+      "ERROR: Foo.aidl:6.10-12: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "e.\n"
+      "ERROR: Foo.aidl:7.15-17: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "f.\n"
+      "ERROR: Foo.aidl:9.23-33: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "nullable1.\n"
+      "ERROR: Foo.aidl:10.34-44: The @FixedSize parcelable 'Foo' has a non-fixed size field named "
+      "nullable2.\n";
+
+  io_delegate_.SetFileContents("Foo.aidl",
+                               "@FixedSize union Foo {\n"
+                               "  int[] a = {};\n"
+                               "  Bar b;\n"
+                               "  String c;\n"
+                               "  ParcelFileDescriptor d;\n"
+                               "  IBinder e;\n"
+                               "  List<String> f;\n"
+                               "  int isFixedSize;\n"
+                               "  @nullable OtherFixed nullable1;\n"
+                               "  @nullable(heap=true) OtherFixed nullable2;\n"
+                               "  float[16] floats;\n"
+                               "}");
+  io_delegate_.SetFileContents("Bar.aidl", "parcelable Bar { int a; }");
+  io_delegate_.SetFileContents("OtherFixed.aidl", "@FixedSize parcelable OtherFixed { int a; }");
+  Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(GetLanguage()));
+
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -2788,7 +3698,7 @@
   Options options = Options::From("aidl Foo.aidl -I . --lang=" + to_string(GetLanguage()));
 
   CaptureStderr();
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -2804,7 +3714,7 @@
   io_delegate_.SetFileContents("dir2/q/IBar.aidl", "package q; interface IBar{}");
 
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -2831,7 +3741,7 @@
   // use without import
   io_delegate_.SetFileContents("p/IFoo.aidl",
                                "package p; interface IFoo{ void foo(in ParcelFileDescriptor fd);}");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 
   // capture output files
   map<string, string> outputs = io_delegate_.OutputFiles();
@@ -2840,7 +3750,7 @@
   io_delegate_.SetFileContents(
       "p/IFoo.aidl",
       "package p; interface IFoo{ void foo(in android.os.ParcelFileDescriptor fd);}");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   // output files should be the same
   EXPECT_EQ(outputs, io_delegate_.OutputFiles());
 
@@ -2851,7 +3761,7 @@
                                "interface IFoo{"
                                "  void foo(in ParcelFileDescriptor fd);"
                                "}");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   // output files should be the same
   EXPECT_EQ(outputs, io_delegate_.OutputFiles());
 }
@@ -2864,7 +3774,7 @@
                                "interface IFoo{"
                                "  void foo(out ParcelFileDescriptor fd);"
                                "}");
-  EXPECT_EQ(1, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_THAT(GetCapturedStderr(), HasSubstr("can't be an out parameter"));
 }
 
@@ -2876,7 +3786,7 @@
                                "interface IFoo{"
                                "  void foo(ParcelFileDescriptor fd);"
                                "}");
-  EXPECT_EQ(1, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_THAT(GetCapturedStderr(),
               HasSubstr("ParcelFileDescriptor can be an in or inout parameter."));
 }
@@ -2888,7 +3798,7 @@
                                "  void foo() = 0;\n"
                                "  void bar() = 1;\n"
                                "}");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 }
 
 TEST_F(AidlTest, ManualIdsWithMetaTransactions) {
@@ -2898,7 +3808,7 @@
                                "  void foo() = 0;\n"
                                "  void bar() = 1;\n"
                                "}");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 }
 
 TEST_F(AidlTest, FailOnDuplicatedIds) {
@@ -2911,7 +3821,7 @@
                                "  void bar() = 3;\n"
                                "}");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -2927,7 +3837,7 @@
                                "  void bar() = 16777115;\n"
                                "}");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -2941,15 +3851,38 @@
                                "  void bar();\n"
                                "}");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
+TEST_F(AidlTest, AssignedIds) {
+  CaptureStderr();
+  EXPECT_NE(nullptr, Parse("IFoo.aidl",
+                           "interface IFoo {\n"
+                           "  void foo();\n"
+                           "  void bar();\n"
+                           "  interface INested {\n"
+                           "    void foo();\n"
+                           "    void bar();\n"
+                           "  }\n"
+                           "}",
+                           typenames_, Options::Language::JAVA));
+  EXPECT_EQ("", GetCapturedStderr());
+  auto foo = typenames_.ResolveTypename("IFoo").defined_type;
+  ASSERT_EQ(2u, foo->GetMethods().size());
+  EXPECT_EQ(0, foo->GetMethods()[0]->GetId());
+  EXPECT_EQ(1, foo->GetMethods()[1]->GetId());
+  auto nested = typenames_.ResolveTypename("IFoo.INested").defined_type;
+  ASSERT_EQ(2u, nested->GetMethods().size());
+  EXPECT_EQ(0, nested->GetMethods()[0]->GetId());
+  EXPECT_EQ(1, nested->GetMethods()[1]->GetId());
+}
+
 TEST_F(AidlTest, AllowDuplicatedImportPaths) {
   Options options = Options::From("aidl --lang=java -I dir -I dir IFoo.aidl");
   io_delegate_.SetFileContents("dir/IBar.aidl", "interface IBar{}");
   io_delegate_.SetFileContents("IFoo.aidl", "import IBar; interface IFoo{}");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 }
 
 TEST_F(AidlTest, FailOnAmbiguousImports) {
@@ -2964,7 +3897,7 @@
   io_delegate_.SetFileContents("dir2/IBar.aidl", "interface IBar{}");
   io_delegate_.SetFileContents("IFoo.aidl", "import IBar; interface IFoo{}");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -2978,7 +3911,7 @@
   io_delegate_.SetFileContents("a/b/IQux.aidl", "package a.b; interface IQux { void foo(); }");
 
   Options options = Options::From("aidl --lang=ndk a/b/IFoo.aidl -I . -o out -h out/include");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 
   string output;
   EXPECT_TRUE(io_delegate_.GetWrittenContents("out/include/aidl/a/b/IFoo.h", &output));
@@ -3008,7 +3941,7 @@
     })--");
 
   Options java_options = Options::From("aidl -I . --lang=java -o out a/IFoo.aidl a/MyEnum.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
 
   string java_out;
   EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/IFoo.java", &java_out));
@@ -3029,14 +3962,14 @@
   // Other backends shouldn't be bothered
   Options cpp_options =
       Options::From("aidl -I . --lang=cpp -o out -h out a/IFoo.aidl a/MyEnum.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(cpp_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(cpp_options, io_delegate_));
 
   Options ndk_options =
       Options::From("aidl -I . --lang=ndk -o out -h out a/IFoo.aidl a/MyEnum.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(ndk_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(ndk_options, io_delegate_));
 
   Options rust_options = Options::From("aidl -I . --lang=rust -o out a/IFoo.aidl a/MyEnum.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(rust_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(rust_options, io_delegate_));
 }
 
 TEST_F(AidlTest, ParseRustDerive) {
@@ -3047,7 +3980,7 @@
     })");
 
   Options rust_options = Options::From("aidl --lang=rust -o out a/Foo.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(rust_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(rust_options, io_delegate_));
 
   string rust_out;
   EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/Foo.rs", &rust_out));
@@ -3055,13 +3988,147 @@
 
   // Other backends shouldn't be bothered
   Options cpp_options = Options::From("aidl --lang=cpp -o out -h out a/Foo.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(cpp_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(cpp_options, io_delegate_));
 
   Options ndk_options = Options::From("aidl --lang=ndk -o out -h out a/Foo.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(ndk_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(ndk_options, io_delegate_));
 
   Options java_options = Options::From("aidl --lang=java -o out a/Foo.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(java_options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(java_options, io_delegate_));
+}
+
+TEST_F(AidlTest, EmptyEnforceAnnotation) {
+  io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
+    interface IFoo {
+        @EnforcePermission()
+        void Protected();
+    })");
+
+  Options options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Unable to parse @EnforcePermission annotation"));
+}
+
+TEST_F(AidlTest, InterfaceEnforceCondition) {
+  io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
+    @EnforcePermission("INTERNET")
+    interface IFoo {
+        void Protected();
+    })");
+
+  Options options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+}
+
+TEST_F(AidlTest, EnforceConditionAny) {
+  io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
+    interface IFoo {
+        @EnforcePermission(anyOf={"INTERNET", "READ_PHONE_STATE"})
+        void Protected();
+    })");
+
+  Options options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+}
+
+TEST_F(AidlTest, EnforceConditionAll) {
+  io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
+    interface IFoo {
+        @EnforcePermission(allOf={"INTERNET", "READ_PHONE_STATE"})
+        void Protected();
+    })");
+
+  Options options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+}
+
+TEST_F(AidlTest, InterfaceAndMethodEnforceCondition) {
+  io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
+    @EnforcePermission("INTERNET")
+    interface IFoo {
+        @EnforcePermission("SYSTEM_UID")
+        void Protected();
+    })");
+
+  Options options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+}
+
+TEST_F(AidlTest, NoPermissionInterfaceEnforceMethod) {
+  io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
+    @RequiresNoPermission
+    interface IFoo {
+        @EnforcePermission("INTERNET")
+        void Protected();
+    })");
+
+  Options options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(),
+              HasSubstr("The interface IFoo is annotated as requiring no permission"));
+}
+
+TEST_F(AidlTest, ManualPermissionInterfaceEnforceMethod) {
+  io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
+    @PermissionManuallyEnforced
+    interface IFoo {
+        @EnforcePermission("INTERNET")
+        void Protected();
+    })");
+
+  Options options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(
+      GetCapturedStderr(),
+      HasSubstr("The interface IFoo is annotated as manually implementing permission checks"));
+}
+
+TEST_F(AidlTest, EnforceInterfaceNoPermissionsMethod) {
+  io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
+    @EnforcePermission("INTERNET")
+    interface IFoo {
+        @RequiresNoPermission
+        void Protected();
+    })");
+
+  Options options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(),
+              HasSubstr("The interface IFoo enforces permissions using annotations"));
+}
+
+TEST_F(AidlTest, EnforceInterfaceManualPermissionMethod) {
+  io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
+    @EnforcePermission("INTERNET")
+    interface IFoo {
+        @PermissionManuallyEnforced
+        void Protected();
+    })");
+
+  Options options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(),
+              HasSubstr("The interface IFoo enforces permissions using annotations"));
+}
+
+TEST_F(AidlTest, JavaSuppressLint) {
+  io_delegate_.SetFileContents("a/IFoo.aidl", R"(package a;
+    @JavaSuppressLint({"NewApi"})
+    interface IFoo {
+    })");
+
+  Options options = Options::From("aidl --lang=java -o out a/IFoo.aidl");
+  CaptureStderr();
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+  EXPECT_EQ(GetCapturedStderr(), "");
+  string code;
+  EXPECT_TRUE(io_delegate_.GetWrittenContents("out/a/IFoo.java", &code));
+  EXPECT_THAT(code, HasSubstr("@android.annotation.SuppressLint(value = {\"NewApi\"})"));
 }
 
 class AidlOutputPathTest : public AidlTest {
@@ -3072,7 +4139,7 @@
   }
 
   void Test(const Options& options, const std::string expected_output_path) {
-    EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+    EXPECT_TRUE(compile_aidl(options, io_delegate_));
     // check the existence
     EXPECT_TRUE(io_delegate_.GetWrittenContents(expected_output_path, nullptr));
   }
@@ -3101,7 +4168,7 @@
 TEST_P(AidlTest, FailOnOutOfBoundsInt32MaxConstInt) {
   AidlError error;
   const string expected_stderr =
-      "ERROR: p/IFoo.aidl:3.58-69: Invalid type specifier for an int64 literal: int\n";
+      "ERROR: p/IFoo.aidl:3.58-69: Invalid type specifier for an int64 literal: int (2147483650)\n";
   CaptureStderr();
   EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
                            R"(package p;
@@ -3117,7 +4184,8 @@
 TEST_P(AidlTest, FailOnOutOfBoundsInt32MinConstInt) {
   AidlError error;
   const string expected_stderr =
-      "ERROR: p/IFoo.aidl:3.58-60: Invalid type specifier for an int64 literal: int\n";
+      "ERROR: p/IFoo.aidl:3.58-60: Invalid type specifier for an int64 literal: int "
+      "(-2147483650)\n";
   CaptureStderr();
   EXPECT_EQ(nullptr, Parse("p/IFoo.aidl",
                            R"(package p;
@@ -3165,7 +4233,7 @@
 TEST_P(AidlTest, FailOnOutOfBoundsAutofilledEnum) {
   AidlError error;
   const string expected_stderr =
-      "ERROR: p/TestEnum.aidl:5.1-36: Invalid type specifier for an int32 literal: byte\n"
+      "ERROR: p/TestEnum.aidl:5.1-36: Invalid type specifier for an int32 literal: byte (FOO+1)\n"
       "ERROR: p/TestEnum.aidl:5.1-36: Enumerator type differs from enum backing type.\n";
   CaptureStderr();
   EXPECT_EQ(nullptr, Parse("p/TestEnum.aidl",
@@ -3181,6 +4249,25 @@
   EXPECT_EQ(AidlError::BAD_TYPE, error);
 }
 
+TEST_P(AidlTest, FailOnUnsupportedBackingType) {
+  AidlError error;
+  const string expected_stderr =
+      "ERROR: p/TestEnum.aidl:3.35-44: Invalid backing type: boolean. Backing type must be one of: "
+      "byte, int, long\n";
+  CaptureStderr();
+  EXPECT_EQ(nullptr, Parse("p/TestEnum.aidl",
+                           R"(package p;
+                              @Backing(type="boolean")
+                              enum TestEnum {
+                                FOO = 0,
+                                BAR = 1,
+                              }
+                             )",
+                           typenames_, GetLanguage(), &error));
+  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+  EXPECT_EQ(AidlError::BAD_TYPE, error);
+}
+
 TEST_P(AidlTest, UnsupportedBackingAnnotationParam) {
   AidlError error;
   const string expected_stderr =
@@ -3215,7 +4302,7 @@
   io_delegate_.SetFileContents("Baz.aidl",
                                "@JavaOnlyImmutable @JavaOnlyStableParcelable parcelable Baz;");
   Options options = Options::From("aidl --lang=java -I . Foo.aidl");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
 }
 
 TEST_F(AidlTest, RejectMutableParcelableFromJavaOnlyImmutableParcelable) {
@@ -3226,7 +4313,7 @@
       "named 'bar'.\n";
   CaptureStderr();
   Options options = Options::From("aidl --lang=java Foo.aidl -I .");
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_error, GetCapturedStderr());
 }
 
@@ -3235,7 +4322,7 @@
   io_delegate_.SetFileContents("Bar.aidl", "enum Bar { FOO }");
   CaptureStderr();
   Options options = Options::From("aidl --lang=java Foo.aidl -I .");
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   EXPECT_EQ("", GetCapturedStderr());
 }
 
@@ -3247,7 +4334,7 @@
       "named 'bar'.\n";
   CaptureStderr();
   Options options = Options::From("aidl --lang=java Foo.aidl -I .");
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_error, GetCapturedStderr());
 }
 
@@ -3259,7 +4346,7 @@
       "only be an in parameter.\n";
   CaptureStderr();
   Options options = Options::From("aidl --lang=java IBar.aidl -I .");
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_error, GetCapturedStderr());
 }
 
@@ -3271,7 +4358,7 @@
       "only be an in parameter.\n";
   CaptureStderr();
   Options options = Options::From("aidl --lang=java IBar.aidl -I .");
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_error, GetCapturedStderr());
 }
 
@@ -3282,7 +4369,7 @@
       "ERROR: Foo.aidl:1.47-49: 'Foo' has duplicate field name 'A' after capitalizing the first "
       "letter\n";
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -3326,7 +4413,7 @@
   Options options = Options::From("aidl Foo.aidl --lang=" + to_string(GetLanguage()));
   const string expected_stderr = "";
   CaptureStderr();
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -3337,7 +4424,7 @@
       Options::From("aidl Foo.aidl --lang=" + to_string(Options::Language::CPP) + " -o out -h out");
   const string expected_stderr = "";
   CaptureStderr();
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 
   string code;
@@ -3356,7 +4443,7 @@
       Options::From("aidl Foo.aidl --lang=" + to_string(Options::Language::NDK) + " -o out -h out");
   const string expected_stderr = "";
   CaptureStderr();
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 
   string code;
@@ -3376,7 +4463,7 @@
   Options options = Options::From("aidl a/Foo.aidl -I . -o out --lang=java");
   const string expected_stderr = "";
   CaptureStderr();
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 
   string code;
@@ -3386,15 +4473,78 @@
                   "a.Baz<a.Bar<a.Bar<java.lang.String[]>>[],a.Bar<java.lang.String>> barss;"));
 }
 
-TEST_F(AidlTest, DoubleArrayError) {
+TEST_F(AidlTest, AcceptMultiDimensionalFixedSizeArray) {
+  io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[2][3] a; }");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=ndk");
+  CaptureStderr();
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+  EXPECT_EQ("", GetCapturedStderr());
+}
+
+TEST_F(AidlTest, AcceptBinarySizeArray) {
+  io_delegate_.SetFileContents(
+      "a/Bar.aidl", "package a; parcelable Bar { const int CONST = 3; String[CONST + 1] a; }");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=ndk");
+  CaptureStderr();
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+  EXPECT_EQ("", GetCapturedStderr());
+}
+
+TEST_F(AidlTest, AcceptRefSizeArray) {
+  io_delegate_.SetFileContents(
+      "a/Bar.aidl", "package a; parcelable Bar { const int CONST = 3; String[CONST] a; }");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=ndk");
+  CaptureStderr();
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+  EXPECT_EQ("", GetCapturedStderr());
+}
+
+TEST_F(AidlTest, RejectArrayOfFixedSizeArray) {
+  io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[2][] a; }");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Multi-dimensional arrays must be fixed size."));
+}
+
+TEST_F(AidlTest, RejectFixedSizeArrayOfDynamicArray) {
+  io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[][3] a; }");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Multi-dimensional arrays must be fixed size."));
+}
+
+TEST_F(AidlTest, RejectArrayOfArray) {
   io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[][] a; }");
 
   Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
-  const string expected_stderr =
-      "ERROR: a/Bar.aidl:1.28-37: Can only have one dimensional arrays.\n";
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
-  EXPECT_EQ(expected_stderr, GetCapturedStderr());
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Multi-dimensional arrays must be fixed size."));
+}
+
+TEST_F(AidlTest, RejectInvalidArraySize_Negative) {
+  io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[-1] a; }");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Array size must be a positive number"));
+}
+
+TEST_F(AidlTest, RejectInvalidArraySize_WrongType) {
+  io_delegate_.SetFileContents("a/Bar.aidl", "package a; parcelable Bar { String[\"3\"] a; }");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Array size must be a positive number"));
 }
 
 TEST_F(AidlTest, DoubleGenericError) {
@@ -3405,7 +4555,7 @@
   const string expected_stderr =
       "ERROR: a/Bar.aidl:1.28-33: Can only specify one set of type parameters.\n";
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -3414,7 +4564,7 @@
 
   Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_THAT(GetCapturedStderr(), testing::HasSubstr("syntax error, unexpected '<'"));
 }
 
@@ -3424,7 +4574,7 @@
 
   Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
   CaptureStderr();
-  EXPECT_EQ(1, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_THAT(GetCapturedStderr(), testing::HasSubstr("Annotations for arrays are not supported."));
 }
 
@@ -3434,11 +4584,65 @@
 
   Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
   CaptureStderr();
-  EXPECT_EQ(1, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_THAT(GetCapturedStderr(),
               testing::HasSubstr("Annotations for type arguments are not supported."));
 }
 
+TEST_F(AidlTest, DefaultShouldMatchWithFixedSizeArray) {
+  io_delegate_.SetFileContents("a/Bar.aidl",
+                               "package a;\n"
+                               "parcelable Bar {\n"
+                               "  int[2][3] a = {{1,2,3}, {4,5,6}};\n"
+                               "}");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=ndk");
+  CaptureStderr();
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+  EXPECT_EQ("", GetCapturedStderr());
+}
+
+TEST_F(AidlTest, FixedSizeArrayWithWrongTypeDefaultValue) {
+  io_delegate_.SetFileContents("a/Bar.aidl",
+                               "package a;\n"
+                               "parcelable Bar {\n"
+                               "  int[2][3] a = {{\"1\",\"2\",\"3\"}, {4,5,6}};\n"
+                               "}");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Invalid type specifier for a literal string: int"));
+}
+
+TEST_F(AidlTest, FixedSizeArrayWithMoreElements) {
+  io_delegate_.SetFileContents("a/Bar.aidl",
+                               "package a;\n"
+                               "parcelable Bar {\n"
+                               "  int[2][3] a = {{1,2,3,4}, {4,5,6}};\n"
+                               "}");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(),
+              HasSubstr("Expected an array of 3 elements, but found one with 4 elements"));
+}
+
+TEST_F(AidlTest, FixedSizeArrayWithFewerElements) {
+  io_delegate_.SetFileContents("a/Bar.aidl",
+                               "package a;\n"
+                               "parcelable Bar {\n"
+                               "  int[2][3] a = {};\n"
+                               "}");
+
+  Options options = Options::From("aidl a/Bar.aidl -I . -o out --lang=java");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(),
+              HasSubstr("Expected an array of 2 elements, but found one with 0 elements"));
+}
+
 struct GenericAidlTest : ::testing::Test {
   FakeIoDelegate io_delegate_;
   void Compile(string cmd) {
@@ -3449,7 +4653,7 @@
 
     Options options = Options::From(cmd);
     CaptureStderr();
-    EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+    EXPECT_TRUE(compile_aidl(options, io_delegate_));
     EXPECT_EQ("", GetCapturedStderr());
   }
 };
@@ -3478,7 +4682,7 @@
   const string expected_stderr =
       "ERROR: Foo.aidl:1.11-15: Every type parameter should be unique.\n";
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -3487,7 +4691,7 @@
   Options options = Options::From("aidl Foo.aidl --lang=" + to_string(GetLanguage()));
   const string expected_stderr = "ERROR: Foo.aidl:1.22-24: Failed to resolve 'T'\n";
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expected_stderr, GetCapturedStderr());
 }
 
@@ -3495,7 +4699,7 @@
   io_delegate_.SetFileContents("Foo.aidl", "enum Foo { FOO = (1 << 1) /* comment */ | 0x0 }");
   Options options = Options::From("aidl Foo.aidl --lang=" + to_string(GetLanguage()));
   CaptureStderr();
-  EXPECT_EQ(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   EXPECT_EQ("", GetCapturedStderr());
 }
 
@@ -3512,7 +4716,7 @@
       "prohibited because it is not guaranteed that the objects in the list are recognizable in "
       "the receiving side. Consider switching to an array or a generic List/Map.\n";
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expectedErr, GetCapturedStderr());
 }
 
@@ -3529,7 +4733,7 @@
       "prohibited because it is not guaranteed that the objects in the list are recognizable in "
       "the receiving side. Consider switching to an array or a generic List/Map.\n";
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expectedErr, GetCapturedStderr());
 }
 
@@ -3548,7 +4752,7 @@
       "prohibited because it is not guaranteed that the objects in the list are recognizable in "
       "the receiving side. Consider switching to an array or a generic List/Map.\n";
   CaptureStderr();
-  EXPECT_NE(0, ::android::aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(expectedErr, GetCapturedStderr());
 }
 
@@ -3562,7 +4766,7 @@
 })");
   CaptureStderr();
   auto options = Options::From("aidl -I a --lang java -o out a/p/Foo.aidl");
-  EXPECT_EQ(0, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   auto err = GetCapturedStderr();
   EXPECT_EQ("", err);
 
@@ -3581,13 +4785,13 @@
 })");
   CaptureStderr();
   auto options = Options::From("aidl -I a --lang cpp -o out -h out a/p/Foo.aidl");
-  EXPECT_EQ(0, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   auto err = GetCapturedStderr();
   EXPECT_EQ("", err);
 
   string code;
   EXPECT_TRUE(io_delegate_.GetWrittenContents("out/p/Foo.h", &code));
-  EXPECT_THAT(code, testing::HasSubstr("::p::Enum e = ::p::Enum(::p::Enum::BAR);"));
+  EXPECT_THAT(code, testing::HasSubstr("::p::Enum e = ::p::Enum::BAR;"));
 }
 
 TEST_F(AidlTest, EnumWithDefaults_Ndk) {
@@ -3600,7 +4804,7 @@
 })");
   CaptureStderr();
   auto options = Options::From("aidl -I a --lang ndk -o out -h out a/p/Foo.aidl");
-  EXPECT_EQ(0, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   auto err = GetCapturedStderr();
   EXPECT_EQ("", err);
 
@@ -3620,7 +4824,7 @@
 })");
   CaptureStderr();
   auto options = Options::From("aidl -I a --lang rust -o out -h out a/p/Foo.aidl");
-  EXPECT_EQ(0, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   auto err = GetCapturedStderr();
   EXPECT_EQ("", err);
 
@@ -3693,19 +4897,33 @@
 })");
   CaptureStderr();
   auto options = Options::From("aidl -I a --lang java -o out -h out a/p/Foo.aidl");
-  EXPECT_EQ(1, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   auto err = GetCapturedStderr();
   EXPECT_EQ("ERROR: a/p/Foo.aidl:5.11-20: Invalid value (Enum.FOO|Enum.BAR) for enum p.Enum\n",
             err);
 }
 
+TEST_F(AidlTest, EnumDefaultShouldBeEnumerators_RejectsNumericValue) {
+  io_delegate_.SetFileContents("a/p/Enum.aidl", "package p; enum Enum { FOO = 1, BAR = 2}");
+  io_delegate_.SetFileContents("a/p/Foo.aidl", R"(
+package p;
+import p.Enum;
+parcelable Foo {
+  Enum e = 1;
+})");
+  CaptureStderr();
+  auto options = Options::From("aidl -I a --lang java -o out -h out a/p/Foo.aidl");
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("Invalid value (1) for enum p.Enum"));
+}
+
 TEST_P(AidlTest, DefaultWithEmptyArray) {
   io_delegate_.SetFileContents("a/p/Foo.aidl", "package p; parcelable Foo { p.Bar[] bars = {}; }");
   io_delegate_.SetFileContents("a/p/Bar.aidl", "package p; parcelable Bar { }");
   CaptureStderr();
   auto options =
       Options::From("aidl -I a --lang " + to_string(GetLanguage()) + " -o out -h out a/p/Foo.aidl");
-  EXPECT_EQ(0, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   auto err = GetCapturedStderr();
   EXPECT_EQ("", err);
 }
@@ -3719,7 +4937,7 @@
   CaptureStderr();
   auto options =
       Options::From("aidl --lang " + to_string(GetLanguage()) + " -o out -h out a/p/IFoo.aidl");
-  EXPECT_EQ(1, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   auto err = GetCapturedStderr();
   EXPECT_EQ(
       "ERROR: a/p/IFoo.aidl:3.31-41: Value must be a constant expression but contains reference to "
@@ -3734,7 +4952,7 @@
   io_delegate_.SetFileContents("a/p/Bar.aidl", "package p; enum Bar { FOO, BAR }");
   CaptureStderr();
   auto options = Options::From("aidl -I a --lang ndk -o out -h out a/p/Foo.aidl");
-  EXPECT_EQ(0, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   auto err = GetCapturedStderr();
   EXPECT_EQ("", err);
   string code;
@@ -3748,12 +4966,9 @@
   io_delegate_.SetFileContents("a/p/Foo.aidl", "package p; enum Foo { A = B, B }");
   CaptureStderr();
   auto options = Options::From("aidl -I a --lang ndk -o out -h out a/p/Foo.aidl");
-  EXPECT_EQ(1, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   auto err = GetCapturedStderr();
-  EXPECT_EQ(
-      "ERROR: a/p/Foo.aidl:1.26-28: Found a circular reference: B -> A -> B\n"
-      "ERROR: a/p/Foo.aidl:1.29-31: Found a circular reference: A -> B -> A\n",
-      err);
+  EXPECT_EQ("ERROR: a/p/Foo.aidl:1.26-28: Found a circular reference: B -> A -> B\n", err);
 }
 
 TEST_F(AidlTest, RejectsCircularReferencingConsts) {
@@ -3761,7 +4976,7 @@
                                "package p; parcelable Foo { const int A = A + 1; }");
   CaptureStderr();
   auto options = Options::From("aidl -I a --lang ndk -o out -h out a/p/Foo.aidl");
-  EXPECT_EQ(1, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   auto err = GetCapturedStderr();
   EXPECT_EQ("ERROR: a/p/Foo.aidl:1.42-44: Found a circular reference: A -> A\n", err);
 }
@@ -3774,20 +4989,40 @@
   io_delegate_.SetFileContents("a/p/Baz.aidl", "package p; parcelable Baz { const int A = 1; }");
   CaptureStderr();
   auto options = Options::From("aidl -I a --lang ndk -o out -h out a/p/Foo.aidl");
-  EXPECT_EQ(0, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
+  EXPECT_EQ("", GetCapturedStderr());
+}
+
+TEST_P(AidlTest, CircularReferenceWithFullyQualified) {
+  io_delegate_.SetFileContents("Foo.aidl", "enum Foo { A = Foo.A }");
+  auto options =
+      Options::From("aidl --lang " + to_string(GetLanguage()) + " -I . -o out -h out Foo.aidl");
+  const string err = "ERROR: Foo.aidl:1.15-21: Found a circular reference: Foo.A -> Foo.A\n";
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_EQ(err, GetCapturedStderr());
+}
+
+TEST_P(AidlTest, ConstRefsCanPointToTheSameValue) {
+  io_delegate_.SetFileContents("Foo.aidl", "enum Foo { A = 0 }");
+  // this demonstrates the case that "Foo.A" const-ref node is visited twice by B and C.
+  io_delegate_.SetFileContents("Bar.aidl", "enum Bar { A = Foo.A, B = A, C = A }");
+  auto options =
+      Options::From("aidl --lang " + to_string(GetLanguage()) + " -I . -o out -h out Bar.aidl");
+  CaptureStderr();
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   EXPECT_EQ("", GetCapturedStderr());
 }
 
 TEST_P(AidlTest, UnknownConstReference) {
-  io_delegate_.SetFileContents("Foo.aidl", " parcelable Foo { UnknownType field = UNKNOWN_REF; }");
+  io_delegate_.SetFileContents("Foo.aidl", " parcelable Foo { int field = UNKNOWN_REF; }");
   auto options =
       Options::From("aidl --lang " + to_string(GetLanguage()) + " -o out -h out Foo.aidl");
   const string err =
-      "ERROR: Foo.aidl:1.18-30: Failed to resolve 'UnknownType'\n"
-      "ERROR: Foo.aidl:1.38-50: Can't find UNKNOWN_REF in Foo\n"
-      "ERROR: Foo.aidl:1.38-50: Unknown reference 'UNKNOWN_REF'\n";
+      "ERROR: Foo.aidl:1.30-42: Can't find UNKNOWN_REF in Foo\n"
+      "ERROR: Foo.aidl:1.30-42: Unknown reference 'UNKNOWN_REF'\n";
   CaptureStderr();
-  EXPECT_EQ(1, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ(err, GetCapturedStderr());
 }
 
@@ -3805,7 +5040,7 @@
   auto options = Options::From("aidl --lang " + to_string(GetLanguage()) +
                                " -Weverything -o out -h out p/Foo.aidl");
   CaptureStderr();
-  EXPECT_EQ(0, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_TRUE(compile_aidl(options, io_delegate_));
   EXPECT_EQ("WARNING: p/Foo.aidl:1.1-10: Interface names should start with I. [-Winterface-name]\n",
             GetCapturedStderr());
 }
@@ -3815,7 +5050,7 @@
   auto options = Options::From("aidl --lang " + to_string(GetLanguage()) +
                                " -Weverything -Werror -o out -h out p/Foo.aidl");
   CaptureStderr();
-  EXPECT_EQ(1, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_EQ("ERROR: p/Foo.aidl:1.1-10: Interface names should start with I. [-Winterface-name]\n",
             GetCapturedStderr());
 }
@@ -3829,7 +5064,7 @@
 
   auto options = Options::From({"aidl-cpp", input_file, header_dir, output_file});
   CaptureStderr();
-  EXPECT_EQ(1, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_THAT(
       GetCapturedStderr(),
       testing::StartsWith(
@@ -3852,22 +5087,18 @@
       {{{"/*\n"
          " * Hello, world!\n"
          " */"}},
-       "/**\n"
-       " * Hello, world!\n"
-       " */"},
-      {{{"/* @hide */"}}, "/** @hide */"},
+       "/** Hello, world! */\n"},
+      {{{"/* @hide */"}}, "/** @hide */\n"},
       {{{"/**\n"
          "   @param foo ...\n"
          "*/"}},
-       "/**\n"
-       "   @param foo ...\n"
-       "*/"},
-      {{{"/* @hide */"}, {"/* @hide */"}}, "/* @hide *//** @hide */"},
+       "/** @param foo ... */\n"},
+      {{{"/* @hide */"}, {"/* @hide */"}}, "/* @hide */\n/** @hide */\n"},
       {{{"/* @deprecated first */"}, {"/* @deprecated second */"}},
-       "/* @deprecated first *//** @deprecated second */"},
-      {{{"/* @deprecated */"}, {"/** @param foo */"}}, "/* @deprecated *//** @param foo */"},
+       "/* @deprecated first */\n/** @deprecated second */\n"},
+      {{{"/* @deprecated */"}, {"/** @param foo */"}}, "/* @deprecated */\n/** @param foo */\n"},
       // Line comments are printed as they are
-      {{{"/* @deprecated */"}, {"// line comments\n"}}, "/* @deprecated */// line comments\n"},
+      {{{"/* @deprecated */"}, {"// line comments\n"}}, "/* @deprecated */\n// line comments\n"},
   };
   for (const auto& [input, formatted] : testcases) {
     EXPECT_EQ(formatted, FormatCommentsForJava(input));
@@ -3881,7 +5112,7 @@
                                "}");
   auto options = Options::From("aidl --lang=java IFoo.aidl");
   CaptureStderr();
-  EXPECT_EQ(1, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_THAT(GetCapturedStderr(), HasSubstr("@Hide is not available"));
 }
 
@@ -3889,139 +5120,322 @@
   io_delegate_.SetFileContents(
       "IFoo.aidl",
       "interface IFoo {\n"
-      "  void foo(in @SuppressWarnings(value=\"inout-parameter\") int x);\n"
+      "  void foo(in @SuppressWarnings(value={\"inout-parameter\"}) int x);\n"
       "}");
   auto options = Options::From("aidl --lang=java IFoo.aidl");
   CaptureStderr();
-  EXPECT_EQ(1, aidl::compile_aidl(options, io_delegate_));
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
   EXPECT_THAT(GetCapturedStderr(), HasSubstr("@SuppressWarnings is not available"));
 }
 
+TEST_F(AidlTest, VoidCantBeUsedInMethodParameterType) {
+  io_delegate_.SetFileContents("p/IFoo.aidl", "interface IFoo{ void j(void n);}");
+  auto options = Options::From("aidl --lang=java -o out p/IFoo.aidl");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(options, io_delegate_));
+  EXPECT_THAT(GetCapturedStderr(), HasSubstr("'void' is an invalid type for the parameter 'n'"));
+}
+
+TEST_F(AidlTest, InterfaceVectorIsAvailableAfterTiramisu) {
+  io_delegate_.SetFileContents("p/IFoo.aidl",
+                               "interface IFoo{\n"
+                               "  void foo(in IFoo[] n);\n"
+                               "  void bar(in List<IFoo> n);\n"
+                               "}");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(
+      Options::From("aidl --lang=java --min_sdk_version 30 -o out p/IFoo.aidl"), io_delegate_));
+  auto captured_stderr = GetCapturedStderr();
+  EXPECT_THAT(captured_stderr, HasSubstr("Array of interfaces is available since"));
+  EXPECT_THAT(captured_stderr, HasSubstr("List of interfaces is available since"));
+
+  CaptureStderr();
+  EXPECT_TRUE(
+      compile_aidl(Options::From("aidl --lang=java --min_sdk_version Tiramisu -o out p/IFoo.aidl"),
+                   io_delegate_));
+  EXPECT_EQ(GetCapturedStderr(), "");
+}
+
+TEST_F(AidlTest, PropagateBeforeTiramisu) {
+  io_delegate_.SetFileContents("p/IFoo.aidl",
+                               "interface IFoo{\n"
+                               "  @PropagateAllowBlocking IBinder foo();\n"
+                               "}");
+  CaptureStderr();
+  EXPECT_FALSE(compile_aidl(
+      Options::From("aidl --lang=java --min_sdk_version 30 -o out p/IFoo.aidl"), io_delegate_));
+  auto captured_stderr = GetCapturedStderr();
+  EXPECT_THAT(captured_stderr, HasSubstr("@PropagateAllowBlocking requires"));
+
+  CaptureStderr();
+  EXPECT_TRUE(
+      compile_aidl(Options::From("aidl --lang=java --min_sdk_version Tiramisu -o out p/IFoo.aidl"),
+                   io_delegate_));
+  EXPECT_EQ(GetCapturedStderr(), "");
+}
+
+TEST_F(AidlTest, RustNameOf_PfdFixedArray) {
+  auto pfd = typenames_.MakeResolvedType(AIDL_LOCATION_HERE, "ParcelFileDescriptor", false);
+  ASSERT_TRUE(pfd->MakeArray(FixedSizeArray{
+      std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(AIDL_LOCATION_HERE, "2"))}));
+  ASSERT_TRUE(pfd->MakeArray(FixedSizeArray{
+      std::unique_ptr<AidlConstantValue>(AidlConstantValue::Integral(AIDL_LOCATION_HERE, "3"))}));
+  EXPECT_EQ(
+      rust::RustNameOf(*pfd, typenames_, rust::StorageMode::PARCELABLE_FIELD, rust::Lifetime::NONE),
+      "[[Option<binder::ParcelFileDescriptor>; 3]; 2]");
+  EXPECT_EQ(
+      rust::RustNameOf(*pfd, typenames_, rust::StorageMode::DEFAULT_VALUE, rust::Lifetime::NONE),
+      "[[Option<binder::ParcelFileDescriptor>; 3]; 2]");
+  EXPECT_EQ(
+      rust::RustNameOf(*pfd, typenames_, rust::StorageMode::IN_ARGUMENT, rust::Lifetime::NONE),
+      "&[[binder::ParcelFileDescriptor; 3]; 2]");
+  EXPECT_EQ(rust::RustNameOf(*pfd, typenames_, rust::StorageMode::VALUE, rust::Lifetime::NONE),
+            "[[binder::ParcelFileDescriptor; 3]; 2]");
+}
+
+TEST_F(AidlTest, RustNameOf_PfdDynamicArray) {
+  auto pfd = typenames_.MakeResolvedType(AIDL_LOCATION_HERE, "ParcelFileDescriptor", true);
+  EXPECT_EQ(
+      rust::RustNameOf(*pfd, typenames_, rust::StorageMode::PARCELABLE_FIELD, rust::Lifetime::NONE),
+      "Vec<binder::ParcelFileDescriptor>");
+  EXPECT_EQ(
+      rust::RustNameOf(*pfd, typenames_, rust::StorageMode::DEFAULT_VALUE, rust::Lifetime::NONE),
+      "Vec<Option<binder::ParcelFileDescriptor>>");
+  // we use UNSIZED_ARGUMENT mode for input argument of dynamic array
+  EXPECT_EQ(
+      rust::RustNameOf(*pfd, typenames_, rust::StorageMode::UNSIZED_ARGUMENT, rust::Lifetime::NONE),
+      "&[binder::ParcelFileDescriptor]");
+  EXPECT_EQ(rust::RustNameOf(*pfd, typenames_, rust::StorageMode::VALUE, rust::Lifetime::NONE),
+            "Vec<binder::ParcelFileDescriptor>");
+}
+
 struct TypeParam {
   string kind;
   string literal;
 };
 
 const TypeParam kTypeParams[] = {
-    {"primitive", "int"},   {"primitiveArray", "int[]"},
-    {"String", "String"},   {"StringArray", "String[]"},
-    {"IBinder", "IBinder"}, {"ParcelFileDescriptor", "ParcelFileDescriptor"},
-    {"parcelable", "Foo"},  {"enum", "a.Enum"},
-    {"union", "a.Union"},   {"interface", "a.IBar"},
+    {"primitive", "int"},
+    {"primitiveArray", "int[]"},
+    {"primitiveFixedArray", "int[3]"},
+    {"String", "String"},
+    {"StringArray", "String[]"},
+    {"IBinder", "IBinder"},
+    {"ParcelFileDescriptor", "ParcelFileDescriptor"},
+    {"parcelable", "a.Foo"},
+    {"enum", "a.Enum"},
+    {"union", "a.Union"},
+    {"interface", "a.IBar"},
 };
 
-const std::map<std::string, std::string> kListSupportExpectations = {
-    {"cpp_primitive", "A generic type cannot have any primitive type parameters."},
-    {"java_primitive", "A generic type cannot have any primitive type parameters."},
-    {"ndk_primitive", "A generic type cannot have any primitive type parameters."},
-    {"rust_primitive", "A generic type cannot have any primitive type parameters."},
-    {"cpp_primitiveArray", "List of arrays is not supported."},
-    {"java_primitiveArray", "List of arrays is not supported."},
-    {"ndk_primitiveArray", "List of arrays is not supported."},
-    {"rust_primitiveArray", "List of arrays is not supported."},
-    {"cpp_String", ""},
-    {"java_String", ""},
-    {"ndk_String", ""},
-    {"rust_String", ""},
-    {"cpp_StringArray", "List of arrays is not supported."},
-    {"java_StringArray", "List of arrays is not supported."},
-    {"ndk_StringArray", "List of arrays is not supported."},
-    {"rust_StringArray", "List of arrays is not supported."},
-    {"cpp_IBinder", ""},
-    {"java_IBinder", ""},
-    {"ndk_IBinder", "List<IBinder> is not supported. List in NDK doesn't support IBinder."},
-    {"rust_IBinder", ""},
-    {"cpp_ParcelFileDescriptor", ""},
-    {"java_ParcelFileDescriptor", ""},
-    {"ndk_ParcelFileDescriptor", ""},
-    {"rust_ParcelFileDescriptor", ""},
-    {"cpp_interface", "List<a.IBar> is not supported."},
-    {"java_interface", "List<a.IBar> is not supported."},
-    {"ndk_interface", "List<a.IBar> is not supported."},
-    {"rust_interface", "List<a.IBar> is not supported."},
-    {"cpp_parcelable", ""},
-    {"java_parcelable", ""},
-    {"ndk_parcelable", ""},
-    {"rust_parcelable", ""},
-    {"cpp_enum", "A generic type cannot have any primitive type parameters."},
-    {"java_enum", "A generic type cannot have any primitive type parameters."},
-    {"ndk_enum", "A generic type cannot have any primitive type parameters."},
-    {"rust_enum", "A generic type cannot have any primitive type parameters."},
-    {"cpp_union", ""},
-    {"java_union", ""},
-    {"ndk_union", ""},
-    {"rust_union", ""},
+struct ExpectedResult {
+  string expected_error;
+  string expected_error_for_nullable;
 };
 
-const std::map<std::string, std::string> kArraySupportExpectations = {
-    {"cpp_primitive", ""},
-    {"java_primitive", ""},
-    {"ndk_primitive", ""},
-    {"rust_primitive", ""},
-    {"cpp_primitiveArray", "Can only have one dimensional arrays."},
-    {"java_primitiveArray", "Can only have one dimensional arrays."},
-    {"ndk_primitiveArray", "Can only have one dimensional arrays."},
-    {"rust_primitiveArray", "Can only have one dimensional arrays."},
-    {"cpp_String", ""},
-    {"java_String", ""},
-    {"ndk_String", ""},
-    {"rust_String", ""},
-    {"cpp_StringArray", "Can only have one dimensional arrays."},
-    {"java_StringArray", "Can only have one dimensional arrays."},
-    {"ndk_StringArray", "Can only have one dimensional arrays."},
-    {"rust_StringArray", "Can only have one dimensional arrays."},
-    {"cpp_IBinder", ""},
-    {"java_IBinder", ""},
-    {"ndk_IBinder", "The ndk backend does not support array of IBinder"},
-    {"rust_IBinder", "The rust backend does not support array of IBinder"},
-    {"cpp_ParcelFileDescriptor", ""},
-    {"java_ParcelFileDescriptor", ""},
-    {"ndk_ParcelFileDescriptor", ""},
-    {"rust_ParcelFileDescriptor", ""},
-    {"cpp_interface", "Binder type cannot be an array"},
-    {"java_interface", "Binder type cannot be an array"},
-    {"ndk_interface", "Binder type cannot be an array"},
-    {"rust_interface", "Binder type cannot be an array"},
-    {"cpp_parcelable", ""},
-    {"java_parcelable", ""},
-    {"ndk_parcelable", ""},
-    {"rust_parcelable", ""},
-    {"cpp_enum", ""},
-    {"java_enum", ""},
-    {"ndk_enum", ""},
-    {"rust_enum", ""},
-    {"cpp_union", ""},
-    {"java_union", ""},
-    {"ndk_union", ""},
-    {"rust_union", ""},
+const std::map<std::string, ExpectedResult> kListSupportExpectations = {
+    {"cpp_primitive", {"A generic type cannot", "A generic type cannot"}},
+    {"java_primitive", {"A generic type cannot", "A generic type cannot"}},
+    {"ndk_primitive", {"A generic type cannot", "A generic type cannot"}},
+    {"rust_primitive", {"A generic type cannot", "A generic type cannot"}},
+    {"cpp_primitiveArray", {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"java_primitiveArray", {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"ndk_primitiveArray", {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"rust_primitiveArray", {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"cpp_primitiveFixedArray",
+     {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"java_primitiveFixedArray",
+     {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"ndk_primitiveFixedArray",
+     {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"rust_primitiveFixedArray",
+     {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"cpp_String", {"", ""}},
+    {"java_String", {"", ""}},
+    {"ndk_String", {"", ""}},
+    {"rust_String", {"", ""}},
+    {"cpp_StringArray", {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"java_StringArray", {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"ndk_StringArray", {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"rust_StringArray", {"List of arrays is not supported", "List of arrays is not supported"}},
+    {"cpp_IBinder", {"", ""}},
+    {"java_IBinder", {"", ""}},
+    {"ndk_IBinder", {"", ""}},
+    {"rust_IBinder", {"", ""}},
+    {"cpp_ParcelFileDescriptor", {"", ""}},
+    {"java_ParcelFileDescriptor", {"", ""}},
+    {"ndk_ParcelFileDescriptor", {"", ""}},
+    {"rust_ParcelFileDescriptor", {"", ""}},
+    {"cpp_interface", {"", ""}},
+    {"java_interface", {"", ""}},
+    {"ndk_interface", {"", ""}},
+    {"rust_interface", {"", ""}},
+    {"cpp_parcelable", {"", ""}},
+    {"java_parcelable", {"", ""}},
+    {"ndk_parcelable", {"", ""}},
+    {"rust_parcelable", {"", ""}},
+    {"cpp_enum", {"A generic type cannot", "A generic type cannot"}},
+    {"java_enum", {"A generic type cannot", "A generic type cannot"}},
+    {"ndk_enum", {"A generic type cannot", "A generic type cannot"}},
+    {"rust_enum", {"A generic type cannot", "A generic type cannot"}},
+    {"cpp_union", {"", ""}},
+    {"java_union", {"", ""}},
+    {"ndk_union", {"", ""}},
+    {"rust_union", {"", ""}},
 };
 
-class AidlTypeParamTest : public testing::TestWithParam<std::tuple<Options::Language, TypeParam>> {
+const std::map<std::string, ExpectedResult> kArraySupportExpectations = {
+    {"cpp_primitive", {"", ""}},
+    {"java_primitive", {"", ""}},
+    {"ndk_primitive", {"", ""}},
+    {"rust_primitive", {"", ""}},
+    {"cpp_primitiveArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"java_primitiveArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"ndk_primitiveArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"rust_primitiveArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"cpp_primitiveFixedArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"java_primitiveFixedArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"ndk_primitiveFixedArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"rust_primitiveFixedArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"cpp_String", {"", ""}},
+    {"java_String", {"", ""}},
+    {"ndk_String", {"", ""}},
+    {"rust_String", {"", ""}},
+    {"cpp_StringArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"java_StringArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"ndk_StringArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"rust_StringArray",
+     {"Multi-dimensional arrays must be fixed size.",
+      "Multi-dimensional arrays must be fixed size."}},
+    {"cpp_IBinder", {"", ""}},
+    {"java_IBinder", {"", ""}},
+    {"ndk_IBinder", {"", ""}},
+    {"rust_IBinder", {"", ""}},
+    {"cpp_ParcelFileDescriptor", {"", ""}},
+    {"java_ParcelFileDescriptor", {"", ""}},
+    {"ndk_ParcelFileDescriptor", {"", ""}},
+    {"rust_ParcelFileDescriptor", {"", ""}},
+    {"cpp_interface", {"", ""}},
+    {"java_interface", {"", ""}},
+    {"ndk_interface", {"", ""}},
+    {"rust_interface", {"", ""}},
+    {"cpp_parcelable", {"", ""}},
+    {"java_parcelable", {"", ""}},
+    {"ndk_parcelable", {"", ""}},
+    {"rust_parcelable", {"", ""}},
+    {"cpp_enum", {"", ""}},
+    {"java_enum", {"", ""}},
+    {"ndk_enum", {"", ""}},
+    {"rust_enum", {"", ""}},
+    {"cpp_union", {"", ""}},
+    {"java_union", {"", ""}},
+    {"ndk_union", {"", ""}},
+    {"rust_union", {"", ""}},
+};
+
+const std::map<std::string, ExpectedResult> kFieldSupportExpectations = {
+    {"cpp_primitive", {"", "cannot get nullable annotation"}},
+    {"java_primitive", {"", "cannot get nullable annotation"}},
+    {"ndk_primitive", {"", "cannot get nullable annotation"}},
+    {"rust_primitive", {"", "cannot get nullable annotation"}},
+    {"cpp_primitiveArray", {"", ""}},
+    {"java_primitiveArray", {"", ""}},
+    {"ndk_primitiveArray", {"", ""}},
+    {"rust_primitiveArray", {"", ""}},
+    {"cpp_primitiveFixedArray", {"", ""}},
+    {"java_primitiveFixedArray", {"", ""}},
+    {"ndk_primitiveFixedArray", {"", ""}},
+    {"rust_primitiveFixedArray", {"", ""}},
+    {"cpp_String", {"", ""}},
+    {"java_String", {"", ""}},
+    {"ndk_String", {"", ""}},
+    {"rust_String", {"", ""}},
+    {"cpp_StringArray", {"", ""}},
+    {"java_StringArray", {"", ""}},
+    {"ndk_StringArray", {"", ""}},
+    {"rust_StringArray", {"", ""}},
+    {"cpp_IBinder", {"", ""}},
+    {"java_IBinder", {"", ""}},
+    {"ndk_IBinder", {"", ""}},
+    {"rust_IBinder", {"", ""}},
+    {"cpp_ParcelFileDescriptor", {"", ""}},
+    {"java_ParcelFileDescriptor", {"", ""}},
+    {"ndk_ParcelFileDescriptor", {"", ""}},
+    {"rust_ParcelFileDescriptor", {"", ""}},
+    {"cpp_interface", {"", ""}},
+    {"java_interface", {"", ""}},
+    {"ndk_interface", {"", ""}},
+    {"rust_interface", {"", ""}},
+    {"cpp_parcelable", {"", ""}},
+    {"java_parcelable", {"", ""}},
+    {"ndk_parcelable", {"", ""}},
+    {"rust_parcelable", {"", ""}},
+    {"cpp_enum", {"", "cannot get nullable annotation"}},
+    {"java_enum", {"", "cannot get nullable annotation"}},
+    {"ndk_enum", {"", "cannot get nullable annotation"}},
+    {"rust_enum", {"", "cannot get nullable annotation"}},
+    {"cpp_union", {"", ""}},
+    {"java_union", {"", ""}},
+    {"ndk_union", {"", ""}},
+    {"rust_union", {"", ""}},
+};
+
+class AidlTypeParamTest
+    : public testing::TestWithParam<std::tuple<Options::Language, TypeParam, bool>> {
  public:
   void Run(const std::string& generic_type_decl,
-           const std::map<std::string, std::string>& expectations) {
+           const std::map<std::string, ExpectedResult>& expectations) {
     const auto& param = GetParam();
     const auto& lang = to_string(std::get<0>(param));
     const auto& kind = std::get<1>(param).kind;
+    const bool nullable = std::get<2>(param);
 
     FakeIoDelegate io;
     io.SetFileContents("a/IBar.aidl", "package a; interface IBar { }");
     io.SetFileContents("a/Enum.aidl", "package a; enum Enum { A }");
     io.SetFileContents("a/Union.aidl", "package a; union Union { int a; }");
+    io.SetFileContents("a/Foo.aidl", "package a; parcelable Foo { int a; }");
     std::string decl = fmt::format(generic_type_decl, std::get<1>(param).literal);
-    io.SetFileContents("a/Foo.aidl", "package a; parcelable Foo { " + decl + " f; }");
+    if (nullable) {
+      decl = "@nullable " + decl;
+    }
+    io.SetFileContents("a/Target.aidl", "package a; parcelable Target { " + decl + " f; }");
 
-    const auto options =
-        Options::From(fmt::format("aidl -I . --lang={} a/Foo.aidl -o out -h out", lang));
+    const auto options = Options::From(fmt::format(
+        "aidl -I . --min_sdk_version current --lang={} a/Target.aidl -o out -h out", lang));
     CaptureStderr();
     compile_aidl(options, io);
     auto it = expectations.find(lang + "_" + kind);
-    EXPECT_TRUE(it != expectations.end());
+    ASSERT_TRUE(it != expectations.end()) << "missing expectation for " << lang << "_" << kind;
     const string err = GetCapturedStderr();
-    if (it->second.empty()) {
+    const string expected_error =
+        nullable ? it->second.expected_error_for_nullable : it->second.expected_error;
+    if (expected_error.empty()) {
       EXPECT_EQ("", err);
     } else {
-      EXPECT_THAT(err, testing::HasSubstr(it->second));
+      EXPECT_THAT(err, testing::HasSubstr(expected_error));
     }
   }
 };
@@ -4030,9 +5444,13 @@
     AidlTestSuite, AidlTypeParamTest,
     testing::Combine(testing::Values(Options::Language::CPP, Options::Language::JAVA,
                                      Options::Language::NDK, Options::Language::RUST),
-                     testing::ValuesIn(kTypeParams)),
-    [](const testing::TestParamInfo<std::tuple<Options::Language, TypeParam>>& info) {
-      return to_string(std::get<0>(info.param)) + "_" + std::get<1>(info.param).kind;
+                     testing::ValuesIn(kTypeParams), testing::Values(true, false)),
+    [](const testing::TestParamInfo<std::tuple<Options::Language, TypeParam, bool>>& info) {
+      string name = to_string(std::get<0>(info.param)) + "_" + std::get<1>(info.param).kind;
+      if (std::get<2>(info.param)) {
+        name += "_nullable";
+      }
+      return name;
     });
 
 TEST_P(AidlTypeParamTest, ListSupportedTypes) {
@@ -4043,5 +5461,9 @@
   Run("{}[]", kArraySupportExpectations);
 }
 
+TEST_P(AidlTypeParamTest, ParcelableFieldTypes) {
+  Run("{}", kFieldSupportExpectations);
+}
+
 }  // namespace aidl
 }  // namespace android
diff --git a/ast_cpp.cpp b/ast_cpp.cpp
deleted file mode 100644
index 39af24c..0000000
--- a/ast_cpp.cpp
+++ /dev/null
@@ -1,499 +0,0 @@
-/*
- * Copyright (C) 2015, 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.
- */
-
-#include "ast_cpp.h"
-
-#include <algorithm>
-
-#include <android-base/strings.h>
-
-#include "code_writer.h"
-#include "logging.h"
-
-using std::string;
-using std::unique_ptr;
-using std::vector;
-
-namespace android {
-namespace aidl {
-namespace cpp {
-
-std::string AstNode::ToString() {
-  std::string str;
-  Write(CodeWriter::ForString(&str).get());
-  return str;
-}
-
-LiteralDecl::LiteralDecl(const std::string& expression) : expression_(expression) {}
-
-void LiteralDecl::Write(CodeWriter* to) const {
-  to->Write("%s", expression_.c_str());
-}
-
-ClassDecl::ClassDecl(const std::string& name, const std::string& parent,
-                     const std::vector<std::string>& template_params, const std::string& attributes)
-    : name_(name), parent_(parent), attributes_(attributes), template_params_(template_params) {}
-
-ClassDecl::ClassDecl(const std::string& name, const std::string& parent,
-                     const std::vector<std::string>& template_params,
-                     std::vector<unique_ptr<Declaration>> public_members,
-                     std::vector<unique_ptr<Declaration>> private_members,
-                     const std::string& attributes)
-    : name_(name),
-      parent_(parent),
-      attributes_(attributes),
-      template_params_(template_params),
-      public_members_(std::move(public_members)),
-      private_members_(std::move(private_members)) {}
-
-void ClassDecl::Write(CodeWriter* to) const {
-  if (!template_params_.empty())
-    to->Write("template <typename %s>\n", base::Join(template_params_, ", typename ").c_str());
-
-  to->Write("class");
-  if (!attributes_.empty()) {
-    to->Write(" %s", attributes_.c_str());
-  }
-  to->Write(" %s ", name_.c_str());
-
-  if (parent_.length() > 0) to->Write(": public %s ", parent_.c_str());
-
-  to->Write("{\n");
-
-  if (!public_members_.empty()) to->Write("public:\n");
-
-  to->Indent();
-  for (const auto& dec : public_members_)
-    dec->Write(to);
-  to->Dedent();
-
-  if (!private_members_.empty()) to->Write("private:\n");
-
-  to->Indent();
-  for (const auto& dec : private_members_)
-    dec->Write(to);
-  to->Dedent();
-
-  to->Write("};  // class %s\n", name_.c_str());
-}
-
-void ClassDecl::AddPublic(std::unique_ptr<Declaration> member) {
-  public_members_.push_back(std::move(member));
-}
-
-void ClassDecl::AddPrivate(std::unique_ptr<Declaration> member) {
-  private_members_.push_back(std::move(member));
-}
-
-Enum::EnumField::EnumField(const string& k, const string& v, const string& a)
-    : key(k), value(v), attribute(a) {}
-
-Enum::Enum(const string& name, const string& base_type, bool is_class,
-           const std::string& attributes)
-    : enum_name_(name), underlying_type_(base_type), attributes_(attributes), is_class_(is_class) {}
-
-void Enum::Write(CodeWriter* to) const {
-  to->Write("enum ");
-  if (is_class_) {
-    to->Write("class ");
-  }
-  if (!attributes_.empty()) {
-    to->Write("%s ", attributes_.c_str());
-  }
-  if (underlying_type_.empty()) {
-    to->Write("%s {\n", enum_name_.c_str());
-  } else {
-    to->Write("%s : %s {\n", enum_name_.c_str(), underlying_type_.c_str());
-  }
-  to->Indent();
-  for (const auto& field : fields_) {
-    to->Write("%s", field.key.c_str());
-    if (!field.attribute.empty()) {
-      to->Write(" %s", field.attribute.c_str());
-    }
-    if (!field.value.empty()) {
-      to->Write(" = %s", field.value.c_str());
-    }
-    to->Write(",\n");
-  }
-  to->Dedent();
-  to->Write("};\n");
-}
-
-void Enum::AddValue(const string& key, const string& value, const string& attribute) {
-  fields_.emplace_back(key, value, attribute);
-}
-
-ArgList::ArgList(const std::string& single_argument)
-    : ArgList(vector<string>{single_argument}) {}
-
-ArgList::ArgList(const std::vector<std::string>& arg_list) {
-  for (const auto& s : arg_list) {
-    arguments_.emplace_back(new LiteralExpression(s));
-  }
-}
-
-ArgList::ArgList(std::vector<std::unique_ptr<AstNode>> arg_list)
-    : arguments_(std::move(arg_list)) {}
-
-ArgList::ArgList(ArgList&& arg_list) noexcept : arguments_(std::move(arg_list.arguments_)) {}
-
-void ArgList::Write(CodeWriter* to) const {
-  to->Write("(");
-  bool is_first = true;
-  for (const auto& s : arguments_) {
-    if (!is_first) { to->Write(", "); }
-    is_first = false;
-    s->Write(to);
-  }
-  to->Write(")");
-}
-
-ConstructorDecl::ConstructorDecl(
-    const std::string& name,
-    ArgList&& arg_list)
-    : ConstructorDecl(name, std::move(arg_list), 0u) {}
-
-ConstructorDecl::ConstructorDecl(
-    const std::string& name,
-    ArgList&& arg_list,
-    uint32_t modifiers)
-    : name_(name),
-      arguments_(std::move(arg_list)),
-      modifiers_(modifiers) {}
-
-void ConstructorDecl::Write(CodeWriter* to) const {
-  if (modifiers_ & Modifiers::IS_VIRTUAL)
-    to->Write("virtual ");
-
-  if (modifiers_ & Modifiers::IS_EXPLICIT)
-    to->Write("explicit ");
-
-  to->Write("%s", name_.c_str());
-
-  arguments_.Write(to);
-
-  if (modifiers_ & Modifiers::IS_DEFAULT)
-    to->Write(" = default");
-
-  to->Write(";\n");
-}
-
-MacroDecl::MacroDecl(const std::string& name, ArgList&& arg_list)
-    : name_(name),
-      arguments_(std::move(arg_list)) {}
-
-void MacroDecl::Write(CodeWriter* to) const {
-  to->Write("%s", name_.c_str());
-  arguments_.Write(to);
-  to->Write("\n");
-}
-
-MethodDecl::MethodDecl(const std::string& return_type, const std::string& name, ArgList&& arg_list,
-                       const std::string& attributes)
-    : MethodDecl(return_type, name, std::move(arg_list), 0u, attributes) {}
-
-MethodDecl::MethodDecl(const std::string& return_type, const std::string& name, ArgList&& arg_list,
-                       uint32_t modifiers, const std::string& attributes)
-    : return_type_(return_type),
-      name_(name),
-      attributes_(attributes),
-      arguments_(std::move(arg_list)),
-      is_const_(modifiers & IS_CONST),
-      is_virtual_(modifiers & IS_VIRTUAL),
-      is_override_(modifiers & IS_OVERRIDE),
-      is_pure_virtual_(modifiers & IS_PURE_VIRTUAL),
-      is_static_(modifiers & IS_STATIC),
-      is_final_(modifiers & IS_FINAL) {}
-
-void MethodDecl::Write(CodeWriter* to) const {
-  if (is_virtual_)
-    to->Write("virtual ");
-
-  if (is_static_)
-    to->Write("static ");
-
-  to->Write("%s %s", return_type_.c_str(), name_.c_str());
-
-  arguments_.Write(to);
-
-  if (is_const_)
-    to->Write(" const");
-
-  if (is_override_)
-    to->Write(" override");
-
-  if (is_final_) to->Write(" final");
-
-  if (!attributes_.empty()) to->Write(" %s", attributes_.c_str());
-
-  if (is_pure_virtual_)
-    to->Write(" = 0");
-
-  to->Write(";\n");
-}
-
-void StatementBlock::AddStatement(unique_ptr<AstNode> statement) {
-  statements_.push_back(std::move(statement));
-}
-
-void StatementBlock::AddStatement(AstNode* statement) {
-  statements_.emplace_back(statement);
-}
-
-void StatementBlock::AddLiteral(const std::string& expression_str,
-                                bool add_semicolon) {
-  if (add_semicolon) {
-    statements_.push_back(unique_ptr<AstNode>(new Statement(expression_str)));
-  } else {
-    statements_.push_back(unique_ptr<AstNode>(
-        new LiteralExpression(expression_str)));
-  }
-}
-
-void StatementBlock::Write(CodeWriter* to) const {
-  to->Write("{\n");
-  to->Indent();
-  for (const auto& statement : statements_) {
-    statement->Write(to);
-  }
-  to->Dedent();
-  to->Write("}\n");
-}
-
-ConstructorImpl::ConstructorImpl(const string& class_name,
-                                 ArgList&& arg_list,
-                                 const vector<string>& initializer_list)
-      : class_name_(class_name),
-        arguments_(std::move(arg_list)),
-        initializer_list_(initializer_list) {}
-
-StatementBlock* ConstructorImpl::GetStatementBlock() {
-  return &body_;
-}
-
-void ConstructorImpl::Write(CodeWriter* to) const {
-  to->Write("%s::%s", class_name_.c_str(), class_name_.c_str());
-  arguments_.Write(to);
-  to->Write("\n");
-
-  bool is_first = true;
-  for (const string& i : initializer_list_) {
-    if (is_first) {
-      to->Write("    : %s", i.c_str());
-    } else {
-      to->Write(",\n      %s", i.c_str());
-    }
-    is_first = false;
-  }
-
-  body_.Write(to);
-}
-
-MethodImpl::MethodImpl(const string& return_type, const string& class_name,
-                       const string& method_name, const std::vector<std::string>& template_params,
-                       ArgList&& arg_list, bool is_const_method)
-    : return_type_(return_type),
-      method_name_(method_name),
-      arguments_(std::move(arg_list)),
-      is_const_method_(is_const_method),
-      template_params_(template_params) {
-  if (!class_name.empty()) {
-    if (!template_params.empty()) {
-      method_name_ = class_name + "<" + base::Join(template_params, ",") + ">::" + method_name;
-    } else {
-      method_name_ = class_name + "::" + method_name;
-    }
-  }
-}
-
-StatementBlock* MethodImpl::GetStatementBlock() {
-  return &statements_;
-}
-
-void MethodImpl::Write(CodeWriter* to) const {
-  if (!template_params_.empty())
-    to->Write("template <typename %s>\n", base::Join(template_params_, ", typename ").c_str());
-  to->Write("%s %s", return_type_.c_str(), method_name_.c_str());
-  arguments_.Write(to);
-  to->Write("%s ", (is_const_method_) ? " const" : "");
-  statements_.Write(to);
-}
-
-SwitchStatement::SwitchStatement(const std::string& expression)
-    : switch_expression_(expression) {}
-
-StatementBlock* SwitchStatement::AddCase(const string& value_expression) {
-  auto it = std::find(case_values_.begin(), case_values_.end(), value_expression);
-  if (it != case_values_.end()) {
-    AIDL_ERROR(value_expression) << "Duplicate switch case labels";
-    return nullptr;
-  }
-  StatementBlock* ret = new StatementBlock();
-  case_values_.push_back(value_expression);
-  case_logic_.push_back(unique_ptr<StatementBlock>{ret});
-  return ret;
-}
-
-void SwitchStatement::Write(CodeWriter* to) const {
-  to->Write("switch (%s) {\n", switch_expression_.c_str());
-  for (size_t i = 0; i < case_values_.size(); ++i) {
-    const string& case_value = case_values_[i];
-    const unique_ptr<StatementBlock>& statements = case_logic_[i];
-    if (case_value.empty()) {
-      to->Write("default:\n");
-    } else {
-      to->Write("case %s:\n", case_value.c_str());
-    }
-    statements->Write(to);
-    to->Write("break;\n");
-  }
-  to->Write("}\n");
-}
-
-
-Assignment::Assignment(const std::string& left, const std::string& right)
-    : Assignment(left, new LiteralExpression{right}) {}
-
-Assignment::Assignment(const std::string& left, AstNode* right)
-    : lhs_(left),
-      rhs_(right) {}
-
-void Assignment::Write(CodeWriter* to) const {
-  to->Write("%s = ", lhs_.c_str());
-  rhs_->Write(to);
-  to->Write(";\n");
-}
-
-MethodCall::MethodCall(const std::string& method_name,
-                       const std::string& single_argument)
-    : MethodCall(method_name, ArgList{single_argument}) {}
-
-MethodCall::MethodCall(const std::string& method_name,
-                       ArgList&& arg_list)
-    : method_name_(method_name),
-      arguments_{std::move(arg_list)} {}
-
-void MethodCall::Write(CodeWriter* to) const {
-  to->Write("%s", method_name_.c_str());
-  arguments_.Write(to);
-}
-
-IfStatement::IfStatement(AstNode* expression, bool invert_expression)
-    : expression_(expression),
-      invert_expression_(invert_expression) {}
-
-void IfStatement::Write(CodeWriter* to) const {
-  to->Write("if (%s", (invert_expression_) ? "!(" : "");
-  expression_->Write(to);
-  to->Write(")%s ", (invert_expression_) ? ")" : "");
-  on_true_.Write(to);
-
-  if (!on_false_.Empty()) {
-    to->Write("else ");
-    on_false_.Write(to);
-  }
-}
-
-Statement::Statement(unique_ptr<AstNode> expression)
-    : expression_(std::move(expression)) {}
-
-Statement::Statement(AstNode* expression) : expression_(expression) {}
-
-Statement::Statement(const string& expression)
-    : expression_(new LiteralExpression(expression)) {}
-
-void Statement::Write(CodeWriter* to) const {
-  expression_->Write(to);
-  to->Write(";\n");
-}
-
-Comparison::Comparison(AstNode* lhs, const string& comparison, AstNode* rhs)
-    : left_(lhs),
-      right_(rhs),
-      operator_(comparison) {}
-
-void Comparison::Write(CodeWriter* to) const {
-  to->Write("((");
-  left_->Write(to);
-  to->Write(") %s (", operator_.c_str());
-  right_->Write(to);
-  to->Write("))");
-}
-
-LiteralExpression::LiteralExpression(const std::string& expression)
-    : expression_(expression) {}
-
-void LiteralExpression::Write(CodeWriter* to) const {
-  to->Write("%s", expression_.c_str());
-}
-
-CppNamespace::CppNamespace(const std::string& name,
-                           std::vector<unique_ptr<Declaration>> declarations)
-    : declarations_(std::move(declarations)),
-      name_(name) {}
-
-CppNamespace::CppNamespace(const std::string& name,
-                           unique_ptr<Declaration> declaration)
-    : name_(name) {
-  declarations_.push_back(std::move(declaration));
-}
-CppNamespace::CppNamespace(const std::string& name)
-    : name_(name) {}
-
-void CppNamespace::Write(CodeWriter* to) const {
-  to->Write("namespace %s {\n\n", name_.c_str());
-
-  for (const auto& dec : declarations_) {
-    dec->Write(to);
-    to->Write("\n");
-  }
-
-  to->Write("}  // namespace %s\n", name_.c_str());
-}
-
-Document::Document(const std::vector<std::string>& include_list,
-                   std::vector<unique_ptr<Declaration>> declarations)
-    : include_list_(include_list), declarations_(std::move(declarations)) {}
-
-void Document::Write(CodeWriter* to) const {
-  for (const auto& include : include_list_) {
-    to->Write("#include <%s>\n", include.c_str());
-  }
-  to->Write("\n");
-
-  for (const auto& declaration : declarations_) {
-    declaration->Write(to);
-  }
-}
-
-CppHeader::CppHeader(const std::vector<std::string>& include_list,
-                     std::vector<std::unique_ptr<Declaration>> declarations)
-    : Document(include_list, std::move(declarations)) {}
-
-void CppHeader::Write(CodeWriter* to) const {
-  to->Write("#pragma once\n\n");
-
-  Document::Write(to);
-}
-
-CppSource::CppSource(const std::vector<std::string>& include_list,
-                     std::vector<std::unique_ptr<Declaration>> declarations)
-    : Document(include_list, std::move(declarations)) {}
-
-}  // namespace cpp
-}  // namespace aidl
-}  // namespace android
diff --git a/ast_cpp.h b/ast_cpp.h
deleted file mode 100644
index ca5105c..0000000
--- a/ast_cpp.h
+++ /dev/null
@@ -1,394 +0,0 @@
-/*
- * Copyright (C) 2015, 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.
- */
-
-#pragma once
-
-#include <memory>
-#include <string>
-#include <vector>
-
-namespace android {
-namespace aidl {
-class CodeWriter;
-}  // namespace aidl
-}  // namespace android
-
-namespace android {
-namespace aidl {
-namespace cpp {
-
-class AstNode {
- public:
-  AstNode() = default;
-  virtual ~AstNode() = default;
-
-  // All ast nodes are non-copyable and non-movable
-  AstNode(const AstNode&) = delete;
-  AstNode(AstNode&&) = delete;
-  AstNode& operator=(const AstNode&) = delete;
-  AstNode& operator=(AstNode&&) = delete;
-
-  virtual void Write(CodeWriter* to) const = 0;
-  std::string ToString();
-};  // class AstNode
-
-class Declaration : public AstNode {
- public:
-  Declaration() = default;
-  virtual ~Declaration() = default;
-};  // class Declaration
-
-class LiteralDecl : public Declaration {
- public:
-  explicit LiteralDecl(const std::string& expression);
-  ~LiteralDecl() = default;
-  void Write(CodeWriter* to) const override;
-
- private:
-  const std::string expression_;
-};  // class LiteralDecl
-
-class ClassDecl : public Declaration {
- public:
-  ClassDecl(const std::string& name, const std::string& parent,
-            const std::vector<std::string>& template_params, const std::string& attributes = "");
-  ClassDecl(const std::string& name, const std::string& parent,
-            const std::vector<std::string>& template_params,
-            std::vector<std::unique_ptr<Declaration>> public_members,
-            std::vector<std::unique_ptr<Declaration>> private_members,
-            const std::string& attributes = "");
-  virtual ~ClassDecl() = default;
-
-  void Write(CodeWriter* to) const override;
-
-  void AddPublic(std::unique_ptr<Declaration> member);
-  void AddPrivate(std::unique_ptr<Declaration> member);
-
- private:
-  std::string name_;
-  std::string parent_;
-  std::string attributes_;
-  std::vector<std::string> template_params_;
-  std::vector<std::unique_ptr<Declaration>> public_members_;
-  std::vector<std::unique_ptr<Declaration>> private_members_;
-};  // class ClassDecl
-
-class Enum : public Declaration {
- public:
-  Enum(const std::string& name, const std::string& base_type, bool is_class,
-       const std::string& attributes = "");
-  virtual ~Enum() = default;
-
-  bool HasValues() const { return !fields_.empty(); }
-  void Write(CodeWriter* to) const override;
-
-  void AddValue(const std::string& key, const std::string& value,
-                const std::string& attribute = "");
-
- private:
-  struct EnumField {
-    EnumField(const std::string& k, const std::string& v, const std::string& a);
-    const std::string key;
-    const std::string value;
-    const std::string attribute;
-  };
-
-  std::string enum_name_;
-  std::string underlying_type_;
-  std::string attributes_;
-  bool is_class_;
-  std::vector<EnumField> fields_;
-};  // class Enum
-
-class ArgList : public AstNode {
- public:
-  ArgList() = default;
-  explicit ArgList(const std::string& single_argument);
-  explicit ArgList(const std::vector<std::string>& arg_list);
-  explicit ArgList(std::vector<std::unique_ptr<AstNode>> arg_list);
-  ArgList(ArgList&& arg_list) noexcept;
-  virtual ~ArgList() = default;
-
-  void Write(CodeWriter* to) const override;
-
- private:
-  std::vector<std::unique_ptr<AstNode>> arguments_;
-};  // class ArgList
-
-class ConstructorDecl : public Declaration {
- public:
-  enum Modifiers {
-    IS_VIRTUAL = 1 << 0,
-    IS_DEFAULT = 1 << 1,
-    IS_EXPLICIT = 1 << 2,
-  };
-
-  ConstructorDecl(const std::string& name,
-                  ArgList&& arg_list);
-  ConstructorDecl(const std::string& name,
-                  ArgList&& arg_list,
-                  uint32_t modifiers);
-
-  virtual ~ConstructorDecl() = default;
-
-  void Write(CodeWriter* to) const override;
-
- private:
-  const std::string name_;
-  const ArgList arguments_;
-  const uint32_t modifiers_;
-};  // class ConstructorDecl
-
-class MacroDecl : public Declaration {
- public:
-  MacroDecl(const std::string& name, ArgList&& arg_list);
-  virtual ~MacroDecl() = default;
-
-  void Write(CodeWriter* to) const override;
-
- private:
-  const std::string name_;
-  const ArgList arguments_;
-};  // class MacroDecl
-
-class MethodDecl : public Declaration {
- public:
-  enum Modifiers {
-    IS_CONST = 1 << 0,
-    IS_VIRTUAL = 1 << 1,
-    IS_OVERRIDE = 1 << 2,
-    IS_PURE_VIRTUAL = 1 << 3,
-    IS_STATIC = 1 << 4,
-    IS_FINAL = 1 << 5,
-  };
-
-  MethodDecl(const std::string& return_type, const std::string& name, ArgList&& arg_list,
-             const std::string& attributes = "");
-  MethodDecl(const std::string& return_type, const std::string& name, ArgList&& arg_list,
-             uint32_t modifiers, const std::string& attributes = "");
-  virtual ~MethodDecl() = default;
-
-  void Write(CodeWriter* to) const override;
-
- private:
-  const std::string return_type_;
-  const std::string name_;
-  const std::string attributes_;
-  const ArgList arguments_;
-  bool is_const_ = false;
-  bool is_virtual_ = false;
-  bool is_override_ = false;
-  bool is_pure_virtual_ = false;
-  bool is_static_ = true;
-  bool is_final_ = false;
-};  // class MethodDecl
-
-class StatementBlock : public Declaration {
- public:
-  StatementBlock() = default;
-  virtual ~StatementBlock() = default;
-
-  void AddStatement(std::unique_ptr<AstNode> statement);
-  void AddStatement(AstNode* statement);  // Takes ownership
-  void AddLiteral(const std::string& expression, bool add_semicolon = true);
-  bool Empty() const { return statements_.empty(); }
-
-  void Write(CodeWriter* to) const override;
-
- private:
-  std::vector<std::unique_ptr<AstNode>> statements_;
-};  // class StatementBlock
-
-class ConstructorImpl : public Declaration {
- public:
-  ConstructorImpl(const std::string& class_name,
-                  ArgList&& arg_list,
-                  const std::vector<std::string>& initializer_list);
-  virtual ~ConstructorImpl() = default;
-
-  // ConstructorImpl retains ownership of the statement block.
-  StatementBlock* GetStatementBlock();
-
-  void Write(CodeWriter* to) const override;
-
- private:
-  std::string class_name_;
-  ArgList arguments_;
-  std::vector<std::string> initializer_list_;
-  StatementBlock body_;
-};  // class ConstructorImpl
-
-class MethodImpl : public Declaration {
- public:
-  // Passing an empty class name causes the method to be declared as a normal
-  // function (ie. no ClassName:: qualifier).
-  MethodImpl(const std::string& return_type, const std::string& class_name,
-             const std::string& method_name, const std::vector<std::string>& template_params,
-             ArgList&& arg_list, bool is_const_method = false);
-  virtual ~MethodImpl() = default;
-
-  // MethodImpl retains ownership of the statement block.
-  StatementBlock* GetStatementBlock();
-
-  void Write(CodeWriter* to) const override;
-
- private:
-  std::string return_type_;
-  std::string method_name_;
-  const ArgList arguments_;
-  StatementBlock statements_;
-  bool is_const_method_ = false;
-  std::vector<std::string> template_params_;
-};  // class MethodImpl
-
-class SwitchStatement : public AstNode {
- public:
-  explicit SwitchStatement(const std::string& expression);
-  virtual ~SwitchStatement() = default;
-
-  // Add a case statement and return a pointer code block corresponding
-  // to the case.  The switch statement will add a break statement
-  // after the code block by default to prevent accidental fall-through.
-  // Returns nullptr on duplicate value expressions (by strcmp, not value
-  // equivalence).
-  StatementBlock* AddCase(const std::string& value_expression);
-  void Write(CodeWriter* to) const override;
-
- private:
-  const std::string switch_expression_;
-  std::vector<std::string> case_values_;
-  std::vector<std::unique_ptr<StatementBlock>> case_logic_;
-};  // class SwitchStatement
-
-class Assignment : public AstNode {
- public:
-  Assignment(const std::string& left, const std::string& right);
-  Assignment(const std::string& left, AstNode* right);
-  ~Assignment() = default;
-  void Write(CodeWriter* to) const override;
-
- private:
-  const std::string lhs_;
-  std::unique_ptr<AstNode> rhs_;
-};  // class Assignment
-
-class MethodCall : public AstNode {
- public:
-  MethodCall(const std::string& method_name,
-             const std::string& single_argument);
-  MethodCall(const std::string& method_name, ArgList&& arg_list);
-  ~MethodCall() = default;
-  void Write(CodeWriter* to) const override;
-
- private:
-  const std::string method_name_;
-  const ArgList arguments_;
-};  // class MethodCall
-
-class IfStatement : public AstNode {
- public:
-  explicit IfStatement(AstNode* expression,
-              bool invert_expression = false);
-  virtual ~IfStatement() = default;
-  StatementBlock* OnTrue() { return &on_true_; }
-  StatementBlock* OnFalse() { return &on_false_; }
-  void Write(CodeWriter* to) const override;
-
- private:
-  std::unique_ptr<AstNode> expression_;
-  bool invert_expression_ = false;
-  StatementBlock on_true_;
-  StatementBlock on_false_;
-};  // class IfStatement
-
-class Statement : public AstNode {
- public:
-  explicit Statement(std::unique_ptr<AstNode> expression);
-  explicit Statement(AstNode* expression);  // Takes possession.
-  explicit Statement(const std::string& expression);
-  ~Statement() = default;
-  void Write(CodeWriter* to) const override;
-
- private:
-  std::unique_ptr<AstNode> expression_;
-};  // class Statement
-
-class Comparison : public AstNode {
- public:
-  Comparison(AstNode* lhs, const std::string& comparison, AstNode* rhs);
-  ~Comparison() = default;
-  void Write(CodeWriter* to) const override;
-
- private:
-  std::unique_ptr<AstNode> left_;
-  std::unique_ptr<AstNode> right_;
-  const std::string operator_;
-};  // class Comparison
-
-class LiteralExpression : public AstNode {
- public:
-  explicit LiteralExpression(const std::string& expression);
-  ~LiteralExpression() = default;
-  void Write(CodeWriter* to) const override;
-
- private:
-  const std::string expression_;
-};  // class LiteralExpression
-
-class CppNamespace : public Declaration {
- public:
-  CppNamespace(const std::string& name,
-               std::vector<std::unique_ptr<Declaration>> declarations);
-  CppNamespace(const std::string& name,
-               std::unique_ptr<Declaration> declaration);
-  explicit CppNamespace(const std::string& name);
-  virtual ~CppNamespace() = default;
-
-  void Write(CodeWriter* to) const override;
-
- private:
-  std::vector<std::unique_ptr<Declaration>> declarations_;
-  std::string name_;
-};  // class CppNamespace
-
-class Document : public AstNode {
- public:
-  Document(const std::vector<std::string>& include_list,
-           std::vector<std::unique_ptr<Declaration>> declarations);
-
-  void Write(CodeWriter* to) const override;
-
- private:
-  std::vector<std::string> include_list_;
-  std::vector<std::unique_ptr<Declaration>> declarations_;
-};  // class Document
-
-class CppHeader final : public Document {
- public:
-  CppHeader(const std::vector<std::string>& include_list,
-            std::vector<std::unique_ptr<Declaration>> declarations);
-  void Write(CodeWriter* to) const override;
-};  // class CppHeader
-
-class CppSource final : public Document {
- public:
-  CppSource(const std::vector<std::string>& include_list,
-            std::vector<std::unique_ptr<Declaration>> declarations);
-};  // class CppSource
-
-}  // namespace cpp
-}  // namespace aidl
-}  // namespace android
diff --git a/ast_cpp_unittest.cpp b/ast_cpp_unittest.cpp
deleted file mode 100644
index 0efdbcd..0000000
--- a/ast_cpp_unittest.cpp
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * Copyright (C) 2015, 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.
- */
-
-#include <string>
-
-#include <gtest/gtest.h>
-
-#include "ast_cpp.h"
-#include "code_writer.h"
-
-using std::string;
-using std::vector;
-using std::unique_ptr;
-
-namespace android {
-namespace aidl {
-namespace cpp {
-namespace {
-
-// clang-format off
-const char kExpectedHeaderOutput[] =
-    R"(#pragma once
-
-#include <string>
-#include <memory>
-
-namespace android {
-
-namespace test {
-
-class TestClass {
-public:
-  void NormalMethod(int normalarg, float normal2);
-  virtual void SubMethod(int subarg) const;
-};  // class TestClass
-
-class TestSubClass : public TestClass {
-public:
-  virtual void SubMethod(int subarg) const;
-};  // class TestSubClass
-
-}  // namespace test
-
-}  // namespace android
-)";
-
-const char kExpectedGenericHeaderOutput[] =
-    R"(#pragma once
-
-#include <string>
-#include <memory>
-
-namespace android {
-
-namespace test {
-
-template <typename A, typename B>
-class TestParcelable : public ::android::Parcelable {
-public:
-  int a;
-};  // class TestParcelable
-
-}  // namespace test
-
-}  // namespace android
-)";
-// clang-format on
-
-const char kExpectedSwitchOutput[] =
-R"(switch (var) {
-case 2:
-{
-  baz;
-}
-break;
-case 1:
-{
-  foo;
-  bar;
-}
-break;
-}
-)";
-
-const char kExpectedMethodImplOutput[] =
-    R"(return_type ClassName::MethodName(int32_t a, int32_t b, int32_t* c) const {
-  foo;
-  bar;
-}
-)";
-const char kExpectedGenericMethodImplOutput[] =
-    R"(template <typename T>
-return_type ClassName<T>::MethodName(int32_t a, int32_t b, int32_t* c) const {
-  foo;
-  bar;
-}
-)";
-}  // namespace
-
-class AstCppTests : public ::testing::Test {
- protected:
-  void CompareGeneratedCode(const AstNode& node,
-                            const string& expected_output) {
-    string actual_output;
-    node.Write(CodeWriter::ForString(&actual_output).get());
-    EXPECT_EQ(expected_output, actual_output);
-  }
-};  // class AstCppTests
-
-
-TEST_F(AstCppTests, GeneratesHeader) {
-  unique_ptr<MethodDecl> norm{new MethodDecl(
-      "void", "NormalMethod",
-      ArgList{vector<string>{"int normalarg", "float normal2"}})};
-  unique_ptr<MethodDecl> sub{
-      new MethodDecl("void", "SubMethod",
-                     ArgList{ "int subarg" },
-                     MethodDecl::IS_CONST | MethodDecl::IS_VIRTUAL)};
-  unique_ptr<MethodDecl> sub2{
-      new MethodDecl("void", "SubMethod",
-                     ArgList{ "int subarg" },
-                     MethodDecl::IS_CONST | MethodDecl::IS_VIRTUAL)};
-  vector<unique_ptr<Declaration>> test_methods;
-  test_methods.push_back(std::move(norm));
-  test_methods.push_back(std::move(sub));
-
-  vector<unique_ptr<Declaration>> test_sub_methods;
-  test_sub_methods.push_back(std::move(sub2));
-
-  unique_ptr<Declaration> test{new ClassDecl{"TestClass", "", {}, std::move(test_methods), {}}};
-
-  unique_ptr<Declaration> test_sub{
-      new ClassDecl{"TestSubClass", "TestClass", {}, std::move(test_sub_methods), {}}};
-
-  vector<unique_ptr<Declaration>> classes;
-  classes.push_back(std::move(test));
-  classes.push_back(std::move(test_sub));
-
-  unique_ptr<CppNamespace> test_ns{new CppNamespace {"test",
-      std::move(classes)}};
-
-  vector<unique_ptr<Declaration>> test_ns_vec;
-  test_ns_vec.push_back(std::move(test_ns));
-
-  unique_ptr<CppNamespace> android_ns{new CppNamespace {"android",
-      std::move(test_ns_vec) }};
-
-  vector<unique_ptr<Declaration>> test_ns_globals;
-  test_ns_globals.push_back(std::move(android_ns));
-
-  CppHeader cpp_header{{"string", "memory"}, std::move(test_ns_globals)};
-  CompareGeneratedCode(cpp_header, kExpectedHeaderOutput);
-}
-
-TEST_F(AstCppTests, GeneratesGenericHeader) {
-  const std::vector<std::string> type_params = {"A", "B"};
-  std::vector<std::unique_ptr<Declaration>> publics;
-  publics.emplace_back(new LiteralDecl("int a;\n"));
-  unique_ptr<Declaration> test{new ClassDecl{
-      "TestParcelable", "::android::Parcelable", type_params, std::move(publics), {}}};
-
-  vector<unique_ptr<Declaration>> classes;
-  classes.push_back(std::move(test));
-
-  unique_ptr<CppNamespace> test_ns{new CppNamespace{"test", std::move(classes)}};
-
-  vector<unique_ptr<Declaration>> test_ns_vec;
-  test_ns_vec.push_back(std::move(test_ns));
-
-  unique_ptr<CppNamespace> android_ns{new CppNamespace{"android", std::move(test_ns_vec)}};
-
-  vector<unique_ptr<Declaration>> test_ns_globals;
-  test_ns_globals.push_back(std::move(android_ns));
-
-  CppHeader cpp_header{{"string", "memory"}, std::move(test_ns_globals)};
-  CompareGeneratedCode(cpp_header, kExpectedGenericHeaderOutput);
-}
-
-TEST_F(AstCppTests, GeneratesUnscopedEnum) {
-  Enum e("Foo", "", false);
-  e.AddValue("BAR", "42");
-  e.AddValue("BAZ", "");
-
-  string expected =
-      R"(enum Foo {
-  BAR = 42,
-  BAZ,
-};
-)";
-
-  CompareGeneratedCode(e, expected);
-}
-
-TEST_F(AstCppTests, GeneratesScopedEnum) {
-  Enum e("Foo", "int32_t", true);
-  e.AddValue("BAR", "42");
-  e.AddValue("BAZ", "");
-
-  string expected =
-      R"(enum class Foo : int32_t {
-  BAR = 42,
-  BAZ,
-};
-)";
-
-  CompareGeneratedCode(e, expected);
-}
-
-TEST_F(AstCppTests, GeneratesArgList) {
-  ArgList simple("foo");
-  CompareGeneratedCode(simple, "(foo)");
-  ArgList compound({"foo", "bar", "baz"});
-  CompareGeneratedCode(compound, "(foo, bar, baz)");
-  std::vector<unique_ptr<AstNode>> args;
-  args.emplace_back(new LiteralExpression("foo()"));
-  ArgList nested(std::move(args));
-  CompareGeneratedCode(nested, "(foo())");
-}
-
-TEST_F(AstCppTests, GeneratesStatement) {
-  Statement s(new LiteralExpression("foo"));
-  CompareGeneratedCode(s, "foo;\n");
-}
-
-TEST_F(AstCppTests, GeneratesComparison) {
-  Comparison c(
-      new LiteralExpression("lhs"), "&&", new LiteralExpression("rhs"));
-  CompareGeneratedCode(c, "((lhs) && (rhs))");
-}
-
-TEST_F(AstCppTests, GeneratesStatementBlock) {
-  StatementBlock block;
-  block.AddStatement(unique_ptr<AstNode>(new Statement("foo")));
-  block.AddStatement(unique_ptr<AstNode>(new Statement("bar")));
-  CompareGeneratedCode(block, "{\n  foo;\n  bar;\n}\n");
-}
-
-TEST_F(AstCppTests, GeneratesConstructorImpl) {
-  ConstructorImpl c("ClassName", ArgList({"a", "b", "c"}),
-                    {"baz_(foo)", "bar_(blah)"});
-  string expected = R"(ClassName::ClassName(a, b, c)
-    : baz_(foo),
-      bar_(blah){
-}
-)";
-  CompareGeneratedCode(c, expected);
-}
-
-TEST_F(AstCppTests, GeneratesAssignment) {
-  Assignment simple("foo", "8");
-  CompareGeneratedCode(simple, "foo = 8;\n");
-  Assignment less_simple("foo", new MethodCall("f", "8"));
-  CompareGeneratedCode(less_simple, "foo = f(8);\n");
-}
-
-TEST_F(AstCppTests, GeneratesMethodCall) {
-  MethodCall single("single", "arg");
-  CompareGeneratedCode(single, "single(arg)");
-  MethodCall multi(
-      "multi",
-      ArgList({"has", "some", "args"}));
-  CompareGeneratedCode(multi, "multi(has, some, args)");
-}
-
-TEST_F(AstCppTests, GeneratesIfStatement) {
-  IfStatement s(new LiteralExpression("foo"));
-  s.OnTrue()->AddLiteral("on true1");
-  s.OnFalse()->AddLiteral("on false");
-  CompareGeneratedCode(s, "if (foo) {\n  on true1;\n}\nelse {\n  on false;\n}\n");
-
-  IfStatement s2(new LiteralExpression("bar"));
-  s2.OnTrue()->AddLiteral("on true1");
-  CompareGeneratedCode(s2, "if (bar) {\n  on true1;\n}\n");
-}
-
-TEST_F(AstCppTests, GeneratesSwitchStatement) {
-  SwitchStatement s("var");
-  // These are intentionally out of alphanumeric order.  We're testing
-  // that switch respects case addition order.
-  auto case2 = s.AddCase("2");
-  case2->AddStatement(unique_ptr<AstNode>{new Statement{"baz"}});
-  auto case1 = s.AddCase("1");
-  case1->AddStatement(unique_ptr<AstNode>{new Statement{"foo"}});
-  case1->AddStatement(unique_ptr<AstNode>{new Statement{"bar"}});
-  CompareGeneratedCode(s, kExpectedSwitchOutput);
-}
-
-TEST_F(AstCppTests, GeneratesMethodImpl) {
-  MethodImpl m{"return_type",
-               "ClassName",
-               "MethodName",
-               {},
-               ArgList{{"int32_t a", "int32_t b", "int32_t* c"}},
-               true};
-  auto b = m.GetStatementBlock();
-  b->AddLiteral("foo");
-  b->AddLiteral("bar");
-  CompareGeneratedCode(m, kExpectedMethodImplOutput);
-}
-
-TEST_F(AstCppTests, GeneratesGenericMethodImpl) {
-  MethodImpl m{"return_type",
-               "ClassName",
-               "MethodName",
-               {"T"},
-               ArgList{{"int32_t a", "int32_t b", "int32_t* c"}},
-               true};
-  auto b = m.GetStatementBlock();
-  b->AddLiteral("foo");
-  b->AddLiteral("bar");
-  CompareGeneratedCode(m, kExpectedGenericMethodImplOutput);
-}
-
-TEST_F(AstCppTests, ToString) {
-  std::string literal = "void foo() {}";
-  LiteralDecl decl(literal);
-  std::string actual = decl.ToString();
-  EXPECT_EQ(literal, actual);
-  std::string written;
-  decl.Write(CodeWriter::ForString(&written).get());
-  EXPECT_EQ(literal, written);
-}
-
-}  // namespace cpp
-}  // namespace aidl
-}  // namespace android
diff --git a/ast_java.cpp b/ast_java.cpp
index 066624e..7d95bd4 100644
--- a/ast_java.cpp
+++ b/ast_java.cpp
@@ -233,15 +233,6 @@
   to->Write(")");
 }
 
-NewArrayExpression::NewArrayExpression(const std::string& t, std::shared_ptr<Expression> s)
-    : type(t), size(s) {}
-
-void NewArrayExpression::Write(CodeWriter* to) const {
-  to->Write("new %s[", this->type.c_str());
-  size->Write(to);
-  to->Write("]");
-}
-
 Cast::Cast(const std::string& t, std::shared_ptr<Expression> e) : type(t), expression(e) {}
 
 void Cast::Write(CodeWriter* to) const {
@@ -285,6 +276,10 @@
   to->Write(";\n");
 }
 
+void BreakStatement::Write(CodeWriter* to) const {
+  to->Write("break;\n");
+}
+
 void TryStatement::Write(CodeWriter* to) const {
   to->Write("try ");
   this->statements->Write(to);
@@ -432,31 +427,6 @@
   to->Write("}\n");
 }
 
-Document::Document(const std::string& comment,
-                   const std::string& package,
-                   std::unique_ptr<Class> clazz)
-    : comment_(comment),
-      package_(package),
-      clazz_(std::move(clazz)) {
-}
-
-void Document::Write(CodeWriter* to) const {
-  if (!comment_.empty()) {
-    to->Write("%s\n", comment_.c_str());
-  }
-  to->Write(
-      "/*\n"
-      " * This file is auto-generated.  DO NOT MODIFY.\n"
-      " */\n");
-  if (!package_.empty()) {
-    to->Write("package %s;\n", package_.c_str());
-  }
-
-  if (clazz_) {
-    clazz_->Write(to);
-  }
-}
-
 std::shared_ptr<Expression> NULL_VALUE = std::make_shared<LiteralExpression>("null");
 std::shared_ptr<Expression> THIS_VALUE = std::make_shared<LiteralExpression>("this");
 std::shared_ptr<Expression> SUPER_VALUE = std::make_shared<LiteralExpression>("super");
diff --git a/ast_java.h b/ast_java.h
index d4e8944..d7e5cb5 100644
--- a/ast_java.h
+++ b/ast_java.h
@@ -207,15 +207,6 @@
   void Write(CodeWriter* to) const override;
 };
 
-struct NewArrayExpression : public Expression {
-  const std::string type;
-  std::shared_ptr<Expression> size;
-
-  NewArrayExpression(const std::string& type, std::shared_ptr<Expression> size);
-  virtual ~NewArrayExpression() = default;
-  void Write(CodeWriter* to) const override;
-};
-
 struct Cast : public Expression {
   const std::string type;
   std::shared_ptr<Expression> expression = nullptr;
@@ -254,6 +245,12 @@
   void Write(CodeWriter* to) const override;
 };
 
+struct BreakStatement : public Statement {
+  BreakStatement() = default;
+  virtual ~BreakStatement() = default;
+  void Write(CodeWriter* to) const override;
+};
+
 struct TryStatement : public Statement {
   std::shared_ptr<StatementBlock> statements = std::make_shared<StatementBlock>();
 
@@ -332,20 +329,6 @@
   void Write(CodeWriter* to) const override;
 };
 
-class Document : public AstNode {
- public:
-  Document(const std::string& comment,
-           const std::string& package,
-           std::unique_ptr<Class> clazz);
-  virtual ~Document() = default;
-  void Write(CodeWriter* to) const override;
-
- private:
-  std::string comment_;
-  std::string package_;
-  std::unique_ptr<Class> clazz_;
-};
-
 extern std::shared_ptr<Expression> NULL_VALUE;
 extern std::shared_ptr<Expression> THIS_VALUE;
 extern std::shared_ptr<Expression> SUPER_VALUE;
diff --git a/build/Android.bp b/build/Android.bp
index 53cf9db..f12a4f5 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -27,7 +27,6 @@
     deps: [
         "blueprint",
         "soong",
-        "soong-apex",
         "soong-android",
         "soong-cc",
         "soong-genrule",
@@ -63,8 +62,11 @@
 // be moved back to LoadHook, and then default can be applied as well.
 cc_defaults {
     name: "aidl-cpp-module-defaults",
-    // TODO(b/31559095): remove when host bionic is available
-    defaults: ["libbinder_ndk_host_user"],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
 }
 
 java_defaults {
@@ -114,7 +116,7 @@
         "tests_1/some_package/IBar.aidl",
     ],
     imports: [
-        "test-piece-1",
+        "test-piece-1-V3",
     ],
     backend: {
         java: {
@@ -133,7 +135,7 @@
         "tests_1/other_package/IBaz.aidl",
     ],
     imports: [
-        "test-piece-2",
+        "test-piece-2-V1",
     ],
     backend: {
         java: {
@@ -152,7 +154,7 @@
         "tests_2/another_package/IFaz.aidl",
     ],
     imports: [
-        "test-piece-1",
+        "test-piece-1-V3",
     ],
     backend: {
         java: {
@@ -173,7 +175,7 @@
         "test_package/IBaz.aidl",
     ],
     imports: [
-        "test-piece-2",
+        "test-piece-2-V1",
     ],
     backend: {
         java: {
@@ -198,6 +200,17 @@
     ],
 }
 
+aidl_interface {
+    name: "test-piece-6",
+    unstable: true,
+    local_include_dir: "tests_6",
+    flags: ["-Werror"],
+    srcs: [
+        "tests_6/test6/Bar.aidl",
+        "tests_6/test6/Foo.aidl",
+    ],
+}
+
 // These test that a parcel imported from A->B->C will have the required dependencies to link in
 // all backends (C++ backends need to link direclty against the constructor of the parcelable
 // in order to work)
@@ -241,3 +254,9 @@
         },
     },
 }
+
+sh_binary {
+    name: "aidl_hash_gen",
+    src: "hash_gen.sh",
+    host_supported: true,
+}
diff --git a/build/aidl_api.go b/build/aidl_api.go
index 2798374..62d2541 100644
--- a/build/aidl_api.go
+++ b/build/aidl_api.go
@@ -31,32 +31,32 @@
 	aidlDumpApiRule = pctx.StaticRule("aidlDumpApiRule", blueprint.RuleParams{
 		Command: `rm -rf "${outDir}" && mkdir -p "${outDir}" && ` +
 			`${aidlCmd} --dumpapi --structured ${imports} ${optionalFlags} --out ${outDir} ${in} && ` +
-			`(cd ${outDir} && find ./ -name "*.aidl" -print0 | LC_ALL=C sort -z | xargs -0 sha1sum && echo ${latestVersion}) | sha1sum | cut -d " " -f 1 > ${hashFile} `,
-		CommandDeps: []string{"${aidlCmd}"},
+			`${aidlHashGen} ${outDir} ${latestVersion} ${hashFile}`,
+		CommandDeps: []string{"${aidlCmd}", "${aidlHashGen}"},
 	}, "optionalFlags", "imports", "outDir", "hashFile", "latestVersion")
 
 	aidlCheckApiRule = pctx.StaticRule("aidlCheckApiRule", blueprint.RuleParams{
-		Command: `(${aidlCmd} ${optionalFlags} --checkapi=${checkApiLevel} ${old} ${new} && touch ${out}) || ` +
+		Command: `(${aidlCmd} ${optionalFlags} --checkapi=${checkApiLevel} ${imports} ${old} ${new} && touch ${out}) || ` +
 			`(cat ${messageFile} && exit 1)`,
 		CommandDeps: []string{"${aidlCmd}"},
 		Description: "AIDL CHECK API: ${new} against ${old}",
-	}, "optionalFlags", "old", "new", "messageFile", "checkApiLevel")
+	}, "optionalFlags", "imports", "old", "new", "messageFile", "checkApiLevel")
 
 	aidlVerifyHashRule = pctx.StaticRule("aidlVerifyHashRule", blueprint.RuleParams{
-		Command: `if [ $$(cd '${apiDir}' && { find ./ -name "*.aidl" -print0 | LC_ALL=C sort -z | xargs -0 sha1sum && echo ${version}; } | sha1sum | cut -d " " -f 1) = $$(read -r <'${hashFile}' hash extra; printf %s $$hash) ]; then ` +
+		Command: `if [ $$(cd '${apiDir}' && { find ./ -name "*.aidl" -print0 | LC_ALL=C sort -z | xargs -0 sha1sum && echo ${version}; } | sha1sum | cut -d " " -f 1) = $$(tail -1 '${hashFile}') ]; then ` +
 			`touch ${out}; else cat '${messageFile}' && exit 1; fi`,
 		Description: "Verify ${apiDir} files have not been modified",
 	}, "apiDir", "version", "messageFile", "hashFile")
 )
 
 type aidlApiProperties struct {
-	BaseName              string
-	Srcs                  []string `android:"path"`
-	AidlRoot              string   // base directory for the input aidl file
-	Stability             *string
-	ImportsWithoutVersion []string
-	Versions              []string
-	Dumpapi               DumpApiProperties
+	BaseName  string
+	Srcs      []string `android:"path"`
+	AidlRoot  string   // base directory for the input aidl file
+	Stability *string
+	Imports   []string
+	Versions  []string
+	Dumpapi   DumpApiProperties
 }
 
 type aidlApi struct {
@@ -75,6 +75,9 @@
 
 	// for triggering freezing API as the new version
 	freezeApiTimestamp android.WritablePath
+
+	// for checking for active development on unfrozen version
+	hasDevelopment android.WritablePath
 }
 
 func (m *aidlApi) apiDir() string {
@@ -87,11 +90,17 @@
 }
 
 type apiDump struct {
+	version  string
 	dir      android.Path
 	files    android.Paths
 	hashFile android.OptionalPath
 }
 
+func (m *aidlApi) getImports(ctx android.ModuleContext, version string) map[string]string {
+	iface := ctx.GetDirectDepWithTag(m.properties.BaseName, interfaceDep).(*aidlInterface)
+	return iface.getImports(version)
+}
+
 func (m *aidlApi) createApiDumpFromSource(ctx android.ModuleContext) apiDump {
 	srcs, imports := getPaths(ctx, m.properties.Srcs, m.properties.AidlRoot)
 
@@ -99,31 +108,20 @@
 		return apiDump{}
 	}
 
-	var importPaths []string
-	importPaths = append(importPaths, imports...)
-	ctx.VisitDirectDeps(func(dep android.Module) {
-		if importedAidl, ok := dep.(*aidlInterface); ok {
-			importPaths = append(importPaths, importedAidl.properties.Full_import_paths...)
-		}
-	})
+	// dumpapi uses imports for ToT("") version
+	deps := getDeps(ctx, m.getImports(ctx, m.nextVersion()))
+	imports = append(imports, deps.imports...)
 
 	var apiDir android.WritablePath
 	var apiFiles android.WritablePaths
 	var hashFile android.WritablePath
 
 	apiDir = android.PathForModuleOut(ctx, "dump")
-	aidlRoot := android.PathForModuleSrc(ctx, m.properties.AidlRoot)
 	for _, src := range srcs {
-		baseDir := getBaseDir(ctx, src, aidlRoot)
-		relPath, _ := filepath.Rel(baseDir, src.String())
-		outFile := android.PathForModuleOut(ctx, "dump", relPath)
+		outFile := android.PathForModuleOut(ctx, "dump", src.Rel())
 		apiFiles = append(apiFiles, outFile)
 	}
 	hashFile = android.PathForModuleOut(ctx, "dump", ".hash")
-	latestVersion := "latest-version"
-	if len(m.properties.Versions) >= 1 {
-		latestVersion = m.properties.Versions[len(m.properties.Versions)-1]
-	}
 
 	var optionalFlags []string
 	if m.properties.Stability != nil {
@@ -132,20 +130,23 @@
 	if proptools.Bool(m.properties.Dumpapi.No_license) {
 		optionalFlags = append(optionalFlags, "--no_license")
 	}
+	optionalFlags = append(optionalFlags, wrap("-p", deps.preprocessed.Strings(), "")...)
 
+	version := nextVersion(m.properties.Versions)
 	ctx.Build(pctx, android.BuildParams{
-		Rule:    aidlDumpApiRule,
-		Outputs: append(apiFiles, hashFile),
-		Inputs:  srcs,
+		Rule:      aidlDumpApiRule,
+		Outputs:   append(apiFiles, hashFile),
+		Inputs:    srcs,
+		Implicits: deps.preprocessed,
 		Args: map[string]string{
 			"optionalFlags": strings.Join(optionalFlags, " "),
-			"imports":       strings.Join(wrap("-I", importPaths, ""), " "),
+			"imports":       strings.Join(wrap("-I", imports, ""), " "),
 			"outDir":        apiDir.String(),
 			"hashFile":      hashFile.String(),
-			"latestVersion": latestVersion,
+			"latestVersion": versionForHashGen(version),
 		},
 	})
-	return apiDump{apiDir, apiFiles.Paths(), android.OptionalPathForPath(hashFile)}
+	return apiDump{version, apiDir, apiFiles.Paths(), android.OptionalPathForPath(hashFile)}
 }
 
 func (m *aidlApi) makeApiDumpAsVersion(ctx android.ModuleContext, dump apiDump, version string, latestVersionDump *apiDump) android.WritablePath {
@@ -154,44 +155,23 @@
 	targetDir := filepath.Join(moduleDir, m.apiDir(), version)
 	rb := android.NewRuleBuilder(pctx, ctx)
 
+	var actionWord string
 	if creatingNewVersion {
+		actionWord = "Making"
 		// We are asked to create a new version. But before doing that, check if the given
 		// dump is the same as the latest version. If so, don't create a new version,
-		// otherwise we will be unnecessarily creating many versions. `newVersionNeededFile`
-		// is created when the equality check fails.
-		newVersionNeededFile := android.PathForModuleOut(ctx, "updateapi_"+version+".needed")
-		rb.Command().Text("rm -f " + newVersionNeededFile.String())
-
-		if latestVersionDump != nil {
-			equalityCheckCommand := rb.Command()
-			equalityCheckCommand.BuiltTool("aidl").
-				FlagWithArg("--checkapi=", "equal")
-			if m.properties.Stability != nil {
-				equalityCheckCommand.FlagWithArg("--stability ", *m.properties.Stability)
-			}
-			equalityCheckCommand.
-				Text(latestVersionDump.dir.String()).Implicits(latestVersionDump.files).
-				Text(dump.dir.String()).Implicits(dump.files).
-				Text("&> /dev/null")
-			equalityCheckCommand.
-				Text("|| touch").
-				Text(newVersionNeededFile.String())
-		} else {
-			// If there is no latest version (i.e. we are creating the initial version)
-			// create the new version unconditionally
-			rb.Command().Text("touch").Text(newVersionNeededFile.String())
-		}
-
+		// otherwise we will be unnecessarily creating many versions.
 		// Copy the given dump to the target directory only when the equality check failed
-		// (i.e. `newVersionNeededFile` exists).
+		// (i.e. `has_development` file contains "1").
 		rb.Command().
-			Text("if [ -f " + newVersionNeededFile.String() + " ]; then").
+			Text("if [ \"$(cat ").Input(m.hasDevelopment).Text(")\" = \"1\" ]; then").
+			Text("mkdir -p " + targetDir + " && ").
 			Text("cp -rf " + dump.dir.String() + "/. " + targetDir).Implicits(dump.files).
 			Text("; fi")
 
 		// Also modify Android.bp file to add the new version to the 'versions' property.
 		rb.Command().
-			Text("if [ -f " + newVersionNeededFile.String() + " ]; then").
+			Text("if [ \"$(cat ").Input(m.hasDevelopment).Text(")\" = \"1\" ]; then").
 			BuiltTool("bpmodify").
 			Text("-w -m " + m.properties.BaseName).
 			Text("-parameter versions -a " + version).
@@ -199,6 +179,7 @@
 			Text("; fi")
 
 	} else {
+		actionWord = "Updating"
 		// We are updating the current version. Don't copy .hash to the current dump
 		rb.Command().Text("mkdir -p " + targetDir)
 		rb.Command().Text("rm -rf " + targetDir + "/*")
@@ -208,73 +189,70 @@
 	timestampFile := android.PathForModuleOut(ctx, "updateapi_"+version+".timestamp")
 	rb.Command().Text("touch").Output(timestampFile)
 
-	rb.Build("dump_aidl_api"+m.properties.BaseName+"_"+version,
-		"Making AIDL API of "+m.properties.BaseName+" as version "+version)
+	rb.Build("dump_aidl_api_"+m.properties.BaseName+"_"+version, actionWord+" AIDL API dump version "+version+" for "+m.properties.BaseName+" (see "+targetDir+")")
 	return timestampFile
 }
 
-type depTag struct {
-	blueprint.BaseDependencyTag
-	name string
+type deps struct {
+	preprocessed android.Paths
+	implicits    android.Paths
+	imports      []string
 }
 
-var (
-	apiDep       = depTag{name: "api"}
-	interfaceDep = depTag{name: "interface"}
-
-	importApiDep       = depTag{name: "imported-api"}
-	importInterfaceDep = depTag{name: "imported-interface"}
-)
-
 // calculates import flags(-I) from deps.
 // When the target is ToT, use ToT of imported interfaces. If not, we use "current" snapshot of
 // imported interfaces.
-func getImportsFromDeps(ctx android.ModuleContext, targetIsToT bool) (importPaths []string, implicits android.Paths) {
+func getDeps(ctx android.ModuleContext, versionedImports map[string]string) deps {
+	var deps deps
 	ctx.VisitDirectDeps(func(dep android.Module) {
-		switch ctx.OtherModuleDependencyTag(dep) {
-		case importInterfaceDep:
+		switch ctx.OtherModuleDependencyTag(dep).(type) {
+		case importInterfaceDepTag:
 			iface := dep.(*aidlInterface)
-			if proptools.Bool(iface.properties.Unstable) || targetIsToT {
-				importPaths = append(importPaths, iface.properties.Full_import_paths...)
-			} else {
-				// use "current" snapshot from stable "imported" modules
-				currentDir := filepath.Join(ctx.OtherModuleDir(dep), aidlApiDir, iface.BaseModuleName(), currentVersion)
-				importPaths = append(importPaths, currentDir)
-				// TODO(b/189288369) this should be transitive
-				importPaths = append(importPaths, iface.properties.Include_dirs...)
+			if version, ok := versionedImports[iface.BaseModuleName()]; ok {
+				if iface.preprocessed[version] == nil {
+					ctx.ModuleErrorf("can't import %v's preprocessed(version=%v)", iface.BaseModuleName(), version)
+				}
+				deps.preprocessed = append(deps.preprocessed, iface.preprocessed[version])
 			}
-		case interfaceDep:
+		case interfaceDepTag:
 			iface := dep.(*aidlInterface)
-			importPaths = append(importPaths, iface.properties.Include_dirs...)
-		case importApiDep, apiDep:
+			deps.imports = append(deps.imports, iface.properties.Include_dirs...)
+		case apiDepTag:
 			api := dep.(*aidlApi)
 			// add imported module's checkapiTimestamps as implicits to make sure that imported apiDump is up-to-date
-			implicits = append(implicits, api.checkApiTimestamps.Paths()...)
-			implicits = append(implicits, api.checkHashTimestamps.Paths()...)
+			deps.implicits = append(deps.implicits, api.checkApiTimestamps.Paths()...)
+			deps.implicits = append(deps.implicits, api.checkHashTimestamps.Paths()...)
 		}
 	})
-	return
+	return deps
 }
 
 func (m *aidlApi) checkApi(ctx android.ModuleContext, oldDump, newDump apiDump, checkApiLevel string, messageFile android.Path) android.WritablePath {
 	newVersion := newDump.dir.Base()
 	timestampFile := android.PathForModuleOut(ctx, "checkapi_"+newVersion+".timestamp")
 
+	// --checkapi(old,new) should use imports for "new"
+	deps := getDeps(ctx, m.getImports(ctx, newDump.version))
+	var implicits android.Paths
+	implicits = append(implicits, deps.implicits...)
+	implicits = append(implicits, deps.preprocessed...)
+	implicits = append(implicits, oldDump.files...)
+	implicits = append(implicits, newDump.files...)
+	implicits = append(implicits, messageFile)
+
 	var optionalFlags []string
 	if m.properties.Stability != nil {
 		optionalFlags = append(optionalFlags, "--stability", *m.properties.Stability)
 	}
+	optionalFlags = append(optionalFlags, wrap("-p", deps.preprocessed.Strings(), "")...)
 
-	var implicits android.Paths
-	implicits = append(implicits, oldDump.files...)
-	implicits = append(implicits, newDump.files...)
-	implicits = append(implicits, messageFile)
 	ctx.Build(pctx, android.BuildParams{
 		Rule:      aidlCheckApiRule,
 		Implicits: implicits,
 		Output:    timestampFile,
 		Args: map[string]string{
 			"optionalFlags": strings.Join(optionalFlags, " "),
+			"imports":       strings.Join(wrap("-I", deps.imports, ""), " "),
 			"old":           oldDump.dir.String(),
 			"new":           newDump.dir.String(),
 			"messageFile":   messageFile.String(),
@@ -304,10 +282,6 @@
 	rb.Command().Text("sed").Flag(" s/%s/" + m.properties.BaseName + "/g ").Input(messageFile).Text(" > ").Output(formattedMessageFile)
 	rb.Build("format_message_"+m.properties.BaseName, "")
 
-	var implicits android.Paths
-	implicits = append(implicits, oldDump.files...)
-	implicits = append(implicits, newDump.files...)
-	implicits = append(implicits, formattedMessageFile)
 	return m.checkApi(ctx, oldDump, newDump, "equal", formattedMessageFile)
 }
 
@@ -316,13 +290,6 @@
 	timestampFile := android.PathForModuleOut(ctx, "checkhash_"+version+".timestamp")
 	messageFile := android.PathForSource(ctx, "system/tools/aidl/build/message_check_integrity.txt")
 
-	i, _ := strconv.Atoi(version)
-	if i == 1 {
-		version = "latest-version"
-	} else {
-		version = strconv.Itoa(i - 1)
-	}
-
 	var implicits android.Paths
 	implicits = append(implicits, dump.files...)
 	implicits = append(implicits, dump.hashFile.Path())
@@ -333,7 +300,7 @@
 		Output:    timestampFile,
 		Args: map[string]string{
 			"apiDir":      dump.dir.String(),
-			"version":     version,
+			"version":     versionForHashGen(version),
 			"hashFile":    dump.hashFile.Path().String(),
 			"messageFile": messageFile.String(),
 		},
@@ -341,6 +308,31 @@
 	return timestampFile
 }
 
+func (m *aidlApi) checkForDevelopment(ctx android.ModuleContext, latestVersionDump *apiDump, totDump apiDump) android.WritablePath {
+	hasDevPath := android.PathForModuleOut(ctx, "has_development")
+	rb := android.NewRuleBuilder(pctx, ctx)
+	rb.Command().Text("rm -f " + hasDevPath.String())
+	if latestVersionDump != nil {
+		hasDevCommand := rb.Command()
+		hasDevCommand.BuiltTool("aidl").FlagWithArg("--checkapi=", "equal")
+		if m.properties.Stability != nil {
+			hasDevCommand.FlagWithArg("--stability ", *m.properties.Stability)
+		}
+		// checkapi(latest, tot) should use imports for nextVersion(=tot)
+		deps := getDeps(ctx, m.getImports(ctx, m.nextVersion()))
+		hasDevCommand.
+			FlagForEachArg("-I", deps.imports).Implicits(deps.implicits).
+			FlagForEachInput("-p", deps.preprocessed).
+			Text(latestVersionDump.dir.String()).Implicits(latestVersionDump.files).
+			Text(totDump.dir.String()).Implicits(totDump.files).
+			Text("2> /dev/null; echo $? >").Output(hasDevPath)
+	} else {
+		rb.Command().Text("echo 1 >").Output(hasDevPath)
+	}
+	rb.Build("check_for_development", "")
+	return hasDevPath
+}
+
 func (m *aidlApi) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	// An API dump is created from source and it is compared against the API dump of the
 	// 'current' (yet-to-be-finalized) version. By checking this we enforce that any change in
@@ -351,6 +343,7 @@
 	var currentApiDump apiDump
 	if currentApiDir.Valid() {
 		currentApiDump = apiDump{
+			version:  nextVersion(m.properties.Versions),
 			dir:      currentApiDir.Path(),
 			files:    ctx.Glob(filepath.Join(currentApiDir.Path().String(), "**/*.aidl"), nil),
 			hashFile: android.ExistentPathForSource(ctx, ctx.ModuleDir(), m.apiDir(), currentVersion, ".hash"),
@@ -379,11 +372,20 @@
 		apiDir := filepath.Join(ctx.ModuleDir(), m.apiDir(), ver)
 		apiDirPath := android.ExistentPathForSource(ctx, apiDir)
 		if apiDirPath.Valid() {
-			dumps = append(dumps, apiDump{
+			hashFilePath := filepath.Join(apiDir, ".hash")
+			dump := apiDump{
+				version:  ver,
 				dir:      apiDirPath.Path(),
 				files:    ctx.Glob(filepath.Join(apiDirPath.String(), "**/*.aidl"), nil),
-				hashFile: android.ExistentPathForSource(ctx, ctx.ModuleDir(), m.apiDir(), ver, ".hash"),
-			})
+				hashFile: android.ExistentPathForSource(ctx, hashFilePath),
+			}
+			if !dump.hashFile.Valid() {
+				// We should show the source path of hash_gen because aidl_hash_gen cannot be built due to build error.
+				cmd := fmt.Sprintf(`(croot && system/tools/aidl/build/hash_gen.sh %s %s %s)`, apiDir, versionForHashGen(ver), hashFilePath)
+				ctx.ModuleErrorf("A frozen aidl_interface must have '.hash' file, but %s-V%s doesn't have it. Use the command below to generate hash.\n%s\n",
+					m.properties.BaseName, ver, cmd)
+			}
+			dumps = append(dumps, dump)
 		} else if ctx.Config().AllowMissingDependencies() {
 			ctx.AddMissingDependencies([]string{apiDir})
 		} else {
@@ -410,6 +412,9 @@
 		m.checkApiTimestamps = append(m.checkApiTimestamps, checked)
 	}
 
+	// Check for active development on the unfrozen version
+	m.hasDevelopment = m.checkForDevelopment(ctx, latestVersionDump, totApiDump)
+
 	// API dump from source is updated to the 'current' version. Triggered by `m <name>-update-api`
 	m.updateApiTimestamp = m.makeApiDumpAsVersion(ctx, totApiDump, currentVersion, nil)
 
@@ -434,7 +439,7 @@
 }
 
 func (m *aidlApi) DepsMutator(ctx android.BottomUpMutatorContext) {
-	ctx.AddDependency(ctx.Module(), nil, wrap("", m.properties.ImportsWithoutVersion, aidlInterfaceSuffix)...)
+	ctx.AddReverseDependency(ctx.Module(), nil, aidlMetadataSingletonName)
 }
 
 func aidlApiFactory() android.Module {
@@ -450,17 +455,26 @@
 	mctx.CreateModule(aidlApiFactory, &nameProperties{
 		Name: proptools.StringPtr(apiModule),
 	}, &aidlApiProperties{
-		BaseName:              i.ModuleBase.Name(),
-		Srcs:                  srcs,
-		AidlRoot:              aidlRoot,
-		Stability:             i.properties.Stability,
-		ImportsWithoutVersion: concat(i.properties.ImportsWithoutVersion, []string{i.ModuleBase.Name()}),
-		Versions:              i.properties.Versions,
-		Dumpapi:               i.properties.Dumpapi,
+		BaseName:  i.ModuleBase.Name(),
+		Srcs:      srcs,
+		AidlRoot:  aidlRoot,
+		Stability: i.properties.Stability,
+		Imports:   i.properties.Imports,
+		Versions:  i.properties.Versions,
+		Dumpapi:   i.properties.Dumpapi,
 	})
 	return apiModule
 }
 
+func versionForHashGen(ver string) string {
+	// aidlHashGen uses the version before current version. If it has never been frozen, return 'latest-version'.
+	verInt, _ := strconv.Atoi(ver)
+	if verInt > 1 {
+		return strconv.Itoa(verInt - 1)
+	}
+	return "latest-version"
+}
+
 func init() {
 	android.RegisterSingletonType("aidl-freeze-api", freezeApiSingletonFactory)
 }
@@ -478,7 +492,16 @@
 			return
 		}
 		if m, ok := module.(*aidlApi); ok {
-			files = append(files, m.freezeApiTimestamp)
+			ownersToFreeze := strings.Fields(ctx.Config().Getenv("AIDL_FREEZE_OWNERS"))
+			var shouldBeFrozen bool
+			if len(ownersToFreeze) > 0 {
+				shouldBeFrozen = android.InList(m.Owner(), ownersToFreeze)
+			} else {
+				shouldBeFrozen = m.Owner() == ""
+			}
+			if shouldBeFrozen {
+				files = append(files, m.freezeApiTimestamp)
+			}
 		}
 	})
 	ctx.Phony("aidl-freeze-api", files...)
diff --git a/build/aidl_api/test-piece-2/1/.hash b/build/aidl_api/test-piece-2/1/.hash
index 705fc31..3c32edf 100644
--- a/build/aidl_api/test-piece-2/1/.hash
+++ b/build/aidl_api/test-piece-2/1/.hash
@@ -1 +1,2 @@
+c544902ab8a1d2e72ae9396032ba113e9b9698c4
 fcd36db451cdbeeb049833fd7f499a987acf3930
diff --git a/build/aidl_gen_rule.go b/build/aidl_gen_rule.go
index f944617..3dd0fde 100644
--- a/build/aidl_gen_rule.go
+++ b/build/aidl_gen_rule.go
@@ -63,19 +63,22 @@
 )
 
 type aidlGenProperties struct {
-	Srcs                  []string `android:"path"`
-	AidlRoot              string   // base directory for the input aidl file
-	IsToT                 bool
-	ImportsWithoutVersion []string
-	Stability             *string
-	Lang                  string // target language [java|cpp|ndk|rust]
-	BaseName              string
-	GenLog                bool
-	Version               string
-	GenTrace              bool
-	Unstable              *bool
-	Visibility            []string
-	Flags                 []string
+	Srcs            []string `android:"path"`
+	AidlRoot        string   // base directory for the input aidl file
+	Imports         []string
+	Stability       *string
+	Min_sdk_version *string
+	Platform_apis   bool
+	Lang            string // target language [java|cpp|ndk|rust]
+	BaseName        string
+	GenLog          bool
+	Version         string
+	GenRpc          bool
+	GenTrace        bool
+	Unstable        *bool
+	NotFrozen       bool
+	Visibility      []string
+	Flags           []string
 }
 
 type aidlGenRule struct {
@@ -83,10 +86,11 @@
 
 	properties aidlGenProperties
 
+	deps           deps
 	implicitInputs android.Paths
 	importFlags    string
 
-	// TODO(b/149952131): always have a hash file
+	// A frozen aidl_interface always have a hash file
 	hashFile android.Path
 
 	genOutDir     android.ModuleGenPath
@@ -98,6 +102,15 @@
 var _ android.SourceFileProducer = (*aidlGenRule)(nil)
 var _ genrule.SourceFileGenerator = (*aidlGenRule)(nil)
 
+func (g *aidlGenRule) aidlInterface(ctx android.BaseModuleContext) *aidlInterface {
+	return ctx.GetDirectDepWithTag(g.properties.BaseName, interfaceDep).(*aidlInterface)
+}
+
+func (g *aidlGenRule) getImports(ctx android.ModuleContext) map[string]string {
+	iface := g.aidlInterface(ctx)
+	return iface.getImports(g.properties.Version)
+}
+
 func (g *aidlGenRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
 	srcs, imports := getPaths(ctx, g.properties.Srcs, g.properties.AidlRoot)
 
@@ -105,12 +118,14 @@
 		return
 	}
 
+	g.deps = getDeps(ctx, g.getImports(ctx))
+
 	genDirTimestamp := android.PathForModuleGen(ctx, "timestamp") // $out/gen/timestamp
 	g.implicitInputs = append(g.implicitInputs, genDirTimestamp)
+	g.implicitInputs = append(g.implicitInputs, g.deps.implicits...)
+	g.implicitInputs = append(g.implicitInputs, g.deps.preprocessed...)
 
-	importPaths, implicits := getImportsFromDeps(ctx, g.properties.IsToT)
-	imports = append(imports, importPaths...)
-
+	imports = append(imports, g.deps.imports...)
 	g.importFlags = strings.Join(wrap("-I", imports, ""), " ")
 
 	g.genOutDir = android.PathForModuleGen(ctx)
@@ -123,10 +138,9 @@
 
 	// This is to clean genOutDir before generating any file
 	ctx.Build(pctx, android.BuildParams{
-		Rule:      aidlDirPrepareRule,
-		Implicits: implicits,
-		Inputs:    srcs,
-		Output:    genDirTimestamp,
+		Rule:   aidlDirPrepareRule,
+		Inputs: srcs,
+		Output: genDirTimestamp,
 		Args: map[string]string{
 			"outDir": g.genOutDir.String(),
 		},
@@ -141,7 +155,8 @@
 }
 
 func (g *aidlGenRule) generateBuildActionsForSingleAidl(ctx android.ModuleContext, src android.Path) (android.WritablePath, android.Paths) {
-	baseDir := getBaseDir(ctx, src, android.PathForModuleSrc(ctx, g.properties.AidlRoot))
+	relPath := src.Rel()
+	baseDir := strings.TrimSuffix(strings.TrimSuffix(src.String(), relPath), "/")
 
 	var ext string
 	if g.properties.Lang == langJava {
@@ -151,7 +166,6 @@
 	} else {
 		ext = "cpp"
 	}
-	relPath, _ := filepath.Rel(baseDir, src.String())
 	outFile := android.PathForModuleGen(ctx, pathtools.ReplaceExtension(relPath, ext))
 	implicits := g.implicitInputs
 
@@ -160,10 +174,10 @@
 		optionalFlags = append(optionalFlags, "--version "+g.properties.Version)
 
 		hash := "notfrozen"
-		if !strings.HasPrefix(baseDir, ctx.Config().BuildDir()) {
+		if !strings.HasPrefix(baseDir, ctx.Config().SoongOutDir()) {
 			hashFile := android.ExistentPathForSource(ctx, baseDir, ".hash")
 			if hashFile.Valid() {
-				hash = "$$(read -r <" + hashFile.Path().String() + " hash extra; printf '%s' \"$$hash\")"
+				hash = "$$(tail -1 '" + hashFile.Path().String() + "')"
 				implicits = append(implicits, hashFile.Path())
 
 				g.hashFile = hashFile.Path()
@@ -171,12 +185,22 @@
 		}
 		optionalFlags = append(optionalFlags, "--hash "+hash)
 	}
+	if g.properties.GenRpc {
+		optionalFlags = append(optionalFlags, "--rpc")
+	}
 	if g.properties.GenTrace {
 		optionalFlags = append(optionalFlags, "-t")
 	}
 	if g.properties.Stability != nil {
 		optionalFlags = append(optionalFlags, "--stability", *g.properties.Stability)
 	}
+	if g.properties.Platform_apis {
+		optionalFlags = append(optionalFlags, "--min_sdk_version platform_apis")
+	} else {
+		minSdkVer := proptools.StringDefault(g.properties.Min_sdk_version, "current")
+		optionalFlags = append(optionalFlags, "--min_sdk_version "+minSdkVer)
+	}
+	optionalFlags = append(optionalFlags, wrap("-p", g.deps.preprocessed.Strings(), "")...)
 
 	var headers android.WritablePaths
 	if g.properties.Lang == langJava {
@@ -272,17 +296,6 @@
 }
 
 func (g *aidlGenRule) DepsMutator(ctx android.BottomUpMutatorContext) {
-	// original interface
-	ctx.AddDependency(ctx.Module(), interfaceDep, g.properties.BaseName+aidlInterfaceSuffix)
-
-	if !proptools.Bool(g.properties.Unstable) {
-		// for checkapi timestamps
-		ctx.AddDependency(ctx.Module(), apiDep, g.properties.BaseName+aidlApiSuffix)
-	}
-
-	// imported interfaces
-	ctx.AddDependency(ctx.Module(), importInterfaceDep, wrap("", g.properties.ImportsWithoutVersion, aidlInterfaceSuffix)...)
-
 	ctx.AddReverseDependency(ctx.Module(), nil, aidlMetadataSingletonName)
 }
 
diff --git a/build/aidl_interface.go b/build/aidl_interface.go
index 251d0d6..8d27826 100644
--- a/build/aidl_interface.go
+++ b/build/aidl_interface.go
@@ -27,8 +27,8 @@
 	"sort"
 	"strconv"
 	"strings"
-	"sync"
 
+	"github.com/google/blueprint"
 	"github.com/google/blueprint/proptools"
 )
 
@@ -40,8 +40,10 @@
 	langCpp                   = "cpp"
 	langJava                  = "java"
 	langNdk                   = "ndk"
-	langNdkPlatform           = "ndk_platform"
 	langRust                  = "rust"
+	// TODO(b/161456198) remove the NDK platform backend as the 'platform' variant of the NDK
+	// backend serves the same purpose.
+	langNdkPlatform = "ndk_platform"
 
 	currentVersion = "current"
 )
@@ -53,128 +55,113 @@
 func init() {
 	pctx.Import("android/soong/android")
 	pctx.HostBinToolVariable("aidlCmd", "aidl")
+	pctx.HostBinToolVariable("aidlHashGen", "aidl_hash_gen")
 	pctx.SourcePathVariable("aidlToJniCmd", "system/tools/aidl/build/aidl_to_jni.py")
 	pctx.SourcePathVariable("aidlRustGlueCmd", "system/tools/aidl/build/aidl_rust_glue.py")
 	android.RegisterModuleType("aidl_interface", aidlInterfaceFactory)
-	android.PreArchMutators(registerPreDepsMutators)
-	android.PreArchBp2BuildMutators(registerPreDepsMutators)
-	android.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
-		ctx.BottomUp("checkUnstableModule", checkUnstableModuleMutator).Parallel()
-		ctx.BottomUp("recordVersions", recordVersions).Parallel()
-		ctx.BottomUp("checkDuplicatedVersions", checkDuplicatedVersions).Parallel()
-	})
+	android.PreArchMutators(registerPreArchMutators)
+	android.PreArchBp2BuildMutators(registerPreArchMutators)
+	android.PostDepsMutators(registerPostDepsMutators)
 }
 
-func registerPreDepsMutators(ctx android.RegisterMutatorsContext) {
+func registerPreArchMutators(ctx android.RegisterMutatorsContext) {
+	ctx.BottomUp("addInterfaceDeps", addInterfaceDeps).Parallel()
 	ctx.BottomUp("checkImports", checkImports).Parallel()
 	ctx.TopDown("createAidlInterface", createAidlInterfaceMutator).Parallel()
 }
 
+func registerPostDepsMutators(ctx android.RegisterMutatorsContext) {
+	ctx.BottomUp("checkAidlGeneratedModules", checkAidlGeneratedModules).Parallel()
+}
+
 func createAidlInterfaceMutator(mctx android.TopDownMutatorContext) {
 	if g, ok := mctx.Module().(*aidlImplementationGenerator); ok {
 		g.GenerateImplementation(mctx)
 	}
 }
 
-func checkUnstableModuleMutator(mctx android.BottomUpMutatorContext) {
-	// If it is an aidl interface, we don't need to check its dependencies.
-	if isAidlModule(mctx.ModuleName(), mctx.Config()) {
-		return
-	}
-	mctx.VisitDirectDepsIf(func(m android.Module) bool {
-		return android.InList(m.Name(), *unstableModules(mctx.Config()))
-	}, func(m android.Module) {
-		if mctx.ModuleName() == m.Name() {
-			return
-		}
-		// TODO(b/154066686): Replace it with a common method instead of listing up module types.
-		// Test libraries are exempted.
-		if android.InList(mctx.ModuleType(), []string{"cc_test_library", "android_test", "cc_benchmark", "cc_test"}) {
-			return
-		}
+// A marker struct for AIDL-generated library modules
+type AidlGeneratedModuleProperties struct{}
 
-		mctx.ModuleErrorf(m.Name() + " is disallowed in release version because it is unstable, and its \"owner\" property is missing.")
-	})
+func wrapLibraryFactory(factory func() android.Module) func() android.Module {
+	return func() android.Module {
+		m := factory()
+		// put a marker struct for AIDL-generated modules
+		m.AddProperties(&AidlGeneratedModuleProperties{})
+		return m
+	}
 }
 
-func isAidlModule(moduleName string, config android.Config) bool {
-	for _, i := range *aidlInterfaces(config) {
-		if android.InList(moduleName, i.internalModuleNames) {
+func isAidlGeneratedModule(module android.Module) bool {
+	for _, props := range module.GetProperties() {
+		// check if there's a marker struct
+		if _, ok := props.(*AidlGeneratedModuleProperties); ok {
 			return true
 		}
 	}
 	return false
 }
 
-func recordVersions(mctx android.BottomUpMutatorContext) {
-	switch mctx.Module().(type) {
-	case *java.Library:
-	case *cc.Module:
-	case *rust.Module:
-	case *aidlGenRule:
-	default:
-		return
-	}
-
-	isAidlModule := isAidlModule(mctx.ModuleName(), mctx.Config())
-
-	// First, gather all the AIDL interfaces modules that are directly or indirectly
-	// depended on by this module
-	myAidlDeps := make(map[DepInfo]bool)
-	mctx.VisitDirectDeps(func(dep android.Module) {
-		switch dep.(type) {
-		case *java.Library:
-		case *cc.Module:
-		case *rust.Module:
-		case *aidlGenRule:
-			// Dependencies to the source module is tracked only when it's from a client
-			// module, i.e. not from an AIDL-generated stub library
-			if isAidlModule {
-				return
-			}
-		default:
-			return
-		}
-		depName := mctx.OtherModuleName(dep)
-		isSource := strings.HasSuffix(depName, "-source")
-		depName = strings.TrimSuffix(depName, "-source")
-		// If this module depends on one of the aidl interface module, record it
-		for _, i := range *aidlInterfaces(mctx.Config()) {
-			if android.InList(depName, i.internalModuleNames) {
-				ifaceName := i.ModuleBase.Name()
-				verLang := depName[len(ifaceName):]
-				myAidlDeps[DepInfo{ifaceName, verLang, isSource}] = true
-				break
-			}
-		}
-		// If dep is in aidlDeps, that means dep has direct or indirect dependencies to AIDL interfaces
-		// That becomes this module's aidlDeps as well
-		aidlDepsMutex.RLock()
-		if depsOfDep, ok := aidlDeps(mctx.Config())[dep]; ok {
-			for _, d := range depsOfDep {
-				myAidlDeps[d] = true
-			}
-		}
-		aidlDepsMutex.RUnlock()
-	})
-
-	if len(myAidlDeps) == 0 {
-		// This should be usual case.
-		return
-	}
-
-	// Then, record the aidl deps of this module to the global map so that it can be used by
-	// next runs of this mutator for the modules that depend on this module.
-	var list []DepInfo
-	for d := range myAidlDeps {
-		list = append(list, d)
-	}
-	aidlDepsMutex.Lock()
-	aidlDeps(mctx.Config())[mctx.Module()] = list
-	aidlDepsMutex.Unlock()
+// AildVersionInfo keeps the *-source module for each (aidl_interface & lang) and the list of
+// not-frozen versions (which shouldn't be used by other modules)
+type AildVersionInfo struct {
+	notFrozen []string
+	sourceMap map[string]string
 }
 
-func checkDuplicatedVersions(mctx android.BottomUpMutatorContext) {
+var AidlVersionInfoProvider = blueprint.NewMutatorProvider(AildVersionInfo{}, "checkAidlGeneratedModules")
+
+// Merges `other` version info into this one.
+// Returns the pair of mismatching versions when there's conflict. Otherwise returns nil.
+// For example, when a module depends on 'foo-V2-ndk', the map contains an entry of (foo, foo-V2-ndk-source).
+// Merging (foo, foo-V1-ndk-source) and (foo, foo-V2-ndk-source) will fail and returns
+// {foo-V1-ndk-source, foo-V2-ndk-source}.
+func (info *AildVersionInfo) merge(other AildVersionInfo) []string {
+	info.notFrozen = append(info.notFrozen, other.notFrozen...)
+
+	if other.sourceMap == nil {
+		return nil
+	}
+	if info.sourceMap == nil {
+		info.sourceMap = make(map[string]string)
+	}
+	for ifaceName, otherSourceName := range other.sourceMap {
+		if sourceName, ok := info.sourceMap[ifaceName]; ok {
+			if sourceName != otherSourceName {
+				return []string{sourceName, otherSourceName}
+			}
+		} else {
+			info.sourceMap[ifaceName] = otherSourceName
+		}
+	}
+	return nil
+}
+
+func reportUsingNotFrozenError(ctx android.BaseModuleContext, notFrozen []string) {
+	// TODO(b/154066686): Replace it with a common method instead of listing up module types.
+	// Test libraries are exempted.
+	if android.InList(ctx.ModuleType(), []string{"cc_test_library", "android_test", "cc_benchmark", "cc_test"}) {
+		return
+	}
+	for _, name := range notFrozen {
+		ctx.ModuleErrorf("%v is disallowed in release version because it is unstable, and its \"owner\" property is missing.",
+			name)
+	}
+}
+
+func reportMultipleVersionError(ctx android.BaseModuleContext, violators []string) {
+	sort.Strings(violators)
+	ctx.ModuleErrorf("depends on multiple versions of the same aidl_interface: %s", strings.Join(violators, ", "))
+	ctx.WalkDeps(func(child android.Module, parent android.Module) bool {
+		if android.InList(child.Name(), violators) {
+			ctx.ModuleErrorf("Dependency path: %s", ctx.GetPathString(true))
+			return false
+		}
+		return true
+	})
+}
+
+func checkAidlGeneratedModules(mctx android.BottomUpMutatorContext) {
 	switch mctx.Module().(type) {
 	case *java.Library:
 	case *cc.Module:
@@ -183,47 +170,37 @@
 	default:
 		return
 	}
-
-	aidlDepsMutex.RLock()
-	myAidlDeps := aidlDeps(mctx.Config())[mctx.Module()]
-	aidlDepsMutex.RUnlock()
-	if myAidlDeps == nil || len(myAidlDeps) == 0 {
-		return // This should be the usual case
+	if gen, ok := mctx.Module().(*aidlGenRule); ok {
+		var notFrozen []string
+		if gen.properties.NotFrozen {
+			notFrozen = []string{strings.TrimSuffix(mctx.ModuleName(), "-source")}
+		}
+		mctx.SetProvider(AidlVersionInfoProvider, AildVersionInfo{
+			notFrozen: notFrozen,
+			sourceMap: map[string]string{
+				gen.properties.BaseName + "-" + gen.properties.Lang: gen.Name(),
+			},
+		})
+		return
 	}
-
-	// Lastly, report an error if there is any duplicated versions of the same interface * lang
-	for _, lang := range []string{langJava, langCpp, langNdk, langNdkPlatform} {
-		// interfaceName -> verLang -> list of module names
-		versionsOf := make(map[string]map[string][]string)
-		for _, dep := range myAidlDeps {
-			if !strings.HasSuffix(dep.verLang, lang) {
-				continue
-			}
-			versions := versionsOf[dep.ifaceName]
-			if versions == nil {
-				versions = make(map[string][]string)
-				versionsOf[dep.ifaceName] = versions
-			}
-			versions[dep.verLang] = append(versions[dep.verLang], dep.moduleName())
-		}
-
-		for _, versions := range versionsOf {
-			if len(versions) >= 2 {
-				var violators []string
-				for _, modules := range versions {
-					violators = append(violators, modules...)
-				}
-				violators = android.SortedUniqueStrings(violators)
-				mctx.ModuleErrorf("depends on multiple versions of the same aidl_interface: %s", strings.Join(violators, ", "))
-				mctx.WalkDeps(func(child android.Module, parent android.Module) bool {
-					if android.InList(child.Name(), violators) {
-						mctx.ModuleErrorf("Dependency path: %s", mctx.GetPathString(true))
-						return false
-					}
-					return true
-				})
+	// Collect/merge AildVersionInfos from direct dependencies
+	var info AildVersionInfo
+	mctx.VisitDirectDeps(func(dep android.Module) {
+		if mctx.OtherModuleHasProvider(dep, AidlVersionInfoProvider) {
+			otherInfo := mctx.OtherModuleProvider(dep, AidlVersionInfoProvider).(AildVersionInfo)
+			if violators := info.merge(otherInfo); violators != nil {
+				reportMultipleVersionError(mctx, violators)
 			}
 		}
+	})
+	if !isAidlGeneratedModule(mctx.Module()) && len(info.notFrozen) > 0 {
+		reportUsingNotFrozenError(mctx, info.notFrozen)
+	}
+	if mctx.Failed() {
+		return
+	}
+	if info.sourceMap != nil || len(info.notFrozen) > 0 {
+		mctx.SetProvider(AidlVersionInfoProvider, info)
 	}
 }
 
@@ -238,7 +215,7 @@
 	}
 
 	if len(srcs) == 0 {
-		ctx.PropertyErrorf("srcs", "No sources provided.")
+		ctx.PropertyErrorf("srcs", "No sources provided in %v", root)
 	}
 
 	// gather base directories from input .aidl files
@@ -275,11 +252,6 @@
 	// For native modules, the property needs to be set when a module is a part of mainline modules(APEX).
 	// Forwarded to generated java/native module.
 	Min_sdk_version *string
-
-	// Determines whether the generated source files are available or not. When set to true,
-	// the source files can be added to `srcs` property via `:<ifacename>-<backend>-source`,
-	// e.g., ":myaidl-java-source"
-	Srcs_available *bool
 }
 
 type CommonNativeBackendProperties struct {
@@ -321,6 +293,9 @@
 	// Whether the library can be installed on the product image.
 	Product_available *bool
 
+	// Whether the library can be installed on the recovery image.
+	Recovery_available *bool
+
 	// Whether the library can be loaded multiple times into the same process
 	Double_loadable *bool
 
@@ -344,12 +319,6 @@
 	// It could be an aidl_interface solely or with version(such as -V1)
 	Imports []string
 
-	// List of aidl_interface modules that this uses. It trims version suffix in 'Imports' field.
-	ImportsWithoutVersion []string `blueprint:"mutated"`
-
-	// Used by gen dependency to fill out aidl include path
-	Full_import_paths []string `blueprint:"mutated"`
-
 	// Stability promise. Currently only supports "vintf".
 	// If this is unset, this corresponds to an interface with stability within
 	// this compilation context (so an interface loaded here can only be used
@@ -362,6 +331,12 @@
 	// the list is considered as the most recent version.
 	Versions []string
 
+	// The minimum version of the sdk that the compiled artifacts will run against
+	// For native modules, the property needs to be set when a module is a part of mainline modules(APEX).
+	// Forwarded to generated java/native module. This can be overridden by
+	// backend.<name>.min_sdk_version.
+	Min_sdk_version *string
+
 	Backend struct {
 		// Backend of the compiler generating code for Java clients.
 		// When enabled, this creates a target called "<name>-java".
@@ -373,6 +348,11 @@
 			// Whether to compile against platform APIs instead of
 			// an SDK.
 			Platform_apis *bool
+			// Whether RPC features are enabled (requires API level 32)
+			// TODO(b/175819535): enable this automatically?
+			Gen_rpc *bool
+			// Lint properties for generated java module
+			java.LintProperties
 		}
 		// Backend of the compiler generating code for C++ clients using
 		// libbinder (unstable C++ interface)
@@ -380,19 +360,18 @@
 		Cpp struct {
 			CommonNativeBackendProperties
 		}
-		// Backend of the compiler generating code for C++ clients using
-		// libbinder_ndk (stable C interface to system's libbinder)
-		// When enabled, this creates a target called "<name>-ndk"
-		// (for apps) and "<name>-ndk_platform" (for platform usage).
+		// Backend of the compiler generating code for C++ clients using libbinder_ndk
+		// (stable C interface to system's libbinder) When enabled, this creates a target
+		// called "<name>-V<ver>-ndk" (for both apps and platform) and
+		// "<name>-V<ver>-ndk_platform" (for platform only).
+		// TODO(b/161456198): remove the ndk_platform backend as the ndk backend can serve
+		// the same purpose.
 		Ndk struct {
 			CommonNativeBackendProperties
 
-			// Currently, all ndk-supported interfaces generate two variants:
-			// - ndk - for apps to use, against an NDK
-			// - ndk_platform - for the platform to use
-			//
-			// This adds an option to disable the 'ndk' variant in cases where APIs
-			// only available in the platform version work.
+			// If set to false, the ndk backend is exclusive to platform and is not
+			// available to applications. Default is true (i.e. available to both
+			// applications and platform).
 			Apps_enabled *bool
 		}
 		// Backend of the compiler generating code for Rust clients.
@@ -422,61 +401,163 @@
 
 	// list of module names that are created for this interface
 	internalModuleNames []string
+
+	// map for version to preprocessed.aidl file.
+	// There's two additional alias for versions:
+	// - ""(empty) is for ToT
+	// - "latest" is for i.latestVersion()
+	preprocessed map[string]android.WritablePath
 }
 
 func (i *aidlInterface) shouldGenerateJavaBackend() bool {
 	// explicitly true if not specified to give early warning to devs
-	return i.properties.Backend.Java.Enabled == nil || *i.properties.Backend.Java.Enabled
+	return proptools.BoolDefault(i.properties.Backend.Java.Enabled, true)
 }
 
 func (i *aidlInterface) shouldGenerateCppBackend() bool {
 	// explicitly true if not specified to give early warning to devs
-	return i.properties.Backend.Cpp.Enabled == nil || *i.properties.Backend.Cpp.Enabled
+	return proptools.BoolDefault(i.properties.Backend.Cpp.Enabled, true)
 }
 
 func (i *aidlInterface) shouldGenerateNdkBackend() bool {
 	// explicitly true if not specified to give early warning to devs
-	return i.properties.Backend.Ndk.Enabled == nil || *i.properties.Backend.Ndk.Enabled
+	return proptools.BoolDefault(i.properties.Backend.Ndk.Enabled, true)
 }
 
+// Returns whether the ndk backend supports applications or not. Default is `true`. `false` is
+// returned when `apps_enabled` is explicitly set to false or the interface is exclusive to vendor
+// (i.e. `vendor: true`). Note that the ndk_platform backend (which will be removed in the future)
+// is not affected by this. In other words, it is always exclusive for the platform, as its name
+// clearly shows.
 func (i *aidlInterface) shouldGenerateAppNdkBackend() bool {
-	if !i.shouldGenerateNdkBackend() {
-		return false
-	}
-	// explicitly true if not specified to give early warning to devs
-	return i.properties.Backend.Ndk.Apps_enabled == nil || *i.properties.Backend.Ndk.Apps_enabled
+	return i.shouldGenerateNdkBackend() &&
+		proptools.BoolDefault(i.properties.Backend.Ndk.Apps_enabled, true) &&
+		!i.SocSpecific()
 }
 
 func (i *aidlInterface) shouldGenerateRustBackend() bool {
 	return i.properties.Backend.Rust.Enabled != nil && *i.properties.Backend.Rust.Enabled
 }
 
-func (i *aidlInterface) gatherInterface(mctx android.LoadHookContext) {
-	aidlInterfaces := aidlInterfaces(mctx.Config())
-	aidlInterfaceMutex.Lock()
-	defer aidlInterfaceMutex.Unlock()
-	*aidlInterfaces = append(*aidlInterfaces, i)
+func (i *aidlInterface) minSdkVersion(lang string) *string {
+	var ver *string
+	switch lang {
+	case langCpp:
+		ver = i.properties.Backend.Cpp.Min_sdk_version
+	case langJava:
+		ver = i.properties.Backend.Java.Min_sdk_version
+	case langNdk, langNdkPlatform:
+		ver = i.properties.Backend.Ndk.Min_sdk_version
+	case langRust:
+		ver = i.properties.Backend.Rust.Min_sdk_version
+	default:
+		panic(fmt.Errorf("unsupported language backend %q\n", lang))
+	}
+	if ver == nil {
+		return i.properties.Min_sdk_version
+	}
+	return ver
 }
 
-func addUnstableModule(mctx android.LoadHookContext, moduleName string) {
-	unstableModules := unstableModules(mctx.Config())
-	unstableModuleMutex.Lock()
-	defer unstableModuleMutex.Unlock()
-	*unstableModules = append(*unstableModules, moduleName)
+// Dep to *-api module(aidlApi)
+type apiDepTag struct {
+	blueprint.BaseDependencyTag
+	name string
 }
 
+type importInterfaceDepTag struct {
+	blueprint.BaseDependencyTag
+	anImport string
+}
+
+type interfaceDepTag struct {
+	blueprint.BaseDependencyTag
+}
+
+var (
+	// Dep from *-source (aidlGenRule) to *-api (aidlApi)
+	apiDep = apiDepTag{name: "api"}
+	// Dep from *-api (aidlApi) to *-api (aidlApi), representing imported interfaces
+	importApiDep = apiDepTag{name: "imported-api"}
+	// Dep to original *-interface (aidlInterface)
+	interfaceDep = interfaceDepTag{}
+)
+
+func addImportedInterfaceDeps(ctx android.BottomUpMutatorContext, imports []string) {
+	for _, anImport := range imports {
+		name, _ := parseModuleWithVersion(anImport)
+		ctx.AddDependency(ctx.Module(), importInterfaceDepTag{anImport: anImport}, name+aidlInterfaceSuffix)
+	}
+}
+
+// Run custom "Deps" mutator between AIDL modules created at LoadHook stage.
+// We can't use the "DepsMutator" for these dependencies because
+// - We need to create library modules (cc/java/...) before "arch" mutator. Note that cc_library
+//   should be mutated by os/image/arch mutators as well.
+// - When creating library modules, we need to access the original interface and its imported
+//   interfaces to determine which version to use. See aidlInterface.getImportWithVersion.
+func addInterfaceDeps(mctx android.BottomUpMutatorContext) {
+	switch i := mctx.Module().(type) {
+	case *aidlInterface:
+		// In fact this isn't necessary because soong checks dependencies on undefined modules.
+		// But since aidl_interface overrides its name internally, this provides better error message.
+		for _, anImportWithVersion := range i.properties.Imports {
+			anImport, _ := parseModuleWithVersion(anImportWithVersion)
+			if !mctx.OtherModuleExists(anImport + aidlInterfaceSuffix) {
+				if !mctx.Config().AllowMissingDependencies() {
+					mctx.PropertyErrorf("imports", "Import does not exist: "+anImport)
+				}
+			}
+		}
+		if mctx.Failed() {
+			return
+		}
+		addImportedInterfaceDeps(mctx, i.properties.Imports)
+	case *aidlImplementationGenerator:
+		mctx.AddDependency(i, interfaceDep, i.properties.AidlInterfaceName+aidlInterfaceSuffix)
+		addImportedInterfaceDeps(mctx, i.properties.Imports)
+	case *rust.Module:
+		for _, props := range i.GetProperties() {
+			if sp, ok := props.(*aidlRustSourceProviderProperties); ok {
+				mctx.AddDependency(i, interfaceDep, sp.AidlInterfaceName+aidlInterfaceSuffix)
+				addImportedInterfaceDeps(mctx, sp.Imports)
+				break
+			}
+		}
+	case *aidlApi:
+		mctx.AddDependency(i, interfaceDep, i.properties.BaseName+aidlInterfaceSuffix)
+		addImportedInterfaceDeps(mctx, i.properties.Imports)
+		for _, anImport := range i.properties.Imports {
+			name, _ := parseModuleWithVersion(anImport)
+			mctx.AddDependency(i, importApiDep, name+aidlApiSuffix)
+		}
+	case *aidlGenRule:
+		mctx.AddDependency(i, interfaceDep, i.properties.BaseName+aidlInterfaceSuffix)
+		addImportedInterfaceDeps(mctx, i.properties.Imports)
+		if !proptools.Bool(i.properties.Unstable) {
+			// for checkapi timestamps
+			mctx.AddDependency(i, apiDep, i.properties.BaseName+aidlApiSuffix)
+		}
+	}
+}
+
+// checkImports checks if "import:" property is valid.
+// In fact, this isn't necessary because Soong can check/report when we add a dependency to
+// undefined/unknown module. But module names are very implementation specific and may not be easy
+// to understand. For example, when foo (with java enabled) depends on bar (with java disabled), the
+// error message would look like "foo-V2-java depends on unknown module `bar-V3-java`", which isn't
+// clear that backend.java.enabled should be turned on.
 func checkImports(mctx android.BottomUpMutatorContext) {
 	if i, ok := mctx.Module().(*aidlInterface); ok {
-		for _, anImportWithVersion := range i.properties.Imports {
-			anImport, version := parseModuleWithVersion(anImportWithVersion)
-			other := lookupInterface(anImport, mctx.Config())
-
-			if other == nil {
-				if mctx.Config().AllowMissingDependencies() {
-					continue
-				}
-				mctx.PropertyErrorf("imports", "Import does not exist: "+anImport)
+		mctx.VisitDirectDeps(func(dep android.Module) {
+			tag, ok := mctx.OtherModuleDependencyTag(dep).(importInterfaceDepTag)
+			if !ok {
+				return
 			}
+			other := dep.(*aidlInterface)
+			anImport := other.ModuleBase.Name()
+			anImportWithVersion := tag.anImport
+			_, version := parseModuleWithVersion(tag.anImport)
 			if version != "" {
 				candidateVersions := concat(other.properties.Versions, []string{other.nextVersion()})
 				if !android.InList(version, candidateVersions) {
@@ -502,7 +583,7 @@
 				mctx.PropertyErrorf("backend.rust.enabled",
 					"Rust backend not enabled in the imported AIDL interface %q", anImport)
 			}
-		}
+		})
 	}
 }
 
@@ -632,17 +713,10 @@
 	if hasVersionSuffix(i.ModuleBase.Name()) {
 		mctx.PropertyErrorf("name", "aidl_interface should not have '-V<number> suffix")
 	}
-	i.properties.ImportsWithoutVersion = trimVersionSuffixInList(i.properties.Imports)
 	if !isRelativePath(i.properties.Local_include_dir) {
 		mctx.PropertyErrorf("local_include_dir", "must be relative path: "+i.properties.Local_include_dir)
 	}
-	var importPaths []string
-	importPaths = append(importPaths, filepath.Join(mctx.ModuleDir(), i.properties.Local_include_dir))
-	importPaths = append(importPaths, i.properties.Include_dirs...)
 
-	i.properties.Full_import_paths = importPaths
-
-	i.gatherInterface(mctx)
 	i.checkStability(mctx)
 	i.checkVersions(mctx)
 	i.checkVndkUseVersion(mctx)
@@ -653,7 +727,6 @@
 	}
 
 	var libs []string
-	sdkIsFinal := !mctx.Config().DefaultAppTargetSdk(mctx).IsPreview()
 
 	unstable := proptools.Bool(i.properties.Unstable)
 
@@ -668,13 +741,18 @@
 		}
 	}
 
+	sdkIsFinal := !mctx.Config().DefaultAppTargetSdk(mctx).IsPreview()
+	requireFrozenNoOwner := i.Owner() == "" && (sdkIsFinal || mctx.Config().IsEnvTrue("AIDL_FROZEN_REL"))
+	requireFrozenWithOwner := i.Owner() != "" && android.InList(i.Owner(), strings.Fields(mctx.Config().Getenv("AIDL_FROZEN_OWNERS")))
+	requireFrozenByOwner := requireFrozenNoOwner || requireFrozenWithOwner
+
 	// Two different types of 'unstable' here
 	// - 'unstable: true' meaning the module is never stable
 	// - current unfrozen ToT version
 	//
 	// OEM branches may remove 'i.Owner()' here to apply the check to all interfaces, in
 	// addition to core platform interfaces. Otherwise, we rely on vts_treble_vintf_vendor_test.
-	requireFrozenVersion := !unstable && sdkIsFinal && i.Owner() == ""
+	requireFrozenVersion := !unstable && requireFrozenByOwner
 
 	// surface error early, main check is via checkUnstableModuleMutator
 	if requireFrozenVersion && !i.hasVersion() {
@@ -684,21 +762,24 @@
 	versions := i.properties.Versions
 	nextVersion := i.nextVersion()
 	shouldGenerateLangBackendMap := map[string]bool{
-		langCpp:         i.shouldGenerateCppBackend(),
-		langNdk:         i.shouldGenerateAppNdkBackend(),
-		langNdkPlatform: i.shouldGenerateNdkBackend(),
-		langJava:        i.shouldGenerateJavaBackend(),
-		langRust:        i.shouldGenerateRustBackend()}
+		langCpp:  i.shouldGenerateCppBackend(),
+		langNdk:  i.shouldGenerateNdkBackend(),
+		langJava: i.shouldGenerateJavaBackend(),
+		langRust: i.shouldGenerateRustBackend()}
+
+	// The ndk_platform backend is generated only when explicitly requested. This will
+	// eventually be completely removed the devices in the long tail are gone.
+	if mctx.DeviceConfig().GenerateAidlNdkPlatformBackend() {
+		shouldGenerateLangBackendMap[langNdkPlatform] = i.shouldGenerateNdkBackend()
+	}
+
 	for lang, shouldGenerate := range shouldGenerateLangBackendMap {
 		if !shouldGenerate {
 			continue
 		}
-		libs = append(libs, addLibrary(mctx, i, nextVersion, lang))
-		if requireFrozenVersion {
-			addUnstableModule(mctx, libs[len(libs)-1])
-		}
+		libs = append(libs, addLibrary(mctx, i, nextVersion, lang, requireFrozenVersion))
 		for _, version := range versions {
-			libs = append(libs, addLibrary(mctx, i, version, lang))
+			libs = append(libs, addLibrary(mctx, i, version, lang, false))
 		}
 	}
 
@@ -742,86 +823,92 @@
 	}
 }
 
-// srcsVisibility gives the value for the `visibility` property of the source gen module for the
-// language backend `lang`. By default, the source gen module is not visible to the clients of
-// aidl_interface (because it's an impl detail), but when `backend.<backend>.srcs_available` is set
-// to true, the source gen module follows the visibility of the aidl_interface module.
-func srcsVisibility(mctx android.LoadHookContext, lang string) []string {
-	if a, ok := mctx.Module().(*aidlInterface); !ok {
-		panic(fmt.Errorf("%q is not aidl_interface", mctx.Module().String()))
-	} else {
-		if proptools.Bool(a.commonBackendProperties(lang).Srcs_available) {
-			// Returning nil so that the visibility of the source module defaults to the
-			// the package-level default visibility. This way, the source module gets
-			// the same visibility as the library modules.
-			return nil
-		}
-	}
-	return []string{
-		"//" + mctx.ModuleDir(),
-		// system/tools/aidl/build is always added because aidl_metadata_json in the
-		// directory has dependencies to all aidl_interface modules.
-		"//system/tools/aidl/build",
-	}
-}
-
 func (i *aidlInterface) Name() string {
 	return i.ModuleBase.Name() + aidlInterfaceSuffix
 }
+
 func (i *aidlInterface) GenerateAndroidBuildActions(ctx android.ModuleContext) {
-	aidlRoot := android.PathForModuleSrc(ctx, i.properties.Local_include_dir)
-	for _, src := range android.PathsForModuleSrc(ctx, i.properties.Srcs) {
-		baseDir := getBaseDir(ctx, src, aidlRoot)
-		relPath, _ := filepath.Rel(baseDir, src.String())
-		computedType := strings.TrimSuffix(strings.ReplaceAll(relPath, "/", "."), ".aidl")
+	srcs, _ := getPaths(ctx, i.properties.Srcs, i.properties.Local_include_dir)
+	for _, src := range srcs {
+		computedType := strings.TrimSuffix(strings.ReplaceAll(src.Rel(), "/", "."), ".aidl")
 		i.computedTypes = append(i.computedTypes, computedType)
 	}
+
+	i.preprocessed = make(map[string]android.WritablePath)
+	// generate (len(versions) + 1) preprocessed.aidl files
+	for _, version := range concat(i.properties.Versions, []string{i.nextVersion()}) {
+		i.preprocessed[version] = i.buildPreprocessed(ctx, version)
+	}
+	// helpful aliases
+	if !proptools.Bool(i.properties.Unstable) {
+		if i.hasVersion() {
+			i.preprocessed["latest"] = i.preprocessed[i.latestVersion()]
+		} else {
+			// when we have no frozen versions yet, use "next version" as latest
+			i.preprocessed["latest"] = i.preprocessed[i.nextVersion()]
+		}
+		i.preprocessed[""] = i.preprocessed[i.nextVersion()]
+	}
 }
+
+// imported interfaces
+// TODO(b/146436251) use imports in versions_with_info
+// For example, foo-V1 should use bar-V1 while foo-V2 should use bar-V2
+//   name: "foo",
+//   versions_with_info: [
+//     { version: "1", imports: ["bar-V1"]},
+//     { version: "2", imports: ["bar-V2"]},
+//   ]
+func (i *aidlInterface) getImports(version string) map[string]string {
+	imports := make(map[string]string)
+	useLatestStable := !proptools.Bool(i.properties.Unstable) && version != "" && version != i.nextVersion()
+	for _, importString := range i.properties.Imports {
+		name, targetVersion := parseModuleWithVersion(importString)
+		if targetVersion == "" && useLatestStable {
+			targetVersion = "latest"
+		}
+		imports[name] = targetVersion
+	}
+	return imports
+}
+
+// generate preprocessed.aidl which contains only types with evaluated constants.
+// "imports" will use preprocessed.aidl with -p flag to avoid parsing the entire transitive list
+// of dependencies.
+func (i *aidlInterface) buildPreprocessed(ctx android.ModuleContext, version string) android.WritablePath {
+	deps := getDeps(ctx, i.getImports(version))
+
+	preprocessed := android.PathForModuleOut(ctx, version, "preprocessed.aidl")
+	rb := android.NewRuleBuilder(pctx, ctx)
+	srcs, root_dir := i.srcsForVersion(ctx, version)
+
+	if len(srcs) == 0 {
+		ctx.PropertyErrorf("srcs", "No sources for a previous version in %v. Was a version manually added to .bp file? This is added automatically by <module>-freeze-api.", root_dir)
+	}
+
+	paths, imports := getPaths(ctx, srcs, root_dir)
+
+	preprocessCommand := rb.Command().BuiltTool("aidl").
+		FlagWithOutput("--preprocess ", preprocessed).
+		Flag("--structured")
+	if i.properties.Stability != nil {
+		preprocessCommand.FlagWithArg("--stability ", *i.properties.Stability)
+	}
+	preprocessCommand.FlagForEachInput("-p", deps.preprocessed)
+	preprocessCommand.FlagForEachArg("-I", concat(imports, i.properties.Include_dirs))
+	preprocessCommand.Inputs(paths)
+	name := i.BaseModuleName()
+	if version != "" {
+		name += "/" + version
+	}
+	rb.Build("export_"+name, "export types for "+name)
+	return preprocessed
+}
+
 func (i *aidlInterface) DepsMutator(ctx android.BottomUpMutatorContext) {
 	ctx.AddReverseDependency(ctx.Module(), nil, aidlMetadataSingletonName)
 }
 
-var (
-	aidlInterfacesKey   = android.NewOnceKey("aidlInterfaces")
-	unstableModulesKey  = android.NewOnceKey("unstableModules")
-	aidlDepsKey         = android.NewOnceKey("aidlDeps")
-	aidlInterfaceMutex  sync.Mutex
-	unstableModuleMutex sync.Mutex
-	aidlDepsMutex       sync.RWMutex
-)
-
-func aidlInterfaces(config android.Config) *[]*aidlInterface {
-	return config.Once(aidlInterfacesKey, func() interface{} {
-		return &[]*aidlInterface{}
-	}).(*[]*aidlInterface)
-}
-
-func unstableModules(config android.Config) *[]string {
-	return config.Once(unstableModulesKey, func() interface{} {
-		return &[]string{}
-	}).(*[]string)
-}
-
-type DepInfo struct {
-	ifaceName string
-	verLang   string
-	isSource  bool
-}
-
-func (d DepInfo) moduleName() string {
-	name := d.ifaceName + d.verLang
-	if d.isSource {
-		name += "-source"
-	}
-	return name
-}
-
-func aidlDeps(config android.Config) map[android.Module][]DepInfo {
-	return config.Once(aidlDepsKey, func() interface{} {
-		return make(map[android.Module][]DepInfo)
-	}).(map[android.Module][]DepInfo)
-}
-
 func aidlInterfaceFactory() android.Module {
 	i := &aidlInterface{}
 	i.AddProperties(&i.properties)
@@ -829,12 +916,3 @@
 	android.AddLoadHook(i, func(ctx android.LoadHookContext) { aidlInterfaceHook(ctx, i) })
 	return i
 }
-
-func lookupInterface(name string, config android.Config) *aidlInterface {
-	for _, i := range *aidlInterfaces(config) {
-		if i.ModuleBase.Name() == name {
-			return i
-		}
-	}
-	return nil
-}
diff --git a/build/aidl_interface_backends.go b/build/aidl_interface_backends.go
index 79b6625..ac4fce4 100644
--- a/build/aidl_interface_backends.go
+++ b/build/aidl_interface_backends.go
@@ -26,16 +26,16 @@
 	"github.com/google/blueprint/proptools"
 )
 
-func addLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, lang string) string {
+func addLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, lang string, notFrozen bool) string {
 	if lang == langJava {
-		return addJavaLibrary(mctx, i, version)
+		return addJavaLibrary(mctx, i, version, notFrozen)
 	} else if lang == langRust {
-		return addRustLibrary(mctx, i, version)
+		return addRustLibrary(mctx, i, version, notFrozen)
 	}
-	return addCppLibrary(mctx, i, version, lang)
+	return addCppLibrary(mctx, i, version, lang, notFrozen)
 }
 
-func addCppLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, lang string) string {
+func addCppLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, lang string, notFrozen bool) string {
 	cppSourceGen := i.versionedName(version) + "-" + lang + "-source"
 	cppModuleGen := i.versionedName(version) + "-" + lang
 
@@ -73,30 +73,32 @@
 	mctx.CreateModule(aidlGenFactory, &nameProperties{
 		Name: proptools.StringPtr(cppSourceGen),
 	}, &aidlGenProperties{
-		Srcs:                  srcs,
-		AidlRoot:              aidlRoot,
-		IsToT:                 version == i.nextVersion(),
-		ImportsWithoutVersion: i.properties.ImportsWithoutVersion,
-		Stability:             i.properties.Stability,
-		Lang:                  lang,
-		BaseName:              i.ModuleBase.Name(),
-		GenLog:                genLog,
-		Version:               i.versionForAidlGenRule(version),
-		GenTrace:              genTrace,
-		Unstable:              i.properties.Unstable,
-		Visibility:            srcsVisibility(mctx, lang),
-		Flags:                 i.flagsForAidlGenRule(version),
+		Srcs:            srcs,
+		AidlRoot:        aidlRoot,
+		Imports:         i.properties.Imports,
+		Stability:       i.properties.Stability,
+		Min_sdk_version: i.minSdkVersion(lang),
+		Lang:            lang,
+		BaseName:        i.ModuleBase.Name(),
+		GenLog:          genLog,
+		Version:         i.versionForAidlGenRule(version),
+		GenTrace:        genTrace,
+		Unstable:        i.properties.Unstable,
+		NotFrozen:       notFrozen,
+		Flags:           i.flagsForAidlGenRule(version),
 	})
 
 	importExportDependencies := []string{}
 	var sharedLibDependency []string
 	var headerLibs []string
 	var sdkVersion *string
-	var minSdkVersion *string
 	var stl *string
 	var cpp_std *string
 	var hostSupported *bool
 	var addCflags []string
+	targetProp := ccTargetProperties{
+		Darwin: darwinProperties{Enabled: proptools.BoolPtr(false)},
+	}
 
 	if lang == langCpp {
 		importExportDependencies = append(importExportDependencies, "libbinder", "libutils")
@@ -104,24 +106,26 @@
 			sharedLibDependency = append(sharedLibDependency, "libcutils")
 		}
 		hostSupported = i.properties.Host_supported
-		minSdkVersion = i.properties.Backend.Cpp.Min_sdk_version
-	} else if lang == langNdk {
+	} else if lang == langNdk || lang == langNdkPlatform {
 		importExportDependencies = append(importExportDependencies, "libbinder_ndk")
+		nonAppProps := imageProperties{
+			Cflags: []string{"-DBINDER_STABILITY_SUPPORT"},
+		}
 		if genTrace {
 			sharedLibDependency = append(sharedLibDependency, "libandroid")
+			nonAppProps.Exclude_shared_libs = []string{"libandroid"}
+			nonAppProps.Header_libs = []string{"libandroid_aidltrace"}
+			nonAppProps.Shared_libs = []string{"libcutils"}
 		}
-		sdkVersion = proptools.StringPtr("current")
-		stl = proptools.StringPtr("c++_shared")
-		minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
-	} else if lang == langNdkPlatform {
-		importExportDependencies = append(importExportDependencies, "libbinder_ndk")
-		if genTrace {
-			headerLibs = append(headerLibs, "libandroid_aidltrace")
-			sharedLibDependency = append(sharedLibDependency, "libcutils")
-		}
+		targetProp.Platform = nonAppProps
+		targetProp.Vendor = nonAppProps
+		targetProp.Product = nonAppProps
 		hostSupported = i.properties.Host_supported
-		addCflags = append(addCflags, "-DBINDER_STABILITY_SUPPORT")
-		minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
+		if lang == langNdk && i.shouldGenerateAppNdkBackend() {
+			sdkVersion = proptools.StringPtr("current")
+			// Don't worry! This maps to libc++.so for the platform variant.
+			stl = proptools.StringPtr("c++_shared")
+		}
 	} else {
 		panic("Unrecognized language: " + lang)
 	}
@@ -129,6 +133,7 @@
 	vendorAvailable := i.properties.Vendor_available
 	odmAvailable := i.properties.Odm_available
 	productAvailable := i.properties.Product_available
+	recoveryAvailable := i.properties.Recovery_available
 	if lang == langCpp {
 		// Vendor and product modules cannot use the libbinder (cpp) backend of AIDL in a
 		// way that is stable. So, in order to prevent accidental usage of these library by
@@ -145,31 +150,20 @@
 		productAvailable = nil
 	}
 
-	if lang == langNdk {
-		// TODO(b/121157555): when the NDK variant is its own variant, these wouldn't interact,
-		// but we can't create a vendor or product version of an NDK variant
-		//
-		// nil (unspecified) is used instead of false so that this can't conflict with
-		// 'vendor: true', for instance.
-		vendorAvailable = nil
-		odmAvailable = nil
-		productAvailable = nil
-		overrideVndkProperties.Vndk.Enabled = proptools.BoolPtr(false)
-		overrideVndkProperties.Vndk.Support_system_process = proptools.BoolPtr(false)
-	}
-
 	mctx.CreateModule(aidlImplementationGeneratorFactory, &nameProperties{
 		Name: proptools.StringPtr(cppModuleGen + "-generator"),
 	}, &aidlImplementationGeneratorProperties{
 		Lang:              lang,
 		AidlInterfaceName: i.ModuleBase.Name(),
 		Version:           version,
+		Imports:           i.properties.Imports,
 		ModuleProperties: []interface{}{
 			&ccProperties{
 				Name:                      proptools.StringPtr(cppModuleGen),
 				Vendor_available:          vendorAvailable,
 				Odm_available:             odmAvailable,
 				Product_available:         productAvailable,
+				Recovery_available:        recoveryAvailable,
 				Host_supported:            hostSupported,
 				Defaults:                  []string{"aidl-cpp-module-defaults"},
 				Double_loadable:           i.properties.Double_loadable,
@@ -184,21 +178,9 @@
 				Cpp_std:                   cpp_std,
 				Cflags:                    append(addCflags, "-Wextra", "-Wall", "-Werror", "-Wextra-semi"),
 				Apex_available:            commonProperties.Apex_available,
-				Min_sdk_version:           minSdkVersion,
-				UseApexNameMacro:          true,
-				Target: ccTargetProperties{
-					// Currently necessary for host builds
-					// TODO(b/31559095): bionic on host should define this
-					// TODO(b/146436251): default isn't applied because the module is created
-					// in PreArchMutators, when import behavior becomes explicit, the logic can
-					// be moved back to LoadHook
-					Host: hostProperties{Cflags: []string{
-						"-D__INTRODUCED_IN(n)=",
-						"-D__assert(a,b,c)=",
-						// We want all the APIs to be available on the host.
-						"-D__ANDROID_API__=10000"}},
-					Darwin: perTargetProperties{Enabled: proptools.BoolPtr(false)}},
-				Tidy: proptools.BoolPtr(true),
+				Min_sdk_version:           i.minSdkVersion(lang),
+				Target:                    targetProp,
+				Tidy:                      proptools.BoolPtr(true),
 				// Do the tidy check only for the generated headers
 				Tidy_flags:            []string{"--header-filter=" + android.PathForOutput(mctx).String() + ".*"},
 				Tidy_checks_as_errors: []string{"*"},
@@ -211,7 +193,7 @@
 	return cppModuleGen
 }
 
-func addJavaLibrary(mctx android.LoadHookContext, i *aidlInterface, version string) string {
+func addJavaLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, notFrozen bool) string {
 	javaSourceGen := i.versionedName(version) + "-java-source"
 	javaModuleGen := i.versionedName(version) + "-java"
 	srcs, aidlRoot := i.srcsForVersion(mctx, version)
@@ -221,28 +203,34 @@
 		// Don't create a library for the yet-to-be-frozen version.
 		return ""
 	}
-
+	minSdkVersion := i.minSdkVersion(langJava)
 	sdkVersion := i.properties.Backend.Java.Sdk_version
 	if !proptools.Bool(i.properties.Backend.Java.Platform_apis) && sdkVersion == nil {
 		// platform apis requires no default
 		sdkVersion = proptools.StringPtr("system_current")
 	}
+	// use sdkVersion if minSdkVersion is not set
+	if sdkVersion != nil && minSdkVersion == nil {
+		minSdkVersion = proptools.StringPtr(android.SdkSpecFrom(mctx, *sdkVersion).ApiLevel.String())
+	}
 
 	mctx.CreateModule(aidlGenFactory, &nameProperties{
 		Name: proptools.StringPtr(javaSourceGen),
 	}, &aidlGenProperties{
-		Srcs:                  srcs,
-		AidlRoot:              aidlRoot,
-		IsToT:                 version == i.nextVersion(),
-		ImportsWithoutVersion: i.properties.ImportsWithoutVersion,
-		Stability:             i.properties.Stability,
-		Lang:                  langJava,
-		BaseName:              i.ModuleBase.Name(),
-		Version:               i.versionForAidlGenRule(version),
-		GenTrace:              proptools.Bool(i.properties.Gen_trace),
-		Unstable:              i.properties.Unstable,
-		Visibility:            srcsVisibility(mctx, langJava),
-		Flags:                 i.flagsForAidlGenRule(version),
+		Srcs:            srcs,
+		AidlRoot:        aidlRoot,
+		Imports:         i.properties.Imports,
+		Stability:       i.properties.Stability,
+		Min_sdk_version: minSdkVersion,
+		Platform_apis:   proptools.Bool(i.properties.Backend.Java.Platform_apis),
+		Lang:            langJava,
+		BaseName:        i.ModuleBase.Name(),
+		Version:         i.versionForAidlGenRule(version),
+		GenRpc:          proptools.Bool(i.properties.Backend.Java.Gen_rpc),
+		GenTrace:        proptools.Bool(i.properties.Gen_trace),
+		Unstable:        i.properties.Unstable,
+		NotFrozen:       notFrozen,
+		Flags:           i.flagsForAidlGenRule(version),
 	})
 
 	mctx.CreateModule(aidlImplementationGeneratorFactory, &nameProperties{
@@ -251,6 +239,7 @@
 		Lang:              langJava,
 		AidlInterfaceName: i.ModuleBase.Name(),
 		Version:           version,
+		Imports:           i.properties.Imports,
 		ModuleProperties: []interface{}{&javaProperties{
 			Name:            proptools.StringPtr(javaModuleGen),
 			Installable:     proptools.BoolPtr(true),
@@ -259,14 +248,14 @@
 			Platform_apis:   i.properties.Backend.Java.Platform_apis,
 			Srcs:            []string{":" + javaSourceGen},
 			Apex_available:  i.properties.Backend.Java.Apex_available,
-			Min_sdk_version: i.properties.Backend.Java.Min_sdk_version,
-		}},
+			Min_sdk_version: i.minSdkVersion(langJava),
+		}, &i.properties.Backend.Java.LintProperties},
 	})
 
 	return javaModuleGen
 }
 
-func addRustLibrary(mctx android.LoadHookContext, i *aidlInterface, version string) string {
+func addRustLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, notFrozen bool) string {
 	rustSourceGen := i.versionedName(version) + "-rust-source"
 	rustModuleGen := i.versionedName(version) + "-rust"
 	srcs, aidlRoot := i.srcsForVersion(mctx, version)
@@ -280,30 +269,32 @@
 	mctx.CreateModule(aidlGenFactory, &nameProperties{
 		Name: proptools.StringPtr(rustSourceGen),
 	}, &aidlGenProperties{
-		Srcs:                  srcs,
-		AidlRoot:              aidlRoot,
-		ImportsWithoutVersion: i.properties.ImportsWithoutVersion,
-		IsToT:                 version == i.nextVersion(),
-		Stability:             i.properties.Stability,
-		Lang:                  langRust,
-		BaseName:              i.ModuleBase.Name(),
-		Version:               i.versionForAidlGenRule(version),
-		Unstable:              i.properties.Unstable,
-		Visibility:            srcsVisibility(mctx, langRust),
-		Flags:                 i.flagsForAidlGenRule(version),
+		Srcs:            srcs,
+		AidlRoot:        aidlRoot,
+		Imports:         i.properties.Imports,
+		Stability:       i.properties.Stability,
+		Min_sdk_version: i.minSdkVersion(langRust),
+		Lang:            langRust,
+		BaseName:        i.ModuleBase.Name(),
+		Version:         i.versionForAidlGenRule(version),
+		Unstable:        i.properties.Unstable,
+		NotFrozen:       notFrozen,
+		Flags:           i.flagsForAidlGenRule(version),
 	})
 
 	versionedRustName := fixRustName(i.versionedName(version))
 	rustCrateName := fixRustName(i.ModuleBase.Name())
 
-	mctx.CreateModule(aidlRustLibraryFactory, &rustProperties{
-		Name:           proptools.StringPtr(rustModuleGen),
-		Crate_name:     rustCrateName,
-		Stem:           proptools.StringPtr("lib" + versionedRustName),
-		Defaults:       []string{"aidl-rust-module-defaults"},
-		Host_supported: i.properties.Host_supported,
-		Apex_available: i.properties.Backend.Rust.Apex_available,
-		Target:         rustTargetProperties{Darwin: perTargetProperties{Enabled: proptools.BoolPtr(false)}},
+	mctx.CreateModule(wrapLibraryFactory(aidlRustLibraryFactory), &rustProperties{
+		Name:             proptools.StringPtr(rustModuleGen),
+		Crate_name:       rustCrateName,
+		Stem:             proptools.StringPtr("lib" + versionedRustName),
+		Defaults:         []string{"aidl-rust-module-defaults"},
+		Host_supported:   i.properties.Host_supported,
+		Vendor_available: i.properties.Vendor_available,
+		Apex_available:   i.properties.Backend.Rust.Apex_available,
+		Min_sdk_version:  i.minSdkVersion(langRust),
+		Target:           rustTargetProperties{Darwin: darwinProperties{Enabled: proptools.BoolPtr(false)}},
 	}, &rust.SourceProviderProperties{
 		Source_stem: proptools.StringPtr(versionedRustName),
 	}, &aidlRustSourceProviderProperties{
@@ -331,7 +322,7 @@
 	return name + "-V" + version
 }
 
-func (i *aidlInterface) srcsForVersion(mctx android.LoadHookContext, version string) (srcs []string, aidlRoot string) {
+func (i *aidlInterface) srcsForVersion(mctx android.EarlyModuleContext, version string) (srcs []string, aidlRoot string) {
 	if version == i.nextVersion() {
 		return i.properties.Srcs, i.properties.Local_include_dir
 	} else {
@@ -387,11 +378,10 @@
 // ToT version(including unstable)     | whatever                | ToT version(unstable if unstable)
 // otherwise                           | whatever                | the latest stable version
 // In the case that import specifies the version which it wants to use, use that version.
-func (i *aidlInterface) getImportWithVersion(version string, anImport string, config android.Config) string {
+func (i *aidlInterface) getImportWithVersion(version string, anImport string, other *aidlInterface) string {
 	if hasVersionSuffix(anImport) {
 		return anImport
 	}
-	other := lookupInterface(anImport, config)
 	if proptools.Bool(other.properties.Unstable) {
 		return anImport
 	}
@@ -401,6 +391,21 @@
 	return other.versionedName(other.latestVersion())
 }
 
+// Assuming that the context module has deps to its original aidl_interface and imported
+// aidl_interface modules with interfaceDepTag and importInterfaceDepTag, returns the list of
+// imported interfaces with versions.
+func getImportsWithVersion(ctx android.BaseMutatorContext, interfaceName, version string) []string {
+	i := ctx.GetDirectDepWithTag(interfaceName+aidlInterfaceSuffix, interfaceDep).(*aidlInterface)
+	var imports []string
+	ctx.VisitDirectDeps(func(dep android.Module) {
+		if tag, ok := ctx.OtherModuleDependencyTag(dep).(importInterfaceDepTag); ok {
+			other := dep.(*aidlInterface)
+			imports = append(imports, i.getImportWithVersion(version, tag.anImport, other))
+		}
+	})
+	return imports
+}
+
 func aidlImplementationGeneratorFactory() android.Module {
 	g := &aidlImplementationGenerator{}
 	g.AddProperties(&g.properties)
@@ -417,6 +422,7 @@
 	Lang              string
 	AidlInterfaceName string
 	Version           string
+	Imports           []string
 	ModuleProperties  []interface{}
 }
 
@@ -427,27 +433,17 @@
 }
 
 func (g *aidlImplementationGenerator) GenerateImplementation(ctx android.TopDownMutatorContext) {
-	i := lookupInterface(g.properties.AidlInterfaceName, ctx.Config())
-	version := g.properties.Version
-	lang := g.properties.Lang
+	imports := wrap("", getImportsWithVersion(ctx, g.properties.AidlInterfaceName, g.properties.Version), "-"+g.properties.Lang)
 	if g.properties.Lang == langJava {
-		imports := make([]string, len(i.properties.Imports))
-		for idx, anImport := range i.properties.Imports {
-			imports[idx] = i.getImportWithVersion(version, anImport, ctx.Config()) + "-" + langJava
-		}
 		if p, ok := g.properties.ModuleProperties[0].(*javaProperties); ok {
 			p.Static_libs = imports
 		}
-		ctx.CreateModule(java.LibraryFactory, g.properties.ModuleProperties...)
+		ctx.CreateModule(wrapLibraryFactory(java.LibraryFactory), g.properties.ModuleProperties...)
 	} else {
-		imports := make([]string, len(i.properties.Imports))
-		for idx, anImport := range i.properties.Imports {
-			imports[idx] = i.getImportWithVersion(version, anImport, ctx.Config()) + "-" + lang
-		}
 		if p, ok := g.properties.ModuleProperties[0].(*ccProperties); ok {
 			p.Shared_libs = append(p.Shared_libs, imports...)
 			p.Export_shared_lib_headers = append(p.Export_shared_lib_headers, imports...)
 		}
-		ctx.CreateModule(cc.LibraryFactory, g.properties.ModuleProperties...)
+		ctx.CreateModule(wrapLibraryFactory(cc.LibraryFactory), g.properties.ModuleProperties...)
 	}
 }
diff --git a/build/aidl_interface_metadata_singleton.go b/build/aidl_interface_metadata_singleton.go
index 84fd834..9e2e014 100644
--- a/build/aidl_interface_metadata_singleton.go
+++ b/build/aidl_interface_metadata_singleton.go
@@ -31,11 +31,13 @@
 			`echo "\"name\": \"${name}\"," && ` +
 			`echo "\"stability\": \"${stability}\"," && ` +
 			`echo "\"types\": [${types}]," && ` +
-			`echo "\"hashes\": [${hashes}]" && ` +
+			`echo "\"hashes\": [${hashes}]," && ` +
+			`echo "\"has_development\": ${has_development}," && ` +
+			`echo "\"versions\": [${versions}]" && ` +
 			`echo '}' ` +
 			`;} >> ${out}`,
 		Description: "AIDL metadata: ${out}",
-	}, "name", "stability", "types", "hashes")
+	}, "name", "stability", "types", "hashes", "has_development", "versions")
 
 	joinJsonObjectsToArrayRule = pctx.StaticRule("joinJsonObjectsToArrayRule", blueprint.RuleParams{
 		Rspfile:        "$out.rsp",
@@ -78,9 +80,11 @@
 	}
 
 	type ModuleInfo struct {
-		Stability     string
-		ComputedTypes []string
-		HashFiles     []string
+		Stability      string
+		ComputedTypes  []string
+		HashFiles      []string
+		HasDevelopment android.WritablePath
+		Versions       []string
 	}
 
 	// name -> ModuleInfo
@@ -95,6 +99,7 @@
 			info := moduleInfos[t.ModuleBase.Name()]
 			info.Stability = proptools.StringDefault(t.properties.Stability, "")
 			info.ComputedTypes = t.computedTypes
+			info.Versions = t.properties.Versions
 			moduleInfos[t.ModuleBase.Name()] = info
 		case *aidlGenRule:
 			info := moduleInfos[t.properties.BaseName]
@@ -102,6 +107,10 @@
 				info.HashFiles = append(info.HashFiles, t.hashFile.String())
 			}
 			moduleInfos[t.properties.BaseName] = info
+		case *aidlApi:
+			info := moduleInfos[t.properties.BaseName]
+			info.HasDevelopment = t.hasDevelopment
+			moduleInfos[t.properties.BaseName] = info
 		}
 
 	})
@@ -116,21 +125,31 @@
 		// objects per version and sub-objects per backend, we could
 		// avoid needing to filter out duplicates.
 		info.HashFiles = android.FirstUniqueStrings(info.HashFiles)
+		readHashes := ""
+		if len(info.HashFiles) > 0 {
+			readHashes = "$$(sed 's/.*/\"&\",/' " + strings.Join(info.HashFiles, " ") +
+				"| tr '\\n' ' ' | sed 's/, $$//')"
+		}
 
 		implicits := android.PathsForSource(ctx, info.HashFiles)
+		hasDevelopmentValue := "true"
+		if info.HasDevelopment != nil {
+			hasDevelopmentValue = "$$(if [ \"$$(cat " + info.HasDevelopment.String() +
+				")\" = \"1\" ]; then echo true; else echo false; fi)"
+		}
 
 		ctx.Build(pctx, android.BuildParams{
 			Rule:      aidlMetadataRule,
 			Implicits: implicits,
+			Input:     info.HasDevelopment,
 			Output:    metadataPath,
 			Args: map[string]string{
-				"name":      name,
-				"stability": info.Stability,
-				"types":     strings.Join(wrap(`\"`, info.ComputedTypes, `\"`), ", "),
-				"hashes": strings.Join(
-					wrap(`\"$$(read -r < `,
-						info.HashFiles,
-						` hash extra; printf '%s' $$hash)\"`), ", "),
+				"name":            name,
+				"stability":       info.Stability,
+				"types":           strings.Join(wrap(`\"`, info.ComputedTypes, `\"`), ", "),
+				"hashes":          readHashes,
+				"has_development": hasDevelopmentValue,
+				"versions":        strings.Join(info.Versions, ", "),
 			},
 		})
 	}
diff --git a/build/aidl_rust_glue.py b/build/aidl_rust_glue.py
index ef31c3b..acbd871 100755
--- a/build/aidl_rust_glue.py
+++ b/build/aidl_rust_glue.py
@@ -71,9 +71,11 @@
         node.files.append((in_name, inp))
 
   with open(output, "w") as lib_rs_file:
+    # Enable custom attributes for #![rustfmt::skip]
+    lib_rs_file.write("#![feature(custom_inner_attributes)]\n")
     lib_rs_file.write("#![allow(non_snake_case)]\n")
     lib_rs_file.write("#![allow(missing_docs)]\n")
-    lib_rs_file.write("pub use binder::public_api as binder;\n")
+    lib_rs_file.write("pub use binder;\n")
 
     lib_rs_file.write("pub mod aidl {\n")
     root_module.emit(lib_rs_file, indent="  ")
diff --git a/build/aidl_rust_source_provider.go b/build/aidl_rust_source_provider.go
index eab45f1..16050fb 100644
--- a/build/aidl_rust_source_provider.go
+++ b/build/aidl_rust_source_provider.go
@@ -96,11 +96,8 @@
 func (sp *aidlRustSourceProvider) SourceProviderDeps(ctx rust.DepsContext, deps rust.Deps) rust.Deps {
 	deps = sp.BaseSourceProvider.SourceProviderDeps(ctx, deps)
 	deps.Rustlibs = append(deps.Rustlibs, "libbinder_rs", "liblazy_static")
-	ai := lookupInterface(sp.properties.AidlInterfaceName, ctx.Config())
-	for _, dep := range sp.properties.Imports {
-		deps.Rustlibs = append(deps.Rustlibs, ai.getImportWithVersion(sp.properties.Version, dep, ctx.Config())+"-"+langRust)
-	}
-
+	deps.Rustlibs = append(deps.Rustlibs, wrap("", getImportsWithVersion(ctx, sp.properties.AidlInterfaceName, sp.properties.Version), "-"+langRust)...)
+	deps.ProcMacros = append(deps.ProcMacros, "libasync_trait")
 	// Add a depencency to the source module (*-rust-source) directly via `ctx` because
 	// the source module is specific to aidlRustSourceProvider and we don't want the rust module
 	// to know about it.
diff --git a/build/aidl_test.go b/build/aidl_test.go
index 325cbda..2d5dc17 100644
--- a/build/aidl_test.go
+++ b/build/aidl_test.go
@@ -25,7 +25,6 @@
 	"github.com/google/blueprint/proptools"
 
 	"android/soong/android"
-	"android/soong/apex"
 	"android/soong/cc"
 	"android/soong/genrule"
 	"android/soong/java"
@@ -54,6 +53,13 @@
 	})
 }
 
+func setTestFreezeEnv() android.FixturePreparer {
+	return android.FixtureMergeEnv(map[string]string{
+		"AIDL_FROZEN_REL":    "true",
+		"AIDL_FROZEN_OWNERS": "aosp test",
+	})
+}
+
 func _testAidl(t *testing.T, bp string, customizers ...android.FixturePreparer) android.FixturePreparer {
 	t.Helper()
 
@@ -63,6 +69,7 @@
 		cc.PrepareForTestWithCcDefaultModules,
 		java.PrepareForTestWithJavaDefaultModules,
 		genrule.PrepareForTestWithGenRuleBuildComponents,
+		android.PrepareForTestWithNamespace,
 	)
 
 	bp = bp + `
@@ -80,15 +87,18 @@
 		}
 		cc_library {
 			name: "libbinder",
+			recovery_available: true,
 		}
 		cc_library {
 			name: "libutils",
+			recovery_available: true,
 		}
 		cc_library {
 			name: "libcutils",
 		}
 		cc_library {
 			name: "libbinder_ndk",
+			recovery_available: true,
 			stubs: {
 				versions: ["29"],
 			}
@@ -128,8 +138,13 @@
 			crate_name: "binder",
 			srcs: [""],
 		}
+		rust_proc_macro {
+			name: "libasync_trait",
+			crate_name: "async_trait",
+			srcs: [""],
+			no_stdlibs: true,
+		}
 	`
-
 	preparers = append(preparers, android.FixtureWithRootAndroidBp(bp))
 	preparers = append(preparers, android.FixtureAddTextFile("system/tools/aidl/build/Android.bp", `
 		aidl_interfaces_metadata {
@@ -150,7 +165,6 @@
 	preparers = append(preparers, customizers...)
 
 	preparers = append(preparers,
-		apex.PrepareForTestWithApexBuildComponents,
 		rust.PrepareForTestWithRustBuildComponents,
 		android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
 			ctx.RegisterModuleType("aidl_interface", aidlInterfaceFactory)
@@ -158,17 +172,8 @@
 			ctx.RegisterModuleType("rust_defaults", func() android.Module {
 				return rust.DefaultsFactory()
 			})
-
-			ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
-				ctx.BottomUp("checkImports", checkImports)
-				ctx.TopDown("createAidlInterface", createAidlInterfaceMutator)
-			})
-
-			ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
-				ctx.BottomUp("checkUnstableModule", checkUnstableModuleMutator).Parallel()
-				ctx.BottomUp("recordVersions", recordVersions).Parallel()
-				ctx.BottomUp("checkDuplicatedVersions", checkDuplicatedVersions).Parallel()
-			})
+			ctx.PreArchMutators(registerPreArchMutators)
+			ctx.PostDepsMutators(registerPostDepsMutators)
 		}),
 	)
 
@@ -244,9 +249,10 @@
 	}`
 	expectedError := `module "foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false, PLATFORM_VERSION_CODENAME is REL, and "owner" property is missing.`
 	testAidlError(t, expectedError, vintfWithoutVersionBp, setReleaseEnv())
+	testAidlError(t, expectedError, vintfWithoutVersionBp, setTestFreezeEnv())
 
 	ctx, _ := testAidl(t, vintfWithoutVersionBp)
-	assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk", "foo-V1-ndk_platform")
+	assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk")
 }
 
 // Check if using unstable version in release cause an error.
@@ -265,15 +271,15 @@
 		name: "bar",
 		libs: ["foo-V2-java"],
 	}`
+	files := withFiles(map[string][]byte{
+		"aidl_api/foo/1/foo.1.aidl": nil,
+		"aidl_api/foo/1/.hash":      nil,
+	})
 
 	expectedError := `foo-V2-java is disallowed in release version because it is unstable.`
-	testAidlError(t, expectedError, unstableVersionUsageInJavaBp, setReleaseEnv(), withFiles(map[string][]byte{
-		"aidl_api/foo/1/foo.1.aidl": nil,
-	}))
-
-	testAidl(t, unstableVersionUsageInJavaBp, withFiles(map[string][]byte{
-		"aidl_api/foo/1/foo.1.aidl": nil,
-	}))
+	testAidlError(t, expectedError, unstableVersionUsageInJavaBp, setReleaseEnv(), files)
+	testAidlError(t, expectedError, unstableVersionUsageInJavaBp, setTestFreezeEnv(), files)
+	testAidl(t, unstableVersionUsageInJavaBp, files)
 
 	// A stable version can be used in release version
 	stableVersionUsageInJavaBp := `
@@ -291,13 +297,39 @@
 		libs: ["foo-V1-java"],
 	}`
 
-	testAidl(t, stableVersionUsageInJavaBp, setReleaseEnv(), withFiles(map[string][]byte{
-		"aidl_api/foo/1/foo.1.aidl": nil,
-	}))
+	testAidl(t, stableVersionUsageInJavaBp, setReleaseEnv(), files)
+	testAidl(t, stableVersionUsageInJavaBp, setTestFreezeEnv(), files)
+	testAidl(t, stableVersionUsageInJavaBp, files)
+}
 
-	testAidl(t, stableVersionUsageInJavaBp, withFiles(map[string][]byte{
+func TestUsingUnstableVersionIndirectlyInRelease(t *testing.T) {
+	unstableVersionUsageInJavaBp := `
+	aidl_interface {
+		name: "xxx",
+		srcs: ["IFoo.aidl"],
+		versions: ["1"],
+	}
+	aidl_interface {
+		name: "foo",
+		imports: ["xxx-V2"],    // not OK
+		versions: ["1"],
+		srcs: ["IFoo.aidl"],
+	}
+	java_library {
+		name: "bar",
+		libs: ["foo-V1-java"],  // OK
+	}`
+	files := withFiles(map[string][]byte{
 		"aidl_api/foo/1/foo.1.aidl": nil,
-	}))
+		"aidl_api/foo/1/.hash":      nil,
+		"aidl_api/xxx/1/foo.1.aidl": nil,
+		"aidl_api/xxx/1/.hash":      nil,
+	})
+
+	expectedError := `xxx-V2-java is disallowed in release version because it is unstable.`
+	testAidlError(t, expectedError, unstableVersionUsageInJavaBp, setReleaseEnv(), files)
+	testAidlError(t, expectedError, unstableVersionUsageInJavaBp, setTestFreezeEnv(), files)
+	testAidl(t, unstableVersionUsageInJavaBp, files)
 }
 
 // The module which has never been frozen and is not "unstable" is not allowed in release version.
@@ -317,6 +349,7 @@
 
 	expectedError := `"foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false, PLATFORM_VERSION_CODENAME is REL, and "owner" property is missing.`
 	testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setReleaseEnv())
+	testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv())
 	testAidl(t, nonVersionedModuleUsageInJavaBp)
 
 	nonVersionedUnstableModuleUsageInJavaBp := `
@@ -334,9 +367,51 @@
 	}`
 
 	testAidl(t, nonVersionedUnstableModuleUsageInJavaBp, setReleaseEnv())
+	testAidl(t, nonVersionedUnstableModuleUsageInJavaBp, setTestFreezeEnv())
 	testAidl(t, nonVersionedUnstableModuleUsageInJavaBp)
 }
 
+func TestNonVersionedModuleOwnedByTestUsageInRelease(t *testing.T) {
+	nonVersionedModuleUsageInJavaBp := `
+	aidl_interface {
+		name: "foo",
+		owner: "test",
+		srcs: [
+			"IFoo.aidl",
+		],
+	}
+
+	java_library {
+		name: "bar",
+		libs: ["foo-V1-java"],
+	}`
+
+	expectedError := `"foo_interface": versions: must be set \(need to be frozen\) when "unstable" is false, PLATFORM_VERSION_CODENAME is REL, and "owner" property is missing.`
+	testAidl(t, nonVersionedModuleUsageInJavaBp, setReleaseEnv())
+	testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv())
+	testAidl(t, nonVersionedModuleUsageInJavaBp)
+}
+
+func TestNonVersionedModuleOwnedByOtherUsageInRelease(t *testing.T) {
+	nonVersionedModuleUsageInJavaBp := `
+	aidl_interface {
+		name: "foo",
+		owner: "unknown-owner",
+		srcs: [
+			"IFoo.aidl",
+		],
+	}
+
+	java_library {
+		name: "bar",
+		libs: ["foo-V1-java"],
+	}`
+
+	testAidl(t, nonVersionedModuleUsageInJavaBp, setReleaseEnv())
+	testAidl(t, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv())
+	testAidl(t, nonVersionedModuleUsageInJavaBp)
+}
+
 func TestImportInRelease(t *testing.T) {
 	importInRelease := `
 	aidl_interface {
@@ -344,7 +419,7 @@
 		srcs: [
 			"IFoo.aidl",
 		],
-		imports: ["bar"],
+		imports: ["bar-V1"],
 		versions: ["1"],
 	}
 
@@ -356,13 +431,16 @@
 		versions: ["1"],
 	}
 	`
-
-	testAidl(t, importInRelease, setReleaseEnv(), withFiles(map[string][]byte{
+	files := withFiles(map[string][]byte{
 		"aidl_api/foo/1/foo.1.aidl": nil,
 		"aidl_api/foo/1/.hash":      nil,
 		"aidl_api/bar/1/bar.1.aidl": nil,
 		"aidl_api/bar/1/.hash":      nil,
-	}))
+	})
+
+	testAidl(t, importInRelease, setReleaseEnv(), files)
+	testAidl(t, importInRelease, setTestFreezeEnv(), files)
+	testAidl(t, importInRelease, files)
 }
 
 func TestUnstableVersionedModuleUsageInRelease(t *testing.T) {
@@ -382,11 +460,64 @@
 
 	expectedError := `Android.bp:10:2: module \"bar\" variant \"android_common\": foo-V2-java is disallowed in release version because it is unstable, and its \"owner\" property is missing.`
 	testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setReleaseEnv())
+	testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv())
 	testAidl(t, nonVersionedModuleUsageInJavaBp, withFiles(map[string][]byte{
 		"aidl_api/foo/1/foo.1.aidl": nil,
+		"aidl_api/foo/1/.hash":      nil,
 	}))
 }
 
+func TestUnstableVersionedModuleOwnedByTestUsageInRelease(t *testing.T) {
+	nonVersionedModuleUsageInJavaBp := `
+	aidl_interface {
+		name: "foo",
+		owner: "test",
+		srcs: [
+			"IFoo.aidl",
+		],
+		versions: ["1"],
+	}
+
+	java_library {
+		name: "bar",
+		libs: ["foo-V2-java"],
+	}`
+	files := withFiles(map[string][]byte{
+		"aidl_api/foo/1/foo.1.aidl": nil,
+		"aidl_api/foo/1/.hash":      nil,
+	})
+
+	expectedError := `Android.bp:11:2: module \"bar\" variant \"android_common\": foo-V2-java is disallowed in release version because it is unstable, and its \"owner\" property is missing.`
+	testAidl(t, nonVersionedModuleUsageInJavaBp, setReleaseEnv(), files)
+	testAidlError(t, expectedError, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv(), files)
+	testAidl(t, nonVersionedModuleUsageInJavaBp, files)
+}
+
+func TestUnstableVersionedModuleOwnedByOtherUsageInRelease(t *testing.T) {
+	nonVersionedModuleUsageInJavaBp := `
+	aidl_interface {
+		name: "foo",
+		owner: "unknown-owner",
+		srcs: [
+			"IFoo.aidl",
+		],
+		versions: ["1"],
+	}
+
+	java_library {
+		name: "bar",
+		libs: ["foo-V2-java"],
+	}`
+	files := withFiles(map[string][]byte{
+		"aidl_api/foo/1/foo.1.aidl": nil,
+		"aidl_api/foo/1/.hash":      nil,
+	})
+
+	testAidl(t, nonVersionedModuleUsageInJavaBp, setReleaseEnv(), files)
+	testAidl(t, nonVersionedModuleUsageInJavaBp, setTestFreezeEnv(), files)
+	testAidl(t, nonVersionedModuleUsageInJavaBp, files)
+}
+
 func TestUnstableModules(t *testing.T) {
 	testAidlError(t, `module "foo_interface": stability: must be empty when "unstable" is true`, `
 		aidl_interface {
@@ -437,7 +568,7 @@
 		}
 	`)
 
-	assertModulesExists(t, ctx, "foo-java", "foo-rust", "foo-cpp", "foo-ndk", "foo-ndk_platform")
+	assertModulesExists(t, ctx, "foo-java", "foo-rust", "foo-cpp", "foo-ndk")
 }
 
 func TestCreatesModulesWithNoVersions(t *testing.T) {
@@ -455,12 +586,12 @@
 		}
 	`)
 
-	assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk", "foo-V1-ndk_platform")
+	assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk")
 }
 
 func TestCreatesModulesWithFrozenVersions(t *testing.T) {
 	// Each version should be under aidl_api/<name>/<ver>
-	testAidlError(t, `aidl_api/foo/1`, `
+	testAidlError(t, `No sources for a previous version in aidl_api/foo/1. Was a version manually added to .bp file?`, `
 		aidl_interface {
 			name: "foo",
 			srcs: [
@@ -494,13 +625,14 @@
 		}
 	`, withFiles(map[string][]byte{
 		"aidl_api/foo/1/foo.1.aidl": nil,
+		"aidl_api/foo/1/.hash":      nil,
 	}))
 
 	// For frozen version "1"
-	assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk", "foo-V1-ndk_platform")
+	assertModulesExists(t, ctx, "foo-V1-java", "foo-V1-rust", "foo-V1-cpp", "foo-V1-ndk")
 
 	// For ToT (current)
-	assertModulesExists(t, ctx, "foo-V2-java", "foo-V2-rust", "foo-V2-cpp", "foo-V2-ndk", "foo-V2-ndk_platform")
+	assertModulesExists(t, ctx, "foo-V2-java", "foo-V2-rust", "foo-V2-cpp", "foo-V2-ndk")
 }
 
 func TestErrorsWithUnsortedVersions(t *testing.T) {
@@ -628,7 +760,9 @@
 		}
 	`, withFiles(map[string][]byte{
 		"aidl_api/foo/1/foo.1.aidl": nil,
+		"aidl_api/foo/1/.hash":      nil,
 		"aidl_api/foo/2/foo.2.aidl": nil,
+		"aidl_api/foo/2/.hash":      nil,
 	}))
 
 	// alias for the latest frozen version (=2)
@@ -646,7 +780,7 @@
 	assertOutput("foo-V3-cpp", nativeVariant, "foo-V3-cpp.so")
 	assertOutput("foo-V3-rust", nativeRustVariant, "libfoo_V3.dylib.so")
 
-	// skip ndk/ndk_platform since they follow the same rule with cpp
+	// skip ndk since they follow the same rule with cpp
 }
 
 func TestImports(t *testing.T) {
@@ -669,7 +803,7 @@
 				"IFoo.aidl",
 			],
 			imports: [
-				"bar",
+				"bar-V1",
 			]
 		}
 		aidl_interface {
@@ -692,7 +826,7 @@
 				"IFoo.aidl",
 			],
 			imports: [
-				"bar",
+				"bar-V1",
 			]
 		}
 		aidl_interface {
@@ -720,7 +854,7 @@
 				},
 			},
 			imports: [
-				"bar.1",
+				"bar.1-V1",
 			]
 		}
 		aidl_interface {
@@ -745,7 +879,7 @@
 
 	rustcRule := ctx.ModuleForTests("foo-V1-rust", nativeRustVariant).Rule("rustc")
 	libFlags = rustcRule.Args["libFlags"]
-	libBar = filepath.Join("out", "soong", ".intermediates", "bar.1-V1-rust", nativeRustVariant, "libbar_1_V1.dylib.so")
+	libBar = filepath.Join("out", "soong", ".intermediates", "bar.1-V1-rust", nativeRustVariant, "unstripped", "libbar_1_V1.dylib.so")
 	libBarFlag := "--extern bar_1=" + libBar
 	if !strings.Contains(libFlags, libBarFlag) {
 		t.Errorf("%q is not found in %q", libBarFlag, libFlags)
@@ -755,7 +889,7 @@
 func TestDuplicatedVersions(t *testing.T) {
 	// foo depends on myiface-V2-ndk via direct dep and also on
 	// myiface-V1-ndk via indirect dep. This should be prohibited.
-	testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-ndk, myiface-V2-ndk`, `
+	testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-.*, myiface-V2-.*`, `
 		aidl_interface {
 			name: "myiface",
 			srcs: ["IFoo.aidl"],
@@ -778,7 +912,7 @@
 		"aidl_api/myiface/2/myiface.2.aidl": nil,
 		"aidl_api/myiface/2/.hash":          nil,
 	}))
-	testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-ndk, myiface-V2-ndk`, `
+	testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-.*, myiface-V2-.*`, `
 		aidl_interface {
 			name: "myiface",
 			srcs: ["IFoo.aidl"],
@@ -788,7 +922,7 @@
 		aidl_interface {
 			name: "myiface2",
 			srcs: ["IBar.aidl"],
-			imports: ["myiface"]
+			imports: ["myiface-V2"]
 		}
 
 		cc_library {
@@ -800,22 +934,17 @@
 		"aidl_api/myiface/1/myiface.1.aidl": nil,
 		"aidl_api/myiface/1/.hash":          nil,
 	}))
-	testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-ndk-source, myiface-V2-ndk`, `
+	testAidlError(t, `depends on multiple versions of the same aidl_interface: myiface-V1-.*, myiface-V2-.*`, `
 		aidl_interface {
 			name: "myiface",
 			srcs: ["IFoo.aidl"],
 			versions: ["1"],
-			backend: {
-				ndk: {
-					srcs_available: true,
-				},
-			},
 		}
 
 		aidl_interface {
 			name: "myiface2",
 			srcs: ["IBar.aidl"],
-			imports: ["myiface"]
+			imports: ["myiface-V2"]
 		}
 
 		cc_library {
@@ -828,22 +957,32 @@
 		"aidl_api/myiface/1/myiface.1.aidl": nil,
 		"aidl_api/myiface/1/.hash":          nil,
 	}))
+	// Okay to reference two different
 	testAidl(t, `
 		aidl_interface {
 			name: "myiface",
 			srcs: ["IFoo.aidl"],
 			versions: ["1"],
-			backend: {
-				ndk: {
-					srcs_available: true,
-				},
-			},
+		}
+		cc_library {
+			name: "foobar",
+			shared_libs: ["myiface-V1-cpp", "myiface-V1-ndk"],
+		}
+	`, withFiles(map[string][]byte{
+		"aidl_api/myiface/1/myiface.1.aidl": nil,
+		"aidl_api/myiface/1/.hash":          nil,
+	}))
+	testAidl(t, `
+		aidl_interface {
+			name: "myiface",
+			srcs: ["IFoo.aidl"],
+			versions: ["1"],
 		}
 
 		aidl_interface {
 			name: "myiface2",
 			srcs: ["IBar.aidl"],
-			imports: ["myiface"]
+			imports: ["myiface-V2"]
 		}
 
 		cc_library {
@@ -866,7 +1005,7 @@
 		aidl_interface {
 			name: "myiface2",
 			srcs: ["IBar.aidl"],
-			imports: ["myiface"]
+			imports: ["myiface-V2"]
 		}
 
 		cc_library {
@@ -918,75 +1057,16 @@
 	`)
 }
 
-func TestCcModuleWithApexNameMacro(t *testing.T) {
+func TestRecoveryAvailable(t *testing.T) {
 	ctx, _ := testAidl(t, `
 		aidl_interface {
 			name: "myiface",
+			recovery_available: true,
 			srcs: ["IFoo.aidl"],
-			backend: {
-				ndk: {
-					apex_available: ["myapex"],
-				},
-			},
 		}
-		apex {
-			name: "myapex",
-			key: "myapex.key",
-			native_shared_libs: ["myiface-V1-ndk_platform"],
-			updatable: false,
-		}
-		apex_key {
-			name: "myapex.key",
-			public_key: "testkey.avbpubkey",
-			private_key: "testkey.pem",
-		}
-	`, withFiles(map[string][]byte{
-		"system/sepolicy/apex/myapex-file_contexts": nil,
-	}))
-
-	ccRule := ctx.ModuleForTests("myiface-V1-ndk_platform", "android_arm64_armv8-a_static_myapex").Rule("cc")
-	assertContains(t, ccRule.Args["cFlags"], "-D__ANDROID_APEX__")
-	assertContains(t, ccRule.Args["cFlags"], "-D__ANDROID_APEX_NAME__='\"myapex\"'")
-	assertContains(t, ccRule.Args["cFlags"], "-D__ANDROID_APEX_MYAPEX__")
-}
-
-func TestSrcsAvailable(t *testing.T) {
-	bp := `
-		aidl_interface {
-			name: "myiface",
-			srcs: ["IFoo.aidl"],
-			backend: {
-				java: {
-					srcs_available: %s,
-				},
-				cpp: {
-					srcs_available: %s,
-				},
-			},
-		}
-	`
-	customizer := withFiles(map[string][]byte{
-		"otherpackage/Android.bp": []byte(`
-			java_library {
-				name: "javalib",
-				srcs: [":myiface-V1-java-source"],
-			}
-			cc_library_shared {
-				name: "cclib",
-				srcs: [":myiface-V1-cpp-source"],
-			}
-		`),
-	})
-	ctx, _ := testAidl(t, fmt.Sprintf(bp, "true", "true"), customizer)
-	javaInputs := ctx.ModuleForTests("javalib", "android_common").Rule("javac").Inputs.Strings()
-	assertListContains(t, javaInputs, "myiface-V1-java-source/gen/IFoo.java")
-	ccInput := ctx.ModuleForTests("cclib", "android_arm64_armv8-a_shared").Rule("cc").Input.String()
-	assertContains(t, ccInput, "myiface-V1-cpp-source/gen/IFoo.cpp")
-
-	testAidlError(t, `depends on //.:myiface-V1-java-source which is not visible to this module`,
-		fmt.Sprintf(bp, "false", "true"), customizer)
-	testAidlError(t, `depends on //.:myiface-V1-cpp-source which is not visible to this module`,
-		fmt.Sprintf(bp, "true", "false"), customizer)
+	`)
+	ctx.ModuleForTests("myiface-V1-ndk", "android_recovery_arm64_armv8-a_shared")
+	ctx.ModuleForTests("myiface-V1-cpp", "android_recovery_arm64_armv8-a_shared")
 }
 
 func TestRustDuplicateNames(t *testing.T) {
@@ -1003,7 +1083,86 @@
 	`)
 }
 
-func TestAidlImportFlagsForIncludeDirs(t *testing.T) {
+func TestAidlImportFlagsForImportedModules(t *testing.T) {
+	customizer := withFiles(map[string][]byte{
+		"foo/Android.bp": []byte(`
+			aidl_interface {
+				name: "foo-iface",
+				srcs: ["a/Foo.aidl"],
+				imports: ["bar-iface-V2"],
+				versions: ["1"],
+			}
+		`),
+		"foo/a/Foo.aidl": nil,
+		"foo/aidl_api/foo-iface/current/a/Foo.aidl": nil,
+		"foo/aidl_api/foo-iface/1/a/Foo.aidl":       nil,
+		"foo/aidl_api/foo-iface/1/.hash":            nil,
+
+		"bar/Android.bp": []byte(`
+			aidl_interface {
+				name: "bar-iface",
+				srcs: ["b/Bar.aidl"],
+				imports: ["baz-iface-V1"],
+				versions: ["1"],
+			}
+		`),
+		"bar/b/Bar.aidl": nil,
+		"bar/aidl_api/bar-iface/current/b/Bar.aidl": nil,
+		"bar/aidl_api/bar-iface/1/b/Bar.aidl":       nil,
+		"bar/aidl_api/bar-iface/1/.hash":            nil,
+
+		"baz/Android.bp": []byte(`
+			aidl_interface {
+				name: "baz-iface",
+				srcs: ["b/Baz.aidl"],
+				include_dirs: ["baz-include"],
+				versions: ["1"],
+			}
+		`),
+		"baz/b/Baz.aidl": nil,
+		"baz/aidl_api/baz-iface/current/b/Baz.aidl": nil,
+		"baz/aidl_api/baz-iface/1/b/Baz.aidl":       nil,
+		"baz/aidl_api/baz-iface/1/.hash":            nil,
+	})
+	ctx, _ := testAidl(t, ``, customizer)
+
+	// checkapidump rule is to compare "compatibility" between ToT(dump) and "current"
+	{
+		rule := ctx.ModuleForTests("foo-iface-api", "").Output("checkapi_dump.timestamp")
+		android.AssertStringEquals(t, "checkapi(dump == current) imports", "", rule.Args["imports"])
+		android.AssertStringDoesContain(t, "checkapi(dump == current) optionalFlags",
+			rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/bar/bar-iface_interface/2/preprocessed.aidl")
+	}
+
+	// has_development rule runs --checkapi for equality between latest("1")
+	// and ToT
+	{
+		rule := ctx.ModuleForTests("foo-iface-api", "").Output("has_development")
+		android.AssertStringDoesContain(t, "checkapi(dump == latest(1)) should import import's preprocessed",
+			rule.RuleParams.Command,
+			"-pout/soong/.intermediates/bar/bar-iface_interface/2/preprocessed.aidl")
+	}
+
+	// compile (v1)
+	{
+		rule := ctx.ModuleForTests("foo-iface-V1-cpp-source", "").Output("a/Foo.cpp")
+		android.AssertStringEquals(t, "compile(old=1) should import aidl_api/1", "-Ifoo/aidl_api/foo-iface/1", rule.Args["imports"])
+		android.AssertStringDoesContain(t, "compile(old=1) should import bar.preprocessed",
+			rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/bar/bar-iface_interface/2/preprocessed.aidl")
+	}
+	// compile ToT(v2)
+	{
+		rule := ctx.ModuleForTests("foo-iface-V2-cpp-source", "").Output("a/Foo.cpp")
+		android.AssertStringEquals(t, "compile(tot=2) should import base dirs of srcs", "-Ifoo", rule.Args["imports"])
+		android.AssertStringDoesContain(t, "compile(tot=2) should import bar.preprocessed",
+			rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/bar/bar-iface_interface/2/preprocessed.aidl")
+	}
+}
+
+func TestAidlPreprocess(t *testing.T) {
 	customizer := withFiles(map[string][]byte{
 		"foo/Android.bp": []byte(`
 			aidl_interface {
@@ -1017,9 +1176,9 @@
 						"src/foo/Foo.aidl",
 				],
 				imports: [
-						"bar-iface",
+					"bar-iface",
 				],
-				versions: ["1", "2"],
+				unstable: true,
 			}
 			aidl_interface {
 				name: "bar-iface",
@@ -1027,40 +1186,62 @@
 				srcs: [
 						"src/bar/Bar.aidl",
 				],
+				unstable: true,
 			}
 		`),
-		"foo/src/foo/Foo.aidl":                        nil,
-		"foo/src/bar/Bar.aidl":                        nil,
-		"foo/aidl_api/foo-iface/current/foo/Foo.aidl": nil,
-		"foo/aidl_api/foo-iface/1/foo/Foo.aidl":       nil,
-		"foo/aidl_api/foo-iface/1/.hash":              nil,
-		"foo/aidl_api/foo-iface/2/foo/Foo.aidl":       nil,
-		"foo/aidl_api/foo-iface/2/.hash":              nil,
+		"foo/src/foo/Foo.aidl": nil,
+		"foo/src/bar/Bar.aidl": nil,
 	})
 	ctx, _ := testAidl(t, ``, customizer)
 
-	// compile for older version
-	{
-		rule := ctx.ModuleForTests("foo-iface-V1-cpp-source", "").Output("foo/Foo.cpp")
-		imports := strings.Split(rule.Args["imports"], " ")
-		android.AssertArrayString(t, "should import foo/1(target) and bar/current(imported)", []string{
-			"-Ifoo/aidl_api/foo-iface/1",
-			"-Ipath1",
-			"-Ipath2/sub",
-			"-Ifoo/aidl_api/bar-iface/current",
-		}, imports)
-	}
-	// compile for tot version
-	{
-		rule := ctx.ModuleForTests("foo-iface-V3-cpp-source", "").Output("foo/Foo.cpp")
-		imports := strings.Split(rule.Args["imports"], " ")
-		android.AssertArrayString(t, "aidlCompile should import ToT", []string{
-			"-Ifoo/src",
-			"-Ipath1",
-			"-Ipath2/sub",
-			"-Ifoo/src",
-		}, imports)
-	}
+	rule := ctx.ModuleForTests("foo-iface_interface", "").Output("preprocessed.aidl")
+	android.AssertStringDoesContain(t, "preprocessing should import srcs and include_dirs",
+		rule.RuleParams.Command,
+		"-Ifoo/src -Ipath1 -Ipath2/sub")
+	android.AssertStringDoesContain(t, "preprocessing should import import's preprocess",
+		rule.RuleParams.Command,
+		"-pout/soong/.intermediates/foo/bar-iface_interface/preprocessed.aidl")
+}
+
+func TestAidlImportFlagsForUnstable(t *testing.T) {
+	customizer := withFiles(map[string][]byte{
+		"foo/Android.bp": []byte(`
+			aidl_interface {
+				name: "foo-iface",
+				local_include_dir: "src",
+				include_dirs: [
+						"path1",
+						"path2/sub",
+				],
+				srcs: [
+						"src/foo/Foo.aidl",
+				],
+				imports: [
+					"bar-iface",
+				],
+				unstable: true,
+			}
+			aidl_interface {
+				name: "bar-iface",
+				local_include_dir: "src",
+				srcs: [
+						"src/bar/Bar.aidl",
+				],
+				unstable: true,
+			}
+		`),
+		"foo/src/foo/Foo.aidl": nil,
+		"foo/src/bar/Bar.aidl": nil,
+	})
+	ctx, _ := testAidl(t, ``, customizer)
+
+	rule := ctx.ModuleForTests("foo-iface-cpp-source", "").Output("foo/Foo.cpp")
+	android.AssertStringEquals(t, "compile(unstable) should import foo/base_dirs(target) and bar/base_dirs(imported)",
+		"-Ifoo/src -Ipath1 -Ipath2/sub",
+		rule.Args["imports"])
+	android.AssertStringDoesContain(t, "compile(unstable) should import bar.preprocessed",
+		rule.Args["optionalFlags"],
+		"-pout/soong/.intermediates/foo/bar-iface_interface/preprocessed.aidl")
 }
 
 func TestSupportsGenruleAndFilegroup(t *testing.T) {
@@ -1079,7 +1260,7 @@
 						":gen1",
 				],
 				imports: [
-						"bar-iface",
+						"bar-iface-V1",
 				],
 				versions: ["1"],
 			}
@@ -1102,8 +1283,16 @@
 				local_include_dir: "src",
 				srcs: [
 						"src/bar/Bar.aidl",
+						":gen-bar",
 				],
 			}
+			genrule {
+				name: "gen-bar",
+				cmd: "generate gen/GenBar.aidl",
+				out: [
+					"gen/GenBar.aidl",
+				]
+			}
 		`),
 		"foo/aidl_api/foo-iface/1/foo/Foo.aidl": nil,
 		"foo/aidl_api/foo-iface/1/.hash":        nil,
@@ -1115,26 +1304,22 @@
 	// aidlCompile for snapshots (v1)
 	{
 		rule := ctx.ModuleForTests("foo-iface-V1-cpp-source", "").Output("foo/Foo.cpp")
-		imports := strings.Split(rule.Args["imports"], " ")
-		android.AssertArrayString(t, "aidlCompile should import filegroup/genrule as well", []string{
-			"-Ifoo/aidl_api/foo-iface/1",
-			"-Ipath1",
-			"-Ipath2/sub",
-			"-Ifoo/aidl_api/bar-iface/current",
-		}, imports)
+		android.AssertStringEquals(t, "compile(1) should import foo/aidl_api/1",
+			"-Ifoo/aidl_api/foo-iface/1 -Ipath1 -Ipath2/sub",
+			rule.Args["imports"])
+		android.AssertStringDoesContain(t, "compile(1) should import bar.preprocessed",
+			rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/foo/bar-iface_interface/1/preprocessed.aidl")
 	}
 	// aidlCompile for ToT (v2)
 	{
 		rule := ctx.ModuleForTests("foo-iface-V2-cpp-source", "").Output("foo/Foo.cpp")
-		imports := strings.Split(rule.Args["imports"], " ")
-		android.AssertArrayString(t, "aidlCompile should import filegroup/genrule as well", []string{
-			"-Ifoo/src",
-			"-Ifoo/filegroup/sub",
-			"-Iout/soong/.intermediates/foo/gen1/gen",
-			"-Ipath1",
-			"-Ipath2/sub",
-			"-Ifoo/src",
-		}, imports)
+		android.AssertStringEquals(t, "compile(tot=2) should import foo.base_dirs",
+			"-Ifoo/src -Ifoo/filegroup/sub -Iout/soong/.intermediates/foo/gen1/gen -Ipath1 -Ipath2/sub",
+			rule.Args["imports"])
+		android.AssertStringDoesContain(t, "compile(tot=2) should import bar.preprocessed",
+			rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/foo/bar-iface_interface/1/preprocessed.aidl")
 	}
 
 	// dumpapi
@@ -1154,23 +1339,12 @@
 			dumpDir + "/.hash",
 		}, rule.Outputs.Paths())
 
-		imports := strings.Split(rule.Args["imports"], " ")
-		android.AssertArrayString(t, "dumpapi should import filegroup/genrule as well", []string{
-			// these are from foo-iface.srcs
-			"-Ifoo/src",
-			"-Ifoo/filegroup/sub",
-			"-Iout/soong/.intermediates/foo/gen1/gen",
-
-			// this is from bar-iface.srcs
-			"-Ifoo/src",
-
-			// this is from foo-iface.Local_include_dir
-			"-Ifoo/src",
-
-			// these are from foo-iface.include_dirs
-			"-Ipath1",
-			"-Ipath2/sub",
-		}, imports)
+		android.AssertStringEquals(t, "dumpapi should import base_dirs and include_dirs",
+			"-Ifoo/src -Ifoo/filegroup/sub -Iout/soong/.intermediates/foo/gen1/gen -Ipath1 -Ipath2/sub",
+			rule.Args["imports"])
+		android.AssertStringDoesContain(t, "dumpapi should import bar.preprocessed",
+			rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/foo/bar-iface_interface/1/preprocessed.aidl")
 	}
 }
 
@@ -1199,6 +1373,22 @@
 	}
 }
 
+func TestAidlModuleJavaSdkVersionDeterminesMinSdkVersion(t *testing.T) {
+	ctx, _ := testAidl(t, `
+		aidl_interface {
+			name: "myiface",
+			srcs: ["a/Foo.aidl"],
+			backend: {
+				java: {
+					sdk_version: "28",
+				},
+			},
+		}
+	`, java.FixtureWithPrebuiltApis(map[string][]string{"28": {"foo"}}))
+	params := ctx.ModuleForTests("myiface-V1-java-source", "").Output("a/Foo.java")
+	assertContains(t, params.Args["optionalFlags"], "--min_sdk_version 28")
+}
+
 func TestAidlModuleNameContainsVersion(t *testing.T) {
 	testAidlError(t, "aidl_interface should not have '-V<number> suffix", `
 		aidl_interface {
@@ -1276,3 +1466,187 @@
 		"aidl_api/bar/1/.hash":    nil,
 	}))
 }
+
+func TestUseVersionedPreprocessedWhenImporotedWithVersions(t *testing.T) {
+	ctx, _ := testAidl(t, `
+		aidl_interface {
+			name: "unstable-foo",
+			srcs: ["foo/Foo.aidl"],
+			imports: [
+					"bar-V2",
+					"baz-V1",
+					"unstable-bar",
+			],
+			unstable: true,
+		}
+		aidl_interface {
+			name: "foo",
+			srcs: ["foo/Foo.aidl"],
+			imports: [
+					"bar-V1",
+					"baz-V1",
+			],
+			versions: ["1"],
+		}
+		aidl_interface {
+			name: "foo-no-versions",
+			srcs: ["foo/Foo.aidl"],
+			imports: [
+					"bar-V2",
+			],
+		}
+		aidl_interface {
+			name: "bar",
+			srcs: ["bar/Bar.aidl"],
+			versions: ["1"],
+		}
+		aidl_interface {
+			name: "unstable-bar",
+			srcs: ["bar/Bar.aidl"],
+			unstable: true,
+		}
+		aidl_interface {
+			name: "baz",
+			srcs: ["baz/Baz.aidl"],
+			versions: ["1"],
+		}
+	`, withFiles(map[string][]byte{
+		"foo/Foo.aidl":                nil,
+		"bar/Bar.aidl":                nil,
+		"baz/Baz.aidl":                nil,
+		"aidl_api/foo/1/foo/Foo.aidl": nil,
+		"aidl_api/foo/1/.hash":        nil,
+		"aidl_api/bar/1/bar/Bar.aidl": nil,
+		"aidl_api/bar/1/.hash":        nil,
+		"aidl_api/baz/1/baz/Baz.aidl": nil,
+		"aidl_api/baz/1/.hash":        nil,
+	}))
+	{
+		rule := ctx.ModuleForTests("foo-V2-java-source", "").Output("foo/Foo.java")
+		android.AssertStringDoesContain(t, "foo-V2(tot) imports bar-V1 for 'bar-V1'", rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/bar_interface/1/preprocessed.aidl")
+		android.AssertStringDoesContain(t, "foo-V2(tot) imports baz-V1 for 'baz-V1'", rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/baz_interface/1/preprocessed.aidl")
+	}
+	{
+		rule := ctx.ModuleForTests("foo-V1-java-source", "").Output("foo/Foo.java")
+		android.AssertStringDoesContain(t, "foo-V1 imports bar-V1(latest) for 'bar'", rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/bar_interface/1/preprocessed.aidl")
+		android.AssertStringDoesContain(t, "foo-V1 imports baz-V1 for 'baz-V1'", rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/baz_interface/1/preprocessed.aidl")
+	}
+	{
+		rule := ctx.ModuleForTests("unstable-foo-java-source", "").Output("foo/Foo.java")
+		android.AssertStringDoesContain(t, "unstable-foo imports bar-V2(latest) for 'bar'", rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/bar_interface/2/preprocessed.aidl")
+		android.AssertStringDoesContain(t, "unstable-foo imports baz-V1 for 'baz-V1'", rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/baz_interface/1/preprocessed.aidl")
+		android.AssertStringDoesContain(t, "unstable-foo imports unstable-bar(ToT) for 'unstable-bar'", rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/unstable-bar_interface/preprocessed.aidl")
+	}
+	{
+		rule := ctx.ModuleForTests("foo-no-versions-V1-java-source", "").Output("foo/Foo.java")
+		android.AssertStringDoesContain(t, "foo-no-versions-V1(latest) imports bar-V2(latest) for 'bar'", rule.Args["optionalFlags"],
+			"-pout/soong/.intermediates/bar_interface/2/preprocessed.aidl")
+	}
+}
+
+func FindModule(ctx *android.TestContext, name, variant, dir string) android.Module {
+	var module android.Module
+	ctx.VisitAllModules(func(m blueprint.Module) {
+		if ctx.ModuleName(m) == name && ctx.ModuleSubDir(m) == variant && ctx.ModuleDir(m) == dir {
+			module = m.(android.Module)
+		}
+	})
+	if module == nil {
+		m := ctx.ModuleForTests(name, variant).Module()
+		panic(fmt.Errorf("failed to find module %q variant %q dir %q, but found one in %q",
+			name, variant, dir, ctx.ModuleDir(m)))
+	}
+	return module
+}
+
+func TestDuplicateInterfacesWithTheSameNameInDifferentSoongNamespaces(t *testing.T) {
+	ctx, _ := testAidl(t, ``, withFiles(map[string][]byte{
+		"common/Android.bp": []byte(`
+		  aidl_interface {
+				name: "common",
+				srcs: ["ICommon.aidl"],
+				versions: ["1", "2"],
+			}
+		`),
+		"common/aidl_api/common/1/ICommon.aidl": nil,
+		"common/aidl_api/common/1/.hash":        nil,
+		"common/aidl_api/common/2/ICommon.aidl": nil,
+		"common/aidl_api/common/2/.hash":        nil,
+		"vendor/a/Android.bp": []byte(`
+			soong_namespace {}
+		`),
+		"vendor/a/foo/Android.bp": []byte(`
+			aidl_interface {
+				name: "foo",
+				srcs: ["IFoo.aidl"],
+				imports: ["common-V1"],
+			}
+		`),
+		"vendor/b/Android.bp": []byte(`
+			soong_namespace {}
+		`),
+		"vendor/b/foo/Android.bp": []byte(`
+			aidl_interface {
+				name: "foo",
+				srcs: ["IFoo.aidl"],
+				imports: ["common-V2"],
+			}
+		`),
+	}))
+
+	aFooV1Java := FindModule(ctx, "foo-V1-java", "android_common", "vendor/a/foo").(*java.Library)
+	android.AssertStringListContains(t, "a/foo deps", aFooV1Java.CompilerDeps(), "common-V1-java")
+
+	bFooV1Java := FindModule(ctx, "foo-V1-java", "android_common", "vendor/b/foo").(*java.Library)
+	android.AssertStringListContains(t, "a/foo deps", bFooV1Java.CompilerDeps(), "common-V2-java")
+}
+
+func TestUnstableChecksForAidlInterfacesInDifferentNamespaces(t *testing.T) {
+	files := withFiles(map[string][]byte{
+		"vendor/a/Android.bp": []byte(`
+			soong_namespace {}
+		`),
+		"vendor/a/foo/Android.bp": []byte(`
+			aidl_interface {
+				name: "foo",
+				srcs: ["IFoo.aidl"],
+				versions: ["1", "2"],
+			}
+			java_library {
+				name: "bar",
+				libs: ["foo-V2-java"],  // OK
+			}
+		`),
+		"vendor/a/foo/aidl_api/foo/1/IFoo.aidl": nil,
+		"vendor/a/foo/aidl_api/foo/1/.hash":     nil,
+		"vendor/a/foo/aidl_api/foo/2/IFoo.aidl": nil,
+		"vendor/a/foo/aidl_api/foo/2/.hash":     nil,
+		"vendor/b/Android.bp": []byte(`
+			soong_namespace {}
+		`),
+		"vendor/b/foo/Android.bp": []byte(`
+			aidl_interface {
+				name: "foo",
+				srcs: ["IFoo.aidl"],
+				versions: ["1"],
+			}
+			java_library {
+				name: "bar",
+				libs: ["foo-V1-java"],  // OK
+			}
+		`),
+		"vendor/b/foo/aidl_api/foo/1/IFoo.aidl": nil,
+		"vendor/b/foo/aidl_api/foo/1/.hash":     nil,
+	})
+
+	testAidl(t, ``, files, setReleaseEnv())
+	testAidl(t, ``, files, setTestFreezeEnv())
+	testAidl(t, ``, files)
+}
diff --git a/build/aidl_utils.go b/build/aidl_utils.go
index b19793c..4e0fba9 100644
--- a/build/aidl_utils.go
+++ b/build/aidl_utils.go
@@ -15,7 +15,6 @@
 package aidl
 
 import (
-	"android/soong/android"
 	"strings"
 )
 
@@ -46,22 +45,6 @@
 	return ret
 }
 
-// baseDir is the directory where the package name starts. e.g. For an AIDL fil
-// mymodule/aidl_src/com/android/IFoo.aidl, baseDir is mymodule/aidl_src given that the package name is
-// com.android. The build system however don't know the package name without actually reading the AIDL file.
-// Therefore, we rely on the user to correctly set the base directory via following two methods:
-// 1) via the 'path' property of filegroup or
-// 2) via `local_include_dir' of the aidl_interface module.
-func getBaseDir(ctx android.ModuleContext, src android.Path, aidlRoot android.Path) string {
-	// By default, we try to get 1) by reading Rel() of the input path.
-	baseDir := strings.TrimSuffix(src.String(), src.Rel())
-	// However, if 2) is set and it's more specific (i.e. deeper) than 1), we use 2).
-	if strings.HasPrefix(aidlRoot.String(), baseDir) {
-		baseDir = aidlRoot.String()
-	}
-	return baseDir
-}
-
 func fixRustName(name string) string {
 	return strings.Map(func(r rune) rune {
 		switch r {
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
deleted file mode 100644
index 03342a3..0000000
--- a/build/apex/Android.bp
+++ /dev/null
@@ -1,33 +0,0 @@
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "system_tools_aidl_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["system_tools_aidl_license"],
-}
-
-apex_test {
-    name: "com.android.aidltest",
-    manifest: "apex_manifest.json",
-    file_contexts: ":apex.test-file_contexts",
-    key: "com.android.aidltest.key",
-    certificate: ":com.android.aidltest.certificate",
-    installable: false,
-    updatable: false,
-
-    native_shared_libs: [
-        "test-piece-1-V3-ndk_platform",
-    ],
-}
-
-apex_key {
-    name: "com.android.aidltest.key",
-    public_key: "com.android.aidltest.pubkey",
-    private_key: "com.android.aidltest.pem",
-}
-
-android_app_certificate {
-    name: "com.android.aidltest.certificate",
-    certificate: "com.android.aidltest",
-}
diff --git a/build/apex/apex_manifest.json b/build/apex/apex_manifest.json
deleted file mode 100644
index 5b81403..0000000
--- a/build/apex/apex_manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
-  "name": "com.android.aidltest",
-  "version": 1
-}
diff --git a/build/apex/com.android.aidltest.pem b/build/apex/com.android.aidltest.pem
deleted file mode 100644
index 1982a2d..0000000
--- a/build/apex/com.android.aidltest.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKQIBAAKCAgEA5b93QQ6WB+Ms0/IztCz9ZqvEx0oL/9ZsBrzkiQcd3Yp9HVcF
-Jevu4KeX86Bu2t8nZnr6CxJPy6gw92itfHSbOXmd+fs8tch1D6bqtU3xxq3Wg8SB
-CKWD7wZoDd7rkLqCjV6IDebUK0DtP1WmtTMm2mIGKTCnqOgfcnkSe1YwQ22suKKs
-orOIrrs2wjyIZnh0iIvPpsfaI4YQ6Oo0+VTqb2kMpkSlB1ynd8fUTxMRJCYXywyO
-u8HT7DVMj9/XYF0nN7YFFf/Qcd0UOXGg0vCbmnijJawkvcb4fLqQtJ/oVajBhC+t
-cnF1mUgoh4qqBFMVcaKikiLI/9nuOr2jalnM4tpdzPWbPCBFtrp+1Bjm44+2KdwZ
-Klzzzj5gL8IOpTDGbA706nGah/YsWIewyLNub6OxZ9Sue4Sgjjl2mZMto6o1cmnw
-wzNf5B6jqAa8X8zLXjKuf9HVP+vu6wVFmfFxCVEPFTuij8fOB3YC+qIKu+ut7Z25
-MPhPQaK2xTyPFM+PxgI8oIB8Vc4U0Q3B/FsRSivQ5D3bU6t44z36VNiE0LQgWcVT
-sC6byvc3bFQelZxVZV9iOasK9tOIPTQZyvFVlEDC2UGlFIkh8o1yvDiVWqUmP6fa
-qc05ye+4WQU+QjGMzxiSmApJvyWxwQonUA31wh7hN4SYw95GQTzwh0wEIw8CAwEA
-AQKCAgAD3sXTgrtkRp9qspnMXzWllR8rfEPXe3U2Z9gxtrz6DmstI1oi2WacwjX9
-FKbJaRjw0QGFTjmp5Jtuj4Tco9o5jaLrox/SsB3ItbcedsGr5yHF9nl1+9PNIv59
-vVOajInGd+Ey2sCYOe/FMVwtkT8GTsBr0TYB0mc1NnTpPvpxKFfQhG0EEKIsz1qM
-yxhBIaZU5oYI+TTjhE6knc1mpdeNKOfdpSpihV0M14DsFBYl1b5w3TVKVGmNgRhZ
-FBw8s1UFyzsqs7R/NoowrYlYBFWatI2LBOtZhxCIiVwGrurrBny8DVGOq/qfKmgE
-YIGcsQmbcHHspElehf1NYARwtjKNV5N8IlSFMuGoMqBgxky267uBk2MsmGpSNbwy
-LNORpDz+FbGicxntqIE+F77TH8XSi2wJR9gSiWv3vfQF3WDsuiTqjnkcnaa0j/Nh
-X8bkNW8d846OopbxWSsLQHk/0tgUHmvx9VVwVwgvtdEHDFORdUI2b6FkpwwqNYB0
-F+Q7eYc4k+ZUUCj1MCwfgSoIwiHpeSjyYslFqsaTfk6cMTdgFCMrljLyMDlz1O3m
-RmCrsrkrRAdl0wMlrHhLq4ZSmwUPh8QzD0lZdLgO1ca3/k6q+l1d8UpkM4k6Pdqc
-PbU8di/GOnb37ovS6q36tVoRVmhm/wxOI0Nk6xBeS0F5HvBXAQKCAQEA+rOg9fki
-DsDNKMzI87aU8/JVbA50oYm4kxYheDQCcl6xwq6pfAshRI4Muym5GNQvvAV5kIEu
-sP4u9UGMvDFVnJn4zf8Ont53DNWLA5CA7dR1CSUUC78xzy6x2vwQN31laa3zgDmn
-2Nr3+uwvBkK96xuWPQoYKouykQ0psyio9rhAy+V9PIEnJkpKn5YIrOGsjTKTZAln
-L/uzeHgEdgGDWp0jqMMeMu8+VJSb9LND2ClquLhRnRzcEH880Crp/3V2+J7xtBz6
-7Q+jV7KkH+pPpIvOlQ0w7KK2D9nFo7Mdq/DE1A8+8UYyy28DtgQ2W5jh5vwn4K1U
-ebkpKSfxOUJqVwKCAQEA6pp4kC1XbK7dcgaWlRNFOr0IouHm/JfaSzH173qG9l/E
-zjHQjoQYN3A+lZcXWXScXrmuS0iS+RUd5Lm65EB0TEx40r7m9DL/7pJxnRSvfbrD
-cNbTZFQ25e9uJYiKodvDya706e0n0wBWb8mb/X5NlCBTPXopZbC3fn6SLm0PnNq9
-/vEPNcYABD2dUf0hF05Q2WtoGeY5dPCaO77zq+N3M6hgdfLMnDiYJBbwxbFUsH4R
-j8kDUlevQaamdgWSuHIS4xn5S5Tp019l+RmnoGYbdWSSxqrOsPRYuaSVKYx+oHQP
-UEsj4H2k0McOLe2bcQgk+8RSheIeIIrskfuDbVEKCQKCAQEA3OnozpdIUaPHpUo/
-UbL0Mrq6V0utrqMDSGlZ+Ogrt8iF772lj67nE9fwlATCHITtw0s3wgRztndlvayT
-bUoz3Jk5S5yTr57tXRvXMb7mPazXrMVFksxaAe1twEAZsiwHb0ZfqgAkTc02c6Ao
-F+Y8IK7ghs0cWnFbWsI0mrEborzeLE3/O4+7hdw1Qccdweni+VE13BMFIJ01mtR3
-ad0PeIu73nyBYfS8AiAqBUjqYdKtPjT9hermaIsWdYE7TWae/Zph9osK+larYx4B
-zjXVFHQ2B9Xl5L/EmtcVd5jgbqDtcMg2eLmZDPa4WG4B0Fk5xycvpKZYKCLniGKw
-B/rkZQKCAQAD06M1zteHOU75ZiwcoGTXsW+roH2xDxULdvQpBNmguS0vo9ZgDL2M
-YfNTY1SJLALE9MhoB/YFxBdpvLHUuUxsVi7+WQjRYOeVz6O0yTqXlW1MsORf1ZPT
-qlUknZaNT1VhO85Y5npo0a+XQTWfK+k+CkzxSsXUF87WbGAcC8FecJ76wpnZ6bHk
-X9DqHnPkum1NLphTG9NCGg6Z/OJiomI2YH+6TMyTm8S3ifxBbUQRYO0OaFv6gt2j
-94DtmeerxIiUVb8gQXyS6xJxvr5iOmgmQQ632N9oOYQc+xdHxzfljB8X0zHxnnsK
-wMR1cVPAwz4/MRObhXWyWDHFq9GX/eNpAoIBAQCxWqsYbTC4JzoBBaZSoMBpyVYB
-R9lfyKaMLlh4szG0YcP7naPI5KAidSjkU4son7vz7LsXDHBKzgK4gMtbUIFOqFFv
-ZUaaSkSBkbEcJgs7eP24QMD3I3kNprkPFIZnyMT9VKIRVLhToA2TddSS+HcIiLUV
-NpG7eD8LZW9B/CfUOEq7bnc+mw0KD48b94Bj/PGF7IOvBjyQhOs92OUnw3H+3lio
-X1gezko6qobMIBvbu4giGaJHj7bTil0l0bWR8dwfMRphYf9lpXpkiLOK/VjWT/Fn
-5nJ++VczKi7UfACemZo9uhY2o/oEuXxQ6NHI/WexZSN/ovo+RXcoBk/TZjJT
------END RSA PRIVATE KEY-----
diff --git a/build/apex/com.android.aidltest.pk8 b/build/apex/com.android.aidltest.pk8
deleted file mode 100644
index aa7a092..0000000
--- a/build/apex/com.android.aidltest.pk8
+++ /dev/null
Binary files differ
diff --git a/build/apex/com.android.aidltest.pubkey b/build/apex/com.android.aidltest.pubkey
deleted file mode 100644
index 6196ca6..0000000
--- a/build/apex/com.android.aidltest.pubkey
+++ /dev/null
Binary files differ
diff --git a/build/apex/com.android.aidltest.x509.pem b/build/apex/com.android.aidltest.x509.pem
deleted file mode 100644
index 66972ff..0000000
--- a/build/apex/com.android.aidltest.x509.pem
+++ /dev/null
@@ -1,35 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIGJzCCBA+gAwIBAgIUGIiwEuQwMTOwnLSG/4GGkY1o/jEwDQYJKoZIhvcNAQEL
-BQAwgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
-DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
-b2lkMR0wGwYDVQQDDBRjb20uYW5kcm9pZC5haWRsdGVzdDEiMCAGCSqGSIb3DQEJ
-ARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAgFw0yMDA4MTgwNTQ2MThaGA80NzU4MDcx
-NTA1NDYxOFowgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYw
-FAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQL
-DAdBbmRyb2lkMR0wGwYDVQQDDBRjb20uYW5kcm9pZC5haWRsdGVzdDEiMCAGCSqG
-SIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQAD
-ggIPADCCAgoCggIBAMHqtY+vlXFVIiRNYlnrJ3dhfBPfNxvwK5n25BeAyZMlOmLr
-L8Nr5PJVsiGXts6forTUsnLSVzrNUjdFBWrOWXSJQ/QbNn0luryxcUyfDBzP85vl
-M6PZmwie3/bzQzGUY+LZwNqTMCKy1xv8KiWkmz4SN/yb4ACkhBTD/9jP/WhTLjrp
-vO7/RxigA8GyNri/CRTY5tu1E1xC+K9HVfTHjnQg69SUzIVQJpDYBwIQDXkc7uNu
-OVeoTFzzWqTHpM6fvIVvBuKBWL6uTajdnsJ6e75WIV21bwuvRBNlDKucC7Z3h8q6
-hDgm7q1YgLDBjzpfYOa+PhACEmn5FSorCZ6Ujm2osWIqaaTsrj7M+iuwOaANRVTu
-gReUtHyw9lhqotBrhEMkPMdRjKnqMQlh81+3D3H6/cZzdEsVXFerLewZI8iJYohp
-z0777SDo8FEEBrmdm/7VknNJRykKhfSpFfYZZE6AiTL1x8lH+5YBHCbadkd/reiQ
-EjfWlwfePPLV7oIki3yqRWjYT1MTt3KlASGZ9HZI2odezIcojZvgHdHX8MGytfWD
-kXziJVrXMUXgUfljQwpsjEhE1R13E5jdpVspw624BPLOwoEzY70tE0sEd6WlSVE1
-FV3AiVIS3vlXEgbK+6hmG+lg/qv0ZIcwD2bjKnvEOtL077HHWWpjy6zuVFEvAgMB
-AAGjUzBRMB0GA1UdDgQWBBSpYialgC5HyXVb1G3rqKnxa0SozjAfBgNVHSMEGDAW
-gBSpYialgC5HyXVb1G3rqKnxa0SozjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
-DQEBCwUAA4ICAQAPAIWQdUp0pmRcTqtHN0k4CGvBJrUrJj92Ui2vDEiphH3ctxOZ
-kcW1lje1LlHGd9b070nSQhuwyJHos++xHPP3J2FcKgVS5XTLP27asIqZnS5bmESV
-yjLIiXWk3ifgyd5ntfR4pov6MUmfYJ6etRHz+16UH7IfsDU4boaZ5pd0jNL9yAHM
-S0hqEWMVSUnT6fHlEXB7WyXR92fGkmGdVMmFwtpNnmIkthvfndueaJEDWHRbwr1Y
-f0lbvZ0p7dVi9ZhR1k6aRmM6fvAWYB7A0bZe/kvUtFJjNThP4C6fLrvalBsBavw4
-zaGJAUv0cDD1dlaN4XXRs0pLFIemxtiy4FNb+lXinCu1M/LeY04SZrV24jMXX0Jl
-z0g99OByejGn2OqycTguhgdO8KKVOsHm29p9l9aDUUjtEZGd6MD+z/AA+yP/TvKm
-Lu1fwScSqSllZLY/qNMFZUTaL4upY2W3Xk2FxMG/9h8IHw6Dcn9A74Psf6tsdRWg
-D3pFceg8k9nJTh2MCChhVBP2icGsrJXtQRHtGuqOU9lsz6HD1r4DQgnPoHmP511k
-p8uKlMk0IxBf5T1hB1ebvZYS9VTNC5J9/Cjp20LXR5wZa3qT5u4G0NMJN1JX0MR1
-dQWBpJjzXI932kYJA6d3djUn8kXAobTBgySs90i+MjKe08l8/xZo/4FwXA==
------END CERTIFICATE-----
diff --git a/build/apex/key.pem b/build/apex/key.pem
deleted file mode 100644
index ad5f02c..0000000
--- a/build/apex/key.pem
+++ /dev/null
@@ -1,52 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQDB6rWPr5VxVSIk
-TWJZ6yd3YXwT3zcb8CuZ9uQXgMmTJTpi6y/Da+TyVbIhl7bOn6K01LJy0lc6zVI3
-RQVqzll0iUP0GzZ9Jbq8sXFMnwwcz/Ob5TOj2ZsInt/280MxlGPi2cDakzAistcb
-/ColpJs+Ejf8m+AApIQUw//Yz/1oUy466bzu/0cYoAPBsja4vwkU2ObbtRNcQviv
-R1X0x450IOvUlMyFUCaQ2AcCEA15HO7jbjlXqExc81qkx6TOn7yFbwbigVi+rk2o
-3Z7Cenu+ViFdtW8Lr0QTZQyrnAu2d4fKuoQ4Ju6tWICwwY86X2Dmvj4QAhJp+RUq
-KwmelI5tqLFiKmmk7K4+zPorsDmgDUVU7oEXlLR8sPZYaqLQa4RDJDzHUYyp6jEJ
-YfNftw9x+v3Gc3RLFVxXqy3sGSPIiWKIac9O++0g6PBRBAa5nZv+1ZJzSUcpCoX0
-qRX2GWROgIky9cfJR/uWARwm2nZHf63okBI31pcH3jzy1e6CJIt8qkVo2E9TE7dy
-pQEhmfR2SNqHXsyHKI2b4B3R1/DBsrX1g5F84iVa1zFF4FH5Y0MKbIxIRNUddxOY
-3aVbKcOtuATyzsKBM2O9LRNLBHelpUlRNRVdwIlSEt75VxIGyvuoZhvpYP6r9GSH
-MA9m4yp7xDrS9O+xx1lqY8us7lRRLwIDAQABAoICAEenzEl5D1bep4wUkEg7zcye
-WDQbooiPWf09rxFERLg75HRTBcZHo0UtB3LEVgfKE1yQ0BP/x73xyvSja5oJACNA
-6bxVJfBetb8uLniquNYYvaMYsdlU+qXX11iwkV7Lv5E+97WM+BeKUFSF/KkGR1tL
-bibJDqAOKsRlnK/oQ3J+cjHQ10DVUdc2ocy8Zt4jsV5jvALpyWqpUK2sRYX7C5e7
-5okaJu0ILggN26EWf3QGjfu6ajQK+5TJU/BZ2XuEqSwBV+Dw/PMRA59nrVed3QX7
-W7794TfHHvevulvbgLR/PM1b2KnLMR0a/ArUq3FddzgsilBuA5HnObvoRVi0+l/D
-Sc0eoOS3+8dRklsv1+pR2rJX6vNkspex4D60/nV/vSLhaH5Qnkxs1lrApBtlnhVv
-4uRFotW8LXkFTBno4aTxHXMK0bJeQQsHyHHglcdEFpa3CZAfl/bvfiZEvJBfbIKD
-69MHii/OQBl2nslXoK9Cdcrv4Blg2Ht1V9v7opqvj+7tH86qyk+TpGwjJv0RHj+x
-nLZvix3zh77JhaPCp7+uhi7oo8ZT9y7o0gTHVWEWFi8V+tN/Trn1fLar8AFMxuD5
-4BFSgPlyzXo1hzsQLrbW6WHrbQo75LY6PQOeNI7lk9mp7PkzZ4Hwe3AU3STBEZKz
-uKf/7OnsznOcy+s+J30pAoIBAQD6y0CDUmZs+6aYxJ0D/AAIr2JUvRPlwowRZ7Ye
-Oil22DQ+cCTa5j6luAZrQ3x8Qmzy3RSetdxekygehyueWJwxtfsnUgUyIFlb1icJ
-Ou0rBFMZv/pfuGgO9QlJ67rWnd7ceolcT7i3OUvJMDMMCP5dqgQcyFqRnTMroX1c
-Y3IM0R7tzJMPX6mwgnZXNn2KVKtD4ZI2+F8t2GnK6XHv274NhTl8JCdsb3yuUhzH
-zX6axMAVIXNd0keMQ6eLdGV6LT6dCNYRrrmbjd8NzsxbIW8IsGZFlRoB6i845/sa
-C37Jntt2/G7p3cVA8tyOQ7ZZVZQ2nlL1sM8F8RACPfPaqmlVAoIBAQDF8TSk90NP
-Wc4HONuo8QPCMEXaHo1tqH+aUzqX9WamVWk4yfv1BVuD3q2UvKLNRMzQpa1gAZjk
-e4STOa1eCNCpeA3aqbdunrUrfoz02SQSoTKM+o5hbBiiH4wK+oXkkR29+VdU2Yww
-kCTKCFjBf4hV+2u1/eBuR1MDcOVwQW6N3Sk37ImwGtygRrHIPuY8Ir00WQmpKP6W
-MMdi0tUNXxp51vs8Q8TGrfZC/l7gs1OEaaSrb+60epprwFPWMiFubPHyQ7f9dm32
-lbjhUPvJfF04pTazV2aAyAYZPaQmNhQ1TQlW8ggtZfVc9/Hw/eq4K/3VevixCqqK
-mmcYcDf4qwBzAoIBADEhtm7Dqss49adCBVytdrg826+sJwTA+z3Bqpz7WfotWvbM
-c3vq1WUTyzYiT3XscXmWtB5vlE921so8QuBPjbHza9OFLv1l9vuV1anqQGJIA5us
-z3kHIGOlv38azkyTOwDIhLZv68kBUYaFicqWzHY/A3U8Dvot6MNobK230bUPFtcR
-V9IQNKcet95YD3oVIkQ3IbThLYxGtFsLJsYNr4roiZ13W73TjYJ9FaRS7rWVS+gX
-2IkN0/R3oJAiamroCDctbvqh1zzRK1yCIejMgPsby71f+2tanIuybq/ohpsrIuWJ
-iJUKXEVgDrNUMpoHuPSGScxWKgiI9FDsICS7c80CggEALUJmwCWNbXJiSoJ0r19U
-da1l+2aq/dzeOGI5bo99BiFXatW8V5z+/NsIo46yRu8pSbfoOaCD3hJkEOnKO0sW
-svkxacMOnyuIz0YjYsTXm67iCRwtPBdkVoWSFtyLiuSngU2m607G4D/FObDI4o2P
-leFkEnvXOj/yukGxJIbBiYx9JT1fijXKJpejhN7k8/EZhAOr0tL9y0eh/3Wno2QQ
-gLVoQrJYJvmV6mGRPh2ixg8FyPFSClBSSLr0MHDL9hzRAYz8X+cZY51+ZX6H490c
-z5vvMviUBnQ1+MWAaABLhJh1vzyeJAtBHB3RY0Ibzjq40nxIqup+biy5z/uwwJoR
-AwKCAQBWMGM6CNec1ZzVBjELuvOhcnL+gN6UpmiKbQR+gDqx+Ne2nGXnNvhHwmHz
-4itN/KwE3v65d89LVmWc1VBEbCc22GYAgtoNm81NTeMIiDZsckg4GWFriG7NI7vl
-ssl7NDBHfk5f3jSiv/dguEK8FQgUaYL+T0fhH714Jzdru5MAVZ3XSTqtU3KX+PHh
-6rEh2RxkP2iZZnpM1VfW/icdUalzgt6o+CNREhcg3oxo4MKJqccYw8CKiCOT5J97
-c+x69cDAOSStC9bGkRi4IDOG71asodXvfvpO/NznF43bQIslm4AO63V9A8G+oaDc
-rXj28Z+zT528vAQI3nb+Oq3EvUNN
------END PRIVATE KEY-----
diff --git a/build/go.mod b/build/go.mod
index 3ef7a49..5e5f4b9 100644
--- a/build/go.mod
+++ b/build/go.mod
@@ -7,8 +7,16 @@
 
 replace android/soong v0.0.0 => ../../../../build/soong
 
-replace github.com/golang/protobuf v0.0.0 => ../../../../external/golang-protobuf
+replace google.golang.org/protobuf v0.0.0 => ../../../../external/golang-protobuf
 
 replace github.com/google/blueprint v0.0.0 => ../../../../build/blueprint
 
+// Indirect deps from golang-protobuf
+exclude github.com/golang/protobuf v1.5.0
+
+replace github.com/google/go-cmp v0.5.5 => ../../../../external/go-cmp
+
+// Indirect dep from go-cmp
+exclude golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
+
 go 1.13
diff --git a/.clang-format b/build/hash_gen.sh
old mode 100644
new mode 100755
similarity index 63%
rename from .clang-format
rename to build/hash_gen.sh
index da79056..9bb7e83
--- a/.clang-format
+++ b/build/hash_gen.sh
@@ -1,5 +1,6 @@
-#
-# Copyright (C) 2018 The Android Open Source Project
+#!/usr/bin/env bash
+
+# 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.
@@ -12,13 +13,11 @@
 # 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.
-#
 
-BasedOnStyle: Google
-CommentPragmas: NOLINT:.*
-DerivePointerAlignment: false
-AllowShortFunctionsOnASingleLine: Inline
-ColumnLimit: 100
-TabWidth: 2
-UseTab: Never
-IndentWidth: 2
+set -e
+
+if [ $# != 3 ]; then
+  echo "Usage: hash_gen.sh <api_path> <latest-version> <hash_file_path>"
+  exit 1
+fi
+(cd $1 && find ./ -name "*.aidl" -print0 | LC_ALL=C sort -z | xargs -0 sha1sum && echo $2) | sha1sum | cut -d " " -f 1 >> $3
diff --git a/build/properties.go b/build/properties.go
index 69914ed..a37453a 100644
--- a/build/properties.go
+++ b/build/properties.go
@@ -21,17 +21,28 @@
 type hostProperties struct {
 	Cflags []string
 }
-type perTargetProperties struct {
+
+type darwinProperties struct {
 	Enabled *bool
 }
 
+type imageProperties struct {
+	Shared_libs         []string
+	Header_libs         []string
+	Exclude_shared_libs []string
+	Cflags              []string
+}
+
 type ccTargetProperties struct {
-	Host   hostProperties
-	Darwin perTargetProperties
+	Host     hostProperties
+	Darwin   darwinProperties
+	Platform imageProperties
+	Vendor   imageProperties
+	Product  imageProperties
 }
 
 type rustTargetProperties struct {
-	Darwin perTargetProperties
+	Darwin darwinProperties
 }
 
 type ccProperties struct {
@@ -42,6 +53,7 @@
 	Vendor_available          *bool
 	Odm_available             *bool
 	Product_available         *bool
+	Recovery_available        *bool
 	Host_supported            *bool
 	Generated_sources         []string
 	Generated_headers         []string
@@ -56,7 +68,6 @@
 	Stem                      *string
 	Apex_available            []string
 	Min_sdk_version           *string
-	UseApexNameMacro          bool
 	Target                    ccTargetProperties
 	Tidy                      *bool
 	Tidy_flags                []string
@@ -77,16 +88,18 @@
 }
 
 type rustProperties struct {
-	Name           *string
-	Crate_name     string
-	Owner          *string
-	Defaults       []string
-	Host_supported *bool
-	Srcs           []string
-	Rustlibs       []string
-	Stem           *string
-	Target         rustTargetProperties
-	Apex_available []string
+	Name             *string
+	Crate_name       string
+	Owner            *string
+	Defaults         []string
+	Host_supported   *bool
+	Vendor_available *bool
+	Srcs             []string
+	Rustlibs         []string
+	Stem             *string
+	Target           rustTargetProperties
+	Apex_available   []string
+	Min_sdk_version  *string
 }
 
 type phonyProperties struct {
diff --git a/build/tests_6/test6/Bar.aidl b/build/tests_6/test6/Bar.aidl
new file mode 100644
index 0000000..671efac
--- /dev/null
+++ b/build/tests_6/test6/Bar.aidl
@@ -0,0 +1,7 @@
+package test6;
+
+import test6.Foo;
+
+parcelable Bar {
+    Foo[] foos;
+}
diff --git a/build/tests_6/test6/Foo.aidl b/build/tests_6/test6/Foo.aidl
new file mode 100644
index 0000000..143d9f2
--- /dev/null
+++ b/build/tests_6/test6/Foo.aidl
@@ -0,0 +1,6 @@
+package test6;
+
+parcelable Foo {
+    ParcelableHolder ph;
+    ParcelFileDescriptor[] pfds; // not moveable
+}
diff --git a/check_valid.cpp b/check_valid.cpp
new file mode 100644
index 0000000..2d7fb90
--- /dev/null
+++ b/check_valid.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+#include "check_valid.h"
+#include "aidl.h"
+
+#include <vector>
+
+namespace android {
+namespace aidl {
+
+using TypePredicate = std::function<bool(const AidlTypeSpecifier&)>;
+
+namespace {
+bool IsListOf(const AidlTypeSpecifier& type, TypePredicate pred) {
+  return type.GetName() == "List" && type.IsGeneric() && type.GetTypeParameters().size() == 1 &&
+         pred(*type.GetTypeParameters().at(0));
+}
+bool IsArrayOf(const AidlTypeSpecifier& type, TypePredicate pred) {
+  return type.IsArray() && pred(type);
+}
+bool IsInterface(const AidlTypeSpecifier& type) {
+  return type.GetDefinedType() && type.GetDefinedType()->AsInterface();
+}
+}  // namespace
+
+struct CheckTypeVisitor : AidlVisitor {
+  bool success = true;
+  std::vector<TypePredicate> checkers;
+
+  void Visit(const AidlTypeSpecifier& type) override {
+    for (auto& checker : checkers) {
+      if (!checker(type)) {
+        success = false;
+      }
+    }
+  }
+
+  void Check(TypePredicate checker) { checkers.push_back(std::move(checker)); }
+};
+
+bool CheckValid(const AidlDocument& doc, const Options& options) {
+  const auto lang = options.TargetLanguage();
+  const auto min_sdk_version = options.GetMinSdkVersion();
+
+  CheckTypeVisitor v;
+
+  v.Check([&](const AidlTypeSpecifier& type) {
+    const auto valid_version = MinSdkVersionFromString("Tiramisu").value();
+    if ((IsListOf(type, IsInterface) || IsArrayOf(type, IsInterface)) &&
+        lang == Options::Language::JAVA && min_sdk_version < valid_version) {
+      const auto kind = IsListOf(type, IsInterface) ? "List" : "Array";
+      AIDL_ERROR(type) << kind << " of interfaces is available since SDK = " << valid_version
+                       << " in Java. Current min_sdk_version is " << min_sdk_version << ".";
+      return false;
+    }
+    return true;
+  });
+
+  v.Check([&](const AidlTypeSpecifier& type) {
+    const auto valid_version = MinSdkVersionFromString("S").value();
+    if (type.GetName() == "ParcelableHolder" && min_sdk_version < valid_version) {
+      AIDL_ERROR(type) << " ParcelableHolder is available since SDK = " << valid_version
+                       << ". Current min_sdk_version is " << min_sdk_version << ".";
+      return false;
+    }
+    return true;
+  });
+
+  v.Check([&](const AidlTypeSpecifier& type) {
+    // TODO(b/151102494): annotation is applied on the return type
+    if (type.IsPropagateAllowBlocking() && options.GetMinSdkVersion() < JAVA_PROPAGATE_VERSION) {
+      AIDL_ERROR(type) << "@PropagateAllowBlocking requires " << JAVA_PROPAGATE_VERSION
+                       << ". Current min_sdk_version is " << min_sdk_version << ".";
+      return false;
+    }
+    return true;
+  });
+
+  VisitTopDown(v, doc);
+  return v.success;
+}
+
+}  // namespace aidl
+}  // namespace android
diff --git a/check_valid.h b/check_valid.h
new file mode 100644
index 0000000..0fdd220
--- /dev/null
+++ b/check_valid.h
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "aidl_language.h"
+#include "options.h"
+
+namespace android {
+namespace aidl {
+
+bool CheckValid(const AidlDocument& doc, const Options& options);
+
+}
+}  // namespace android
\ No newline at end of file
diff --git a/comments.cpp b/comments.cpp
index afbdc8f..8feee28 100644
--- a/comments.cpp
+++ b/comments.cpp
@@ -40,6 +40,7 @@
 
 static const std::string_view kLineCommentBegin = "//";
 static const std::string_view kBlockCommentBegin = "/*";
+static const std::string_view kBlockCommentMid = " *";
 static const std::string_view kBlockCommentEnd = "*/";
 static const std::string_view kDocCommentBegin = "/**";
 static const std::string kTagDeprecated = "@deprecated";
@@ -222,15 +223,31 @@
   std::stringstream out;
   for (auto it = begin(comments); it != end(comments); it++) {
     const bool last = next(it) == end(comments);
-    // We only re-format the last/block comment which is not already a doc-style comment.
-    if (last && it->type == Comment::Type::BLOCK && !StartsWith(it->body, kDocCommentBegin)) {
-      out << kDocCommentBegin << ConsumePrefix(it->body, kBlockCommentBegin);
+    auto lines = TrimmedLines(*it);
+
+    if (it->type == Comment::Type::LINE) {
+      for (const auto& line : lines) {
+        out << kLineCommentBegin << line;
+      }
     } else {
-      out << it->body;
+      if (last || StartsWith(it->body, kDocCommentBegin)) {
+        out << kDocCommentBegin;
+      } else {
+        out << kBlockCommentBegin;
+      }
+      bool multiline = lines.size() > 1;
+
+      if (multiline) out << "\n";
+      for (const auto& line : lines) {
+        if (multiline) out << kBlockCommentMid;
+        out << " " << line;
+        if (multiline) out << "\n";
+      }
+      out << " " << kBlockCommentEnd << "\n";
     }
   }
   return out.str();
 }
 
 }  // namespace aidl
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/diagnostics.cpp b/diagnostics.cpp
index 694e96a..13f918f 100644
--- a/diagnostics.cpp
+++ b/diagnostics.cpp
@@ -195,6 +195,7 @@
     bool has_twoway = false;
     for (const auto& m : i.GetMethods()) {
       if (!m->IsUserDefined()) continue;
+      if (Suppressed(*m)) continue;
       if (m->IsOneway()) {
         has_oneway = true;
       } else {
@@ -208,6 +209,14 @@
              "of client code.";
     }
   }
+  bool Suppressed(const AidlMethod& m) const {
+    for (const auto& w : m.GetType().SuppressWarnings()) {
+      if (w == to_string(DiagnosticID::mixed_oneway)) {
+        return true;
+      }
+    }
+    return false;
+  }
 };
 
 struct DiagnoseOutArray : DiagnosticsVisitor {
@@ -248,6 +257,45 @@
   }
 };
 
+struct DiagnoseImports : DiagnosticsVisitor {
+  DiagnoseImports(DiagnosticsContext& diag) : DiagnosticsVisitor(diag) {}
+  void Visit(const AidlDocument& doc) override {
+    auto collide_with_decls = [&](const auto& import) {
+      for (const auto& type : doc.DefinedTypes()) {
+        if (type->GetCanonicalName() != import && type->GetName() == SimpleName(import)) {
+          return true;
+        }
+      }
+      return false;
+    };
+
+    std::set<std::string> imported_names;
+    for (const auto& import : doc.Imports()) {
+      if (collide_with_decls(import)) {
+        diag.Report(doc.GetLocation(), DiagnosticID::unique_import)
+            << SimpleName(import) << " is already defined in this file.";
+      }
+      auto [_, inserted] = imported_names.insert(SimpleName(import));
+      if (!inserted) {
+        diag.Report(doc.GetLocation(), DiagnosticID::unique_import)
+            << SimpleName(import) << " is already imported.";
+      }
+    }
+  }
+};
+
+struct DiagnoseUntypedCollection : DiagnosticsVisitor {
+  DiagnoseUntypedCollection(DiagnosticsContext& diag) : DiagnosticsVisitor(diag) {}
+  void Visit(const AidlTypeSpecifier& t) override {
+    if (t.GetName() == "List" || t.GetName() == "Map") {
+      if (!t.IsGeneric()) {
+        diag.Report(t.GetLocation(), DiagnosticID::untyped_collection)
+            << "Use List<V> or Map<K,V> instead.";
+      }
+    }
+  }
+};
+
 bool Diagnose(const AidlDocument& doc, const DiagnosticMapping& mapping) {
   DiagnosticsContext diag(mapping);
 
@@ -259,6 +307,8 @@
   DiagnoseOutArray{diag}.Check(doc);
   DiagnoseFileDescriptor{diag}.Check(doc);
   DiagnoseOutNullable{diag}.Check(doc);
+  DiagnoseImports{diag}.Check(doc);
+  DiagnoseUntypedCollection{diag}.Check(doc);
 
   return diag.ErrorCount() == 0;
 }
diff --git a/diagnostics.inc b/diagnostics.inc
index 59ea7c8..101b737 100644
--- a/diagnostics.inc
+++ b/diagnostics.inc
@@ -7,4 +7,6 @@
 DIAG(mixed_oneway, "mixed-oneway", false)
 DIAG(out_array, "out-array", false)
 DIAG(out_nullable, "out-nullable", false)
+DIAG(unique_import, "unique-import", false)
 DIAG(unknown_warning, "unknown-warning", false)
+DIAG(untyped_collection, "untyped-collection", false)
diff --git a/diagnostics_unittest.cpp b/diagnostics_unittest.cpp
index 0ea3141..0066b9f 100644
--- a/diagnostics_unittest.cpp
+++ b/diagnostics_unittest.cpp
@@ -129,6 +129,17 @@
   });
 }
 
+TEST_F(DiagnosticsTest, DontMixOnewayWithTwowayMethodsSuppressedAtMethod) {
+  expect_diagnostics = {};
+  ParseFiles({
+      {"IFoo.aidl",
+       "interface IFoo {\n"
+       "  void foo();\n"
+       "  @SuppressWarnings(value={\"mixed-oneway\"}) oneway void bar();\n"
+       "}"},
+  });
+}
+
 TEST_F(DiagnosticsTest, OnewayInterfaceIsOkayWithSyntheticMethods) {
   optional_args = "--version 2";  // will add getInterfaceVersion() synthetic method
   expect_diagnostics = {};
@@ -178,3 +189,62 @@
                "}"},
               {"Bar.aidl", "parcelable Bar {}"}});
 }
+
+TEST_F(DiagnosticsTest, RejectImportsCollisionWithTopLevelDecl) {
+  expect_diagnostics = {DiagnosticID::unique_import};
+  ParseFiles({{"p/IFoo.aidl",
+               "package p;\n"
+               "import q.IFoo;\n"  // should collide with previous import
+               "interface IFoo{}"},
+              {"q/IFoo.aidl", "package q; interface IFoo{}"}});
+}
+
+TEST_F(DiagnosticsTest, RejectImportsCollision) {
+  expect_diagnostics = {DiagnosticID::unique_import};
+  ParseFiles({{"p/IFoo.aidl",
+               "package p;\n"
+               "import q.IBar;\n"
+               "import r.IBar;\n"  // should collide with previous import
+               "interface IFoo{}"},
+              {"q/IBar.aidl", "package q; interface IBar{}"},
+              {"r/IBar.aidl", "package r; interface IBar{}"}});
+}
+
+TEST_F(DiagnosticsTest, AllowImportingSelf) {
+  expect_diagnostics = {};
+  ParseFiles({{"p/IFoo.aidl",
+               "package p;\n"
+               "import p.IFoo;\n"
+               "interface IFoo{}"}});
+}
+
+TEST_F(DiagnosticsTest, RedundantImports) {
+  expect_diagnostics = {DiagnosticID::unique_import};
+  ParseFiles({{"p/IFoo.aidl",
+               "package p;\n"
+               "import q.IBar;\n"
+               "import q.IBar;\n"
+               "interface IFoo{}"},
+              {"q/IBar.aidl", "package q; interface IBar{}"}});
+}
+
+TEST_F(DiagnosticsTest, UntypedCollectionInterface) {
+  expect_diagnostics = {DiagnosticID::untyped_collection};
+  ParseFiles({{"IFoo.aidl", "interface IFoo { void foo(in Map m); }"}});
+}
+
+TEST_F(DiagnosticsTest, UntypedCollectionParcelable) {
+  expect_diagnostics = {DiagnosticID::untyped_collection};
+  ParseFiles({{"Foo.aidl", "parcelable Foo { Map m; }"}});
+}
+
+TEST_F(DiagnosticsTest, UntypedCollectionUnion) {
+  expect_diagnostics = {DiagnosticID::untyped_collection};
+  ParseFiles({{"Foo.aidl", "union Foo { List l; }"}});
+}
+
+TEST_F(DiagnosticsTest, UntypedCollectionInTypeArg) {
+  expect_diagnostics = {DiagnosticID::untyped_collection};
+  ParseFiles({{"IFoo.aidl", "interface IFoo { void foo(in Bar<Map> m); }"},
+              {"Bar.aidl", "parcelable Bar<T> {}"}});
+}
\ No newline at end of file
diff --git a/generate_aidl_mappings.cpp b/generate_aidl_mappings.cpp
index 994d6a3..4d2a5a0 100644
--- a/generate_aidl_mappings.cpp
+++ b/generate_aidl_mappings.cpp
@@ -27,8 +27,7 @@
   return method.PrintLine();
 }
 
-SignatureMap generate_mappings(const AidlDefinedType* defined_type,
-                               const AidlTypenames& typenames) {
+SignatureMap generate_mappings(const AidlDefinedType* defined_type) {
   const AidlInterface* interface = defined_type->AsInterface();
   SignatureMap mappings;
   if (interface == nullptr) {
@@ -40,10 +39,10 @@
       signature << interface->GetCanonicalName() << "|";
       signature << method->GetName() << "|";
       for (const auto& arg : method->GetArguments()) {
-        signature << java::JavaSignatureOf(arg->GetType(), typenames) << ",";
+        signature << java::JavaSignatureOf(arg->GetType()) << ",";
       }
       signature << "|";
-      signature << java::JavaSignatureOf(method->GetType(), typenames);
+      signature << java::JavaSignatureOf(method->GetType());
       mappings[signature.str()] = dump_location(*method);
     }
   }
diff --git a/generate_aidl_mappings.h b/generate_aidl_mappings.h
index d74a17f..09f611e 100644
--- a/generate_aidl_mappings.h
+++ b/generate_aidl_mappings.h
@@ -26,7 +26,7 @@
 
 using SignatureMap = std::unordered_map<std::string, std::string>;
 
-SignatureMap generate_mappings(const AidlDefinedType* iface, const AidlTypenames& typenames);
+SignatureMap generate_mappings(const AidlDefinedType* iface);
 }  // namespace mappings
 }  // namespace aidl
 }  // namespace android
diff --git a/generate_cpp.cpp b/generate_cpp.cpp
index 619a2f2..1ea2010 100644
--- a/generate_cpp.cpp
+++ b/generate_cpp.cpp
@@ -1,4 +1,4 @@
-/*
+/**
  * Copyright (C) 2015, The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -31,7 +31,6 @@
 
 #include "aidl_language.h"
 #include "aidl_to_cpp.h"
-#include "ast_cpp.h"
 #include "code_writer.h"
 #include "logging.h"
 #include "os.h"
@@ -55,6 +54,7 @@
 const char kDataVarName[] = "_aidl_data";
 const char kErrorLabel[] = "_aidl_error";
 const char kImplVarName[] = "_aidl_impl";
+const char kDelegateImplVarName[] = "_aidl_delegate";
 const char kParcelVarName[] = "_aidl_parcel";
 const char kReplyVarName[] = "_aidl_reply";
 const char kReturnVarName[] = "_aidl_return";
@@ -75,32 +75,24 @@
 const char kStrongPointerHeader[] = "utils/StrongPointer.h";
 const char kAndroidBaseMacrosHeader[] = "android-base/macros.h";
 
-unique_ptr<AstNode> BreakOnStatusNotOk() {
-  IfStatement* ret = new IfStatement(new Comparison(
-      new LiteralExpression(kAndroidStatusVarName), "!=",
-      new LiteralExpression(kAndroidStatusOk)));
-  ret->OnTrue()->AddLiteral("break");
-  return unique_ptr<AstNode>(ret);
+void GenerateBreakOnStatusNotOk(CodeWriter& out) {
+  out.Write("if (((%s) != (%s))) {\n", kAndroidStatusVarName, kAndroidStatusOk);
+  out.Write("  break;\n");
+  out.Write("}\n");
 }
 
-unique_ptr<AstNode> GotoErrorOnBadStatus() {
-  IfStatement* ret = new IfStatement(new Comparison(
-      new LiteralExpression(kAndroidStatusVarName), "!=",
-      new LiteralExpression(kAndroidStatusOk)));
-  ret->OnTrue()->AddLiteral(StringPrintf("goto %s", kErrorLabel));
-  return unique_ptr<AstNode>(ret);
+void GenerateGotoErrorOnBadStatus(CodeWriter& out) {
+  out.Write("if (((%s) != (%s))) {\n", kAndroidStatusVarName, kAndroidStatusOk);
+  out.Write("  goto %s;\n", kErrorLabel);
+  out.Write("}\n");
 }
 
-unique_ptr<AstNode> ReturnOnStatusNotOk() {
-  IfStatement* ret = new IfStatement(new Comparison(new LiteralExpression(kAndroidStatusVarName),
-                                                    "!=", new LiteralExpression(kAndroidStatusOk)));
-  ret->OnTrue()->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
-  return unique_ptr<AstNode>(ret);
-}
-
-ArgList BuildArgList(const AidlTypenames& typenames, const AidlMethod& method, bool for_declaration,
-                     bool type_name_only = false) {
-  // Build up the argument list for the server method call.
+// Format three types of arg list for method.
+//  for_declaration & !type_name_only: int a      // for method decl with type and arg
+//  for_declaration &  type_name_only: int /*a*/  // for method decl with type
+// !for_declaration                  :     a      // for method call with arg (with direction)
+string GenerateArgList(const AidlTypenames& typenames, const AidlMethod& method,
+                       bool for_declaration, bool type_name_only) {
   vector<string> method_arguments;
   for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
     string literal;
@@ -108,7 +100,7 @@
     // const reference but by value to make it easier for the user to keep
     // it beyond the scope of the call. unique_fd is a thin wrapper for an
     // int (fd) so passing by value is not expensive.
-    const bool nonCopyable = IsNonCopyableType(a->GetType(), typenames);
+    const bool non_copyable = IsNonCopyableType(a->GetType(), typenames);
     if (for_declaration) {
       // Method declarations need typenames, pointers to out params, and variable
       // names that match the .aidl specification.
@@ -117,28 +109,30 @@
       if (a->IsOut()) {
         literal = literal + "*";
       } else {
-        const auto definedType = typenames.TryGetDefinedType(a->GetType().GetName());
+        const auto defined_type = typenames.TryGetDefinedType(a->GetType().GetName());
 
-        const bool isEnum = definedType && definedType->AsEnumDeclaration() != nullptr;
-        const bool isPrimitive = AidlTypenames::IsPrimitiveTypename(a->GetType().GetName());
+        const bool is_enum = defined_type && defined_type->AsEnumDeclaration() != nullptr;
+        const bool is_primitive = AidlTypenames::IsPrimitiveTypename(a->GetType().GetName());
 
         // We pass in parameters that are not primitives by const reference.
         // Arrays of primitives are not primitives.
-        if (!(isPrimitive || isEnum || nonCopyable) || a->GetType().IsArray()) {
+        if (!(is_primitive || is_enum || non_copyable) || a->GetType().IsArray()) {
           literal = "const " + literal + "&";
         }
       }
-      if (!type_name_only) {
+      if (type_name_only) {
+        literal += " /*" + a->GetName() + "*/";
+      } else {
         literal += " " + a->GetName();
       }
     } else {
-      std::string varName = BuildVarName(*a);
+      std::string var_name = BuildVarName(*a);
       if (a->IsOut()) {
-        literal = "&" + varName;
-      } else if (nonCopyable) {
-        literal = "std::move(" + varName + ")";
+        literal = "&" + var_name;
+      } else if (non_copyable) {
+        literal = "std::move(" + var_name + ")";
       } else {
-        literal = varName;
+        literal = var_name;
       }
     }
     method_arguments.push_back(literal);
@@ -148,7 +142,9 @@
     string literal;
     if (for_declaration) {
       literal = CppNameOf(method.GetType(), typenames) + "*";
-      if (!type_name_only) {
+      if (type_name_only) {
+        literal += " /*" + string(kReturnVarName) + "*/";
+      } else {
         literal += " " + string(kReturnVarName);
       }
     } else {
@@ -157,165 +153,85 @@
     method_arguments.push_back(literal);
   }
 
-  return ArgList(method_arguments);
+  return Join(method_arguments, ", ");
 }
 
-unique_ptr<Declaration> BuildMethodDecl(const AidlMethod& method, const AidlTypenames& typenames,
-                                        bool for_interface) {
-  uint32_t modifiers = 0;
-  if (for_interface) {
-    modifiers |= MethodDecl::IS_VIRTUAL;
-    modifiers |= MethodDecl::IS_PURE_VIRTUAL;
-  } else {
-    modifiers |= MethodDecl::IS_OVERRIDE;
-  }
-
-  const string attribute = GetDeprecatedAttribute(method);
-  return unique_ptr<Declaration>{new MethodDecl{
-      kBinderStatusLiteral, method.GetName(),
-      BuildArgList(typenames, method, true /* for method decl */), modifiers, attribute}};
+void GenerateMethodDecl(CodeWriter& out, const AidlTypenames& types, const AidlMethod& method,
+                        const string& clazz) {
+  string clazz_prefix = clazz.empty() ? "" : clazz + "::";
+  out << "::android::binder::Status " << clazz_prefix << method.GetName() << "("
+      << GenerateArgList(types, method, /*for_declartion=*/true, /*type_name_only=*/false) << ")";
 }
 
-unique_ptr<Declaration> BuildMetaMethodDecl(const AidlMethod& method, const AidlTypenames&,
-                                            const Options& options, bool for_interface) {
-  AIDL_FATAL_IF(method.IsUserDefined(), method);
-  if (method.GetName() == kGetInterfaceVersion && options.Version()) {
-    std::ostringstream code;
-    if (for_interface) {
-      code << "virtual ";
-    }
-    code << "int32_t " << kGetInterfaceVersion << "()";
-    if (for_interface) {
-      code << " = 0;\n";
-    } else {
-      code << " override;\n";
-    }
-    return unique_ptr<Declaration>(new LiteralDecl(code.str()));
-  }
-  if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
-    std::ostringstream code;
-    if (for_interface) {
-      code << "virtual ";
-    }
-    code << "std::string " << kGetInterfaceHash << "()";
-    if (for_interface) {
-      code << " = 0;\n";
-    } else {
-      code << " override;\n";
-    }
-    return unique_ptr<Declaration>(new LiteralDecl(code.str()));
-  }
-  return nullptr;
-}
-
-std::vector<unique_ptr<Declaration>> NestInNamespaces(vector<unique_ptr<Declaration>> decls,
-                                                      const vector<string>& package) {
-  auto it = package.crbegin();  // Iterate over the namespaces inner to outer
-  for (; it != package.crend(); ++it) {
-    vector<unique_ptr<Declaration>> inner;
-    inner.emplace_back(unique_ptr<Declaration>{new CppNamespace{*it, std::move(decls)}});
-
-    decls = std::move(inner);
-  }
-  return decls;
-}
-
-std::vector<unique_ptr<Declaration>> NestInNamespaces(unique_ptr<Declaration> decl,
-                                                      const vector<string>& package) {
-  vector<unique_ptr<Declaration>> decls;
-  decls.push_back(std::move(decl));
-  return NestInNamespaces(std::move(decls), package);
-}
-
-unique_ptr<Declaration> DefineClientTransaction(const AidlTypenames& typenames,
-                                                const AidlInterface& interface,
-                                                const AidlMethod& method, const Options& options) {
+void GenerateClientTransaction(CodeWriter& out, const AidlTypenames& typenames,
+                               const AidlInterface& interface, const AidlMethod& method,
+                               const Options& options) {
   const string i_name = ClassName(interface, ClassNames::INTERFACE);
-  const string bp_name = ClassName(interface, ClassNames::CLIENT);
-  unique_ptr<MethodImpl> ret{
-      new MethodImpl{kBinderStatusLiteral,
-                     bp_name,
-                     method.GetName(),
-                     {},
-                     ArgList{BuildArgList(typenames, method, true /* for method decl */)}}};
-  StatementBlock* b = ret->GetStatementBlock();
+  const string bp_name = GetQualifiedName(interface, ClassNames::CLIENT);
+  const string bn_name = GetQualifiedName(interface, ClassNames::SERVER);
+
+  GenerateMethodDecl(out, typenames, method, bp_name);
+  out << " {\n";
+  out.Indent();
 
   // Declare parcels to hold our query and the response.
-  b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kDataVarName));
+  out.Write("%s %s;\n", kAndroidParcelLiteral, kDataVarName);
   if (interface.IsSensitiveData()) {
-    b->AddLiteral(StringPrintf("%s.markSensitive()", kDataVarName));
+    out.Write("%s.markSensitive();\n", kDataVarName);
   }
-  b->AddLiteral(StringPrintf("%s.markForBinder(remoteStrong())", kDataVarName));
+  out.Write("%s.markForBinder(remoteStrong());\n", kDataVarName);
 
   // Even if we're oneway, the transact method still takes a parcel.
-  b->AddLiteral(StringPrintf("%s %s", kAndroidParcelLiteral, kReplyVarName));
+  out.Write("%s %s;\n", kAndroidParcelLiteral, kReplyVarName);
 
   // Declare the status_t variable we need for error handling.
-  b->AddLiteral(StringPrintf("%s %s = %s", kAndroidStatusLiteral,
-                             kAndroidStatusVarName,
-                             kAndroidStatusOk));
+  out.Write("%s %s = %s;\n", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk);
   // We unconditionally return a Status object.
-  b->AddLiteral(StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName));
+  out.Write("%s %s;\n", kBinderStatusLiteral, kStatusVarName);
 
   if (options.GenTraces()) {
-    b->AddLiteral(
-        StringPrintf("::android::ScopedTrace %s(ATRACE_TAG_AIDL, \"AIDL::cpp::%s::%s::cppClient\")",
-                     kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
+    out.Write("::android::ScopedTrace %s(ATRACE_TAG_AIDL, \"AIDL::cpp::%s::%s::cppClient\");\n",
+              kTraceVarName, interface.GetName().c_str(), method.GetName().c_str());
   }
 
   if (options.GenLog()) {
-    b->AddLiteral(GenLogBeforeExecute(bp_name, method, false /* isServer */, false /* isNdk */),
-                  false /* no semicolon */);
+    out << GenLogBeforeExecute(bp_name, method, false /* isServer */, false /* isNdk */);
   }
 
   // Add the name of the interface we're hoping to call.
-  b->AddStatement(new Assignment(
-      kAndroidStatusVarName,
-      new MethodCall(StringPrintf("%s.writeInterfaceToken",
-                                  kDataVarName),
-                     "getInterfaceDescriptor()")));
-  b->AddStatement(GotoErrorOnBadStatus());
+  out.Write("%s = %s.writeInterfaceToken(getInterfaceDescriptor());\n", kAndroidStatusVarName,
+            kDataVarName);
+  GenerateGotoErrorOnBadStatus(out);
 
-  for (const auto& a: method.GetArguments()) {
+  for (const auto& a : method.GetArguments()) {
     const string var_name = ((a->IsOut()) ? "*" : "") + a->GetName();
 
     if (a->IsIn()) {
       // Serialization looks roughly like:
       //     _aidl_ret_status = _aidl_data.WriteInt32(in_param_name);
       //     if (_aidl_ret_status != ::android::OK) { goto error; }
-      const string& method = ParcelWriteMethodOf(a->GetType(), typenames);
-      b->AddStatement(
-          new Assignment(kAndroidStatusVarName,
-                         new MethodCall(StringPrintf("%s.%s", kDataVarName, method.c_str()),
-                                        ParcelWriteCastOf(a->GetType(), typenames, var_name))));
-      b->AddStatement(GotoErrorOnBadStatus());
-    } else if (a->IsOut() && a->GetType().IsArray()) {
+      out.Write("%s = %s.%s(%s);\n", kAndroidStatusVarName, kDataVarName,
+                ParcelWriteMethodOf(a->GetType(), typenames).c_str(),
+                ParcelWriteCastOf(a->GetType(), typenames, var_name).c_str());
+      GenerateGotoErrorOnBadStatus(out);
+    } else if (a->IsOut() && a->GetType().IsDynamicArray()) {
       // Special case, the length of the out array is written into the parcel.
       //     _aidl_ret_status = _aidl_data.writeVectorSize(&out_param_name);
       //     if (_aidl_ret_status != ::android::OK) { goto error; }
-      b->AddStatement(new Assignment(
-          kAndroidStatusVarName,
-          new MethodCall(StringPrintf("%s.writeVectorSize", kDataVarName), var_name)));
-      b->AddStatement(GotoErrorOnBadStatus());
+      out.Write("%s = %s.writeVectorSize(%s);\n", kAndroidStatusVarName, kDataVarName,
+                var_name.c_str());
+      GenerateGotoErrorOnBadStatus(out);
     }
   }
 
   // Invoke the transaction on the remote binder and confirm status.
-  string transaction_code = GetTransactionIdFor(interface, method);
-
-  vector<string> args = {transaction_code, kDataVarName,
-                         StringPrintf("&%s", kReplyVarName)};
-
   std::vector<std::string> flags;
   if (method.IsOneway()) flags.push_back("::android::IBinder::FLAG_ONEWAY");
   if (interface.IsSensitiveData()) flags.push_back("::android::IBinder::FLAG_CLEAR_BUF");
 
-  args.push_back(flags.empty() ? "0" : Join(flags, " | "));
-
-  b->AddStatement(new Assignment(
-      kAndroidStatusVarName,
-      new MethodCall("remote()->transact",
-                     ArgList(args))));
+  out.Write("%s = remote()->transact(%s, %s, &%s, %s);\n", kAndroidStatusVarName,
+            GetTransactionIdFor(bn_name, method).c_str(), kDataVarName, kReplyVarName,
+            flags.empty() ? "0" : Join(flags, " | ").c_str());
 
   // If the method is not implemented in the remote side, try to call the
   // default implementation, if provided.
@@ -330,30 +246,24 @@
   if (method.GetType().GetName() != "void") {
     arg_names.emplace_back(kReturnVarName);
   }
-  b->AddLiteral(StringPrintf("if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && "
-                             "%s::getDefaultImpl())) {\n"
-                             "   return %s::getDefaultImpl()->%s(%s);\n"
-                             "}\n",
-                             i_name.c_str(), i_name.c_str(), method.GetName().c_str(),
-                             Join(arg_names, ", ").c_str()),
-                false /* no semicolon */);
-
-  b->AddStatement(GotoErrorOnBadStatus());
+  out.Write("if (UNLIKELY(%s == ::android::UNKNOWN_TRANSACTION && %s::getDefaultImpl())) {\n",
+            kAndroidStatusVarName, i_name.c_str());
+  out.Write("   return %s::getDefaultImpl()->%s(%s);\n", i_name.c_str(), method.GetName().c_str(),
+            Join(arg_names, ", ").c_str());
+  out.Write("}\n");
+  GenerateGotoErrorOnBadStatus(out);
 
   if (!method.IsOneway()) {
     // Strip off the exception header and fail if we see a remote exception.
     // _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply);
     // if (_aidl_ret_status != ::android::OK) { goto error; }
     // if (!_aidl_status.isOk()) { return _aidl_ret_status; }
-    b->AddStatement(new Assignment(
-        kAndroidStatusVarName,
-        StringPrintf("%s.readFromParcel(%s)", kStatusVarName, kReplyVarName)));
-    b->AddStatement(GotoErrorOnBadStatus());
-    IfStatement* exception_check = new IfStatement(
-        new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
-    b->AddStatement(exception_check);
-    exception_check->OnTrue()->AddLiteral(
-        StringPrintf("return %s", kStatusVarName));
+    out.Write("%s = %s.readFromParcel(%s);\n", kAndroidStatusVarName, kStatusVarName,
+              kReplyVarName);
+    GenerateGotoErrorOnBadStatus(out);
+    out.Write("if (!%s.isOk()) {\n", kStatusVarName);
+    out.Write("  return %s;\n", kStatusVarName);
+    out.Write("}\n");
   }
 
   // Type checking should guarantee that nothing below emits code until "return
@@ -361,25 +271,20 @@
 
   // If the method is expected to return something, read it first by convention.
   if (method.GetType().GetName() != "void") {
-    const string& method_call = ParcelReadMethodOf(method.GetType(), typenames);
-    b->AddStatement(new Assignment(
-        kAndroidStatusVarName,
-        new MethodCall(StringPrintf("%s.%s", kReplyVarName, method_call.c_str()),
-                       ParcelReadCastOf(method.GetType(), typenames, kReturnVarName))));
-    b->AddStatement(GotoErrorOnBadStatus());
+    out.Write("%s = %s.%s(%s);\n", kAndroidStatusVarName, kReplyVarName,
+              ParcelReadMethodOf(method.GetType(), typenames).c_str(),
+              ParcelReadCastOf(method.GetType(), typenames, kReturnVarName).c_str());
+    GenerateGotoErrorOnBadStatus(out);
   }
 
   for (const AidlArgument* a : method.GetOutArguments()) {
     // Deserialization looks roughly like:
     //     _aidl_ret_status = _aidl_reply.ReadInt32(out_param_name);
     //     if (_aidl_status != ::android::OK) { goto _aidl_error; }
-    string method = ParcelReadMethodOf(a->GetType(), typenames);
-
-    b->AddStatement(
-        new Assignment(kAndroidStatusVarName,
-                       new MethodCall(StringPrintf("%s.%s", kReplyVarName, method.c_str()),
-                                      ParcelReadCastOf(a->GetType(), typenames, a->GetName()))));
-    b->AddStatement(GotoErrorOnBadStatus());
+    out.Write("%s = %s.%s(%s);\n", kAndroidStatusVarName, kReplyVarName,
+              ParcelReadMethodOf(a->GetType(), typenames).c_str(),
+              ParcelReadCastOf(a->GetType(), typenames, a->GetName()).c_str());
+    GenerateGotoErrorOnBadStatus(out);
   }
 
   // If we've gotten to here, one of two things is true:
@@ -387,228 +292,181 @@
   //   2) We've only read status_t == OK and there was no exception in the
   //      response.
   // In both cases, we're free to set Status from the status_t and return.
-  b->AddLiteral(StringPrintf("%s:\n", kErrorLabel), false /* no semicolon */);
-  b->AddLiteral(
-      StringPrintf("%s.setFromStatusT(%s)", kStatusVarName,
-                   kAndroidStatusVarName));
+  out.Write("%s:\n", kErrorLabel);
+  out.Write("%s.setFromStatusT(%s);\n", kStatusVarName, kAndroidStatusVarName);
 
   if (options.GenLog()) {
-    b->AddLiteral(GenLogAfterExecute(bp_name, interface, method, kStatusVarName, kReturnVarName,
-                                     false /* isServer */, false /* isNdk */),
-                  false /* no semicolon */);
+    out << GenLogAfterExecute(bp_name, interface, method, kStatusVarName, kReturnVarName,
+                              false /* isServer */, false /* isNdk */);
   }
 
-  b->AddLiteral(StringPrintf("return %s", kStatusVarName));
-
-  return unique_ptr<Declaration>(ret.release());
+  out.Write("return %s;\n", kStatusVarName);
+  out.Dedent();
+  out << "}\n";
 }
 
-unique_ptr<Declaration> DefineClientMetaTransaction(const AidlTypenames& /* typenames */,
-                                                    const AidlInterface& interface,
-                                                    const AidlMethod& method,
-                                                    const Options& options) {
+void GenerateClientMetaTransaction(CodeWriter& out, const AidlInterface& interface,
+                                   const AidlMethod& method, const Options& options) {
   AIDL_FATAL_IF(method.IsUserDefined(), method);
+  const string bp_name = GetQualifiedName(interface, ClassNames::CLIENT);
+  const string bn_name = GetQualifiedName(interface, ClassNames::SERVER);
   if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
-    const string iface = ClassName(interface, ClassNames::INTERFACE);
-    const string proxy = ClassName(interface, ClassNames::CLIENT);
     // Note: race condition can happen here, but no locking is required
     // because 1) writing an interger is atomic and 2) this transaction
     // will always return the same value, i.e., competing threads will
     // give write the same value to cached_version_.
-    std::ostringstream code;
-    code << "int32_t " << proxy << "::" << kGetInterfaceVersion << "() {\n"
-         << "  if (cached_version_ == -1) {\n"
-         << "    ::android::Parcel data;\n"
-         << "    ::android::Parcel reply;\n"
-         << "    data.writeInterfaceToken(getInterfaceDescriptor());\n"
-         << "    ::android::status_t err = remote()->transact(" << GetTransactionIdFor(interface, method)
-         << ", data, &reply);\n"
-         << "    if (err == ::android::OK) {\n"
-         << "      ::android::binder::Status _aidl_status;\n"
-         << "      err = _aidl_status.readFromParcel(reply);\n"
-         << "      if (err == ::android::OK && _aidl_status.isOk()) {\n"
-         << "        cached_version_ = reply.readInt32();\n"
-         << "      }\n"
-         << "    }\n"
-         << "  }\n"
-         << "  return cached_version_;\n"
-         << "}\n";
-    return unique_ptr<Declaration>(new LiteralDecl(code.str()));
+    out << "int32_t " << bp_name << "::" << kGetInterfaceVersion << "() {\n"
+        << "  if (cached_version_ == -1) {\n"
+        << "    ::android::Parcel data;\n"
+        << "    ::android::Parcel reply;\n"
+        << "    data.writeInterfaceToken(getInterfaceDescriptor());\n"
+        << "    ::android::status_t err = remote()->transact("
+        << GetTransactionIdFor(bn_name, method) << ", data, &reply);\n"
+        << "    if (err == ::android::OK) {\n"
+        << "      ::android::binder::Status _aidl_status;\n"
+        << "      err = _aidl_status.readFromParcel(reply);\n"
+        << "      if (err == ::android::OK && _aidl_status.isOk()) {\n"
+        << "        cached_version_ = reply.readInt32();\n"
+        << "      }\n"
+        << "    }\n"
+        << "  }\n"
+        << "  return cached_version_;\n"
+        << "}\n";
+    out << "\n";
   }
   if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
-    const string iface = ClassName(interface, ClassNames::INTERFACE);
-    const string proxy = ClassName(interface, ClassNames::CLIENT);
-    std::ostringstream code;
-    code << "std::string " << proxy << "::" << kGetInterfaceHash << "() {\n"
-         << "  std::lock_guard<std::mutex> lockGuard(cached_hash_mutex_);\n"
-         << "  if (cached_hash_ == \"-1\") {\n"
-         << "    ::android::Parcel data;\n"
-         << "    ::android::Parcel reply;\n"
-         << "    data.writeInterfaceToken(getInterfaceDescriptor());\n"
-         << "    ::android::status_t err = remote()->transact(" << GetTransactionIdFor(interface, method)
-         << ", data, &reply);\n"
-         << "    if (err == ::android::OK) {\n"
-         << "      ::android::binder::Status _aidl_status;\n"
-         << "      err = _aidl_status.readFromParcel(reply);\n"
-         << "      if (err == ::android::OK && _aidl_status.isOk()) {\n"
-         << "        reply.readUtf8FromUtf16(&cached_hash_);\n"
-         << "      }\n"
-         << "    }\n"
-         << "  }\n"
-         << "  return cached_hash_;\n"
-         << "}\n";
-    return unique_ptr<Declaration>(new LiteralDecl(code.str()));
+    out << "std::string " << bp_name << "::" << kGetInterfaceHash << "() {\n"
+        << "  std::lock_guard<std::mutex> lockGuard(cached_hash_mutex_);\n"
+        << "  if (cached_hash_ == \"-1\") {\n"
+        << "    ::android::Parcel data;\n"
+        << "    ::android::Parcel reply;\n"
+        << "    data.writeInterfaceToken(getInterfaceDescriptor());\n"
+        << "    ::android::status_t err = remote()->transact("
+        << GetTransactionIdFor(bn_name, method) << ", data, &reply);\n"
+        << "    if (err == ::android::OK) {\n"
+        << "      ::android::binder::Status _aidl_status;\n"
+        << "      err = _aidl_status.readFromParcel(reply);\n"
+        << "      if (err == ::android::OK && _aidl_status.isOk()) {\n"
+        << "        reply.readUtf8FromUtf16(&cached_hash_);\n"
+        << "      }\n"
+        << "    }\n"
+        << "  }\n"
+        << "  return cached_hash_;\n"
+        << "}\n";
   }
-  return nullptr;
 }
 
 }  // namespace
 
-unique_ptr<Document> BuildClientSource(const AidlTypenames& typenames,
-                                       const AidlInterface& interface, const Options& options) {
+void GenerateClientSource(CodeWriter& out, const AidlInterface& interface,
+                          const AidlTypenames& typenames, const Options& options) {
   vector<string> include_list = {
       HeaderFile(interface, ClassNames::CLIENT, false),
-      HeaderFile(interface, ClassNames::SERVER, false), // for TRANSACTION_* consts
-      kParcelHeader,
-      kAndroidBaseMacrosHeader
-  };
+      HeaderFile(interface, ClassNames::SERVER, false),  // for TRANSACTION_* consts
+      kParcelHeader, kAndroidBaseMacrosHeader};
   if (options.GenLog()) {
     include_list.emplace_back("chrono");
     include_list.emplace_back("functional");
   }
-  vector<unique_ptr<Declaration>> file_decls;
+  for (const auto& path : include_list) {
+    out << "#include <" << path << ">\n";
+  }
+  out << "\n";
+
+  const string i_name = ClassName(interface, ClassNames::INTERFACE);
+  const string bp_name = ClassName(interface, ClassNames::CLIENT);
+  const string q_name = GetQualifiedName(interface, ClassNames::CLIENT);
+
+  EnterNamespace(out, interface);
+  out << "\n";
 
   // The constructor just passes the IBinder instance up to the super
   // class.
-  const string i_name = ClassName(interface, ClassNames::INTERFACE);
-  const string bp_name = ClassName(interface, ClassNames::CLIENT);
-  file_decls.push_back(unique_ptr<Declaration>{new ConstructorImpl{
-      bp_name,
-      ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s", kImplVarName)},
-      {"BpInterface<" + i_name + ">(" + kImplVarName + ")"}}});
+  out << q_name << "::" << bp_name << "(const ::android::sp<::android::IBinder>& _aidl_impl)\n";
+  out << "    : BpInterface<" + i_name + ">(_aidl_impl){\n";
+  out << "}\n";
+  out << "\n";
 
   if (options.GenLog()) {
-    string code;
-    CodeWriterPtr writer = CodeWriter::ForString(&code);
-    (*writer) << "std::function<void(const " + bp_name + "::TransactionLog&)> " << bp_name
-              << "::logFunc;\n";
-    writer->Close();
-    file_decls.push_back(unique_ptr<Declaration>(new LiteralDecl(code)));
+    out << "std::function<void(const " + q_name + "::TransactionLog&)> " << q_name
+        << "::logFunc;\n";
+    out << "\n";
   }
 
   // Clients define a method per transaction.
   for (const auto& method : interface.GetMethods()) {
-    unique_ptr<Declaration> m;
     if (method->IsUserDefined()) {
-      m = DefineClientTransaction(typenames, interface, *method, options);
+      GenerateClientTransaction(out, typenames, interface, *method, options);
     } else {
-      m = DefineClientMetaTransaction(typenames, interface, *method, options);
+      GenerateClientMetaTransaction(out, interface, *method, options);
     }
-    if (!m) { return nullptr; }
-    file_decls.push_back(std::move(m));
+    out << "\n";
   }
-  return unique_ptr<Document>{new CppSource{
-      include_list,
-      NestInNamespaces(std::move(file_decls), interface.GetSplitPackage())}};
+
+  LeaveNamespace(out, interface);
 }
 
 namespace {
 
-void BuildConstantDefinitions(const AidlDefinedType& type, const AidlTypenames& typenames,
-                              const std::vector<std::string>& type_params,
-                              const std::string& class_name,
-                              vector<unique_ptr<Declaration>>& decls) {
+void GenerateConstantDefinitions(CodeWriter& out, const AidlDefinedType& type,
+                                 const AidlTypenames& typenames, const string& template_decl,
+                                 const string& q_name) {
   for (const auto& constant : type.GetConstantDeclarations()) {
     const AidlConstantValue& value = constant->GetValue();
     if (value.GetType() != AidlConstantValue::Type::STRING) continue;
 
-    std::string cppType = CppNameOf(constant->GetType(), typenames);
-    unique_ptr<MethodImpl> getter(
-        new MethodImpl("const " + cppType + "&", class_name, constant->GetName(), type_params, {}));
-    getter->GetStatementBlock()->AddLiteral(
-        StringPrintf("static const %s value(%s)", cppType.c_str(),
-                     constant->ValueString(ConstantValueDecorator).c_str()));
-    getter->GetStatementBlock()->AddLiteral("return value");
-    decls.push_back(std::move(getter));
+    std::string cpp_type = CppNameOf(constant->GetType(), typenames);
+    out << template_decl;
+    out << "const " << cpp_type << "& " << q_name << "::" << constant->GetName() << "() {\n";
+    out << "  static const " << cpp_type << " value("
+        << constant->ValueString(ConstantValueDecorator) << ");\n";
+    out << "  return value;\n";
+    out << "}\n";
   }
 }
 
-void BuildConstantDeclarations(const AidlDefinedType& type, const AidlTypenames& typenames,
-                               unique_ptr<ClassDecl>& cls, set<string>& includes) {
-  std::vector<std::unique_ptr<Declaration>> string_constants;
-  unique_ptr<Enum> byte_constant_enum{new Enum{"", "int8_t", false}};
-  unique_ptr<Enum> int_constant_enum{new Enum{"", "int32_t", false}};
-  unique_ptr<Enum> long_constant_enum{new Enum{"", "int64_t", false}};
+void GenerateConstantDeclarations(CodeWriter& out, const AidlDefinedType& type,
+                                  const AidlTypenames& typenames) {
   for (const auto& constant : type.GetConstantDeclarations()) {
     const AidlTypeSpecifier& type = constant->GetType();
-    const AidlConstantValue& value = constant->GetValue();
-
-    const string attribute = GetDeprecatedAttribute(*constant);
+    const auto cpp_type = CppNameOf(type, typenames);
     if (type.Signature() == "String") {
-      std::string cppType = CppNameOf(constant->GetType(), typenames);
-      unique_ptr<Declaration> getter(new MethodDecl("const " + cppType + "&", constant->GetName(),
-                                                    {}, MethodDecl::IS_STATIC, attribute));
-      string_constants.push_back(std::move(getter));
-    } else if (type.Signature() == "byte") {
-      byte_constant_enum->AddValue(constant->GetName(),
-                                   constant->ValueString(ConstantValueDecorator), attribute);
-    } else if (type.Signature() == "int") {
-      int_constant_enum->AddValue(constant->GetName(),
-                                  constant->ValueString(ConstantValueDecorator), attribute);
-    } else if (type.Signature() == "long") {
-      long_constant_enum->AddValue(constant->GetName(),
-                                   constant->ValueString(ConstantValueDecorator), attribute);
+      out << "static const " << cpp_type << "& " << constant->GetName() << "()";
+      GenerateDeprecated(out, *constant);
+      out << ";\n";
     } else {
-      AIDL_FATAL(value) << "Unrecognized constant type: " << type.Signature();
-    }
-  }
-  if (byte_constant_enum->HasValues()) {
-    cls->AddPublic(std::move(byte_constant_enum));
-  }
-  if (int_constant_enum->HasValues()) {
-    cls->AddPublic(std::move(int_constant_enum));
-  }
-  if (long_constant_enum->HasValues()) {
-    cls->AddPublic(std::move(long_constant_enum));
-  }
-  if (!string_constants.empty()) {
-    includes.insert(kString16Header);
-
-    for (auto& string_constant : string_constants) {
-      cls->AddPublic(std::move(string_constant));
+      out << "enum : " << cpp_type << " { " << constant->GetName();
+      GenerateDeprecated(out, *constant);
+      out << " = " << constant->ValueString(ConstantValueDecorator) << " };\n";
     }
   }
 }
 
-bool HandleServerTransaction(const AidlTypenames& typenames, const AidlInterface& interface,
-                             const AidlMethod& method, const Options& options, StatementBlock* b) {
+void GenerateServerTransaction(CodeWriter& out, const AidlInterface& interface,
+                               const AidlMethod& method, const AidlTypenames& typenames,
+                               const Options& options) {
+  const string bn_name = GetQualifiedName(interface, ClassNames::SERVER);
+
   // Declare all the parameters now.  In the common case, we expect no errors
   // in serialization.
   for (const unique_ptr<AidlArgument>& a : method.GetArguments()) {
-    b->AddLiteral(StringPrintf("%s %s", CppNameOf(a->GetType(), typenames).c_str(),
-                               BuildVarName(*a).c_str()));
+    out.Write("%s %s;\n", CppNameOf(a->GetType(), typenames).c_str(), BuildVarName(*a).c_str());
   }
 
   // Declare a variable to hold the return value.
   if (method.GetType().GetName() != "void") {
-    string type = CppNameOf(method.GetType(), typenames);
-    b->AddLiteral(StringPrintf("%s %s", type.c_str(), kReturnVarName));
+    out.Write("%s %s;\n", CppNameOf(method.GetType(), typenames).c_str(), kReturnVarName);
   }
 
   // Check that the client is calling the correct interface.
-  IfStatement* interface_check = new IfStatement(
-      new MethodCall(StringPrintf("%s.checkInterface",
-                                  kDataVarName), "this"),
-      true /* invert the check */);
-  b->AddStatement(interface_check);
-  interface_check->OnTrue()->AddStatement(
-      new Assignment(kAndroidStatusVarName, "::android::BAD_TYPE"));
-  interface_check->OnTrue()->AddLiteral("break");
+  out.Write("if (!(%s.checkInterface(this))) {\n", kDataVarName);
+  out.Write("  %s = ::android::BAD_TYPE;\n", kAndroidStatusVarName);
+  out.Write("  break;\n");
+  out.Write("}\n");
 
   if (options.GenTraces()) {
-    b->AddLiteral(
-        StringPrintf("::android::ScopedTrace %s(ATRACE_TAG_AIDL, \"AIDL::cpp::%s::%s::cppServer\")",
-                     kTraceVarName, interface.GetName().c_str(), method.GetName().c_str()));
+    out.Write("::android::ScopedTrace %s(ATRACE_TAG_AIDL, \"AIDL::cpp::%s::%s::cppServer\");\n",
+              kTraceVarName, interface.GetName().c_str(), method.GetName().c_str());
   }
 
   // Deserialize each "in" parameter to the transaction.
@@ -618,111 +476,158 @@
     //     if (_aidl_ret_status != ::android::OK) { break; }
     const string& var_name = "&" + BuildVarName(*a);
     if (a->IsIn()) {
-      const string& readMethod = ParcelReadMethodOf(a->GetType(), typenames);
-      b->AddStatement(
-          new Assignment{kAndroidStatusVarName,
-                         new MethodCall{string(kDataVarName) + "." + readMethod,
-                                        ParcelReadCastOf(a->GetType(), typenames, var_name)}});
-      b->AddStatement(BreakOnStatusNotOk());
-    } else if (a->IsOut() && a->GetType().IsArray()) {
+      out.Write("%s = %s.%s(%s);\n", kAndroidStatusVarName, kDataVarName,
+                ParcelReadMethodOf(a->GetType(), typenames).c_str(),
+                ParcelReadCastOf(a->GetType(), typenames, var_name).c_str());
+      GenerateBreakOnStatusNotOk(out);
+    } else if (a->IsOut() && a->GetType().IsDynamicArray()) {
       // Special case, the length of the out array is written into the parcel.
       //     _aidl_ret_status = _aidl_data.resizeOutVector(&out_param_name);
       //     if (_aidl_ret_status != ::android::OK) { break; }
-      b->AddStatement(
-          new Assignment{kAndroidStatusVarName,
-                         new MethodCall{string(kDataVarName) + ".resizeOutVector", var_name}});
-      b->AddStatement(BreakOnStatusNotOk());
+      out.Write("%s = %s.resizeOutVector(%s);\n", kAndroidStatusVarName, kDataVarName,
+                var_name.c_str());
+      GenerateBreakOnStatusNotOk(out);
     }
   }
 
-  const string bn_name = ClassName(interface, ClassNames::SERVER);
   if (options.GenLog()) {
-    b->AddLiteral(GenLogBeforeExecute(bn_name, method, true /* isServer */, false /* isNdk */),
-                  false);
+    out << GenLogBeforeExecute(bn_name, method, true /* isServer */, false /* isNdk */);
   }
+
+  if (!method.GetArguments().empty() && options.GetMinSdkVersion() >= SDK_VERSION_Tiramisu) {
+    out << "if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {\n";
+    out << "  _aidl_ret_status = st.writeToParcel(_aidl_reply);\n";
+    out << "  break;\n";
+    out << "}\n";
+  }
+
   // Call the actual method.  This is implemented by the subclass.
-  vector<unique_ptr<AstNode>> status_args;
-  status_args.emplace_back(new MethodCall(
-      method.GetName(), BuildArgList(typenames, method, false /* not for method decl */)));
-  b->AddStatement(new Statement(new MethodCall(
-      StringPrintf("%s %s", kBinderStatusLiteral, kStatusVarName),
-      ArgList(std::move(status_args)))));
+  out.Write("%s %s(%s(%s));\n", kBinderStatusLiteral, kStatusVarName, method.GetName().c_str(),
+            GenerateArgList(typenames, method, /*for_declaration=*/false, /*type_name_only=*/false)
+                .c_str());
 
   if (options.GenLog()) {
-    b->AddLiteral(GenLogAfterExecute(bn_name, interface, method, kStatusVarName, kReturnVarName,
-                                     true /* isServer */, false /* isNdk */),
-                  false);
+    out << GenLogAfterExecute(bn_name, interface, method, kStatusVarName, kReturnVarName,
+                              true /* isServer */, false /* isNdk */);
   }
 
   // Write exceptions during transaction handling to parcel.
   if (!method.IsOneway()) {
-    b->AddStatement(new Assignment(
-        kAndroidStatusVarName,
-        StringPrintf("%s.writeToParcel(%s)", kStatusVarName, kReplyVarName)));
-    b->AddStatement(BreakOnStatusNotOk());
-    IfStatement* exception_check = new IfStatement(
-        new LiteralExpression(StringPrintf("!%s.isOk()", kStatusVarName)));
-    b->AddStatement(exception_check);
-    exception_check->OnTrue()->AddLiteral("break");
+    out.Write("%s = %s.writeToParcel(%s);\n", kAndroidStatusVarName, kStatusVarName, kReplyVarName);
+    GenerateBreakOnStatusNotOk(out);
+    out.Write("if (!%s.isOk()) {\n", kStatusVarName);
+    out.Write("  break;\n");
+    out.Write("}\n");
   }
 
   // If we have a return value, write it first.
   if (method.GetType().GetName() != "void") {
-    string writeMethod =
-        string(kReplyVarName) + "->" + ParcelWriteMethodOf(method.GetType(), typenames);
-    b->AddStatement(new Assignment(
-        kAndroidStatusVarName,
-        new MethodCall(writeMethod,
-                       ParcelWriteCastOf(method.GetType(), typenames, kReturnVarName))));
-    b->AddStatement(BreakOnStatusNotOk());
+    out.Write("%s = %s->%s(%s);\n", kAndroidStatusVarName, kReplyVarName,
+              ParcelWriteMethodOf(method.GetType(), typenames).c_str(),
+              ParcelWriteCastOf(method.GetType(), typenames, kReturnVarName).c_str());
+    GenerateBreakOnStatusNotOk(out);
   }
   // Write each out parameter to the reply parcel.
   for (const AidlArgument* a : method.GetOutArguments()) {
     // Serialization looks roughly like:
     //     _aidl_ret_status = data.WriteInt32(out_param_name);
     //     if (_aidl_ret_status != ::android::OK) { break; }
-    const string& writeMethod = ParcelWriteMethodOf(a->GetType(), typenames);
-    b->AddStatement(new Assignment(
-        kAndroidStatusVarName,
-        new MethodCall(string(kReplyVarName) + "->" + writeMethod,
-                       ParcelWriteCastOf(a->GetType(), typenames, BuildVarName(*a)))));
-    b->AddStatement(BreakOnStatusNotOk());
+    out.Write("%s = %s->%s(%s);\n", kAndroidStatusVarName, kReplyVarName,
+              ParcelWriteMethodOf(a->GetType(), typenames).c_str(),
+              ParcelWriteCastOf(a->GetType(), typenames, BuildVarName(*a)).c_str());
+    GenerateBreakOnStatusNotOk(out);
   }
-
-  return true;
 }
 
-bool HandleServerMetaTransaction(const AidlTypenames&, const AidlInterface& interface,
-                                 const AidlMethod& method, const Options& options,
-                                 StatementBlock* b) {
+void GenerateServerMetaTransaction(CodeWriter& out, const AidlInterface& interface,
+                                   const AidlMethod& method, const Options& options) {
   AIDL_FATAL_IF(method.IsUserDefined(), method);
 
+  string iface = ClassName(interface, ClassNames::INTERFACE);
   if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
-    std::ostringstream code;
-    code << "_aidl_data.checkInterface(this);\n"
-         << "_aidl_reply->writeNoException();\n"
-         << "_aidl_reply->writeInt32(" << ClassName(interface, ClassNames::INTERFACE)
-         << "::VERSION)";
-    b->AddLiteral(code.str());
-    return true;
+    out << "_aidl_data.checkInterface(this);\n"
+        << "_aidl_reply->writeNoException();\n"
+        << "_aidl_reply->writeInt32(" << iface << "::VERSION);\n";
   }
   if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
-    std::ostringstream code;
-    code << "_aidl_data.checkInterface(this);\n"
-         << "_aidl_reply->writeNoException();\n"
-         << "_aidl_reply->writeUtf8AsUtf16(" << ClassName(interface, ClassNames::INTERFACE)
-         << "::HASH)";
-    b->AddLiteral(code.str());
-    return true;
+    out << "_aidl_data.checkInterface(this);\n"
+        << "_aidl_reply->writeNoException();\n"
+        << "_aidl_reply->writeUtf8AsUtf16(" << iface << "::HASH);\n";
   }
-  return false;
 }
 
 }  // namespace
 
-unique_ptr<Document> BuildServerSource(const AidlTypenames& typenames,
-                                       const AidlInterface& interface, const Options& options) {
+void GenerateServerOnTransact(CodeWriter& out, const AidlInterface& interface,
+                              const AidlTypenames& typenames, const Options& options) {
   const string bn_name = ClassName(interface, ClassNames::SERVER);
+  const string q_name = GetQualifiedName(interface, ClassNames::SERVER);
+
+  bool deprecated = interface.IsDeprecated() ||
+                    std::any_of(interface.GetMethods().begin(), interface.GetMethods().end(),
+                                [](const auto& m) { return m->IsDeprecated(); });
+  if (deprecated) {
+    out << "#pragma clang diagnostic push\n";
+    out << "#pragma clang diagnostic ignored \"-Wdeprecated\"\n";
+    out << "\n";
+  }
+
+  out.Write("%s %s::onTransact(uint32_t %s, const %s& %s, %s* %s, uint32_t %s) {\n",
+            kAndroidStatusLiteral, q_name.c_str(), kCodeVarName, kAndroidParcelLiteral,
+            kDataVarName, kAndroidParcelLiteral, kReplyVarName, kFlagsVarName);
+  out.Indent();
+  // Declare the status_t variable
+  out.Write("%s %s = %s;\n", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk);
+
+  // Add the all important switch statement
+  out.Write("switch (%s) {\n", kCodeVarName);
+
+  // The switch statement has a case statement for each transaction code.
+  for (const auto& method : interface.GetMethods()) {
+    out.Write("case %s:\n", GetTransactionIdFor(bn_name, *method).c_str());
+    out << "{\n";
+    out.Indent();
+    if (method->IsUserDefined()) {
+      GenerateServerTransaction(out, interface, *method, typenames, options);
+    } else {
+      GenerateServerMetaTransaction(out, interface, *method, options);
+    }
+    out.Dedent();
+    out << "}\n";
+    out << "break;\n";
+  }
+
+  // The switch statement has a default case which defers to the super class.
+  // The superclass handles a few pre-defined transactions.
+  out << "default:\n";
+  out << "{\n";
+  out.Write("  %s = ::android::BBinder::onTransact(%s, %s, %s, %s);\n", kAndroidStatusVarName,
+            kCodeVarName, kDataVarName, kReplyVarName, kFlagsVarName);
+  out << "}\n";
+  out << "break;\n";
+  out << "}\n";  // switch
+
+  // If we saw a null reference, we can map that to an appropriate exception.
+  out.Write("if (%s == ::android::UNEXPECTED_NULL) {\n", kAndroidStatusVarName);
+  out.Write("  %s = %s::fromExceptionCode(%s::EX_NULL_POINTER).writeOverParcel(%s);\n",
+            kAndroidStatusVarName, kBinderStatusLiteral, kBinderStatusLiteral, kReplyVarName);
+  out.Write("}\n");
+
+  // Finally, the server's onTransact method just returns a status code.
+  out.Write("return %s;\n", kAndroidStatusVarName);
+
+  out.Dedent();
+  out << "}\n";
+  out << "\n";
+
+  if (deprecated) {
+    out << "#pragma clang diagnostic pop\n";
+    out << "\n";
+  }
+}
+
+void GenerateServerSource(CodeWriter& out, const AidlInterface& interface,
+                          const AidlTypenames& typenames, const Options& options) {
   vector<string> include_list{
       HeaderFile(interface, ClassNames::SERVER, false),
       kParcelHeader,
@@ -732,327 +637,298 @@
     include_list.emplace_back("chrono");
     include_list.emplace_back("functional");
   }
-
-  unique_ptr<ConstructorImpl> constructor{new ConstructorImpl{bn_name, ArgList{}, {}}};
-
-  if (interface.IsVintfStability()) {
-    constructor->GetStatementBlock()->AddLiteral("::android::internal::Stability::markVintf(this)");
-  } else {
-    constructor->GetStatementBlock()->AddLiteral(
-        "::android::internal::Stability::markCompilationUnit(this)");
+  for (const auto& include : include_list) {
+    out << "#include <" << include << ">\n";
   }
+  out << "\n";
 
-  unique_ptr<MethodImpl> on_transact{
-      new MethodImpl{kAndroidStatusLiteral,
-                     bn_name,
-                     "onTransact",
-                     {},
-                     ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
-                              StringPrintf("const %s& %s", kAndroidParcelLiteral, kDataVarName),
-                              StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
-                              StringPrintf("uint32_t %s", kFlagsVarName)}}}};
-
-  // Declare the status_t variable
-  on_transact->GetStatementBlock()->AddLiteral(
-      StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName,
-                   kAndroidStatusOk));
-
-  // Add the all important switch statement, but retain a pointer to it.
-  SwitchStatement* s = new SwitchStatement{kCodeVarName};
-  on_transact->GetStatementBlock()->AddStatement(s);
-
-  // The switch statement has a case statement for each transaction code.
-  for (const auto& method : interface.GetMethods()) {
-    StatementBlock* b = s->AddCase(GetTransactionIdFor(interface, *method));
-    if (!b) { return nullptr; }
-
-    bool success = false;
-    if (method->IsUserDefined()) {
-      success = HandleServerTransaction(typenames, interface, *method, options, b);
-    } else {
-      success = HandleServerMetaTransaction(typenames, interface, *method, options, b);
-    }
-    if (!success) {
-      return nullptr;
-    }
-  }
-
-  // The switch statement has a default case which defers to the super class.
-  // The superclass handles a few pre-defined transactions.
-  StatementBlock* b = s->AddCase("");
-  b->AddLiteral(StringPrintf(
-                "%s = ::android::BBinder::onTransact(%s, %s, "
-                "%s, %s)", kAndroidStatusVarName, kCodeVarName,
-                kDataVarName, kReplyVarName, kFlagsVarName));
-
-  // If we saw a null reference, we can map that to an appropriate exception.
-  IfStatement* null_check = new IfStatement(
-      new LiteralExpression(string(kAndroidStatusVarName) +
-                            " == ::android::UNEXPECTED_NULL"));
-  on_transact->GetStatementBlock()->AddStatement(null_check);
-  null_check->OnTrue()->AddStatement(new Assignment(
-      kAndroidStatusVarName,
-      StringPrintf("%s::fromExceptionCode(%s::EX_NULL_POINTER)"
-                   ".writeToParcel(%s)",
-                   kBinderStatusLiteral, kBinderStatusLiteral,
-                   kReplyVarName)));
-
-  // Finally, the server's onTransact method just returns a status code.
-  on_transact->GetStatementBlock()->AddLiteral(
-      StringPrintf("return %s", kAndroidStatusVarName));
-  vector<unique_ptr<Declaration>> decls;
-  decls.push_back(std::move(constructor));
-
-  bool deprecated = interface.IsDeprecated() ||
-                    std::any_of(interface.GetMethods().begin(), interface.GetMethods().end(),
-                                [](const auto& m) { return m->IsDeprecated(); });
-  if (deprecated) {
-    decls.emplace_back(
-        new LiteralDecl("#pragma clang diagnostic push\n"
-                        "#pragma clang diagnostic ignored \"-Wdeprecated\"\n"));
-  }
-  decls.push_back(std::move(on_transact));
-  if (deprecated) {
-    decls.emplace_back(new LiteralDecl("#pragma clang diagnostic pop\n"));
-  }
-
-  if (options.Version() > 0) {
-    std::ostringstream code;
-    code << "int32_t " << bn_name << "::" << kGetInterfaceVersion << "() {\n"
-         << "  return " << ClassName(interface, ClassNames::INTERFACE) << "::VERSION;\n"
-         << "}\n";
-    decls.emplace_back(new LiteralDecl(code.str()));
-  }
-  if (!options.Hash().empty()) {
-    std::ostringstream code;
-    code << "std::string " << bn_name << "::" << kGetInterfaceHash << "() {\n"
-         << "  return " << ClassName(interface, ClassNames::INTERFACE) << "::HASH;\n"
-         << "}\n";
-    decls.emplace_back(new LiteralDecl(code.str()));
-  }
-
-  if (options.GenLog()) {
-    string code;
-    CodeWriterPtr writer = CodeWriter::ForString(&code);
-    (*writer) << "std::function<void(const " + bn_name + "::TransactionLog&)> " << bn_name
-              << "::logFunc;\n";
-    writer->Close();
-    decls.push_back(unique_ptr<Declaration>(new LiteralDecl(code)));
-  }
-  return unique_ptr<Document>{
-      new CppSource{include_list, NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
-}
-
-unique_ptr<Document> BuildInterfaceSource(const AidlTypenames& typenames,
-                                          const AidlInterface& interface,
-                                          [[maybe_unused]] const Options& options) {
-  vector<string> include_list{
-      HeaderFile(interface, ClassNames::RAW, false),
-      HeaderFile(interface, ClassNames::CLIENT, false),
-  };
-
-  vector<unique_ptr<Declaration>> decls;
-
-  unique_ptr<MacroDecl> meta_if{
-      new MacroDecl{"DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE",
-                    ArgList{vector<string>{ClassName(interface, ClassNames::BASE),
-                                           '"' + interface.GetDescriptor() + '"'}}}};
-  decls.push_back(std::move(meta_if));
-
-  BuildConstantDefinitions(interface, typenames, {}, ClassName(interface, ClassNames::INTERFACE),
-                           decls);
-
-  return unique_ptr<Document>{new CppSource{
-      include_list,
-      NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
-}
-
-unique_ptr<Document> BuildClientHeader(const AidlTypenames& typenames,
-                                       const AidlInterface& interface, const Options& options) {
-  const string i_name = ClassName(interface, ClassNames::INTERFACE);
-  const string bp_name = ClassName(interface, ClassNames::CLIENT);
-
-  vector<string> includes = {kIBinderHeader, kIInterfaceHeader, "utils/Errors.h",
-                             HeaderFile(interface, ClassNames::RAW, false)};
-
-  unique_ptr<ConstructorDecl> constructor{new ConstructorDecl{
-      bp_name,
-      ArgList{StringPrintf("const ::android::sp<::android::IBinder>& %s",
-                           kImplVarName)},
-      ConstructorDecl::IS_EXPLICIT
-  }};
-  unique_ptr<ConstructorDecl> destructor{new ConstructorDecl{
-      "~" + bp_name,
-      ArgList{},
-      ConstructorDecl::IS_VIRTUAL | ConstructorDecl::IS_DEFAULT}};
-
-  vector<unique_ptr<Declaration>> publics;
-  vector<unique_ptr<Declaration>> privates;
-
-  publics.push_back(std::move(constructor));
-  publics.push_back(std::move(destructor));
-
-  for (const auto& method: interface.GetMethods()) {
-    if (method->IsUserDefined()) {
-      publics.push_back(BuildMethodDecl(*method, typenames, false));
-    } else {
-      publics.push_back(BuildMetaMethodDecl(*method, typenames, options, false));
-    }
-  }
-
-  if (options.GenLog()) {
-    includes.emplace_back("functional");  // for std::function
-    includes.emplace_back("android/binder_to_string.h");
-
-    publics.emplace_back(new LiteralDecl{kTransactionLogStruct});
-    publics.emplace_back(
-        new LiteralDecl{"static std::function<void(const TransactionLog&)> logFunc;\n"});
-  }
-
-  if (options.Version() > 0) {
-    privates.emplace_back(new LiteralDecl("int32_t cached_version_ = -1;\n"));
-  }
-  if (!options.Hash().empty()) {
-    privates.emplace_back(new LiteralDecl("std::string cached_hash_ = \"-1\";\n"));
-    privates.emplace_back(new LiteralDecl("std::mutex cached_hash_mutex_;\n"));
-  }
-
-  const string attribute = GetDeprecatedAttribute(interface);
-  unique_ptr<ClassDecl> bp_class{new ClassDecl{
-      bp_name,
-      "::android::BpInterface<" + i_name + ">",
-      {},
-      std::move(publics),
-      std::move(privates),
-      attribute,
-  }};
-
-  return unique_ptr<Document>{
-      new CppHeader{includes, NestInNamespaces(std::move(bp_class), interface.GetSplitPackage())}};
-}
-
-unique_ptr<Document> BuildServerHeader(const AidlTypenames& /* typenames */,
-                                       const AidlInterface& interface, const Options& options) {
   const string i_name = ClassName(interface, ClassNames::INTERFACE);
   const string bn_name = ClassName(interface, ClassNames::SERVER);
+  const string q_name = GetQualifiedName(interface, ClassNames::SERVER);
 
-  unique_ptr<ConstructorDecl> constructor{
-      new ConstructorDecl{bn_name, ArgList{}, ConstructorDecl::IS_EXPLICIT}};
+  EnterNamespace(out, interface);
+  out << "\n";
 
-  unique_ptr<Declaration> on_transact{new MethodDecl{
-      kAndroidStatusLiteral, "onTransact",
-      ArgList{{StringPrintf("uint32_t %s", kCodeVarName),
-               StringPrintf("const %s& %s", kAndroidParcelLiteral,
-                            kDataVarName),
-               StringPrintf("%s* %s", kAndroidParcelLiteral, kReplyVarName),
-               StringPrintf("uint32_t %s", kFlagsVarName)}},
-      MethodDecl::IS_OVERRIDE
-  }};
-  vector<string> includes = {"binder/IInterface.h", HeaderFile(interface, ClassNames::RAW, false)};
-
-  vector<unique_ptr<Declaration>> publics;
-  vector<unique_ptr<Declaration>> privates;
-
-  for (const auto& method : interface.GetMethods()) {
-    std::ostringstream code;
-    code << "static constexpr uint32_t TRANSACTION_" << method->GetName() << " = "
-         << "::android::IBinder::FIRST_CALL_TRANSACTION + " << method->GetId() << ";\n";
-    publics.push_back(std::make_unique<LiteralDecl>(code.str()));
+  // constructor
+  out.Write("%s::%s()\n", q_name.c_str(), bn_name.c_str());
+  out << "{\n";
+  out.Indent();
+  if (interface.IsVintfStability()) {
+    out << "::android::internal::Stability::markVintf(this);\n";
+  } else {
+    out << "::android::internal::Stability::markCompilationUnit(this);\n";
   }
+  out.Dedent();
+  out << "}\n";
+  out << "\n";
 
-  publics.push_back(std::move(constructor));
-  publics.push_back(std::move(on_transact));
+  GenerateServerOnTransact(out, interface, typenames, options);
 
   if (options.Version() > 0) {
-    std::ostringstream code;
-    code << "int32_t " << kGetInterfaceVersion << "() final;\n";
-    publics.emplace_back(new LiteralDecl(code.str()));
+    out << "int32_t " << q_name << "::" << kGetInterfaceVersion << "() {\n"
+        << "  return " << i_name << "::VERSION;\n"
+        << "}\n";
   }
   if (!options.Hash().empty()) {
-    std::ostringstream code;
-    code << "std::string " << kGetInterfaceHash << "();\n";
-    publics.emplace_back(new LiteralDecl(code.str()));
+    out << "std::string " << q_name << "::" << kGetInterfaceHash << "() {\n"
+        << "  return " << i_name << "::HASH;\n"
+        << "}\n";
+  }
+  if (options.GenLog()) {
+    out << "std::function<void(const " + q_name + "::TransactionLog&)> " << q_name
+        << "::logFunc;\n";
+  }
+
+  LeaveNamespace(out, interface);
+}
+
+void GenerateInterfaceSource(CodeWriter& out, const AidlInterface& interface,
+                             const AidlTypenames& typenames, const Options&) {
+  out << "#include <" << HeaderFile(interface, ClassNames::RAW, false) << ">\n";
+  out << "#include <" << HeaderFile(interface, ClassNames::CLIENT, false) << ">\n";
+
+  EnterNamespace(out, interface);
+
+  if (auto parent = interface.GetParentType(); parent) {
+    out << fmt::format("DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE({}, {}, \"{}\")\n",
+                       GetQualifiedName(*parent), ClassName(interface, ClassNames::BASE),
+                       interface.GetDescriptor());
+  } else {
+    out << fmt::format("DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE({}, \"{}\")\n",
+                       ClassName(interface, ClassNames::BASE), interface.GetDescriptor());
+  }
+
+  GenerateConstantDefinitions(out, interface, typenames, /*template_decl=*/"",
+                              ClassName(interface, ClassNames::INTERFACE));
+
+  LeaveNamespace(out, interface);
+}
+
+void GenerateClientClassDecl(CodeWriter& out, const AidlInterface& interface,
+                             const AidlTypenames& typenames, const Options& options) {
+  const string bp_name = ClassName(interface, ClassNames::CLIENT);
+  const string iface = ClassName(interface, ClassNames::INTERFACE);
+
+  out << "class";
+  GenerateDeprecated(out, interface);
+  out << " " << bp_name << " : public ::android::BpInterface<" << iface << "> {\n";
+  out << "public:\n";
+  out.Indent();
+  out << "explicit " << bp_name << "(const ::android::sp<::android::IBinder>& " << kImplVarName
+      << ");\n";
+  out << "virtual ~" << bp_name << "() = default;\n";
+
+  for (const auto& method : interface.GetMethods()) {
+    if (method->IsUserDefined()) {
+      GenerateMethodDecl(out, typenames, *method, /*clazz=*/"");
+      out << " override";
+      GenerateDeprecated(out, *method);
+      out << ";\n";
+    } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
+      out << "int32_t " << method->GetName() << "() override;\n";
+    } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+      out << "std::string " << method->GetName() << "() override;\n";
+    }
   }
 
   if (options.GenLog()) {
-    includes.emplace_back("functional");  // for std::function
-    includes.emplace_back("android/binder_to_string.h");
-
-    publics.emplace_back(new LiteralDecl{kTransactionLogStruct});
-    publics.emplace_back(
-        new LiteralDecl{"static std::function<void(const TransactionLog&)> logFunc;\n"});
+    out << kTransactionLogStruct;
+    out << "static std::function<void(const TransactionLog&)> logFunc;\n";
   }
-  const string attribute = GetDeprecatedAttribute(interface);
-  unique_ptr<ClassDecl> bn_class{new ClassDecl{
-      bn_name,
-      "::android::BnInterface<" + i_name + ">",
-      {},
-      std::move(publics),
-      std::move(privates),
-      attribute,
-  }};
+  out.Dedent();
 
-  return unique_ptr<Document>{
-      new CppHeader{includes, NestInNamespaces(std::move(bn_class), interface.GetSplitPackage())}};
+  if (options.Version() > 0 || !options.Hash().empty()) {
+    out << "private:\n";
+    out.Indent();
+    if (options.Version() > 0) {
+      out << "int32_t cached_version_ = -1;\n";
+    }
+    if (!options.Hash().empty()) {
+      out << "std::string cached_hash_ = \"-1\";\n";
+      out << "std::mutex cached_hash_mutex_;\n";
+    }
+    out.Dedent();
+  }
+
+  out << "};  // class " << bp_name << "\n";
 }
 
-unique_ptr<Document> BuildInterfaceHeader(const AidlTypenames& typenames,
-                                          const AidlInterface& interface, const Options& options) {
-  set<string> includes = {kIBinderHeader, kIInterfaceHeader, kStatusHeader, kStrongPointerHeader};
-
-  for (const auto& method : interface.GetMethods()) {
-    for (const auto& argument : method->GetArguments()) {
-      AddHeaders(argument->GetType(), typenames, &includes);
-    }
-
-    AddHeaders(method->GetType(), typenames, &includes);
+void GenerateClientHeader(CodeWriter& out, const AidlInterface& interface,
+                          const AidlTypenames& typenames, const Options& options) {
+  out << "#pragma once\n\n";
+  out << "#include <" << kIBinderHeader << ">\n";
+  out << "#include <" << kIInterfaceHeader << ">\n";
+  out << "#include <utils/Errors.h>\n";
+  out << "#include <" << HeaderFile(interface, ClassNames::RAW, false) << ">\n";
+  if (options.GenLog()) {
+    out << "#include <functional>\n";  // for std::function
+    out << "#include <android/binder_to_string.h>\n";
   }
+  out << "\n";
+  EnterNamespace(out, interface);
+  GenerateClientClassDecl(out, interface, typenames, options);
+  LeaveNamespace(out, interface);
+}
 
-  const string i_name = ClassName(interface, ClassNames::INTERFACE);
-  const string attribute = GetDeprecatedAttribute(interface);
-  unique_ptr<ClassDecl> if_class{new ClassDecl{i_name, "::android::IInterface", {}, attribute}};
-  if_class->AddPublic(unique_ptr<Declaration>{new MacroDecl{
-      "DECLARE_META_INTERFACE",
-      ArgList{vector<string>{ClassName(interface, ClassNames::BASE)}}}});
+void GenerateServerClassDecl(CodeWriter& out, const AidlInterface& interface,
+                             const AidlTypenames& typenames, const Options& options) {
+  const string bn_name = ClassName(interface, ClassNames::SERVER);
+  const string iface = ClassName(interface, ClassNames::INTERFACE);
 
+  out << "class";
+  GenerateDeprecated(out, interface);
+  out << " " << bn_name << " : public "
+      << "::android::BnInterface<" << iface << "> {\n";
+  out << "public:\n";
+  out.Indent();
+  for (const auto& method : interface.GetMethods()) {
+    out << "static constexpr uint32_t TRANSACTION_" << method->GetName() << " = "
+        << "::android::IBinder::FIRST_CALL_TRANSACTION + " << std::to_string(method->GetId())
+        << ";\n";
+  }
+  out << "explicit " << bn_name << "();\n";
+  out << fmt::format("{} onTransact(uint32_t {}, const {}& {}, {}* {}, uint32_t {}) override;\n",
+                     kAndroidStatusLiteral, kCodeVarName, kAndroidParcelLiteral, kDataVarName,
+                     kAndroidParcelLiteral, kReplyVarName, kFlagsVarName);
   if (options.Version() > 0) {
-    std::ostringstream code;
-    code << "const int32_t VERSION = " << options.Version() << ";\n";
-
-    if_class->AddPublic(unique_ptr<Declaration>(new LiteralDecl(code.str())));
+    out << "int32_t " << kGetInterfaceVersion << "();\n";
   }
   if (!options.Hash().empty()) {
-    std::ostringstream code;
-    code << "const std::string HASH = \"" << options.Hash() << "\";\n";
-
-    if_class->AddPublic(unique_ptr<Declaration>(new LiteralDecl(code.str())));
+    out << "std::string " << kGetInterfaceHash << "();\n";
   }
-
-  BuildConstantDeclarations(interface, typenames, if_class, includes);
-
-  if (options.GenTraces()) {
-    includes.insert(kTraceHeader);
+  if (options.GenLog()) {
+    out << kTransactionLogStruct;
+    out << "static std::function<void(const TransactionLog&)> logFunc;\n";
   }
+  out.Dedent();
+  out << "};  // class " << bn_name << "\n\n";
 
-  if (!interface.GetMethods().empty()) {
-    for (const auto& method : interface.GetMethods()) {
-      if (method->IsUserDefined()) {
-        // Each method gets an enum entry and pure virtual declaration.
-        if_class->AddPublic(BuildMethodDecl(*method, typenames, true));
-      } else {
-        if_class->AddPublic(BuildMetaMethodDecl(*method, typenames, options, true));
+  std::string d_name = ClassName(interface, ClassNames::DELEGATOR_IMPL);
+  out << "class";
+  GenerateDeprecated(out, interface);
+  out << " " << d_name << " : public " << bn_name << " {\n";
+  out << "public:\n";
+  out.Indent();
+  out << "explicit " << d_name << "(" << StringPrintf("::android::sp<%s> &impl", iface.c_str())
+      << ") " << StringPrintf(": %s(impl)", kDelegateImplVarName) << " {}\n\n";
+
+  for (const auto& method : interface.GetMethods()) {
+    if (method->IsUserDefined()) {
+      GenerateMethodDecl(out, typenames, *method, /*clazz=*/"");
+      out << " override";
+      GenerateDeprecated(out, *method);
+
+      std::vector<std::string> args;
+      for (const auto& arg : method->GetArguments()) {
+        if (IsNonCopyableType(arg->GetType(), typenames)) {
+          args.push_back(StringPrintf("std::move(%s)", arg->GetName().c_str()));
+        } else {
+          args.push_back(arg->GetName());
+        }
       }
+      if (method->GetType().GetName() != "void") {
+        args.push_back(kReturnVarName);
+      }
+      out << " {\n"
+          << "  return " << kDelegateImplVarName << "->" << method->GetName() << "("
+          << base::Join(args, ", ") << ");\n";
+      out << "}\n";
+    } else if (method->GetName() == kGetInterfaceVersion && options.Version()) {
+      out << "int32_t " << kGetInterfaceVersion << "()"
+          << " override {\n";
+      out.Indent();
+      out << "int32_t _delegator_ver = " << bn_name << "::" << kGetInterfaceVersion << "();\n";
+      out << "int32_t _impl_ver = " << kDelegateImplVarName << "->" << kGetInterfaceVersion
+          << "();\n";
+      out << "return _delegator_ver < _impl_ver ? _delegator_ver : _impl_ver;\n";
+      out.Dedent();
+      out << "}\n";
+    } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+      out << "std::string " << kGetInterfaceHash << "()"
+          << " override {\n";
+      out << "  return " << kDelegateImplVarName << "->" << kGetInterfaceHash << "();\n";
+      out << "}\n";
     }
   }
+  out.Dedent();
+  out << "private:\n";
+  out.Indent();
+  out << "::android::sp<" << iface << "> " << kDelegateImplVarName << ";\n";
+  out.Dedent();
+  out << "};  // class " << d_name << "\n";
+}
+
+void GenerateServerHeader(CodeWriter& out, const AidlInterface& interface,
+                          const AidlTypenames& typenames, const Options& options) {
+  out << "#pragma once\n\n";
+  out << "#include <binder/IInterface.h>\n";
+  out << "#include <" << HeaderFile(interface, ClassNames::RAW, false) << ">\n";
+  if (options.GenLog()) {
+    out << "#include <functional>\n";  // for std::function
+    out << "#include <android/binder_to_string.h>\n";
+  }
+  out << "\n";
+  EnterNamespace(out, interface);
+  GenerateServerClassDecl(out, interface, typenames, options);
+  LeaveNamespace(out, interface);
+}
+
+void GenerateClassDecl(CodeWriter& out, const AidlDefinedType& defined_type,
+                       const AidlTypenames& typenames, const Options& options);
+
+void GenerateNestedTypeDecls(CodeWriter& out, const AidlDefinedType& type,
+                             const AidlTypenames& typenames, const Options& options) {
+  auto visit = [&](const auto& nested) { GenerateClassDecl(out, nested, typenames, options); };
+  AIDL_FATAL_IF(!TopologicalVisit(type.GetNestedTypes(), visit), type) << "Cycle detected.";
+}
+
+void GenerateInterfaceClassDecl(CodeWriter& out, const AidlInterface& interface,
+                                const AidlTypenames& typenames, const Options& options) {
+  const string i_name = ClassName(interface, ClassNames::INTERFACE);
+
+  out << "class";
+  GenerateDeprecated(out, interface);
+  out << " " << i_name << " : public ::android::IInterface {\n";
+  out << "public:\n";
+  out.Indent();
+  out << "DECLARE_META_INTERFACE(" << ClassName(interface, ClassNames::BASE) << ")\n";
+  if (options.Version() > 0) {
+    out << "const int32_t VERSION = " << std::to_string(options.Version()) << ";\n";
+  }
+  if (!options.Hash().empty()) {
+    out << "const std::string HASH = \"" << options.Hash() << "\";\n";
+  }
+  GenerateNestedTypeDecls(out, interface, typenames, options);
+  GenerateConstantDeclarations(out, interface, typenames);
+  for (const auto& method : interface.GetMethods()) {
+    if (method->IsUserDefined()) {
+      out << "virtual ";
+      GenerateMethodDecl(out, typenames, *method, /*clazz=*/"");
+      GenerateDeprecated(out, *method);
+      out << " = 0;\n";
+    } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
+      out << "virtual int32_t " << method->GetName() << "() = 0;\n";
+    } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+      out << "virtual std::string " << method->GetName() << "() = 0;\n";
+    }
+  }
+  out.Dedent();
+  out << "};  // class " << i_name << "\n";
+  out << "\n";
 
   // Implement the default impl class.
-  vector<unique_ptr<Declaration>> method_decls;
+  const string default_impl = ClassName(interface, ClassNames::DEFAULT_IMPL);
+  out << "class";
+  GenerateDeprecated(out, interface);
+  out << " " << default_impl << " : public " << i_name << " {\n";
+  out << "public:\n";
+  out.Indent();
   // onAsBinder returns nullptr as this interface is not associated with a
   // real binder.
-  method_decls.emplace_back(
-      new LiteralDecl("::android::IBinder* onAsBinder() override {\n"
-                      "  return nullptr;\n"
-                      "}\n"));
+  out << "::android::IBinder* onAsBinder() override {\n"
+      << "  return nullptr;\n"
+      << "}\n";
+
   // Each interface method by default returns UNKNOWN_TRANSACTION with is
   // the same status that is returned by transact() when the method is
   // not implemented in the server side. In other words, these default
@@ -1060,117 +936,81 @@
   // impl class without having to override all methods in an interface.
   for (const auto& method : interface.GetMethods()) {
     if (method->IsUserDefined()) {
-      std::ostringstream code;
-      code << "::android::binder::Status " << method->GetName()
-           << BuildArgList(typenames, *method, true, true).ToString() << " override";
-      GenerateDeprecated(code, *method);
-      code << " {\n"
-           << "  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);\n"
-           << "}\n";
-      method_decls.emplace_back(new LiteralDecl(code.str()));
-    } else {
-      if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
-        std::ostringstream code;
-        code << "int32_t " << kGetInterfaceVersion << "() override {\n"
-             << "  return 0;\n"
-             << "}\n";
-        method_decls.emplace_back(new LiteralDecl(code.str()));
-      }
-      if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
-        std::ostringstream code;
-        code << "std::string " << kGetInterfaceHash << "() override {\n"
-             << "  return \"\";\n"
-             << "}\n";
-        method_decls.emplace_back(new LiteralDecl(code.str()));
-      }
+      out << "::android::binder::Status " << method->GetName() << "("
+          << GenerateArgList(typenames, *method, /*for_declaration=*/true, /*type_name_only=*/true)
+          << ") override";
+      GenerateDeprecated(out, *method);
+      out << " {\n"
+          << "  return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);\n"
+          << "}\n";
+    } else if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
+      out << "int32_t " << kGetInterfaceVersion << "() override {\n"
+          << "  return 0;\n"
+          << "}\n";
+    } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+      out << "std::string " << kGetInterfaceHash << "() override {\n"
+          << "  return \"\";\n"
+          << "}\n";
     }
   }
+  out.Dedent();
+  out << "};  // class " << default_impl << "\n";
 
-  vector<unique_ptr<Declaration>> decls;
-  decls.emplace_back(std::move(if_class));
-  decls.emplace_back(new ClassDecl{
-      ClassName(interface, ClassNames::DEFAULT_IMPL),
-      i_name,
-      {},
-      std::move(method_decls),
-      {},
-      attribute,  // inherits the same attributes
-  });
-
-  return unique_ptr<Document>{
-      new CppHeader{vector<string>(includes.begin(), includes.end()),
-                    NestInNamespaces(std::move(decls), interface.GetSplitPackage())}};
-}
-
-string GetInitializer(const AidlTypenames& typenames, const AidlVariableDeclaration& variable) {
-  string cppType = CppNameOf(variable.GetType(), typenames);
-  return cppType + "(" + variable.ValueString(ConstantValueDecorator) + ")";
-}
-
-void AddTypeSpecificHeaders(const AidlStructuredParcelable&, std::set<std::string>& includes) {
-  includes.insert("tuple");  // std::tie in comparison operators
-}
-
-void BuildReadFromParcel(const AidlStructuredParcelable& parcel, const AidlTypenames& typenames,
-                         StatementBlock* read_block) {
-  read_block->AddLiteral(
-      StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
-
-  read_block->AddLiteral(
-      "[[maybe_unused]] size_t _aidl_start_pos = _aidl_parcel->dataPosition();\n"
-      "int32_t _aidl_parcelable_raw_size = _aidl_parcel->readInt32();\n"
-      "if (_aidl_parcelable_raw_size < 0) return ::android::BAD_VALUE;\n"
-      "[[maybe_unused]] size_t _aidl_parcelable_size = "
-      "static_cast<size_t>(_aidl_parcelable_raw_size);\n"
-      "if (_aidl_start_pos > SIZE_MAX - _aidl_parcelable_size) return ::android::BAD_VALUE;\n",
-      /*add_semicolon=*/false);
-
-  auto checkAvailableData = StringPrintf(
-      "if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {\n"
-      "  _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n"
-      "  return %s;\n"
-      "}\n",
-      kAndroidStatusVarName);
-
-  for (const auto& variable : parcel.GetFields()) {
-    read_block->AddLiteral(checkAvailableData, /*add_semicolon=*/false);
-    string method = ParcelReadMethodOf(variable->GetType(), typenames);
-    read_block->AddStatement(new Assignment(
-        kAndroidStatusVarName, new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
-                                              ParcelReadCastOf(variable->GetType(), typenames,
-                                                               "&" + variable->GetName()))));
-    read_block->AddStatement(ReturnOnStatusNotOk());
+  // When an interface is nested, every class should be defined together here
+  // because we don't have separate headers for them.
+  // (e.g. IFoo, IFooDefault, BpFoo, BnFoo, IFooDelegator)
+  if (interface.GetParentType()) {
+    GenerateClientClassDecl(out, interface, typenames, options);
+    GenerateServerClassDecl(out, interface, typenames, options);
   }
-  read_block->AddLiteral("_aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size)");
-  read_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
 }
 
-void BuildWriteToParcel(const AidlStructuredParcelable& parcel, const AidlTypenames& typenames,
-                        StatementBlock* write_block) {
-  write_block->AddLiteral(
-      StringPrintf("%s %s = %s", kAndroidStatusLiteral, kAndroidStatusVarName, kAndroidStatusOk));
+void GenerateReadFromParcel(CodeWriter& out, const AidlStructuredParcelable& parcel,
+                            const AidlTypenames& typenames) {
+  out << "::android::status_t _aidl_ret_status = ::android::OK;\n";
+  out << "size_t _aidl_start_pos = _aidl_parcel->dataPosition();\n";
+  out << "int32_t _aidl_parcelable_raw_size = 0;\n";
+  out << "_aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);\n";
+  out << "if (((_aidl_ret_status) != (::android::OK))) {\n";
+  out << "  return _aidl_ret_status;\n";
+  out << "}\n";
+  out << "if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;\n";
+  out << "size_t _aidl_parcelable_size = static_cast<size_t>(_aidl_parcelable_raw_size);\n";
+  out << "if (_aidl_start_pos > SIZE_MAX - _aidl_parcelable_size) return ::android::BAD_VALUE;\n";
+  for (const auto& variable : parcel.GetFields()) {
+    string method = ParcelReadMethodOf(variable->GetType(), typenames);
+    string arg = ParcelReadCastOf(variable->GetType(), typenames, "&" + variable->GetName());
+    out << "if (_aidl_parcel->dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) {\n";
+    out << "  _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n";
+    out << "  return _aidl_ret_status;\n";
+    out << "}\n";
+    out << "_aidl_ret_status = _aidl_parcel->" << method << "(" << arg << ");\n";
+    out << "if (((_aidl_ret_status) != (::android::OK))) {\n";
+    out << "  return _aidl_ret_status;\n";
+    out << "}\n";
+  }
+  out << "_aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);\n";
+  out << "return _aidl_ret_status;\n";
+}
 
-  write_block->AddLiteral(
-      "auto _aidl_start_pos = _aidl_parcel->dataPosition();\n"
-      "_aidl_parcel->writeInt32(0);\n",
-      /*add_semicolon=*/false);
-
+void GenerateWriteToParcel(CodeWriter& out, const AidlStructuredParcelable& parcel,
+                           const AidlTypenames& typenames) {
+  out << "::android::status_t _aidl_ret_status = ::android::OK;\n";
+  out << "auto _aidl_start_pos = " << kParcelVarName << "->dataPosition();\n";
+  out << kParcelVarName << "->writeInt32(0);\n";
   for (const auto& variable : parcel.GetFields()) {
     string method = ParcelWriteMethodOf(variable->GetType(), typenames);
-    write_block->AddStatement(new Assignment(
-        kAndroidStatusVarName,
-        new MethodCall(StringPrintf("_aidl_parcel->%s", method.c_str()),
-                       ParcelWriteCastOf(variable->GetType(), typenames, variable->GetName()))));
-    write_block->AddStatement(ReturnOnStatusNotOk());
+    string arg = ParcelWriteCastOf(variable->GetType(), typenames, variable->GetName());
+    out << "_aidl_ret_status = " << kParcelVarName << "->" << method << "(" << arg << ");\n";
+    out << "if (((_aidl_ret_status) != (::android::OK))) {\n";
+    out << "  return _aidl_ret_status;\n";
+    out << "}\n";
   }
-
-  write_block->AddLiteral(
-      "auto _aidl_end_pos = _aidl_parcel->dataPosition();\n"
-      "_aidl_parcel->setDataPosition(_aidl_start_pos);\n"
-      "_aidl_parcel->writeInt32(_aidl_end_pos - _aidl_start_pos);\n"
-      "_aidl_parcel->setDataPosition(_aidl_end_pos);\n",
-      /*add_semicolon=*/false);
-  write_block->AddLiteral(StringPrintf("return %s", kAndroidStatusVarName));
+  out << "auto _aidl_end_pos = " << kParcelVarName << "->dataPosition();\n";
+  out << kParcelVarName << "->setDataPosition(_aidl_start_pos);\n";
+  out << kParcelVarName << "->writeInt32(_aidl_end_pos - _aidl_start_pos);\n";
+  out << kParcelVarName << "->setDataPosition(_aidl_end_pos);\n";
+  out << "return _aidl_ret_status;\n";
 }
 
 ParcelWriterContext GetParcelWriterContext(const AidlTypenames& typenames) {
@@ -1191,382 +1031,157 @@
   };
 }
 
-void AddTypeSpecificHeaders(const AidlUnionDecl&, std::set<std::string>& includes) {
-  includes.insert(std::begin(UnionWriter::headers), std::end(UnionWriter::headers));
-}
-
-void BuildReadFromParcel(const AidlUnionDecl& decl, const AidlTypenames& typenames,
-                         StatementBlock* read_block) {
-  string body;
+void GenerateReadFromParcel(CodeWriter& out, const AidlUnionDecl& decl,
+                            const AidlTypenames& typenames) {
   UnionWriter uw{decl, typenames, &CppNameOf, &ConstantValueDecorator};
-  uw.ReadFromParcel(*CodeWriter::ForString(&body), GetParcelWriterContext(typenames));
-  read_block->AddLiteral(body, /*add_semicolon=*/false);
+  uw.ReadFromParcel(out, GetParcelWriterContext(typenames));
 }
 
-void BuildWriteToParcel(const AidlUnionDecl& decl, const AidlTypenames& typenames,
-                        StatementBlock* write_block) {
-  string body;
+void GenerateWriteToParcel(CodeWriter& out, const AidlUnionDecl& decl,
+                           const AidlTypenames& typenames) {
   UnionWriter uw{decl, typenames, &CppNameOf, &ConstantValueDecorator};
-  uw.WriteToParcel(*CodeWriter::ForString(&body), GetParcelWriterContext(typenames));
-  write_block->AddLiteral(body, /*add_semicolon=*/false);
+  uw.WriteToParcel(out, GetParcelWriterContext(typenames));
 }
 
-void BuildParcelFields(ClassDecl& clazz, const AidlStructuredParcelable& decl,
-                       const AidlTypenames& typenames) {
+void GenerateParcelFields(CodeWriter& out, const AidlStructuredParcelable& decl,
+                          const AidlTypenames& typenames) {
   for (const auto& variable : decl.GetFields()) {
-    std::ostringstream out;
-    std::string cppType = CppNameOf(variable->GetType(), typenames);
-    out << cppType;
+    const auto& type = variable->GetType();
+    std::string cpp_type = CppNameOf(type, typenames);
+    out << cpp_type;
     GenerateDeprecated(out, *variable);
-    out << " " << variable->GetName().c_str();
+    out << " " << variable->GetName();
     if (variable->GetDefaultValue()) {
-      out << " = " << GetInitializer(typenames, *variable);
-    } else if (variable->GetType().GetName() == "ParcelableHolder") {
-      if (decl.IsVintfStability()) {
-        out << " { ::android::Parcelable::Stability::STABILITY_VINTF }";
-      } else {
-        out << " { ::android::Parcelable::Stability::STABILITY_LOCAL }";
-      }
-    } else if (auto type = variable->GetType().GetDefinedType(); type) {
-      if (auto enum_type = type->AsEnumDeclaration(); enum_type) {
-        if (!variable->GetType().IsArray()) {
-          // if an enum doesn't have explicit default value, do zero-initialization
-          out << " = " << cppType << "(0)";
+      out << " = " << variable->ValueString(ConstantValueDecorator);
+    } else {
+      // Some types needs to be explicitly initialized even when no default value is set.
+      // - ParcelableHolder should be initialized with stability
+      // - enum should be zero initialized, otherwise the value will be indeterminate
+      // - fixed-size arrays should be initialized, otherwise the value will be indeterminate
+      if (type.GetName() == "ParcelableHolder") {
+        if (decl.IsVintfStability()) {
+          out << " { ::android::Parcelable::Stability::STABILITY_VINTF }";
+        } else {
+          out << " { ::android::Parcelable::Stability::STABILITY_LOCAL }";
         }
+      } else if (typenames.GetEnumDeclaration(type) && !type.IsArray()) {
+        out << " = " << cpp_type << "(0)";
+      } else if (type.IsFixedSizeArray() && !type.IsNullable()) {
+        out << " = {{}}";
       }
     }
     out << ";\n";
-
-    clazz.AddPublic(std::unique_ptr<LiteralDecl>(new LiteralDecl(out.str())));
   }
 }
 
-void BuildParcelFields(ClassDecl& clazz, const AidlUnionDecl& decl,
-                       const AidlTypenames& typenames) {
+void GenerateParcelFields(CodeWriter& out, const AidlUnionDecl& decl,
+                          const AidlTypenames& typenames) {
   UnionWriter uw{decl, typenames, &CppNameOf, &ConstantValueDecorator};
-  string public_fields;
-  string private_fields;
-  uw.PublicFields(*CodeWriter::ForString(&public_fields));
-  uw.PrivateFields(*CodeWriter::ForString(&private_fields));
-  clazz.AddPublic(std::make_unique<LiteralDecl>(public_fields));
-  clazz.AddPrivate(std::make_unique<LiteralDecl>(private_fields));
+  uw.PublicFields(out);
 }
 
 template <typename ParcelableType>
-std::unique_ptr<Document> BuildParcelHeader(const AidlTypenames& typenames,
-                                            const ParcelableType& parcel, const Options&) {
-  const std::vector<std::string>& type_params =
-      parcel.IsGeneric() ? parcel.GetTypeParameters() : std::vector<std::string>();
-  const std::string attribute = GetDeprecatedAttribute(parcel);
-  unique_ptr<ClassDecl> parcel_class{
-      new ClassDecl{parcel.GetName(), "::android::Parcelable", type_params, attribute}};
+void GenerateParcelClassDecl(CodeWriter& out, const ParcelableType& parcel,
+                             const AidlTypenames& typenames, const Options& options) {
+  const string clazz = parcel.GetName();
 
-  set<string> includes = {kStatusHeader, kParcelHeader, kString16Header};
-  AddTypeSpecificHeaders(parcel, includes);
+  out << TemplateDecl(parcel);
+  out << "class";
+  GenerateDeprecated(out, parcel);
+  out << " " << clazz << " : public ::android::Parcelable {\n";
+  out << "public:\n";
+  out.Indent();
 
-  for (const auto& variable : parcel.GetFields()) {
-    AddHeaders(variable->GetType(), typenames, &includes);
-  }
-
-  string operator_code;
-  GenerateParcelableComparisonOperators(*CodeWriter::ForString(&operator_code), parcel);
-  parcel_class->AddPublic(std::make_unique<LiteralDecl>(operator_code));
-
-  BuildParcelFields(*parcel_class, parcel, typenames);
-  BuildConstantDeclarations(parcel, typenames, parcel_class, includes);
+  GenerateNestedTypeDecls(out, parcel, typenames, options);
+  GenerateParcelFields(out, parcel, typenames);
+  GenerateParcelableComparisonOperators(out, parcel);
+  GenerateConstantDeclarations(out, parcel, typenames);
 
   if (parcel.IsVintfStability()) {
-    parcel_class->AddPublic(std::unique_ptr<LiteralDecl>(
-        new LiteralDecl("::android::Parcelable::Stability getStability() const override { return "
-                        "::android::Parcelable::Stability::STABILITY_VINTF; }\n")));
+    out << "::android::Parcelable::Stability getStability() const override { return "
+           "::android::Parcelable::Stability::STABILITY_VINTF; }\n";
   }
 
-  unique_ptr<MethodDecl> read(new MethodDecl(kAndroidStatusLiteral, "readFromParcel",
-                                             ArgList("const ::android::Parcel* _aidl_parcel"),
-                                             MethodDecl::IS_FINAL));
-  parcel_class->AddPublic(std::move(read));
-  unique_ptr<MethodDecl> write(new MethodDecl(kAndroidStatusLiteral, "writeToParcel",
-                                              ArgList("::android::Parcel* _aidl_parcel"),
-                                              MethodDecl::IS_CONST | MethodDecl::IS_FINAL));
-  parcel_class->AddPublic(std::move(write));
+  out << kAndroidStatusLiteral << " readFromParcel(const ::android::Parcel* _aidl_parcel) final;\n";
+  out << kAndroidStatusLiteral << " writeToParcel(::android::Parcel* _aidl_parcel) const final;\n";
 
-  parcel_class->AddPublic(std::unique_ptr<LiteralDecl>(
-      new LiteralDecl(StringPrintf("static const ::android::String16& getParcelableDescriptor() {\n"
-                                   "  static const ::android::StaticString16 DESCIPTOR (u\"%s\");\n"
-                                   "  return DESCIPTOR;\n"
-                                   "}\n",
-                                   parcel.GetCanonicalName().c_str()))));
+  const string canonical_name = parcel.GetCanonicalName();
+  out << "static const ::android::String16& getParcelableDescriptor() {\n"
+      << "  static const ::android::StaticString16 DESCIPTOR (u\"" << canonical_name << "\");\n"
+      << "  return DESCIPTOR;\n"
+      << "}\n";
 
-  // toString() method
-  includes.insert("android/binder_to_string.h");
-  string to_string;
-  GenerateToString(*CodeWriter::ForString(&to_string), parcel);
-  parcel_class->AddPublic(std::make_unique<LiteralDecl>(to_string));
+  GenerateToString(out, parcel);
 
-  auto decls = NestInNamespaces(std::move(parcel_class), parcel.GetSplitPackage());
-  // TODO(b/31559095) bionic on host should define this
-  if (parcel.AsUnionDeclaration()) {
-    decls.insert(decls.begin(),
-                 std::make_unique<LiteralDecl>(
-                     "#ifndef __BIONIC__\n#define __assert2(a,b,c,d) ((void)0)\n#endif\n\n"));
+  out.Dedent();
+
+  if (auto decl = AidlCast<AidlUnionDecl>(parcel); decl) {
+    out << "private:\n";
+    out.Indent();
+    UnionWriter uw{*decl, typenames, &CppNameOf, &ConstantValueDecorator};
+    uw.PrivateFields(out);
+    out.Dedent();
   }
-  return unique_ptr<Document>{
-      new CppHeader{vector<string>(includes.begin(), includes.end()), std::move(decls)}};
+
+  out << "};  // class " << clazz << "\n";
 }
 
 template <typename T>
-std::unique_ptr<Document> BuildParcelSource(const AidlTypenames& typenames, const T& parcel,
-                                            const Options&) {
-  const std::vector<std::string>& type_params =
-      parcel.IsGeneric() ? parcel.GetTypeParameters() : std::vector<std::string>();
-  auto read =
-      std::make_unique<MethodImpl>(kAndroidStatusLiteral, parcel.GetName(), "readFromParcel",
-                                   type_params, ArgList("const ::android::Parcel* _aidl_parcel"));
-  BuildReadFromParcel(parcel, typenames, read->GetStatementBlock());
+void GenerateParcelSource(CodeWriter& out, const T& parcel, const AidlTypenames& typenames,
+                          const Options&) {
+  string q_name = GetQualifiedName(parcel);
+  if (parcel.IsGeneric()) {
+    q_name += "<" + Join(parcel.GetTypeParameters(), ",") + ">";
+  }
 
-  auto write = std::make_unique<MethodImpl>(
-      kAndroidStatusLiteral, parcel.GetName(), "writeToParcel", type_params,
-      ArgList("::android::Parcel* _aidl_parcel"), true /*const*/);
-  BuildWriteToParcel(parcel, typenames, write->GetStatementBlock());
+  out << "#include <" << CppHeaderForType(parcel) << ">\n\n";
 
-  vector<unique_ptr<Declaration>> file_decls;
-  BuildConstantDefinitions(parcel, typenames, type_params, parcel.GetName(), file_decls);
-  file_decls.push_back(std::move(read));
-  file_decls.push_back(std::move(write));
+  EnterNamespace(out, parcel);
+  GenerateConstantDefinitions(out, parcel, typenames, TemplateDecl(parcel), q_name);
 
-  set<string> includes = {};
-  AddHeaders(parcel, &includes);
+  out << TemplateDecl(parcel);
+  out << "::android::status_t " << q_name << "::readFromParcel(const ::android::Parcel* "
+      << kParcelVarName << ") {\n";
+  out.Indent();
+  GenerateReadFromParcel(out, parcel, typenames);
+  out.Dedent();
+  out << "}\n";
 
-  return unique_ptr<Document>{
-      new CppSource{vector<string>(includes.begin(), includes.end()),
-                    NestInNamespaces(std::move(file_decls), parcel.GetSplitPackage())}};
+  out << TemplateDecl(parcel);
+  out << "::android::status_t " << q_name << "::writeToParcel(::android::Parcel* " << kParcelVarName
+      << ") const {\n";
+  out.Indent();
+  GenerateWriteToParcel(out, parcel, typenames);
+  out.Dedent();
+  out << "}\n";
+  LeaveNamespace(out, parcel);
 }
 
-std::string GenerateEnumToString(const AidlTypenames& typenames,
-                                 const AidlEnumDeclaration& enum_decl) {
-  std::ostringstream code;
-  code << "[[nodiscard]]";
-  GenerateDeprecated(code, enum_decl);
-  code << " static inline std::string toString(" << enum_decl.GetName() << " val)";
-  code << " {\n";
-  code << "  switch(val) {\n";
-  std::set<std::string> unique_cases;
-  for (const auto& enumerator : enum_decl.GetEnumerators()) {
-    std::string c = enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator);
-    // Only add a case if its value has not yet been used in the switch
-    // statement. C++ does not allow multiple cases with the same value, but
-    // enums does allow this. In this scenario, the first declared
-    // enumerator with the given value is printed.
-    if (unique_cases.count(c) == 0) {
-      unique_cases.insert(c);
-      code << "  case " << enum_decl.GetName() << "::" << enumerator->GetName() << ":\n";
-      code << "    return \"" << enumerator->GetName() << "\";\n";
-    }
-  }
-  code << "  default:\n";
-  code << "    return std::to_string(static_cast<"
-       << CppNameOf(enum_decl.GetBackingType(), typenames) << ">(val));\n";
-  code << "  }\n";
-  code << "}\n";
-  return code.str();
+void GenerateEnumClassDecl(CodeWriter& out, const AidlEnumDeclaration& enum_decl,
+                           const AidlTypenames& typenames) {
+  cpp::GenerateEnumClassDecl(out, enum_decl, CppNameOf(enum_decl.GetBackingType(), typenames),
+                             ConstantValueDecorator);
 }
 
-std::unique_ptr<Document> BuildEnumHeader(const AidlTypenames& typenames,
-                                          const AidlEnumDeclaration& enum_decl) {
-  const std::string attribute = GetDeprecatedAttribute(enum_decl);
-  std::unique_ptr<Enum> generated_enum{new Enum{
-      enum_decl.GetName(), CppNameOf(enum_decl.GetBackingType(), typenames), true, attribute}};
-  for (const auto& enumerator : enum_decl.GetEnumerators()) {
-    generated_enum->AddValue(
-        enumerator->GetName(),
-        enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator));
+void GenerateClassDecl(CodeWriter& out, const AidlDefinedType& defined_type,
+                       const AidlTypenames& typenames, const Options& options) {
+  if (auto iface = AidlCast<AidlInterface>(defined_type); iface) {
+    GenerateInterfaceClassDecl(out, *iface, typenames, options);
+  } else if (auto parcelable = AidlCast<AidlStructuredParcelable>(defined_type); parcelable) {
+    GenerateParcelClassDecl(out, *parcelable, typenames, options);
+  } else if (auto union_decl = AidlCast<AidlUnionDecl>(defined_type); union_decl) {
+    GenerateParcelClassDecl(out, *union_decl, typenames, options);
+  } else if (auto enum_decl = AidlCast<AidlEnumDeclaration>(defined_type); enum_decl) {
+    GenerateEnumClassDecl(out, *enum_decl, typenames);
+  } else {
+    AIDL_FATAL(defined_type) << "Unrecognized type sent for CPP generation.";
   }
-
-  std::set<std::string> includes = {
-      "array",
-      "binder/Enums.h",
-      "string",
-  };
-  AddHeaders(enum_decl.GetBackingType(), typenames, &includes);
-
-  std::vector<std::unique_ptr<Declaration>> decls1;
-  decls1.push_back(std::move(generated_enum));
-  decls1.push_back(std::make_unique<LiteralDecl>(GenerateEnumToString(typenames, enum_decl)));
-
-  std::vector<std::unique_ptr<Declaration>> decls2;
-  decls2.push_back(std::make_unique<LiteralDecl>(GenerateEnumValues(enum_decl, {""})));
-
-  return unique_ptr<Document>{
-      new CppHeader{vector<string>(includes.begin(), includes.end()),
-                    Append(NestInNamespaces(std::move(decls1), enum_decl.GetSplitPackage()),
-                           NestInNamespaces(std::move(decls2), {"android", "internal"}))}};
-}
-
-bool WriteHeader(const Options& options, const AidlTypenames& typenames,
-                 const AidlInterface& interface, const IoDelegate& io_delegate,
-                 ClassNames header_type) {
-  unique_ptr<Document> header;
-  switch (header_type) {
-    case ClassNames::INTERFACE:
-      header = BuildInterfaceHeader(typenames, interface, options);
-      header_type = ClassNames::RAW;
-      break;
-    case ClassNames::CLIENT:
-      header = BuildClientHeader(typenames, interface, options);
-      break;
-    case ClassNames::SERVER:
-      header = BuildServerHeader(typenames, interface, options);
-      break;
-    default:
-      AIDL_FATAL(interface) << "aidl internal error";
-  }
-  if (!header) {
-    AIDL_ERROR(interface) << "aidl internal error: Failed to generate header.";
-    return false;
-  }
-
-  const string header_path = options.OutputHeaderDir() + HeaderFile(interface, header_type);
-  unique_ptr<CodeWriter> code_writer(io_delegate.GetCodeWriter(header_path));
-  header->Write(code_writer.get());
-
-  const bool success = code_writer->Close();
-  if (!success) {
-    io_delegate.RemovePath(header_path);
-  }
-
-  return success;
 }
 
 }  // namespace internals
 
 using namespace internals;
 
-bool GenerateCppInterface(const string& output_file, const Options& options,
-                          const AidlTypenames& typenames, const AidlInterface& interface,
-                          const IoDelegate& io_delegate) {
-  auto interface_src = BuildInterfaceSource(typenames, interface, options);
-  auto client_src = BuildClientSource(typenames, interface, options);
-  auto server_src = BuildServerSource(typenames, interface, options);
-
-  if (!interface_src || !client_src || !server_src) {
-    return false;
-  }
-
-  if (!WriteHeader(options, typenames, interface, io_delegate, ClassNames::INTERFACE) ||
-      !WriteHeader(options, typenames, interface, io_delegate, ClassNames::CLIENT) ||
-      !WriteHeader(options, typenames, interface, io_delegate, ClassNames::SERVER)) {
-    return false;
-  }
-
-  unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(output_file);
-  interface_src->Write(writer.get());
-  client_src->Write(writer.get());
-  server_src->Write(writer.get());
-
-  const bool success = writer->Close();
-  if (!success) {
-    io_delegate.RemovePath(output_file);
-  }
-
-  return success;
-}
-
-template <typename ParcelableType>
-bool GenerateCppParcelable(const std::string& output_file, const Options& options,
-                           const AidlTypenames& typenames, const ParcelableType& parcelable,
-                           const IoDelegate& io_delegate) {
-  auto header = BuildParcelHeader(typenames, parcelable, options);
-  auto source = BuildParcelSource(typenames, parcelable, options);
-
-  if (!header || !source) {
-    return false;
-  }
-
-  const string header_path = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::RAW);
-  unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
-  header->Write(header_writer.get());
-  if (parcelable.IsGeneric()) {
-    // Need to write all of the source in the header file, not cpp file.
-    source->Write(header_writer.get());
-  }
-  AIDL_FATAL_IF(!header_writer->Close(), header_path);
-
-  // TODO(b/111362593): no unecessary files just to have consistent output with interfaces
-  const string bp_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::CLIENT);
-  unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
-  bp_writer->Write("#error TODO(b/111362593) parcelables do not have bp classes");
-  AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
-  const string bn_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::SERVER);
-  unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
-  bn_writer->Write("#error TODO(b/111362593) parcelables do not have bn classes");
-  AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
-
-  unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
-  if (parcelable.IsGeneric()) {
-    // Since the type is generic, the source is written in the header file
-    auto empty_source = unique_ptr<Document>{new CppSource{{}, {}}};
-    empty_source->Write(source_writer.get());
-  } else {
-    source->Write(source_writer.get());
-  }
-  AIDL_FATAL_IF(!source_writer->Close(), output_file);
-
-  return true;
-}
-
-bool GenerateCppParcelDeclaration(const std::string& filename, const Options& options,
-                                  const AidlParcelable& parcelable, const IoDelegate& io_delegate) {
-  CodeWriterPtr source_writer = io_delegate.GetCodeWriter(filename);
-  *source_writer
-      << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
-  AIDL_FATAL_IF(!source_writer->Close(), filename);
-
-  // TODO(b/111362593): no unecessary files just to have consistent output with interfaces
-  const string header_path = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::RAW);
-  unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
-  header_writer->Write("#error TODO(b/111362593) parcelables do not have headers");
-  AIDL_FATAL_IF(!header_writer->Close(), header_path);
-  const string bp_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::CLIENT);
-  unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
-  bp_writer->Write("#error TODO(b/111362593) parcelables do not have bp classes");
-  AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
-  const string bn_header = options.OutputHeaderDir() + HeaderFile(parcelable, ClassNames::SERVER);
-  unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
-  bn_writer->Write("#error TODO(b/111362593) parcelables do not have bn classes");
-  AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
-
-  return true;
-}
-
-bool GenerateCppEnumDeclaration(const std::string& filename, const Options& options,
-                                const AidlTypenames& typenames,
-                                const AidlEnumDeclaration& enum_decl,
-                                const IoDelegate& io_delegate) {
-  auto header = BuildEnumHeader(typenames, enum_decl);
-  if (!header) return false;
-
-  const string header_path = options.OutputHeaderDir() + HeaderFile(enum_decl, ClassNames::RAW);
-  unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
-  header->Write(header_writer.get());
-  AIDL_FATAL_IF(!header_writer->Close(), header_path);
-
-  // TODO(b/111362593): no unnecessary files just to have consistent output with interfaces
-  CodeWriterPtr source_writer = io_delegate.GetCodeWriter(filename);
-  *source_writer
-      << "// This file is intentionally left blank as placeholder for enum declaration.\n";
-  AIDL_FATAL_IF(!source_writer->Close(), filename);
-  const string bp_header = options.OutputHeaderDir() + HeaderFile(enum_decl, ClassNames::CLIENT);
-  unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
-  bp_writer->Write("#error TODO(b/111362593) enums do not have bp classes");
-  AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
-  const string bn_header = options.OutputHeaderDir() + HeaderFile(enum_decl, ClassNames::SERVER);
-  unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
-  bn_writer->Write("#error TODO(b/111362593) enums do not have bn classes");
-  AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
-
-  return true;
-}
-
 // Ensures that output_file is  <out_dir>/<packagename>/<typename>.cpp
 bool ValidateOutputFilePath(const string& output_file, const Options& options,
                             const AidlDefinedType& defined_type) {
@@ -1592,41 +1207,235 @@
   return true;
 }
 
+// Collect all includes for the type's header. Nested types are visited as well via VisitTopDown.
+void GenerateHeaderIncludes(CodeWriter& out, const AidlDefinedType& defined_type,
+                            const AidlTypenames& typenames, const Options& options) {
+  struct Visitor : AidlVisitor {
+    const AidlTypenames& typenames;
+    const Options& options;
+    std::set<std::string> includes;
+    Visitor(const AidlTypenames& typenames, const Options& options)
+        : typenames(typenames), options(options) {}
+
+    // Collect includes for each type reference including built-in type
+    void Visit(const AidlTypeSpecifier& type) override {
+      cpp::AddHeaders(type, typenames, &includes);
+    }
+
+    // Collect implementation-specific includes for each type definition
+    void Visit(const AidlInterface& iface) override {
+      includes.insert(kIBinderHeader);        // IBinder
+      includes.insert(kIInterfaceHeader);     // IInterface
+      includes.insert(kStatusHeader);         // Status
+      includes.insert(kStrongPointerHeader);  // sp<>
+
+      if (options.GenTraces()) {
+        includes.insert(kTraceHeader);
+      }
+
+      // For a nested interface, client/server classes are declared the same header as well.
+      if (iface.GetParentType()) {
+        // client/server class provides logFunc when gen_log is on
+        if (options.GenLog()) {
+          includes.insert("functional");                  // std::function for logFunc
+          includes.insert("android/binder_to_string.h");  // Generic ToString helper
+        }
+      }
+    }
+
+    void Visit(const AidlStructuredParcelable&) override {
+      AddParcelableCommonHeaders();
+      includes.insert("tuple");  // std::tie in comparison operators
+    }
+
+    void Visit(const AidlUnionDecl& union_decl) override {
+      AddParcelableCommonHeaders();
+      auto union_headers = cpp::UnionWriter::GetHeaders(union_decl);
+      includes.insert(std::begin(union_headers), std::end(union_headers));
+    }
+
+    void Visit(const AidlEnumDeclaration&) override {
+      includes.insert("array");           // used in enum_values
+      includes.insert("binder/Enums.h");  // provides enum_range
+      includes.insert("string");          // toString() returns std::string
+    }
+
+    void AddParcelableCommonHeaders() {
+      includes.insert(kParcelHeader);                 // Parcel in readFromParcel/writeToParcel
+      includes.insert(kStatusHeader);                 // Status
+      includes.insert(kString16Header);               // String16 in getParcelableDescriptor
+      includes.insert("android/binder_to_string.h");  // toString()
+    }
+  } v(typenames, options);
+  VisitTopDown(v, defined_type);
+
+  for (const auto& path : v.includes) {
+    out << "#include <" << path << ">\n";
+  }
+  out << "\n";
+  if (v.includes.count("cassert")) {
+    // TODO(b/31559095) bionic on host should define __assert2
+    out << "#ifndef __BIONIC__\n#define __assert2(a,b,c,d) ((void)0)\n#endif\n\n";
+  }
+}
+
+// Generic parcelables and enum utilities should be defined in header.
+void GenerateHeaderDefinitions(CodeWriter& out, const AidlDefinedType& defined_type,
+                               const AidlTypenames& typenames, const Options& options) {
+  struct Visitor : AidlVisitor {
+    CodeWriter& out;
+    const AidlTypenames& typenames;
+    const Options& options;
+    Visitor(CodeWriter& out, const AidlTypenames& typenames, const Options& options)
+        : out(out), typenames(typenames), options(options) {}
+
+    void Visit(const AidlEnumDeclaration& enum_decl) override {
+      const auto backing_type = CppNameOf(enum_decl.GetBackingType(), typenames);
+      EnterNamespace(out, enum_decl);
+      out << GenerateEnumToString(enum_decl, backing_type);
+      LeaveNamespace(out, enum_decl);
+
+      out << "namespace android {\n";
+      out << "namespace internal {\n";
+      out << GenerateEnumValues(enum_decl, {""});
+      out << "}  // namespace internal\n";
+      out << "}  // namespace android\n";
+    }
+
+    void Visit(const AidlStructuredParcelable& parcelable) override {
+      if (parcelable.IsGeneric()) {
+        GenerateParcelSource(out, parcelable, typenames, options);
+      }
+    }
+
+    void Visit(const AidlUnionDecl& union_decl) override {
+      if (union_decl.IsGeneric()) {
+        GenerateParcelSource(out, union_decl, typenames, options);
+      }
+    }
+
+  } v(out, typenames, options);
+  VisitTopDown(v, defined_type);
+}
+
+void GenerateHeader(CodeWriter& out, const AidlDefinedType& defined_type,
+                    const AidlTypenames& typenames, const Options& options) {
+  if (auto parcelable = AidlCast<AidlParcelable>(defined_type); parcelable) {
+    out << "#error TODO(b/111362593) parcelables do not have headers";
+    return;
+  }
+  out << "#pragma once\n\n";
+  GenerateHeaderIncludes(out, defined_type, typenames, options);
+  EnterNamespace(out, defined_type);
+  // Each class decl contains its own nested types' class decls
+  GenerateClassDecl(out, defined_type, typenames, options);
+  LeaveNamespace(out, defined_type);
+  GenerateHeaderDefinitions(out, defined_type, typenames, options);
+}
+
+void GenerateClientHeader(CodeWriter& out, const AidlDefinedType& defined_type,
+                          const AidlTypenames& typenames, const Options& options) {
+  if (auto iface = AidlCast<AidlInterface>(defined_type); iface) {
+    GenerateClientHeader(out, *iface, typenames, options);
+  } else if (auto parcelable = AidlCast<AidlStructuredParcelable>(defined_type); parcelable) {
+    out << "#error TODO(b/111362593) parcelables do not have bp classes";
+  } else if (auto union_decl = AidlCast<AidlUnionDecl>(defined_type); union_decl) {
+    out << "#error TODO(b/111362593) parcelables do not have bp classes";
+  } else if (auto enum_decl = AidlCast<AidlEnumDeclaration>(defined_type); enum_decl) {
+    out << "#error TODO(b/111362593) enums do not have bp classes";
+  } else if (auto parcelable = AidlCast<AidlParcelable>(defined_type); parcelable) {
+    out << "#error TODO(b/111362593) parcelables do not have bp classes";
+  } else {
+    AIDL_FATAL(defined_type) << "Unrecognized type sent for CPP generation.";
+  }
+}
+
+void GenerateServerHeader(CodeWriter& out, const AidlDefinedType& defined_type,
+                          const AidlTypenames& typenames, const Options& options) {
+  if (auto iface = AidlCast<AidlInterface>(defined_type); iface) {
+    GenerateServerHeader(out, *iface, typenames, options);
+  } else if (auto parcelable = AidlCast<AidlStructuredParcelable>(defined_type); parcelable) {
+    out << "#error TODO(b/111362593) parcelables do not have bn classes";
+  } else if (auto union_decl = AidlCast<AidlUnionDecl>(defined_type); union_decl) {
+    out << "#error TODO(b/111362593) parcelables do not have bn classes";
+  } else if (auto enum_decl = AidlCast<AidlEnumDeclaration>(defined_type); enum_decl) {
+    out << "#error TODO(b/111362593) enums do not have bn classes";
+  } else if (auto parcelable = AidlCast<AidlParcelable>(defined_type); parcelable) {
+    out << "#error TODO(b/111362593) parcelables do not have bn classes";
+  } else {
+    AIDL_FATAL(defined_type) << "Unrecognized type sent for CPP generation.";
+  }
+}
+
+void GenerateSource(CodeWriter& out, const AidlDefinedType& defined_type,
+                    const AidlTypenames& typenames, const Options& options) {
+  struct Visitor : AidlVisitor {
+    CodeWriter& out;
+    const AidlTypenames& typenames;
+    const Options& options;
+    Visitor(CodeWriter& out, const AidlTypenames& typenames, const Options& options)
+        : out(out), typenames(typenames), options(options) {}
+
+    void Visit(const AidlInterface& interface) override {
+      GenerateInterfaceSource(out, interface, typenames, options);
+      GenerateClientSource(out, interface, typenames, options);
+      GenerateServerSource(out, interface, typenames, options);
+    }
+
+    void Visit(const AidlStructuredParcelable& parcelable) override {
+      if (!parcelable.IsGeneric()) {
+        GenerateParcelSource(out, parcelable, typenames, options);
+      } else {
+        out << "\n";
+      }
+    }
+
+    void Visit(const AidlUnionDecl& union_decl) override {
+      if (!union_decl.IsGeneric()) {
+        GenerateParcelSource(out, union_decl, typenames, options);
+      } else {
+        out << "\n";
+      }
+    }
+
+    void Visit(const AidlEnumDeclaration& enum_decl) override {
+      if (!enum_decl.GetParentType()) {
+        out << "// This file is intentionally left blank as placeholder for enum declaration.\n";
+      }
+    }
+
+    void Visit(const AidlParcelable& parcelable) override {
+      AIDL_FATAL_IF(parcelable.GetParentType(), parcelable)
+          << "Unstructured parcelable can't be nested.";
+      out << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
+    }
+  } v(out, typenames, options);
+  VisitTopDown(v, defined_type);
+}
+
 bool GenerateCpp(const string& output_file, const Options& options, const AidlTypenames& typenames,
                  const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
   if (!ValidateOutputFilePath(output_file, options, defined_type)) {
     return false;
   }
 
-  const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
-  if (parcelable != nullptr) {
-    return GenerateCppParcelable(output_file, options, typenames, *parcelable, io_delegate);
-  }
+  using GenFn = void (*)(CodeWriter & out, const AidlDefinedType& defined_type,
+                         const AidlTypenames& typenames, const Options& options);
+  // Wrap Generate* function to handle CodeWriter for a file.
+  auto gen = [&](auto file, GenFn fn) {
+    unique_ptr<CodeWriter> writer(io_delegate.GetCodeWriter(file));
+    fn(*writer, defined_type, typenames, options);
+    AIDL_FATAL_IF(!writer->Close(), defined_type) << "I/O Error!";
+    return true;
+  };
 
-  // should come before AsParcelable() because union is a parcelable
-  const AidlUnionDecl* union_decl = defined_type.AsUnionDeclaration();
-  if (union_decl != nullptr) {
-    return GenerateCppParcelable(output_file, options, typenames, *union_decl, io_delegate);
-  }
-
-  // unstructured parcelable
-  const AidlParcelable* parcelable_decl = defined_type.AsParcelable();
-  if (parcelable_decl != nullptr) {
-    return GenerateCppParcelDeclaration(output_file, options, *parcelable_decl, io_delegate);
-  }
-
-  const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
-  if (enum_decl != nullptr) {
-    return GenerateCppEnumDeclaration(output_file, options, typenames, *enum_decl, io_delegate);
-  }
-
-  const AidlInterface* interface = defined_type.AsInterface();
-  if (interface != nullptr) {
-    return GenerateCppInterface(output_file, options, typenames, *interface, io_delegate);
-  }
-
-  AIDL_FATAL(defined_type) << "Unrecognized type sent for cpp generation.";
-  return false;
+  return gen(options.OutputHeaderDir() + HeaderFile(defined_type, ClassNames::RAW),
+             &GenerateHeader) &&
+         gen(options.OutputHeaderDir() + HeaderFile(defined_type, ClassNames::CLIENT),
+             &GenerateClientHeader) &&
+         gen(options.OutputHeaderDir() + HeaderFile(defined_type, ClassNames::SERVER),
+             &GenerateServerHeader) &&
+         gen(output_file, &GenerateSource);
 }
 
 }  // namespace cpp
diff --git a/generate_cpp.h b/generate_cpp.h
index 3b7d2b9..acd3d39 100644
--- a/generate_cpp.h
+++ b/generate_cpp.h
@@ -22,7 +22,6 @@
 #include "aidl_language.h"
 #include "aidl_to_cpp.h"
 #include "aidl_to_cpp_common.h"
-#include "ast_cpp.h"
 #include "options.h"
 
 namespace android {
@@ -32,28 +31,6 @@
 bool GenerateCpp(const string& output_file, const Options& options, const AidlTypenames& typenames,
                  const AidlDefinedType& parsed_doc, const IoDelegate& io_delegate);
 
-namespace internals {
-std::unique_ptr<Document> BuildClientSource(const AidlTypenames& typenames,
-                                            const AidlInterface& parsed_doc,
-                                            const Options& options);
-std::unique_ptr<Document> BuildServerSource(const AidlTypenames& typenames,
-                                            const AidlInterface& parsed_doc,
-                                            const Options& options);
-std::unique_ptr<Document> BuildInterfaceSource(const AidlTypenames& typenames,
-                                               const AidlInterface& parsed_doc,
-                                               const Options& options);
-std::unique_ptr<Document> BuildClientHeader(const AidlTypenames& typenames,
-                                            const AidlInterface& parsed_doc,
-                                            const Options& options);
-std::unique_ptr<Document> BuildServerHeader(const AidlTypenames& typenames,
-                                            const AidlInterface& parsed_doc,
-                                            const Options& options);
-std::unique_ptr<Document> BuildInterfaceHeader(const AidlTypenames& typenames,
-                                               const AidlInterface& parsed_doc,
-                                               const Options& options);
-std::unique_ptr<Document> BuildEnumHeader(const AidlTypenames& typenames,
-                                          const AidlEnumDeclaration& parsed_doc);
-}
 }  // namespace cpp
 }  // namespace aidl
 }  // namespace android
diff --git a/generate_cpp_unittest.cpp b/generate_cpp_unittest.cpp
index ce7c18c..d79f225 100644
--- a/generate_cpp_unittest.cpp
+++ b/generate_cpp_unittest.cpp
@@ -21,7 +21,6 @@
 
 #include "aidl.h"
 #include "aidl_language.h"
-#include "ast_cpp.h"
 #include "code_writer.h"
 #include "generate_cpp.h"
 #include "os.h"
@@ -47,7 +46,7 @@
     io_delegate_.SetFileContents(options_.InputFiles().at(0), file_contents_);
 
     vector<string> imported_files;
-    ImportResolver import_resolver{io_delegate_, options_.InputFiles().at(0), {"."}, {}};
+    ImportResolver import_resolver{io_delegate_, options_.InputFiles().at(0), {"."}};
     AidlError err = ::android::aidl::internals::load_and_validate_aidl(
         options_.InputFiles().front(), options_, io_delegate_, &typenames_, &imported_files);
 
@@ -62,36 +61,6 @@
     return defined_types.front().get()->AsInterface();
   }
 
-  AidlEnumDeclaration* ParseSingleEnumDeclaration() {
-    io_delegate_.SetFileContents(options_.InputFiles().at(0), file_contents_);
-
-    vector<string> imported_files;
-    AidlError err = ::android::aidl::internals::load_and_validate_aidl(
-        options_.InputFiles().front(), options_, io_delegate_, &typenames_, &imported_files);
-
-    if (err != AidlError::OK) {
-      return nullptr;
-    }
-
-    const auto& defined_types = typenames_.MainDocument().DefinedTypes();
-    EXPECT_EQ(1ul, defined_types.size());
-    EXPECT_NE(nullptr, defined_types.front().get()->AsEnumDeclaration());
-
-    return defined_types.front().get()->AsEnumDeclaration();
-  }
-
-  void Compare(Document* doc, const char* expected) {
-    string output;
-    doc->Write(CodeWriter::ForString(&output).get());
-
-    if (expected == output) {
-      return; // Success
-    }
-
-    test::PrintDiff(expected, output);
-    FAIL() << "Document contents did not match expected contents";
-  }
-
   const Options options_;
   const string file_contents_;
   FakeIoDelegate io_delegate_;
@@ -131,11 +100,10 @@
       StringPrintf("%s%c%s", kHeaderDir, OS_PATH_SEPARATOR,
                    kInterfaceHeaderRelPath);
   io_delegate_.AddBrokenFilePath(header_path);
-  ASSERT_FALSE(GenerateCpp(options_.OutputFile(), options_, typenames_, *interface, io_delegate_));
+  ASSERT_DEATH(GenerateCpp(options_.OutputFile(), options_, typenames_, *interface, io_delegate_),
+               "I/O Error!");
   // We should never attempt to write the C++ file if we fail writing headers.
   ASSERT_FALSE(io_delegate_.GetWrittenContents(kOutputPath, nullptr));
-  // We should remove partial results.
-  ASSERT_TRUE(io_delegate_.PathWasRemoved(header_path));
 }
 
 TEST_F(IoErrorHandlingTest, HandlesBadCppWrite) {
@@ -145,9 +113,8 @@
 
   // Simulate issues closing the cpp file.
   io_delegate_.AddBrokenFilePath(kOutputPath);
-  ASSERT_FALSE(GenerateCpp(options_.OutputFile(), options_, typenames_, *interface, io_delegate_));
-  // We should remove partial results.
-  ASSERT_TRUE(io_delegate_.PathWasRemoved(kOutputPath));
+  ASSERT_DEATH(GenerateCpp(options_.OutputFile(), options_, typenames_, *interface, io_delegate_),
+               "I/O Error!");
 }
 
 }  // namespace cpp
diff --git a/generate_java.cpp b/generate_java.cpp
index f3b7a93..a8dd232 100644
--- a/generate_java.cpp
+++ b/generate_java.cpp
@@ -44,15 +44,15 @@
 using android::aidl::java::CodeGeneratorContext;
 using android::aidl::java::ConstantValueDecorator;
 
-inline string getter_name(const AidlVariableDeclaration& variable) {
+inline string GetterName(const AidlVariableDeclaration& variable) {
   return "get" + variable.GetCapitalizedName();
 }
-inline string setter_name(const AidlVariableDeclaration& variable) {
+inline string SetterName(const AidlVariableDeclaration& variable) {
   return "set" + variable.GetCapitalizedName();
 }
 
 // clang-format off
-const map<string, string> contents_describers {
+const map<string, string> kContentsDescribers {
   {"FileDescriptor", R"(if (_v instanceof java.io.FileDescriptor) {
   return android.os.Parcelable.CONTENTS_FILE_DESCRIPTOR;
 })"},
@@ -69,8 +69,7 @@
   }
   return _mask;
 })"},
-  {"Array", R"(Class<?> _clazz = _v.getClass();
-if (_clazz.isArray() && _clazz.getComponentType() == Object.class) {
+  {"Array", R"(if (_v instanceof Object[]) {
   int _mask = 0;
   for (Object o : (Object[]) _v) {
     _mask |= describeContents(o);
@@ -85,7 +84,7 @@
   out.Indent();
   out << "if (_v == null) return 0;\n";
   for (const auto& d : describers) {
-    out << contents_describers.at(d) << "\n";
+    out << kContentsDescribers.at(d) << "\n";
   }
   out << "return 0;\n";
   out.Dedent();
@@ -97,7 +96,12 @@
 bool CanDescribeContents(const AidlTypeSpecifier& type, const AidlTypenames& types,
                          set<string>* describers) {
   if (type.IsArray()) {
-    if (CanDescribeContents(type.ArrayBase(), types, describers)) {
+    bool canDescribe = false;
+    type.ViewAsArrayBase([&](const AidlTypeSpecifier& base) {
+      canDescribe = CanDescribeContents(base, types, describers);
+    });
+
+    if (canDescribe) {
       describers->insert("Array");
       return true;
     }
@@ -168,7 +172,7 @@
     if (CanDescribeContents(f->GetType(), types, &describers)) {
       out << "case " << f->GetName() << ":\n";
       out.Indent();
-      out << "_mask |= describeContents(" << getter_name(*f) << "());\n";
+      out << "_mask |= describeContents(" << GetterName(*f) << "());\n";
       out << "break;\n";
       out.Dedent();
     }
@@ -183,7 +187,7 @@
 }
 
 void GenerateToString(CodeWriter& out, const AidlStructuredParcelable& parcel,
-                      const AidlTypenames& typenames) {
+                      const AidlTypenames& typenames, const Options& options) {
   out << "@Override\n";
   out << "public String toString() {\n";
   out.Indent();
@@ -195,6 +199,7 @@
         .typenames = typenames,
         .type = field->GetType(),
         .var = field->GetName(),
+        .min_sdk_version = options.GetMinSdkVersion(),
     };
     out << "_aidl_sj.add(\"" << field->GetName() << ": \" + (";
     ToStringFor(ctx);
@@ -205,8 +210,8 @@
   out << "}\n";
 }
 
-void GenerateToString(CodeWriter& out, const AidlUnionDecl& parcel,
-                      const AidlTypenames& typenames) {
+void GenerateToString(CodeWriter& out, const AidlUnionDecl& parcel, const AidlTypenames& typenames,
+                      const Options& options) {
   out << "@Override\n";
   out << "public String toString() {\n";
   out.Indent();
@@ -216,7 +221,8 @@
         .writer = out,
         .typenames = typenames,
         .type = field->GetType(),
-        .var = getter_name(*field) + "()",
+        .var = GetterName(*field) + "()",
+        .min_sdk_version = options.GetMinSdkVersion(),
     };
     out << "case " << field->GetName() << ": return \"" << parcel.GetCanonicalName() << "."
         << field->GetName() << "(\" + (";
@@ -290,11 +296,7 @@
 namespace java {
 
 std::string GenerateComments(const AidlCommentable& node) {
-  std::string comments = FormatCommentsForJava(node.GetComments());
-  if (!comments.empty() && comments.back() != '\n') {
-    comments += '\n';
-  }
-  return comments;
+  return FormatCommentsForJava(node.GetComments());
 }
 
 std::string GenerateAnnotations(const AidlNode& node) {
@@ -305,76 +307,9 @@
   return result;
 }
 
-bool generate_java_interface(const string& filename, const AidlInterface* iface,
-                             const AidlTypenames& typenames, const IoDelegate& io_delegate,
-                             const Options& options) {
-  auto cl = generate_binder_interface_class(iface, typenames, options);
-
-  std::unique_ptr<Document> document =
-      std::make_unique<Document>("" /* no comment */, iface->GetPackage(), std::move(cl));
-
-  CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
-  document->Write(code_writer.get());
-
-  return true;
-}
-
-bool generate_java_parcel(const std::string& filename, const AidlStructuredParcelable* parcel,
-                          const AidlTypenames& typenames, const IoDelegate& io_delegate) {
-  auto cl = generate_parcel_class(parcel, typenames);
-
-  std::unique_ptr<Document> document =
-      std::make_unique<Document>("" /* no comment */, parcel->GetPackage(), std::move(cl));
-
-  CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
-  document->Write(code_writer.get());
-
-  return true;
-}
-
-bool generate_java_enum_declaration(const std::string& filename,
-                                    const AidlEnumDeclaration* enum_decl,
-                                    const AidlTypenames& typenames, const IoDelegate& io_delegate) {
-  CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
-  generate_enum(code_writer, enum_decl, typenames);
-  return true;
-}
-
-bool generate_java_union_declaration(const std::string& filename, const AidlUnionDecl* decl,
-                                     const AidlTypenames& typenames,
-                                     const IoDelegate& io_delegate) {
-  CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
-  generate_union(*code_writer, decl, typenames);
-  return true;
-}
-
-bool generate_java(const std::string& filename, const AidlDefinedType* defined_type,
-                   const AidlTypenames& typenames, const IoDelegate& io_delegate,
-                   const Options& options) {
-  if (const AidlStructuredParcelable* parcelable = defined_type->AsStructuredParcelable();
-      parcelable != nullptr) {
-    return generate_java_parcel(filename, parcelable, typenames, io_delegate);
-  }
-
-  if (const AidlEnumDeclaration* enum_decl = defined_type->AsEnumDeclaration();
-      enum_decl != nullptr) {
-    return generate_java_enum_declaration(filename, enum_decl, typenames, io_delegate);
-  }
-
-  if (const AidlInterface* interface = defined_type->AsInterface(); interface != nullptr) {
-    return generate_java_interface(filename, interface, typenames, io_delegate, options);
-  }
-
-  if (const AidlUnionDecl* union_decl = defined_type->AsUnionDeclaration(); union_decl != nullptr) {
-    return generate_java_union_declaration(filename, union_decl, typenames, io_delegate);
-  }
-
-  AIDL_FATAL(defined_type) << "Unrecognized type sent for Java generation.";
-  return false;
-}
-
-std::unique_ptr<android::aidl::java::Class> generate_parcel_class(
-    const AidlStructuredParcelable* parcel, const AidlTypenames& typenames) {
+std::unique_ptr<android::aidl::java::Class> GenerateParcelableClass(
+    const AidlStructuredParcelable* parcel, const AidlTypenames& typenames,
+    const Options& options) {
   auto parcel_class = std::make_unique<Class>();
   parcel_class->comment = GenerateComments(*parcel);
   parcel_class->modifiers = PUBLIC;
@@ -382,6 +317,9 @@
   parcel_class->type = parcel->GetCanonicalName();
   parcel_class->interfaces.push_back("android.os.Parcelable");
   parcel_class->annotations = JavaAnnotationsFor(*parcel);
+  if (parcel->GetParentType()) {
+    parcel_class->modifiers |= STATIC;
+  }
 
   if (parcel->IsGeneric()) {
     parcel_class->type += "<" + base::Join(parcel->GetTypeParameters(), ",") + ">";
@@ -396,12 +334,12 @@
     if (variable->GetType().GetName() == "ParcelableHolder" || parcel->IsJavaOnlyImmutable()) {
       out << "final ";
     }
-    out << JavaSignatureOf(variable->GetType(), typenames) << " " << variable->GetName();
+    out << JavaSignatureOf(variable->GetType()) << " " << variable->GetName();
     if (!parcel->IsJavaOnlyImmutable() && variable->GetDefaultValue()) {
       out << " = " << variable->ValueString(ConstantValueDecorator);
     } else if (variable->GetType().GetName() == "ParcelableHolder") {
       out << std::boolalpha;
-      out << " = new " << JavaSignatureOf(variable->GetType(), typenames) << "(";
+      out << " = new " << JavaSignatureOf(variable->GetType()) << "(";
       if (parcel->IsVintfStability()) {
         out << "android.os.Parcelable.PARCELABLE_STABILITY_VINTF";
       } else {
@@ -423,15 +361,13 @@
 
     out.str("");
     for (const auto& variable : parcel->GetFields()) {
-      out << "private " << JavaSignatureOf(variable->GetType(), typenames) << " "
-          << variable->GetName();
+      out << "private " << JavaSignatureOf(variable->GetType()) << " " << variable->GetName();
       if (variable->GetDefaultValue()) {
         out << " = " << variable->ValueString(ConstantValueDecorator);
       }
       out << ";\n";
-      out << "public Builder " << setter_name(*variable) << "("
-          << JavaSignatureOf(variable->GetType(), typenames) << " " << variable->GetName()
-          << ") {\n"
+      out << "public Builder " << SetterName(*variable) << "("
+          << JavaSignatureOf(variable->GetType()) << " " << variable->GetName() << ") {\n"
           << "  "
           << "this." << variable->GetName() << " = " << variable->GetName() << ";\n"
           << "  return this;\n"
@@ -499,6 +435,7 @@
         .type = field->GetType(),
         .parcel = parcel_variable->name,
         .var = field->GetName(),
+        .min_sdk_version = options.GetMinSdkVersion(),
         .is_return_value = false,
     };
     WriteToParcelFor(context);
@@ -522,8 +459,8 @@
     constructor->name = parcel->GetName();
     constructor->statements = std::make_shared<StatementBlock>();
     for (const auto& field : parcel->GetFields()) {
-      constructor->parameters.push_back(std::make_shared<Variable>(
-          JavaSignatureOf(field->GetType(), typenames), field->GetName()));
+      constructor->parameters.push_back(
+          std::make_shared<Variable>(JavaSignatureOf(field->GetType()), field->GetName()));
       out.str("");
 
       out << "this." << field->GetName() << " = ";
@@ -566,7 +503,8 @@
   out << "int _aidl_start_pos = _aidl_parcel.dataPosition();\n"
       << "int _aidl_parcelable_size = _aidl_parcel.readInt();\n"
       << "try {\n"
-      << "  if (_aidl_parcelable_size < 0) return";
+      << "  if (_aidl_parcelable_size < 4) throw new "
+         "android.os.BadParcelableException(\"Parcelable too small\");";
   if (parcel->IsJavaOnlyImmutable()) {
     out << " " << builder_variable << ".build()";
   }
@@ -597,16 +535,17 @@
         .type = field->GetType(),
         .parcel = parcel_variable->name,
         .var = field_variable_name,
+        .min_sdk_version = options.GetMinSdkVersion(),
         .is_classloader_created = &is_classloader_created,
     };
     context.writer.Indent();
     if (parcel->IsJavaOnlyImmutable()) {
-      context.writer.Write("%s %s;\n", JavaSignatureOf(field->GetType(), typenames).c_str(),
+      context.writer.Write("%s %s;\n", JavaSignatureOf(field->GetType()).c_str(),
                            field_variable_name.c_str());
     }
     CreateFromParcelFor(context);
     if (parcel->IsJavaOnlyImmutable()) {
-      context.writer.Write("%s.%s(%s);\n", builder_variable.c_str(), setter_name(*field).c_str(),
+      context.writer.Write("%s.%s(%s);\n", builder_variable.c_str(), SetterName(*field).c_str(),
                            field_variable_name.c_str());
     }
     writer->Close();
@@ -630,12 +569,12 @@
   parcel_class->elements.push_back(read_or_create_method);
 
   string constants;
-  generate_constant_declarations(*CodeWriter::ForString(&constants), *parcel);
+  GenerateConstantDeclarations(*CodeWriter::ForString(&constants), *parcel);
   parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(constants));
 
   if (parcel->JavaDerive("toString")) {
     string to_string;
-    GenerateToString(*CodeWriter::ForString(&to_string), *parcel, typenames);
+    GenerateToString(*CodeWriter::ForString(&to_string), *parcel, typenames, options);
     parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(to_string));
   }
 
@@ -650,50 +589,54 @@
                                      typenames);
   parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(describe_contents));
 
+  // all the nested types
+  string code;
+  auto writer = CodeWriter::ForString(&code);
+  for (const auto& nested : parcel->GetNestedTypes()) {
+    GenerateClass(*writer, *nested, typenames, options);
+  }
+  GenerateParcelHelpers(*writer, *parcel, options);
+  writer->Close();
+  parcel_class->elements.push_back(std::make_shared<LiteralClassElement>(code));
+
   return parcel_class;
 }
 
-void generate_enum(const CodeWriterPtr& code_writer, const AidlEnumDeclaration* enum_decl,
-                   const AidlTypenames& typenames) {
-  code_writer->Write(
-      "/*\n"
-      " * This file is auto-generated.  DO NOT MODIFY.\n"
-      " */\n");
-
-  code_writer->Write("package %s;\n", enum_decl->GetPackage().c_str());
-  (*code_writer) << GenerateComments(*enum_decl);
-  (*code_writer) << GenerateAnnotations(*enum_decl);
-  code_writer->Write("public @interface %s {\n", enum_decl->GetName().c_str());
-  code_writer->Indent();
-  for (const auto& enumerator : enum_decl->GetEnumerators()) {
-    (*code_writer) << GenerateComments(*enumerator);
-    (*code_writer) << GenerateAnnotations(*enumerator);
-    code_writer->Write(
-        "public static final %s %s = %s;\n",
-        JavaSignatureOf(enum_decl->GetBackingType(), typenames).c_str(),
-        enumerator->GetName().c_str(),
-        enumerator->ValueString(enum_decl->GetBackingType(), ConstantValueDecorator).c_str());
+void GenerateEnumClass(CodeWriter& out, const AidlEnumDeclaration& enum_decl) {
+  out << GenerateComments(enum_decl);
+  out << GenerateAnnotations(enum_decl);
+  out << "public ";
+  if (enum_decl.GetParentType()) {
+    out << "static ";
   }
-  code_writer->Dedent();
-  code_writer->Write("}\n");
+  out << "@interface " << enum_decl.GetName() << " {\n";
+  out.Indent();
+  for (const auto& enumerator : enum_decl.GetEnumerators()) {
+    out << GenerateComments(*enumerator);
+    out << GenerateAnnotations(*enumerator);
+    out << fmt::format("public static final {} {} = {};\n",
+                       JavaSignatureOf(enum_decl.GetBackingType()), enumerator->GetName(),
+                       enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator));
+  }
+  out.Dedent();
+  out << "}\n";
 }
 
-void generate_union(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypenames& typenames) {
+void GenerateUnionClass(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypenames& typenames,
+                        const Options& options) {
   const string tag_type = "int";
-  const AidlTypeSpecifier tag_type_specifier(AIDL_LOCATION_HERE, tag_type, false /* isArray */,
-                                             nullptr /* type_params */, Comments{});
+  auto tag_type_specifier =
+      typenames.MakeResolvedType(AIDL_LOCATION_HERE, tag_type, /* isArray */ false);
   const string clazz = decl->GetName();
 
-  out << "/*\n";
-  out << " * This file is auto-generated.  DO NOT MODIFY.\n";
-  out << " */\n";
-
-  out << "package " + decl->GetPackage() + ";\n";
-  out << "\n";
   out << GenerateComments(*decl);
   out << GenerateAnnotations(*decl);
 
-  out << "public final class " + clazz + " implements android.os.Parcelable {\n";
+  out << "public ";
+  if (decl->GetParentType()) {
+    out << "static ";
+  }
+  out << "final class " + clazz + " implements android.os.Parcelable {\n";
   out.Indent();
 
   size_t tag_index = 0;
@@ -712,13 +655,14 @@
 
   AIDL_FATAL_IF(decl->GetFields().empty(), *decl) << "Union '" << clazz << "' is empty.";
   const auto& first_field = decl->GetFields()[0];
-  const auto& first_type = JavaSignatureOf(first_field->GetType(), typenames);
+  const auto& first_type = JavaSignatureOf(first_field->GetType());
   const auto& first_value = first_field->ValueString(ConstantValueDecorator);
 
   // default ctor() inits with first member's default value
   out << "public " + clazz + "() {\n";
   out.Indent();
-  out << first_type + " _value = " << (first_value.empty() ? "null" : first_value) << ";\n";
+  out << first_type + " _value = "
+      << (first_value.empty() ? DefaultJavaValueOf(first_field->GetType()) : first_value) << ";\n";
   out << "this._tag = " << first_field->GetName() << ";\n";
   out << "this._value = _value;\n";
   out.Dedent();
@@ -751,7 +695,7 @@
     out << "// " + variable->Signature() + ";\n\n";
 
     auto var_name = variable->GetName();
-    auto var_type = JavaSignatureOf(variable->GetType(), typenames);
+    auto var_type = JavaSignatureOf(variable->GetType());
 
     // value ctor
     out << GenerateComments(*variable);
@@ -766,7 +710,7 @@
     if (variable->GetType().IsGeneric()) {
       out << "@SuppressWarnings(\"unchecked\")\n";
     }
-    out << "public " + var_type + " " + getter_name(*variable) + "() {\n";
+    out << "public " + var_type + " " + GetterName(*variable) + "() {\n";
     out.Indent();
     out << "_assertTag(" + var_name + ");\n";
     out << "return (" + var_type + ") _value;\n";
@@ -775,7 +719,7 @@
 
     // setter
     if (!decl->IsJavaOnlyImmutable()) {
-      out << "public void " + setter_name(*variable) + "(" + var_type + " _value) {\n";
+      out << "public void " + SetterName(*variable) + "(" + var_type + " _value) {\n";
       out.Indent();
       out << "_set(" + var_name + ", _value);\n";
       out.Dedent();
@@ -815,6 +759,7 @@
         .type = type,
         .parcel = parcel,
         .var = name,
+        .min_sdk_version = options.GetMinSdkVersion(),
         .is_return_value = false,
     };
     WriteToParcelFor(context);
@@ -825,12 +770,12 @@
   out << "@Override\n";
   out << "public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag) {\n";
   out.Indent();
-  out << write_to_parcel(tag_type_specifier, "_tag", "_aidl_parcel");
+  out << write_to_parcel(*tag_type_specifier, "_tag", "_aidl_parcel");
   out << "switch (_tag) {\n";
   for (const auto& variable : decl->GetFields()) {
     out << "case " + variable->GetName() + ":\n";
     out.Indent();
-    out << write_to_parcel(variable->GetType(), getter_name(*variable) + "()", "_aidl_parcel");
+    out << write_to_parcel(variable->GetType(), GetterName(*variable) + "()", "_aidl_parcel");
     out << "break;\n";
     out.Dedent();
   }
@@ -850,6 +795,7 @@
         .type = type,
         .parcel = parcel,
         .var = name,
+        .min_sdk_version = options.GetMinSdkVersion(),
         .is_classloader_created = &is_classloader_created,
     };
     CreateFromParcelFor(context);
@@ -867,11 +813,11 @@
   }
   out.Indent();
   out << tag_type + " _aidl_tag;\n";
-  out << read_from_parcel(tag_type_specifier, "_aidl_tag", "_aidl_parcel");
+  out << read_from_parcel(*tag_type_specifier, "_aidl_tag", "_aidl_parcel");
   out << "switch (_aidl_tag) {\n";
   for (const auto& variable : decl->GetFields()) {
     auto var_name = variable->GetName();
-    auto var_type = JavaSignatureOf(variable->GetType(), typenames);
+    auto var_type = JavaSignatureOf(variable->GetType());
     out << "case " + var_name + ": {\n";
     out.Indent();
     out << var_type + " _aidl_value;\n";
@@ -889,12 +835,12 @@
   out.Dedent();
   out << "}\n\n";
 
-  generate_constant_declarations(out, *decl);
+  GenerateConstantDeclarations(out, *decl);
 
   GenerateParcelableDescribeContents(out, *decl, typenames);
   out << "\n";
   if (decl->JavaDerive("toString")) {
-    GenerateToString(out, *decl, typenames);
+    GenerateToString(out, *decl, typenames, options);
   }
 
   if (decl->JavaDerive("equals")) {
@@ -930,6 +876,12 @@
     out << "}\n";
   }
 
+  // all the nested types
+  for (const auto& nested : decl->GetNestedTypes()) {
+    GenerateClass(out, *nested, typenames, options);
+  }
+  GenerateParcelHelpers(out, *decl, options);
+
   out.Dedent();
   out << "}\n";
 }
@@ -938,7 +890,7 @@
   return method.PrintLocation();
 }
 
-std::string generate_java_unsupportedappusage_parameters(const AidlAnnotation& a) {
+std::string GenerateJavaUnsupportedAppUsageParameters(const AidlAnnotation& a) {
   const std::map<std::string, std::string> params = a.AnnotationParams(ConstantValueDecorator);
   std::vector<string> parameters_decl;
   for (const auto& name_and_param : params) {
@@ -950,7 +902,7 @@
   return "(" + Join(parameters_decl, ", ") + ")";
 }
 
-std::vector<std::string> generate_java_annotations(const AidlAnnotatable& a) {
+std::vector<std::string> GenerateJavaAnnotations(const AidlAnnotatable& a) {
   std::vector<std::string> result;
   if (a.IsHide()) {
     result.emplace_back("@android.annotation.Hide");
@@ -959,21 +911,35 @@
   const AidlAnnotation* unsupported_app_usage = a.UnsupportedAppUsage();
   if (unsupported_app_usage != nullptr) {
     result.emplace_back("@android.compat.annotation.UnsupportedAppUsage" +
-                        generate_java_unsupportedappusage_parameters(*unsupported_app_usage));
+                        GenerateJavaUnsupportedAppUsageParameters(*unsupported_app_usage));
   }
 
   for (const auto& annotation : a.GetAnnotations()) {
-    if (annotation.GetType() == AidlAnnotation::Type::JAVA_PASSTHROUGH) {
-      result.emplace_back(annotation.ParamValue<std::string>("annotation").value());
+    if (annotation->GetType() == AidlAnnotation::Type::JAVA_PASSTHROUGH) {
+      result.emplace_back(annotation->ParamValue<std::string>("annotation").value());
+    }
+    if (annotation->GetType() == AidlAnnotation::Type::JAVA_SUPPRESS_LINT) {
+      std::vector<std::string> values;
+      for (const auto& [name, value] : annotation->AnnotationParams(ConstantValueDecorator)) {
+        values.emplace_back(name + " = " + value);
+      }
+      result.emplace_back("@android.annotation.SuppressLint(" + Join(values, ", ") + ")");
     }
   }
 
+  if (auto enforce_expr = a.EnforceExpression(); enforce_expr) {
+    result.emplace_back("@android.annotation.EnforcePermission(" +
+                        android::aidl::perm::AsJavaAnnotation(*enforce_expr.get()) + ")");
+  } else if (a.IsPermissionNone()) {
+    result.emplace_back("@android.annotation.RequiresNoPermission");
+  }  // TODO: Add annoation for @PermissionManuallyEnforced
+
   return result;
 }
 
 struct JavaAnnotationsVisitor : AidlVisitor {
   JavaAnnotationsVisitor(std::vector<std::string>& result) : result(result) {}
-  void Visit(const AidlTypeSpecifier& t) override { result = generate_java_annotations(t); }
+  void Visit(const AidlTypeSpecifier& t) override { result = GenerateJavaAnnotations(t); }
   void Visit(const AidlInterface& t) override { ForDefinedType(t); }
   void Visit(const AidlParcelable& t) override { ForDefinedType(t); }
   void Visit(const AidlStructuredParcelable& t) override { ForDefinedType(t); }
@@ -985,14 +951,14 @@
   std::vector<std::string>& result;
 
   void ForDefinedType(const AidlDefinedType& t) {
-    result = generate_java_annotations(t);
+    result = GenerateJavaAnnotations(t);
     if (t.IsDeprecated()) {
       result.push_back("@Deprecated");
     }
   }
   template <typename Member>
   void ForMember(const Member& t) {
-    result = generate_java_annotations(t.GetType());
+    result = GenerateJavaAnnotations(t.GetType());
     if (t.IsDeprecated()) {
       result.push_back("@Deprecated");
     }
@@ -1006,6 +972,43 @@
   return result;
 }
 
+void GenerateClass(CodeWriter& out, const AidlDefinedType& defined_type, const AidlTypenames& types,
+                   const Options& options) {
+  // Generate file header (comments and package) only if it's a root type.
+  if (defined_type.GetParentType() == nullptr) {
+    out << "/*\n";
+    out << " * This file is auto-generated.  DO NOT MODIFY.\n";
+    out << " */\n";
+    if (const auto pkg = defined_type.GetPackage(); !pkg.empty()) {
+      out << "package " << pkg << ";\n";
+    }
+  }
+
+  if (const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
+      parcelable != nullptr) {
+    GenerateParcelableClass(parcelable, types, options)->Write(&out);
+  } else if (const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
+             enum_decl != nullptr) {
+    GenerateEnumClass(out, *enum_decl);
+  } else if (const AidlInterface* interface = defined_type.AsInterface(); interface != nullptr) {
+    GenerateInterfaceClass(interface, types, options)->Write(&out);
+  } else if (const AidlUnionDecl* union_decl = defined_type.AsUnionDeclaration();
+             union_decl != nullptr) {
+    GenerateUnionClass(out, union_decl, types, options);
+  } else {
+    AIDL_FATAL(defined_type) << "Unrecognized type sent for Java generation.";
+  }
+}
+
+// In Java, there's 1:1 mapping between AIDL type and Java type. So we generate a single file for
+// the type.
+void GenerateJava(const std::string& filename, const Options& options, const AidlTypenames& types,
+                  const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
+  CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
+  GenerateClass(*code_writer, defined_type, types, options);
+  AIDL_FATAL_IF(!code_writer->Close(), defined_type) << "I/O Error!";
+}
+
 }  // namespace java
 }  // namespace aidl
 }  // namespace android
diff --git a/generate_java.h b/generate_java.h
index b3cfd6f..bfa2376 100644
--- a/generate_java.h
+++ b/generate_java.h
@@ -27,22 +27,18 @@
 namespace aidl {
 namespace java {
 
-bool generate_java(const std::string& filename, const AidlDefinedType* iface,
-                   const AidlTypenames& typenames, const IoDelegate& io_delegate,
+void GenerateJava(const std::string& filename, const Options& options,
+                  const AidlTypenames& typenames, const AidlDefinedType& defined_type,
+                  const IoDelegate& io_delegate);
+
+void GenerateClass(CodeWriter& out, const AidlDefinedType& defined_type, const AidlTypenames& types,
                    const Options& options);
 
-std::unique_ptr<android::aidl::java::Class> generate_binder_interface_class(
-    const AidlInterface* iface, const AidlTypenames& typenames, const Options& options);
+std::unique_ptr<android::aidl::java::Class> GenerateInterfaceClass(const AidlInterface* iface,
+                                                                   const AidlTypenames& typenames,
+                                                                   const Options& options);
 
-std::unique_ptr<android::aidl::java::Class> generate_parcel_class(
-    const AidlStructuredParcelable* parcel, const AidlTypenames& typenames);
-
-void generate_enum(const CodeWriterPtr& code_writer, const AidlEnumDeclaration* enum_decl,
-                   const AidlTypenames& typenames);
-
-void generate_union(CodeWriter& out, const AidlUnionDecl* decl, const AidlTypenames& typenames);
-
-void generate_constant_declarations(CodeWriter& out, const AidlDefinedType& type);
+void GenerateConstantDeclarations(CodeWriter& out, const AidlDefinedType& type);
 
 std::string GenerateComments(const AidlCommentable& node);
 
diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp
index fa1c14a..fa6ea46 100644
--- a/generate_java_binder.cpp
+++ b/generate_java_binder.cpp
@@ -16,10 +16,12 @@
 
 #include "aidl.h"
 #include "aidl_to_java.h"
+#include "aidl_typenames.h"
 #include "ast_java.h"
 #include "generate_java.h"
 #include "logging.h"
 #include "options.h"
+#include "parser.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -49,8 +51,8 @@
   using Variable = ::android::aidl::java::Variable;
 
   explicit VariableFactory(const std::string& base) : base_(base), index_(0) {}
-  std::shared_ptr<Variable> Get(const AidlTypeSpecifier& type, const AidlTypenames& typenames) {
-    auto v = std::make_shared<Variable>(JavaSignatureOf(type, typenames),
+  std::shared_ptr<Variable> Get(const AidlTypeSpecifier& type) {
+    auto v = std::make_shared<Variable>(JavaSignatureOf(type),
                                         StringPrintf("%s%d", base_.c_str(), index_));
     vars_.push_back(v);
     index_++;
@@ -94,12 +96,12 @@
   size_t all_method_count;
 
   // Finish generation. This will add a default case to the switch.
-  void finish();
+  void Finish();
 
-  std::shared_ptr<Expression> get_transact_descriptor(const AidlMethod* method);
+  std::shared_ptr<Expression> GetTransactDescriptor(const AidlMethod* method);
 
  private:
-  void make_as_interface(const AidlInterface* interfaceType);
+  void MakeAsInterface(const AidlInterface* interfaceType);
 
   std::shared_ptr<Variable> transact_descriptor;
   const Options& options_;
@@ -138,7 +140,7 @@
   this->elements.push_back(ctor);
 
   // asInterface
-  make_as_interface(interfaceType);
+  MakeAsInterface(interfaceType);
 
   // asBinder
   auto asBinder = std::make_shared<Method>();
@@ -199,7 +201,7 @@
   this->transact_switch_user = std::make_shared<SwitchStatement>(this->transact_code);
 }
 
-void StubClass::finish() {
+void StubClass::Finish() {
   auto default_case = std::make_shared<Case>();
 
   auto superCall = std::make_shared<MethodCall>(
@@ -207,8 +209,23 @@
       std::vector<std::shared_ptr<Expression>>{this->transact_code, this->transact_data,
                                                this->transact_reply, this->transact_flags});
   default_case->statements->Add(std::make_shared<ReturnStatement>(superCall));
+
+  auto case_count = transact_switch_user->cases.size();
   transact_switch_user->cases.push_back(default_case);
 
+  // Interface token validation is done for user-defined transactions.
+  if (case_count > 0) {
+    auto ifStatement = std::make_shared<IfStatement>();
+    ifStatement->expression = std::make_shared<LiteralExpression>(
+        "code >= android.os.IBinder.FIRST_CALL_TRANSACTION && "
+        "code <= android.os.IBinder.LAST_CALL_TRANSACTION");
+    ifStatement->statements = std::make_shared<StatementBlock>();
+    ifStatement->statements->Add(std::make_shared<MethodCall>(
+        this->transact_data, "enforceInterface",
+        std::vector<std::shared_ptr<Expression>>{this->GetTransactDescriptor(nullptr)}));
+    transact_statements->Add(ifStatement);
+  }
+
   // Meta transactions are looked up prior to user-defined transactions.
   transact_statements->Add(this->transact_switch_meta);
   transact_statements->Add(this->transact_switch_user);
@@ -222,12 +239,18 @@
     code_switch_default_case->statements->Add(std::make_shared<ReturnStatement>(NULL_VALUE));
     this->code_to_method_name_switch->cases.push_back(code_switch_default_case);
   }
+
+  // There will be at least one statement for the default, but if we emit a
+  // return true after that default, it will be unreachable.
+  if (case_count > 0) {
+    transact_statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
+  }
 }
 
 // The the expression for the interface's descriptor to be used when
 // generating code for the given method. Null is acceptable for method
 // and stands for synthetic cases.
-std::shared_ptr<Expression> StubClass::get_transact_descriptor(const AidlMethod* method) {
+std::shared_ptr<Expression> StubClass::GetTransactDescriptor(const AidlMethod* method) {
   if (transact_outline) {
     if (method != nullptr) {
       // When outlining, each outlined method needs its own literal.
@@ -253,7 +276,7 @@
   return transact_descriptor;
 }
 
-void StubClass::make_as_interface(const AidlInterface* interfaceType) {
+void StubClass::MakeAsInterface(const AidlInterface* interfaceType) {
   auto obj = std::make_shared<Variable>("android.os.IBinder", "obj");
 
   auto m = std::make_shared<Method>();
@@ -355,34 +378,20 @@
 ProxyClass::~ProxyClass() {}
 
 // =================================================
-static void generate_new_array(const AidlTypeSpecifier& type, const AidlTypenames& typenames,
-                               std::shared_ptr<StatementBlock> addTo, std::shared_ptr<Variable> v,
-                               std::shared_ptr<Variable> parcel) {
-  auto len = std::make_shared<Variable>("int", v->name + "_length");
-  addTo->Add(
-      std::make_shared<VariableDeclaration>(len, std::make_shared<MethodCall>(parcel, "readInt")));
-  auto lencheck = std::make_shared<IfStatement>();
-  lencheck->expression =
-      std::make_shared<Comparison>(len, "<", std::make_shared<LiteralExpression>("0"));
-  lencheck->statements->Add(std::make_shared<Assignment>(v, NULL_VALUE));
-  lencheck->elseif = std::make_shared<IfStatement>();
-  lencheck->elseif->statements->Add(std::make_shared<Assignment>(
-      v, std::make_shared<NewArrayExpression>(InstantiableJavaSignatureOf(type, typenames), len)));
-  addTo->Add(lencheck);
-}
 
-static void generate_write_to_parcel(const AidlTypeSpecifier& type,
-                                     std::shared_ptr<StatementBlock> addTo,
-                                     std::shared_ptr<Variable> v, std::shared_ptr<Variable> parcel,
-                                     bool is_return_value, const AidlTypenames& typenames) {
+static void GenerateWriteToParcel(std::shared_ptr<StatementBlock> addTo,
+                                  const AidlTypenames& typenames, const AidlTypeSpecifier& type,
+                                  const std::string& parcel, const std::string& var,
+                                  uint32_t min_sdk_version, bool is_return_value) {
   string code;
   CodeWriterPtr writer = CodeWriter::ForString(&code);
   CodeGeneratorContext context{
       .writer = *(writer.get()),
       .typenames = typenames,
       .type = type,
-      .parcel = parcel->name,
-      .var = v->name,
+      .parcel = parcel,
+      .var = var,
+      .min_sdk_version = min_sdk_version,
       .is_return_value = is_return_value,
   };
   WriteToParcelFor(context);
@@ -390,7 +399,7 @@
   addTo->Add(std::make_shared<LiteralStatement>(code));
 }
 
-void generate_constant_declarations(CodeWriter& out, const AidlDefinedType& type) {
+void GenerateConstantDeclarations(CodeWriter& out, const AidlDefinedType& type) {
   for (const auto& constant : type.GetConstantDeclarations()) {
     const AidlTypeSpecifier& type = constant->GetType();
     out << GenerateComments(*constant);
@@ -400,17 +409,16 @@
   }
 }
 
-static std::shared_ptr<Method> generate_interface_method(const AidlMethod& method,
-                                                         const AidlTypenames& typenames) {
+static std::shared_ptr<Method> GenerateInterfaceMethod(const AidlMethod& method) {
   auto decl = std::make_shared<Method>();
   decl->comment = GenerateComments(method);
   decl->modifiers = PUBLIC;
-  decl->returnType = JavaSignatureOf(method.GetType(), typenames);
+  decl->returnType = JavaSignatureOf(method.GetType());
   decl->name = method.GetName();
   decl->annotations = JavaAnnotationsFor(method);
 
   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
-    auto var = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
+    auto var = std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName());
     var->annotations = JavaAnnotationsFor(arg->GetType());
     decl->parameters.push_back(var);
   }
@@ -420,12 +428,102 @@
   return decl;
 }
 
-static void generate_stub_code(const AidlInterface& iface, const AidlMethod& method, bool oneway,
-                               std::shared_ptr<Variable> transact_data,
-                               std::shared_ptr<Variable> transact_reply,
-                               const AidlTypenames& typenames,
-                               std::shared_ptr<StatementBlock> statement_block,
-                               std::shared_ptr<StubClass> stubClass, const Options& options) {
+// Visitor for the permission declared in the @EnforcePermission annotation.
+struct PermissionVisitor {
+  shared_ptr<Expression> operator()(const perm::AllOf& quantifier) {
+    std::shared_ptr<Expression> result;
+    for (const auto& operand : quantifier.operands) {
+      auto expr = (*this)(operand);
+      if (result) {
+        result = std::make_shared<Comparison>(result, "&&", expr);
+      } else {
+        result = expr;
+      }
+    }
+    return result;
+  }
+
+  shared_ptr<Expression> operator()(const perm::AnyOf& quantifier) {
+    std::shared_ptr<Expression> result;
+    for (const auto& operand : quantifier.operands) {
+      auto expr = (*this)(operand);
+      if (result) {
+        result = std::make_shared<Comparison>(result, "||", expr);
+      } else {
+        result = expr;
+      }
+    }
+    return result;
+  }
+
+  shared_ptr<Expression> operator()(const std::string& permission) {
+    auto attributionSource =
+        std::string("new android.content.AttributionSource(getCallingUid(), null, null)");
+    for (size_t i = 0; i < method_.GetArguments().size(); i++) {
+      const auto& arg = method_.GetArguments()[i];
+      if (arg->GetType().GetName() == "android.content.AttributionSource") {
+        attributionSource = android::base::StringPrintf("_arg%zu", i);
+        break;
+      }
+    }
+    auto checkPermission = std::make_shared<MethodCall>(
+        THIS_VALUE, "permissionCheckerWrapper",
+        std::vector<std::shared_ptr<Expression>>{
+            std::make_shared<LiteralExpression>("android.Manifest.permission." + permission),
+            std::make_shared<MethodCall>(THIS_VALUE, "getCallingPid"),
+            std::make_shared<LiteralExpression>(attributionSource)});
+    return checkPermission;
+  }
+
+  const AidlMethod& method_;
+};
+
+static void GeneratePermissionWrapper(Class* stubClass) {
+  // TODO(b/208707422) avoid generating platform-specific API calls.
+  std::string permissionCheckerWrapperCode =
+      "private boolean permissionCheckerWrapper(\n"
+      "    String permission, int pid, android.content.AttributionSource attributionSource) {\n"
+      "  android.content.Context ctx =\n"
+      "      android.app.ActivityThread.currentActivityThread().getSystemContext();\n"
+      "  return (android.content.PermissionChecker.checkPermissionForDataDelivery(\n"
+      "          ctx, permission, pid, attributionSource, \"\" /*message*/) ==\n"
+      "      android.content.PermissionChecker.PERMISSION_GRANTED);\n"
+      "}\n";
+  auto permissionCheckerWrapper =
+      std::make_shared<LiteralClassElement>(permissionCheckerWrapperCode);
+  stubClass->elements.push_back(permissionCheckerWrapper);
+}
+
+static void GeneratePermissionCheck(const AidlMethod& method, const perm::Expression& expr,
+                                    std::shared_ptr<StatementBlock> addTo) {
+  auto ifstatement = std::make_shared<IfStatement>();
+  auto combinedExpr = std::visit(PermissionVisitor{method}, expr);
+  ifstatement->expression = std::make_shared<Comparison>(combinedExpr, "!=", TRUE_VALUE);
+  ifstatement->statements = std::make_shared<StatementBlock>();
+  ifstatement->statements->Add(std::make_shared<LiteralStatement>(
+      android::base::StringPrintf("throw new SecurityException(\"Access denied, requires: %s\");\n",
+                                  perm::AsJavaAnnotation(expr).c_str())));
+  addTo->Add(ifstatement);
+}
+
+static void GeneratePermissionChecks(const AidlInterface& iface, const AidlMethod& method,
+                                     std::shared_ptr<StatementBlock> addTo) {
+  auto ifacePermExpr = iface.EnforceExpression();
+  if (ifacePermExpr) {
+    GeneratePermissionCheck(method, *ifacePermExpr.get(), addTo);
+  }
+  auto methodPermExpr = method.GetType().EnforceExpression();
+  if (methodPermExpr) {
+    GeneratePermissionCheck(method, *methodPermExpr.get(), addTo);
+  }
+}
+
+static void GenerateStubCode(const AidlInterface& iface, const AidlMethod& method, bool oneway,
+                             std::shared_ptr<Variable> transact_data,
+                             std::shared_ptr<Variable> transact_reply,
+                             const AidlTypenames& typenames,
+                             std::shared_ptr<StatementBlock> statement_block,
+                             const Options& options) {
   // try and finally
   auto tryStatement = std::make_shared<TryStatement>();
   auto finallyStatement = std::make_shared<FinallyStatement>();
@@ -449,11 +547,6 @@
 
   auto realCall = std::make_shared<MethodCall>(THIS_VALUE, method.GetName());
 
-  // interface token validation is the very first thing we do
-  statements->Add(std::make_shared<MethodCall>(
-      transact_data, "enforceInterface",
-      std::vector<std::shared_ptr<Expression>>{stubClass->get_transact_descriptor(&method)}));
-
   // args
   VariableFactory stubArgs("_arg");
   {
@@ -461,36 +554,61 @@
     // at most once.
     bool is_classloader_created = false;
     for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
-      std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType(), typenames);
+      std::shared_ptr<Variable> v = stubArgs.Get(arg->GetType());
 
       statements->Add(std::make_shared<VariableDeclaration>(v));
 
+      string code;
+      CodeWriterPtr writer = CodeWriter::ForString(&code);
       if (arg->GetDirection() & AidlArgument::IN_DIR) {
-        string code;
-        CodeWriterPtr writer = CodeWriter::ForString(&code);
+        // "in/inout" parameter should be created from parcel.
         CodeGeneratorContext context{.writer = *(writer.get()),
                                      .typenames = typenames,
                                      .type = arg->GetType(),
                                      .parcel = transact_data->name,
                                      .var = v->name,
+                                     .min_sdk_version = options.GetMinSdkVersion(),
                                      .is_classloader_created = &is_classloader_created};
         CreateFromParcelFor(context);
-        writer->Close();
-        statements->Add(std::make_shared<LiteralStatement>(code));
       } else {
-        if (!arg->GetType().IsArray()) {
-          statements->Add(std::make_shared<Assignment>(
-              v, std::make_shared<NewExpression>(
-                     InstantiableJavaSignatureOf(arg->GetType(), typenames))));
+        // "out" parameter should be instantiated before calling the real impl.
+        string java_type = InstantiableJavaSignatureOf(arg->GetType());
+
+        if (arg->GetType().IsDynamicArray()) {
+          // dynamic array should be created with a passed length.
+          string var_length = v->name + "_length";
+          (*writer) << "int " << var_length << " = data.readInt();\n";
+          (*writer) << "if (" << var_length << " < 0) {\n";
+          (*writer) << "  " << v->name << " = null;\n";
+          (*writer) << "} else {\n";
+          (*writer) << "  " << v->name << " = new " << java_type << "[" << var_length << "];\n";
+          (*writer) << "}\n";
+        } else if (arg->GetType().IsFixedSizeArray()) {
+          // fixed-size array can be created with a known size
+          string dimensions;
+          for (auto dim : arg->GetType().GetFixedSizeArrayDimensions()) {
+            dimensions += "[" + std::to_string(dim) + "]";
+          }
+          (*writer) << v->name << " = new " << java_type << dimensions << ";\n";
         } else {
-          generate_new_array(arg->GetType(), typenames, statements, v, transact_data);
+          // otherwise, create a new instance with a default constructor
+          (*writer) << v->name << " = new " << java_type << "();\n";
         }
       }
+      writer->Close();
+      statements->Add(std::make_shared<LiteralStatement>(code));
 
       realCall->arguments.push_back(v);
     }
   }
 
+  // EOF check
+  if (!method.GetArguments().empty() && options.GetMinSdkVersion() >= 32u) {
+    statements->Add(std::make_shared<MethodCall>(transact_data, "enforceNoDataAvail"));
+  }
+
+  GeneratePermissionChecks(iface, method, statements);
+
   // the real call
   if (method.GetType().GetName() == "void") {
     statements->Add(realCall);
@@ -501,9 +619,8 @@
       statements->Add(ex);
     }
   } else {
-    auto _result =
-        std::make_shared<Variable>(JavaSignatureOf(method.GetType(), typenames), "_result");
-      statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
+    auto _result = std::make_shared<Variable>(JavaSignatureOf(method.GetType()), "_result");
+    statements->Add(std::make_shared<VariableDeclaration>(_result, realCall));
 
     if (!oneway) {
       // report that there were no exceptions
@@ -512,40 +629,38 @@
     }
 
     // marshall the return value
-    generate_write_to_parcel(method.GetType(), statements, _result, transact_reply, true,
-                             typenames);
+    GenerateWriteToParcel(statements, typenames, method.GetType(), transact_reply->name,
+                          _result->name, options.GetMinSdkVersion(), /*is_return_value=*/true);
   }
 
   // out parameters
   int i = 0;
   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
     std::shared_ptr<Variable> v = stubArgs.Get(i++);
-
     if (arg->GetDirection() & AidlArgument::OUT_DIR) {
-      generate_write_to_parcel(arg->GetType(), statements, v, transact_reply, true, typenames);
+      GenerateWriteToParcel(statements, typenames, arg->GetType(), transact_reply->name, v->name,
+                            options.GetMinSdkVersion(), /*is_return_value=*/true);
     }
   }
-
-  // return true
-  statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
 }
 
-static void generate_stub_case(const AidlInterface& iface, const AidlMethod& method,
-                               const std::string& transactCodeName, bool oneway,
-                               std::shared_ptr<StubClass> stubClass, const AidlTypenames& typenames,
-                               const Options& options) {
+static void GenerateStubCase(const AidlInterface& iface, const AidlMethod& method,
+                             const std::string& transactCodeName, bool oneway,
+                             std::shared_ptr<StubClass> stubClass, const AidlTypenames& typenames,
+                             const Options& options) {
   auto c = std::make_shared<Case>(transactCodeName);
 
-  generate_stub_code(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
-                     typenames, c->statements, stubClass, options);
+  GenerateStubCode(iface, method, oneway, stubClass->transact_data, stubClass->transact_reply,
+                   typenames, c->statements, options);
+  c->statements->Add(std::make_shared<BreakStatement>());
 
   stubClass->transact_switch_user->cases.push_back(c);
 }
 
-static void generate_stub_case_outline(const AidlInterface& iface, const AidlMethod& method,
-                                       const std::string& transactCodeName, bool oneway,
-                                       std::shared_ptr<StubClass> stubClass,
-                                       const AidlTypenames& typenames, const Options& options) {
+static void GenerateStubCaseOutline(const AidlInterface& iface, const AidlMethod& method,
+                                    const std::string& transactCodeName, bool oneway,
+                                    std::shared_ptr<StubClass> stubClass,
+                                    const AidlTypenames& typenames, const Options& options) {
   std::string outline_name = "onTransact$" + method.GetName() + "$";
   // Generate an "outlined" method with the actual code.
   {
@@ -561,8 +676,9 @@
     onTransact_case->exceptions.push_back("android.os.RemoteException");
     stubClass->elements.push_back(onTransact_case);
 
-    generate_stub_code(iface, method, oneway, transact_data, transact_reply, typenames,
-                       onTransact_case->statements, stubClass, options);
+    GenerateStubCode(iface, method, oneway, transact_data, transact_reply, typenames,
+                     onTransact_case->statements, options);
+    onTransact_case->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
   }
 
   // Generate the case dispatch.
@@ -579,29 +695,36 @@
   }
 }
 
-static std::shared_ptr<Method> generate_proxy_method(
-    const AidlInterface& iface, const AidlMethod& method, const std::string& transactCodeName,
-    bool oneway, std::shared_ptr<ProxyClass> proxyClass, const AidlTypenames& typenames,
-    const Options& options) {
+static std::shared_ptr<Method> GenerateProxyMethod(const AidlInterface& iface,
+                                                   const AidlMethod& method,
+                                                   const std::string& transactCodeName, bool oneway,
+                                                   std::shared_ptr<ProxyClass> proxyClass,
+                                                   const AidlTypenames& typenames,
+                                                   const Options& options) {
   auto proxy = std::make_shared<Method>();
   proxy->comment = GenerateComments(method);
   proxy->modifiers = PUBLIC | OVERRIDE;
-  proxy->returnType = JavaSignatureOf(method.GetType(), typenames);
+  proxy->returnType = JavaSignatureOf(method.GetType());
   proxy->name = method.GetName();
   proxy->statements = std::make_shared<StatementBlock>();
   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
     proxy->parameters.push_back(
-        std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
+        std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName()));
   }
   proxy->exceptions.push_back("android.os.RemoteException");
 
   // the parcels
   auto _data = std::make_shared<Variable>("android.os.Parcel", "_data");
-  proxy->statements->Add(std::make_shared<VariableDeclaration>(
-      _data, std::make_shared<MethodCall>("android.os.Parcel", "obtain")));
+  if (options.GenRpc()) {
+    proxy->statements->Add(std::make_shared<LiteralStatement>(
+        "android.os.Parcel _data = android.os.Parcel.obtain(asBinder());\n"));
+  } else {
+    proxy->statements->Add(std::make_shared<LiteralStatement>(
+        "android.os.Parcel _data = android.os.Parcel.obtain();\n"));
+  }
 
   if (iface.IsSensitiveData()) {
-    proxy->statements->Add(std::make_shared<LiteralStatement>("_data.markSensitive();"));
+    proxy->statements->Add(std::make_shared<LiteralStatement>("_data.markSensitive();\n"));
   }
 
   std::shared_ptr<Variable> _reply = nullptr;
@@ -641,9 +764,9 @@
 
   // the parameters
   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
-    auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName());
+    auto v = std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName());
     AidlArgument::Direction dir = arg->GetDirection();
-    if (dir == AidlArgument::OUT_DIR && arg->GetType().IsArray()) {
+    if (dir == AidlArgument::OUT_DIR && arg->GetType().IsDynamicArray()) {
       auto checklen = std::make_shared<IfStatement>();
       checklen->expression = std::make_shared<Comparison>(v, "==", NULL_VALUE);
       checklen->statements->Add(std::make_shared<MethodCall>(
@@ -655,8 +778,8 @@
           std::vector<std::shared_ptr<Expression>>{std::make_shared<FieldVariable>(v, "length")}));
       tryStatement->statements->Add(checklen);
     } else if (dir & AidlArgument::IN_DIR) {
-      generate_write_to_parcel(arg->GetType(), tryStatement->statements, v, _data, false,
-                               typenames);
+      GenerateWriteToParcel(tryStatement->statements, typenames, arg->GetType(), _data->name,
+                            v->name, options.GetMinSdkVersion(), /*is_return_value=*/false);
     }
   }
 
@@ -674,6 +797,12 @@
   auto _status = std::make_shared<Variable>("boolean", "_status");
   tryStatement->statements->Add(std::make_shared<VariableDeclaration>(_status, call));
 
+  // TODO(b/151102494): annotation is applied on the return type
+  if (method.GetType().IsPropagateAllowBlocking()) {
+    tryStatement->statements->Add(
+        std::make_shared<LiteralStatement>("_reply.setPropagateAllowBlocking();\n"));
+  }
+
   // If the transaction returns false, which means UNKNOWN_TRANSACTION, fall back to the local
   // method in the default impl, if set before. Otherwise, throw a RuntimeException if the interface
   // is versioned. We can't throw the exception for unversioned interface because that would be an
@@ -696,19 +825,24 @@
                                     Join(arg_names, ", ").c_str())));
     checkDefaultImpl->statements->Add(std::make_shared<LiteralStatement>("return;\n"));
   }
+
+  auto checkTransactionError = std::make_shared<IfStatement>();
+  checkTransactionError->expression = std::make_shared<LiteralExpression>("!_status");
+
+  if (iface.IsJavaDefault()) {
+    checkTransactionError->statements->Add(checkDefaultImpl);
+  }
+
   if (options.Version() > 0) {
-    checkDefaultImpl->elseif = std::make_shared<IfStatement>();
-    checkDefaultImpl->elseif->statements->Add(
+    checkTransactionError->statements->Add(
         std::make_shared<LiteralStatement>(android::base::StringPrintf(
             "throw new android.os.RemoteException(\"Method %s is unimplemented.\");\n",
             method.GetName().c_str())));
   }
 
-  auto checkTransactionError = std::make_shared<IfStatement>();
-  checkTransactionError->expression = std::make_shared<LiteralExpression>("!_status");
-  checkTransactionError->statements->Add(checkDefaultImpl);
-
-  tryStatement->statements->Add(checkTransactionError);
+  if (iface.IsJavaDefault() || options.Version() > 0) {
+    tryStatement->statements->Add(checkTransactionError);
+  }
 
   // throw back exceptions.
   if (_reply) {
@@ -729,6 +863,7 @@
                                    .type = method.GetType(),
                                    .parcel = _reply->name,
                                    .var = _result->name,
+                                   .min_sdk_version = options.GetMinSdkVersion(),
                                    .is_classloader_created = &is_classloader_created};
       CreateFromParcelFor(context);
       writer->Close();
@@ -745,6 +880,7 @@
                                      .type = arg->GetType(),
                                      .parcel = _reply->name,
                                      .var = arg->GetName(),
+                                     .min_sdk_version = options.GetMinSdkVersion(),
                                      .is_classloader_created = &is_classloader_created};
         ReadFromParcelFor(context);
         writer->Close();
@@ -770,10 +906,10 @@
   return proxy;
 }
 
-static void generate_methods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
-                             std::shared_ptr<StubClass> stubClass,
-                             std::shared_ptr<ProxyClass> proxyClass, int index,
-                             const AidlTypenames& typenames, const Options& options) {
+static void GenerateMethods(const AidlInterface& iface, const AidlMethod& method, Class* interface,
+                            std::shared_ptr<StubClass> stubClass,
+                            std::shared_ptr<ProxyClass> proxyClass, int index,
+                            const AidlTypenames& typenames, const Options& options) {
   const bool oneway = method.IsOneway();
 
   // == the TRANSACT_ constant =============================================
@@ -797,7 +933,7 @@
   // == the declaration in the interface ===================================
   std::shared_ptr<ClassElement> decl;
   if (method.IsUserDefined()) {
-    decl = generate_interface_method(method, typenames);
+    decl = GenerateInterfaceMethod(method);
   } else {
     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
       std::ostringstream code;
@@ -819,17 +955,16 @@
     bool outline_stub =
         stubClass->transact_outline && stubClass->outline_methods.count(&method) != 0;
     if (outline_stub) {
-      generate_stub_case_outline(iface, method, transactCodeName, oneway, stubClass, typenames,
-                                 options);
+      GenerateStubCaseOutline(iface, method, transactCodeName, oneway, stubClass, typenames,
+                              options);
     } else {
-      generate_stub_case(iface, method, transactCodeName, oneway, stubClass, typenames, options);
+      GenerateStubCase(iface, method, transactCodeName, oneway, stubClass, typenames, options);
     }
   } else {
     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
       auto c = std::make_shared<Case>(transactCodeName);
       std::ostringstream code;
-      code << "data.enforceInterface(descriptor);\n"
-           << "reply.writeNoException();\n"
+      code << "reply.writeNoException();\n"
            << "reply.writeInt(" << kGetInterfaceVersion << "());\n"
            << "return true;\n";
       c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
@@ -838,8 +973,7 @@
     if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
       auto c = std::make_shared<Case>(transactCodeName);
       std::ostringstream code;
-      code << "data.enforceInterface(descriptor);\n"
-           << "reply.writeNoException();\n"
+      code << "reply.writeNoException();\n"
            << "reply.writeString(" << kGetInterfaceHash << "());\n"
            << "return true;\n";
       c->statements->Add(std::make_shared<LiteralStatement>(code.str()));
@@ -850,8 +984,8 @@
   // == the proxy method ===================================================
   std::shared_ptr<ClassElement> proxy = nullptr;
   if (method.IsUserDefined()) {
-    proxy = generate_proxy_method(iface, method, transactCodeName, oneway, proxyClass, typenames,
-                                  options);
+    proxy = GenerateProxyMethod(iface, method, transactCodeName, oneway, proxyClass, typenames,
+                                options);
 
   } else {
     if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
@@ -862,17 +996,22 @@
            << "android.os.RemoteException {\n"
            << "  if (mCachedVersion == -1) {\n"
            << "    android.os.Parcel data = android.os.Parcel.obtain();\n"
-           << "    android.os.Parcel reply = android.os.Parcel.obtain();\n"
-           << "    try {\n"
+           << "    android.os.Parcel reply = android.os.Parcel.obtain();\n";
+      if (options.GenRpc()) {
+        code << "    data.markForBinder(asBinder());\n";
+      }
+      code << "    try {\n"
            << "      data.writeInterfaceToken(DESCRIPTOR);\n"
            << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
-           << "data, reply, 0);\n"
-           << "      if (!_status) {\n"
-           << "        if (getDefaultImpl() != null) {\n"
-           << "          return getDefaultImpl().getInterfaceVersion();\n"
-           << "        }\n"
-           << "      }\n"
-           << "      reply.readException();\n"
+           << "data, reply, 0);\n";
+      if (iface.IsJavaDefault()) {
+        code << "      if (!_status) {\n"
+             << "        if (getDefaultImpl() != null) {\n"
+             << "          return getDefaultImpl().getInterfaceVersion();\n"
+             << "        }\n"
+             << "      }\n";
+      }
+      code << "      reply.readException();\n"
            << "      mCachedVersion = reply.readInt();\n"
            << "    } finally {\n"
            << "      reply.recycle();\n"
@@ -891,17 +1030,22 @@
            << "android.os.RemoteException {\n"
            << "  if (\"-1\".equals(mCachedHash)) {\n"
            << "    android.os.Parcel data = android.os.Parcel.obtain();\n"
-           << "    android.os.Parcel reply = android.os.Parcel.obtain();\n"
-           << "    try {\n"
+           << "    android.os.Parcel reply = android.os.Parcel.obtain();\n";
+      if (options.GenRpc()) {
+        code << "    data.markForBinder(asBinder());\n";
+      }
+      code << "    try {\n"
            << "      data.writeInterfaceToken(DESCRIPTOR);\n"
            << "      boolean _status = mRemote.transact(Stub." << transactCodeName << ", "
-           << "data, reply, 0);\n"
-           << "      if (!_status) {\n"
-           << "        if (getDefaultImpl() != null) {\n"
-           << "          return getDefaultImpl().getInterfaceHash();\n"
-           << "        }\n"
-           << "      }\n"
-           << "      reply.readException();\n"
+           << "data, reply, 0);\n";
+      if (iface.IsJavaDefault()) {
+        code << "      if (!_status) {\n"
+             << "        if (getDefaultImpl() != null) {\n"
+             << "          return getDefaultImpl().getInterfaceHash();\n"
+             << "        }\n"
+             << "      }\n";
+      }
+      code << "      reply.readException();\n"
            << "      mCachedHash = reply.readString();\n"
            << "    } finally {\n"
            << "      reply.recycle();\n"
@@ -918,14 +1062,14 @@
   }
 }
 
-static void generate_interface_descriptors(const Options& options, const AidlInterface* iface,
-                                           Class* interface, std::shared_ptr<StubClass> stub,
-                                           std::shared_ptr<ProxyClass> proxy) {
+static void GenerateInterfaceDescriptors(const Options& options, const AidlInterface* iface,
+                                         Class* interface, std::shared_ptr<StubClass> stub,
+                                         std::shared_ptr<ProxyClass> proxy) {
   // the interface descriptor transaction handler
   auto c = std::make_shared<Case>("INTERFACE_TRANSACTION");
   c->statements->Add(std::make_shared<MethodCall>(
       stub->transact_reply, "writeString",
-      std::vector<std::shared_ptr<Expression>>{stub->get_transact_descriptor(nullptr)}));
+      std::vector<std::shared_ptr<Expression>>{stub->GetTransactDescriptor(nullptr)}));
   c->statements->Add(std::make_shared<ReturnStatement>(TRUE_VALUE));
   stub->transact_switch_meta->cases.push_back(c);
 
@@ -973,9 +1117,8 @@
 // number of methods not outlined (are kept in the onTransact() method).
 //
 // Requirements: non_outline_count <= outline_threshold.
-static void compute_outline_methods(const AidlInterface* iface,
-                                    const std::shared_ptr<StubClass> stub, size_t outline_threshold,
-                                    size_t non_outline_count) {
+static void ComputeOutlineMethods(const AidlInterface* iface, const std::shared_ptr<StubClass> stub,
+                                  size_t outline_threshold, size_t non_outline_count) {
   AIDL_FATAL_IF(non_outline_count > outline_threshold, iface);
   // We'll outline (create sub methods) if there are more than min_methods
   // cases.
@@ -1000,31 +1143,29 @@
   }
 }
 
-static shared_ptr<ClassElement> generate_default_impl_method(const AidlMethod& method,
-                                                             const AidlTypenames& typenames) {
+static shared_ptr<ClassElement> GenerateDefaultImplMethod(const AidlMethod& method) {
   auto default_method = std::make_shared<Method>();
   default_method->comment = GenerateComments(method);
   default_method->modifiers = PUBLIC | OVERRIDE;
-  default_method->returnType = JavaSignatureOf(method.GetType(), typenames);
+  default_method->returnType = JavaSignatureOf(method.GetType());
   default_method->name = method.GetName();
   default_method->statements = std::make_shared<StatementBlock>();
   for (const auto& arg : method.GetArguments()) {
     default_method->parameters.push_back(
-        std::make_shared<Variable>(JavaSignatureOf(arg->GetType(), typenames), arg->GetName()));
+        std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName()));
   }
   default_method->exceptions.push_back("android.os.RemoteException");
 
   if (method.GetType().GetName() != "void") {
-    const string& defaultValue = DefaultJavaValueOf(method.GetType(), typenames);
+    const string& defaultValue = DefaultJavaValueOf(method.GetType());
     default_method->statements->Add(
         std::make_shared<LiteralStatement>(StringPrintf("return %s;\n", defaultValue.c_str())));
   }
   return default_method;
 }
 
-static shared_ptr<Class> generate_default_impl_class(const AidlInterface& iface,
-                                                     const AidlTypenames& typenames,
-                                                     const Options& options) {
+static shared_ptr<Class> GenerateDefaultImplClass(const AidlInterface& iface,
+                                                  const Options& options) {
   auto default_class = std::make_shared<Class>();
   default_class->comment = "/** Default implementation for " + iface.GetName() + ". */";
   default_class->modifiers = PUBLIC | STATIC;
@@ -1034,7 +1175,7 @@
 
   for (const auto& m : iface.GetMethods()) {
     if (m->IsUserDefined()) {
-      default_class->elements.emplace_back(generate_default_impl_method(*m, typenames));
+      default_class->elements.emplace_back(GenerateDefaultImplMethod(*m));
     } else {
       // These are called only when the remote side does not implement these
       // methods, which is normally impossible, because these methods are
@@ -1070,9 +1211,99 @@
   return default_class;
 }
 
-std::unique_ptr<Class> generate_binder_interface_class(const AidlInterface* iface,
-                                                       const AidlTypenames& typenames,
-                                                       const Options& options) {
+static shared_ptr<ClassElement> GenerateDelegatorMethod(const AidlMethod& method) {
+  auto delegator_method = std::make_shared<Method>();
+  delegator_method->comment = GenerateComments(method);
+  delegator_method->modifiers = PUBLIC | OVERRIDE;
+  delegator_method->returnType = JavaSignatureOf(method.GetType());
+  delegator_method->name = method.GetName();
+  delegator_method->statements = std::make_shared<StatementBlock>();
+  std::vector<std::string> argNames;
+  for (const auto& arg : method.GetArguments()) {
+    delegator_method->parameters.push_back(
+        std::make_shared<Variable>(JavaSignatureOf(arg->GetType()), arg->GetName()));
+    argNames.push_back(arg->GetName());
+  }
+  delegator_method->exceptions.push_back("android.os.RemoteException");
+
+  std::string return_str;
+  if (method.GetType().GetName() != "void") {
+    return_str = "return ";
+  }
+  delegator_method->statements->Add(
+      std::make_shared<LiteralStatement>(return_str + "mImpl." + method.GetName() + "(" +
+                                         android::base::Join(argNames, ",") + ");\n"));
+  return delegator_method;
+}
+
+static shared_ptr<Class> GenerateDelegatorClass(const AidlInterface& iface,
+                                                const Options& options) {
+  auto delegator_class = std::make_shared<Class>();
+  delegator_class->comment = "/** Delegator implementation for " + iface.GetName() + ". */";
+  delegator_class->modifiers = PUBLIC | STATIC;
+  delegator_class->what = Class::CLASS;
+  delegator_class->type = iface.GetCanonicalName() + ".Delegator";
+  delegator_class->extends = iface.GetCanonicalName() + ".Stub";
+
+  // constructor
+  delegator_class->elements.emplace_back(
+      std::make_shared<LiteralClassElement>("public Delegator(" + iface.GetCanonicalName() +
+                                            " impl) {\n"
+                                            "  this.mImpl = impl;\n"
+                                            "}\n"));
+  // meta methods
+  if (!options.Hash().empty()) {
+    delegator_class->elements.emplace_back(
+        std::make_shared<LiteralClassElement>("@Override\n"
+                                              "public String " +
+                                              kGetInterfaceHash +
+                                              "() throws android.os.RemoteException {\n"
+                                              "  return mImpl." +
+                                              kGetInterfaceHash +
+                                              "();\n"
+                                              "}\n"));
+  }
+  if (options.Version() > 0) {
+    delegator_class->elements.emplace_back(
+        std::make_shared<LiteralClassElement>("@Override\n"
+                                              "public int " +
+                                              kGetInterfaceVersion +
+                                              "() throws android.os.RemoteException {\n"
+                                              "  int implVer = mImpl." +
+                                              kGetInterfaceVersion +
+                                              "();\n"
+                                              "  return VERSION < implVer ? VERSION : implVer;\n"
+                                              "}\n"));
+  }
+
+  // user defined methods
+  for (const auto& m : iface.GetMethods()) {
+    if (m->IsUserDefined()) {
+      delegator_class->elements.emplace_back(GenerateDelegatorMethod(*m));
+    }
+  }
+
+  delegator_class->elements.emplace_back(
+      std::make_shared<LiteralClassElement>(iface.GetCanonicalName() + " mImpl;\n"));
+
+  return delegator_class;
+}
+
+static shared_ptr<ClassElement> GenerateMaxTransactionId(int max_transaction_id) {
+  auto getMaxTransactionId = std::make_shared<Method>();
+  getMaxTransactionId->comment = "/** @hide */";
+  getMaxTransactionId->modifiers = PUBLIC;
+  getMaxTransactionId->returnType = "int";
+  getMaxTransactionId->name = "getMaxTransactionId";
+  getMaxTransactionId->statements = std::make_shared<StatementBlock>();
+  getMaxTransactionId->statements->Add(std::make_shared<ReturnStatement>(
+      std::make_shared<LiteralExpression>(std::to_string(max_transaction_id))));
+  return getMaxTransactionId;
+}
+
+std::unique_ptr<Class> GenerateInterfaceClass(const AidlInterface* iface,
+                                              const AidlTypenames& typenames,
+                                              const Options& options) {
   // the interface class
   auto interface = std::make_unique<Class>();
   interface->comment = GenerateComments(*iface);
@@ -1100,71 +1331,98 @@
   }
 
   // the default impl class
-  auto default_impl = generate_default_impl_class(*iface, typenames, options);
+  auto default_impl = GenerateDefaultImplClass(*iface, options);
   interface->elements.emplace_back(default_impl);
 
+  // the delegator class
+  if (iface->IsJavaDelegator()) {
+    auto delegator = GenerateDelegatorClass(*iface, options);
+    interface->elements.emplace_back(delegator);
+  }
+
   // the stub inner class
   auto stub = std::make_shared<StubClass>(iface, options);
   interface->elements.push_back(stub);
 
-  compute_outline_methods(iface,
-                          stub,
-                          options.onTransact_outline_threshold_,
-                          options.onTransact_non_outline_count_);
+  ComputeOutlineMethods(iface, stub, options.onTransact_outline_threshold_,
+                        options.onTransact_non_outline_count_);
 
   // the proxy inner class
   auto proxy = std::make_shared<ProxyClass>(iface, options);
   stub->elements.push_back(proxy);
 
   // stub and proxy support for getInterfaceDescriptor()
-  generate_interface_descriptors(options, iface, interface.get(), stub, proxy);
+  GenerateInterfaceDescriptors(options, iface, interface.get(), stub, proxy);
 
   // all the declared constants of the interface
   string constants;
-  generate_constant_declarations(*CodeWriter::ForString(&constants), *iface);
+  GenerateConstantDeclarations(*CodeWriter::ForString(&constants), *iface);
   interface->elements.push_back(std::make_shared<LiteralClassElement>(constants));
 
   // all the declared methods of the interface
-
+  bool permissionWrapperGenerated = false;
+  int max_transaction_id = 0;
   for (const auto& item : iface->GetMethods()) {
-    generate_methods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames,
-                     options);
+    if ((iface->EnforceExpression() || item->GetType().EnforceExpression()) &&
+        !permissionWrapperGenerated) {
+      GeneratePermissionWrapper(stub.get());
+      permissionWrapperGenerated = true;
+    }
+    GenerateMethods(*iface, *item, interface.get(), stub, proxy, item->GetId(), typenames, options);
+    max_transaction_id = std::max(max_transaction_id, item->GetId());
   }
 
-  // additional static methods for the default impl set/get to the
-  // stub class. Can't add them to the interface as the generated java files
-  // may be compiled with Java < 1.7 where static interface method isn't
-  // supported.
-  // TODO(b/111417145) make this conditional depending on the Java language
-  // version requested
-  const string i_name = iface->GetCanonicalName();
-  stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
-      StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
-                   "  // Only one user of this interface can use this function\n"
-                   "  // at a time. This is a heuristic to detect if two different\n"
-                   "  // users in the same process use this function.\n"
-                   "  if (Stub.Proxy.sDefaultImpl != null) {\n"
-                   "    throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
-                   "  }\n"
-                   "  if (impl != null) {\n"
-                   "    Stub.Proxy.sDefaultImpl = impl;\n"
-                   "    return true;\n"
-                   "  }\n"
-                   "  return false;\n"
-                   "}\n",
-                   i_name.c_str())));
-  stub->elements.emplace_back(
-      std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
-                                                         "  return Stub.Proxy.sDefaultImpl;\n"
-                                                         "}\n",
-                                                         i_name.c_str())));
+  // getMaxTransactionId
+  if (options.GenTransactionNames()) {
+    stub->elements.push_back(GenerateMaxTransactionId(max_transaction_id));
+  }
 
-  // the static field is defined in the proxy class, not in the interface class
-  // because all fields in an interface class are by default final.
-  proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
-      StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
+  // all the nested types
+  string code;
+  auto writer = CodeWriter::ForString(&code);
+  for (const auto& nested : iface->GetNestedTypes()) {
+    GenerateClass(*writer, *nested, typenames, options);
+  }
+  GenerateParcelHelpers(*writer, *iface, options);
+  writer->Close();
+  interface->elements.push_back(std::make_shared<LiteralClassElement>(code));
 
-  stub->finish();
+  if (iface->IsJavaDefault()) {
+    // additional static methods for the default impl set/get to the
+    // stub class. Can't add them to the interface as the generated java files
+    // may be compiled with Java < 1.7 where static interface method isn't
+    // supported.
+    // TODO(b/111417145) make this conditional depending on the Java language
+    // version requested
+    const string i_name = iface->GetCanonicalName();
+    stub->elements.emplace_back(std::make_shared<LiteralClassElement>(
+        StringPrintf("public static boolean setDefaultImpl(%s impl) {\n"
+                     "  // Only one user of this interface can use this function\n"
+                     "  // at a time. This is a heuristic to detect if two different\n"
+                     "  // users in the same process use this function.\n"
+                     "  if (Stub.Proxy.sDefaultImpl != null) {\n"
+                     "    throw new IllegalStateException(\"setDefaultImpl() called twice\");\n"
+                     "  }\n"
+                     "  if (impl != null) {\n"
+                     "    Stub.Proxy.sDefaultImpl = impl;\n"
+                     "    return true;\n"
+                     "  }\n"
+                     "  return false;\n"
+                     "}\n",
+                     i_name.c_str())));
+    stub->elements.emplace_back(
+        std::make_shared<LiteralClassElement>(StringPrintf("public static %s getDefaultImpl() {\n"
+                                                           "  return Stub.Proxy.sDefaultImpl;\n"
+                                                           "}\n",
+                                                           i_name.c_str())));
+
+    // the static field is defined in the proxy class, not in the interface class
+    // because all fields in an interface class are by default final.
+    proxy->elements.emplace_back(std::make_shared<LiteralClassElement>(
+        StringPrintf("public static %s sDefaultImpl;\n", i_name.c_str())));
+  }
+
+  stub->Finish();
 
   return interface;
 }
diff --git a/generate_ndk.cpp b/generate_ndk.cpp
index ca8d66c..d7b6663 100644
--- a/generate_ndk.cpp
+++ b/generate_ndk.cpp
@@ -28,7 +28,6 @@
 namespace aidl {
 namespace ndk {
 
-static constexpr const char* kClazz = "_g_aidl_clazz";
 static constexpr const char* kDescriptor = "descriptor";
 static constexpr const char* kVersion = "version";
 static constexpr const char* kHash = "hash";
@@ -36,144 +35,87 @@
 static constexpr const char* kCachedHash = "_aidl_cached_hash";
 static constexpr const char* kCachedHashMutex = "_aidl_cached_hash_mutex";
 
-using namespace internals;
 namespace internals {
-void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
-                          const AidlStructuredParcelable& defined_type, const Options& options);
+// 4 outputs for NDK for each type: Header, BpHeader, BnHeader, Source
+void GenerateHeader(CodeWriter& out, const AidlTypenames& types,
+                    const AidlDefinedType& defined_type, const Options& options);
+void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
+                          const AidlDefinedType& defined_type, const Options& options);
+void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
+                          const AidlDefinedType& defined_type, const Options& options);
+void GenerateSource(CodeWriter& out, const AidlTypenames& types,
+                    const AidlDefinedType& defined_type, const Options& options);
+
+// Header contains ClassDecl of a root type
+void GenerateInterfaceClassDecl(CodeWriter& out, const AidlTypenames& types,
+                                const AidlInterface& iface, const Options& options);
+void GenerateParcelClassDecl(CodeWriter& out, const AidlTypenames& types,
+                             const AidlStructuredParcelable& parcelable, const Options& options);
+void GenerateParcelClassDecl(CodeWriter& out, const AidlTypenames& types,
+                             const AidlUnionDecl& union_decl, const Options& options);
+void GenerateEnumClassDecl(CodeWriter& out, const AidlTypenames& types,
+                           const AidlEnumDeclaration& enum_decl, const Options& options);
+
+// BpHeader/BnHeader for interface
+void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
+                          const AidlInterface& defined_type, const Options& options);
+void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
+                          const AidlInterface& defined_type, const Options& options);
+
+// Source for interface
+void GenerateSource(CodeWriter& out, const AidlTypenames& types, const AidlInterface& iface,
+                    const Options& options);
+void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
+                         const AidlInterface& defined_type, const Options& options);
+void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
+                          const AidlInterface& defined_type, const Options& options);
+void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
+                          const AidlInterface& defined_type, const Options& options);
+void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types,
+                             const AidlInterface& defined_type, const Options& options);
+
+// Source for structured parcelable
 void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
                           const AidlStructuredParcelable& defined_type, const Options& options);
-void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
-                          const AidlUnionDecl& defined_type, const Options& options);
+
+// Source for union
 void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
                           const AidlUnionDecl& defined_type, const Options& options);
+
+// Compare headers so that <android/..> and <aidl/..> comes after other (probably) std headers.
+struct HeaderComp {
+  static int rank(const string& a) {
+    return base::StartsWith(a, "aidl/") ? 2 : base::StartsWith(a, "android/") ? 1 : 0;
+  }
+  bool operator()(const string& a, const string& b) const {
+    return std::make_tuple(rank(a), a) < std::make_tuple(rank(b), b);
+  }
+};
 }  // namespace internals
 
+using namespace internals;
 using cpp::ClassNames;
-
-void GenerateNdkInterface(const string& output_file, const Options& options,
-                          const AidlTypenames& types, const AidlInterface& defined_type,
-                          const IoDelegate& io_delegate) {
-  const string i_header = options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
-  unique_ptr<CodeWriter> i_writer(io_delegate.GetCodeWriter(i_header));
-  GenerateInterfaceHeader(*i_writer, types, defined_type, options);
-  AIDL_FATAL_IF(!i_writer->Close(), i_header);
-
-  const string bp_header =
-      options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
-  unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
-  GenerateClientHeader(*bp_writer, types, defined_type, options);
-  AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
-
-  const string bn_header =
-      options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
-  unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
-  GenerateServerHeader(*bn_writer, types, defined_type, options);
-  AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
-
-  unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
-  GenerateSource(*source_writer, types, defined_type, options);
-  AIDL_FATAL_IF(!source_writer->Close(), output_file);
-}
-
-template <typename ParcelableType>
-void GenerateNdkParcel(const string& output_file, const Options& options,
-                       const AidlTypenames& types, const ParcelableType& defined_type,
-                       const IoDelegate& io_delegate) {
-  const string header_path =
-      options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
-  unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
-  GenerateParcelHeader(*header_writer, types, defined_type, options);
-
-  unique_ptr<CodeWriter> source_writer(io_delegate.GetCodeWriter(output_file));
-  if (defined_type.IsGeneric()) {
-    // Need to write source to header if this is a template
-    GenerateParcelSource(*header_writer, types, defined_type, options);
-  } else {
-    GenerateParcelSource(*source_writer, types, defined_type, options);
-  }
-  (source_writer->Close());
-  AIDL_FATAL_IF(!header_writer->Close(), header_path);
-
-  const string bp_header =
-      options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
-  unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
-  *bp_writer << "#error TODO(b/111362593) defined_types do not have bp classes\n";
-  AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
-
-  const string bn_header =
-      options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
-  unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
-  *bn_writer << "#error TODO(b/111362593) defined_types do not have bn classes\n";
-  AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
-}
-
-void GenerateNdkParcelDeclaration(const std::string& filename, const IoDelegate& io_delegate) {
-  CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
-  *code_writer
-      << "// This file is intentionally left blank as placeholder for parcel declaration.\n";
-  AIDL_FATAL_IF(!code_writer->Close(), filename);
-}
-
-void GenerateNdkEnumDeclaration(const string& output_file, const Options& options,
-                                const AidlTypenames& types, const AidlEnumDeclaration& defined_type,
-                                const IoDelegate& io_delegate) {
-  const string header_path =
-      options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW);
-  unique_ptr<CodeWriter> header_writer(io_delegate.GetCodeWriter(header_path));
-  GenerateEnumHeader(*header_writer, types, defined_type, options);
-  AIDL_FATAL_IF(!header_writer->Close(), header_path);
-
-  const string bp_header =
-      options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT);
-  unique_ptr<CodeWriter> bp_writer(io_delegate.GetCodeWriter(bp_header));
-  *bp_writer << "#error TODO(b/111362593) enums do not have bp classes\n";
-  AIDL_FATAL_IF(!bp_writer->Close(), bp_header);
-
-  const string bn_header =
-      options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER);
-  unique_ptr<CodeWriter> bn_writer(io_delegate.GetCodeWriter(bn_header));
-  *bn_writer << "#error TODO(b/111362593) enums do not have bn classes\n";
-  AIDL_FATAL_IF(!bn_writer->Close(), bn_header);
-
-  unique_ptr<CodeWriter> source_writer = io_delegate.GetCodeWriter(output_file);
-  *source_writer
-      << "// This file is intentionally left blank as placeholder for enum declaration.\n";
-  AIDL_FATAL_IF(!source_writer->Close(), output_file);
-}
+using cpp::GetQualifiedName;
 
 void GenerateNdk(const string& output_file, const Options& options, const AidlTypenames& types,
                  const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
-  if (const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
-      parcelable != nullptr) {
-    GenerateNdkParcel<AidlStructuredParcelable>(output_file, options, types, *parcelable,
-                                                io_delegate);
-    return;
-  }
+  using GenFn = void (*)(CodeWriter & out, const AidlTypenames& types,
+                         const AidlDefinedType& defined_type, const Options& options);
+  // Wrap Generate* function to handle CodeWriter for a file.
+  auto gen = [&](auto file, GenFn fn) {
+    unique_ptr<CodeWriter> writer(io_delegate.GetCodeWriter(file));
+    fn(*writer, types, defined_type, options);
+    AIDL_FATAL_IF(!writer->Close(), defined_type) << "I/O Error!";
+  };
 
-  if (const AidlUnionDecl* union_decl = defined_type.AsUnionDeclaration(); union_decl != nullptr) {
-    GenerateNdkParcel<AidlUnionDecl>(output_file, options, types, *union_decl, io_delegate);
-    return;
-  }
-
-  if (const AidlParcelable* parcelable_decl = defined_type.AsParcelable();
-      parcelable_decl != nullptr) {
-    GenerateNdkParcelDeclaration(output_file, io_delegate);
-    return;
-  }
-
-  if (const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
-      enum_decl != nullptr) {
-    GenerateNdkEnumDeclaration(output_file, options, types, *enum_decl, io_delegate);
-    return;
-  }
-
-  if (const AidlInterface* interface = defined_type.AsInterface(); interface != nullptr) {
-    GenerateNdkInterface(output_file, options, types, *interface, io_delegate);
-    return;
-  }
-
-  AIDL_FATAL(defined_type) << "Unrecognized type sent for NDK cpp generation.";
+  gen(options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::RAW), &GenerateHeader);
+  gen(options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::CLIENT),
+      &GenerateClientHeader);
+  gen(options.OutputHeaderDir() + NdkHeaderFile(defined_type, ClassNames::SERVER),
+      &GenerateServerHeader);
+  gen(output_file, &GenerateSource);
 }
+
 namespace internals {
 
 void EnterNdkNamespace(CodeWriter& out, const AidlDefinedType& defined_type) {
@@ -195,121 +137,286 @@
   out << "if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;\n\n";
 }
 
-static void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
-                                   const AidlDefinedType& defined_type) {
-  out << "#include <cstdint>\n";
-  out << "#include <memory>\n";
-  out << "#include <optional>\n";
-  out << "#include <string>\n";
-  out << "#include <vector>\n";
-  out << "#ifdef BINDER_STABILITY_SUPPORT\n";
-  out << "#include <android/binder_stability.h>\n";
-  out << "#endif  // BINDER_STABILITY_SUPPORT\n";
+void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
+                            const AidlDefinedType& defined_type, const Options& options);
 
-  if (defined_type.IsSensitiveData()) {
-    out << "#include <android/binder_parcel_platform.h>\n";
-    out << "#include <android/binder_ibinder_platform.h>\n";
-  }
+void GenerateClassDecl(CodeWriter& out, const AidlTypenames& types,
+                       const AidlDefinedType& defined_type, const Options& options);
 
-  auto headerFilePath = [&types](const AidlTypeSpecifier& typespec) -> std::string {
-    const AidlDefinedType* type = types.TryGetDefinedType(typespec.GetName());
-    if (type == nullptr) {
-      // could be a primitive type.
-      return "";
+void GenerateNestedTypeDecls(CodeWriter& out, const AidlTypenames& types,
+                             const AidlDefinedType& defined_type, const Options& options) {
+  auto visit = [&](const auto& nested) { GenerateClassDecl(out, types, nested, options); };
+  AIDL_FATAL_IF(!TopologicalVisit(defined_type.GetNestedTypes(), visit), defined_type)
+      << "Cycle detected.";
+}
+
+void GenerateHeaderDefinitions(CodeWriter& out, const AidlTypenames& types,
+                               const AidlDefinedType& defined_type, const Options& options) {
+  struct Visitor : AidlVisitor {
+    CodeWriter& out;
+    const AidlTypenames& types;
+    const Options& options;
+    Visitor(CodeWriter& out, const AidlTypenames& types, const Options& options)
+        : out(out), types(types), options(options) {}
+
+    void Visit(const AidlEnumDeclaration& enum_decl) override {
+      const auto backing_type = NdkNameOf(types, enum_decl.GetBackingType(), StorageMode::STACK);
+      EnterNdkNamespace(out, enum_decl);
+      out << cpp::GenerateEnumToString(enum_decl, backing_type);
+      LeaveNdkNamespace(out, enum_decl);
+
+      out << "namespace ndk {\n";
+      out << "namespace internal {\n";
+      out << cpp::GenerateEnumValues(enum_decl, {"aidl"});
+      out << "}  // namespace internal\n";
+      out << "}  // namespace ndk\n";
     }
 
-    if (type->AsInterface() != nullptr) {
-      return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
-    } else if (type->AsStructuredParcelable() != nullptr) {
-      return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
-    } else if (type->AsUnionDeclaration() != nullptr) {
-      return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
-    } else if (type->AsParcelable() != nullptr) {
-      return type->AsParcelable()->GetCppHeader();
-    } else if (type->AsEnumDeclaration() != nullptr) {
-      return NdkHeaderFile(*type, ClassNames::RAW, false /*use_os_sep*/);
-    } else {
-      AIDL_FATAL(*type) << "Unrecognized type.";
-      return "";
-    }
-  };
-
-  std::set<std::string> includes;
-
-  // visit a type and collect all reference types' headers
-  std::function<void(const AidlTypeSpecifier& type)> visit = [&](const AidlTypeSpecifier& type) {
-    includes.insert(headerFilePath(type));
-    if (type.IsGeneric()) {
-      for (const auto& param : type.GetTypeParameters()) {
-        visit(*param);
+    void Visit(const AidlStructuredParcelable& parcelable) override {
+      if (parcelable.IsGeneric()) {
+        GenerateParcelSource(out, types, parcelable, options);
       }
     }
-  };
 
-  const AidlInterface* interface = defined_type.AsInterface();
-  if (interface != nullptr) {
-    for (const auto& method : interface->GetMethods()) {
-      visit(method->GetType());
-      for (const auto& argument : method->GetArguments()) {
-        visit(argument->GetType());
+    void Visit(const AidlUnionDecl& union_decl) override {
+      if (union_decl.IsGeneric()) {
+        GenerateParcelSource(out, types, union_decl, options);
       }
     }
-  }
 
-  auto visit_parcelable = [&](const auto& parcelable) {
-    for (const auto& field : parcelable.GetFields()) {
-      visit(field->GetType());
-      // Check the fields for generic type arguments
-      if (field->GetType().IsGeneric()) {
-        for (const auto& type_argument : field->GetType().GetTypeParameters()) {
-          visit(*type_argument);
+  } v(out, types, options);
+  VisitTopDown(v, defined_type);
+}
+
+void GenerateHeader(CodeWriter& out, const AidlTypenames& types,
+                    const AidlDefinedType& defined_type, const Options& options) {
+  out << "#pragma once\n\n";
+  GenerateHeaderIncludes(out, types, defined_type, options);
+  EnterNdkNamespace(out, defined_type);
+  GenerateClassDecl(out, types, defined_type, options);
+  LeaveNdkNamespace(out, defined_type);
+  GenerateHeaderDefinitions(out, types, defined_type, options);
+}
+
+void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
+                          const AidlDefinedType& defined_type, const Options& options) {
+  if (auto iface = AidlCast<AidlInterface>(defined_type); iface) {
+    GenerateClientHeader(out, types, *iface, options);
+  } else if (auto parcelable = AidlCast<AidlStructuredParcelable>(defined_type); parcelable) {
+    out << "#error TODO(b/111362593) defined_types do not have bp classes\n";
+  } else if (auto union_decl = AidlCast<AidlUnionDecl>(defined_type); union_decl) {
+    out << "#error TODO(b/111362593) defined_types do not have bp classes\n";
+  } else if (auto enum_decl = AidlCast<AidlEnumDeclaration>(defined_type); enum_decl) {
+    out << "#error TODO(b/111362593) enums do not have bp classes\n";
+  } else {
+    AIDL_FATAL(defined_type) << "Unrecognized type sent for NDK generation.";
+  }
+}
+
+void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
+                          const AidlDefinedType& defined_type, const Options& options) {
+  if (auto iface = AidlCast<AidlInterface>(defined_type); iface) {
+    GenerateServerHeader(out, types, *iface, options);
+  } else if (auto parcelable = AidlCast<AidlStructuredParcelable>(defined_type); parcelable) {
+    out << "#error TODO(b/111362593) defined_types do not have bn classes\n";
+  } else if (auto union_decl = AidlCast<AidlUnionDecl>(defined_type); union_decl) {
+    out << "#error TODO(b/111362593) defined_types do not have bn classes\n";
+  } else if (auto enum_decl = AidlCast<AidlEnumDeclaration>(defined_type); enum_decl) {
+    out << "#error TODO(b/111362593) enums do not have bn classes\n";
+  } else {
+    AIDL_FATAL(defined_type) << "Unrecognized type sent for CPP generation.";
+  }
+}
+
+void GenerateSource(CodeWriter& out, const AidlTypenames& types,
+                    const AidlDefinedType& defined_type, const Options& options) {
+  struct Visitor : AidlVisitor {
+    CodeWriter& out;
+    const AidlTypenames& types;
+    const Options& options;
+    Visitor(CodeWriter& out, const AidlTypenames& types, const Options& options)
+        : out(out), types(types), options(options) {}
+
+    void Visit(const AidlInterface& interface) override {
+      GenerateSource(out, types, interface, options);
+    }
+
+    void Visit(const AidlStructuredParcelable& parcelable) override {
+      if (!parcelable.IsGeneric()) {
+        GenerateParcelSource(out, types, parcelable, options);
+      }
+    }
+
+    void Visit(const AidlUnionDecl& union_decl) override {
+      if (!union_decl.IsGeneric()) {
+        GenerateParcelSource(out, types, union_decl, options);
+      }
+    }
+
+    void Visit(const AidlEnumDeclaration& enum_decl) override {
+      if (!enum_decl.GetParentType()) {
+        out << "// This file is intentionally left blank as placeholder for enum declaration.\n";
+      }
+    }
+  } v(out, types, options);
+  VisitTopDown(v, defined_type);
+}
+
+void GenerateHeaderIncludes(CodeWriter& out, const AidlTypenames& types,
+                            const AidlDefinedType& defined_type, const Options& options) {
+  // Collect implementation related headers and referenced defined types by recursivly visiting
+  // nested types
+  struct Visitor : AidlVisitor {
+    const AidlTypenames& types;
+    const Options& options;
+    std::set<std::string, HeaderComp> includes;
+    Visitor(const AidlTypenames& types, const Options& options) : types(types), options(options) {}
+
+    // Collect includes for each type reference
+    void Visit(const AidlTypeSpecifier& type) override {
+      auto defined = type.GetDefinedType();
+      if (!defined) return;
+      includes.insert(NdkHeaderFile(*defined, ClassNames::RAW, false /*use_os_sep*/));
+    }
+
+    // Collect implementation-specific includes for each type definition
+    void Visit(const AidlInterface& interface) override {
+      AddCommonHeaders(interface);
+      includes.insert("android/binder_interface_utils.h");
+      if (options.GenLog()) {
+        includes.insert("functional");
+        includes.insert("chrono");
+        includes.insert("sstream");
+      }
+      // For nested interfacees client/server classes are defined in the same header.
+      // So we need includes for client/server class as well.
+      if (interface.GetParentType()) {
+        includes.insert("android/binder_ibinder.h");
+        if (options.GenTraces()) {
+          includes.insert("android/trace.h");
         }
       }
     }
-  };
 
-  const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
-  if (parcelable != nullptr) {
-    visit_parcelable(*parcelable);
-  }
-
-  const AidlUnionDecl* union_decl = defined_type.AsUnionDeclaration();
-  if (union_decl != nullptr) {
-    visit_parcelable(*union_decl);
-  }
-
-  const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
-  if (enum_decl != nullptr) {
-    visit(enum_decl->GetBackingType());
-  }
-
-  for (const auto& path : includes) {
-    if (path == "") {
-      continue;
+    void Visit(const AidlStructuredParcelable& parcelable) override {
+      AddCommonHeaders(parcelable);
+      includes.insert("android/binder_interface_utils.h");
+      includes.insert("android/binder_parcelable_utils.h");
+      includes.insert("android/binder_to_string.h");  // used by toString()
     }
+
+    void Visit(const AidlUnionDecl& union_decl) override {
+      AddCommonHeaders(union_decl);
+      includes.insert("android/binder_interface_utils.h");
+      includes.insert("android/binder_parcelable_utils.h");
+      includes.insert("android/binder_to_string.h");  // used by toString()
+      auto union_headers = cpp::UnionWriter::GetHeaders(union_decl);
+      includes.insert(std::begin(union_headers), std::end(union_headers));
+    }
+
+    void Visit(const AidlEnumDeclaration& enum_decl) override {
+      AddCommonHeaders(enum_decl);
+      includes.insert("array");
+      includes.insert("android/binder_enums.h");
+    }
+
+    void AddCommonHeaders(const AidlDefinedType& defined_type) {
+      includes.insert("cstdint");
+      includes.insert("memory");
+      includes.insert("optional");
+      includes.insert("string");
+      includes.insert("vector");
+      if (defined_type.IsSensitiveData()) {
+        includes.insert("android/binder_parcel_platform.h");
+        includes.insert("android/binder_ibinder_platform.h");
+      }
+    }
+  } v(types, options);
+  VisitTopDown(v, defined_type);
+
+  for (const auto& path : v.includes) {
     out << "#include <" << path << ">\n";
   }
+  out << "#ifdef BINDER_STABILITY_SUPPORT\n";
+  out << "#include <android/binder_stability.h>\n";
+  out << "#endif  // BINDER_STABILITY_SUPPORT\n";
+  out << "\n";
+
+  if (v.includes.count("cassert")) {
+    // TODO(b/31559095) bionic on host should define __assert2
+    out << "#ifndef __BIONIC__\n#define __assert2(a,b,c,d) ((void)0)\n#endif\n\n";
+  }
+}
+
+void GenerateClassDecl(CodeWriter& out, const AidlTypenames& types,
+                       const AidlDefinedType& defined_type, const Options& options) {
+  if (auto iface = AidlCast<AidlInterface>(defined_type); iface) {
+    GenerateInterfaceClassDecl(out, types, *iface, options);
+  } else if (auto parcelable = AidlCast<AidlStructuredParcelable>(defined_type); parcelable) {
+    GenerateParcelClassDecl(out, types, *parcelable, options);
+  } else if (auto union_decl = AidlCast<AidlUnionDecl>(defined_type); union_decl) {
+    GenerateParcelClassDecl(out, types, *union_decl, options);
+  } else if (auto enum_decl = AidlCast<AidlEnumDeclaration>(defined_type); enum_decl) {
+    GenerateEnumClassDecl(out, types, *enum_decl, options);
+  } else {
+    AIDL_FATAL(defined_type) << "Unrecognized type sent for NDK generation.";
+  }
 }
 
 static void GenerateSourceIncludes(CodeWriter& out, const AidlTypenames& types,
-                                   const AidlDefinedType& /*defined_type*/) {
-  out << "#include <android/binder_parcel_utils.h>\n";
+                                   const AidlDefinedType& defined_type, const Options& options) {
+  // Once in a .cpp file
+  if (defined_type.GetParentType() != nullptr) {
+    return;
+  }
 
+  const string self_header = NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/);
+  out << "#include \"" << self_header << "\"\n";
+  out << "\n";
+
+  std::set<std::string, HeaderComp> includes = {self_header};
+  includes.insert("android/binder_parcel_utils.h");
   types.IterateTypes([&](const AidlDefinedType& a_defined_type) {
     if (a_defined_type.AsInterface() != nullptr) {
-      out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::CLIENT, false /*use_os_sep*/)
-          << ">\n";
-      out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::SERVER, false /*use_os_sep*/)
-          << ">\n";
-      out << "#include <" << NdkHeaderFile(a_defined_type, ClassNames::RAW, false /*use_os_sep*/)
-          << ">\n";
+      includes.insert(NdkHeaderFile(a_defined_type, ClassNames::CLIENT, false /*use_os_sep*/));
+      includes.insert(NdkHeaderFile(a_defined_type, ClassNames::SERVER, false /*use_os_sep*/));
+      includes.insert(NdkHeaderFile(a_defined_type, ClassNames::RAW, false /*use_os_sep*/));
     }
   });
+
+  struct Visitor : AidlVisitor {
+    bool has_interface = false;
+    void Visit(const AidlInterface&) override { has_interface = true; }
+  } v;
+  VisitTopDown(v, defined_type);
+
+  if (v.has_interface && options.GenLog()) {
+    includes.insert("android/binder_to_string.h");
+  }
+
+  // Emit includes except self_header
+  includes.erase(includes.find(self_header));
+  for (const auto& inc : includes) {
+    out << "#include <" << inc << ">\n";
+  }
+  out << "\n";
+
+  // Emit additional definition for gen_traces
+  if (v.has_interface && options.GenTraces()) {
+    out << "namespace {\n";
+    out << "struct ScopedTrace {\n";
+    out.Indent();
+    out << "inline explicit ScopedTrace(const char* name) { ATrace_beginSection(name); }\n";
+    out << "inline ~ScopedTrace() { ATrace_endSection(); }\n";
+    out.Dedent();
+    out << "};\n";
+    out << "}  // namespace\n";
+    out << "\n";
+  }
 }
 
-template <typename TypeWithConstants>
 static void GenerateConstantDeclarations(CodeWriter& out, const AidlTypenames& types,
-                                         const TypeWithConstants& type) {
+                                         const AidlDefinedType& type) {
   for (const auto& constant : type.GetConstantDeclarations()) {
     const AidlTypeSpecifier& type = constant->GetType();
 
@@ -326,8 +433,7 @@
   }
 }
 
-template <typename TypeWithConstants>
-static void GenerateConstantDefinitions(CodeWriter& out, const TypeWithConstants& interface,
+static void GenerateConstantDefinitions(CodeWriter& out, const AidlDefinedType& interface,
                                         const std::string& clazz,
                                         const std::string& tmpl_decl = "") {
   for (const auto& constant : interface.GetConstantDeclarations()) {
@@ -345,12 +451,7 @@
 
 void GenerateSource(CodeWriter& out, const AidlTypenames& types, const AidlInterface& defined_type,
                     const Options& options) {
-  GenerateSourceIncludes(out, types, defined_type);
-  if (options.GenLog()) {
-    out << "#include <android/binder_to_string.h>\n";
-  }
-  out << "\n";
-
+  GenerateSourceIncludes(out, types, defined_type, options);
   EnterNdkNamespace(out, defined_type);
   GenerateClassSource(out, types, defined_type, options);
   GenerateClientSource(out, types, defined_type, options);
@@ -365,11 +466,11 @@
 
 static void GenerateClientMethodDefinition(CodeWriter& out, const AidlTypenames& types,
                                            const AidlInterface& defined_type,
-                                           const AidlMethod& method,
-                                           const Options& options) {
+                                           const AidlMethod& method, const Options& options) {
+  const std::string q_name = GetQualifiedName(defined_type, ClassNames::CLIENT);
   const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
 
-  out << NdkMethodDecl(types, method, clazz) << " {\n";
+  out << NdkMethodDecl(types, method, q_name) << " {\n";
   out.Indent();
   out << "binder_status_t _aidl_ret_status = STATUS_OK;\n";
   out << "::ndk::ScopedAStatus _aidl_status;\n";
@@ -397,8 +498,7 @@
   out << "\n";
 
   if (options.GenLog()) {
-    out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::CLIENT), method,
-                                    false /* isServer */, true /* isNdk */);
+    out << cpp::GenLogBeforeExecute(q_name, method, false /* isServer */, true /* isNdk */);
   }
   if (options.GenTraces()) {
     out << "ScopedTrace _aidl_trace(\"AIDL::" << to_string(options.TargetLanguage())
@@ -421,7 +521,7 @@
       WriteToParcelFor({out, types, arg->GetType(), "_aidl_in.get()", prefix + var_name});
       out << ";\n";
       StatusCheckGoto(out);
-    } else if (arg->IsOut() && arg->GetType().IsArray()) {
+    } else if (arg->IsOut() && arg->GetType().IsDynamicArray()) {
       out << "_aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *" << var_name
           << ");\n";
       StatusCheckGoto(out);
@@ -488,9 +588,8 @@
   out << "_aidl_status.set(AStatus_fromStatus(_aidl_ret_status));\n";
   out << "_aidl_status_return:\n";
   if (options.GenLog()) {
-    out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::CLIENT), defined_type,
-                                   method, "_aidl_status", "_aidl_return", false /* isServer */,
-                                   true /* isNdk */);
+    out << cpp::GenLogAfterExecute(q_name, defined_type, method, "_aidl_status", "_aidl_return",
+                                   false /* isServer */, true /* isNdk */);
   }
 
   out << "return _aidl_status;\n";
@@ -501,6 +600,8 @@
 static void GenerateServerCaseDefinition(CodeWriter& out, const AidlTypenames& types,
                                          const AidlInterface& defined_type,
                                          const AidlMethod& method, const Options& options) {
+  const string q_name = GetQualifiedName(defined_type, ClassNames::SERVER);
+
   out << "case " << MethodId(method) << ": {\n";
   out.Indent();
   for (const auto& arg : method.GetArguments()) {
@@ -525,22 +626,20 @@
       ReadFromParcelFor({out, types, arg->GetType(), "_aidl_in", "&" + var_name});
       out << ";\n";
       StatusCheckBreak(out);
-    } else if (arg->IsOut() && arg->GetType().IsArray()) {
+    } else if (arg->IsOut() && arg->GetType().IsDynamicArray()) {
       out << "_aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &" << var_name << ");\n";
       StatusCheckBreak(out);
     }
   }
   if (options.GenLog()) {
-    out << cpp::GenLogBeforeExecute(ClassName(defined_type, ClassNames::SERVER), method,
-                                    true /* isServer */, true /* isNdk */);
+    out << cpp::GenLogBeforeExecute(q_name, method, true /* isServer */, true /* isNdk */);
   }
   out << "::ndk::ScopedAStatus _aidl_status = _aidl_impl->" << method.GetName() << "("
       << NdkArgList(types, method, FormatArgForCall) << ");\n";
 
   if (options.GenLog()) {
-    out << cpp::GenLogAfterExecute(ClassName(defined_type, ClassNames::SERVER), defined_type,
-                                   method, "_aidl_status", "_aidl_return", true /* isServer */,
-                                   true /* isNdk */);
+    out << cpp::GenLogAfterExecute(q_name, defined_type, method, "_aidl_status", "_aidl_return",
+                                   true /* isServer */, true /* isNdk */);
   }
   if (method.IsOneway()) {
     // For a oneway transaction, the kernel will have already returned a result. This is for the
@@ -570,23 +669,24 @@
   out << "}\n";
 }
 
+static string OnTransactFuncName(const AidlInterface& interface) {
+  string name = interface.GetCanonicalName();
+  std::replace(name.begin(), name.end(), '.', '_');
+  return "_aidl_" + name + "_onTransact";
+}
+
+static string GlobalClassVarName(const AidlInterface& interface) {
+  string name = interface.GetCanonicalName();
+  std::replace(name.begin(), name.end(), '.', '_');
+  return "_g_aidl_" + name + "_clazz";
+}
+
 void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
                          const AidlInterface& defined_type, const Options& options) {
-  const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
-  const std::string bn_clazz = ClassName(defined_type, ClassNames::SERVER);
-  if (options.GenTraces()) {
-    out << "class ScopedTrace {\n";
-    out.Indent();
-    out << "public:\n"
-        << "inline explicit ScopedTrace(const char* name) {\n"
-        << "ATrace_beginSection(name);\n"
-        << "}\n"
-        << "inline ~ScopedTrace() {\n"
-        << "ATrace_endSection();\n"
-        << "}\n";
-    out.Dedent();
-    out << "};\n";
-  }
+  const std::string i_name = GetQualifiedName(defined_type, ClassNames::INTERFACE);
+  const std::string q_name = GetQualifiedName(defined_type, ClassNames::SERVER);
+
+  const string on_transact = OnTransactFuncName(defined_type);
   bool deprecated = defined_type.IsDeprecated() ||
                     std::any_of(defined_type.GetMethods().begin(), defined_type.GetMethods().end(),
                                 [](const auto& m) { return m->IsDeprecated(); });
@@ -594,8 +694,7 @@
     out << "#pragma clang diagnostic push\n";
     out << "#pragma clang diagnostic ignored \"-Wdeprecated\"\n";
   }
-  out << "static binder_status_t "
-      << "_aidl_onTransact"
+  out << "static binder_status_t " << on_transact
       << "(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, "
          "AParcel* _aidl_out) {\n";
   out.Indent();
@@ -605,7 +704,7 @@
   if (!defined_type.GetMethods().empty()) {
     // we know this cast is valid because this method is only called by the ICInterface
     // AIBinder_Class object which is associated with this class.
-    out << "std::shared_ptr<" << bn_clazz << "> _aidl_impl = std::static_pointer_cast<" << bn_clazz
+    out << "std::shared_ptr<" << q_name << "> _aidl_impl = std::static_pointer_cast<" << q_name
         << ">(::ndk::ICInterface::asInterface(_aidl_binder));\n";
     out << "switch (_aidl_code) {\n";
     out.Indent();
@@ -622,8 +721,9 @@
   out.Dedent();
   out << "}\n\n";
 
-  out << "static AIBinder_Class* " << kClazz << " = ::ndk::ICInterface::defineClass(" << clazz
-      << "::" << kDescriptor << ", _aidl_onTransact);\n\n";
+  out << "static AIBinder_Class* " << GlobalClassVarName(defined_type)
+      << " = ::ndk::ICInterface::defineClass(" << i_name << "::" << kDescriptor << ", "
+      << on_transact << ");\n\n";
   if (deprecated) {
     out << "#pragma clang diagnostic pop\n";
   }
@@ -631,32 +731,38 @@
 
 void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
                           const AidlInterface& defined_type, const Options& options) {
+  const std::string q_name = GetQualifiedName(defined_type, ClassNames::CLIENT);
   const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
 
-  out << clazz << "::" << clazz << "(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}\n";
-  out << clazz << "::~" << clazz << "() {}\n";
+  out << q_name << "::" << clazz << "(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}\n";
+  out << q_name << "::~" << clazz << "() {}\n";
   if (options.GenLog()) {
-    out << "std::function<void(const " + clazz + "::TransactionLog&)> " << clazz << "::logFunc;\n";
+    out << "std::function<void(const " << q_name << "::TransactionLog&)> " << q_name
+        << "::logFunc;\n";
   }
   out << "\n";
   for (const auto& method : defined_type.GetMethods()) {
     GenerateClientMethodDefinition(out, types, defined_type, *method, options);
   }
 }
+
 void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
                           const AidlInterface& defined_type, const Options& options) {
+  const std::string q_name = GetQualifiedName(defined_type, ClassNames::SERVER);
   const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
   const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
 
   out << "// Source for " << clazz << "\n";
-  out << clazz << "::" << clazz << "() {}\n";
-  out << clazz << "::~" << clazz << "() {}\n";
+  out << q_name << "::" << clazz << "() {}\n";
+  out << q_name << "::~" << clazz << "() {}\n";
   if (options.GenLog()) {
-    out << "std::function<void(const " + clazz + "::TransactionLog&)> " << clazz << "::logFunc;\n";
+    out << "std::function<void(const " << q_name << "::TransactionLog&)> " << q_name
+        << "::logFunc;\n";
   }
-  out << "::ndk::SpAIBinder " << clazz << "::createBinder() {\n";
+  out << "::ndk::SpAIBinder " << q_name << "::createBinder() {\n";
   out.Indent();
-  out << "AIBinder* binder = AIBinder_new(" << kClazz << ", static_cast<void*>(this));\n";
+  out << "AIBinder* binder = AIBinder_new(" << GlobalClassVarName(defined_type)
+      << ", static_cast<void*>(this));\n";
 
   out << "#ifdef BINDER_STABILITY_SUPPORT\n";
   if (defined_type.IsVintfStability()) {
@@ -676,7 +782,7 @@
       continue;
     }
     if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
-      out << NdkMethodDecl(types, *method, clazz) << " {\n";
+      out << NdkMethodDecl(types, *method, q_name) << " {\n";
       out.Indent();
       out << "*_aidl_return = " << iface << "::" << kVersion << ";\n";
       out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
@@ -684,7 +790,7 @@
       out << "}\n";
     }
     if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
-      out << NdkMethodDecl(types, *method, clazz) << " {\n";
+      out << NdkMethodDecl(types, *method, q_name) << " {\n";
       out.Indent();
       out << "*_aidl_return = " << iface << "::" << kHash << ";\n";
       out << "return ::ndk::ScopedAStatus(AStatus_newOk());\n";
@@ -695,22 +801,24 @@
 }
 void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types,
                              const AidlInterface& defined_type, const Options& options) {
+  const std::string q_name = GetQualifiedName(defined_type, ClassNames::INTERFACE);
   const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
   const std::string bp_clazz = ClassName(defined_type, ClassNames::CLIENT);
 
   out << "// Source for " << clazz << "\n";
-  out << "const char* " << clazz << "::" << kDescriptor << " = \"" << defined_type.GetDescriptor()
+  out << "const char* " << q_name << "::" << kDescriptor << " = \"" << defined_type.GetDescriptor()
       << "\";\n";
-  out << clazz << "::" << clazz << "() {}\n";
-  out << clazz << "::~" << clazz << "() {}\n";
+  out << q_name << "::" << clazz << "() {}\n";
+  out << q_name << "::~" << clazz << "() {}\n";
   out << "\n";
-  GenerateConstantDefinitions(out, defined_type, clazz);
+  GenerateConstantDefinitions(out, defined_type, q_name);
   out << "\n";
 
-  out << "std::shared_ptr<" << clazz << "> " << clazz
+  out << "std::shared_ptr<" << q_name << "> " << q_name
       << "::fromBinder(const ::ndk::SpAIBinder& binder) {\n";
   out.Indent();
-  out << "if (!AIBinder_associateClass(binder.get(), " << kClazz << ")) { return nullptr; }\n";
+  out << "if (!AIBinder_associateClass(binder.get(), " << GlobalClassVarName(defined_type)
+      << ")) { return nullptr; }\n";
   out << "std::shared_ptr<::ndk::ICInterface> interface = "
          "::ndk::ICInterface::asInterface(binder.get());\n";
   out << "if (interface) {\n";
@@ -718,11 +826,12 @@
   out << "return std::static_pointer_cast<" << clazz << ">(interface);\n";
   out.Dedent();
   out << "}\n";
-  out << "return ::ndk::SharedRefBase::make<" << bp_clazz << ">(binder);\n";
+  out << "return ::ndk::SharedRefBase::make<" << GetQualifiedName(defined_type, ClassNames::CLIENT)
+      << ">(binder);\n";
   out.Dedent();
   out << "}\n\n";
 
-  out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel, const std::shared_ptr<"
+  out << "binder_status_t " << q_name << "::writeToParcel(AParcel* parcel, const std::shared_ptr<"
       << clazz << ">& instance) {\n";
   out.Indent();
   out << "return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : "
@@ -730,7 +839,7 @@
   out.Dedent();
   out << "}\n";
 
-  out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel, std::shared_ptr<"
+  out << "binder_status_t " << q_name << "::readFromParcel(const AParcel* parcel, std::shared_ptr<"
       << clazz << ">* instance) {\n";
   out.Indent();
   out << "::ndk::SpAIBinder binder;\n";
@@ -742,7 +851,7 @@
   out << "}\n";
 
   // defintion for static member setDefaultImpl
-  out << "bool " << clazz << "::setDefaultImpl(const std::shared_ptr<" << clazz << ">& impl) {\n";
+  out << "bool " << q_name << "::setDefaultImpl(const std::shared_ptr<" << clazz << ">& impl) {\n";
   out.Indent();
   out << "// Only one user of this interface can use this function\n";
   out << "// at a time. This is a heuristic to detect if two different\n";
@@ -759,17 +868,17 @@
   out << "}\n";
 
   // definition for static member getDefaultImpl
-  out << "const std::shared_ptr<" << clazz << ">& " << clazz << "::getDefaultImpl() {\n";
+  out << "const std::shared_ptr<" << q_name << ">& " << q_name << "::getDefaultImpl() {\n";
   out.Indent();
   out << "return " << clazz << "::default_impl;\n";
   out.Dedent();
   out << "}\n";
 
   // definition for the static field default_impl
-  out << "std::shared_ptr<" << clazz << "> " << clazz << "::default_impl = nullptr;\n";
+  out << "std::shared_ptr<" << q_name << "> " << q_name << "::default_impl = nullptr;\n";
 
   // default implementation for the <Name>Default class members
-  const std::string defaultClazz = clazz + "Default";
+  const std::string defaultClazz = q_name + "Default";
   for (const auto& method : defined_type.GetMethods()) {
     if (method->IsUserDefined()) {
       out << "::ndk::ScopedAStatus " << defaultClazz << "::" << method->GetName() << "("
@@ -815,25 +924,10 @@
   out << "}\n";
 }
 
-void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
-                          const AidlInterface& defined_type, const Options& options) {
+void GenerateClientClassDecl(CodeWriter& out, const AidlTypenames& types,
+                             const AidlInterface& defined_type, const Options& options) {
   const std::string clazz = ClassName(defined_type, ClassNames::CLIENT);
 
-  out << "#pragma once\n\n";
-  out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
-      << "\"\n";
-  out << "\n";
-  out << "#include <android/binder_ibinder.h>\n";
-  if (options.GenLog()) {
-    out << "#include <functional>\n";
-    out << "#include <chrono>\n";
-    out << "#include <sstream>\n";
-  }
-  if (options.GenTraces()) {
-    out << "#include <android/trace.h>\n";
-  }
-  out << "\n";
-  EnterNdkNamespace(out, defined_type);
   out << "class";
   cpp::GenerateDeprecated(out, defined_type);
   out << " " << clazz << " : public ::ndk::BpCInterface<"
@@ -863,20 +957,34 @@
   }
   out.Dedent();
   out << "};\n";
-  LeaveNdkNamespace(out, defined_type);
 }
-void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
-                          const AidlInterface& defined_type, const Options& options) {
-  const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
-  const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
 
+void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
+                          const AidlInterface& defined_type, const Options& options) {
   out << "#pragma once\n\n";
   out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
       << "\"\n";
   out << "\n";
   out << "#include <android/binder_ibinder.h>\n";
+  if (options.GenLog()) {
+    out << "#include <functional>\n";
+    out << "#include <chrono>\n";
+    out << "#include <sstream>\n";
+  }
+  if (options.GenTraces()) {
+    out << "#include <android/trace.h>\n";
+  }
   out << "\n";
   EnterNdkNamespace(out, defined_type);
+  GenerateClientClassDecl(out, types, defined_type, options);
+  LeaveNdkNamespace(out, defined_type);
+}
+
+void GenerateServerClassDecl(CodeWriter& out, const AidlTypenames& types,
+                             const AidlInterface& defined_type, const Options& options) {
+  const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
+  const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
+
   out << "class";
   cpp::GenerateDeprecated(out, defined_type);
   out << " " << clazz << " : public ::ndk::BnCInterface<" << iface << "> {\n";
@@ -911,25 +1019,25 @@
   out.Indent();
   out.Dedent();
   out << "};\n";
+}
+
+void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
+                          const AidlInterface& defined_type, const Options& options) {
+  out << "#pragma once\n\n";
+  out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
+      << "\"\n";
+  out << "\n";
+  out << "#include <android/binder_ibinder.h>\n";
+  out << "\n";
+  EnterNdkNamespace(out, defined_type);
+  GenerateServerClassDecl(out, types, defined_type, options);
   LeaveNdkNamespace(out, defined_type);
 }
-void GenerateInterfaceHeader(CodeWriter& out, const AidlTypenames& types,
-                             const AidlInterface& defined_type, const Options& options) {
+
+void GenerateInterfaceClassDecl(CodeWriter& out, const AidlTypenames& types,
+                                const AidlInterface& defined_type, const Options& options) {
   const std::string clazz = ClassName(defined_type, ClassNames::INTERFACE);
 
-  out << "#pragma once\n\n";
-  out << "#include <android/binder_interface_utils.h>\n";
-  if (options.GenLog()) {
-    out << "#include <functional>\n";
-    out << "#include <chrono>\n";
-    out << "#include <sstream>\n";
-  }
-  out << "\n";
-
-  GenerateHeaderIncludes(out, types, defined_type);
-  out << "\n";
-
-  EnterNdkNamespace(out, defined_type);
   out << "class";
   cpp::GenerateDeprecated(out, defined_type);
   out << " " << clazz << " : public ::ndk::ICInterface {\n";
@@ -939,6 +1047,7 @@
   out << clazz << "();\n";
   out << "virtual ~" << clazz << "();\n";
   out << "\n";
+  GenerateNestedTypeDecls(out, types, defined_type, options);
   GenerateConstantDeclarations(out, types, defined_type);
   if (options.Version() > 0) {
     out << "static const int32_t " << kVersion << " = " << std::to_string(options.Version())
@@ -1000,23 +1109,18 @@
   out.Dedent();
   out << "};\n";
 
-  LeaveNdkNamespace(out, defined_type);
+  // When an interface is nested, every class should be defined together here
+  // because we don't have separate headers for them.
+  // (e.g. IFoo, IFooDefault, BpFoo, BnFoo, IFooDelegator)
+  if (defined_type.GetParentType()) {
+    GenerateClientClassDecl(out, types, defined_type, options);
+    GenerateServerClassDecl(out, types, defined_type, options);
+  }
 }
-void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
-                          const AidlStructuredParcelable& defined_type,
-                          const Options& /*options*/) {
+
+void GenerateParcelClassDecl(CodeWriter& out, const AidlTypenames& types,
+                             const AidlStructuredParcelable& defined_type, const Options& options) {
   const std::string clazz = ClassName(defined_type, ClassNames::RAW);
-
-  out << "#pragma once\n";
-  out << "#include <android/binder_interface_utils.h>\n";
-  out << "#include <android/binder_parcelable_utils.h>\n";
-
-  // used by toString()
-  out << "#include <android/binder_to_string.h>\n";
-
-  GenerateHeaderIncludes(out, types, defined_type);
-
-  EnterNdkNamespace(out, defined_type);
   out << cpp::TemplateDecl(defined_type);
   out << "class";
   cpp::GenerateDeprecated(out, defined_type);
@@ -1030,28 +1134,36 @@
   }
   out << "static const char* descriptor;\n";
   out << "\n";
+  GenerateNestedTypeDecls(out, types, defined_type, options);
   for (const auto& variable : defined_type.GetFields()) {
-    out << NdkNameOf(types, variable->GetType(), StorageMode::STACK);
+    const auto& type = variable->GetType();
+    std::string cpp_type = NdkNameOf(types, type, StorageMode::STACK);
+    out << cpp_type;
     cpp::GenerateDeprecated(out, *variable);
     out << " " << variable->GetName();
-    if (variable->GetType().GetName() == "ParcelableHolder") {
-      out << "{::ndk::" << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL")
-          << "}";
-    }
     if (defined_type.IsFixedSize()) {
-      int alignment = NdkAlignmentOf(types, variable->GetType());
+      int alignment = cpp::AlignmentOf(type, types);
       if (alignment > 0) {
         out << " __attribute__((aligned (" << std::to_string(alignment) << ")))";
       }
     }
     if (variable->GetDefaultValue()) {
       out << " = " << variable->ValueString(ConstantValueDecorator);
-    } else if (auto type = variable->GetType().GetDefinedType(); type) {
-      if (auto enum_type = type->AsEnumDeclaration(); enum_type) {
-        if (!variable->GetType().IsArray()) {
-          // if an enum doesn't have explicit default value, do zero-initialization
-          out << " = " << NdkNameOf(types, variable->GetType(), StorageMode::STACK) << "(0)";
+    } else {
+      // Some types needs to be explicitly initialized even when no default value is set.
+      // - ParcelableHolder should be initialized with stability.
+      // - enum should be zero initialized, otherwise the value will be indeterminate
+      // - fixed-size arrays should be initialized, otherwise the value will be indeterminate
+      if (type.GetName() == "ParcelableHolder") {
+        if (defined_type.IsVintfStability()) {
+          out << "{::ndk::STABILITY_VINTF}";
+        } else {
+          out << "{::ndk::STABILITY_LOCAL}";
         }
+      } else if (types.GetEnumDeclaration(type) && !type.IsArray()) {
+        out << " = " << cpp_type << "(0)";
+      } else if (type.IsFixedSizeArray() && !type.IsNullable()) {
+        out << " = {{}}";
       }
     }
     out << ";\n";
@@ -1071,12 +1183,10 @@
 
   out.Dedent();
   out << "};\n";
-  LeaveNdkNamespace(out, defined_type);
 }
 void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
-                          const AidlStructuredParcelable& defined_type,
-                          const Options& /*options*/) {
-  std::string clazz = ClassName(defined_type, ClassNames::RAW);
+                          const AidlStructuredParcelable& defined_type, const Options& options) {
+  std::string clazz = GetQualifiedName(defined_type);
   if (defined_type.IsGeneric()) {
     std::vector<std::string> template_params;
     for (const auto& parameter : defined_type.GetTypeParameters()) {
@@ -1085,11 +1195,7 @@
     clazz += base::StringPrintf("<%s>", base::Join(template_params, ", ").c_str());
   }
 
-  out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
-      << "\"\n";
-  out << "\n";
-  GenerateSourceIncludes(out, types, defined_type);
-  out << "\n";
+  GenerateSourceIncludes(out, types, defined_type, options);
   EnterNdkNamespace(out, defined_type);
   out << cpp::TemplateDecl(defined_type);
   out << "const char* " << clazz << "::" << kDescriptor << " = \""
@@ -1099,49 +1205,50 @@
   GenerateConstantDefinitions(out, defined_type, clazz, cpp::TemplateDecl(defined_type));
 
   out << cpp::TemplateDecl(defined_type);
-  out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* parcel) {\n";
+  out << "binder_status_t " << clazz << "::readFromParcel(const AParcel* _aidl_parcel) {\n";
   out.Indent();
-  out << "int32_t _aidl_parcelable_size;\n";
-  out << "int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
-  out << "binder_status_t _aidl_ret_status = AParcel_readInt32(parcel, &_aidl_parcelable_size);\n";
-  out << "if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;\n";
-  out << "if (_aidl_parcelable_size < 0) return STATUS_BAD_VALUE;\n";
+  out << "binder_status_t _aidl_ret_status = STATUS_OK;\n";
+  out << "int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);\n";
+  out << "int32_t _aidl_parcelable_size = 0;\n";
+  out << "_aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);\n";
   StatusCheckReturn(out);
-
+  out << "if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;\n";
+  out << "if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;\n";
   for (const auto& variable : defined_type.GetFields()) {
-    out << "if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {\n"
-        << "  AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
+    out << "if (AParcel_getDataPosition(_aidl_parcel) - _aidl_start_pos >= _aidl_parcelable_size) "
+           "{\n"
+        << "  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
         << "  return _aidl_ret_status;\n"
         << "}\n";
     out << "_aidl_ret_status = ";
-    ReadFromParcelFor({out, types, variable->GetType(), "parcel", "&" + variable->GetName()});
+    ReadFromParcelFor({out, types, variable->GetType(), "_aidl_parcel", "&" + variable->GetName()});
     out << ";\n";
     StatusCheckReturn(out);
   }
-  out << "AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
+  out << "AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);\n"
       << "return _aidl_ret_status;\n";
   out.Dedent();
   out << "}\n";
 
   out << cpp::TemplateDecl(defined_type);
-  out << "binder_status_t " << clazz << "::writeToParcel(AParcel* parcel) const {\n";
+  out << "binder_status_t " << clazz << "::writeToParcel(AParcel* _aidl_parcel) const {\n";
   out.Indent();
   out << "binder_status_t _aidl_ret_status;\n";
 
-  out << "size_t _aidl_start_pos = AParcel_getDataPosition(parcel);\n";
-  out << "_aidl_ret_status = AParcel_writeInt32(parcel, 0);\n";
+  out << "size_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);\n";
+  out << "_aidl_ret_status = AParcel_writeInt32(_aidl_parcel, 0);\n";
   StatusCheckReturn(out);
 
   for (const auto& variable : defined_type.GetFields()) {
     out << "_aidl_ret_status = ";
-    WriteToParcelFor({out, types, variable->GetType(), "parcel", variable->GetName()});
+    WriteToParcelFor({out, types, variable->GetType(), "_aidl_parcel", variable->GetName()});
     out << ";\n";
     StatusCheckReturn(out);
   }
-  out << "size_t _aidl_end_pos = AParcel_getDataPosition(parcel);\n";
-  out << "AParcel_setDataPosition(parcel, _aidl_start_pos);\n";
-  out << "AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);\n";
-  out << "AParcel_setDataPosition(parcel, _aidl_end_pos);\n";
+  out << "size_t _aidl_end_pos = AParcel_getDataPosition(_aidl_parcel);\n";
+  out << "AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos);\n";
+  out << "AParcel_writeInt32(_aidl_parcel, _aidl_end_pos - _aidl_start_pos);\n";
+  out << "AParcel_setDataPosition(_aidl_parcel, _aidl_end_pos);\n";
 
   out << "return _aidl_ret_status;\n";
   out.Dedent();
@@ -1150,8 +1257,8 @@
   LeaveNdkNamespace(out, defined_type);
 }
 
-void GenerateParcelHeader(CodeWriter& out, const AidlTypenames& types,
-                          const AidlUnionDecl& defined_type, const Options& /*options*/) {
+void GenerateParcelClassDecl(CodeWriter& out, const AidlTypenames& types,
+                             const AidlUnionDecl& defined_type, const Options& options) {
   const std::string clazz = ClassName(defined_type, ClassNames::RAW);
   cpp::UnionWriter uw{defined_type, types,
                       [&](const AidlTypeSpecifier& type, const AidlTypenames& types) {
@@ -1159,28 +1266,6 @@
                       },
                       &ConstantValueDecorator};
 
-  out << "#pragma once\n";
-  out << "#include <android/binder_interface_utils.h>\n";
-  out << "#include <android/binder_parcelable_utils.h>\n";
-
-  // used by toString()
-  out << "#include <android/binder_to_string.h>\n";
-
-  out << "\n";
-
-  for (const auto& header : cpp::UnionWriter::headers) {
-    out << "#include <" << header << ">\n";
-  }
-  GenerateHeaderIncludes(out, types, defined_type);
-
-  // TODO(b/31559095) bionic on host should define this
-  out << "\n";
-  out << "#ifndef __BIONIC__\n";
-  out << "#define __assert2(a,b,c,d) ((void)0)\n";
-  out << "#endif\n";
-  out << "\n";
-
-  EnterNdkNamespace(out, defined_type);
   out << cpp::TemplateDecl(defined_type);
   out << "class";
   cpp::GenerateDeprecated(out, defined_type);
@@ -1194,6 +1279,7 @@
   }
   out << "static const char* descriptor;\n";
   out << "\n";
+  GenerateNestedTypeDecls(out, types, defined_type, options);
   uw.PublicFields(out);
 
   out << "binder_status_t readFromParcel(const AParcel* _parcel);\n";
@@ -1212,11 +1298,10 @@
   uw.PrivateFields(out);
   out.Dedent();
   out << "};\n";
-  LeaveNdkNamespace(out, defined_type);
 }
 void GenerateParcelSource(CodeWriter& out, const AidlTypenames& types,
-                          const AidlUnionDecl& defined_type, const Options& /*options*/) {
-  std::string clazz = ClassName(defined_type, ClassNames::RAW);
+                          const AidlUnionDecl& defined_type, const Options& options) {
+  std::string clazz = GetQualifiedName(defined_type);
   if (defined_type.IsGeneric()) {
     std::vector<std::string> template_params;
     for (const auto& parameter : defined_type.GetTypeParameters()) {
@@ -1244,11 +1329,7 @@
           },
   };
 
-  out << "#include \"" << NdkHeaderFile(defined_type, ClassNames::RAW, false /*use_os_sep*/)
-      << "\"\n";
-  out << "\n";
-  GenerateSourceIncludes(out, types, defined_type);
-  out << "\n";
+  GenerateSourceIncludes(out, types, defined_type, options);
   EnterNdkNamespace(out, defined_type);
   out << cpp::TemplateDecl(defined_type);
   out << "const char* " << clazz << "::" << kDescriptor << " = \""
@@ -1274,70 +1355,12 @@
   LeaveNdkNamespace(out, defined_type);
 }
 
-std::string GenerateEnumToString(const AidlTypenames& typenames,
-                                 const AidlEnumDeclaration& enum_decl) {
-  std::ostringstream code;
-  const std::string signature =
-      "[[nodiscard]] static inline std::string toString(" + enum_decl.GetName() + " val)";
-  if (enum_decl.IsDeprecated()) {
-    code << signature;
-    cpp::GenerateDeprecated(code, enum_decl);
-    code << ";\n";
-  }
-  code << signature << " {\n";
-  code << "  switch(val) {\n";
-  std::set<std::string> unique_cases;
-  for (const auto& enumerator : enum_decl.GetEnumerators()) {
-    std::string c = enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator);
-    // Only add a case if its value has not yet been used in the switch
-    // statement. C++ does not allow multiple cases with the same value, but
-    // enums does allow this. In this scenario, the first declared
-    // enumerator with the given value is printed.
-    if (unique_cases.count(c) == 0) {
-      unique_cases.insert(c);
-      code << "  case " << enum_decl.GetName() << "::" << enumerator->GetName() << ":\n";
-      code << "    return \"" << enumerator->GetName() << "\";\n";
-    }
-  }
-  code << "  default:\n";
-  code << "    return std::to_string(static_cast<"
-       << NdkNameOf(typenames, enum_decl.GetBackingType(), StorageMode::STACK) << ">(val));\n";
-  code << "  }\n";
-  code << "}\n";
-  return code.str();
-}
-
-void GenerateEnumHeader(CodeWriter& out, const AidlTypenames& types,
-                        const AidlEnumDeclaration& enum_decl, const Options& /*options*/) {
-  out << "#pragma once\n";
+void GenerateEnumClassDecl(CodeWriter& out, const AidlTypenames& types,
+                           const AidlEnumDeclaration& enum_decl, const Options&) {
+  cpp::GenerateEnumClassDecl(out, enum_decl,
+                             NdkNameOf(types, enum_decl.GetBackingType(), StorageMode::STACK),
+                             ConstantValueDecorator);
   out << "\n";
-
-  GenerateHeaderIncludes(out, types, enum_decl);
-  // enum specific headers
-  out << "#include <array>\n";
-  out << "#include <android/binder_enums.h>\n";
-
-  EnterNdkNamespace(out, enum_decl);
-  out << "enum class";
-  cpp::GenerateDeprecated(out, enum_decl);
-  out << " " << enum_decl.GetName() << " : "
-      << NdkNameOf(types, enum_decl.GetBackingType(), StorageMode::STACK) << " {\n";
-  out.Indent();
-  for (const auto& enumerator : enum_decl.GetEnumerators()) {
-    out << enumerator->GetName() << " = "
-        << enumerator->ValueString(enum_decl.GetBackingType(), ConstantValueDecorator) << ",\n";
-  }
-  out.Dedent();
-  out << "};\n";
-  out << "\n";
-  out << GenerateEnumToString(types, enum_decl);
-  LeaveNdkNamespace(out, enum_decl);
-
-  out << "namespace ndk {\n";
-  out << "namespace internal {\n";
-  out << cpp::GenerateEnumValues(enum_decl, {"aidl"});
-  out << "}  // namespace internal\n";
-  out << "}  // namespace android\n";
 }
 
 }  // namespace internals
diff --git a/generate_ndk.h b/generate_ndk.h
index 6b893a3..d9bc910 100644
--- a/generate_ndk.h
+++ b/generate_ndk.h
@@ -29,28 +29,6 @@
 void GenerateNdk(const string& output_file, const Options& options, const AidlTypenames& types,
                  const AidlDefinedType& defined_type, const IoDelegate& io_delegate);
 
-namespace internals {
-void GenerateSource(CodeWriter& out, const AidlTypenames& types, const AidlInterface& defined_type,
-                    const Options& options);
-void GenerateClassSource(CodeWriter& out, const AidlTypenames& types,
-                         const AidlInterface& defined_type, const Options& options);
-void GenerateClientSource(CodeWriter& out, const AidlTypenames& types,
-                          const AidlInterface& defined_type, const Options& options);
-void GenerateServerSource(CodeWriter& out, const AidlTypenames& types,
-                          const AidlInterface& defined_type, const Options& options);
-void GenerateInterfaceSource(CodeWriter& out, const AidlTypenames& types,
-                             const AidlInterface& defined_type, const Options& options);
-void GenerateClientHeader(CodeWriter& out, const AidlTypenames& types,
-                          const AidlInterface& defined_type, const Options& options);
-void GenerateServerHeader(CodeWriter& out, const AidlTypenames& types,
-                          const AidlInterface& defined_type, const Options& options);
-void GenerateInterfaceHeader(CodeWriter& out, const AidlTypenames& types,
-                             const AidlInterface& defined_type, const Options& options);
-
-void GenerateEnumHeader(CodeWriter& out, const AidlTypenames& types,
-                        const AidlEnumDeclaration& enum_decl, const Options& options);
-
-}  // namespace internals
 }  // namespace ndk
 }  // namespace aidl
 }  // namespace android
diff --git a/generate_rust.cpp b/generate_rust.cpp
index 3817f64..079a6c7 100644
--- a/generate_rust.cpp
+++ b/generate_rust.cpp
@@ -33,6 +33,7 @@
 #include "logging.h"
 
 using android::base::Join;
+using android::base::Split;
 using std::ostringstream;
 using std::shared_ptr;
 using std::string;
@@ -47,73 +48,128 @@
 static constexpr const char kGetInterfaceVersion[] = "getInterfaceVersion";
 static constexpr const char kGetInterfaceHash[] = "getInterfaceHash";
 
-void GenerateMangledAlias(CodeWriter& out, const AidlDefinedType* type) {
-  ostringstream alias;
-  for (const auto& component : type->GetSplitPackage()) {
-    alias << "_" << component.size() << "_" << component;
-  }
-  alias << "_" << type->GetName().size() << "_" << type->GetName();
-  out << "pub(crate) mod mangled { pub use super::" << type->GetName() << " as " << alias.str()
-      << "; }\n";
+void GenerateMangledAliases(CodeWriter& out, const AidlDefinedType& type) {
+  struct Visitor : AidlVisitor {
+    CodeWriter& out;
+    Visitor(CodeWriter& out) : out(out) {}
+    void Visit(const AidlStructuredParcelable& type) override { VisitType(type); }
+    void Visit(const AidlInterface& type) override { VisitType(type); }
+    void Visit(const AidlEnumDeclaration& type) override { VisitType(type); }
+    void Visit(const AidlUnionDecl& type) override { VisitType(type); }
+    void VisitType(const AidlDefinedType& type) {
+      out << " pub use " << Qname(type) << " as " << Mangled(type) << ";\n";
+    }
+    // Return a mangled name for a type (including AIDL package)
+    string Mangled(const AidlDefinedType& type) const {
+      ostringstream alias;
+      for (const auto& component : Split(type.GetCanonicalName(), ".")) {
+        alias << "_" << component.size() << "_" << component;
+      }
+      return alias.str();
+    }
+    // Return a fully qualified name for a type in the current file (excluding AIDL package)
+    string Qname(const AidlDefinedType& type) const { return Module(type) + "::" + type.GetName(); }
+    // Return a module name for a type (relative to the file)
+    string Module(const AidlDefinedType& type) const {
+      if (type.GetParentType()) {
+        return Module(*type.GetParentType()) + "::" + type.GetName();
+      } else {
+        return "super";
+      }
+    }
+  } v(out);
+  out << "pub(crate) mod mangled {\n";
+  VisitTopDown(v, type);
+  out << "}\n";
 }
 
-string BuildArg(const AidlArgument& arg, const AidlTypenames& typenames) {
+string BuildArg(const AidlArgument& arg, const AidlTypenames& typenames, Lifetime lifetime) {
   // We pass in parameters that are not primitives by const reference.
   // Arrays get passed in as slices, which is handled in RustNameOf.
   auto arg_mode = ArgumentStorageMode(arg, typenames);
-  auto arg_type = RustNameOf(arg.GetType(), typenames, arg_mode);
+  auto arg_type = RustNameOf(arg.GetType(), typenames, arg_mode, lifetime);
   return kArgumentPrefix + arg.GetName() + ": " + arg_type;
 }
 
-string BuildMethod(const AidlMethod& method, const AidlTypenames& typenames) {
-  auto method_type = RustNameOf(method.GetType(), typenames, StorageMode::VALUE);
-  auto return_type = string{"binder::public_api::Result<"} + method_type + ">";
+enum class MethodKind {
+  // This is a normal non-async method.
+  NORMAL,
+  // This is an async method. Identical to NORMAL except that async is added
+  // in front of `fn`.
+  ASYNC,
+  // This is an async function, but using a boxed future instead of the async
+  // keyword.
+  BOXED_FUTURE,
+  // This could have been a non-async method, but it returns a Future so that
+  // it would not be breaking to make the function do async stuff in the future.
+  READY_FUTURE,
+};
+
+string BuildMethod(const AidlMethod& method, const AidlTypenames& typenames,
+                   const MethodKind kind = MethodKind::NORMAL) {
+  // We need to mark the arguments with a lifetime only when returning a future that
+  // actually captures the arguments.
+  Lifetime lifetime;
+  switch (kind) {
+    case MethodKind::NORMAL:
+    case MethodKind::ASYNC:
+    case MethodKind::READY_FUTURE:
+      lifetime = Lifetime::NONE;
+      break;
+    case MethodKind::BOXED_FUTURE:
+      lifetime = Lifetime::A;
+      break;
+  }
+
+  auto method_type = RustNameOf(method.GetType(), typenames, StorageMode::VALUE, lifetime);
+  auto return_type = string{"binder::Result<"} + method_type + ">";
+  auto fn_prefix = string{""};
+
+  switch (kind) {
+    case MethodKind::NORMAL:
+      // Don't wrap the return type in anything.
+      break;
+    case MethodKind::ASYNC:
+      fn_prefix = "async ";
+      break;
+    case MethodKind::BOXED_FUTURE:
+      return_type = "binder::BoxFuture<'a, " + return_type + ">";
+      break;
+    case MethodKind::READY_FUTURE:
+      return_type = "std::future::Ready<" + return_type + ">";
+      break;
+  }
+
+  string parameters = "&" + RustLifetimeName(lifetime) + "self";
+  string lifetime_str = RustLifetimeGeneric(lifetime);
+
+  for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
+    parameters += ", ";
+    parameters += BuildArg(*arg, typenames, lifetime);
+  }
+
+  return fn_prefix + "fn " + method.GetName() + lifetime_str + "(" + parameters + ") -> " +
+         return_type;
+}
+
+void GenerateClientMethodHelpers(CodeWriter& out, const AidlInterface& iface,
+                                 const AidlMethod& method, const AidlTypenames& typenames,
+                                 const Options& options, const std::string& default_trait_name) {
   string parameters = "&self";
   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
     parameters += ", ";
-    parameters += BuildArg(*arg, typenames);
-  }
-  return "fn " + method.GetName() + "(" + parameters + ") -> " + return_type;
-}
-
-void GenerateClientMethod(CodeWriter& out, const AidlInterface& iface, const AidlMethod& method,
-                          const AidlTypenames& typenames, const Options& options,
-                          const std::string& trait_name) {
-  // Generate the method
-  out << BuildMethod(method, typenames) << " {\n";
-  out.Indent();
-
-  if (!method.IsUserDefined()) {
-    if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
-      // Check if the version is in the cache
-      out << "let _aidl_version = "
-             "self.cached_version.load(std::sync::atomic::Ordering::Relaxed);\n";
-      out << "if _aidl_version != -1 { return Ok(_aidl_version); }\n";
-    }
-
-    if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
-      out << "{\n";
-      out << "  let _aidl_hash_lock = self.cached_hash.lock().unwrap();\n";
-      out << "  if let Some(ref _aidl_hash) = *_aidl_hash_lock {\n";
-      out << "    return Ok(_aidl_hash.clone());\n";
-      out << "  }\n";
-      out << "}\n";
-    }
+    parameters += BuildArg(*arg, typenames, Lifetime::NONE);
   }
 
-  // Call transact()
-  vector<string> flags;
-  if (method.IsOneway()) flags.push_back("binder::FLAG_ONEWAY");
-  if (iface.IsSensitiveData()) flags.push_back("binder::FLAG_CLEAR_BUF");
-  flags.push_back("binder::FLAG_PRIVATE_LOCAL");
-
-  string transact_flags = flags.empty() ? "0" : Join(flags, " | ");
-  out << "let _aidl_reply = self.binder.transact("
-      << "transactions::" << method.GetName() << ", " << transact_flags << ", |_aidl_data| {\n";
+  // Generate build_parcel helper.
+  out << "fn build_parcel_" + method.GetName() + "(" + parameters +
+             ") -> binder::Result<binder::binder_impl::Parcel> {\n";
   out.Indent();
 
+  out << "let mut aidl_data = self.binder.prepare_transact()?;\n";
+
   if (iface.IsSensitiveData()) {
-    out << "_aidl_data.mark_sensitive();\n";
+    out << "aidl_data.mark_sensitive();\n";
   }
 
   // Arguments
@@ -124,24 +180,31 @@
       // (unless we turned it into an Option<&T>)
       auto ref_mode = ArgumentReferenceMode(*arg, typenames);
       if (IsReference(ref_mode)) {
-        out << "_aidl_data.write(" << arg_name << ")?;\n";
+        out << "aidl_data.write(" << arg_name << ")?;\n";
       } else {
-        out << "_aidl_data.write(&" << arg_name << ")?;\n";
+        out << "aidl_data.write(&" << arg_name << ")?;\n";
       }
-    } else if (arg->GetType().IsArray()) {
+    } else if (arg->GetType().IsDynamicArray()) {
       // For out-only arrays, send the array size
       if (arg->GetType().IsNullable()) {
-        out << "_aidl_data.write_slice_size(" << arg_name << ".as_deref())?;\n";
+        out << "aidl_data.write_slice_size(" << arg_name << ".as_deref())?;\n";
       } else {
-        out << "_aidl_data.write_slice_size(Some(" << arg_name << "))?;\n";
+        out << "aidl_data.write_slice_size(Some(" << arg_name << "))?;\n";
       }
     }
   }
 
-  // Return Ok(()) if all the `_aidl_data.write(...)?;` calls pass
-  out << "Ok(())\n";
+  out << "Ok(aidl_data)\n";
   out.Dedent();
-  out << "});\n";
+  out << "}\n";
+
+  // Generate read_response helper.
+  auto return_type = RustNameOf(method.GetType(), typenames, StorageMode::VALUE, Lifetime::NONE);
+  out << "fn read_response_" + method.GetName() + "(" + parameters +
+             ", _aidl_reply: std::result::Result<binder::binder_impl::Parcel, "
+             "binder::StatusCode>) -> binder::Result<" +
+             return_type + "> {\n";
+  out.Indent();
 
   // Check for UNKNOWN_TRANSACTION and call the default impl
   if (method.IsUserDefined()) {
@@ -154,7 +217,7 @@
       default_args += arg->GetName();
     }
     out << "if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {\n";
-    out << "  if let Some(_aidl_default_impl) = <Self as " << trait_name
+    out << "  if let Some(_aidl_default_impl) = <Self as " << default_trait_name
         << ">::getDefaultImpl() {\n";
     out << "    return _aidl_default_impl." << method.GetName() << "(" << default_args << ");\n";
     out << "  }\n";
@@ -172,7 +235,8 @@
 
     // Return reply value
     if (method.GetType().GetName() != "void") {
-      auto return_type = RustNameOf(method.GetType(), typenames, StorageMode::VALUE);
+      auto return_type =
+          RustNameOf(method.GetType(), typenames, StorageMode::VALUE, Lifetime::NONE);
       out << "let _aidl_return: " << return_type << " = _aidl_reply.read()?;\n";
       return_val = "_aidl_return";
 
@@ -187,12 +251,138 @@
     }
 
     for (const AidlArgument* arg : method.GetOutArguments()) {
-      out << "*" << kArgumentPrefix << arg->GetName() << " = _aidl_reply.read()?;\n";
+      out << "_aidl_reply.read_onto(" << kArgumentPrefix << arg->GetName() << ")?;\n";
     }
   }
 
   // Return the result
   out << "Ok(" << return_val << ")\n";
+
+  out.Dedent();
+  out << "}\n";
+}
+
+void GenerateClientMethod(CodeWriter& out, const AidlInterface& iface, const AidlMethod& method,
+                          const AidlTypenames& typenames, const Options& options,
+                          const MethodKind kind) {
+  // Generate the method
+  out << BuildMethod(method, typenames, kind) << " {\n";
+  out.Indent();
+
+  if (!method.IsUserDefined()) {
+    if (method.GetName() == kGetInterfaceVersion && options.Version() > 0) {
+      // Check if the version is in the cache
+      out << "let _aidl_version = "
+             "self.cached_version.load(std::sync::atomic::Ordering::Relaxed);\n";
+      switch (kind) {
+        case MethodKind::NORMAL:
+        case MethodKind::ASYNC:
+          out << "if _aidl_version != -1 { return Ok(_aidl_version); }\n";
+          break;
+        case MethodKind::BOXED_FUTURE:
+          out << "if _aidl_version != -1 { return Box::pin(std::future::ready(Ok(_aidl_version))); "
+                 "}\n";
+          break;
+        case MethodKind::READY_FUTURE:
+          out << "if _aidl_version != -1 { return std::future::ready(Ok(_aidl_version)); }\n";
+          break;
+      }
+    }
+
+    if (method.GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+      out << "{\n";
+      out << "  let _aidl_hash_lock = self.cached_hash.lock().unwrap();\n";
+      out << "  if let Some(ref _aidl_hash) = *_aidl_hash_lock {\n";
+      switch (kind) {
+        case MethodKind::NORMAL:
+        case MethodKind::ASYNC:
+          out << "    return Ok(_aidl_hash.clone());\n";
+          break;
+        case MethodKind::BOXED_FUTURE:
+          out << "    return Box::pin(std::future::ready(Ok(_aidl_hash.clone())));\n";
+          break;
+        case MethodKind::READY_FUTURE:
+          out << "    return std::future::ready(Ok(_aidl_hash.clone()));\n";
+          break;
+      }
+      out << "  }\n";
+      out << "}\n";
+    }
+  }
+
+  string build_parcel_args;
+  for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
+    if (!build_parcel_args.empty()) {
+      build_parcel_args += ", ";
+    }
+    build_parcel_args += kArgumentPrefix;
+    build_parcel_args += arg->GetName();
+  }
+
+  string read_response_args =
+      build_parcel_args.empty() ? "_aidl_reply" : build_parcel_args + ", _aidl_reply";
+
+  vector<string> flags;
+  if (method.IsOneway()) flags.push_back("binder::binder_impl::FLAG_ONEWAY");
+  if (iface.IsSensitiveData()) flags.push_back("binder::binder_impl::FLAG_CLEAR_BUF");
+  flags.push_back("binder::binder_impl::FLAG_PRIVATE_LOCAL");
+
+  string transact_flags = flags.empty() ? "0" : Join(flags, " | ");
+
+  switch (kind) {
+    case MethodKind::NORMAL:
+    case MethodKind::ASYNC:
+      // Prepare transaction.
+      out << "let _aidl_data = self.build_parcel_" + method.GetName() + "(" + build_parcel_args +
+                 ")?;\n";
+      // Submit transaction.
+      out << "let _aidl_reply = self.binder.submit_transact(transactions::" << method.GetName()
+          << ", _aidl_data, " << transact_flags << ");\n";
+      // Deserialize response.
+      out << "self.read_response_" + method.GetName() + "(" + read_response_args + ")\n";
+      break;
+    case MethodKind::READY_FUTURE:
+      // Prepare transaction.
+      out << "let _aidl_data = match self.build_parcel_" + method.GetName() + "(" +
+                 build_parcel_args + ") {\n";
+      out.Indent();
+      out << "Ok(_aidl_data) => _aidl_data,\n";
+      out << "Err(err) => return std::future::ready(Err(err)),\n";
+      out.Dedent();
+      out << "};\n";
+      // Submit transaction.
+      out << "let _aidl_reply = self.binder.submit_transact(transactions::" << method.GetName()
+          << ", _aidl_data, " << transact_flags << ");\n";
+      // Deserialize response.
+      out << "std::future::ready(self.read_response_" + method.GetName() + "(" +
+                 read_response_args + "))\n";
+      break;
+    case MethodKind::BOXED_FUTURE:
+      // Prepare transaction.
+      out << "let _aidl_data = match self.build_parcel_" + method.GetName() + "(" +
+                 build_parcel_args + ") {\n";
+      out.Indent();
+      out << "Ok(_aidl_data) => _aidl_data,\n";
+      out << "Err(err) => return Box::pin(std::future::ready(Err(err))),\n";
+      out.Dedent();
+      out << "};\n";
+      // Submit transaction.
+      out << "let binder = self.binder.clone();\n";
+      out << "P::spawn(\n";
+      out.Indent();
+      out << "move || binder.submit_transact(transactions::" << method.GetName() << ", _aidl_data, "
+          << transact_flags << "),\n";
+      out << "move |_aidl_reply| async move {\n";
+      out.Indent();
+      // Deserialize response.
+      out << "self.read_response_" + method.GetName() + "(" + read_response_args + ")\n";
+      out.Dedent();
+      out << "}\n";
+      out.Dedent();
+      out << ")\n";
+      break;
+  }
+
   out.Dedent();
   out << "}\n";
 }
@@ -212,12 +402,12 @@
       // We need a value we can call Default::default() on
       arg_mode = StorageMode::DEFAULT_VALUE;
     }
-    auto arg_type = RustNameOf(arg->GetType(), typenames, arg_mode);
+    auto arg_type = RustNameOf(arg->GetType(), typenames, arg_mode, Lifetime::NONE);
 
     string arg_mut = arg->IsOut() ? "mut " : "";
     string arg_init = arg->IsIn() ? "_aidl_data.read()?" : "Default::default()";
     out << "let " << arg_mut << arg_name << ": " << arg_type << " = " << arg_init << ";\n";
-    if (!arg->IsIn() && arg->GetType().IsArray()) {
+    if (!arg->IsIn() && arg->GetType().IsDynamicArray()) {
       // _aidl_data.resize_[nullable_]out_vec(&mut _arg_foo)?;
       auto resize_name = arg->GetType().IsNullable() ? "resize_nullable_out_vec" : "resize_out_vec";
       out << "_aidl_data." << resize_name << "(&mut " << arg_name << ")?;\n";
@@ -253,7 +443,7 @@
         // any None, return UNEXPECTED_NULL (this is what libbinder_ndk does)
         out << "if " << arg_name << ".iter().any(Option::is_none) { "
             << "return Err(binder::StatusCode::UNEXPECTED_NULL); }\n";
-      } else if (!arg->IsIn() && !TypeHasDefault(arg_type, typenames)) {
+      } else if (!arg->IsIn() && TypeNeedsOption(arg_type, typenames)) {
         // Unwrap out-only arguments that we wrapped in Option<T>
         out << "let " << arg_name << " = " << arg_name
             << ".ok_or(binder::StatusCode::UNEXPECTED_NULL)?;\n";
@@ -278,7 +468,7 @@
   auto server_name = ClassName(*iface, cpp::ClassNames::SERVER);
 
   // Forward all IFoo functions from Binder to the inner object
-  out << "impl " << trait_name << " for binder::Binder<" << server_name << "> {\n";
+  out << "impl " << trait_name << " for binder::binder_impl::Binder<" << server_name << "> {\n";
   out.Indent();
   for (const auto& method : iface->GetMethods()) {
     string args;
@@ -299,9 +489,11 @@
          "_aidl_service: &dyn "
       << trait_name
       << ", "
-         "_aidl_code: binder::TransactionCode, "
-         "_aidl_data: &binder::parcel::Parcel, "
-         "_aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {\n";
+         "_aidl_code: binder::binder_impl::TransactionCode, "
+         "_aidl_data: &binder::binder_impl::BorrowedParcel<'_>, "
+         "_aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), "
+         "binder::StatusCode> "
+         "{\n";
   out.Indent();
   out << "match _aidl_code {\n";
   out.Indent();
@@ -337,7 +529,7 @@
       const_type = "&str";
     } else if (type.Signature() == "byte" || type.Signature() == "int" ||
                type.Signature() == "long") {
-      const_type = RustNameOf(type, typenames, StorageMode::VALUE);
+      const_type = RustNameOf(type, typenames, StorageMode::VALUE, Lifetime::NONE);
     } else {
       AIDL_FATAL(value) << "Unrecognized constant type: " << type.Signature();
     }
@@ -348,17 +540,16 @@
   }
 }
 
-bool GenerateRustInterface(const string& filename, const AidlInterface* iface,
-                           const AidlTypenames& typenames, const IoDelegate& io_delegate,
-                           const Options& options) {
-  CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
-
+void GenerateRustInterface(CodeWriter* code_writer, const AidlInterface* iface,
+                           const AidlTypenames& typenames, const Options& options) {
   *code_writer << "#![allow(non_upper_case_globals)]\n";
   *code_writer << "#![allow(non_snake_case)]\n";
   // Import IBinderInternal for transact()
-  *code_writer << "#[allow(unused_imports)] use binder::IBinderInternal;\n";
+  *code_writer << "#[allow(unused_imports)] use binder::binder_impl::IBinderInternal;\n";
 
   auto trait_name = ClassName(*iface, cpp::ClassNames::INTERFACE);
+  auto trait_name_async = trait_name + "Async";
+  auto trait_name_async_server = trait_name + "AsyncServer";
   auto client_name = ClassName(*iface, cpp::ClassNames::CLIENT);
   auto server_name = ClassName(*iface, cpp::ClassNames::SERVER);
   *code_writer << "use binder::declare_binder_interface;\n";
@@ -383,14 +574,16 @@
   }
   code_writer->Dedent();
   *code_writer << "},\n";
-  code_writer->Dedent();
+  *code_writer << "async: " << trait_name_async << ",\n";
   if (iface->IsVintfStability()) {
-    *code_writer << "stability: binder::Stability::Vintf,\n";
+    *code_writer << "stability: binder::binder_impl::Stability::Vintf,\n";
   }
+  code_writer->Dedent();
   *code_writer << "}\n";
   code_writer->Dedent();
   *code_writer << "}\n";
 
+  // Emit the trait.
   GenerateDeprecated(*code_writer, *iface);
   *code_writer << "pub trait " << trait_name << ": binder::Interface + Send {\n";
   code_writer->Indent();
@@ -430,6 +623,125 @@
   code_writer->Dedent();
   *code_writer << "}\n";
 
+  // Emit the async trait.
+  GenerateDeprecated(*code_writer, *iface);
+  *code_writer << "pub trait " << trait_name_async << "<P>: binder::Interface + Send {\n";
+  code_writer->Indent();
+  *code_writer << "fn get_descriptor() -> &'static str where Self: Sized { \""
+               << iface->GetDescriptor() << "\" }\n";
+
+  for (const auto& method : iface->GetMethods()) {
+    // Generate the method
+    GenerateDeprecated(*code_writer, *method);
+
+    MethodKind kind = method->IsOneway() ? MethodKind::READY_FUTURE : MethodKind::BOXED_FUTURE;
+
+    if (method->IsUserDefined()) {
+      *code_writer << BuildMethod(*method, typenames, kind) << ";\n";
+    } else {
+      // Generate default implementations for meta methods
+      *code_writer << BuildMethod(*method, typenames, kind) << " {\n";
+      code_writer->Indent();
+      if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
+        *code_writer << "Box::pin(async move { Ok(VERSION) })\n";
+      } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+        *code_writer << "Box::pin(async move { Ok(HASH.into()) })\n";
+      }
+      code_writer->Dedent();
+      *code_writer << "}\n";
+    }
+  }
+  code_writer->Dedent();
+  *code_writer << "}\n";
+
+  // Emit the async server trait.
+  GenerateDeprecated(*code_writer, *iface);
+  *code_writer << "#[::async_trait::async_trait]\n";
+  *code_writer << "pub trait " << trait_name_async_server << ": binder::Interface + Send {\n";
+  code_writer->Indent();
+  *code_writer << "fn get_descriptor() -> &'static str where Self: Sized { \""
+               << iface->GetDescriptor() << "\" }\n";
+
+  for (const auto& method : iface->GetMethods()) {
+    // Generate the method
+    if (method->IsUserDefined()) {
+      GenerateDeprecated(*code_writer, *method);
+      *code_writer << BuildMethod(*method, typenames, MethodKind::ASYNC) << ";\n";
+    }
+  }
+  code_writer->Dedent();
+  *code_writer << "}\n";
+
+  // Emit a new_async_binder method for binding an async server.
+  *code_writer << "impl " << server_name << " {\n";
+  code_writer->Indent();
+  *code_writer << "/// Create a new async binder service.\n";
+  *code_writer << "pub fn new_async_binder<T, R>(inner: T, rt: R, features: "
+                  "binder::BinderFeatures) -> binder::Strong<dyn "
+               << trait_name << ">\n";
+  *code_writer << "where\n";
+  code_writer->Indent();
+  *code_writer << "T: " << trait_name_async_server
+               << " + binder::Interface + Send + Sync + 'static,\n";
+  *code_writer << "R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,\n";
+  code_writer->Dedent();
+  *code_writer << "{\n";
+  code_writer->Indent();
+  // Define a wrapper struct that implements the non-async trait by calling block_on.
+  *code_writer << "struct Wrapper<T, R> {\n";
+  code_writer->Indent();
+  *code_writer << "_inner: T,\n";
+  *code_writer << "_rt: R,\n";
+  code_writer->Dedent();
+  *code_writer << "}\n";
+  *code_writer << "impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: "
+                  "Send + Sync {\n";
+  code_writer->Indent();
+  *code_writer << "fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }\n";
+  *code_writer
+      << "fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> "
+         "std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }\n";
+  code_writer->Dedent();
+  *code_writer << "}\n";
+  *code_writer << "impl<T, R> " << trait_name << " for Wrapper<T, R>\n";
+  *code_writer << "where\n";
+  code_writer->Indent();
+  *code_writer << "T: " << trait_name_async_server << " + Send + Sync + 'static,\n";
+  *code_writer << "R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,\n";
+  code_writer->Dedent();
+  *code_writer << "{\n";
+  code_writer->Indent();
+  for (const auto& method : iface->GetMethods()) {
+    // Generate the method
+    if (method->IsUserDefined()) {
+      string args = "";
+      for (const std::unique_ptr<AidlArgument>& arg : method->GetArguments()) {
+        if (!args.empty()) {
+          args += ", ";
+        }
+        args += kArgumentPrefix;
+        args += arg->GetName();
+      }
+
+      *code_writer << BuildMethod(*method, typenames) << " {\n";
+      code_writer->Indent();
+      *code_writer << "self._rt.block_on(self._inner." << method->GetName() << "(" << args
+                   << "))\n";
+      code_writer->Dedent();
+      *code_writer << "}\n";
+    }
+  }
+  code_writer->Dedent();
+  *code_writer << "}\n";
+
+  *code_writer << "let wrapped = Wrapper { _inner: inner, _rt: rt };\n";
+  *code_writer << "Self::new_binder(wrapped, features)\n";
+
+  code_writer->Dedent();
+  *code_writer << "}\n";
+  code_writer->Dedent();
+  *code_writer << "}\n";
+
   // Emit the default trait
   *code_writer << "pub trait " << default_trait_name << ": Send + Sync {\n";
   code_writer->Indent();
@@ -455,8 +767,8 @@
   for (const auto& method : iface->GetMethods()) {
     // Generate the transaction code constant
     *code_writer << "pub const " << method->GetName()
-                 << ": binder::TransactionCode = "
-                    "binder::FIRST_CALL_TRANSACTION + " +
+                 << ": binder::binder_impl::TransactionCode = "
+                    "binder::binder_impl::FIRST_CALL_TRANSACTION + " +
                         std::to_string(method->GetId()) + ";\n";
   }
   code_writer->Dedent();
@@ -474,8 +786,6 @@
   // Emit the interface constants
   GenerateConstantDeclarations(*code_writer, *iface, typenames);
 
-  GenerateMangledAlias(*code_writer, iface);
-
   // Emit VERSION and HASH
   // These need to be top-level item constants instead of associated consts
   // because the latter are incompatible with trait objects, see
@@ -487,19 +797,40 @@
     *code_writer << "pub const HASH: &str = \"" << options.Hash() << "\";\n";
   }
 
+  // Generate the client-side method helpers
+  //
+  // The methods in this block are not marked pub, so they are not accessible from outside the
+  // AIDL generated code.
+  *code_writer << "impl " << client_name << " {\n";
+  code_writer->Indent();
+  for (const auto& method : iface->GetMethods()) {
+    GenerateClientMethodHelpers(*code_writer, *iface, *method, typenames, options, trait_name);
+  }
+  code_writer->Dedent();
+  *code_writer << "}\n";
+
   // Generate the client-side methods
   *code_writer << "impl " << trait_name << " for " << client_name << " {\n";
   code_writer->Indent();
   for (const auto& method : iface->GetMethods()) {
-    GenerateClientMethod(*code_writer, *iface, *method, typenames, options, trait_name);
+    GenerateClientMethod(*code_writer, *iface, *method, typenames, options, MethodKind::NORMAL);
+  }
+  code_writer->Dedent();
+  *code_writer << "}\n";
+
+  // Generate the async client-side methods
+  *code_writer << "impl<P: binder::BinderAsyncPool> " << trait_name_async << "<P> for "
+               << client_name << " {\n";
+  code_writer->Indent();
+  for (const auto& method : iface->GetMethods()) {
+    MethodKind kind = method->IsOneway() ? MethodKind::READY_FUTURE : MethodKind::BOXED_FUTURE;
+    GenerateClientMethod(*code_writer, *iface, *method, typenames, options, kind);
   }
   code_writer->Dedent();
   *code_writer << "}\n";
 
   // Generate the server-side methods
   GenerateServerItems(*code_writer, iface, typenames);
-
-  return true;
 }
 
 void GenerateParcelBody(CodeWriter& out, const AidlStructuredParcelable* parcel,
@@ -509,7 +840,8 @@
   out.Indent();
   for (const auto& variable : parcel->GetFields()) {
     GenerateDeprecated(out, *variable);
-    auto field_type = RustNameOf(variable->GetType(), typenames, StorageMode::PARCELABLE_FIELD);
+    auto field_type =
+        RustNameOf(variable->GetType(), typenames, StorageMode::PARCELABLE_FIELD, Lifetime::NONE);
     out << "pub " << variable->GetName() << ": " << field_type << ",\n";
   }
   out.Dedent();
@@ -524,11 +856,28 @@
   out << "Self {\n";
   out.Indent();
   for (const auto& variable : parcel->GetFields()) {
+    out << variable->GetName() << ": ";
     if (variable->GetDefaultValue()) {
-      out << variable->GetName() << ": " << variable->ValueString(ConstantValueDecorator) << ",\n";
+      out << variable->ValueString(ConstantValueDecorator);
     } else {
-      out << variable->GetName() << ": Default::default(),\n";
+      // Some types don't implement "Default".
+      // - ParcelableHolder
+      // - Arrays
+      if (variable->GetType().GetName() == "ParcelableHolder") {
+        out << "binder::ParcelableHolder::new(";
+        if (parcel->IsVintfStability()) {
+          out << "binder::binder_impl::Stability::Vintf";
+        } else {
+          out << "binder::binder_impl::Stability::Local";
+        }
+        out << ")";
+      } else if (variable->GetType().IsFixedSizeArray() && !variable->GetType().IsNullable()) {
+        out << ArrayDefaultValue(variable->GetType());
+      } else {
+        out << "Default::default()";
+      }
     }
+    out << ",\n";
   }
   out.Dedent();
   out << "}\n";
@@ -543,12 +892,12 @@
   out << "parcel.sized_write(|subparcel| {\n";
   out.Indent();
   for (const auto& variable : parcel->GetFields()) {
-    if (!TypeHasDefault(variable->GetType(), typenames)) {
-      out << "let __field_ref = this." << variable->GetName()
+    if (TypeNeedsOption(variable->GetType(), typenames)) {
+      out << "let __field_ref = self." << variable->GetName()
           << ".as_ref().ok_or(binder::StatusCode::UNEXPECTED_NULL)?;\n";
       out << "subparcel.write(__field_ref)?;\n";
     } else {
-      out << "subparcel.write(&this." << variable->GetName() << ")?;\n";
+      out << "subparcel.write(&self." << variable->GetName() << ")?;\n";
     }
   }
   out << "Ok(())\n";
@@ -558,37 +907,23 @@
 
 void GenerateParcelDeserializeBody(CodeWriter& out, const AidlStructuredParcelable* parcel,
                                    const AidlTypenames& typenames) {
-  out << "let start_pos = parcel.get_data_position();\n";
-  out << "let parcelable_size: i32 = parcel.read()?;\n";
-  out << "if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }\n";
-  out << "if start_pos.checked_add(parcelable_size).is_none() {\n";
-  out << "  return Err(binder::StatusCode::BAD_VALUE);\n";
-  out << "}\n";
+  out << "parcel.sized_read(|subparcel| {\n";
+  out.Indent();
 
-  // Pre-emit the common field prologue code, shared between all fields:
-  ostringstream prologue;
-  prologue << "if (parcel.get_data_position() - start_pos) == parcelable_size {\n";
-  // We assume the lhs can never be > parcelable_size, because then the read
-  // immediately preceding this check would have returned NOT_ENOUGH_DATA
-  prologue << "  return Ok(Some(result));\n";
-  prologue << "}\n";
-  string prologue_str = prologue.str();
-
-  out << "let mut result = Self::default();\n";
   for (const auto& variable : parcel->GetFields()) {
-    out << prologue_str;
-    if (!TypeHasDefault(variable->GetType(), typenames)) {
-      out << "result." << variable->GetName() << " = Some(parcel.read()?);\n";
+    out << "if subparcel.has_more_data() {\n";
+    out.Indent();
+    if (TypeNeedsOption(variable->GetType(), typenames)) {
+      out << "self." << variable->GetName() << " = Some(subparcel.read()?);\n";
     } else {
-      out << "result." << variable->GetName() << " = parcel.read()?;\n";
+      out << "self." << variable->GetName() << " = subparcel.read()?;\n";
     }
+    out.Dedent();
+    out << "}\n";
   }
-  // Now we read all fields.
-  // Skip remaining data in case we're reading from a newer version
-  out << "unsafe {\n";
-  out << "  parcel.set_data_position(start_pos + parcelable_size)?;\n";
-  out << "}\n";
-  out << "Ok(Some(result))\n";
+  out << "Ok(())\n";
+  out.Dedent();
+  out << "})\n";
 }
 
 void GenerateParcelBody(CodeWriter& out, const AidlUnionDecl* parcel,
@@ -598,7 +933,8 @@
   out.Indent();
   for (const auto& variable : parcel->GetFields()) {
     GenerateDeprecated(out, *variable);
-    auto field_type = RustNameOf(variable->GetType(), typenames, StorageMode::PARCELABLE_FIELD);
+    auto field_type =
+        RustNameOf(variable->GetType(), typenames, StorageMode::PARCELABLE_FIELD, Lifetime::NONE);
     out << variable->GetCapitalizedName() << "(" << field_type << "),\n";
   }
   out.Dedent();
@@ -631,14 +967,14 @@
 
 void GenerateParcelSerializeBody(CodeWriter& out, const AidlUnionDecl* parcel,
                                  const AidlTypenames& typenames) {
-  out << "match this {\n";
+  out << "match self {\n";
   out.Indent();
   int tag = 0;
   for (const auto& variable : parcel->GetFields()) {
     out << "Self::" << variable->GetCapitalizedName() << "(v) => {\n";
     out.Indent();
     out << "parcel.write(&" << std::to_string(tag++) << "i32)?;\n";
-    if (!TypeHasDefault(variable->GetType(), typenames)) {
+    if (TypeNeedsOption(variable->GetType(), typenames)) {
       out << "let __field_ref = v.as_ref().ok_or(binder::StatusCode::UNEXPECTED_NULL)?;\n";
       out << "parcel.write(__field_ref)\n";
     } else {
@@ -658,17 +994,19 @@
   out.Indent();
   int tag = 0;
   for (const auto& variable : parcel->GetFields()) {
-    auto field_type = RustNameOf(variable->GetType(), typenames, StorageMode::PARCELABLE_FIELD);
+    auto field_type =
+        RustNameOf(variable->GetType(), typenames, StorageMode::PARCELABLE_FIELD, Lifetime::NONE);
 
     out << std::to_string(tag++) << " => {\n";
     out.Indent();
     out << "let value: " << field_type << " = ";
-    if (!TypeHasDefault(variable->GetType(), typenames)) {
+    if (TypeNeedsOption(variable->GetType(), typenames)) {
       out << "Some(parcel.read()?);\n";
     } else {
       out << "parcel.read()?;\n";
     }
-    out << "Ok(Some(Self::" << variable->GetCapitalizedName() << "(value)))\n";
+    out << "*self = Self::" << variable->GetCapitalizedName() << "(value);\n";
+    out << "Ok(())\n";
     out.Dedent();
     out << "}\n";
   }
@@ -680,70 +1018,55 @@
 }
 
 template <typename ParcelableType>
-void GenerateParcelSerialize(CodeWriter& out, const ParcelableType* parcel,
+void GenerateParcelableTrait(CodeWriter& out, const ParcelableType* parcel,
                              const AidlTypenames& typenames) {
-  out << "impl binder::parcel::Serialize for " << parcel->GetName() << " {\n";
-  out << "  fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {\n";
-  out << "    <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)\n";
-  out << "  }\n";
-  out << "}\n";
-
-  out << "impl binder::parcel::SerializeArray for " << parcel->GetName() << " {}\n";
-
-  out << "impl binder::parcel::SerializeOption for " << parcel->GetName() << " {\n";
+  out << "impl binder::Parcelable for " << parcel->GetName() << " {\n";
   out.Indent();
-  out << "fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> "
-         "binder::Result<()> {\n";
-  out.Indent();
-  out << "let this = if let Some(this) = this {\n";
-  out << "  parcel.write(&1i32)?;\n";
-  out << "  this\n";
-  out << "} else {\n";
-  out << "  return parcel.write(&0i32);\n";
-  out << "};\n";
 
-  GenerateParcelSerializeBody(out, parcel, typenames);
-
-  out.Dedent();
-  out << "}\n";
-  out.Dedent();
-  out << "}\n";
-}
-
-template <typename ParcelableType>
-void GenerateParcelDeserialize(CodeWriter& out, const ParcelableType* parcel,
-                               const AidlTypenames& typenames) {
-  out << "impl binder::parcel::Deserialize for " << parcel->GetName() << " {\n";
-  out << "  fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {\n";
-  out << "    <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)\n";
-  out << "       .transpose()\n";
-  out << "       .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))\n";
-  out << "  }\n";
-  out << "}\n";
-
-  out << "impl binder::parcel::DeserializeArray for " << parcel->GetName() << " {}\n";
-
-  out << "impl binder::parcel::DeserializeOption for " << parcel->GetName() << " {\n";
-  out.Indent();
-  out << "fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> "
+  out << "fn write_to_parcel(&self, "
+         "parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), "
+         "binder::StatusCode> "
          "{\n";
   out.Indent();
-  out << "let status: i32 = parcel.read()?;\n";
-  out << "if status == 0 { return Ok(None); }\n";
+  GenerateParcelSerializeBody(out, parcel, typenames);
+  out.Dedent();
+  out << "}\n";
 
+  out << "fn read_from_parcel(&mut self, "
+         "parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), "
+         "binder::StatusCode> {\n";
+  out.Indent();
   GenerateParcelDeserializeBody(out, parcel, typenames);
+  out.Dedent();
+  out << "}\n";
 
   out.Dedent();
   out << "}\n";
+
+  // Emit the outer (de)serialization traits
+  out << "binder::impl_serialize_for_parcelable!(" << parcel->GetName() << ");\n";
+  out << "binder::impl_deserialize_for_parcelable!(" << parcel->GetName() << ");\n";
+}
+
+template <typename ParcelableType>
+void GenerateMetadataTrait(CodeWriter& out, const ParcelableType* parcel) {
+  out << "impl binder::binder_impl::ParcelableMetadata for " << parcel->GetName() << " {\n";
+  out.Indent();
+
+  out << "fn get_descriptor() -> &'static str { \"" << parcel->GetCanonicalName() << "\" }\n";
+
+  if (parcel->IsVintfStability()) {
+    out << "fn get_stability(&self) -> binder::binder_impl::Stability { "
+           "binder::binder_impl::Stability::Vintf }\n";
+  }
+
   out.Dedent();
   out << "}\n";
 }
 
 template <typename ParcelableType>
-bool GenerateRustParcel(const string& filename, const ParcelableType* parcel,
-                        const AidlTypenames& typenames, const IoDelegate& io_delegate) {
-  CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
-
+void GenerateRustParcel(CodeWriter* code_writer, const ParcelableType* parcel,
+                        const AidlTypenames& typenames) {
   // Debug is always derived because all Rust AIDL types implement it
   // ParcelFileDescriptor doesn't support any of the others because
   // it's a newtype over std::fs::File which only implements Debug
@@ -760,61 +1083,75 @@
   *code_writer << "#[derive(" << Join(derives, ", ") << ")]\n";
   GenerateParcelBody(*code_writer, parcel, typenames);
   GenerateConstantDeclarations(*code_writer, *parcel, typenames);
-  GenerateMangledAlias(*code_writer, parcel);
   GenerateParcelDefault(*code_writer, parcel);
-  GenerateParcelSerialize(*code_writer, parcel, typenames);
-  GenerateParcelDeserialize(*code_writer, parcel, typenames);
-  return true;
+  GenerateParcelableTrait(*code_writer, parcel, typenames);
+  GenerateMetadataTrait(*code_writer, parcel);
 }
 
-bool GenerateRustEnumDeclaration(const string& filename, const AidlEnumDeclaration* enum_decl,
-                                 const AidlTypenames& typenames, const IoDelegate& io_delegate) {
-  CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
-
+void GenerateRustEnumDeclaration(CodeWriter* code_writer, const AidlEnumDeclaration* enum_decl,
+                                 const AidlTypenames& typenames) {
   const auto& aidl_backing_type = enum_decl->GetBackingType();
-  auto backing_type = RustNameOf(aidl_backing_type, typenames, StorageMode::VALUE);
+  auto backing_type = RustNameOf(aidl_backing_type, typenames, StorageMode::VALUE, Lifetime::NONE);
 
-  // TODO(b/177860423) support "deprecated" for enum types
   *code_writer << "#![allow(non_upper_case_globals)]\n";
   *code_writer << "use binder::declare_binder_enum;\n";
-  *code_writer << "declare_binder_enum! { " << enum_decl->GetName() << " : " << backing_type
-               << " {\n";
+  *code_writer << "declare_binder_enum! {\n";
+  code_writer->Indent();
+
+  GenerateDeprecated(*code_writer, *enum_decl);
+  *code_writer << enum_decl->GetName() << " : [" << backing_type << "; "
+               << std::to_string(enum_decl->GetEnumerators().size()) << "] {\n";
   code_writer->Indent();
   for (const auto& enumerator : enum_decl->GetEnumerators()) {
     auto value = enumerator->GetValue()->ValueString(aidl_backing_type, ConstantValueDecorator);
     *code_writer << enumerator->GetName() << " = " << value << ",\n";
   }
   code_writer->Dedent();
-  *code_writer << "} }\n";
+  *code_writer << "}\n";
 
-  GenerateMangledAlias(*code_writer, enum_decl);
-
-  return true;
+  code_writer->Dedent();
+  *code_writer << "}\n";
 }
 
-bool GenerateRust(const string& filename, const AidlDefinedType* defined_type,
-                  const AidlTypenames& typenames, const IoDelegate& io_delegate,
-                  const Options& options) {
-  if (const AidlStructuredParcelable* parcelable = defined_type->AsStructuredParcelable();
+void GenerateClass(CodeWriter* code_writer, const AidlDefinedType& defined_type,
+                   const AidlTypenames& types, const Options& options) {
+  if (const AidlStructuredParcelable* parcelable = defined_type.AsStructuredParcelable();
       parcelable != nullptr) {
-    return GenerateRustParcel(filename, parcelable, typenames, io_delegate);
+    GenerateRustParcel(code_writer, parcelable, types);
+  } else if (const AidlEnumDeclaration* enum_decl = defined_type.AsEnumDeclaration();
+             enum_decl != nullptr) {
+    GenerateRustEnumDeclaration(code_writer, enum_decl, types);
+  } else if (const AidlInterface* interface = defined_type.AsInterface(); interface != nullptr) {
+    GenerateRustInterface(code_writer, interface, types, options);
+  } else if (const AidlUnionDecl* union_decl = defined_type.AsUnionDeclaration();
+             union_decl != nullptr) {
+    GenerateRustParcel(code_writer, union_decl, types);
+  } else {
+    AIDL_FATAL(defined_type) << "Unrecognized type sent for Rust generation.";
   }
 
-  if (const AidlUnionDecl* parcelable = defined_type->AsUnionDeclaration(); parcelable != nullptr) {
-    return GenerateRustParcel(filename, parcelable, typenames, io_delegate);
+  for (const auto& nested : defined_type.GetNestedTypes()) {
+    (*code_writer) << "pub mod " << nested->GetName() << " {\n";
+    code_writer->Indent();
+    GenerateClass(code_writer, *nested, types, options);
+    code_writer->Dedent();
+    (*code_writer) << "}\n";
   }
+}
 
-  if (const AidlEnumDeclaration* enum_decl = defined_type->AsEnumDeclaration();
-      enum_decl != nullptr) {
-    return GenerateRustEnumDeclaration(filename, enum_decl, typenames, io_delegate);
-  }
+void GenerateRust(const string& filename, const Options& options, const AidlTypenames& types,
+                  const AidlDefinedType& defined_type, const IoDelegate& io_delegate) {
+  CodeWriterPtr code_writer = io_delegate.GetCodeWriter(filename);
 
-  if (const AidlInterface* interface = defined_type->AsInterface(); interface != nullptr) {
-    return GenerateRustInterface(filename, interface, typenames, io_delegate, options);
-  }
+  // Forbid the use of unsafe in auto-generated code.
+  // Unsafe code should only be allowed in libbinder_rs.
+  *code_writer << "#![forbid(unsafe_code)]\n";
+  // Disable rustfmt on auto-generated files, including the golden outputs
+  *code_writer << "#![rustfmt::skip]\n";
+  GenerateClass(code_writer.get(), defined_type, types, options);
+  GenerateMangledAliases(*code_writer, defined_type);
 
-  AIDL_FATAL(filename) << "Unrecognized type sent for Rust generation.";
-  return false;
+  AIDL_FATAL_IF(!code_writer->Close(), defined_type) << "I/O Error!";
 }
 
 }  // namespace rust
diff --git a/generate_rust.h b/generate_rust.h
index 35daf9b..9de8e56 100644
--- a/generate_rust.h
+++ b/generate_rust.h
@@ -26,9 +26,8 @@
 namespace aidl {
 namespace rust {
 
-bool GenerateRust(const std::string& filename, const AidlDefinedType* iface,
-                  const AidlTypenames& typenames, const IoDelegate& io_delegate,
-                  const Options& options);
+void GenerateRust(const string& filename, const Options& options, const AidlTypenames& types,
+                  const AidlDefinedType& defined_type, const IoDelegate& io_delegate);
 
 }  // namespace rust
 }  // namespace aidl
diff --git a/import_resolver.cpp b/import_resolver.cpp
index 1bf2794..48fba3c 100644
--- a/import_resolver.cpp
+++ b/import_resolver.cpp
@@ -30,6 +30,7 @@
 
 #include "os.h"
 
+using std::set;
 using std::string;
 using std::vector;
 
@@ -37,8 +38,8 @@
 namespace aidl {
 
 ImportResolver::ImportResolver(const IoDelegate& io_delegate, const string& input_file_name,
-                               const set<string>& import_paths, const vector<string>& input_files)
-    : io_delegate_(io_delegate), input_file_name_(input_file_name), input_files_(input_files) {
+                               const set<string>& import_paths)
+    : io_delegate_(io_delegate), input_file_name_(input_file_name) {
   for (string path : import_paths) {
     if (path.empty()) {
       path = ".";
@@ -46,43 +47,42 @@
     if (path[path.size() - 1] != OS_PATH_SEPARATOR) {
       path += OS_PATH_SEPARATOR;
     }
-    import_paths_.push_back(std::move(path));
+    import_paths_.emplace(std::move(path));
   }
 }
 
 string ImportResolver::FindImportFile(const string& canonical_name) const {
-  // Convert the canonical name to a relative file path.
-  string relative_path = canonical_name;
-  for (char& c : relative_path) {
-    if (c == '.') {
-      c = OS_PATH_SEPARATOR;
+  auto parts = base::Split(canonical_name, ".");
+  while (!parts.empty()) {
+    string relative_path = base::Join(parts, OS_PATH_SEPARATOR) + ".aidl";
+    auto candidates = ScanImportPaths(relative_path);
+    if (candidates.size() == 0) {
+      // remove the last part & keep searching
+      parts.pop_back();
+      continue;
+    }
+    if (candidates.size() == 1) {
+      // found!
+      return *candidates.begin();
+    }
+    if (candidates.size() > 1) {
+      AIDL_ERROR(input_file_name_) << "Duplicate files found for " << canonical_name << " from:\n"
+                                   << base::Join(candidates, "\n");
+      break;
     }
   }
-  relative_path += ".aidl";
+  return "";
+}
 
+set<string> ImportResolver::ScanImportPaths(const string& relative_path) const {
   // Look for that relative path at each of our import roots.
-  vector<string> found_paths;
-  for (string path : import_paths_) {
-    path = path + relative_path;
-    if (io_delegate_.FileIsReadable(path)) {
-      found_paths.emplace_back(path);
+  set<string> found;
+  for (const auto& path : import_paths_) {
+    if (io_delegate_.FileIsReadable(path + relative_path)) {
+      found.emplace(path + relative_path);
     }
   }
-  // remove duplicates
-  std::sort(found_paths.begin(), found_paths.end());
-  auto last = std::unique(found_paths.begin(), found_paths.end());
-  found_paths.erase(last, found_paths.end());
-
-  int num_found = found_paths.size();
-  if (num_found == 0) {
-    return "";
-  } else if (num_found == 1) {
-    return found_paths.front();
-  } else {
-    AIDL_ERROR(input_file_name_) << "Duplicate files found for " << canonical_name << " from:\n"
-                                 << android::base::Join(found_paths, "\n");
-    return "";
-  }
+  return found;
 }
 
 }  // namespace aidl
diff --git a/import_resolver.h b/import_resolver.h
index e52843e..a9f38fd 100644
--- a/import_resolver.h
+++ b/import_resolver.h
@@ -18,7 +18,6 @@
 
 #include <set>
 #include <string>
-#include <vector>
 
 #include "io_delegate.h"
 
@@ -28,8 +27,7 @@
 class ImportResolver {
  public:
   ImportResolver(const IoDelegate& io_delegate, const std::string& input_file_name,
-                 const std::set<std::string>& import_paths,
-                 const std::vector<std::string>& input_files);
+                 const std::set<std::string>& import_paths);
   virtual ~ImportResolver() = default;
 
   // non-copyable, non-movable
@@ -43,10 +41,11 @@
   std::string FindImportFile(const std::string& canonical_name) const;
 
  private:
+  std::set<std::string> ScanImportPaths(const std::string& relative_path) const;
+
   const IoDelegate& io_delegate_;
   const std::string& input_file_name_;
-  std::vector<std::string> import_paths_;
-  std::vector<std::string> input_files_;
+  std::set<std::string> import_paths_;
 };
 
 }  // namespace aidl
diff --git a/io_delegate.cpp b/io_delegate.cpp
index 45ef65a..d40bf1d 100644
--- a/io_delegate.cpp
+++ b/io_delegate.cpp
@@ -43,6 +43,7 @@
 using android::base::Error;
 using android::base::Result;
 using android::base::Split;
+using android::base::StartsWith;
 
 namespace android {
 namespace aidl {
@@ -107,11 +108,6 @@
   return contents;
 }
 
-unique_ptr<LineReader> IoDelegate::GetLineReader(
-    const string& file_path) const {
-  return LineReader::ReadFromFile(file_path);
-}
-
 bool IoDelegate::FileIsReadable(const string& path) const {
 #ifdef _WIN32
   // check that the file exists and is not write-only
@@ -187,14 +183,6 @@
   }
 }
 
-void IoDelegate::RemovePath(const std::string& file_path) const {
-#ifdef _WIN32
-  _unlink(file_path.c_str());
-#else
-  unlink(file_path.c_str());
-#endif
-}
-
 #ifdef _WIN32
 Result<vector<string>> IoDelegate::ListFiles(const string&) const {
   return Error() << "File listing not implemented on Windows";
@@ -244,5 +232,12 @@
 }
 #endif
 
+string IoDelegate::CleanPath(const string& path) {
+  if (base::StartsWith(path, string{'.', OS_PATH_SEPARATOR})) {
+    return path.substr(2);
+  }
+  return path;
+}
+
 }  // namespace android
 }  // namespace aidl
diff --git a/io_delegate.h b/io_delegate.h
index 6c1ef96..a92a9b9 100644
--- a/io_delegate.h
+++ b/io_delegate.h
@@ -23,7 +23,6 @@
 #include <android-base/result.h>
 
 #include "code_writer.h"
-#include "line_reader.h"
 
 namespace android {
 namespace aidl {
@@ -44,22 +43,20 @@
   static bool GetAbsolutePath(const std::string& path,
                               std::string* absolute_path);
 
+  // Remove leading "./" from |path|.
+  static std::string CleanPath(const std::string& path);
+
   // Returns a unique_ptr to the contents of |filename|.
   // Will append the optional |content_suffix| to the returned contents.
   virtual std::unique_ptr<std::string> GetFileContents(
       const std::string& filename,
       const std::string& content_suffix = "") const;
 
-  virtual std::unique_ptr<LineReader> GetLineReader(
-      const std::string& file_path) const;
-
   virtual bool FileIsReadable(const std::string& path) const;
 
   virtual std::unique_ptr<CodeWriter> GetCodeWriter(
       const std::string& file_path) const;
 
-  virtual void RemovePath(const std::string& file_path) const;
-
   virtual android::base::Result<std::vector<std::string>> ListFiles(const std::string& dir) const;
 
  private:
diff --git a/line_reader.cpp b/line_reader.cpp
deleted file mode 100644
index dedca20..0000000
--- a/line_reader.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2015, 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.
- */
-
-#include "line_reader.h"
-
-#include <fstream>
-#include <sstream>
-
-using std::istringstream;
-using std::ifstream;
-using std::string;
-using std::unique_ptr;
-
-namespace android {
-namespace aidl {
-
-class FileLineReader : public LineReader {
- public:
-  FileLineReader() = default;
-  ~FileLineReader() override {
-    input_stream_.close();
-  }
-
-  // non-copyable, non-movable
-  FileLineReader(const FileLineReader&) = delete;
-  FileLineReader(FileLineReader&&) = delete;
-  FileLineReader& operator=(const FileLineReader&) = delete;
-  FileLineReader& operator=(FileLineReader&&) = delete;
-
-  bool Init(const std::string& file_path) {
-    input_stream_.open(file_path, ifstream::in | ifstream::binary);
-    return input_stream_.is_open() && input_stream_.good();
-  }
-
-  bool ReadLine(string* line) override {
-    if (!input_stream_.good()) {
-      return false;
-    }
-    line->clear();
-    std::getline(input_stream_, *line);
-    return true;
-  }
-
- private:
-  ifstream input_stream_;
-};  // class FileLineReader
-
-class MemoryLineReader : public LineReader {
- public:
-  explicit MemoryLineReader(const string& contents) : input_stream_(contents) {}
-  ~MemoryLineReader() override = default;
-
-  // non-copyable, non-movable
-  MemoryLineReader(const MemoryLineReader&) = delete;
-  MemoryLineReader(MemoryLineReader&&) = delete;
-  MemoryLineReader& operator=(const MemoryLineReader&) = delete;
-  MemoryLineReader& operator=(MemoryLineReader&&) = delete;
-
-  bool ReadLine(string* line) override {
-    if (!input_stream_.good()) {
-      return false;
-    }
-    line->clear();
-    std::getline(input_stream_, *line);
-    return true;
-  }
-
- private:
-  istringstream input_stream_;
-};  // class MemoryLineReader
-
-unique_ptr<LineReader> LineReader::ReadFromFile(const string& file_path) {
-  unique_ptr<FileLineReader> file_reader(new FileLineReader());
-  unique_ptr<LineReader> ret;
-  if (file_reader->Init(file_path)) {
-    ret.reset(file_reader.release());
-  }
-  return ret;
-}
-
-unique_ptr<LineReader> LineReader::ReadFromMemory(const string& contents) {
-  return unique_ptr<LineReader>(new MemoryLineReader(contents));
-}
-
-}  // namespace aidl
-}  // namespace android
diff --git a/line_reader.h b/line_reader.h
deleted file mode 100644
index 0b81a60..0000000
--- a/line_reader.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2015, 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.
- */
-
-#pragma once
-
-#include <memory>
-#include <string>
-
-namespace android {
-namespace aidl {
-
-class LineReader {
- public:
-  LineReader() = default;
-  virtual ~LineReader() = default;
-
-  LineReader(const LineReader&) = delete;
-  LineReader(LineReader&&) = delete;
-  LineReader& operator=(const LineReader&) = delete;
-  LineReader& operator=(LineReader&&) = delete;
-
-  virtual bool ReadLine(std::string* line) = 0;
-
-  static std::unique_ptr<LineReader> ReadFromFile(
-      const std::string& file_path);
-  static std::unique_ptr<LineReader> ReadFromMemory(
-      const std::string& contents);
-};  // class LineReader
-
-}  // namespace aidl
-}  // namespace android
diff --git a/main.cpp b/main.cpp
index 69ba060..c0078ba 100644
--- a/main.cpp
+++ b/main.cpp
@@ -31,10 +31,6 @@
 
 int main(int argc, char* argv[]) {
   Options options(argc, argv, kDefaultLang);
-  if (!options.Ok()) {
-    AIDL_ERROR(options.GetErrorMessage()) << options.GetUsage();
-    return 1;
-  }
 
   // Only minimal functionality should go here, so that as much of possible of
   // the aidl compiler is mocked with the single function `aidl_entry`
diff --git a/metadata/include/aidl/metadata.h b/metadata/include/aidl/metadata.h
index a9f9f43..09c60ba 100644
--- a/metadata/include/aidl/metadata.h
+++ b/metadata/include/aidl/metadata.h
@@ -34,6 +34,12 @@
   // list of all hashes
   std::vector<std::string> hashes;
 
+  // true if the interface is different from the last frozen version
+  bool has_development;
+
+  // list of all frozen versions
+  std::vector<size_t> versions;
+
   static std::vector<AidlInterfaceMetadata> all();
 };
 
diff --git a/metadata/parser.cpp b/metadata/parser.cpp
index 7334554..646a77b 100644
--- a/metadata/parser.cpp
+++ b/metadata/parser.cpp
@@ -56,6 +56,12 @@
       std::cout << "std::string(\"" << intf.asString() << "\")," << std::endl;
     }
     std::cout << "}," << std::endl;
+    std::cout << entry["has_development"].asString() << "," << std::endl;
+    std::cout << "std::vector<size_t>{" << std::endl;
+    for (const Json::Value& intf : entry["versions"]) {
+      std::cout << intf.asString() << "," << std::endl;
+    }
+    std::cout << "}," << std::endl;
     std::cout << "}," << std::endl;
   }
   std::cout << "};" << std::endl;
diff --git a/metadata/test.cpp b/metadata/test.cpp
index 67d08b2..5617415 100644
--- a/metadata/test.cpp
+++ b/metadata/test.cpp
@@ -40,4 +40,17 @@
   EXPECT_THAT(info->hashes, ElementsAre("13e24b2fac6a979971819fba2ab0d6d7c4182122",
                                         "dc2a9292847e43b4360bb183f7491f0e9895eaa9",
                                         "54f935920ab0934c242145cf00f9852ae3f5a63e"));
+  EXPECT_THAT(info->versions, ElementsAre(1, 2, 3));
+  EXPECT_EQ(info->has_development, true);
+}
+
+TEST(AidlMetadata, HasTestInstancesNoDevelopment) {
+  const auto& info = metadataForModule("test-piece-2");
+  ASSERT_NE(info, std::nullopt);
+  EXPECT_EQ(info->stability, "");
+  EXPECT_THAT(info->types, ElementsAre("INoPackage", "some_package.IBar"));
+  EXPECT_THAT(info->hashes, ElementsAre("c544902ab8a1d2e72ae9396032ba113e9b9698c4",
+                                        "fcd36db451cdbeeb049833fd7f499a987acf3930"));
+  EXPECT_THAT(info->versions, ElementsAre(1));
+  EXPECT_EQ(info->has_development, false);
 }
diff --git a/options.cpp b/options.cpp
index b383052..b9878b8 100644
--- a/options.cpp
+++ b/options.cpp
@@ -15,20 +15,25 @@
  */
 
 #include "options.h"
-#include "logging.h"
-#include "os.h"
 
+#include <android-base/logging.h>
+#include <android-base/parseint.h>
+#include <android-base/result.h>
+#include <android-base/strings.h>
 #include <getopt.h>
 #include <stdlib.h>
 #include <unistd.h>
+
 #include <algorithm>
 #include <iostream>
 #include <sstream>
 #include <string>
 
-#include <android-base/strings.h>
 #include "aidl_language.h"
+#include "logging.h"
+#include "os.h"
 
+using android::base::Result;
 using android::base::Split;
 using android::base::Trim;
 using std::endl;
@@ -59,6 +64,15 @@
        << "   Check whether NEW_DIR API dump is {compatible|equal} extension " << endl
        << "   of the API dump OLD_DIR. Default: compatible" << endl
 #endif
+       << endl
+       << myname_ << " --apimapping OUTPUT INPUT..." << endl
+       << "   Generate a mapping of declared aidl method signatures to" << endl
+       << "   the original line number. e.g.: " << endl
+       << "       If line 39 of foo/bar/IFoo.aidl contains:"
+       << "         void doFoo(int bar, String baz);" << endl
+       << "       Then the result would be:" << endl
+       << "         foo.bar.Baz|doFoo|int,String,|void" << endl
+       << "         foo/bar/IFoo.aidl:39" << endl
        << endl;
 
   // Legacy option formats
@@ -79,8 +93,6 @@
   sstr << "OPTION:" << endl
        << "  -I DIR, --include=DIR" << endl
        << "          Use DIR as a search path for import statements." << endl
-       << "  -m FILE, --import=FILE" << endl
-       << "          Import FILE directly without searching in the search paths." << endl
        << "  -p FILE, --preprocessed=FILE" << endl
        << "          Include FILE which is created by --preprocess." << endl
        << "  -d FILE, --dep=FILE" << endl
@@ -97,25 +109,25 @@
        << "          Trigger fail when trying to compile a parcelable." << endl
        << "  --ninja" << endl
        << "          Generate dependency file in a format ninja understands." << endl
+       << "  --rpc" << endl
+       << "          (for Java) whether to generate support for RPC transactions." << endl
        << "  --structured" << endl
        << "          Whether this interface is defined exclusively in AIDL." << endl
        << "          It is therefore a candidate for stabilization." << endl
        << "  --stability=<level>" << endl
        << "          The stability requirement of this interface." << endl
+       << "  --min_sdk_version=<version>" << endl
+       << "          Minimum SDK version that the generated code should support." << endl
+       << "          Defaults to " << DEFAULT_SDK_VERSION_JAVA << " for --lang=java, " << endl
+       << "            " << DEFAULT_SDK_VERSION_CPP << " for --lang=cpp, " << endl
+       << "            " << DEFAULT_SDK_VERSION_NDK << " for --lang=ndk, " << endl
+       << "            " << DEFAULT_SDK_VERSION_RUST << " for --lang=rust, " << endl
        << "  -t, --trace" << endl
        << "          Include tracing code for systrace. Note that if either" << endl
        << "          the client or service code is not auto-generated by this" << endl
        << "          tool, that part will not be traced." << endl
        << "  --transaction_names" << endl
        << "          Generate transaction names." << endl
-       << "  --apimapping" << endl
-       << "          Generates a mapping of declared aidl method signatures to" << endl
-       << "          the original line number. e.g.: " << endl
-       << "              If line 39 of foo/bar/IFoo.aidl contains:"
-       << "              void doFoo(int bar, String baz);" << endl
-       << "              Then the result would be:" << endl
-       << "              foo.bar.Baz|doFoo|int,String,|void" << endl
-       << "              foo/bar/IFoo.aidl:39" << endl
        << "  -v VER, --version=VER" << endl
        << "          Set the version of the interface and parcelable to VER." << endl
        << "          VER must be an interger greater than 0." << endl
@@ -181,6 +193,44 @@
   return false;
 }
 
+static const std::map<std::string, uint32_t> codeNameToVersion = {
+    {"S", 31},
+    {"Tiramisu", SDK_VERSION_Tiramisu},
+    // this is an alias for the latest in-development platform version
+    {"current", SDK_VERSION_current},
+    // this is an alias for use of all APIs, including those not in any API surface
+    {"platform_apis", 10001},
+};
+
+Result<uint32_t> MinSdkVersionFromString(const std::string& str) {
+  uint32_t num;
+  if (!android::base::ParseUint(str, &num, 10000u /* max */)) {
+    if (auto found = codeNameToVersion.find(str); found != codeNameToVersion.end()) {
+      return found->second;
+    }
+    return Errorf("Invalid SDK version: {}", str);
+  }
+  return num;
+}
+
+static uint32_t DefaultMinSdkVersionForLang(const Options::Language lang) {
+  switch (lang) {
+    case Options::Language::CPP:
+      return DEFAULT_SDK_VERSION_CPP;
+    case Options::Language::JAVA:
+      return DEFAULT_SDK_VERSION_JAVA;
+    case Options::Language::NDK:
+      return DEFAULT_SDK_VERSION_NDK;
+    case Options::Language::RUST:
+      return DEFAULT_SDK_VERSION_RUST;
+    case Options::Language::UNSPECIFIED:
+      return DEFAULT_SDK_VERSION_JAVA;  // The safest option
+    default:
+      AIDL_FATAL(AIDL_LOCATION_HERE)
+          << "Unexpected Options::Language enumerator: " << static_cast<size_t>(lang);
+  }
+}
+
 Options Options::From(const string& cmdline) {
   vector<string> args = Split(cmdline, " ");
   return From(args);
@@ -202,7 +252,7 @@
 }
 
 Options::Options(int argc, const char* const raw_argv[], Options::Language default_lang)
-    : myname_(raw_argv[0]), language_(default_lang) {
+    : myname_(argc >= 1 ? raw_argv[0] : "aidl"), language_(default_lang) {
   std::vector<const char*> argv = warning_options_.Parse(argc, raw_argv, error_message_);
   if (!Ok()) return;
   argc = argv.size();
@@ -220,13 +270,14 @@
 #endif
         {"apimapping", required_argument, 0, 'i'},
         {"include", required_argument, 0, 'I'},
-        {"import", required_argument, 0, 'm'},
         {"preprocessed", required_argument, 0, 'p'},
         {"dep", required_argument, 0, 'd'},
         {"out", required_argument, 0, 'o'},
         {"header_out", required_argument, 0, 'h'},
         {"ninja", no_argument, 0, 'n'},
+        {"rpc", no_argument, 0, 'r'},
         {"stability", required_argument, 0, 'Y'},
+        {"min_sdk_version", required_argument, 0, 'm'},
         {"structured", no_argument, 0, 'S'},
         {"trace", no_argument, 0, 't'},
         {"transaction_names", no_argument, 0, 'c'},
@@ -237,7 +288,7 @@
         {0, 0, 0, 0},
     };
     const int c = getopt_long(argc, const_cast<char* const*>(argv.data()),
-                              "I:m:p:d:o:h:abtv:", long_options, nullptr);
+                              "I:p:d:o:h:abtv:i:", long_options, nullptr);
     if (c == -1) {
       // no more options
       break;
@@ -271,33 +322,27 @@
         }
         break;
       case 's':
-        if (task_ != Options::Task::UNSPECIFIED) {
-          task_ = Options::Task::PREPROCESS;
-        }
+        task_ = Options::Task::PREPROCESS;
         break;
 #ifndef _WIN32
       case 'u':
-        if (task_ != Options::Task::UNSPECIFIED) {
-          task_ = Options::Task::DUMP_API;
-        }
+        task_ = Options::Task::DUMP_API;
         break;
       case 'x':
         dump_no_license_ = true;
         break;
       case 'A':
-        if (task_ != Options::Task::UNSPECIFIED) {
-          task_ = Options::Task::CHECK_API;
-          // to ensure that all parcelables in the api dumpes are structured
-          structured_ = true;
-          if (optarg) {
-            if (strcmp(optarg, "compatible") == 0)
-              check_api_level_ = CheckApiLevel::COMPATIBLE;
-            else if (strcmp(optarg, "equal") == 0)
-              check_api_level_ = CheckApiLevel::EQUAL;
-            else {
-              error_message_ << "Unsupported --checkapi level: '" << optarg << "'" << endl;
-              return;
-            }
+        task_ = Options::Task::CHECK_API;
+        // to ensure that all parcelables in the api dumpes are structured
+        structured_ = true;
+        if (optarg) {
+          if (strcmp(optarg, "compatible") == 0)
+            check_api_level_ = CheckApiLevel::COMPATIBLE;
+          else if (strcmp(optarg, "equal") == 0)
+            check_api_level_ = CheckApiLevel::EQUAL;
+          else {
+            error_message_ << "Unsupported --checkapi level: '" << optarg << "'" << endl;
+            return;
           }
         }
         break;
@@ -306,10 +351,6 @@
         import_dirs_.emplace(Trim(optarg));
         break;
       }
-      case 'm': {
-        import_files_.emplace(Trim(optarg));
-        break;
-      }
       case 'p':
         preprocessed_files_.emplace_back(Trim(optarg));
         break;
@@ -343,6 +384,17 @@
         }
         break;
       }
+      case 'm':
+        if (auto ret = MinSdkVersionFromString(Trim(optarg)); ret.ok()) {
+          min_sdk_version_ = *ret;
+        } else {
+          error_message_ << ret.error();
+          return;
+        }
+        break;
+      case 'r':
+        gen_rpc_ = true;
+        break;
       case 't':
         gen_traces_ = true;
         break;
@@ -375,14 +427,17 @@
         break;
       case 'e':
         std::cerr << GetUsage();
-        exit(0);
+        task_ = Task::HELP;
+        CHECK(Ok());
+        return;
       case 'i':
         output_file_ = Trim(optarg);
         task_ = Task::DUMP_MAPPINGS;
         break;
       default:
-        std::cerr << GetUsage();
-        exit(1);
+        error_message_ << GetUsage();
+        CHECK(!Ok());
+        return;
     }
   }  // while
 
@@ -430,7 +485,8 @@
     }
   } else {
     // the new arguments format
-    if (task_ == Options::Task::COMPILE || task_ == Options::Task::DUMP_API) {
+    if (task_ == Options::Task::COMPILE || task_ == Options::Task::DUMP_API ||
+        task_ == Options::Task::DUMP_MAPPINGS) {
       if (argc - optind < 1) {
         error_message_ << "No input file." << endl;
         return;
@@ -441,7 +497,7 @@
                        << "got " << (argc - optind) << "." << endl;
         return;
       }
-      if (task_ != Options::Task::CHECK_API && task_ != Options::Task::DUMP_MAPPINGS) {
+      if (task_ != Options::Task::CHECK_API) {
         output_file_ = argv[optind++];
       }
     }
@@ -530,6 +586,31 @@
       return;
     }
   }
+  if (task_ != Options::Task::COMPILE) {
+    if (min_sdk_version_ != 0) {
+      error_message_ << "--min_sdk_version is available only for compilation." << endl;
+      return;
+    }
+    // For other tasks, use "current"
+    min_sdk_version_ = MinSdkVersionFromString("current").value();
+  }
+
+  uint32_t default_ver = DefaultMinSdkVersionForLang(language_);
+  if (min_sdk_version_ == 0) {  // --min_sdk_version flag not specified
+    min_sdk_version_ = default_ver;
+  } else if (min_sdk_version_ < default_ver) {
+    error_message_ << "Min SDK version should at least be " << default_ver << "." << endl;
+    return;
+  }
+
+  uint32_t rpc_version = MinSdkVersionFromString("Tiramisu").value();
+  // note: we would like to always generate (Java) code to support RPC out of
+  // the box, but doing so causes an unclear error for people trying to use RPC
+  // - now we require them to add the gen_rpc build rule and get this clear message.
+  if (gen_rpc_ && min_sdk_version_ < rpc_version) {
+    error_message_ << "RPC code requires minimum SDK version of at least " << rpc_version << endl;
+    return;
+  }
 
   AIDL_FATAL_IF(!output_dir_.empty() && output_dir_.back() != OS_PATH_SEPARATOR, output_dir_);
   AIDL_FATAL_IF(!output_header_dir_.empty() && output_header_dir_.back() != OS_PATH_SEPARATOR,
diff --git a/options.h b/options.h
index 11a5e59..204b371 100644
--- a/options.h
+++ b/options.h
@@ -19,6 +19,8 @@
 #include <string>
 #include <vector>
 
+#include <android-base/result.h>
+
 #include "diagnostics.h"
 
 namespace android {
@@ -28,6 +30,19 @@
 using std::string;
 using std::vector;
 
+// The oldest SDK version that is supported for each backend. For non-Java backends, these are the
+// platform SDK version where the support for the backend was added. For Java backend, this is 1.
+// TODO(b/205065703) switch back to DEFAULT_SDK_VERSION_JAVA = 23
+constexpr uint32_t DEFAULT_SDK_VERSION_JAVA = 1;
+constexpr uint32_t DEFAULT_SDK_VERSION_CPP = 23;
+constexpr uint32_t DEFAULT_SDK_VERSION_NDK = 29;
+constexpr uint32_t DEFAULT_SDK_VERSION_RUST = 31;
+
+constexpr uint32_t SDK_VERSION_current = 10000;
+constexpr uint32_t SDK_VERSION_Tiramisu = SDK_VERSION_current;
+
+constexpr uint32_t JAVA_PROPAGATE_VERSION = SDK_VERSION_Tiramisu;
+
 // A simple wrapper around ostringstream. This is just to make Options class
 // copiable by the implicit copy constructor. If ostingstream is not wrapped,
 // the implcit copy constructor is not generated because ostringstream isn't
@@ -77,7 +92,7 @@
  public:
   enum class Language { UNSPECIFIED, JAVA, CPP, NDK, RUST };
 
-  enum class Task { UNSPECIFIED, COMPILE, PREPROCESS, DUMP_API, CHECK_API, DUMP_MAPPINGS };
+  enum class Task { HELP, COMPILE, PREPROCESS, DUMP_API, CHECK_API, DUMP_MAPPINGS };
 
   enum class CheckApiLevel { COMPATIBLE, EQUAL };
 
@@ -86,6 +101,12 @@
 
   Options(int argc, const char* const argv[], Language default_lang = Language::UNSPECIFIED);
 
+  Options PlusImportDir(const std::string& import_dir) const {
+    Options copy(*this);
+    copy.import_dirs_.insert(import_dir);
+    return copy;
+  }
+
   static Options From(const string& cmdline);
 
   static Options From(const vector<string>& args);
@@ -97,6 +118,8 @@
 
   Stability GetStability() const { return stability_; }
 
+  uint32_t GetMinSdkVersion() const { return min_sdk_version_; }
+
   Language TargetLanguage() const { return language_; }
   bool IsCppOutput() const { return language_ == Language::CPP || language_ == Language::NDK; }
 
@@ -106,8 +129,6 @@
 
   const set<string>& ImportDirs() const { return import_dirs_; }
 
-  const set<string>& ImportFiles() const { return import_files_; }
-
   const vector<string>& PreprocessedFiles() const { return preprocessed_files_; }
 
   string DependencyFile() const {
@@ -116,6 +137,8 @@
 
   bool AutoDepFile() const { return auto_dep_file_; }
 
+  bool GenRpc() const { return gen_rpc_; }
+
   bool GenTraces() const { return gen_traces_; }
 
   bool GenTransactionNames() const { return gen_transaction_names_; }
@@ -171,14 +194,15 @@
   Task task_ = Task::COMPILE;
   CheckApiLevel check_api_level_ = CheckApiLevel::COMPATIBLE;
   set<string> import_dirs_;
-  set<string> import_files_;
   vector<string> preprocessed_files_;
   string dependency_file_;
+  bool gen_rpc_ = false;
   bool gen_traces_ = false;
   bool gen_transaction_names_ = false;
   bool dependency_file_ninja_ = false;
   bool structured_ = false;
   Stability stability_ = Stability::UNSPECIFIED;
+  uint32_t min_sdk_version_ = 0;  // invalid version
   string output_dir_;
   string output_header_dir_;
   bool fail_on_parcelable_ = false;
@@ -194,6 +218,7 @@
 };
 
 std::string to_string(Options::Language language);
+android::base::Result<uint32_t> MinSdkVersionFromString(const std::string& str);
 
 }  // namespace aidl
 }  // namespace android
diff --git a/options_unittest.cpp b/options_unittest.cpp
index 9f07400..1121402 100644
--- a/options_unittest.cpp
+++ b/options_unittest.cpp
@@ -445,5 +445,64 @@
   EXPECT_THAT(GetCapturedStderr(), testing::HasSubstr("Unsupported --checkapi level: 'unknown'"));
 }
 
+TEST(OptionsTest, AcceptValidMinSdkVersion) {
+  const char* args[] = {
+      "aidl", "--lang=java", "--min_sdk_version=30", "--out=out", "input.aidl", nullptr,
+  };
+  auto options = GetOptions(args);
+  EXPECT_TRUE(options->Ok());
+  EXPECT_EQ(30u, options->GetMinSdkVersion());
+}
+
+TEST(OPtionsTests, AcceptCodeNameAsMinSdkVersion) {
+  const char* args[] = {
+      "aidl", "--lang=java", "--min_sdk_version=Tiramisu", "--out=out", "input.aidl", nullptr,
+  };
+  auto options = GetOptions(args);
+  EXPECT_TRUE(options->Ok());
+  EXPECT_EQ(10000u, options->GetMinSdkVersion());
+}
+
+TEST(OptionsTest, DefaultMinSdkVersion) {
+  const char* args[] = {
+      "aidl", "--lang=java", "--out=out", "input.aidl", nullptr,
+  };
+  auto options = GetOptions(args);
+  EXPECT_TRUE(options->Ok());
+  EXPECT_EQ(DEFAULT_SDK_VERSION_JAVA, options->GetMinSdkVersion());
+}
+
+TEST(OptionsTest, RejectInvalidMinSdkVersion) {
+  const char* args[] = {
+      "aidl", "--lang=java", "--min_sdk_version=NOT_A_VERSION", "--out=out", "input.aidl", nullptr,
+  };
+  CaptureStderr();
+  auto options = GetOptions(args);
+  EXPECT_FALSE(options->Ok());
+  EXPECT_THAT(GetCapturedStderr(), testing::HasSubstr("Invalid SDK version: NOT_A_VERSION"));
+}
+
+TEST(OptionsTest, RejectOldMinSdkVersion) {
+  const char* args[] = {
+      "aidl",       "--lang=cpp", "--min_sdk_version=22", "--out=out", "--header_out=out",
+      "input.aidl", nullptr,
+  };
+  CaptureStderr();
+  auto options = GetOptions(args);
+  EXPECT_FALSE(options->Ok());
+  EXPECT_THAT(GetCapturedStderr(), testing::HasSubstr("Min SDK version should at least be 23"));
+}
+
+TEST(OptionsTest, RejectRpcOnOldSdkVersion) {
+  const char* args[] = {
+      "aidl", "--lang=java", "--rpc", "--min_sdk_version=23", "--out=out", "input.aidl", nullptr,
+  };
+  CaptureStderr();
+  auto options = GetOptions(args);
+  EXPECT_FALSE(options->Ok());
+  EXPECT_THAT(GetCapturedStderr(),
+              testing::HasSubstr("RPC code requires minimum SDK version of at least"));
+}
+
 }  // namespace aidl
 }  // namespace android
diff --git a/parser.cpp b/parser.cpp
index 721979f..9988f56 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -15,6 +15,9 @@
  */
 
 #include "parser.h"
+
+#include <queue>
+
 #include "aidl_language_y.h"
 #include "logging.h"
 
@@ -25,13 +28,20 @@
 YY_BUFFER_STATE yy_scan_buffer(char*, size_t, void*);
 void yy_delete_buffer(YY_BUFFER_STATE, void*);
 
-std::unique_ptr<Parser> Parser::Parse(const std::string& filename,
-                                      const android::aidl::IoDelegate& io_delegate,
-                                      AidlTypenames& typenames) {
+const AidlDocument* Parser::Parse(const std::string& filename,
+                                  const android::aidl::IoDelegate& io_delegate,
+                                  AidlTypenames& typenames, bool is_preprocessed) {
+  auto clean_path = android::aidl::IoDelegate::CleanPath(filename);
+  // reuse pre-parsed document from typenames
+  for (auto& doc : typenames.AllDocuments()) {
+    if (doc->GetLocation().GetFile() == clean_path) {
+      return doc.get();
+    }
+  }
   // Make sure we can read the file first, before trashing previous state.
-  unique_ptr<string> raw_buffer = io_delegate.GetFileContents(filename);
+  unique_ptr<string> raw_buffer = io_delegate.GetFileContents(clean_path);
   if (raw_buffer == nullptr) {
-    AIDL_ERROR(filename) << "Error while opening file for parsing";
+    AIDL_ERROR(clean_path) << "Error while opening file for parsing";
     return nullptr;
   }
 
@@ -39,13 +49,18 @@
   // nulls at the end.
   raw_buffer->append(2u, '\0');
 
-  std::unique_ptr<Parser> parser(new Parser(filename, *raw_buffer, typenames));
+  Parser parser(clean_path, *raw_buffer, is_preprocessed);
 
-  if (yy::parser(parser.get()).parse() != 0 || parser->HasError()) {
+  if (yy::parser(&parser).parse() != 0 || parser.HasError()) {
     return nullptr;
   }
 
-  return parser;
+  // transfer ownership to AidlTypenames and return the raw pointer
+  const AidlDocument* result = parser.document_.get();
+  if (!typenames.AddDocument(std::move(parser.document_))) {
+    return nullptr;
+  }
+  return result;
 }
 
 void Parser::SetTypeParameters(AidlTypeSpecifier* type,
@@ -61,64 +76,201 @@
   }
 }
 
-class ConstantReferenceResolver : public AidlVisitor {
- public:
-  ConstantReferenceResolver(const AidlDefinedType* scope, const AidlTypenames& typenames,
-                            TypeResolver& resolver, bool* success)
-      : scope_(scope), typenames_(typenames), resolver_(resolver), success_(success) {}
-  void Visit(const AidlConstantReference& v) override {
-    if (IsCircularReference(&v)) {
-      *success_ = false;
-      return;
-    }
+void Parser::CheckValidTypeName(const AidlToken& token, const AidlLocation& loc) {
+  if (!is_preprocessed_ && token.GetText().find('.') != std::string::npos) {
+    AIDL_ERROR(loc) << "Type name can't be qualified. Use `package`.";
+    AddError();
+  }
+}
 
-    if (v.GetRefType() && !v.GetRefType()->IsResolved()) {
-      if (!resolver_(typenames_.GetDocumentFor(scope_), v.GetRefType().get())) {
-        AIDL_ERROR(v.GetRefType()) << "Unknown type '" << v.GetRefType()->GetName() << "'";
-        *success_ = false;
-        return;
+void Parser::SetPackage(const std::string& package) {
+  if (is_preprocessed_) {
+    AIDL_ERROR(package) << "Preprocessed file can't declare package.";
+    AddError();
+  }
+  package_ = package;
+}
+
+bool CheckNoRecursiveDefinition(const AidlNode& node) {
+  struct Visitor : AidlVisitor {
+    enum {
+      NOT_STARTED = 0,
+      STARTED = 1,
+      FINISHED = 2,
+    };
+    std::map<const AidlParcelable*, int> visited;
+    std::vector<std::string> path;
+    bool found_cycle = false;
+
+    void Visit(const AidlStructuredParcelable& t) override { FindCycle(&t); }
+    void Visit(const AidlUnionDecl& t) override { FindCycle(&t); }
+    void Visit(const AidlParcelable& t) override { FindCycle(&t); }
+
+    bool FindCycle(const AidlParcelable* p) {
+      // no need to search further
+      if (found_cycle) {
+        return true;
       }
+      // we just found a cycle
+      if (visited[p] == STARTED) {
+        path.push_back(p->GetName());
+        AIDL_ERROR(p) << p->GetName()
+                      << " is a recursive parcelable: " << android::base::Join(path, "->");
+        return (found_cycle = true);
+      }
+      // we arrived here with a different route.
+      if (visited[p] == FINISHED) {
+        return false;
+      }
+      // start DFS
+      visited[p] = STARTED;
+      path.push_back(p->GetName());
+      for (const auto& f : p->GetFields()) {
+        const auto& ref = f->GetType();
+        if (!ref.IsArray() && !ref.IsHeapNullable()) {
+          const auto& type = ref.GetDefinedType();
+          if (type && type->AsParcelable()) {
+            if (FindCycle(type->AsParcelable())) {
+              return true;
+            }
+          }
+        }
+      }
+      path.pop_back();
+      visited[p] = FINISHED;
+      return false;
     }
-    const AidlConstantValue* resolved = v.Resolve(scope_);
-    if (!resolved) {
-      AIDL_ERROR(v) << "Unknown reference '" << v.Literal() << "'";
-      *success_ = false;
-      return;
-    }
+  } v;
+  VisitTopDown(v, node);
+  return !v.found_cycle;
+}
 
-    // resolve recursive references
-    Push(&v);
-    VisitTopDown(*this, *resolved);
-    Pop();
+// Each Visit*() method can use Scope() to get its scope(AidlDefinedType)
+class ScopedVisitor : public AidlVisitor {
+ protected:
+  const AidlDefinedType* Scope() const {
+    AIDL_FATAL_IF(scope_.empty(), AIDL_LOCATION_HERE) << "Scope is empty";
+    return scope_.back();
+  }
+  void PushScope(const AidlDefinedType* scope) { scope_.push_back(scope); }
+  void PopScope() { scope_.pop_back(); }
+  // Keep user defined type as a defining scope
+  void VisitScopedTopDown(const AidlNode& node) {
+    std::function<void(const AidlNode&)> top_down = [&](const AidlNode& a) {
+      a.DispatchVisit(*this);
+      auto defined_type = AidlCast<AidlDefinedType>(a);
+      if (defined_type) PushScope(defined_type);
+      a.TraverseChildren(top_down);
+      if (defined_type) PopScope();
+    };
+    top_down(node);
   }
 
  private:
-  struct StackElem {
-    const AidlDefinedType* scope;
-    const AidlConstantReference* ref;
-  };
+  std::vector<const AidlDefinedType*> scope_ = {};
+};
 
-  void Push(const AidlConstantReference* ref) {
-    stack_.push_back({scope_, ref});
-    if (ref->GetRefType()) {
-      scope_ = ref->GetRefType()->GetDefinedType();
+class TypeReferenceResolver : public ScopedVisitor {
+ public:
+  TypeReferenceResolver(TypeResolver& resolver) : resolver_(resolver) {}
+
+  void Visit(const AidlTypeSpecifier& t) override {
+    // We're visiting the same node again. This can happen when two constant references
+    // point to an ancestor of this node.
+    if (t.IsResolved()) {
+      return;
+    }
+    AidlTypeSpecifier& type = const_cast<AidlTypeSpecifier&>(t);
+    if (!resolver_(Scope(), &type)) {
+      AIDL_ERROR(type) << "Failed to resolve '" << type.GetUnresolvedName() << "'";
+      success_ = false;
+      return;
+    }
+
+    // In case a new document is imported for the type reference, enqueue it for type resolution.
+    auto resolved = t.GetDefinedType();
+    if (resolved) {
+      queue_.push(&resolved->GetDocument());
     }
   }
 
-  void Pop() {
-    scope_ = stack_.back().scope;
+  bool Resolve(const AidlDocument& document) {
+    queue_.push(&document);
+    while (!queue_.empty()) {
+      auto doc = queue_.front();
+      queue_.pop();
+      // Skip the doc if it's visited already.
+      if (!visited_.insert(doc).second) {
+        continue;
+      }
+      VisitScopedTopDown(*doc);
+    }
+    return success_;
+  }
+
+ private:
+  TypeResolver& resolver_;
+  bool success_ = true;
+  std::queue<const AidlDocument*> queue_ = {};
+  std::set<const AidlDocument*> visited_ = {};
+};
+
+class ConstantReferenceResolver : public ScopedVisitor {
+ public:
+  ConstantReferenceResolver() = default;
+
+  void Visit(const AidlConstantReference& v) override {
+    if (IsCircularReference(&v)) {
+      success_ = false;
+      return;
+    }
+
+    const AidlConstantValue* resolved = v.Resolve(Scope());
+    if (!resolved) {
+      AIDL_ERROR(v) << "Unknown reference '" << v.Literal() << "'";
+      success_ = false;
+      return;
+    }
+
+    // On error, skip recursive visiting to avoid redundant messages
+    if (!success_) {
+      return;
+    }
+    // resolve recursive references
+    PushConstRef(&v);
+    VisitScopedTopDown(*resolved);
+    PopConstRef();
+  }
+
+  bool Resolve(const AidlDocument& document) {
+    VisitScopedTopDown(document);
+    return success_;
+  }
+
+ private:
+  void PushConstRef(const AidlConstantReference* ref) {
+    stack_.push_back(ref);
+    if (ref->GetRefType()) {
+      PushScope(ref->GetRefType()->GetDefinedType());
+    }
+  }
+
+  void PopConstRef() {
+    if (stack_.back()->GetRefType()) {
+      PopScope();
+    }
     stack_.pop_back();
   }
 
   bool IsCircularReference(const AidlConstantReference* ref) {
-    auto it = std::find_if(stack_.begin(), stack_.end(),
-                           [&](const auto& elem) { return elem.ref == ref; });
+    auto it =
+        std::find_if(stack_.begin(), stack_.end(), [&](const auto& elem) { return elem == ref; });
     if (it == stack_.end()) {
       return false;
     }
     std::vector<std::string> path;
     while (it != stack_.end()) {
-      path.push_back(it->ref->Literal());
+      path.push_back((*it)->Literal());
       ++it;
     }
     path.push_back(ref->Literal());
@@ -126,35 +278,28 @@
     return true;
   }
 
-  const AidlDefinedType* scope_;
-  const AidlTypenames& typenames_;
-  TypeResolver& resolver_;
-  bool* success_;
-  std::vector<StackElem> stack_ = {};
+  bool success_ = true;
+  std::vector<const AidlConstantReference*> stack_ = {};
 };
 
-bool Parser::Resolve(TypeResolver& type_resolver) {
-  bool success = true;
-  for (AidlTypeSpecifier* typespec : unresolved_typespecs_) {
-    if (!type_resolver(document_, typespec)) {
-      AIDL_ERROR(typespec) << "Failed to resolve '" << typespec->GetUnresolvedName() << "'";
-      success = false;
-      // don't stop to show more errors if any
-    }
+// Resolve references(types/constants) in the "main" document.
+bool ResolveReferences(const AidlDocument& document, TypeResolver& type_resolver) {
+  // Types are resolved first before resolving constant references so that every referenced document
+  // gets imported.
+  if (!TypeReferenceResolver(type_resolver).Resolve(document)) {
+    return false;
   }
-
-  // resolve "field references" as well.
-  for (const auto& type : document_->DefinedTypes()) {
-    ConstantReferenceResolver ref_resolver{type.get(), typenames_, type_resolver, &success};
-    VisitTopDown(ref_resolver, *type);
+  if (!ConstantReferenceResolver().Resolve(document)) {
+    return false;
   }
-
-  return success;
+  if (!CheckNoRecursiveDefinition(document)) {
+    return false;
+  }
+  return true;
 }
 
-Parser::Parser(const std::string& filename, std::string& raw_buffer,
-               android::aidl::AidlTypenames& typenames)
-    : filename_(filename), typenames_(typenames) {
+Parser::Parser(const std::string& filename, std::string& raw_buffer, bool is_preprocessed)
+    : filename_(filename), is_preprocessed_(is_preprocessed) {
   yylex_init(&scanner_);
   buffer_ = yy_scan_buffer(&raw_buffer[0], raw_buffer.length(), scanner_);
 }
@@ -163,3 +308,11 @@
   yy_delete_buffer(buffer_, scanner_);
   yylex_destroy(scanner_);
 }
+
+void Parser::MakeDocument(const AidlLocation& location, const Comments& comments,
+                          std::vector<std::string> imports,
+                          std::vector<std::unique_ptr<AidlDefinedType>> defined_types) {
+  AIDL_FATAL_IF(document_.get(), location);
+  document_ = std::make_unique<AidlDocument>(location, comments, std::move(imports),
+                                             std::move(defined_types), is_preprocessed_);
+}
diff --git a/parser.h b/parser.h
index e2dea08..074d6d5 100644
--- a/parser.h
+++ b/parser.h
@@ -54,7 +54,8 @@
   android::aidl::Comments comments_;
 };
 
-using TypeResolver = std::function<bool(const AidlDocument*, AidlTypeSpecifier*)>;
+using TypeResolver = std::function<bool(const AidlDefinedType*, AidlTypeSpecifier*)>;
+bool ResolveReferences(const AidlDocument& document, TypeResolver& resolver);
 
 class Parser {
  public:
@@ -65,9 +66,9 @@
   ~Parser();
 
   // Parse contents of file |filename|. Should only be called once.
-  static std::unique_ptr<Parser> Parse(const std::string& filename,
-                                       const android::aidl::IoDelegate& io_delegate,
-                                       AidlTypenames& typenames);
+  static const AidlDocument* Parse(const std::string& filename,
+                                   const android::aidl::IoDelegate& io_delegate,
+                                   AidlTypenames& typenames, bool is_preprocessed = false);
 
   void AddError() { error_++; }
   bool HasError() const { return error_ != 0; }
@@ -84,43 +85,25 @@
   void SetTypeParameters(AidlTypeSpecifier* type,
                          std::vector<std::unique_ptr<AidlTypeSpecifier>>* type_args);
 
-  void SetPackage(const std::string& package) { package_ = package; }
+  // fully-qualified type names are allowed only in preprocessed files
+  void CheckValidTypeName(const AidlToken& token, const AidlLocation& loc);
+
+  void SetPackage(const std::string& package);
   const std::string& Package() const { return package_; }
 
-  void DeferResolution(AidlTypeSpecifier* typespec) {
-    unresolved_typespecs_.emplace_back(typespec);
-  }
-
-  const vector<AidlTypeSpecifier*>& GetUnresolvedTypespecs() const { return unresolved_typespecs_; }
-
-  bool Resolve(TypeResolver& type_resolver);
-  void SetDocument(std::unique_ptr<AidlDocument>&& document) {
-    // The parsed document is owned by typenames_. This parser object only has
-    // a reference to it.
-    document_ = document.get();
-    if (!typenames_.AddDocument(std::move(document))) {
-      document_ = nullptr;
-      AddError();
-    }
-  }
-
-  const AidlDocument& ParsedDocument() const {
-    AIDL_FATAL_IF(HasError(), FileName());
-    return *document_;
-  }
+  void MakeDocument(const AidlLocation& location, const Comments& comments,
+                    std::vector<std::string> imports,
+                    std::vector<std::unique_ptr<AidlDefinedType>> defined_types);
 
  private:
-  explicit Parser(const std::string& filename, std::string& raw_buffer,
-                  android::aidl::AidlTypenames& typenames);
+  explicit Parser(const std::string& filename, std::string& raw_buffer, bool is_preprocessed);
 
   std::string filename_;
+  bool is_preprocessed_;
   std::string package_;
-  AidlTypenames& typenames_;
-
   void* scanner_ = nullptr;
   YY_BUFFER_STATE buffer_;
   int error_ = 0;
 
-  vector<AidlTypeSpecifier*> unresolved_typespecs_;
-  const AidlDocument* document_;
+  std::unique_ptr<AidlDocument> document_;
 };
diff --git a/permission.cpp b/permission.cpp
new file mode 100644
index 0000000..96cff20
--- /dev/null
+++ b/permission.cpp
@@ -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.
+ */
+
+#include "permission.h"
+#include <memory>
+#include <string>
+#include <variant>
+#include <vector>
+
+#include <android-base/strings.h>
+
+namespace android {
+namespace aidl {
+namespace perm {
+
+std::string AsJavaAnnotation(const Expression& expr) {
+  if (const auto& s = std::get_if<std::string>(&expr); s) {
+    return JavaAnnotation(*s);
+  }
+  if (const auto& all = std::get_if<AllOf>(&expr); all) {
+    return all->JavaAnnotation();
+  }
+  if (const auto& any = std::get_if<AnyOf>(&expr); any) {
+    return any->JavaAnnotation();
+  }
+  return "";
+}
+
+std::string JavaAnnotation(const std::string& permission) {
+  return "android.Manifest.permission." + permission;
+}
+
+}  // namespace perm
+}  // namespace aidl
+}  // namespace android
diff --git a/permission.h b/permission.h
new file mode 100644
index 0000000..cd87d5c
--- /dev/null
+++ b/permission.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <variant>
+#include <vector>
+
+#include <android-base/strings.h>
+
+namespace android {
+namespace aidl {
+namespace perm {
+
+struct AnyOf;
+struct AllOf;
+
+typedef std::variant<std::string, AnyOf, AllOf> Expression;
+std::string AsJavaAnnotation(const Expression& expr);
+std::string JavaAnnotation(const std::string& permission);
+
+struct AnyOf {
+  std::vector<std::string> operands;
+
+  std::string JavaAnnotation() const {
+    std::string ret("anyOf = {");
+    for (size_t i = 0; i < operands.size(); i++) {
+      ret += android::aidl::perm::JavaAnnotation(operands[i]);
+      if (i != operands.size() - 1) {
+        ret += ", ";
+      }
+    }
+    return ret + "}";
+  }
+};
+
+struct AllOf {
+  std::vector<std::string> operands;
+
+  std::string JavaAnnotation() const {
+    std::string ret("allOf = {");
+    for (size_t i = 0; i < operands.size(); i++) {
+      ret += android::aidl::perm::JavaAnnotation(operands[i]);
+      if (i != operands.size() - 1) {
+        ret += ", ";
+      }
+    }
+    return ret + "}";
+  }
+};
+
+
+
+}  // namespace perm
+}  // namespace aidl
+}  // namespace android
diff --git a/preprocess.cpp b/preprocess.cpp
new file mode 100644
index 0000000..b332f2e
--- /dev/null
+++ b/preprocess.cpp
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+#include "preprocess.h"
+
+#include <android-base/strings.h>
+
+#include "aidl.h"
+
+using android::base::Join;
+
+namespace android {
+namespace aidl {
+
+namespace {
+// PreprocessVisitor emits
+// - types including comments(hide/deprecated) and annotations
+// - constant delcarations for interface/parcelable/unions
+// - enumerators for enums
+struct PreprocessVisitor : AidlVisitor {
+  CodeWriter& out;
+  PreprocessVisitor(CodeWriter& out) : out(out) {}
+
+  void DumpType(const AidlDefinedType& dt, const string& type) {
+    DumpComments(dt);
+    DumpAnnotations(dt);
+    // Top-level definition emits canonical name while nested type emits "name" only.
+    if (dt.GetParentType()) {
+      out << type << " " << dt.GetName();
+    } else {
+      out << type << " " << dt.GetCanonicalName();
+    }
+    if (auto generic_type = dt.AsParameterizable(); generic_type && generic_type->IsGeneric()) {
+      out << "<" << Join(generic_type->GetTypeParameters(), ", ") << ">";
+    }
+  }
+  void DumpMembers(const AidlDefinedType& dt) {
+    out << " {\n";
+    out.Indent();
+    for (const auto& constdecl : dt.GetConstantDeclarations()) {
+      constdecl->DispatchVisit(*this);
+    }
+    for (const auto& nested : dt.GetNestedTypes()) {
+      nested->DispatchVisit(*this);
+    }
+    out.Dedent();
+    out << "}\n";
+  }
+  void DumpComments(const AidlCommentable& c) {
+    const auto hidden = c.IsHidden();
+    const auto deprecated = FindDeprecated(c.GetComments());
+    if (hidden || deprecated) {
+      out << "/**\n";
+      if (hidden) {
+        out << " * @hide\n";
+      }
+      if (deprecated) {
+        out << " * @deprecated " << deprecated->note << "\n";
+      }
+      out << " */\n";
+    }
+  }
+  void DumpAnnotations(const AidlAnnotatable& a) {
+    auto annotations = a.ToString();
+    if (!annotations.empty()) {
+      out << annotations << "\n";
+    }
+  }
+  void DumpConstantValue(const AidlTypeSpecifier& type, const AidlConstantValue& c) {
+    out << c.ValueString(type, AidlConstantValueDecorator);
+  }
+  void Visit(const AidlInterface& t) override {
+    DumpType(t, "interface");
+    DumpMembers(t);
+  }
+  void Visit(const AidlParcelable& t) override {
+    DumpType(t, "parcelable");
+    if (const auto& cpp_header = t.GetCppHeader(); !cpp_header.empty()) {
+      out << " cpp_header " << cpp_header;
+    }
+    out << ";\n";
+  }
+  void Visit(const AidlStructuredParcelable& t) override {
+    DumpType(t, "parcelable");
+    DumpMembers(t);
+  }
+  void Visit(const AidlUnionDecl& t) override {
+    DumpType(t, "union");
+    DumpMembers(t);
+  }
+  void Visit(const AidlEnumDeclaration& t) override {
+    DumpType(t, "enum");
+    out << " {\n";
+    out.Indent();
+    for (const auto& e : t.GetEnumerators()) {
+      out << e->GetName() << " = ";
+      DumpConstantValue(t.GetBackingType(), *e->GetValue());
+      out << ",\n";
+    }
+    out.Dedent();
+    out << "}\n";
+  }
+  void Visit(const AidlConstantDeclaration& c) override {
+    DumpComments(c);
+    out << "const ";
+    Visit(c.GetType());
+    out << " " << c.GetName() << " = ";
+    DumpConstantValue(c.GetType(), c.GetValue());
+    out << ";\n";
+  }
+  void Visit(const AidlTypeSpecifier& t) override { out << t.ToString(); }
+};
+
+}  // namespace
+
+bool Preprocess(const Options& options, const IoDelegate& io_delegate) {
+  unique_ptr<CodeWriter> writer = io_delegate.GetCodeWriter(options.OutputFile());
+  PreprocessVisitor visitor(*writer);
+
+  for (const auto& file : options.InputFiles()) {
+    AidlTypenames typenames;
+    auto result =
+        internals::load_and_validate_aidl(file, options, io_delegate, &typenames, nullptr);
+    if (result == AidlError::OK) {
+      const auto& doc = typenames.MainDocument();
+      for (const auto& t : doc.DefinedTypes()) {
+        t->DispatchVisit(visitor);
+      }
+    } else {
+      return false;
+    }
+  }
+
+  return writer->Close();
+}
+
+}  // namespace aidl
+}  // namespace android
\ No newline at end of file
diff --git a/preprocess.h b/preprocess.h
new file mode 100644
index 0000000..d734a68
--- /dev/null
+++ b/preprocess.h
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "aidl_language.h"
+#include "code_writer.h"
+
+namespace android {
+namespace aidl {
+
+bool Preprocess(const Options& options, const IoDelegate& io_delegate);
+
+}  // namespace aidl
+}  // namespace android
diff --git a/run_integration_tests.sh b/run_integration_tests.sh
index 1cfd1c1..a423a3e 100755
--- a/run_integration_tests.sh
+++ b/run_integration_tests.sh
@@ -33,5 +33,17 @@
 adb push \
     ${ANDROID_PRODUCT_OUT}/testcases/aidl_test_java_client/*/aidl_test_java_client.jar \
     /data/framework/aidl_test_java_client.jar
+adb push \
+    ${ANDROID_PRODUCT_OUT}/testcases/aidl_test_java_service_sdk29/*/aidl_test_java_service_sdk29.jar \
+    /data/framework/aidl_test_java_service_sdk29.jar
+adb push \
+    ${ANDROID_PRODUCT_OUT}/testcases/aidl_test_java_client_sdk29/*/aidl_test_java_client_sdk29.jar \
+    /data/framework/aidl_test_java_client_sdk29.jar
+adb push \
+    ${ANDROID_PRODUCT_OUT}/testcases/aidl_test_java_service_sdk1/*/aidl_test_java_service_sdk1.jar \
+    /data/framework/aidl_test_java_service_sdk1.jar
+adb push \
+    ${ANDROID_PRODUCT_OUT}/testcases/aidl_test_java_client_sdk1/*/aidl_test_java_client_sdk1.jar \
+    /data/framework/aidl_test_java_client_sdk1.jar
 
 ${ANDROID_BUILD_TOP}/system/tools/aidl/tests/aidl_integration_test.py
diff --git a/rustfmt.toml b/rustfmt.toml
new file mode 120000
index 0000000..475ba8f
--- /dev/null
+++ b/rustfmt.toml
@@ -0,0 +1 @@
+../../../build/soong/scripts/rustfmt.toml
\ No newline at end of file
diff --git a/tests/aidl_integration_test.py b/tests/aidl_integration_test.py
index ca767f4..5f086da 100755
--- a/tests/aidl_integration_test.py
+++ b/tests/aidl_integration_test.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python3
 
+from itertools import product
 import pipes
 import re
 import subprocess
@@ -159,6 +160,38 @@
         if re.search(INSTRUMENTATION_SUCCESS_PATTERN, result.stdout) is None:
             raise TestFail(result.stdout)
 
+class JavaVersionTestClient:
+    def __init__(self, host, bitness, ver):
+        self.name = "java_client_sdk%d_%s" % (ver, pretty_bitness(bitness))
+        self.host = host
+        self.bitness = bitness
+        self.ver = ver
+    def cleanup(self):
+        self.host.run('killall ' + APP_PROCESS_FOR_PRETTY_BITNESS % pretty_bitness(self.bitness),
+                      ignore_status=True)
+    def run(self):
+        result = self.host.run('CLASSPATH=/data/framework/aidl_test_java_client_sdk%d.jar ' % self.ver
+                               + APP_PROCESS_FOR_PRETTY_BITNESS % pretty_bitness(self.bitness) +
+                               ' /data/framework android.aidl.sdkversion.tests.AidlJavaVersionTests')
+        print(result.printable_string())
+        if re.search(INSTRUMENTATION_SUCCESS_PATTERN, result.stdout) is None:
+            raise TestFail(result.stdout)
+
+class JavaVersionTestServer:
+    def __init__(self, host, bitness, ver):
+        self.name = "java_server_sdk%s_%s" % (ver, pretty_bitness(bitness))
+        self.host = host
+        self.bitness = bitness
+        self.ver = ver
+    def cleanup(self):
+        self.host.run('killall ' + APP_PROCESS_FOR_PRETTY_BITNESS % pretty_bitness(self.bitness),
+                      ignore_status=True)
+    def run(self):
+        return self.host.run('CLASSPATH=/data/framework/aidl_test_java_service_sdk%d.jar ' % self.ver
+                             + APP_PROCESS_FOR_PRETTY_BITNESS % pretty_bitness(self.bitness) +
+                             ' /data/framework android.aidl.sdkversion.service.AidlJavaVersionTestService',
+                             background=True)
+
 def getprop(host, prop):
     return host.run('getprop "%s"' % prop).stdout.strip()
 
@@ -185,6 +218,16 @@
     def run(self):
         return self.host.run(self.binary, background=True)
 
+class RustAsyncServer:
+    def __init__(self, host, bitness):
+        self.name = "%s_bit_rust_server_async" % pretty_bitness(bitness)
+        self.host = host
+        self.binary = RUST_TEST_SERVICE_FOR_BITNESS % bitness
+    def cleanup(self):
+        self.host.run('killall %s' % self.binary, ignore_status=True)
+    def run(self):
+        return self.host.run(self.binary, background=True)
+
 def supported_bitnesses(host):
     bitnesses = []
     if getprop(host, "ro.product.cpu.abilist32") != "":
@@ -209,6 +252,11 @@
             server.cleanup()
     return test
 
+def add_test(client, server):
+    test_name = 'test_%s_to_%s' % (client.name, server.name)
+    test = make_test(client, server)
+    setattr(TestAidl, test_name, test)
+
 if __name__ == '__main__':
     host = AdbHost()
     bitnesses = supported_bitnesses(host)
@@ -230,12 +278,19 @@
 
         clients += [RustClient(host, bitness)]
         servers += [RustServer(host, bitness)]
+        servers += [RustAsyncServer(host, bitness)]
 
     for client in clients:
         for server in servers:
-            test_name = 'test_%s_to_%s' % (client.name, server.name)
-            test = make_test(client, server)
-            setattr(TestAidl, test_name, test)
+            add_test(client, server)
+
+    # boolean: >= 29
+    # typed:   >= 23
+    versions = [1, 29]
+    for c_version, c_bitness, s_version, s_bitness in product(versions, bitnesses, repeat=2):
+        client = JavaVersionTestClient(host, c_bitness, c_version)
+        server = JavaVersionTestServer(host, s_bitness, s_version)
+        add_test(client, server)
 
     suite = unittest.TestLoader().loadTestsFromTestCase(TestAidl)
     sys.exit(not unittest.TextTestRunner(verbosity=2).run(suite).wasSuccessful())
diff --git a/tests/aidl_integration_test.xml b/tests/aidl_integration_test.xml
index 6f4f686..4e56e30 100644
--- a/tests/aidl_integration_test.xml
+++ b/tests/aidl_integration_test.xml
@@ -41,6 +41,12 @@
       <option name="push" value="aidl_test_java_client.jar->/data/framework/aidl_test_java_client.jar" />
       <option name="push" value="aidl_test_java_service.jar->/data/framework/aidl_test_java_service.jar" />
 
+      <option name="push" value="aidl_test_java_client_sdk29.jar->/data/framework/aidl_test_java_client_sdk29.jar" />
+      <option name="push" value="aidl_test_java_service_sdk29.jar->/data/framework/aidl_test_java_service_sdk29.jar" />
+
+      <option name="push" value="aidl_test_java_client_sdk1.jar->/data/framework/aidl_test_java_client_sdk1.jar" />
+      <option name="push" value="aidl_test_java_service_sdk1.jar->/data/framework/aidl_test_java_service_sdk1.jar" />
+
       <option name="cleanup" value="true" />
     </target_preparer>
 
diff --git a/tests/aidl_parser_fuzzer.cpp b/tests/aidl_parser_fuzzer.cpp
index cbae184..4e37b31 100644
--- a/tests/aidl_parser_fuzzer.cpp
+++ b/tests/aidl_parser_fuzzer.cpp
@@ -29,7 +29,30 @@
 
 using android::aidl::test::FakeIoDelegate;
 
-void fuzz(const FakeIoDelegate& io, const std::vector<std::string>& args) {
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  if (size <= 1) return 0;  // no use
+
+  // b/145447540, large nested expressions sometimes hit the stack depth limit.
+  // Fuzzing things of this size don't provide any additional meaningful
+  // coverage. This is an approximate value which should allow us to explore all
+  // of the language w/o hitting a stack overflow.
+  if (size > 2000) return 0;
+
+  FuzzedDataProvider provider = FuzzedDataProvider(data, size);
+  FakeIoDelegate io;
+  std::vector<std::string> args;
+
+  size_t numArgs = provider.ConsumeIntegralInRange(0, 20);
+  for (size_t i = 0; i < numArgs; i++) {
+    args.emplace_back(provider.ConsumeRandomLengthString());
+  }
+
+  while (provider.remaining_bytes() > 0) {
+    const std::string name = provider.ConsumeRandomLengthString();
+    const std::string contents = provider.ConsumeRandomLengthString();
+    io.SetFileContents(name, contents);
+  }
+
   if (kFuzzLog) {
     std::cout << "cmd: ";
     for (const std::string& arg : args) {
@@ -43,71 +66,16 @@
   }
 
   int ret = android::aidl::aidl_entry(Options::From(args), io);
-  if (ret != 0) return;
 
   if (kFuzzLog) {
-    for (const auto& [f, output] : io.OutputFiles()) {
-      std::cout << "OUTPUT " << f << ": " << std::endl;
-      std::cout << output << std::endl;
+    std::cout << "RET: " << ret << std::endl;
+    if (ret != 0) {
+      for (const auto& [f, output] : io.OutputFiles()) {
+        std::cout << "OUTPUT " << f << ": " << std::endl;
+        std::cout << output << std::endl;
+      }
     }
   }
-}
-
-void fuzzLang(const std::string& langOpt, const std::string& content) {
-  FakeIoDelegate io;
-  io.SetFileContents("a/path/Foo.aidl", content);
-
-  std::vector<std::string> args;
-  args.emplace_back("aidl");
-  args.emplace_back("--lang=" + langOpt);
-  args.emplace_back("-b");
-  args.emplace_back("-I .");
-  args.emplace_back("-o out");
-  // corresponding package also in aidl_parser_fuzzer.dict
-  args.emplace_back("a/path/Foo.aidl");
-
-  fuzz(io, args);
-}
-
-void fuzzCheckApi(const std::string& a, const std::string& b) {
-  FakeIoDelegate io;
-  io.SetFileContents("a/path/Foo.aidl", a);
-  io.SetFileContents("b/path/Foo.aidl", b);
-
-  std::vector<std::string> args;
-  args.emplace_back("aidl");
-  args.emplace_back("--checkapi");
-  // corresponding package also in aidl_parser_fuzzer.dict
-  args.emplace_back("a/path/");
-  args.emplace_back("b/path/");
-
-  fuzz(io, args);
-}
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  if (size <= 1) return 0;  // no use
-
-  // b/145447540, large nested expressions sometimes hit the stack depth limit.
-  // Fuzzing things of this size don't provide any additional meaningful
-  // coverage. This is an approximate value which should allow us to explore all
-  // of the language w/o hitting a stack overflow.
-  if (size > 2000) return 0;
-
-  FuzzedDataProvider provider = FuzzedDataProvider(data, size);
-
-  if (provider.ConsumeBool()) {
-    std::string content = provider.ConsumeRemainingBytesAsString();
-
-    fuzzLang("ndk", content);
-    fuzzLang("cpp", content);
-    fuzzLang("java", content);
-    fuzzLang("rust", content);
-  } else {
-    std::string contentA = provider.ConsumeRandomLengthString();
-    std::string contentB = provider.ConsumeRemainingBytesAsString();
-
-    fuzzCheckApi(contentA, contentB);
-  }
 
   return 0;
 }
diff --git a/tests/aidl_parser_fuzzer.dict b/tests/aidl_parser_fuzzer.dict
index ef5fa8b..eb2d8ce 100644
--- a/tests/aidl_parser_fuzzer.dict
+++ b/tests/aidl_parser_fuzzer.dict
@@ -55,6 +55,8 @@
 " @Descriptor "
 " @JavaDervie "
 " @RustDerive "
+" /** @hide */ "
+" /** @deprecated reason */ "
 
 # annotation arguments
 " value "
@@ -86,4 +88,41 @@
 " a.path "
 " b.path "
 " Foo "
+" a/path/Foo.aidl "
+" b/path/Foo.aidl "
+" path/Foo.aidl "
 
+#arguments
+" aidl "
+" --apimapping "
+" --checkapi=compatible "
+" --checkapi=equal "
+" --hash "
+" --help "
+" --lang=java "
+" --lang=ndk "
+" --lang=ndk "
+" --lang=rust "
+" --log "
+" --ninja "
+" --preprocess "
+" --stability "
+" --stability=vintf "
+" --structured "
+" --trace "
+" --transaction_names "
+" -I "
+" -W "
+" -Werror "
+" -Weverything "
+" -Wno- "
+" -Wno-error "
+" -a "
+" -b "
+" -d "
+" -h "
+" -o "
+" -p "
+" -t "
+" -v "
+" -w "
diff --git a/tests/aidl_test_client_builtin_transactions.cpp b/tests/aidl_test_client_builtin_transactions.cpp
new file mode 100644
index 0000000..3252875
--- /dev/null
+++ b/tests/aidl_test_client_builtin_transactions.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+#include "aidl_test_client.h"
+
+#include <binder/IInterface.h>
+
+using android::IInterface;
+using android::OK;
+using android::String16;
+
+TEST_F(AidlTest, Ping) {
+  EXPECT_EQ(OK, IInterface::asBinder(service)->pingBinder());
+}
+
+TEST_F(AidlTest, GetInterfaceDescriptor) {
+  EXPECT_EQ(String16("android.aidl.tests.ITestService"),
+            IInterface::asBinder(service)->getInterfaceDescriptor());
+}
diff --git a/tests/aidl_test_client_defaultimpl.cpp b/tests/aidl_test_client_defaultimpl.cpp
index 32e35d8..df57d2c 100644
--- a/tests/aidl_test_client_defaultimpl.cpp
+++ b/tests/aidl_test_client_defaultimpl.cpp
@@ -38,8 +38,19 @@
   }
 };
 
+/* Make sure the unimplementedMethod behaves as expected before testing the
+ * default impl
+ */
+TEST_F(AidlTest, unimplementedMethodImpl) {
+  int32_t returned_value;
+  auto status = service->UnimplementedMethod(kExpectedArgValue, &returned_value);
+  ASSERT_FALSE(status.isOk()) << status;
+  ASSERT_EQ(status.exceptionCode(), android::binder::Status::EX_TRANSACTION_FAILED);
+  EXPECT_EQ(status.transactionError(), android::UNKNOWN_TRANSACTION);
+}
+
 TEST_F(AidlTest, defaultImpl) {
-  std::unique_ptr<ITestService> defImpl = std::make_unique<Def>();
+  android::sp<ITestService> defImpl = android::sp<Def>::make();
   auto ret = ITestService::setDefaultImpl(std::move(defImpl));
   ASSERT_TRUE(ret);
 
diff --git a/tests/aidl_test_client_delegate.cpp b/tests/aidl_test_client_delegate.cpp
new file mode 100644
index 0000000..c171179
--- /dev/null
+++ b/tests/aidl_test_client_delegate.cpp
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+#include "aidl_test_client.h"
+#include "gmock/gmock.h"
+
+#include "android/aidl/tests/BnTestService.h"
+
+using android::binder::Status;
+
+using android::aidl::tests::ITestService;
+using android::aidl::tests::ITestServiceDelegator;
+
+static constexpr int8_t kCustomByte = 8;
+
+struct CustomDelegator : public ITestServiceDelegator {
+ public:
+  CustomDelegator(sp<ITestService>& impl) : ITestServiceDelegator(impl) {}
+
+  // Change RepeatByte to always return the same byte.
+  Status RepeatByte(int8_t /* token */, int8_t* _aidl_return) override {
+    *_aidl_return = kCustomByte;
+    return Status::ok();
+  }
+};
+
+TEST_F(AidlTest, Delegator) {
+  std::unique_ptr<ITestServiceDelegator> delegator =
+      std::make_unique<ITestServiceDelegator>(service);
+
+  int8_t returned_value;
+  auto status = delegator->RepeatByte(12, &returned_value);
+  ASSERT_TRUE(status.isOk()) << status;
+  EXPECT_EQ(12, returned_value);
+}
+
+TEST_F(AidlTest, CustomDelegator) {
+  std::unique_ptr<CustomDelegator> delegator = std::make_unique<CustomDelegator>(service);
+
+  int8_t returned_value;
+  auto status = delegator->RepeatByte(12, &returned_value);
+  ASSERT_TRUE(status.isOk()) << status;
+  EXPECT_EQ(kCustomByte, returned_value);
+}
diff --git a/tests/aidl_test_client_ndk_nested.cpp b/tests/aidl_test_client_ndk_nested.cpp
new file mode 100644
index 0000000..632e5be
--- /dev/null
+++ b/tests/aidl_test_client_ndk_nested.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <utils/String16.h>
+
+#include <aidl/android/aidl/tests/nested/INestedService.h>
+#include <aidl/android/aidl/tests/nested/ParcelableWithNested.h>
+
+#include <optional>
+
+using aidl::android::aidl::tests::nested::INestedService;
+using aidl::android::aidl::tests::nested::ParcelableWithNested;
+using NestedResult = aidl::android::aidl::tests::nested::INestedService::Result;
+using NestedStatus = aidl::android::aidl::tests::nested::ParcelableWithNested::Status;
+using std::optional;
+using std::shared_ptr;
+using std::vector;
+using testing::Eq;
+using testing::Optional;
+
+struct AidlTest : testing::Test {
+  template <typename T>
+  std::shared_ptr<T> getService() {
+    ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_getService(T::descriptor));
+    return T::fromBinder(binder);
+  }
+};
+
+TEST_F(AidlTest, NestedService) {
+  auto nestedService = getService<INestedService>();
+  ASSERT_NE(nullptr, nestedService);
+
+  ParcelableWithNested p;
+  p.status = NestedStatus::OK;
+  NestedResult r;
+  // OK -> NOT_OK
+  auto status = nestedService->flipStatus(p, &r);
+  EXPECT_TRUE(status.isOk());
+  EXPECT_EQ(r.status, NestedStatus::NOT_OK);
+
+  // NOT_OK -> OK with callback (nested interface)
+  struct Callback : INestedService::BnCallback {
+    optional<ParcelableWithNested::Status> result;
+    ndk::ScopedAStatus done(ParcelableWithNested::Status st) override {
+      result = st;
+      return ndk::ScopedAStatus::ok();
+    }
+  };
+  auto cb = ndk::SharedRefBase::make<Callback>();
+  status = nestedService->flipStatusWithCallback(r.status, cb);
+  EXPECT_TRUE(status.isOk());
+  EXPECT_THAT(cb->result, Optional(NestedStatus::OK));
+
+  // android::enum_ranges<>
+  vector<NestedStatus> values{ndk::enum_range<NestedStatus>().begin(),
+                              ndk::enum_range<NestedStatus>().end()};
+  EXPECT_EQ(values, vector<NestedStatus>({NestedStatus::OK, NestedStatus::NOT_OK}));
+
+  // toString()
+  EXPECT_EQ(toString(NestedStatus::NOT_OK), "NOT_OK");
+}
diff --git a/tests/aidl_test_client_ndk_nullables.cpp b/tests/aidl_test_client_ndk_nullables.cpp
new file mode 100644
index 0000000..7b56cf9
--- /dev/null
+++ b/tests/aidl_test_client_ndk_nullables.cpp
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <aidl/android/aidl/tests/ITestService.h>
+
+using aidl::android::aidl::tests::BackendType;
+using aidl::android::aidl::tests::INamedCallback;
+using aidl::android::aidl::tests::ITestService;
+using testing::Eq;
+
+struct AidlTest : testing::Test {
+  template <typename T>
+  std::shared_ptr<T> getService() {
+    ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_getService(T::descriptor));
+    return T::fromBinder(binder);
+  }
+  void SetUp() override {
+    service = getService<ITestService>();
+    auto status = service->getBackendType(&backend);
+    ASSERT_TRUE(status.isOk()) << status.getDescription();
+  }
+  std::shared_ptr<ITestService> service;
+  BackendType backend;
+
+  template <typename T>
+  void DoTest(ndk::ScopedAStatus (ITestService::*func)(const std::optional<T>&, std::optional<T>*),
+              std::optional<T> input) {
+    std::optional<T> output;
+    auto status = (*service.*func)(input, &output);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(output.has_value());
+    ASSERT_THAT(*output, Eq(*input));
+
+    input.reset();
+    status = (*service.*func)(input, &output);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_FALSE(output.has_value());
+  }
+};
+
+TEST_F(AidlTest, parcelableArray) {
+  std::vector<std::optional<ITestService::Empty>> input;
+  input.push_back(ITestService::Empty());
+  input.push_back(std::nullopt);
+  DoTest(&ITestService::RepeatNullableParcelableArray, std::make_optional(input));
+}
+
+TEST_F(AidlTest, parcelableList) {
+  std::vector<std::optional<ITestService::Empty>> input;
+  input.push_back(ITestService::Empty());
+  input.push_back(std::nullopt);
+  DoTest(&ITestService::RepeatNullableParcelableList, std::make_optional(input));
+}
+
+TEST_F(AidlTest, nullBinder) {
+  auto status = service->TakesAnIBinder(nullptr);
+  ASSERT_THAT(status.getStatus(), Eq(STATUS_UNEXPECTED_NULL)) << status.getDescription();
+  // Note that NDK backend checks null before transaction while C++ backends doesn't.
+}
+
+TEST_F(AidlTest, binderListWithNull) {
+  std::vector<ndk::SpAIBinder> input{service->asBinder(), nullptr};
+  auto status = service->TakesAnIBinderList(input);
+  ASSERT_THAT(status.getStatus(), Eq(STATUS_UNEXPECTED_NULL));
+  // Note that NDK backend checks null before transaction while C++ backends doesn't.
+}
+
+TEST_F(AidlTest, nonNullBinder) {
+  auto status = service->TakesAnIBinder(service->asBinder());
+  ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(AidlTest, binderListWithoutNull) {
+  std::vector<ndk::SpAIBinder> input{service->asBinder()};
+  auto status = service->TakesAnIBinderList(input);
+  ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(AidlTest, nullBinderToAnnotatedMethod) {
+  auto status = service->TakesANullableIBinder(nullptr);
+  ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(AidlTest, binderListWithNullToAnnotatedMethod) {
+  std::vector<ndk::SpAIBinder> input{service->asBinder(), nullptr};
+  auto status = service->TakesANullableIBinderList(input);
+  ASSERT_TRUE(status.isOk());
+}
+
+TEST_F(AidlTest, binderArray) {
+  std::vector<ndk::SpAIBinder> repeated;
+  if (backend == BackendType::JAVA) {
+    // Java can only modify out-argument arrays in-place
+    repeated.resize(2);
+  }
+  // get INamedCallback for "SpAIBinder" object
+  std::shared_ptr<INamedCallback> callback;
+  auto status = service->GetCallback(false, &callback);
+  ASSERT_TRUE(status.isOk()) << status.getDescription();
+
+  std::vector<ndk::SpAIBinder> reversed;
+  std::vector<ndk::SpAIBinder> input{service->asBinder(), callback->asBinder()};
+  status = service->ReverseIBinderArray(input, &repeated, &reversed);
+  ASSERT_TRUE(status.isOk()) << status.getDescription();
+
+  EXPECT_THAT(input, Eq(repeated));
+  std::reverse(std::begin(reversed), std::end(reversed));
+  EXPECT_THAT(input, Eq(reversed));
+}
+
+TEST_F(AidlTest, nullableBinderArray) {
+  std::optional<std::vector<ndk::SpAIBinder>> repeated;
+  if (backend == BackendType::JAVA) {
+    // Java can only modify out-argument arrays in-place
+    repeated = std::vector<ndk::SpAIBinder>(2);
+  }
+
+  std::optional<std::vector<ndk::SpAIBinder>> reversed;
+  std::optional<std::vector<ndk::SpAIBinder>> input =
+      std::vector<ndk::SpAIBinder>{service->asBinder(), service->asBinder()};
+  auto status = service->ReverseNullableIBinderArray(input, &repeated, &reversed);
+  ASSERT_TRUE(status.isOk()) << status.getDescription();
+
+  EXPECT_THAT(input, Eq(repeated));
+  ASSERT_TRUE(reversed);
+  std::reverse(std::begin(*reversed), std::end(*reversed));
+  EXPECT_THAT(input, Eq(reversed));
+}
\ No newline at end of file
diff --git a/tests/aidl_test_client_ndk_parcelables.cpp b/tests/aidl_test_client_ndk_parcelables.cpp
new file mode 100644
index 0000000..72d309d
--- /dev/null
+++ b/tests/aidl_test_client_ndk_parcelables.cpp
@@ -0,0 +1,204 @@
+/*
+ * 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.
+ */
+
+#include <aidl/android/aidl/loggable/ILoggableInterface.h>
+
+#include <functional>
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <gtest/gtest.h>
+
+#include <aidl/android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+#include <aidl/android/aidl/tests/ITestService.h>
+#include <aidl/android/aidl/tests/RecursiveList.h>
+
+using aidl::android::aidl::fixedsizearray::FixedSizeArrayExample;
+using BnRepeatFixedSizeArray =
+    aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::BnRepeatFixedSizeArray;
+using BpRepeatFixedSizeArray =
+    aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::BpRepeatFixedSizeArray;
+using IntParcelable = aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable;
+using IRepeatFixedSizeArray =
+    aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IRepeatFixedSizeArray;
+using BnEmptyInterface =
+    aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::BnEmptyInterface;
+using aidl::android::aidl::tests::BackendType;
+using aidl::android::aidl::tests::ITestService;
+using aidl::android::aidl::tests::RecursiveList;
+using android::OK;
+using ndk::AParcel_readData;
+using ndk::AParcel_writeData;
+using ndk::ScopedAStatus;
+using ndk::SharedRefBase;
+using ndk::SpAIBinder;
+
+struct AidlTest : testing::Test {
+  template <typename T>
+  std::shared_ptr<T> getService() {
+    ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_getService(T::descriptor));
+    return T::fromBinder(binder);
+  }
+};
+
+// TODO(b/196454897): copy more tests from aidl_test_client
+
+TEST_F(AidlTest, ReverseRecursiveList) {
+  std::unique_ptr<RecursiveList> head;
+  for (int i = 0; i < 10; i++) {
+    auto node = std::make_unique<RecursiveList>();
+    node->value = i;
+    node->next = std::move(head);
+    head = std::move(node);
+  }
+  // head: [9, 8, ... 0]
+
+  RecursiveList reversed;
+  auto status = getService<ITestService>()->ReverseList(*head, &reversed);
+  ASSERT_TRUE(status.isOk());
+
+  // reversed should be [0, 1, .. 9]
+  RecursiveList* cur = &reversed;
+  for (int i = 0; i < 10; i++) {
+    EXPECT_EQ(i, cur->value);
+    cur = cur->next.get();
+  }
+  EXPECT_EQ(nullptr, cur);
+}
+
+TEST_F(AidlTest, FixedSizeArray) {
+  auto parcel = AParcel_create();
+
+  FixedSizeArrayExample p;
+  p.byteMatrix[0][0] = 0;
+  p.byteMatrix[0][1] = 1;
+  p.byteMatrix[1][0] = 2;
+  p.byteMatrix[1][1] = 3;
+  p.floatMatrix[0][0] = 0.f;
+  p.floatMatrix[0][1] = 1.f;
+  p.floatMatrix[1][0] = 2.f;
+  p.floatMatrix[1][1] = 3.f;
+  EXPECT_EQ(OK, p.writeToParcel(parcel));
+
+  AParcel_setDataPosition(parcel, 0);
+
+  FixedSizeArrayExample q;
+  EXPECT_EQ(OK, q.readFromParcel(parcel));
+  EXPECT_EQ(p, q);
+
+  AParcel_delete(parcel);
+}
+
+TEST_F(AidlTest, FixedSizeArrayWithValuesAtNullableFields) {
+  auto parcel = AParcel_create();
+
+  FixedSizeArrayExample p;
+  p.boolNullableArray = std::array<bool, 2>{true, false};
+  p.byteNullableArray = std::array<uint8_t, 2>{42, 0};
+  p.stringNullableArray = std::array<std::optional<std::string>, 2>{"hello", "world"};
+
+  p.boolNullableMatrix.emplace();
+  p.boolNullableMatrix->at(0) = std::array<bool, 2>{true, false};
+  p.byteNullableMatrix.emplace();
+  p.byteNullableMatrix->at(0) = std::array<uint8_t, 2>{42, 0};
+  p.stringNullableMatrix.emplace();
+  p.stringNullableMatrix->at(0) = std::array<std::optional<std::string>, 2>{"hello", "world"};
+
+  EXPECT_EQ(OK, p.writeToParcel(parcel));
+
+  AParcel_setDataPosition(parcel, 0);
+
+  FixedSizeArrayExample q;
+  EXPECT_EQ(OK, q.readFromParcel(parcel));
+  EXPECT_EQ(p, q);
+
+  AParcel_delete(parcel);
+}
+
+TEST_F(AidlTest, FixedSizeArrayOfBytesShouldBePacked) {
+  auto parcel = AParcel_create();
+
+  std::array<std::array<uint8_t, 3>, 2> byte_array;
+  byte_array[0] = {1, 2, 3};
+  byte_array[1] = {4, 5, 6};
+  EXPECT_EQ(OK, AParcel_writeData(parcel, byte_array));
+
+  AParcel_setDataPosition(parcel, 0);
+
+  int32_t len;
+  EXPECT_EQ(OK, AParcel_readData(parcel, &len));
+  EXPECT_EQ(2, len);
+  std::vector<uint8_t> byte_vector;
+  EXPECT_EQ(OK, AParcel_readData(parcel, &byte_vector));
+  EXPECT_EQ(byte_vector, (std::vector<uint8_t>{1, 2, 3}));
+  EXPECT_EQ(OK, AParcel_readData(parcel, &byte_vector));
+  EXPECT_EQ(byte_vector, (std::vector<uint8_t>{4, 5, 6}));
+
+  AParcel_delete(parcel);
+}
+
+template <typename Service, typename MemFn, typename Input>
+void CheckRepeat(Service service, MemFn fn, Input input) {
+  Input out1, out2;
+  EXPECT_TRUE(std::invoke(fn, service, input, &out1, &out2).isOk());
+  EXPECT_EQ(input, out1);
+  EXPECT_EQ(input, out2);
+}
+
+template <typename T>
+std::array<std::array<T, 3>, 2> Make2dArray(std::initializer_list<T> values) {
+  std::array<std::array<T, 3>, 2> arr = {};
+  auto it = std::begin(values);
+  for (auto& row : arr) {
+    for (auto& el : row) {
+      if (it == std::end(values)) break;
+      el = *it++;
+    }
+  }
+  return arr;
+}
+
+TEST_F(AidlTest, FixedSizeArrayOverBinder) {
+  auto service = getService<IRepeatFixedSizeArray>();
+
+  CheckRepeat(service, &IRepeatFixedSizeArray::RepeatBytes, (std::array<uint8_t, 3>{1, 2, 3}));
+
+  CheckRepeat(service, &IRepeatFixedSizeArray::RepeatInts, (std::array<int32_t, 3>{1, 2, 3}));
+
+  auto binder1 = SharedRefBase::make<BnEmptyInterface>()->asBinder();
+  auto binder2 = SharedRefBase::make<BnEmptyInterface>()->asBinder();
+  auto binder3 = SharedRefBase::make<BnEmptyInterface>()->asBinder();
+  CheckRepeat(service, &IRepeatFixedSizeArray::RepeatBinders,
+              (std::array<SpAIBinder, 3>{binder1, binder2, binder3}));
+
+  IntParcelable p1, p2, p3;
+  p1.value = 1;
+  p2.value = 2;
+  p3.value = 3;
+  CheckRepeat(service, &IRepeatFixedSizeArray::RepeatParcelables,
+              (std::array<IntParcelable, 3>{p1, p2, p3}));
+
+  CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dBytes, Make2dArray<uint8_t>({1, 2, 3}));
+
+  CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dInts, Make2dArray<int32_t>({1, 2, 3}));
+
+  // Not-nullable
+  CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dBinders,
+              Make2dArray<SpAIBinder>({binder1, binder2, binder3, binder1, binder2, binder3}));
+
+  CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dParcelables,
+              Make2dArray<IntParcelable>({p1, p2, p3}));
+}
diff --git a/tests/aidl_test_client_ndk_primitives_test.cpp b/tests/aidl_test_client_ndk_primitives_test.cpp
new file mode 100644
index 0000000..e82354f
--- /dev/null
+++ b/tests/aidl_test_client_ndk_primitives_test.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <aidl/android/aidl/tests/ITestService.h>
+
+using aidl::android::aidl::tests::INamedCallback;
+using aidl::android::aidl::tests::ITestService;
+using testing::Eq;
+
+struct AidlTest : testing::Test {
+  template <typename T>
+  std::shared_ptr<T> getService() {
+    ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_getService(T::descriptor));
+    return T::fromBinder(binder);
+  }
+};
+
+TEST_F(AidlTest, InterfaceExchange) {
+  auto service = getService<ITestService>();
+  std::vector<std::string> names = {"Larry", "Curly", "Moe"};
+
+  for (size_t i = 0; i < names.size(); i++) {
+    std::shared_ptr<INamedCallback> got;
+    ASSERT_TRUE(service->GetOtherTestService(names[i], &got).isOk());
+    std::string name;
+    ASSERT_TRUE(got->GetName(&name).isOk());
+    ASSERT_THAT(name, Eq(names[i]));
+  }
+  {
+    std::vector<std::shared_ptr<INamedCallback>> got;
+    ASSERT_TRUE(service->GetInterfaceArray(names, &got).isOk());
+
+    bool verified = false;
+    ASSERT_TRUE(service->VerifyNamesWithInterfaceArray(got, names, &verified).isOk());
+    ASSERT_TRUE(verified);
+
+    for (size_t i = 0; i < names.size(); i++) {
+      std::string name;
+      ASSERT_TRUE(got[i]->GetName(&name).isOk());
+      ASSERT_THAT(name, Eq(names[i]));
+    }
+  }
+  {
+    std::vector<std::optional<std::string>> names = {"Larry", std::nullopt, "Moe"};
+    std::optional<std::vector<std::shared_ptr<INamedCallback>>> got;
+    ASSERT_TRUE(service->GetNullableInterfaceArray(names, &got).isOk());
+    bool verified = false;
+    ASSERT_TRUE(service->VerifyNamesWithNullableInterfaceArray(got, names, &verified).isOk());
+    ASSERT_TRUE(verified);
+    ASSERT_TRUE(got.has_value());
+    for (size_t i = 0; i < names.size(); i++) {
+      if (names[i].has_value()) {
+        ASSERT_NE(got->at(i).get(), nullptr);
+        std::string name;
+        ASSERT_TRUE(got->at(i)->GetName(&name).isOk());
+        ASSERT_THAT(name, Eq(names[i].value()));
+      } else {
+        ASSERT_EQ(got->at(i).get(), nullptr);
+      }
+    }
+  }
+  {
+    std::vector<std::optional<std::string>> names = {"Larry", std::nullopt, "Moe"};
+    std::optional<std::vector<std::shared_ptr<INamedCallback>>> got;
+    ASSERT_TRUE(service->GetInterfaceList(names, &got).isOk());
+    bool verified = false;
+    ASSERT_TRUE(service->VerifyNamesWithInterfaceList(got, names, &verified).isOk());
+    ASSERT_TRUE(verified);
+    ASSERT_TRUE(got.has_value());
+    for (size_t i = 0; i < names.size(); i++) {
+      if (names[i].has_value()) {
+        ASSERT_NE(got->at(i).get(), nullptr);
+        std::string name;
+        ASSERT_TRUE(got->at(i)->GetName(&name).isOk());
+        ASSERT_THAT(name, Eq(names[i].value()));
+      } else {
+        ASSERT_EQ(got->at(i).get(), nullptr);
+      }
+    }
+  }
+}
diff --git a/tests/aidl_test_client_ndk_strings_test.cpp b/tests/aidl_test_client_ndk_strings_test.cpp
new file mode 100644
index 0000000..3623d7e
--- /dev/null
+++ b/tests/aidl_test_client_ndk_strings_test.cpp
@@ -0,0 +1,153 @@
+/*
+ * 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.
+ */
+
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <aidl/android/aidl/tests/ITestService.h>
+
+using aidl::android::aidl::tests::BackendType;
+using aidl::android::aidl::tests::ITestService;
+using testing::Eq;
+
+struct AidlTest : testing::Test {
+  template <typename T>
+  std::shared_ptr<T> getService() {
+    ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_getService(T::descriptor));
+    return T::fromBinder(binder);
+  }
+  void SetUp() override {
+    service = getService<ITestService>();
+    auto status = service->getBackendType(&backend);
+    ASSERT_TRUE(status.isOk()) << status.getDescription();
+  }
+  std::shared_ptr<ITestService> service;
+  BackendType backend;
+};
+
+TEST_F(AidlTest, repeatUtf8String) {
+  const std::vector<std::string> utf8_inputs = {
+      std::string("Deliver us from evil."),
+      std::string(),
+      std::string("\0\0", 2),
+      // Similarly, the utf8 encodings of the small letter yee and euro sign.
+      std::string("\xF0\x90\x90\xB7\xE2\x82\xAC"),
+      ITestService::STRING_TEST_CONSTANT_UTF8,
+  };
+
+  for (const auto& input : utf8_inputs) {
+    std::string reply;
+    auto status = service->RepeatUtf8CppString(input, &reply);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_THAT(reply, Eq(input));
+  }
+
+  std::optional<std::string> reply;
+  auto status = service->RepeatNullableUtf8CppString(std::nullopt, &reply);
+  ASSERT_TRUE(status.isOk());
+  ASSERT_FALSE(reply.has_value());
+
+  for (const auto& input : utf8_inputs) {
+    std::optional<std::string> reply;
+    auto status = service->RepeatNullableUtf8CppString(input, &reply);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(reply.has_value());
+    ASSERT_THAT(*reply, Eq(input));
+  }
+}
+
+TEST_F(AidlTest, reverseUtf8StringArray) {
+  std::vector<std::string> input = {"a", "", "\xc3\xb8"};
+  decltype(input) repeated;
+  if (backend == BackendType::JAVA) {
+    repeated = decltype(input)(input.size());
+  }
+  decltype(input) reversed;
+
+  auto status = service->ReverseUtf8CppString(input, &repeated, &reversed);
+  ASSERT_TRUE(status.isOk()) << status.getDescription();
+  ASSERT_THAT(repeated, Eq(input));
+
+  decltype(input) reversed_input(input);
+  std::reverse(reversed_input.begin(), reversed_input.end());
+  ASSERT_THAT(reversed, Eq(reversed_input));
+}
+
+struct AidlStringArrayTest : public AidlTest {
+  void DoTest(::ndk::ScopedAStatus (ITestService::*func)(
+      const std::optional<std::vector<std::optional<std::string>>>&,
+      std::optional<std::vector<std::optional<std::string>>>*,
+      std::optional<std::vector<std::optional<std::string>>>*)) {
+    std::optional<std::vector<std::optional<std::string>>> input;
+    decltype(input) repeated;
+    decltype(input) reversed;
+
+    auto status = (*service.*func)(input, &repeated, &reversed);
+    ASSERT_TRUE(status.isOk()) << status.getDescription();
+
+    if (func == &ITestService::ReverseUtf8CppStringList && backend == BackendType::JAVA) {
+      // Java cannot clear the input variable to return a null value. It can
+      // only ever fill out a list.
+      ASSERT_TRUE(repeated.has_value());
+    } else {
+      ASSERT_FALSE(repeated.has_value());
+    }
+
+    ASSERT_FALSE(reversed.has_value());
+
+    input = std::vector<std::optional<std::string>>();
+    input->push_back("Deliver us from evil.");
+    input->push_back(std::nullopt);
+    input->push_back("\xF0\x90\x90\xB7\xE2\x82\xAC");
+
+    // usable size needs to be initialized for Java
+    repeated = std::vector<std::optional<std::string>>(input->size());
+
+    status = (*service.*func)(input, &repeated, &reversed);
+    ASSERT_TRUE(status.isOk()) << status.getDescription();
+    ASSERT_TRUE(reversed.has_value());
+    ASSERT_TRUE(repeated.has_value());
+    ASSERT_THAT(reversed->size(), Eq(input->size()));
+    ASSERT_THAT(repeated->size(), Eq(input->size()));
+
+    for (size_t i = 0; i < input->size(); i++) {
+      auto input_str = (*input)[i];
+      auto repeated_str = (*repeated)[i];
+      auto reversed_str = (*reversed)[(reversed->size() - 1) - i];
+      if (!input_str) {
+        ASSERT_FALSE(repeated_str.has_value());
+        ASSERT_FALSE(reversed_str.has_value());
+        // 3 nullptrs to strings.  No need to compare values.
+        continue;
+      }
+      ASSERT_TRUE(repeated_str.has_value());
+      ASSERT_TRUE(reversed_str.has_value());
+
+      ASSERT_THAT(*repeated_str, Eq(*input_str));
+      ASSERT_THAT(*reversed_str, Eq(*input_str));
+    }
+  }
+};
+
+TEST_F(AidlStringArrayTest, nullableList) {
+  DoTest(&ITestService::ReverseUtf8CppStringList);
+}
+
+TEST_F(AidlStringArrayTest, nullableArray) {
+  DoTest(&ITestService::ReverseNullableUtf8CppString);
+}
diff --git a/tests/aidl_test_client_ndk_versioned_interface.cpp b/tests/aidl_test_client_ndk_versioned_interface.cpp
index 9d34b8c..97da834 100644
--- a/tests/aidl_test_client_ndk_versioned_interface.cpp
+++ b/tests/aidl_test_client_ndk_versioned_interface.cpp
@@ -64,8 +64,12 @@
 
 TEST_F(VersionedInterfaceTest, readDataCorrectlyAfterParcelableWithNewField) {
   Foo inFoo, inoutFoo, outFoo;
+  inoutFoo.intDefault42 = 0;
+  outFoo.intDefault42 = 0;
   int32_t ret;
   auto status = versioned->ignoreParcelablesAndRepeatInt(inFoo, &inoutFoo, &outFoo, 43, &ret);
   EXPECT_TRUE(status.isOk()) << status.getDescription();
   EXPECT_EQ(43, ret);
+  EXPECT_EQ(0, inoutFoo.intDefault42);
+  EXPECT_EQ(0, outFoo.intDefault42);
 }
\ No newline at end of file
diff --git a/tests/aidl_test_client_nested.cpp b/tests/aidl_test_client_nested.cpp
new file mode 100644
index 0000000..9f637b1
--- /dev/null
+++ b/tests/aidl_test_client_nested.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#include "aidl_test_client.h"
+
+#include <android/aidl/tests/nested/INestedService.h>
+#include <binder/IServiceManager.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <utils/String16.h>
+
+using android::IBinder;
+using android::sp;
+using android::String16;
+using android::aidl::tests::nested::INestedService;
+using android::aidl::tests::nested::ParcelableWithNested;
+using android::binder::Status;
+using NestedResult = android::aidl::tests::nested::INestedService::Result;
+using NestedStatus = android::aidl::tests::nested::ParcelableWithNested::Status;
+using std::optional;
+using std::pair;
+using std::string;
+using std::vector;
+using testing::Eq;
+using testing::Optional;
+
+TEST_F(AidlTest, NestedService) {
+  sp<INestedService> nestedService;
+  EXPECT_EQ(android::OK, android::getService(INestedService::descriptor, &nestedService));
+  ASSERT_NE(nullptr, nestedService);
+
+  ParcelableWithNested p;
+  p.status = NestedStatus::OK;
+  NestedResult r;
+  // OK -> NOT_OK
+  EXPECT_TRUE(nestedService->flipStatus(p, &r).isOk());
+  EXPECT_EQ(r.status, NestedStatus::NOT_OK);
+
+  // NOT_OK -> OK with callback nested interface
+  struct Callback : INestedService::BnCallback {
+    optional<NestedStatus> result;
+    Status done(NestedStatus st) override {
+      result = st;
+      return Status::ok();
+    }
+  };
+  sp<Callback> cb = new Callback;
+  EXPECT_TRUE(nestedService->flipStatusWithCallback(r.status, cb).isOk());
+  EXPECT_THAT(cb->result, Optional(NestedStatus::OK));
+
+  // android::enum_ranges<>
+  vector<NestedStatus> values{android::enum_range<NestedStatus>().begin(),
+                              android::enum_range<NestedStatus>().end()};
+  EXPECT_EQ(values, vector<NestedStatus>({NestedStatus::OK, NestedStatus::NOT_OK}));
+
+  // toString()
+  EXPECT_EQ(toString(NestedStatus::NOT_OK), "NOT_OK");
+}
diff --git a/tests/aidl_test_client_nullables.cpp b/tests/aidl_test_client_nullables.cpp
index 9a931f8..6cedf63 100644
--- a/tests/aidl_test_client_nullables.cpp
+++ b/tests/aidl_test_client_nullables.cpp
@@ -95,10 +95,8 @@
 }
 
 TEST_F(RepeatNullableTest, parcelable) {
-  auto input = std::make_optional<StructuredParcelable>();
-  input->f = 42;
-
-  std::optional<StructuredParcelable> output;
+  auto input = std::make_optional<ITestService::Empty>();
+  std::optional<ITestService::Empty> output;
   auto status = service->RepeatNullableParcelable(input, &output);
   ASSERT_TRUE(status.isOk());
   ASSERT_TRUE(output.has_value());
@@ -110,6 +108,20 @@
   ASSERT_FALSE(output.has_value());
 }
 
+TEST_F(RepeatNullableTest, parcelableArray) {
+  std::vector<std::optional<ITestService::Empty>> input;
+  input.push_back(ITestService::Empty());
+  input.push_back(std::nullopt);
+  DoTest(&ITestService::RepeatNullableParcelableArray, std::make_optional(input));
+}
+
+TEST_F(RepeatNullableTest, parcelableList) {
+  std::vector<std::optional<ITestService::Empty>> input;
+  input.push_back(ITestService::Empty());
+  input.push_back(std::nullopt);
+  DoTest(&ITestService::RepeatNullableParcelableList, std::make_optional(input));
+}
+
 TEST_F(AidlTest, nullBinder) {
   auto status = service->TakesAnIBinder(nullptr);
 
@@ -121,10 +133,8 @@
 }
 
 TEST_F(AidlTest, binderListWithNull) {
-  if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
-
   std::vector<sp<IBinder>> input{new BBinder(), nullptr};
-  auto status = cpp_java_tests->TakesAnIBinderList(input);
+  auto status = service->TakesAnIBinderList(input);
 
   if (backend == BackendType::JAVA) {
     ASSERT_TRUE(status.isOk()) << status;
@@ -140,10 +150,8 @@
 }
 
 TEST_F(AidlTest, binderListWithoutNull) {
-  if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
-
   std::vector<sp<IBinder>> input{new BBinder(), new BBinder()};
-  auto status = cpp_java_tests->TakesAnIBinderList(input);
+  auto status = service->TakesAnIBinderList(input);
   ASSERT_TRUE(status.isOk());
 }
 
@@ -153,13 +161,47 @@
 }
 
 TEST_F(AidlTest, binderListWithNullToAnnotatedMethod) {
-  if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
-
   std::vector<sp<IBinder>> input{new BBinder(), nullptr};
-  auto status = cpp_java_tests->TakesANullableIBinderList(input);
+  auto status = service->TakesANullableIBinderList(input);
   ASSERT_TRUE(status.isOk());
 }
 
+TEST_F(AidlTest, binderArray) {
+  std::vector<sp<IBinder>> repeated;
+  if (backend == BackendType::JAVA) {
+    // Java can only modify out-argument arrays in-place
+    repeated.resize(2);
+  }
+
+  std::vector<sp<IBinder>> reversed;
+  std::vector<sp<IBinder>> input{new BBinder(), new BBinder()};
+  auto status = service->ReverseIBinderArray(input, &repeated, &reversed);
+  ASSERT_TRUE(status.isOk()) << status;
+
+  EXPECT_THAT(input, Eq(repeated));
+  std::reverse(std::begin(reversed), std::end(reversed));
+  EXPECT_THAT(input, Eq(reversed));
+}
+
+TEST_F(AidlTest, nullableBinderArray) {
+  std::optional<std::vector<sp<IBinder>>> repeated;
+  if (backend == BackendType::JAVA) {
+    // Java can only modify out-argument arrays in-place
+    repeated = std::vector<sp<IBinder>>();
+    repeated->resize(2);
+  }
+
+  std::optional<std::vector<sp<IBinder>>> reversed;
+  std::optional<std::vector<sp<IBinder>>> input = std::vector<sp<IBinder>>{new BBinder(), nullptr};
+  auto status = service->ReverseNullableIBinderArray(input, &repeated, &reversed);
+  ASSERT_TRUE(status.isOk()) << status;
+
+  EXPECT_THAT(input, Eq(repeated));
+  ASSERT_TRUE(reversed);
+  std::reverse(std::begin(*reversed), std::end(*reversed));
+  EXPECT_THAT(input, Eq(reversed));
+}
+
 TEST_F(AidlTest, nonNullBinderToAnnotatedMethod) {
   sp<IBinder> input = new BBinder();
   auto status = service->TakesANullableIBinder(input);
@@ -167,10 +209,8 @@
 }
 
 TEST_F(AidlTest, binderListWithoutNullToAnnotatedMethod) {
-  if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
-
   std::vector<sp<IBinder>> input{new BBinder(), new BBinder()};
-  auto status = cpp_java_tests->TakesANullableIBinderList(input);
+  auto status = service->TakesANullableIBinderList(input);
   ASSERT_TRUE(status.isOk());
 }
 
diff --git a/tests/aidl_test_client_parcelables.cpp b/tests/aidl_test_client_parcelables.cpp
index 5d00aa8..99052bc 100644
--- a/tests/aidl_test_client_parcelables.cpp
+++ b/tests/aidl_test_client_parcelables.cpp
@@ -14,11 +14,13 @@
  * limitations under the License.
  */
 
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
 #include <android/aidl/tests/ParcelableForToString.h>
 #include <android/aidl/tests/extension/MyExt.h>
 #include <android/aidl/tests/extension/MyExt2.h>
 #include <android/aidl/tests/extension/MyExtLike.h>
 #include <android/aidl/tests/unions/EnumUnion.h>
+#include <binder/Binder.h>
 #include "aidl_test_client.h"
 
 #include <string>
@@ -27,6 +29,9 @@
 using android::IInterface;
 using android::sp;
 using android::String16;
+using android::String8;
+using android::aidl::fixedsizearray::FixedSizeArrayExample;
+using android::aidl::tests::BadParcelable;
 using android::aidl::tests::ConstantExpressionEnum;
 using android::aidl::tests::GenericStructuredParcelable;
 using android::aidl::tests::INamedCallback;
@@ -34,6 +39,7 @@
 using android::aidl::tests::ITestService;
 using android::aidl::tests::OtherParcelableForToString;
 using android::aidl::tests::ParcelableForToString;
+using android::aidl::tests::RecursiveList;
 using android::aidl::tests::SimpleParcelable;
 using android::aidl::tests::StructuredParcelable;
 using android::aidl::tests::Union;
@@ -42,11 +48,35 @@
 using android::aidl::tests::extension::MyExt2;
 using android::aidl::tests::extension::MyExtLike;
 using android::aidl::tests::unions::EnumUnion;
+using IntParcelable = android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable;
+using IRepeatFixedSizeArray =
+    android::aidl::fixedsizearray::FixedSizeArrayExample::IRepeatFixedSizeArray;
+using android::BBinder;
+using android::IBinder;
+using android::OK;
 using android::binder::Status;
 using android::os::PersistableBundle;
 using std::string;
 using std::vector;
 
+TEST_F(AidlTest, BadParcelable) {
+  if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
+
+  BadParcelable output;
+  {
+    BadParcelable bad(/*bad=*/true, "Booya", 42);
+    Status status = cpp_java_tests->RepeatBadParcelable(bad, &output);
+    ASSERT_FALSE(status.isOk());
+    EXPECT_EQ(status.exceptionCode(), Status::Exception::EX_BAD_PARCELABLE);
+  }
+  {
+    BadParcelable not_bad(/*bad=*/false, "Booya", 42);
+    Status status = cpp_java_tests->RepeatBadParcelable(not_bad, &output);
+    ASSERT_TRUE(status.isOk());
+    EXPECT_EQ(not_bad, output);
+  }
+}
+
 TEST_F(AidlTest, RepeatSimpleParcelable) {
   if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
 
@@ -295,6 +325,10 @@
   EXPECT_EQ(parcelable.int64_max, INT64_MAX);
   EXPECT_EQ(parcelable.hexInt32_neg_1, -1);
 
+  for (size_t ndx = 0; ndx < parcelable.int8_1.size(); ndx++) {
+    EXPECT_EQ(parcelable.int8_1[ndx], 1) << ndx;
+  }
+
   for (size_t ndx = 0; ndx < parcelable.int32_1.size(); ndx++) {
     EXPECT_EQ(parcelable.int32_1[ndx], 1) << ndx;
   }
@@ -516,3 +550,145 @@
 
   EXPECT_EQ(expected, p.toString());
 }
+
+TEST_F(AidlTest, ReverseRecursiveList) {
+  std::unique_ptr<RecursiveList> head;
+  for (int i = 0; i < 10; i++) {
+    auto node = std::make_unique<RecursiveList>();
+    node->value = i;
+    node->next = std::move(head);
+    head = std::move(node);
+  }
+  // head: [9, 8, ... 0]
+
+  RecursiveList reversed;
+  auto status = service->ReverseList(*head, &reversed);
+  ASSERT_TRUE(status.isOk()) << status.toString8();
+
+  // reversed should be [0, 1, .. 9]
+  RecursiveList* cur = &reversed;
+  for (int i = 0; i < 10; i++) {
+    EXPECT_EQ(i, cur->value);
+    cur = cur->next.get();
+  }
+  EXPECT_EQ(nullptr, cur);
+}
+
+TEST_F(AidlTest, FixedSizeArray) {
+  android::Parcel parcel;
+
+  FixedSizeArrayExample p;
+  p.byteMatrix[0][0] = 0;
+  p.byteMatrix[0][1] = 1;
+  p.byteMatrix[1][0] = 2;
+  p.byteMatrix[1][1] = 3;
+  p.floatMatrix[0][0] = 0.f;
+  p.floatMatrix[0][1] = 1.f;
+  p.floatMatrix[1][0] = 2.f;
+  p.floatMatrix[1][1] = 3.f;
+  EXPECT_EQ(OK, p.writeToParcel(&parcel));
+
+  parcel.setDataPosition(0);
+
+  FixedSizeArrayExample q;
+  EXPECT_EQ(OK, q.readFromParcel(&parcel));
+  EXPECT_EQ(p, q);
+}
+
+TEST_F(AidlTest, FixedSizeArrayWithValuesAtNullableFields) {
+  android::Parcel parcel;
+
+  FixedSizeArrayExample p;
+  p.boolNullableArray = std::array<bool, 2>{true, false};
+  p.byteNullableArray = std::array<uint8_t, 2>{42, 0};
+  p.stringNullableArray = std::array<std::optional<std::string>, 2>{"hello", "world"};
+
+  p.boolNullableMatrix.emplace();
+  p.boolNullableMatrix->at(0) = std::array<bool, 2>{true, false};
+  p.byteNullableMatrix.emplace();
+  p.byteNullableMatrix->at(0) = std::array<uint8_t, 2>{42, 0};
+  p.stringNullableMatrix.emplace();
+  p.stringNullableMatrix->at(0) = std::array<std::optional<std::string>, 2>{"hello", "world"};
+
+  EXPECT_EQ(OK, p.writeToParcel(&parcel));
+
+  parcel.setDataPosition(0);
+
+  FixedSizeArrayExample q;
+  EXPECT_EQ(OK, q.readFromParcel(&parcel));
+  EXPECT_EQ(p, q);
+}
+
+TEST_F(AidlTest, FixedSizeArrayOfBytesShouldBePacked) {
+  android::Parcel parcel;
+
+  std::array<std::array<uint8_t, 3>, 2> byte_array;
+  byte_array[0] = {1, 2, 3};
+  byte_array[1] = {4, 5, 6};
+  EXPECT_EQ(OK, parcel.writeFixedArray(byte_array));
+
+  parcel.setDataPosition(0);
+
+  int32_t len;
+  EXPECT_EQ(OK, parcel.readInt32(&len));
+  EXPECT_EQ(2, len);
+  std::vector<uint8_t> byte_vector;
+  EXPECT_EQ(OK, parcel.readByteVector(&byte_vector));
+  EXPECT_EQ(byte_vector, (std::vector<uint8_t>{1, 2, 3}));
+  EXPECT_EQ(OK, parcel.readByteVector(&byte_vector));
+  EXPECT_EQ(byte_vector, (std::vector<uint8_t>{4, 5, 6}));
+}
+
+template <typename Service, typename MemFn, typename Input>
+void CheckRepeat(Service service, MemFn fn, Input input) {
+  Input out1, out2;
+  EXPECT_TRUE(std::invoke(fn, service, input, &out1, &out2).isOk());
+  EXPECT_EQ(input, out1);
+  EXPECT_EQ(input, out2);
+}
+
+template <typename T>
+std::array<std::array<T, 3>, 2> Make2dArray(std::initializer_list<T> values) {
+  std::array<std::array<T, 3>, 2> arr = {};
+  auto it = std::begin(values);
+  for (auto& row : arr) {
+    for (auto& el : row) {
+      if (it == std::end(values)) break;
+      el = *it++;
+    }
+  }
+  return arr;
+}
+
+TEST_F(AidlTest, FixedSizeArrayOverBinder) {
+  sp<IRepeatFixedSizeArray> service;
+  ASSERT_EQ(OK, getService(IRepeatFixedSizeArray::descriptor, &service));
+
+  CheckRepeat(service, &IRepeatFixedSizeArray::RepeatBytes, (std::array<uint8_t, 3>{1, 2, 3}));
+
+  CheckRepeat(service, &IRepeatFixedSizeArray::RepeatInts, (std::array<int32_t, 3>{1, 2, 3}));
+
+  sp<IBinder> binder1 = new BBinder();
+  sp<IBinder> binder2 = new BBinder();
+  sp<IBinder> binder3 = new BBinder();
+  CheckRepeat(service, &IRepeatFixedSizeArray::RepeatBinders,
+              (std::array<sp<IBinder>, 3>{binder1, binder2, binder3}));
+
+  IntParcelable p1, p2, p3;
+  p1.value = 1;
+  p2.value = 2;
+  p3.value = 3;
+  CheckRepeat(service, &IRepeatFixedSizeArray::RepeatParcelables,
+              (std::array<IntParcelable, 3>{p1, p2, p3}));
+
+  CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dBytes, Make2dArray<uint8_t>({1, 2, 3}));
+
+  CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dInts, Make2dArray<int32_t>({1, 2, 3}));
+
+  // Not-nullable
+  CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dBinders,
+              Make2dArray<sp<IBinder>>({binder1, binder2, binder3, binder1, binder2, binder3}));
+
+  CheckRepeat(service, &IRepeatFixedSizeArray::Repeat2dParcelables,
+              Make2dArray<IntParcelable>({p1, p2, p3}));
+}
\ No newline at end of file
diff --git a/tests/aidl_test_client_primitives.cpp b/tests/aidl_test_client_primitives.cpp
index f15b67e..eff67c4 100644
--- a/tests/aidl_test_client_primitives.cpp
+++ b/tests/aidl_test_client_primitives.cpp
@@ -196,7 +196,62 @@
     ASSERT_TRUE(status.isOk());
     input.push_back(INamedCallback::asBinder(got));
   }
-
+  {
+    std::vector<sp<INamedCallback>> got;
+    auto status = service->GetInterfaceArray(names, &got);
+    ASSERT_TRUE(status.isOk());
+    bool verified = false;
+    status = service->VerifyNamesWithInterfaceArray(got, names, &verified);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(verified);
+    for (int i = 0; i < 3; i++) {
+      String16 name;
+      ASSERT_TRUE(got[i]->GetName(&name).isOk());
+      ASSERT_THAT(name, Eq(names[i]));
+    }
+  }
+  {
+    std::vector<std::optional<String16>> names = {String16{"Larry"}, std::nullopt, String16{"Moe"}};
+    std::optional<std::vector<sp<INamedCallback>>> got;
+    auto status = service->GetNullableInterfaceArray(names, &got);
+    ASSERT_TRUE(status.isOk());
+    bool verified = false;
+    status = service->VerifyNamesWithNullableInterfaceArray(got, names, &verified);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(verified);
+    ASSERT_TRUE(got.has_value());
+    for (int i = 0; i < 3; i++) {
+      if (names[i].has_value()) {
+        ASSERT_NE(got->at(i).get(), nullptr);
+        String16 name;
+        ASSERT_TRUE(got->at(i)->GetName(&name).isOk());
+        ASSERT_THAT(name, Eq(names[i].value()));
+      } else {
+        ASSERT_EQ(got->at(i).get(), nullptr);
+      }
+    }
+  }
+  {
+    std::vector<std::optional<String16>> names = {String16{"Larry"}, std::nullopt, String16{"Moe"}};
+    std::optional<std::vector<sp<INamedCallback>>> got;
+    auto status = service->GetInterfaceList(names, &got);
+    ASSERT_TRUE(status.isOk());
+    bool verified = false;
+    status = service->VerifyNamesWithInterfaceList(got, names, &verified);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_TRUE(verified);
+    ASSERT_TRUE(got.has_value());
+    for (int i = 0; i < 3; i++) {
+      if (names[i].has_value()) {
+        ASSERT_NE(got->at(i).get(), nullptr);
+        String16 name;
+        ASSERT_TRUE(got->at(i)->GetName(&name).isOk());
+        ASSERT_THAT(name, Eq(names[i].value()));
+      } else {
+        ASSERT_EQ(got->at(i).get(), nullptr);
+      }
+    }
+  }
   if (cpp_java_tests) {
     std::vector<sp<IBinder>> output;
     std::vector<sp<IBinder>> reversed;
diff --git a/tests/aidl_test_client_service_exceptions.cpp b/tests/aidl_test_client_service_exceptions.cpp
index df3b29f..89dc19c 100644
--- a/tests/aidl_test_client_service_exceptions.cpp
+++ b/tests/aidl_test_client_service_exceptions.cpp
@@ -24,16 +24,12 @@
 }
 
 TEST_F(AidlTest, serviceSpecificException) {
-  if (backend == BackendType::JAVA) {
-    // TODO(b/169704480): investigate why this is returning 'unexpected null'
-    GTEST_SKIP() << "Broken in Java? b/169704480";
-  }
-
   using testing::Eq;
 
   for (int32_t i = -1; i < 2; ++i) {
     auto status = service->ThrowServiceException(i);
-    ASSERT_THAT(status.exceptionCode(), Eq(android::binder::Status::EX_SERVICE_SPECIFIC)) << status;
-    ASSERT_THAT(status.serviceSpecificErrorCode(), Eq(i)) << status;
+    EXPECT_THAT(status.exceptionCode(), Eq(android::binder::Status::EX_SERVICE_SPECIFIC))
+        << status << " for " << i;
+    EXPECT_THAT(status.serviceSpecificErrorCode(), Eq(i)) << status << " for " << i;
   }
 }
diff --git a/tests/aidl_test_client_versioned_interface.cpp b/tests/aidl_test_client_versioned_interface.cpp
index c42a41b..22a887b 100644
--- a/tests/aidl_test_client_versioned_interface.cpp
+++ b/tests/aidl_test_client_versioned_interface.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android/aidl/versioned/tests/BnFooInterface.h>
 #include <android/aidl/versioned/tests/IFooInterface.h>
 #include <binder/IServiceManager.h>
 #include <gtest/gtest.h>
@@ -27,6 +28,7 @@
 using android::aidl::versioned::tests::BazUnion;
 using android::aidl::versioned::tests::Foo;
 using android::aidl::versioned::tests::IFooInterface;
+using android::aidl::versioned::tests::IFooInterfaceDelegator;
 
 class VersionedInterfaceTest : public AidlTest {
  public:
@@ -79,8 +81,22 @@
 
 TEST_F(VersionedInterfaceTest, readDataCorrectlyAfterParcelableWithNewField) {
   Foo inFoo, inoutFoo, outFoo;
+  inoutFoo.intDefault42 = 0;
+  outFoo.intDefault42 = 0;
   int32_t ret;
   auto status = versioned->ignoreParcelablesAndRepeatInt(inFoo, &inoutFoo, &outFoo, 43, &ret);
   EXPECT_TRUE(status.isOk());
   EXPECT_EQ(43, ret);
-}
\ No newline at end of file
+  EXPECT_EQ(0, inoutFoo.intDefault42);
+  EXPECT_EQ(0, outFoo.intDefault42);
+}
+
+TEST_F(VersionedInterfaceTest, newerDelegatorReturnsImplVersion) {
+  auto delegator = sp<IFooInterfaceDelegator>::make(versioned);
+  EXPECT_EQ(1, delegator->getInterfaceVersion());
+}
+
+TEST_F(VersionedInterfaceTest, newerDelegatorReturnsImplHash) {
+  auto delegator = sp<IFooInterfaceDelegator>::make(versioned);
+  EXPECT_EQ("9e7be1859820c59d9d55dd133e71a3687b5d2e5b", delegator->getInterfaceHash());
+}
diff --git a/tests/aidl_test_service.cpp b/tests/aidl_test_service.cpp
index 22cd42b..f000372 100644
--- a/tests/aidl_test_service.cpp
+++ b/tests/aidl_test_service.cpp
@@ -54,9 +54,13 @@
 #include "android/aidl/tests/extension/MyExt.h"
 #include "android/aidl/tests/extension/MyExt2.h"
 
+#include "android/aidl/tests/nested/BnNestedService.h"
+
 #include "android/aidl/loggable/BnLoggableInterface.h"
 #include "android/aidl/loggable/Data.h"
 
+#include "android/aidl/fixedsizearray/FixedSizeArrayExample.h"
+
 // Used implicitly.
 #undef LOG_TAG
 #define LOG_TAG "aidl_native_service"
@@ -83,6 +87,7 @@
 
 // Generated code:
 using android::aidl::tests::BackendType;
+using android::aidl::tests::BadParcelable;
 using android::aidl::tests::BnCppJavaTests;
 using android::aidl::tests::BnNamedCallback;
 using android::aidl::tests::BnNewName;
@@ -97,6 +102,7 @@
 using android::aidl::tests::IntEnum;
 using android::aidl::tests::IOldName;
 using android::aidl::tests::LongEnum;
+using android::aidl::tests::RecursiveList;
 using android::aidl::tests::SimpleParcelable;
 using android::aidl::tests::StructuredParcelable;
 using android::aidl::tests::Union;
@@ -178,6 +184,11 @@
   CppJavaTests() = default;
   ~CppJavaTests() = default;
 
+  Status RepeatBadParcelable(const BadParcelable& input, BadParcelable* _aidl_return) override {
+    *_aidl_return = input;
+    return Status::ok();
+  }
+
   Status RepeatSimpleParcelable(const SimpleParcelable& input, SimpleParcelable* repeat,
                                 SimpleParcelable* _aidl_return) override {
     ALOGI("Repeated a SimpleParcelable %s", input.toString().c_str());
@@ -249,6 +260,7 @@
   Status ReverseFileDescriptorArray(const vector<unique_fd>& input, vector<unique_fd>* repeated,
                                     vector<unique_fd>* _aidl_return) override {
     ALOGI("Reversing descriptor array of length %zu", input.size());
+    repeated->clear();
     for (const auto& item : input) {
       repeated->push_back(unique_fd(dup(item.get())));
       _aidl_return->push_back(unique_fd(dup(item.get())));
@@ -256,27 +268,6 @@
     std::reverse(_aidl_return->begin(), _aidl_return->end());
     return Status::ok();
   }
-
-  Status TakesAnIBinderList(const vector<sp<IBinder>>& input) override {
-    (void)input;
-    return Status::ok();
-  }
-  Status TakesANullableIBinderList(const optional<vector<sp<IBinder>>>& input) {
-    (void)input;
-    return Status::ok();
-  }
-
-  ::android::binder::Status RepeatExtendableParcelable(
-      const ::android::aidl::tests::extension::ExtendableParcelable& ep,
-      ::android::aidl::tests::extension::ExtendableParcelable* ep2) {
-    ep2->a = ep.a;
-    ep2->b = ep.b;
-    std::shared_ptr<android::aidl::tests::extension::MyExt> myExt;
-    ep.ext.getParcelable(&myExt);
-    ep2->ext.setParcelable(myExt);
-
-    return Status::ok();
-  }
 };
 
 class NativeService : public BnTestService {
@@ -432,6 +423,92 @@
     return status;
   }
 
+  Status GetInterfaceArray(const vector<String16>& names,
+                           vector<sp<INamedCallback>>* _aidl_return) override {
+    vector<sp<INamedCallback>> services(names.size());
+    for (size_t i = 0; i < names.size(); i++) {
+      if (auto st = GetOtherTestService(names[i], &services[i]); !st.isOk()) {
+        return st;
+      }
+    }
+    *_aidl_return = std::move(services);
+    return Status::ok();
+  }
+
+  Status VerifyNamesWithInterfaceArray(const vector<sp<INamedCallback>>& services,
+                                       const vector<String16>& names, bool* _aidl_ret) override {
+    if (services.size() == names.size()) {
+      for (size_t i = 0; i < services.size(); i++) {
+        if (auto st = VerifyName(services[i], names[i], _aidl_ret); !st.isOk() || !*_aidl_ret) {
+          return st;
+        }
+      }
+      *_aidl_ret = true;
+    } else {
+      *_aidl_ret = false;
+    }
+    return Status::ok();
+  }
+
+  Status GetNullableInterfaceArray(const optional<vector<optional<String16>>>& names,
+                                   optional<vector<sp<INamedCallback>>>* _aidl_ret) override {
+    vector<sp<INamedCallback>> services;
+    if (names.has_value()) {
+      for (const auto& name : *names) {
+        if (name.has_value()) {
+          sp<INamedCallback> ret;
+          if (auto st = GetOtherTestService(*name, &ret); !st.isOk()) {
+            return st;
+          }
+          services.push_back(std::move(ret));
+        } else {
+          services.emplace_back();
+        }
+      }
+    }
+    *_aidl_ret = std::move(services);
+    return Status::ok();
+  }
+
+  Status VerifyNamesWithNullableInterfaceArray(const optional<vector<sp<INamedCallback>>>& services,
+                                               const optional<vector<optional<String16>>>& names,
+                                               bool* _aidl_ret) override {
+    if (services.has_value() && names.has_value()) {
+      if (services->size() == names->size()) {
+        for (size_t i = 0; i < services->size(); i++) {
+          if (services->at(i).get() && names->at(i).has_value()) {
+            if (auto st = VerifyName(services->at(i), names->at(i).value(), _aidl_ret);
+                !st.isOk() || !*_aidl_ret) {
+              return st;
+            }
+          } else if (services->at(i).get() || names->at(i).has_value()) {
+            *_aidl_ret = false;
+            return Status::ok();
+          } else {
+            // ok if service=null && name=null
+          }
+        }
+        *_aidl_ret = true;
+      } else {
+        *_aidl_ret = false;
+      }
+    } else {
+      *_aidl_ret = services.has_value() == names.has_value();
+    }
+    return Status::ok();
+  }
+
+  Status GetInterfaceList(const optional<vector<optional<String16>>>& names,
+                          optional<vector<sp<INamedCallback>>>* _aidl_ret) override {
+    return GetNullableInterfaceArray(names, _aidl_ret);
+  }
+
+  Status VerifyNamesWithInterfaceList(const optional<vector<sp<INamedCallback>>>& services,
+                                      const optional<vector<optional<String16>>>& names,
+                                      bool* _aidl_ret) override {
+    return VerifyNamesWithNullableInterfaceArray(services, names, _aidl_ret);
+  }
+
   Status ReverseStringList(const vector<String16>& input,
                            vector<String16>* repeated,
                            vector<String16>* _aidl_return) override {
@@ -493,8 +570,20 @@
     return RepeatNullable(input, _aidl_return);
   }
 
-  Status RepeatNullableParcelable(const optional<StructuredParcelable>& input,
-                                  optional<StructuredParcelable>* _aidl_return) {
+  Status RepeatNullableParcelable(const optional<ITestService::Empty>& input,
+                                  optional<ITestService::Empty>* _aidl_return) {
+    return RepeatNullable(input, _aidl_return);
+  }
+
+  Status RepeatNullableParcelableList(
+      const optional<vector<optional<ITestService::Empty>>>& input,
+      optional<vector<optional<ITestService::Empty>>>* _aidl_return) {
+    return RepeatNullable(input, _aidl_return);
+  }
+
+  Status RepeatNullableParcelableArray(
+      const optional<vector<optional<ITestService::Empty>>>& input,
+      optional<vector<optional<ITestService::Empty>>>* _aidl_return) {
     return RepeatNullable(input, _aidl_return);
   }
 
@@ -506,6 +595,14 @@
     (void)input;
     return Status::ok();
   }
+  Status TakesAnIBinderList(const vector<sp<IBinder>>& input) override {
+    (void)input;
+    return Status::ok();
+  }
+  Status TakesANullableIBinderList(const optional<vector<sp<IBinder>>>& input) {
+    (void)input;
+    return Status::ok();
+  }
 
   Status RepeatUtf8CppString(const string& token,
                              string* _aidl_return) override {
@@ -586,6 +683,51 @@
     return Status::ok();
   }
 
+  ::android::binder::Status RepeatExtendableParcelable(
+      const ::android::aidl::tests::extension::ExtendableParcelable& ep,
+      ::android::aidl::tests::extension::ExtendableParcelable* ep2) {
+    ep2->a = ep.a;
+    ep2->b = ep.b;
+    std::shared_ptr<android::aidl::tests::extension::MyExt> myExt;
+    ep.ext.getParcelable(&myExt);
+    ep2->ext.setParcelable(myExt);
+
+    return Status::ok();
+  }
+
+  ::android::binder::Status ReverseList(const RecursiveList& list, RecursiveList* ret) override {
+    std::unique_ptr<RecursiveList> reversed;
+    const RecursiveList* cur = &list;
+    while (cur) {
+      auto node = std::make_unique<RecursiveList>();
+      node->value = cur->value;
+      node->next = std::move(reversed);
+      reversed = std::move(node);
+      cur = cur->next.get();
+    }
+    *ret = std::move(*reversed);
+    return Status::ok();
+  }
+
+  Status ReverseIBinderArray(const vector<sp<IBinder>>& input, vector<sp<IBinder>>* repeated,
+                             vector<sp<IBinder>>* _aidl_return) override {
+    *repeated = input;
+    *_aidl_return = input;
+    std::reverse(_aidl_return->begin(), _aidl_return->end());
+    return Status::ok();
+  }
+
+  Status ReverseNullableIBinderArray(const std::optional<vector<sp<IBinder>>>& input,
+                                     std::optional<vector<sp<IBinder>>>* repeated,
+                                     std::optional<vector<sp<IBinder>>>* _aidl_return) override {
+    *repeated = input;
+    *_aidl_return = input;
+    if (*_aidl_return) {
+      std::reverse((*_aidl_return)->begin(), (*_aidl_return)->end());
+    }
+    return Status::ok();
+  }
+
   Status UnimplementedMethod(int32_t /* arg */, int32_t* /* _aidl_return */) override {
     LOG_ALWAYS_FATAL("UnimplementedMethod shouldn't be called");
   }
@@ -673,6 +815,94 @@
   }
 };
 
+using namespace android::aidl::tests::nested;
+class NestedService : public BnNestedService {
+ public:
+  NestedService() {}
+  virtual ~NestedService() = default;
+
+  virtual Status flipStatus(const ParcelableWithNested& p, INestedService::Result* _aidl_return) {
+    if (p.status == ParcelableWithNested::Status::OK) {
+      _aidl_return->status = ParcelableWithNested::Status::NOT_OK;
+    } else {
+      _aidl_return->status = ParcelableWithNested::Status::OK;
+    }
+    return Status::ok();
+  }
+  virtual Status flipStatusWithCallback(ParcelableWithNested::Status status,
+                                        const sp<INestedService::ICallback>& cb) {
+    if (status == ParcelableWithNested::Status::OK) {
+      return cb->done(ParcelableWithNested::Status::NOT_OK);
+    } else {
+      return cb->done(ParcelableWithNested::Status::OK);
+    }
+  }
+};
+
+using android::aidl::fixedsizearray::FixedSizeArrayExample;
+class FixedSizeArrayService : public FixedSizeArrayExample::BnRepeatFixedSizeArray {
+ public:
+  FixedSizeArrayService() {}
+  virtual ~FixedSizeArrayService() = default;
+
+  Status RepeatBytes(const std::array<uint8_t, 3>& in_input, std::array<uint8_t, 3>* out_repeated,
+                     std::array<uint8_t, 3>* _aidl_return) override {
+    *out_repeated = in_input;
+    *_aidl_return = in_input;
+    return Status::ok();
+  }
+  Status RepeatInts(const std::array<int32_t, 3>& in_input, std::array<int32_t, 3>* out_repeated,
+                    std::array<int32_t, 3>* _aidl_return) override {
+    *out_repeated = in_input;
+    *_aidl_return = in_input;
+    return Status::ok();
+  }
+  Status RepeatBinders(const std::array<sp<IBinder>, 3>& in_input,
+                       std::array<sp<IBinder>, 3>* out_repeated,
+                       std::array<sp<IBinder>, 3>* _aidl_return) override {
+    *out_repeated = in_input;
+    *_aidl_return = in_input;
+    return Status::ok();
+  }
+  Status RepeatParcelables(
+      const std::array<FixedSizeArrayExample::IntParcelable, 3>& in_input,
+      std::array<FixedSizeArrayExample::IntParcelable, 3>* out_repeated,
+      std::array<FixedSizeArrayExample::IntParcelable, 3>* _aidl_return) override {
+    *out_repeated = in_input;
+    *_aidl_return = in_input;
+    return Status::ok();
+  }
+  Status Repeat2dBytes(const std::array<std::array<uint8_t, 3>, 2>& in_input,
+                       std::array<std::array<uint8_t, 3>, 2>* out_repeated,
+                       std::array<std::array<uint8_t, 3>, 2>* _aidl_return) override {
+    *out_repeated = in_input;
+    *_aidl_return = in_input;
+    return Status::ok();
+  }
+  Status Repeat2dInts(const std::array<std::array<int32_t, 3>, 2>& in_input,
+                      std::array<std::array<int32_t, 3>, 2>* out_repeated,
+                      std::array<std::array<int32_t, 3>, 2>* _aidl_return) override {
+    *out_repeated = in_input;
+    *_aidl_return = in_input;
+    return Status::ok();
+  }
+  Status Repeat2dBinders(const std::array<std::array<sp<IBinder>, 3>, 2>& in_input,
+                         std::array<std::array<sp<IBinder>, 3>, 2>* out_repeated,
+                         std::array<std::array<sp<IBinder>, 3>, 2>* _aidl_return) override {
+    *out_repeated = in_input;
+    *_aidl_return = in_input;
+    return Status::ok();
+  }
+  Status Repeat2dParcelables(
+      const std::array<std::array<FixedSizeArrayExample::IntParcelable, 3>, 2>& in_input,
+      std::array<std::array<FixedSizeArrayExample::IntParcelable, 3>, 2>* out_repeated,
+      std::array<std::array<FixedSizeArrayExample::IntParcelable, 3>, 2>* _aidl_return) override {
+    *out_repeated = in_input;
+    *_aidl_return = in_input;
+    return Status::ok();
+  }
+};
+
 int Run() {
   android::sp<NativeService> service = new NativeService;
   sp<Looper> looper(Looper::prepare(0 /* opts */));
@@ -714,6 +944,23 @@
     return -1;
   }
 
+  android::sp<NestedService> nestedService = new NestedService;
+  status =
+      defaultServiceManager()->addService(nestedService->getInterfaceDescriptor(), nestedService);
+  if (status != OK) {
+    ALOGE("Failed to add service %s", String8(nestedService->getInterfaceDescriptor()).c_str());
+    return -1;
+  }
+
+  android::sp<FixedSizeArrayService> fixedSizeArrayService = new FixedSizeArrayService;
+  status = defaultServiceManager()->addService(fixedSizeArrayService->getInterfaceDescriptor(),
+                                               fixedSizeArrayService);
+  if (status != OK) {
+    ALOGE("Failed to add service %s",
+          String8(fixedSizeArrayService->getInterfaceDescriptor()).c_str());
+    return -1;
+  }
+
   ALOGI("Entering loop");
   while (true) {
     const int result = looper->pollAll(-1 /* timeoutMillis */);
diff --git a/tests/android/aidl/fixedsizearray/FixedSizeArrayExample.aidl b/tests/android/aidl/fixedsizearray/FixedSizeArrayExample.aidl
new file mode 100644
index 0000000..e226c3d
--- /dev/null
+++ b/tests/android/aidl/fixedsizearray/FixedSizeArrayExample.aidl
@@ -0,0 +1,119 @@
+/*
+ * 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.fixedsizearray;
+
+@RustDerive(PartialEq=true)
+parcelable FixedSizeArrayExample {
+    // to see if NxM array works
+    int[2][3] int2x3 = {{1, 2, 3}, {4, 5, 6}};
+
+    boolean[2] boolArray;
+    byte[2] byteArray;
+    char[2] charArray;
+    int[2] intArray;
+    long[2] longArray;
+    float[2] floatArray;
+    double[2] doubleArray;
+    @utf8InCpp String[2] stringArray = {"hello", "world"};
+    ByteEnum[2] byteEnumArray;
+    IntEnum[2] intEnumArray;
+    LongEnum[2] longEnumArray;
+    IntParcelable[2] parcelableArray;
+    // Following fields are not test-friendly because they should be initialized as non-null.
+    // IBinder[2] binderArray;
+    // ParcelFileDescriptor[2] pfdArray;
+    // IEmptyInterface[2] interfaceArray;
+
+    boolean[2][2] boolMatrix;
+    byte[2][2] byteMatrix;
+    char[2][2] charMatrix;
+    int[2][2] intMatrix;
+    long[2][2] longMatrix;
+    float[2][2] floatMatrix;
+    double[2][2] doubleMatrix;
+    @utf8InCpp String[2][2] stringMatrix = {{"hello", "world"}, {"Ciao", "mondo"}};
+    ByteEnum[2][2] byteEnumMatrix;
+    IntEnum[2][2] intEnumMatrix;
+    LongEnum[2][2] longEnumMatrix;
+    IntParcelable[2][2] parcelableMatrix;
+    // Following fields are not test-friendly because they should be initialized as non-null.
+    // ParcelFileDescriptor[2][2] pfdMatrix;
+    // IBinder[2][2] binderMatrix;
+    // IEmptyInterface[2][2] interfaceMatrix;
+
+    @nullable boolean[2] boolNullableArray;
+    @nullable byte[2] byteNullableArray;
+    @nullable char[2] charNullableArray;
+    @nullable int[2] intNullableArray;
+    @nullable long[2] longNullableArray;
+    @nullable float[2] floatNullableArray;
+    @nullable double[2] doubleNullableArray;
+    @nullable @utf8InCpp String[2] stringNullableArray = {"hello", "world"};
+    @nullable ByteEnum[2] byteEnumNullableArray;
+    @nullable IntEnum[2] intEnumNullableArray;
+    @nullable LongEnum[2] longEnumNullableArray;
+    @nullable IBinder[2] binderNullableArray;
+    @nullable ParcelFileDescriptor[2] pfdNullableArray;
+    @nullable IntParcelable[2] parcelableNullableArray;
+    @nullable IEmptyInterface[2] interfaceNullableArray;
+
+    @nullable boolean[2][2] boolNullableMatrix;
+    @nullable byte[2][2] byteNullableMatrix;
+    @nullable char[2][2] charNullableMatrix;
+    @nullable int[2][2] intNullableMatrix;
+    @nullable long[2][2] longNullableMatrix;
+    @nullable float[2][2] floatNullableMatrix;
+    @nullable double[2][2] doubleNullableMatrix;
+    @nullable @utf8InCpp String[2][2] stringNullableMatrix = {
+            {"hello", "world"}, {"Ciao", "mondo"}};
+    @nullable ByteEnum[2][2] byteEnumNullableMatrix;
+    @nullable IntEnum[2][2] intEnumNullableMatrix;
+    @nullable LongEnum[2][2] longEnumNullableMatrix;
+    @nullable IBinder[2][2] binderNullableMatrix;
+    @nullable ParcelFileDescriptor[2][2] pfdNullableMatrix;
+    @nullable IntParcelable[2][2] parcelableNullableMatrix;
+    @nullable IEmptyInterface[2][2] interfaceNullableMatrix;
+
+    @SuppressWarnings(value={"out-array"})
+    interface IRepeatFixedSizeArray {
+        byte[3] RepeatBytes(in byte[3] input, out byte[3] repeated);
+        int[3] RepeatInts(in int[3] input, out int[3] repeated);
+        IBinder[3] RepeatBinders(in IBinder[3] input, out IBinder[3] repeated);
+        IntParcelable[3] RepeatParcelables(
+                in IntParcelable[3] input, out IntParcelable[3] repeated);
+
+        byte[2][3] Repeat2dBytes(in byte[2][3] input, out byte[2][3] repeated);
+        int[2][3] Repeat2dInts(in int[2][3] input, out int[2][3] repeated);
+        IBinder[2][3] Repeat2dBinders(in IBinder[2][3] input, out IBinder[2][3] repeated);
+        IntParcelable[2][3] Repeat2dParcelables(
+                in IntParcelable[2][3] input, out IntParcelable[2][3] repeated);
+    }
+
+    enum ByteEnum { A }
+
+    @Backing(type="int") enum IntEnum { A }
+
+    @Backing(type="long") enum LongEnum { A }
+
+    @JavaDerive(equals=true)
+    @RustDerive(Clone=true, Copy=true, PartialEq=true)
+    parcelable IntParcelable {
+        int value;
+    }
+
+    interface IEmptyInterface {}
+}
diff --git a/tests/android/aidl/loggable/ILoggableInterface.aidl b/tests/android/aidl/loggable/ILoggableInterface.aidl
index 586ce34..066884d 100644
--- a/tests/android/aidl/loggable/ILoggableInterface.aidl
+++ b/tests/android/aidl/loggable/ILoggableInterface.aidl
@@ -11,4 +11,8 @@
             in Data dataValue, @nullable IBinder binderValue,
             inout @nullable ParcelFileDescriptor pfdValue,
             inout ParcelFileDescriptor[] pfdArray);
+
+    interface ISub {
+        void Log(int value);
+    }
 }
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/android/aidl/tests/BadParcelable.aidl b/tests/android/aidl/tests/BadParcelable.aidl
new file mode 100644
index 0000000..3fc6ed5
--- /dev/null
+++ b/tests/android/aidl/tests/BadParcelable.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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;
+
+parcelable BadParcelable cpp_header "tests/bad_parcelable.h";
diff --git a/tests/android/aidl/tests/FixedSize.aidl b/tests/android/aidl/tests/FixedSize.aidl
new file mode 100644
index 0000000..295199f
--- /dev/null
+++ b/tests/android/aidl/tests/FixedSize.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+import android.aidl.tests.LongEnum;
+
+parcelable FixedSize {
+    @FixedSize
+    parcelable FixedParcelable {
+        boolean booleanValue;
+        byte byteValue;
+        char charValue;
+        int intValue;
+        long longValue;
+        float floatValue;
+        double doubleValue;
+        LongEnum enumValue = LongEnum.FOO;
+        FixedUnion parcelableValue;
+    }
+
+    @FixedSize
+    union FixedUnion {
+        boolean booleanValue = false;
+        byte byteValue;
+        char charValue;
+        int intValue;
+        long longValue;
+        float floatValue;
+        double doubleValue;
+        LongEnum enumValue;
+    }
+}
diff --git a/tests/android/aidl/tests/ICppJavaTests.aidl b/tests/android/aidl/tests/ICppJavaTests.aidl
index b0da53a..243d110 100644
--- a/tests/android/aidl/tests/ICppJavaTests.aidl
+++ b/tests/android/aidl/tests/ICppJavaTests.aidl
@@ -16,16 +16,18 @@
 
 package android.aidl.tests;
 
+import android.aidl.tests.BadParcelable;
 import android.aidl.tests.GenericStructuredParcelable;
 import android.aidl.tests.IntEnum;
 import android.aidl.tests.SimpleParcelable;
 import android.aidl.tests.StructuredParcelable;
 import android.aidl.tests.Union;
-import android.aidl.tests.extension.ExtendableParcelable;
 import android.os.PersistableBundle;
 
 // Tests that are only supported by the C++/Java backends, not NDK/Rust
 interface ICppJavaTests {
+    BadParcelable RepeatBadParcelable(in BadParcelable input);
+
     SimpleParcelable RepeatSimpleParcelable(in SimpleParcelable input, out SimpleParcelable repeat);
     GenericStructuredParcelable<int, StructuredParcelable, IntEnum> RepeatGenericParcelable(
             in GenericStructuredParcelable<int, StructuredParcelable, IntEnum> input,
@@ -43,9 +45,4 @@
     FileDescriptor RepeatFileDescriptor(in FileDescriptor read);
     FileDescriptor[] ReverseFileDescriptorArray(
             in FileDescriptor[] input, out FileDescriptor[] repeated);
-
-    void TakesAnIBinderList(in List<IBinder> input);
-    void TakesANullableIBinderList(in @nullable List<IBinder> input);
-
-    void RepeatExtendableParcelable(in ExtendableParcelable ep, out ExtendableParcelable ep2);
 }
diff --git a/tests/android/aidl/tests/ITestService.aidl b/tests/android/aidl/tests/ITestService.aidl
index 1914a4c..f8e168a 100644
--- a/tests/android/aidl/tests/ITestService.aidl
+++ b/tests/android/aidl/tests/ITestService.aidl
@@ -23,12 +23,30 @@
 import android.aidl.tests.IOldName;
 import android.aidl.tests.IntEnum;
 import android.aidl.tests.LongEnum;
+import android.aidl.tests.RecursiveList;
 import android.aidl.tests.StructuredParcelable;
+import android.aidl.tests.extension.ExtendableParcelable;
 
+/**
+ * interface comment
+ */
 @SuppressWarnings(value={"inout-parameter", "mixed-oneway", "out-array"})
 @SensitiveData
+@JavaDefault
+@JavaDelegator
 interface ITestService {
     // Test that constants are accessible
+
+    /**
+     * extra doc comment
+     */
+    // extra line comment
+    /*
+     * extra regular comment
+     */
+    /**
+     * const comment
+     */
     const int TEST_CONSTANT = 42;
     const int TEST_CONSTANT2 = -42;
     const int TEST_CONSTANT3 = +42;
@@ -98,8 +116,18 @@
     LongEnum[] ReverseLongEnum(in LongEnum[] input, out LongEnum[] repeated);
 
     // Test that clients can send and receive Binders.
-    INamedCallback GetOtherTestService(String name);
+    @PropagateAllowBlocking INamedCallback GetOtherTestService(String name);
     boolean VerifyName(INamedCallback service, String name);
+    INamedCallback[] GetInterfaceArray(in String[] names);
+    boolean VerifyNamesWithInterfaceArray(in INamedCallback[] services, in String[] names);
+    @nullable INamedCallback[] GetNullableInterfaceArray(
+            in @nullable String[] names);
+    boolean VerifyNamesWithNullableInterfaceArray(
+            in @nullable INamedCallback[] services, in @nullable String[] names);
+
+    @nullable List<INamedCallback> GetInterfaceList(in @nullable String[] names);
+    boolean VerifyNamesWithInterfaceList(in @nullable List<INamedCallback> services,
+            in @nullable String[] names);
 
     // Test that List<T> types work correctly.
     List<String> ReverseStringList(in List<String> input, out List<String> repeated);
@@ -119,11 +147,20 @@
     @nullable String RepeatNullableString(in @nullable String input);
     @nullable List<String> RepeatNullableStringList(
             in @nullable List<String> input);
-    @nullable StructuredParcelable RepeatNullableParcelable(
-            in @nullable StructuredParcelable input);
+
+    // Small empty parcelable for nullability check
+    @JavaDerive(equals=true)
+    @RustDerive(Clone=true, PartialEq=true)
+    parcelable Empty {}
+    @nullable Empty RepeatNullableParcelable(in @nullable Empty input);
+    @nullable Empty[] RepeatNullableParcelableArray(in @nullable Empty[] input);
+    @nullable List<Empty> RepeatNullableParcelableList(
+            in @nullable List<Empty> input);
 
     void TakesAnIBinder(in IBinder input);
     void TakesANullableIBinder(in @nullable IBinder input);
+    void TakesAnIBinderList(in List<IBinder> input);
+    void TakesANullableIBinderList(in @nullable List<IBinder> input);
 
     // Test utf8 decoding from utf16 wire format
     @utf8InCpp String RepeatUtf8CppString(@utf8InCpp String token);
@@ -143,12 +180,23 @@
             in @nullable @utf8InCpp List<String> input,
             out @nullable @utf8InCpp List<String> repeated);
 
+    /**
+     * comment before annotation
+     */
     @nullable INamedCallback GetCallback(boolean return_null);
 
     // Since this paracelable has clearly defined default values, it would be
     // inefficient to use an IPC to fill it out in practice.
     void FillOutStructuredParcelable(inout StructuredParcelable parcel);
 
+    void RepeatExtendableParcelable(in ExtendableParcelable ep, out ExtendableParcelable ep2);
+
+    RecursiveList ReverseList(in RecursiveList list);
+
+    IBinder[] ReverseIBinderArray(in IBinder[] input, out IBinder[] repeated);
+    @nullable IBinder[] ReverseNullableIBinderArray(
+            in @nullable IBinder[] input, out @nullable IBinder[] repeated);
+
     // All these constant expressions should be equal to 1
     const int A1 = (~(-1)) == 0;
     const int A2 = ~~(1 << 31) == (1 << 31);
@@ -215,4 +263,30 @@
     @nullable IBinder GetCppJavaTests();
 
     BackendType getBackendType();
+
+    parcelable CompilerChecks {
+        // IBinder
+        IBinder binder;
+        @nullable IBinder nullable_binder;
+        IBinder[] binder_array;
+        @nullable IBinder[] nullable_binder_array;
+        List<IBinder> binder_list;
+        @nullable List<IBinder> nullable_binder_list;
+
+        // ParcelFileDescriptor
+        ParcelFileDescriptor pfd;
+        @nullable ParcelFileDescriptor nullable_pfd;
+        ParcelFileDescriptor[] pfd_array;
+        @nullable ParcelFileDescriptor[] nullable_pfd_array;
+        List<ParcelFileDescriptor> pfd_list;
+        @nullable List<ParcelFileDescriptor> nullable_pfd_list;
+
+        // parcelable
+        Empty parcel;
+        @nullable Empty nullable_parcel;
+        Empty[] parcel_array;
+        @nullable Empty[] nullable_parcel_array;
+        List<Empty> parcel_list;
+        @nullable List<Empty> nullable_parcel_list;
+    }
 }
diff --git a/tests/android/aidl/tests/ListOfInterfaces.aidl b/tests/android/aidl/tests/ListOfInterfaces.aidl
new file mode 100644
index 0000000..07ba2ac
--- /dev/null
+++ b/tests/android/aidl/tests/ListOfInterfaces.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-nullable"})
+parcelable ListOfInterfaces {
+    interface IEmptyInterface {}
+
+    interface IMyInterface {
+        @nullable List<IEmptyInterface> methodWithInterfaces(IEmptyInterface iface,
+                @nullable IEmptyInterface nullable_iface,
+                in List<IEmptyInterface> iface_list_in, out List<IEmptyInterface> iface_list_out,
+                inout List<IEmptyInterface> iface_list_inout,
+                in @nullable List<IEmptyInterface> nullable_iface_list_in,
+                out @nullable List<IEmptyInterface> nullable_iface_list_out,
+                inout @nullable List<IEmptyInterface> nullable_iface_list_inout);
+    }
+
+    @JavaDerive(toString=true, equals=true)
+    parcelable MyParcelable {
+        IEmptyInterface iface;
+        @nullable IEmptyInterface nullable_iface;
+        List<IEmptyInterface> iface_list;
+        @nullable List<IEmptyInterface> nullable_iface_list;
+    }
+
+    @JavaDerive(toString=true, equals=true)
+    union MyUnion {
+        IEmptyInterface iface;
+        @nullable IEmptyInterface nullable_iface;
+        List<IEmptyInterface> iface_list;
+        @nullable List<IEmptyInterface> nullable_iface_list;
+    }
+}
diff --git a/tests/android/aidl/tests/RecursiveList.aidl b/tests/android/aidl/tests/RecursiveList.aidl
new file mode 100644
index 0000000..7af10d3
--- /dev/null
+++ b/tests/android/aidl/tests/RecursiveList.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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;
+
+parcelable RecursiveList {
+    int value;
+    @nullable(heap=true) RecursiveList next;
+}
diff --git a/tests/android/aidl/tests/StructuredParcelable.aidl b/tests/android/aidl/tests/StructuredParcelable.aidl
index df66cd3..41fcdfb 100644
--- a/tests/android/aidl/tests/StructuredParcelable.aidl
+++ b/tests/android/aidl/tests/StructuredParcelable.aidl
@@ -71,7 +71,22 @@
 
     @nullable IBinder ibinder;
 
+    // Make sure we can send an empty parcelable
+    @JavaDerive(toString=true, equals=true)
+    @RustDerive(Clone=true, PartialEq=true)
+    parcelable Empty {}
+
+    Empty empty;
+
     // Constant expressions that evaluate to 1
+    byte[] int8_1 = {
+            1,
+            0xffu8 + 1 == 0,
+            255u8 + 1 == 0,
+            0x80u8 == -128,
+            // u8 type is reinterpreted as a signed type
+            0x80u8 / 2 == -0x40u8,
+    };
     int[] int32_1 = {
             (~(-1)) == 0,
             ~~(1 << 31) == (1 << 31),
diff --git a/tests/android/aidl/tests/map/IMapTest.aidl b/tests/android/aidl/tests/map/IMapTest.aidl
new file mode 100644
index 0000000..f1188db
--- /dev/null
+++ b/tests/android/aidl/tests/map/IMapTest.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.map;
+
+import android.aidl.tests.map.Bar;
+import android.aidl.tests.map.IEmpty;
+import android.aidl.tests.map.IntEnum;
+
+interface IMapTest {
+    Map<String, IntEnum[]> repeatIntEnumArrayMap(
+            in Map<String, IntEnum[]> input, out Map<String, IntEnum[]> output);
+    Map<String, int[]> repeatIntArrayMap(
+            in Map<String, int[]> input, out Map<String, int[]> output);
+    Map<String, Bar> repeatBarMap(in Map<String, Bar> input, out Map<String, Bar> output);
+    Map<String, Bar[]> repeatBarArrayMap(
+            in Map<String, Bar[]> input, out Map<String, Bar[]> output);
+    Map<String, String> repeatStringMap(
+            in Map<String, String> input, out Map<String, String> output);
+    Map<String, String[]> repeatStringArrayMap(
+            in Map<String, String[]> input, out Map<String, String[]> output);
+    Map<String, IEmpty> repeatInterfaceMap(
+            in Map<String, IEmpty> input, out Map<String, IEmpty> output);
+    Map<String, IBinder> repeatIbinderMap(
+            in Map<String, IBinder> input, out Map<String, IBinder> output);
+}
diff --git a/tests/android/aidl/tests/nested/DeeplyNested.aidl b/tests/android/aidl/tests/nested/DeeplyNested.aidl
new file mode 100644
index 0000000..ff6dc38
--- /dev/null
+++ b/tests/android/aidl/tests/nested/DeeplyNested.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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.nested;
+
+parcelable DeeplyNested {
+    parcelable A {
+        // Can reference deeply nested type of a sibling type.
+        B.C.D.E e = B.C.D.E.OK;
+    }
+    parcelable B {
+        parcelable C {
+            parcelable D {
+                enum E { OK }
+            }
+        }
+    }
+}
diff --git a/tests/android/aidl/tests/nested/INestedService.aidl b/tests/android/aidl/tests/nested/INestedService.aidl
new file mode 100644
index 0000000..d23f5be
--- /dev/null
+++ b/tests/android/aidl/tests/nested/INestedService.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.nested;
+
+import android.aidl.tests.nested.ParcelableWithNested;
+
+interface INestedService {
+    @RustDerive(PartialEq=true)
+    parcelable Result {
+        ParcelableWithNested.Status status = ParcelableWithNested.Status.OK;
+    }
+
+    Result flipStatus(in ParcelableWithNested p);
+
+    interface ICallback {
+        void done(ParcelableWithNested.Status status);
+    }
+    void flipStatusWithCallback(ParcelableWithNested.Status status, ICallback cb);
+}
diff --git a/tests/android/aidl/tests/nested/ParcelableWithNested.aidl b/tests/android/aidl/tests/nested/ParcelableWithNested.aidl
new file mode 100644
index 0000000..fbcfa2c
--- /dev/null
+++ b/tests/android/aidl/tests/nested/ParcelableWithNested.aidl
@@ -0,0 +1,22 @@
+/*
+ * 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.nested;
+
+parcelable ParcelableWithNested {
+    enum Status { OK, NOT_OK }
+    Status status = Status.OK;
+}
diff --git a/tests/android/aidl/tests/permission/IProtected.aidl b/tests/android/aidl/tests/permission/IProtected.aidl
new file mode 100644
index 0000000..6b46e9d
--- /dev/null
+++ b/tests/android/aidl/tests/permission/IProtected.aidl
@@ -0,0 +1,9 @@
+package android.aidl.tests.permission;
+
+interface IProtected {
+    @EnforcePermission("READ_PHONE_STATE") void PermissionProtected();
+
+    @EnforcePermission(allOf={"INTERNET", "VIBRATE"}) void MultiplePermissionsAll();
+
+    @EnforcePermission(anyOf={"INTERNET", "VIBRATE"}) void MultiplePermissionsAny();
+}
diff --git a/tests/android/aidl/tests/permission/IProtectedInterface.aidl b/tests/android/aidl/tests/permission/IProtectedInterface.aidl
new file mode 100644
index 0000000..9316642
--- /dev/null
+++ b/tests/android/aidl/tests/permission/IProtectedInterface.aidl
@@ -0,0 +1,8 @@
+package android.aidl.tests.permission;
+
+@EnforcePermission("ACCESS_FINE_LOCATION")
+interface IProtectedInterface {
+    void Method1();
+
+    @EnforcePermission("INTERNET") void Method2();
+}
diff --git a/tests/android/aidl/tests/permission/platform/IProtected.aidl b/tests/android/aidl/tests/permission/platform/IProtected.aidl
new file mode 100644
index 0000000..d4670a6
--- /dev/null
+++ b/tests/android/aidl/tests/permission/platform/IProtected.aidl
@@ -0,0 +1,8 @@
+package android.aidl.tests.permission.platform;
+
+import android.content.AttributionSource;
+
+interface IProtected {
+    @EnforcePermission(allOf={"INTERNET", "VIBRATE"})
+    void ProtectedWithSourceAttribution(in AttributionSource source);
+}
diff --git a/tests/bad_parcelable.cpp b/tests/bad_parcelable.cpp
new file mode 100644
index 0000000..36ca727
--- /dev/null
+++ b/tests/bad_parcelable.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#include "tests/bad_parcelable.h"
+
+#include <android-base/stringprintf.h>
+#include <binder/Parcel.h>
+#include <utils/String8.h>
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace aidl {
+namespace tests {
+
+BadParcelable::BadParcelable(bool bad, const std::string& name, int32_t number)
+    : bad_(bad), name_(name.c_str(), name.length()), number_(number) {}
+
+status_t BadParcelable::writeToParcel(Parcel* parcel) const {
+  if (auto status = parcel->writeBool(bad_); status != OK) return status;
+  if (auto status = parcel->writeString16(name_); status != OK) return status;
+  if (auto status = parcel->writeInt32(number_); status != OK) return status;
+  // BAD! write superfluous data
+  if (bad_) parcel->writeInt32(42);
+  return OK;
+}
+
+status_t BadParcelable::readFromParcel(const Parcel* parcel) {
+  if (auto status = parcel->readBool(&bad_); status != OK) return status;
+  if (auto status = parcel->readString16(&name_); status != OK) return status;
+  if (auto status = parcel->readInt32(&number_); status != OK) return status;
+  return OK;
+}
+
+std::string BadParcelable::toString() const {
+  return StringPrintf("BadParcelable{bad=%d,name=%s,number=%d}", bad_, String8(name_).string(),
+                      number_);
+}
+
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/bad_parcelable.h b/tests/bad_parcelable.h
new file mode 100644
index 0000000..3dcc9bf
--- /dev/null
+++ b/tests/bad_parcelable.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+
+#include <binder/Parcelable.h>
+#include <utils/Errors.h>
+#include <utils/String16.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+
+class BadParcelable : public Parcelable {
+ public:
+  BadParcelable() = default;
+  BadParcelable(bool bad, const std::string& name, int32_t number);
+  virtual ~BadParcelable() = default;
+
+  status_t writeToParcel(Parcel* parcel) const override;
+  status_t readFromParcel(const Parcel* parcel) override;
+
+  std::string toString() const;
+
+  friend bool operator==(const BadParcelable& lhs, const BadParcelable& rhs) {
+    return (lhs.bad_ == rhs.bad_) && (lhs.name_ == rhs.name_) && (lhs.number_ == rhs.number_);
+  }
+  friend bool operator!=(const BadParcelable& lhs, const BadParcelable& rhs) {
+    return !(lhs == rhs);
+  }
+
+ private:
+  bool bad_;
+  String16 name_;
+  int32_t number_ = 0;
+};  // class BadParcelable
+
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/corpus/char_seq_leak b/tests/corpus/char_seq_leak
deleted file mode 100644
index 688d6d8..0000000
--- a/tests/corpus/char_seq_leak
+++ /dev/null
@@ -1 +0,0 @@
-1enum F{U}parcelable e{CharSequence e;}
diff --git a/tests/corpus/const_overflow b/tests/corpus/const_overflow
deleted file mode 100644
index 065a432..0000000
--- a/tests/corpus/const_overflow
+++ /dev/null
@@ -1 +0,0 @@
-–enum o{p=- s,zp=- false ,s,U,U,s,s,sU,s,T,teS,s,U,U,byt,U,U,s,s,sU,s,U,teS,s,U,U,byt,s}
\ No newline at end of file
diff --git a/tests/corpus/const_value_binary_exp b/tests/corpus/const_value_binary_exp
deleted file mode 100644
index d55f8d1..0000000
--- a/tests/corpus/const_value_binary_exp
+++ /dev/null
@@ -1 +0,0 @@
-¬interface a{const int O=4591016363&7;}enum F{p}
\ No newline at end of file
diff --git a/tests/corpus/double_include b/tests/corpus/double_include
deleted file mode 100644
index e2e4a3d..0000000
--- a/tests/corpus/double_include
+++ /dev/null
@@ -1 +0,0 @@
-;import d;import d;
\ No newline at end of file
diff --git a/tests/corpus/duplicated_imports b/tests/corpus/duplicated_imports
deleted file mode 100644
index e4073a7..0000000
--- a/tests/corpus/duplicated_imports
+++ /dev/null
@@ -1 +0,0 @@
-;import d;import d;
diff --git a/tests/corpus/enum_invalid_unary b/tests/corpus/enum_invalid_unary
deleted file mode 100644
index c52f567..0000000
--- a/tests/corpus/enum_invalid_unary
+++ /dev/null
@@ -1 +0,0 @@
-ÿenum o{r=+""}
\ No newline at end of file
diff --git a/tests/corpus/enum_named_byte b/tests/corpus/enum_named_byte
deleted file mode 100644
index 3cf3ad6..0000000
--- a/tests/corpus/enum_named_byte
+++ /dev/null
@@ -1 +0,0 @@
-= import s;enum byte{p}enum s{p} enum oz{p2}parcelable e{e oy;oz y;} 
\ No newline at end of file
diff --git a/tests/corpus/enum_string b/tests/corpus/enum_string
deleted file mode 100644
index 645e109..0000000
--- a/tests/corpus/enum_string
+++ /dev/null
@@ -1 +0,0 @@
- enum o{p="§"}
\ No newline at end of file
diff --git a/tests/corpus/example_cpp b/tests/corpus/example_cpp
new file mode 100644
index 0000000..2865db1
--- /dev/null
+++ b/tests/corpus/example_cpp
@@ -0,0 +1 @@
+aidl\ --lang=cpp\ tests/IFoo.aidl\ --out\ .\ --header_out\ .\ tests/IFoo.aidl\ interface IFoo { const int a = 3 + 3; void doFoo(); }
\ No newline at end of file
diff --git a/tests/corpus/example_enforce b/tests/corpus/example_enforce
new file mode 100644
index 0000000..73b5587
--- /dev/null
+++ b/tests/corpus/example_enforce
@@ -0,0 +1 @@
+aidl\ --lang=java\ tests/IFoo.aidl\ --out\ .\ --header_out\ .\ tests/IFoo.aidl\ interface IFoo {  @Enforce("permission = ABC || permission=DEF") void doFoo(); }
diff --git a/tests/corpus/example_java b/tests/corpus/example_java
new file mode 100644
index 0000000..188f6c1
--- /dev/null
+++ b/tests/corpus/example_java
@@ -0,0 +1 @@
+aidl\ --lang=java\ tests/IFoo.aidl\ --out\ .\ --header_out\ .\ tests/IFoo.aidl\ interface IFoo { const int a = 3 + 3; void doFoo(); }
\ No newline at end of file
diff --git a/tests/corpus/example_ndk b/tests/corpus/example_ndk
new file mode 100644
index 0000000..5f48c23
--- /dev/null
+++ b/tests/corpus/example_ndk
@@ -0,0 +1 @@
+aidl\ --lang=ndk\ tests/IFoo.aidl\ --out\ .\ --header_out\ .\ tests/IFoo.aidl\ interface IFoo { const int a = 3 + 3; void doFoo(); }
\ No newline at end of file
diff --git a/tests/corpus/example_rust b/tests/corpus/example_rust
new file mode 100644
index 0000000..c792b89
--- /dev/null
+++ b/tests/corpus/example_rust
@@ -0,0 +1 @@
+aidl\ --lang=rust\ tests/IFoo.aidl\ --out\ .\ --header_out\ .\ tests/IFoo.aidl\ interface IFoo { const int a = 3 + 3; void doFoo(); }
\ No newline at end of file
diff --git a/tests/corpus/fails_only_in_java b/tests/corpus/fails_only_in_java
deleted file mode 100644
index 640a650..0000000
--- a/tests/corpus/fails_only_in_java
+++ /dev/null
@@ -1 +0,0 @@
-&enum l{p}parcelable e{Map y0;} 
\ No newline at end of file
diff --git a/tests/corpus/ibinder_array b/tests/corpus/ibinder_array
deleted file mode 100644
index 853e41a..0000000
--- a/tests/corpus/ibinder_array
+++ /dev/null
@@ -1 +0,0 @@
- enum F{p}parcelable e{IBinder[]y;}
diff --git a/tests/corpus/invalid_binary_op_types b/tests/corpus/invalid_binary_op_types
deleted file mode 100644
index c9fb817..0000000
--- a/tests/corpus/invalid_binary_op_types
+++ /dev/null
@@ -1 +0,0 @@
-&enum l{p}parcelable e{Map y=.0&0;}
\ No newline at end of file
diff --git a/tests/corpus/invalid_type_after_valid_type b/tests/corpus/invalid_type_after_valid_type
deleted file mode 100644
index 6909cfc..0000000
--- a/tests/corpus/invalid_type_after_valid_type
+++ /dev/null
@@ -1 +0,0 @@
- parcelable m{}t
diff --git a/tests/corpus/java_map b/tests/corpus/java_map
new file mode 100644
index 0000000..b335b8c
--- /dev/null
+++ b/tests/corpus/java_map
@@ -0,0 +1 @@
+aidl\ --lang=java\ tests/IFoo.aidl\ --out\ .\ --header_out\ .\ tests/IFoo.aidl\ interface IFoo { boolean getFds(out Map<String,FileDescriptor> fds); }
\ No newline at end of file
diff --git a/tests/corpus/large_shift_overflow b/tests/corpus/large_shift_overflow
deleted file mode 100644
index baa4ffb..0000000
--- a/tests/corpus/large_shift_overflow
+++ /dev/null
@@ -1 +0,0 @@
-  enum l{p}parcelable e{Map y=36<<-3922331256<<2237203310;}
diff --git a/tests/corpus/map_leak b/tests/corpus/map_leak
deleted file mode 100644
index 11cc670..0000000
--- a/tests/corpus/map_leak
+++ /dev/null
@@ -1 +0,0 @@
-qparcelable a{Map e;}enum n{p}
diff --git a/tests/corpus/ndk_file_descriptor b/tests/corpus/ndk_file_descriptor
deleted file mode 100644
index 3769da0..0000000
--- a/tests/corpus/ndk_file_descriptor
+++ /dev/null
@@ -1 +0,0 @@
-&enum F{p}parcelable e{FileDescriptor e;}
\ No newline at end of file
diff --git a/tests/corpus/negative_left_shift b/tests/corpus/negative_left_shift
deleted file mode 100644
index f7de8b3..0000000
--- a/tests/corpus/negative_left_shift
+++ /dev/null
@@ -1 +0,0 @@
-/ enum o {p=127L>>-1>>2>30>-81>>0>4>26L>>-1>-2>>1-8>1-30>>1>>-7L>>-1>>-2>>0>>-2>>1-8>>-30>>-2>>1-80>>-7>>6L>>-1>>0>4>26L>>-1>-2>>1-8>>-3>>-30>>-2>>2>>1>>1-8>>-30>>-2>>1-80>>-7>>6L>>-1>>0>4>2L>>-1>-2>>1-8>>-3>>-30>>-2>>2>>42>>1>>1-8>>-30>>-2>>1-80>>-7>>6L>>-17>>6L>>-1>>-1>>0>4>26L>>-1>-2>>1-8>>-30>>1>>-7L>>-1>>-2>>0>>-2>>1-8>>-30>>-2>>1-80>>-7>>6L>>-1>>0>4>26L>>-1>-2>>1-8>>-3>>-30>>-2>>2>>1>>1-8>>-30>>-2>>1-80>>-7>>6L>>-1>>0>4>2L>>-1>-2>>1-8>>-3>>-30>>-2>>2>>1-80>>-7>>6L>>-1>>0>4>26L>>-1>-2>>1-8>>-3>>-31>>0>4>26L>>-1>-80>>-7>>6L>>-1>>0>4>26L>>-1>-2>>1-3>>-3>>-30>>-2>>1-80>>-1-80>>-7>>6L>>-1>>0>4>26L>>-1>-2>>1}
\ No newline at end of file
diff --git a/tests/corpus/nongeneric_list b/tests/corpus/nongeneric_list
deleted file mode 100644
index 96e9e97..0000000
--- a/tests/corpus/nongeneric_list
+++ /dev/null
@@ -1 +0,0 @@
-²enum F{t}parcelable e{List e;}
\ No newline at end of file
diff --git a/tests/corpus/nullable_parcelable_array b/tests/corpus/nullable_parcelable_array
deleted file mode 100644
index 65cb0af..0000000
--- a/tests/corpus/nullable_parcelable_array
+++ /dev/null
@@ -1 +0,0 @@
-)enum r{r}parcelable e{@nullable e[]e;}
\ No newline at end of file
diff --git a/tests/corpus/nullable_pfd_array b/tests/corpus/nullable_pfd_array
deleted file mode 100644
index a18ddd1..0000000
--- a/tests/corpus/nullable_pfd_array
+++ /dev/null
@@ -1 +0,0 @@
- enum F{p}parcelable e{@nullable ParcelFileDescriptor[]y;}
\ No newline at end of file
diff --git a/tests/corpus/other_string_operation b/tests/corpus/other_string_operation
deleted file mode 100644
index b04fcc2..0000000
--- a/tests/corpus/other_string_operation
+++ /dev/null
Binary files differ
diff --git a/tests/corpus/parcelable_holder_array b/tests/corpus/parcelable_holder_array
deleted file mode 100644
index 412866f..0000000
--- a/tests/corpus/parcelable_holder_array
+++ /dev/null
@@ -1 +0,0 @@
-Öenum Fo{prp}parcelable e{ ParcelableHolder []o;}
\ No newline at end of file
diff --git a/tests/corpus/shift_left_gt_leading_zeros b/tests/corpus/shift_left_gt_leading_zeros
deleted file mode 100644
index 402cf20..0000000
--- a/tests/corpus/shift_left_gt_leading_zeros
+++ /dev/null
@@ -1 +0,0 @@
- enum o {p=06L>>-2>>-2L>>0-2>>-8-2>>0-21>>0-2>>-8-2>>0-2>>-6>>-9L>>0-2>>-6>>-2L>>0>1}
\ No newline at end of file
diff --git a/tests/corpus/shift_overflow b/tests/corpus/shift_overflow
deleted file mode 100644
index 647a254..0000000
--- a/tests/corpus/shift_overflow
+++ /dev/null
@@ -1 +0,0 @@
-Öenum o{x=4<<92}
\ No newline at end of file
diff --git a/tests/corpus/shift_right_64 b/tests/corpus/shift_right_64
deleted file mode 100644
index 7180d4d..0000000
--- a/tests/corpus/shift_right_64
+++ /dev/null
@@ -1 +0,0 @@
-/ enum o {p=1756L>>-1>>1>>-4>26L>>1>>-4>26>>-1>>1>>-100-1>>1>>-4>26>>-1>>1>>-100>4>>266>>-1>>1>>-1>>1>-2-8>>-2>>-1>>1>>-1>>-7L>>11>>-2>>0>>-28>>-30>>-2>>1-80>>-7>30>>-7<56L>>-1>>1>>-4>24>>-.1>>1>>-100-1>>1>>-4>26>>-1>>1>>-26>>-1>>1>>-4>26>>-1>>1>>-100-1>>1>>-4>26>>-1>>1>>-100>4>>26L>>0>>-2>>0064>26L>>-1}
\ No newline at end of file
diff --git a/tests/corpus/shift_zero_left_32 b/tests/corpus/shift_zero_left_32
deleted file mode 100644
index 4bf12f7..0000000
--- a/tests/corpus/shift_zero_left_32
+++ /dev/null
@@ -1 +0,0 @@
- enum o{p=0>>-32}
\ No newline at end of file
diff --git a/tests/corpus/type_param_leak b/tests/corpus/type_param_leak
deleted file mode 100644
index 36eb684..0000000
--- a/tests/corpus/type_param_leak
+++ /dev/null
@@ -1 +0,0 @@
-;parcelable p<g
\ No newline at end of file
diff --git a/tests/corpus/utf8_non_string b/tests/corpus/utf8_non_string
deleted file mode 100644
index f7a4e3a..0000000
--- a/tests/corpus/utf8_non_string
+++ /dev/null
@@ -1 +0,0 @@
-Uenum o{r}parcelable e{@utf8InCpp byte[]y;}
\ No newline at end of file
diff --git a/tests/fake_io_delegate.cpp b/tests/fake_io_delegate.cpp
index a99a20a..6bd2984 100644
--- a/tests/fake_io_delegate.cpp
+++ b/tests/fake_io_delegate.cpp
@@ -57,16 +57,6 @@
   return contents;
 }
 
-unique_ptr<LineReader> FakeIoDelegate::GetLineReader(
-    const string& file_path) const {
-  unique_ptr<LineReader> ret;
-  const auto& it = file_contents_.find(CleanPath(file_path));
-  if (it != file_contents_.cend()) {
-    ret = LineReader::ReadFromMemory(it->second);
-  }
-  return ret;
-}
-
 bool FakeIoDelegate::FileIsReadable(const string& path) const {
   return file_contents_.find(CleanPath(path)) != file_contents_.end();
 }
@@ -76,15 +66,10 @@
   if (broken_files_.count(file_path) > 0) {
     return unique_ptr<CodeWriter>(new BrokenCodeWriter);
   }
-  removed_files_.erase(file_path);
   written_file_contents_[file_path] = "";
   return CodeWriter::ForString(&written_file_contents_[file_path]);
 }
 
-void FakeIoDelegate::RemovePath(const std::string& file_path) const {
-  removed_files_.insert(file_path);
-}
-
 void FakeIoDelegate::SetFileContents(const string& filename,
                                      const string& contents) {
   file_contents_[filename] = contents;
@@ -160,23 +145,6 @@
   return written_file_contents_;
 }
 
-bool FakeIoDelegate::PathWasRemoved(const std::string& path) {
-  if (removed_files_.count(path) > 0) {
-    return true;
-  }
-  return false;
-}
-
-string FakeIoDelegate::CleanPath(const string& path) const {
-  string clean_path = path;
-  while (clean_path.length() >= 2 &&
-         clean_path[0] == '.' &&
-         clean_path[1] == OS_PATH_SEPARATOR) {
-    clean_path = clean_path.substr(2);
-  }
-  return clean_path;
-}
-
 }  // namespace test
 }  // namespace aidl
 }  // namespace android
diff --git a/tests/fake_io_delegate.h b/tests/fake_io_delegate.h
index 6f24678..81d6f89 100644
--- a/tests/fake_io_delegate.h
+++ b/tests/fake_io_delegate.h
@@ -42,12 +42,9 @@
   std::unique_ptr<std::string> GetFileContents(
       const std::string& filename,
       const std::string& append_content_suffix = "") const override;
-  std::unique_ptr<LineReader> GetLineReader(
-      const std::string& file_path) const override;
   bool FileIsReadable(const std::string& path) const override;
   std::unique_ptr<CodeWriter> GetCodeWriter(
       const std::string& file_path) const override;
-  void RemovePath(const std::string& file_path) const override;
   android::base::Result<std::vector<std::string>> ListFiles(const std::string& dir) const override;
 
   // Methods added to facilitate testing.
@@ -65,12 +62,7 @@
   const std::map<std::string, std::string>& InputFiles() const;
   const std::map<std::string, std::string>& OutputFiles() const;
 
-  bool PathWasRemoved(const std::string& path);
-
  private:
-  // Remove leading "./" from |path|.
-  std::string CleanPath(const std::string& path) const;
-
   std::map<std::string, std::string> file_contents_;
   // Normally, writing to files leaves the IoDelegate unchanged, so
   // GetCodeWriter is a const method.  However, for tests, we break this
@@ -80,7 +72,6 @@
   // We normally just write to strings in |written_file_contents_| but for
   // files in this list, we simulate I/O errors.
   std::set<std::string> broken_files_;
-  mutable std::set<std::string> removed_files_;
 };  // class FakeIoDelegate
 
 }  // namespace test
diff --git a/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp b/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp
new file mode 100644
index 0000000..faa4248
--- /dev/null
+++ b/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp
@@ -0,0 +1,1456 @@
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+::android::status_t FixedSizeArrayExample::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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->readFixedArray(&int2x3);
+  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->readFixedArray(&boolArray);
+  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->readFixedArray(&byteArray);
+  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->readFixedArray(&charArray);
+  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->readFixedArray(&intArray);
+  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->readFixedArray(&longArray);
+  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->readFixedArray(&floatArray);
+  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->readFixedArray(&doubleArray);
+  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->readFixedArray(&stringArray);
+  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->readFixedArray(&byteEnumArray);
+  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->readFixedArray(&intEnumArray);
+  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->readFixedArray(&longEnumArray);
+  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->readFixedArray(&parcelableArray);
+  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->readFixedArray(&boolMatrix);
+  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->readFixedArray(&byteMatrix);
+  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->readFixedArray(&charMatrix);
+  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->readFixedArray(&intMatrix);
+  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->readFixedArray(&longMatrix);
+  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->readFixedArray(&floatMatrix);
+  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->readFixedArray(&doubleMatrix);
+  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->readFixedArray(&stringMatrix);
+  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->readFixedArray(&byteEnumMatrix);
+  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->readFixedArray(&intEnumMatrix);
+  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->readFixedArray(&longEnumMatrix);
+  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->readFixedArray(&parcelableMatrix);
+  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->readFixedArray(&boolNullableArray);
+  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->readFixedArray(&byteNullableArray);
+  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->readFixedArray(&charNullableArray);
+  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->readFixedArray(&intNullableArray);
+  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->readFixedArray(&longNullableArray);
+  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->readFixedArray(&floatNullableArray);
+  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->readFixedArray(&doubleNullableArray);
+  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->readFixedArray(&stringNullableArray);
+  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->readFixedArray(&byteEnumNullableArray);
+  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->readFixedArray(&intEnumNullableArray);
+  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->readFixedArray(&longEnumNullableArray);
+  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->readFixedArray(&binderNullableArray);
+  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->readFixedArray(&pfdNullableArray);
+  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->readFixedArray(&parcelableNullableArray);
+  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->readFixedArray(&interfaceNullableArray);
+  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->readFixedArray(&boolNullableMatrix);
+  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->readFixedArray(&byteNullableMatrix);
+  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->readFixedArray(&charNullableMatrix);
+  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->readFixedArray(&intNullableMatrix);
+  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->readFixedArray(&longNullableMatrix);
+  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->readFixedArray(&floatNullableMatrix);
+  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->readFixedArray(&doubleNullableMatrix);
+  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->readFixedArray(&stringNullableMatrix);
+  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->readFixedArray(&byteEnumNullableMatrix);
+  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->readFixedArray(&intEnumNullableMatrix);
+  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->readFixedArray(&longEnumNullableMatrix);
+  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->readFixedArray(&binderNullableMatrix);
+  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->readFixedArray(&pfdNullableMatrix);
+  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->readFixedArray(&parcelableNullableMatrix);
+  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->readFixedArray(&interfaceNullableMatrix);
+  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 FixedSizeArrayExample::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->writeFixedArray(int2x3);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(boolArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(byteArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(charArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(intArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(longArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(floatArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(doubleArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(stringArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(byteEnumArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(intEnumArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(longEnumArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(parcelableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(boolMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(byteMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(charMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(intMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(longMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(floatMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(doubleMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(stringMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(byteEnumMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(intEnumMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(longEnumMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(parcelableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(boolNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(byteNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(charNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(intNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(longNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(floatNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(doubleNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(stringNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(byteEnumNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(intEnumNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(longEnumNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(binderNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(pfdNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(parcelableNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(interfaceNullableArray);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(boolNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(byteNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(charNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(intNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(longNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(floatNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(doubleNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(stringNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(byteEnumNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(intEnumNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(longEnumNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(binderNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(pfdNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(parcelableNullableMatrix);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFixedArray(interfaceNullableMatrix);
+  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 fixedsizearray
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE(FixedSizeArrayExample, RepeatFixedSizeArray, "android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray")
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+#include <binder/Parcel.h>
+#include <android-base/macros.h>
+
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+
+FixedSizeArrayExample::BpRepeatFixedSizeArray::BpRepeatFixedSizeArray(const ::android::sp<::android::IBinder>& _aidl_impl)
+    : BpInterface<IRepeatFixedSizeArray>(_aidl_impl){
+}
+
+::android::binder::Status FixedSizeArrayExample::BpRepeatFixedSizeArray::RepeatBytes(const std::array<uint8_t, 3>& input, std::array<uint8_t, 3>* repeated, std::array<uint8_t, 3>* _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.writeFixedArray(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(FixedSizeArrayExample::BnRepeatFixedSizeArray::TRANSACTION_RepeatBytes, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IRepeatFixedSizeArray::getDefaultImpl())) {
+     return IRepeatFixedSizeArray::getDefaultImpl()->RepeatBytes(input, repeated, _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.readFixedArray(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readFixedArray(repeated);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status FixedSizeArrayExample::BpRepeatFixedSizeArray::RepeatInts(const std::array<int32_t, 3>& input, std::array<int32_t, 3>* repeated, std::array<int32_t, 3>* _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.writeFixedArray(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(FixedSizeArrayExample::BnRepeatFixedSizeArray::TRANSACTION_RepeatInts, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IRepeatFixedSizeArray::getDefaultImpl())) {
+     return IRepeatFixedSizeArray::getDefaultImpl()->RepeatInts(input, repeated, _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.readFixedArray(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readFixedArray(repeated);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status FixedSizeArrayExample::BpRepeatFixedSizeArray::RepeatBinders(const std::array<::android::sp<::android::IBinder>, 3>& input, std::array<::android::sp<::android::IBinder>, 3>* repeated, std::array<::android::sp<::android::IBinder>, 3>* _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.writeFixedArray(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(FixedSizeArrayExample::BnRepeatFixedSizeArray::TRANSACTION_RepeatBinders, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IRepeatFixedSizeArray::getDefaultImpl())) {
+     return IRepeatFixedSizeArray::getDefaultImpl()->RepeatBinders(input, repeated, _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.readFixedArray(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readFixedArray(repeated);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status FixedSizeArrayExample::BpRepeatFixedSizeArray::RepeatParcelables(const std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>& input, std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* repeated, std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* _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.writeFixedArray(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(FixedSizeArrayExample::BnRepeatFixedSizeArray::TRANSACTION_RepeatParcelables, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IRepeatFixedSizeArray::getDefaultImpl())) {
+     return IRepeatFixedSizeArray::getDefaultImpl()->RepeatParcelables(input, repeated, _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.readFixedArray(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readFixedArray(repeated);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status FixedSizeArrayExample::BpRepeatFixedSizeArray::Repeat2dBytes(const std::array<std::array<uint8_t, 3>, 2>& input, std::array<std::array<uint8_t, 3>, 2>* repeated, std::array<std::array<uint8_t, 3>, 2>* _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.writeFixedArray(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(FixedSizeArrayExample::BnRepeatFixedSizeArray::TRANSACTION_Repeat2dBytes, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IRepeatFixedSizeArray::getDefaultImpl())) {
+     return IRepeatFixedSizeArray::getDefaultImpl()->Repeat2dBytes(input, repeated, _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.readFixedArray(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readFixedArray(repeated);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status FixedSizeArrayExample::BpRepeatFixedSizeArray::Repeat2dInts(const std::array<std::array<int32_t, 3>, 2>& input, std::array<std::array<int32_t, 3>, 2>* repeated, std::array<std::array<int32_t, 3>, 2>* _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.writeFixedArray(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(FixedSizeArrayExample::BnRepeatFixedSizeArray::TRANSACTION_Repeat2dInts, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IRepeatFixedSizeArray::getDefaultImpl())) {
+     return IRepeatFixedSizeArray::getDefaultImpl()->Repeat2dInts(input, repeated, _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.readFixedArray(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readFixedArray(repeated);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status FixedSizeArrayExample::BpRepeatFixedSizeArray::Repeat2dBinders(const std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>& input, std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>* repeated, std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>* _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.writeFixedArray(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(FixedSizeArrayExample::BnRepeatFixedSizeArray::TRANSACTION_Repeat2dBinders, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IRepeatFixedSizeArray::getDefaultImpl())) {
+     return IRepeatFixedSizeArray::getDefaultImpl()->Repeat2dBinders(input, repeated, _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.readFixedArray(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readFixedArray(repeated);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status FixedSizeArrayExample::BpRepeatFixedSizeArray::Repeat2dParcelables(const std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>& input, std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* repeated, std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* _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.writeFixedArray(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(FixedSizeArrayExample::BnRepeatFixedSizeArray::TRANSACTION_Repeat2dParcelables, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IRepeatFixedSizeArray::getDefaultImpl())) {
+     return IRepeatFixedSizeArray::getDefaultImpl()->Repeat2dParcelables(input, repeated, _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.readFixedArray(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readFixedArray(repeated);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+
+FixedSizeArrayExample::BnRepeatFixedSizeArray::BnRepeatFixedSizeArray()
+{
+  ::android::internal::Stability::markCompilationUnit(this);
+}
+
+::android::status_t FixedSizeArrayExample::BnRepeatFixedSizeArray::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 BnRepeatFixedSizeArray::TRANSACTION_RepeatBytes:
+  {
+    std::array<uint8_t, 3> in_input;
+    std::array<uint8_t, 3> out_repeated;
+    std::array<uint8_t, 3> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readFixedArray(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(RepeatBytes(in_input, &out_repeated, &_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->writeFixedArray(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeFixedArray(out_repeated);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnRepeatFixedSizeArray::TRANSACTION_RepeatInts:
+  {
+    std::array<int32_t, 3> in_input;
+    std::array<int32_t, 3> out_repeated;
+    std::array<int32_t, 3> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readFixedArray(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(RepeatInts(in_input, &out_repeated, &_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->writeFixedArray(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeFixedArray(out_repeated);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnRepeatFixedSizeArray::TRANSACTION_RepeatBinders:
+  {
+    std::array<::android::sp<::android::IBinder>, 3> in_input;
+    std::array<::android::sp<::android::IBinder>, 3> out_repeated;
+    std::array<::android::sp<::android::IBinder>, 3> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readFixedArray(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(RepeatBinders(in_input, &out_repeated, &_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->writeFixedArray(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeFixedArray(out_repeated);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnRepeatFixedSizeArray::TRANSACTION_RepeatParcelables:
+  {
+    std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3> in_input;
+    std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3> out_repeated;
+    std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readFixedArray(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(RepeatParcelables(in_input, &out_repeated, &_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->writeFixedArray(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeFixedArray(out_repeated);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnRepeatFixedSizeArray::TRANSACTION_Repeat2dBytes:
+  {
+    std::array<std::array<uint8_t, 3>, 2> in_input;
+    std::array<std::array<uint8_t, 3>, 2> out_repeated;
+    std::array<std::array<uint8_t, 3>, 2> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readFixedArray(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(Repeat2dBytes(in_input, &out_repeated, &_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->writeFixedArray(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeFixedArray(out_repeated);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnRepeatFixedSizeArray::TRANSACTION_Repeat2dInts:
+  {
+    std::array<std::array<int32_t, 3>, 2> in_input;
+    std::array<std::array<int32_t, 3>, 2> out_repeated;
+    std::array<std::array<int32_t, 3>, 2> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readFixedArray(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(Repeat2dInts(in_input, &out_repeated, &_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->writeFixedArray(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeFixedArray(out_repeated);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnRepeatFixedSizeArray::TRANSACTION_Repeat2dBinders:
+  {
+    std::array<std::array<::android::sp<::android::IBinder>, 3>, 2> in_input;
+    std::array<std::array<::android::sp<::android::IBinder>, 3>, 2> out_repeated;
+    std::array<std::array<::android::sp<::android::IBinder>, 3>, 2> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readFixedArray(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(Repeat2dBinders(in_input, &out_repeated, &_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->writeFixedArray(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeFixedArray(out_repeated);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnRepeatFixedSizeArray::TRANSACTION_Repeat2dParcelables:
+  {
+    std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2> in_input;
+    std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2> out_repeated;
+    std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readFixedArray(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(Repeat2dParcelables(in_input, &out_repeated, &_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->writeFixedArray(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeFixedArray(out_repeated);
+    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).writeOverParcel(_aidl_reply);
+  }
+  return _aidl_ret_status;
+}
+
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+::android::status_t FixedSizeArrayExample::IntParcelable::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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->readInt32(&value);
+  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 FixedSizeArrayExample::IntParcelable::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->writeInt32(value);
+  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 fixedsizearray
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE(FixedSizeArrayExample, EmptyInterface, "android.aidl.fixedsizearray.FixedSizeArrayExample.IEmptyInterface")
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+#include <binder/Parcel.h>
+#include <android-base/macros.h>
+
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+
+FixedSizeArrayExample::BpEmptyInterface::BpEmptyInterface(const ::android::sp<::android::IBinder>& _aidl_impl)
+    : BpInterface<IEmptyInterface>(_aidl_impl){
+}
+
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+
+FixedSizeArrayExample::BnEmptyInterface::BnEmptyInterface()
+{
+  ::android::internal::Stability::markCompilationUnit(this);
+}
+
+::android::status_t FixedSizeArrayExample::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).writeOverParcel(_aidl_reply);
+  }
+  return _aidl_ret_status;
+}
+
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp.d b/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp.d
new file mode 100644
index 0000000..940e183
--- /dev/null
+++ b/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-fixedsizearray-cpp-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp : \
+  system/tools/aidl/tests/android/aidl/fixedsizearray/FixedSizeArrayExample.aidl
diff --git a/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/include/android/aidl/fixedsizearray/BnFixedSizeArrayExample.h b/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/include/android/aidl/fixedsizearray/BnFixedSizeArrayExample.h
new file mode 100644
index 0000000..ce72aa3
--- /dev/null
+++ b/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/include/android/aidl/fixedsizearray/BnFixedSizeArrayExample.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-fixedsizearray-cpp-source/gen/include/android/aidl/fixedsizearray/BpFixedSizeArrayExample.h b/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/include/android/aidl/fixedsizearray/BpFixedSizeArrayExample.h
new file mode 100644
index 0000000..27af6b1
--- /dev/null
+++ b/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/include/android/aidl/fixedsizearray/BpFixedSizeArrayExample.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-fixedsizearray-cpp-source/gen/include/android/aidl/fixedsizearray/FixedSizeArrayExample.h b/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/include/android/aidl/fixedsizearray/FixedSizeArrayExample.h
new file mode 100644
index 0000000..7460a38
--- /dev/null
+++ b/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/include/android/aidl/fixedsizearray/FixedSizeArrayExample.h
@@ -0,0 +1,418 @@
+#pragma once
+
+#include <android/aidl/fixedsizearray/FixedSizeArrayExample.h>
+#include <android/binder_to_string.h>
+#include <array>
+#include <binder/Enums.h>
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/ParcelFileDescriptor.h>
+#include <binder/Status.h>
+#include <cstdint>
+#include <optional>
+#include <string>
+#include <tuple>
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+class FixedSizeArrayExample : public ::android::Parcelable {
+public:
+  class IntParcelable : public ::android::Parcelable {
+  public:
+    int32_t value = 0;
+    inline bool operator!=(const IntParcelable& rhs) const {
+      return std::tie(value) != std::tie(rhs.value);
+    }
+    inline bool operator<(const IntParcelable& rhs) const {
+      return std::tie(value) < std::tie(rhs.value);
+    }
+    inline bool operator<=(const IntParcelable& rhs) const {
+      return std::tie(value) <= std::tie(rhs.value);
+    }
+    inline bool operator==(const IntParcelable& rhs) const {
+      return std::tie(value) == std::tie(rhs.value);
+    }
+    inline bool operator>(const IntParcelable& rhs) const {
+      return std::tie(value) > std::tie(rhs.value);
+    }
+    inline bool operator>=(const IntParcelable& rhs) const {
+      return std::tie(value) >= std::tie(rhs.value);
+    }
+
+    ::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.fixedsizearray.FixedSizeArrayExample.IntParcelable");
+      return DESCIPTOR;
+    }
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "IntParcelable{";
+      os << "value: " << ::android::internal::ToString(value);
+      os << "}";
+      return os.str();
+    }
+  };  // class IntParcelable
+  class IRepeatFixedSizeArray : public ::android::IInterface {
+  public:
+    DECLARE_META_INTERFACE(RepeatFixedSizeArray)
+    virtual ::android::binder::Status RepeatBytes(const std::array<uint8_t, 3>& input, std::array<uint8_t, 3>* repeated, std::array<uint8_t, 3>* _aidl_return) = 0;
+    virtual ::android::binder::Status RepeatInts(const std::array<int32_t, 3>& input, std::array<int32_t, 3>* repeated, std::array<int32_t, 3>* _aidl_return) = 0;
+    virtual ::android::binder::Status RepeatBinders(const std::array<::android::sp<::android::IBinder>, 3>& input, std::array<::android::sp<::android::IBinder>, 3>* repeated, std::array<::android::sp<::android::IBinder>, 3>* _aidl_return) = 0;
+    virtual ::android::binder::Status RepeatParcelables(const std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>& input, std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* repeated, std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* _aidl_return) = 0;
+    virtual ::android::binder::Status Repeat2dBytes(const std::array<std::array<uint8_t, 3>, 2>& input, std::array<std::array<uint8_t, 3>, 2>* repeated, std::array<std::array<uint8_t, 3>, 2>* _aidl_return) = 0;
+    virtual ::android::binder::Status Repeat2dInts(const std::array<std::array<int32_t, 3>, 2>& input, std::array<std::array<int32_t, 3>, 2>* repeated, std::array<std::array<int32_t, 3>, 2>* _aidl_return) = 0;
+    virtual ::android::binder::Status Repeat2dBinders(const std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>& input, std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>* repeated, std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>* _aidl_return) = 0;
+    virtual ::android::binder::Status Repeat2dParcelables(const std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>& input, std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* repeated, std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* _aidl_return) = 0;
+  };  // class IRepeatFixedSizeArray
+
+  class IRepeatFixedSizeArrayDefault : public IRepeatFixedSizeArray {
+  public:
+    ::android::IBinder* onAsBinder() override {
+      return nullptr;
+    }
+    ::android::binder::Status RepeatBytes(const std::array<uint8_t, 3>& /*input*/, std::array<uint8_t, 3>* /*repeated*/, std::array<uint8_t, 3>* /*_aidl_return*/) override {
+      return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+    ::android::binder::Status RepeatInts(const std::array<int32_t, 3>& /*input*/, std::array<int32_t, 3>* /*repeated*/, std::array<int32_t, 3>* /*_aidl_return*/) override {
+      return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+    ::android::binder::Status RepeatBinders(const std::array<::android::sp<::android::IBinder>, 3>& /*input*/, std::array<::android::sp<::android::IBinder>, 3>* /*repeated*/, std::array<::android::sp<::android::IBinder>, 3>* /*_aidl_return*/) override {
+      return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+    ::android::binder::Status RepeatParcelables(const std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>& /*input*/, std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* /*repeated*/, std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* /*_aidl_return*/) override {
+      return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+    ::android::binder::Status Repeat2dBytes(const std::array<std::array<uint8_t, 3>, 2>& /*input*/, std::array<std::array<uint8_t, 3>, 2>* /*repeated*/, std::array<std::array<uint8_t, 3>, 2>* /*_aidl_return*/) override {
+      return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+    ::android::binder::Status Repeat2dInts(const std::array<std::array<int32_t, 3>, 2>& /*input*/, std::array<std::array<int32_t, 3>, 2>* /*repeated*/, std::array<std::array<int32_t, 3>, 2>* /*_aidl_return*/) override {
+      return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+    ::android::binder::Status Repeat2dBinders(const std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>& /*input*/, std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>* /*repeated*/, std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>* /*_aidl_return*/) override {
+      return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+    ::android::binder::Status Repeat2dParcelables(const std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>& /*input*/, std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* /*repeated*/, std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* /*_aidl_return*/) override {
+      return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+  };  // class IRepeatFixedSizeArrayDefault
+  class BpRepeatFixedSizeArray : public ::android::BpInterface<IRepeatFixedSizeArray> {
+  public:
+    explicit BpRepeatFixedSizeArray(const ::android::sp<::android::IBinder>& _aidl_impl);
+    virtual ~BpRepeatFixedSizeArray() = default;
+    ::android::binder::Status RepeatBytes(const std::array<uint8_t, 3>& input, std::array<uint8_t, 3>* repeated, std::array<uint8_t, 3>* _aidl_return) override;
+    ::android::binder::Status RepeatInts(const std::array<int32_t, 3>& input, std::array<int32_t, 3>* repeated, std::array<int32_t, 3>* _aidl_return) override;
+    ::android::binder::Status RepeatBinders(const std::array<::android::sp<::android::IBinder>, 3>& input, std::array<::android::sp<::android::IBinder>, 3>* repeated, std::array<::android::sp<::android::IBinder>, 3>* _aidl_return) override;
+    ::android::binder::Status RepeatParcelables(const std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>& input, std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* repeated, std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* _aidl_return) override;
+    ::android::binder::Status Repeat2dBytes(const std::array<std::array<uint8_t, 3>, 2>& input, std::array<std::array<uint8_t, 3>, 2>* repeated, std::array<std::array<uint8_t, 3>, 2>* _aidl_return) override;
+    ::android::binder::Status Repeat2dInts(const std::array<std::array<int32_t, 3>, 2>& input, std::array<std::array<int32_t, 3>, 2>* repeated, std::array<std::array<int32_t, 3>, 2>* _aidl_return) override;
+    ::android::binder::Status Repeat2dBinders(const std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>& input, std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>* repeated, std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>* _aidl_return) override;
+    ::android::binder::Status Repeat2dParcelables(const std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>& input, std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* repeated, std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* _aidl_return) override;
+  };  // class BpRepeatFixedSizeArray
+  class BnRepeatFixedSizeArray : public ::android::BnInterface<IRepeatFixedSizeArray> {
+  public:
+    static constexpr uint32_t TRANSACTION_RepeatBytes = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
+    static constexpr uint32_t TRANSACTION_RepeatInts = ::android::IBinder::FIRST_CALL_TRANSACTION + 1;
+    static constexpr uint32_t TRANSACTION_RepeatBinders = ::android::IBinder::FIRST_CALL_TRANSACTION + 2;
+    static constexpr uint32_t TRANSACTION_RepeatParcelables = ::android::IBinder::FIRST_CALL_TRANSACTION + 3;
+    static constexpr uint32_t TRANSACTION_Repeat2dBytes = ::android::IBinder::FIRST_CALL_TRANSACTION + 4;
+    static constexpr uint32_t TRANSACTION_Repeat2dInts = ::android::IBinder::FIRST_CALL_TRANSACTION + 5;
+    static constexpr uint32_t TRANSACTION_Repeat2dBinders = ::android::IBinder::FIRST_CALL_TRANSACTION + 6;
+    static constexpr uint32_t TRANSACTION_Repeat2dParcelables = ::android::IBinder::FIRST_CALL_TRANSACTION + 7;
+    explicit BnRepeatFixedSizeArray();
+    ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
+  };  // class BnRepeatFixedSizeArray
+
+  class IRepeatFixedSizeArrayDelegator : public BnRepeatFixedSizeArray {
+  public:
+    explicit IRepeatFixedSizeArrayDelegator(::android::sp<IRepeatFixedSizeArray> &impl) : _aidl_delegate(impl) {}
+
+    ::android::binder::Status RepeatBytes(const std::array<uint8_t, 3>& input, std::array<uint8_t, 3>* repeated, std::array<uint8_t, 3>* _aidl_return) override {
+      return _aidl_delegate->RepeatBytes(input, repeated, _aidl_return);
+    }
+    ::android::binder::Status RepeatInts(const std::array<int32_t, 3>& input, std::array<int32_t, 3>* repeated, std::array<int32_t, 3>* _aidl_return) override {
+      return _aidl_delegate->RepeatInts(input, repeated, _aidl_return);
+    }
+    ::android::binder::Status RepeatBinders(const std::array<::android::sp<::android::IBinder>, 3>& input, std::array<::android::sp<::android::IBinder>, 3>* repeated, std::array<::android::sp<::android::IBinder>, 3>* _aidl_return) override {
+      return _aidl_delegate->RepeatBinders(input, repeated, _aidl_return);
+    }
+    ::android::binder::Status RepeatParcelables(const std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>& input, std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* repeated, std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* _aidl_return) override {
+      return _aidl_delegate->RepeatParcelables(input, repeated, _aidl_return);
+    }
+    ::android::binder::Status Repeat2dBytes(const std::array<std::array<uint8_t, 3>, 2>& input, std::array<std::array<uint8_t, 3>, 2>* repeated, std::array<std::array<uint8_t, 3>, 2>* _aidl_return) override {
+      return _aidl_delegate->Repeat2dBytes(input, repeated, _aidl_return);
+    }
+    ::android::binder::Status Repeat2dInts(const std::array<std::array<int32_t, 3>, 2>& input, std::array<std::array<int32_t, 3>, 2>* repeated, std::array<std::array<int32_t, 3>, 2>* _aidl_return) override {
+      return _aidl_delegate->Repeat2dInts(input, repeated, _aidl_return);
+    }
+    ::android::binder::Status Repeat2dBinders(const std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>& input, std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>* repeated, std::array<std::array<::android::sp<::android::IBinder>, 3>, 2>* _aidl_return) override {
+      return _aidl_delegate->Repeat2dBinders(input, repeated, _aidl_return);
+    }
+    ::android::binder::Status Repeat2dParcelables(const std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>& input, std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* repeated, std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* _aidl_return) override {
+      return _aidl_delegate->Repeat2dParcelables(input, repeated, _aidl_return);
+    }
+  private:
+    ::android::sp<IRepeatFixedSizeArray> _aidl_delegate;
+  };  // class IRepeatFixedSizeArrayDelegator
+  enum class ByteEnum : int8_t {
+    A = 0,
+  };
+  enum class IntEnum : int32_t {
+    A = 0,
+  };
+  enum class LongEnum : int64_t {
+    A = 0L,
+  };
+  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
+  std::array<std::array<int32_t, 3>, 2> int2x3 = {{{{1, 2, 3}}, {{4, 5, 6}}}};
+  std::array<bool, 2> boolArray = {{}};
+  std::array<uint8_t, 2> byteArray = {{}};
+  std::array<char16_t, 2> charArray = {{}};
+  std::array<int32_t, 2> intArray = {{}};
+  std::array<int64_t, 2> longArray = {{}};
+  std::array<float, 2> floatArray = {{}};
+  std::array<double, 2> doubleArray = {{}};
+  std::array<::std::string, 2> stringArray = {{"hello", "world"}};
+  std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum, 2> byteEnumArray = {{}};
+  std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum, 2> intEnumArray = {{}};
+  std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum, 2> longEnumArray = {{}};
+  std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 2> parcelableArray = {{}};
+  std::array<std::array<bool, 2>, 2> boolMatrix = {{}};
+  std::array<std::array<uint8_t, 2>, 2> byteMatrix = {{}};
+  std::array<std::array<char16_t, 2>, 2> charMatrix = {{}};
+  std::array<std::array<int32_t, 2>, 2> intMatrix = {{}};
+  std::array<std::array<int64_t, 2>, 2> longMatrix = {{}};
+  std::array<std::array<float, 2>, 2> floatMatrix = {{}};
+  std::array<std::array<double, 2>, 2> doubleMatrix = {{}};
+  std::array<std::array<::std::string, 2>, 2> stringMatrix = {{{{"hello", "world"}}, {{"Ciao", "mondo"}}}};
+  std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum, 2>, 2> byteEnumMatrix = {{}};
+  std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum, 2>, 2> intEnumMatrix = {{}};
+  std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum, 2>, 2> longEnumMatrix = {{}};
+  std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 2>, 2> parcelableMatrix = {{}};
+  ::std::optional<std::array<bool, 2>> boolNullableArray;
+  ::std::optional<std::array<uint8_t, 2>> byteNullableArray;
+  ::std::optional<std::array<char16_t, 2>> charNullableArray;
+  ::std::optional<std::array<int32_t, 2>> intNullableArray;
+  ::std::optional<std::array<int64_t, 2>> longNullableArray;
+  ::std::optional<std::array<float, 2>> floatNullableArray;
+  ::std::optional<std::array<double, 2>> doubleNullableArray;
+  ::std::optional<std::array<::std::optional<::std::string>, 2>> stringNullableArray = {{{"hello", "world"}}};
+  ::std::optional<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum, 2>> byteEnumNullableArray;
+  ::std::optional<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum, 2>> intEnumNullableArray;
+  ::std::optional<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum, 2>> longEnumNullableArray;
+  ::std::optional<std::array<::android::sp<::android::IBinder>, 2>> binderNullableArray;
+  ::std::optional<std::array<::std::optional<::android::os::ParcelFileDescriptor>, 2>> pfdNullableArray;
+  ::std::optional<std::array<::std::optional<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable>, 2>> parcelableNullableArray;
+  ::std::optional<std::array<::android::sp<::android::aidl::fixedsizearray::FixedSizeArrayExample::IEmptyInterface>, 2>> interfaceNullableArray;
+  ::std::optional<std::array<std::array<bool, 2>, 2>> boolNullableMatrix;
+  ::std::optional<std::array<std::array<uint8_t, 2>, 2>> byteNullableMatrix;
+  ::std::optional<std::array<std::array<char16_t, 2>, 2>> charNullableMatrix;
+  ::std::optional<std::array<std::array<int32_t, 2>, 2>> intNullableMatrix;
+  ::std::optional<std::array<std::array<int64_t, 2>, 2>> longNullableMatrix;
+  ::std::optional<std::array<std::array<float, 2>, 2>> floatNullableMatrix;
+  ::std::optional<std::array<std::array<double, 2>, 2>> doubleNullableMatrix;
+  ::std::optional<std::array<std::array<::std::optional<::std::string>, 2>, 2>> stringNullableMatrix = {{{{{"hello", "world"}}, {{"Ciao", "mondo"}}}}};
+  ::std::optional<std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum, 2>, 2>> byteEnumNullableMatrix;
+  ::std::optional<std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum, 2>, 2>> intEnumNullableMatrix;
+  ::std::optional<std::array<std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum, 2>, 2>> longEnumNullableMatrix;
+  ::std::optional<std::array<std::array<::android::sp<::android::IBinder>, 2>, 2>> binderNullableMatrix;
+  ::std::optional<std::array<std::array<::std::optional<::android::os::ParcelFileDescriptor>, 2>, 2>> pfdNullableMatrix;
+  ::std::optional<std::array<std::array<::std::optional<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable>, 2>, 2>> parcelableNullableMatrix;
+  ::std::optional<std::array<std::array<::android::sp<::android::aidl::fixedsizearray::FixedSizeArrayExample::IEmptyInterface>, 2>, 2>> interfaceNullableMatrix;
+  inline bool operator!=(const FixedSizeArrayExample& rhs) const {
+    return std::tie(int2x3, boolArray, byteArray, charArray, intArray, longArray, floatArray, doubleArray, stringArray, byteEnumArray, intEnumArray, longEnumArray, parcelableArray, boolMatrix, byteMatrix, charMatrix, intMatrix, longMatrix, floatMatrix, doubleMatrix, stringMatrix, byteEnumMatrix, intEnumMatrix, longEnumMatrix, parcelableMatrix, boolNullableArray, byteNullableArray, charNullableArray, intNullableArray, longNullableArray, floatNullableArray, doubleNullableArray, stringNullableArray, byteEnumNullableArray, intEnumNullableArray, longEnumNullableArray, binderNullableArray, pfdNullableArray, parcelableNullableArray, interfaceNullableArray, boolNullableMatrix, byteNullableMatrix, charNullableMatrix, intNullableMatrix, longNullableMatrix, floatNullableMatrix, doubleNullableMatrix, stringNullableMatrix, byteEnumNullableMatrix, intEnumNullableMatrix, longEnumNullableMatrix, binderNullableMatrix, pfdNullableMatrix, parcelableNullableMatrix, interfaceNullableMatrix) != std::tie(rhs.int2x3, rhs.boolArray, rhs.byteArray, rhs.charArray, rhs.intArray, rhs.longArray, rhs.floatArray, rhs.doubleArray, rhs.stringArray, rhs.byteEnumArray, rhs.intEnumArray, rhs.longEnumArray, rhs.parcelableArray, rhs.boolMatrix, rhs.byteMatrix, rhs.charMatrix, rhs.intMatrix, rhs.longMatrix, rhs.floatMatrix, rhs.doubleMatrix, rhs.stringMatrix, rhs.byteEnumMatrix, rhs.intEnumMatrix, rhs.longEnumMatrix, rhs.parcelableMatrix, rhs.boolNullableArray, rhs.byteNullableArray, rhs.charNullableArray, rhs.intNullableArray, rhs.longNullableArray, rhs.floatNullableArray, rhs.doubleNullableArray, rhs.stringNullableArray, rhs.byteEnumNullableArray, rhs.intEnumNullableArray, rhs.longEnumNullableArray, rhs.binderNullableArray, rhs.pfdNullableArray, rhs.parcelableNullableArray, rhs.interfaceNullableArray, rhs.boolNullableMatrix, rhs.byteNullableMatrix, rhs.charNullableMatrix, rhs.intNullableMatrix, rhs.longNullableMatrix, rhs.floatNullableMatrix, rhs.doubleNullableMatrix, rhs.stringNullableMatrix, rhs.byteEnumNullableMatrix, rhs.intEnumNullableMatrix, rhs.longEnumNullableMatrix, rhs.binderNullableMatrix, rhs.pfdNullableMatrix, rhs.parcelableNullableMatrix, rhs.interfaceNullableMatrix);
+  }
+  inline bool operator<(const FixedSizeArrayExample& rhs) const {
+    return std::tie(int2x3, boolArray, byteArray, charArray, intArray, longArray, floatArray, doubleArray, stringArray, byteEnumArray, intEnumArray, longEnumArray, parcelableArray, boolMatrix, byteMatrix, charMatrix, intMatrix, longMatrix, floatMatrix, doubleMatrix, stringMatrix, byteEnumMatrix, intEnumMatrix, longEnumMatrix, parcelableMatrix, boolNullableArray, byteNullableArray, charNullableArray, intNullableArray, longNullableArray, floatNullableArray, doubleNullableArray, stringNullableArray, byteEnumNullableArray, intEnumNullableArray, longEnumNullableArray, binderNullableArray, pfdNullableArray, parcelableNullableArray, interfaceNullableArray, boolNullableMatrix, byteNullableMatrix, charNullableMatrix, intNullableMatrix, longNullableMatrix, floatNullableMatrix, doubleNullableMatrix, stringNullableMatrix, byteEnumNullableMatrix, intEnumNullableMatrix, longEnumNullableMatrix, binderNullableMatrix, pfdNullableMatrix, parcelableNullableMatrix, interfaceNullableMatrix) < std::tie(rhs.int2x3, rhs.boolArray, rhs.byteArray, rhs.charArray, rhs.intArray, rhs.longArray, rhs.floatArray, rhs.doubleArray, rhs.stringArray, rhs.byteEnumArray, rhs.intEnumArray, rhs.longEnumArray, rhs.parcelableArray, rhs.boolMatrix, rhs.byteMatrix, rhs.charMatrix, rhs.intMatrix, rhs.longMatrix, rhs.floatMatrix, rhs.doubleMatrix, rhs.stringMatrix, rhs.byteEnumMatrix, rhs.intEnumMatrix, rhs.longEnumMatrix, rhs.parcelableMatrix, rhs.boolNullableArray, rhs.byteNullableArray, rhs.charNullableArray, rhs.intNullableArray, rhs.longNullableArray, rhs.floatNullableArray, rhs.doubleNullableArray, rhs.stringNullableArray, rhs.byteEnumNullableArray, rhs.intEnumNullableArray, rhs.longEnumNullableArray, rhs.binderNullableArray, rhs.pfdNullableArray, rhs.parcelableNullableArray, rhs.interfaceNullableArray, rhs.boolNullableMatrix, rhs.byteNullableMatrix, rhs.charNullableMatrix, rhs.intNullableMatrix, rhs.longNullableMatrix, rhs.floatNullableMatrix, rhs.doubleNullableMatrix, rhs.stringNullableMatrix, rhs.byteEnumNullableMatrix, rhs.intEnumNullableMatrix, rhs.longEnumNullableMatrix, rhs.binderNullableMatrix, rhs.pfdNullableMatrix, rhs.parcelableNullableMatrix, rhs.interfaceNullableMatrix);
+  }
+  inline bool operator<=(const FixedSizeArrayExample& rhs) const {
+    return std::tie(int2x3, boolArray, byteArray, charArray, intArray, longArray, floatArray, doubleArray, stringArray, byteEnumArray, intEnumArray, longEnumArray, parcelableArray, boolMatrix, byteMatrix, charMatrix, intMatrix, longMatrix, floatMatrix, doubleMatrix, stringMatrix, byteEnumMatrix, intEnumMatrix, longEnumMatrix, parcelableMatrix, boolNullableArray, byteNullableArray, charNullableArray, intNullableArray, longNullableArray, floatNullableArray, doubleNullableArray, stringNullableArray, byteEnumNullableArray, intEnumNullableArray, longEnumNullableArray, binderNullableArray, pfdNullableArray, parcelableNullableArray, interfaceNullableArray, boolNullableMatrix, byteNullableMatrix, charNullableMatrix, intNullableMatrix, longNullableMatrix, floatNullableMatrix, doubleNullableMatrix, stringNullableMatrix, byteEnumNullableMatrix, intEnumNullableMatrix, longEnumNullableMatrix, binderNullableMatrix, pfdNullableMatrix, parcelableNullableMatrix, interfaceNullableMatrix) <= std::tie(rhs.int2x3, rhs.boolArray, rhs.byteArray, rhs.charArray, rhs.intArray, rhs.longArray, rhs.floatArray, rhs.doubleArray, rhs.stringArray, rhs.byteEnumArray, rhs.intEnumArray, rhs.longEnumArray, rhs.parcelableArray, rhs.boolMatrix, rhs.byteMatrix, rhs.charMatrix, rhs.intMatrix, rhs.longMatrix, rhs.floatMatrix, rhs.doubleMatrix, rhs.stringMatrix, rhs.byteEnumMatrix, rhs.intEnumMatrix, rhs.longEnumMatrix, rhs.parcelableMatrix, rhs.boolNullableArray, rhs.byteNullableArray, rhs.charNullableArray, rhs.intNullableArray, rhs.longNullableArray, rhs.floatNullableArray, rhs.doubleNullableArray, rhs.stringNullableArray, rhs.byteEnumNullableArray, rhs.intEnumNullableArray, rhs.longEnumNullableArray, rhs.binderNullableArray, rhs.pfdNullableArray, rhs.parcelableNullableArray, rhs.interfaceNullableArray, rhs.boolNullableMatrix, rhs.byteNullableMatrix, rhs.charNullableMatrix, rhs.intNullableMatrix, rhs.longNullableMatrix, rhs.floatNullableMatrix, rhs.doubleNullableMatrix, rhs.stringNullableMatrix, rhs.byteEnumNullableMatrix, rhs.intEnumNullableMatrix, rhs.longEnumNullableMatrix, rhs.binderNullableMatrix, rhs.pfdNullableMatrix, rhs.parcelableNullableMatrix, rhs.interfaceNullableMatrix);
+  }
+  inline bool operator==(const FixedSizeArrayExample& rhs) const {
+    return std::tie(int2x3, boolArray, byteArray, charArray, intArray, longArray, floatArray, doubleArray, stringArray, byteEnumArray, intEnumArray, longEnumArray, parcelableArray, boolMatrix, byteMatrix, charMatrix, intMatrix, longMatrix, floatMatrix, doubleMatrix, stringMatrix, byteEnumMatrix, intEnumMatrix, longEnumMatrix, parcelableMatrix, boolNullableArray, byteNullableArray, charNullableArray, intNullableArray, longNullableArray, floatNullableArray, doubleNullableArray, stringNullableArray, byteEnumNullableArray, intEnumNullableArray, longEnumNullableArray, binderNullableArray, pfdNullableArray, parcelableNullableArray, interfaceNullableArray, boolNullableMatrix, byteNullableMatrix, charNullableMatrix, intNullableMatrix, longNullableMatrix, floatNullableMatrix, doubleNullableMatrix, stringNullableMatrix, byteEnumNullableMatrix, intEnumNullableMatrix, longEnumNullableMatrix, binderNullableMatrix, pfdNullableMatrix, parcelableNullableMatrix, interfaceNullableMatrix) == std::tie(rhs.int2x3, rhs.boolArray, rhs.byteArray, rhs.charArray, rhs.intArray, rhs.longArray, rhs.floatArray, rhs.doubleArray, rhs.stringArray, rhs.byteEnumArray, rhs.intEnumArray, rhs.longEnumArray, rhs.parcelableArray, rhs.boolMatrix, rhs.byteMatrix, rhs.charMatrix, rhs.intMatrix, rhs.longMatrix, rhs.floatMatrix, rhs.doubleMatrix, rhs.stringMatrix, rhs.byteEnumMatrix, rhs.intEnumMatrix, rhs.longEnumMatrix, rhs.parcelableMatrix, rhs.boolNullableArray, rhs.byteNullableArray, rhs.charNullableArray, rhs.intNullableArray, rhs.longNullableArray, rhs.floatNullableArray, rhs.doubleNullableArray, rhs.stringNullableArray, rhs.byteEnumNullableArray, rhs.intEnumNullableArray, rhs.longEnumNullableArray, rhs.binderNullableArray, rhs.pfdNullableArray, rhs.parcelableNullableArray, rhs.interfaceNullableArray, rhs.boolNullableMatrix, rhs.byteNullableMatrix, rhs.charNullableMatrix, rhs.intNullableMatrix, rhs.longNullableMatrix, rhs.floatNullableMatrix, rhs.doubleNullableMatrix, rhs.stringNullableMatrix, rhs.byteEnumNullableMatrix, rhs.intEnumNullableMatrix, rhs.longEnumNullableMatrix, rhs.binderNullableMatrix, rhs.pfdNullableMatrix, rhs.parcelableNullableMatrix, rhs.interfaceNullableMatrix);
+  }
+  inline bool operator>(const FixedSizeArrayExample& rhs) const {
+    return std::tie(int2x3, boolArray, byteArray, charArray, intArray, longArray, floatArray, doubleArray, stringArray, byteEnumArray, intEnumArray, longEnumArray, parcelableArray, boolMatrix, byteMatrix, charMatrix, intMatrix, longMatrix, floatMatrix, doubleMatrix, stringMatrix, byteEnumMatrix, intEnumMatrix, longEnumMatrix, parcelableMatrix, boolNullableArray, byteNullableArray, charNullableArray, intNullableArray, longNullableArray, floatNullableArray, doubleNullableArray, stringNullableArray, byteEnumNullableArray, intEnumNullableArray, longEnumNullableArray, binderNullableArray, pfdNullableArray, parcelableNullableArray, interfaceNullableArray, boolNullableMatrix, byteNullableMatrix, charNullableMatrix, intNullableMatrix, longNullableMatrix, floatNullableMatrix, doubleNullableMatrix, stringNullableMatrix, byteEnumNullableMatrix, intEnumNullableMatrix, longEnumNullableMatrix, binderNullableMatrix, pfdNullableMatrix, parcelableNullableMatrix, interfaceNullableMatrix) > std::tie(rhs.int2x3, rhs.boolArray, rhs.byteArray, rhs.charArray, rhs.intArray, rhs.longArray, rhs.floatArray, rhs.doubleArray, rhs.stringArray, rhs.byteEnumArray, rhs.intEnumArray, rhs.longEnumArray, rhs.parcelableArray, rhs.boolMatrix, rhs.byteMatrix, rhs.charMatrix, rhs.intMatrix, rhs.longMatrix, rhs.floatMatrix, rhs.doubleMatrix, rhs.stringMatrix, rhs.byteEnumMatrix, rhs.intEnumMatrix, rhs.longEnumMatrix, rhs.parcelableMatrix, rhs.boolNullableArray, rhs.byteNullableArray, rhs.charNullableArray, rhs.intNullableArray, rhs.longNullableArray, rhs.floatNullableArray, rhs.doubleNullableArray, rhs.stringNullableArray, rhs.byteEnumNullableArray, rhs.intEnumNullableArray, rhs.longEnumNullableArray, rhs.binderNullableArray, rhs.pfdNullableArray, rhs.parcelableNullableArray, rhs.interfaceNullableArray, rhs.boolNullableMatrix, rhs.byteNullableMatrix, rhs.charNullableMatrix, rhs.intNullableMatrix, rhs.longNullableMatrix, rhs.floatNullableMatrix, rhs.doubleNullableMatrix, rhs.stringNullableMatrix, rhs.byteEnumNullableMatrix, rhs.intEnumNullableMatrix, rhs.longEnumNullableMatrix, rhs.binderNullableMatrix, rhs.pfdNullableMatrix, rhs.parcelableNullableMatrix, rhs.interfaceNullableMatrix);
+  }
+  inline bool operator>=(const FixedSizeArrayExample& rhs) const {
+    return std::tie(int2x3, boolArray, byteArray, charArray, intArray, longArray, floatArray, doubleArray, stringArray, byteEnumArray, intEnumArray, longEnumArray, parcelableArray, boolMatrix, byteMatrix, charMatrix, intMatrix, longMatrix, floatMatrix, doubleMatrix, stringMatrix, byteEnumMatrix, intEnumMatrix, longEnumMatrix, parcelableMatrix, boolNullableArray, byteNullableArray, charNullableArray, intNullableArray, longNullableArray, floatNullableArray, doubleNullableArray, stringNullableArray, byteEnumNullableArray, intEnumNullableArray, longEnumNullableArray, binderNullableArray, pfdNullableArray, parcelableNullableArray, interfaceNullableArray, boolNullableMatrix, byteNullableMatrix, charNullableMatrix, intNullableMatrix, longNullableMatrix, floatNullableMatrix, doubleNullableMatrix, stringNullableMatrix, byteEnumNullableMatrix, intEnumNullableMatrix, longEnumNullableMatrix, binderNullableMatrix, pfdNullableMatrix, parcelableNullableMatrix, interfaceNullableMatrix) >= std::tie(rhs.int2x3, rhs.boolArray, rhs.byteArray, rhs.charArray, rhs.intArray, rhs.longArray, rhs.floatArray, rhs.doubleArray, rhs.stringArray, rhs.byteEnumArray, rhs.intEnumArray, rhs.longEnumArray, rhs.parcelableArray, rhs.boolMatrix, rhs.byteMatrix, rhs.charMatrix, rhs.intMatrix, rhs.longMatrix, rhs.floatMatrix, rhs.doubleMatrix, rhs.stringMatrix, rhs.byteEnumMatrix, rhs.intEnumMatrix, rhs.longEnumMatrix, rhs.parcelableMatrix, rhs.boolNullableArray, rhs.byteNullableArray, rhs.charNullableArray, rhs.intNullableArray, rhs.longNullableArray, rhs.floatNullableArray, rhs.doubleNullableArray, rhs.stringNullableArray, rhs.byteEnumNullableArray, rhs.intEnumNullableArray, rhs.longEnumNullableArray, rhs.binderNullableArray, rhs.pfdNullableArray, rhs.parcelableNullableArray, rhs.interfaceNullableArray, rhs.boolNullableMatrix, rhs.byteNullableMatrix, rhs.charNullableMatrix, rhs.intNullableMatrix, rhs.longNullableMatrix, rhs.floatNullableMatrix, rhs.doubleNullableMatrix, rhs.stringNullableMatrix, rhs.byteEnumNullableMatrix, rhs.intEnumNullableMatrix, rhs.longEnumNullableMatrix, rhs.binderNullableMatrix, rhs.pfdNullableMatrix, rhs.parcelableNullableMatrix, rhs.interfaceNullableMatrix);
+  }
+
+  ::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.fixedsizearray.FixedSizeArrayExample");
+    return DESCIPTOR;
+  }
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "FixedSizeArrayExample{";
+    os << "int2x3: " << ::android::internal::ToString(int2x3);
+    os << ", boolArray: " << ::android::internal::ToString(boolArray);
+    os << ", byteArray: " << ::android::internal::ToString(byteArray);
+    os << ", charArray: " << ::android::internal::ToString(charArray);
+    os << ", intArray: " << ::android::internal::ToString(intArray);
+    os << ", longArray: " << ::android::internal::ToString(longArray);
+    os << ", floatArray: " << ::android::internal::ToString(floatArray);
+    os << ", doubleArray: " << ::android::internal::ToString(doubleArray);
+    os << ", stringArray: " << ::android::internal::ToString(stringArray);
+    os << ", byteEnumArray: " << ::android::internal::ToString(byteEnumArray);
+    os << ", intEnumArray: " << ::android::internal::ToString(intEnumArray);
+    os << ", longEnumArray: " << ::android::internal::ToString(longEnumArray);
+    os << ", parcelableArray: " << ::android::internal::ToString(parcelableArray);
+    os << ", boolMatrix: " << ::android::internal::ToString(boolMatrix);
+    os << ", byteMatrix: " << ::android::internal::ToString(byteMatrix);
+    os << ", charMatrix: " << ::android::internal::ToString(charMatrix);
+    os << ", intMatrix: " << ::android::internal::ToString(intMatrix);
+    os << ", longMatrix: " << ::android::internal::ToString(longMatrix);
+    os << ", floatMatrix: " << ::android::internal::ToString(floatMatrix);
+    os << ", doubleMatrix: " << ::android::internal::ToString(doubleMatrix);
+    os << ", stringMatrix: " << ::android::internal::ToString(stringMatrix);
+    os << ", byteEnumMatrix: " << ::android::internal::ToString(byteEnumMatrix);
+    os << ", intEnumMatrix: " << ::android::internal::ToString(intEnumMatrix);
+    os << ", longEnumMatrix: " << ::android::internal::ToString(longEnumMatrix);
+    os << ", parcelableMatrix: " << ::android::internal::ToString(parcelableMatrix);
+    os << ", boolNullableArray: " << ::android::internal::ToString(boolNullableArray);
+    os << ", byteNullableArray: " << ::android::internal::ToString(byteNullableArray);
+    os << ", charNullableArray: " << ::android::internal::ToString(charNullableArray);
+    os << ", intNullableArray: " << ::android::internal::ToString(intNullableArray);
+    os << ", longNullableArray: " << ::android::internal::ToString(longNullableArray);
+    os << ", floatNullableArray: " << ::android::internal::ToString(floatNullableArray);
+    os << ", doubleNullableArray: " << ::android::internal::ToString(doubleNullableArray);
+    os << ", stringNullableArray: " << ::android::internal::ToString(stringNullableArray);
+    os << ", byteEnumNullableArray: " << ::android::internal::ToString(byteEnumNullableArray);
+    os << ", intEnumNullableArray: " << ::android::internal::ToString(intEnumNullableArray);
+    os << ", longEnumNullableArray: " << ::android::internal::ToString(longEnumNullableArray);
+    os << ", binderNullableArray: " << ::android::internal::ToString(binderNullableArray);
+    os << ", pfdNullableArray: " << ::android::internal::ToString(pfdNullableArray);
+    os << ", parcelableNullableArray: " << ::android::internal::ToString(parcelableNullableArray);
+    os << ", interfaceNullableArray: " << ::android::internal::ToString(interfaceNullableArray);
+    os << ", boolNullableMatrix: " << ::android::internal::ToString(boolNullableMatrix);
+    os << ", byteNullableMatrix: " << ::android::internal::ToString(byteNullableMatrix);
+    os << ", charNullableMatrix: " << ::android::internal::ToString(charNullableMatrix);
+    os << ", intNullableMatrix: " << ::android::internal::ToString(intNullableMatrix);
+    os << ", longNullableMatrix: " << ::android::internal::ToString(longNullableMatrix);
+    os << ", floatNullableMatrix: " << ::android::internal::ToString(floatNullableMatrix);
+    os << ", doubleNullableMatrix: " << ::android::internal::ToString(doubleNullableMatrix);
+    os << ", stringNullableMatrix: " << ::android::internal::ToString(stringNullableMatrix);
+    os << ", byteEnumNullableMatrix: " << ::android::internal::ToString(byteEnumNullableMatrix);
+    os << ", intEnumNullableMatrix: " << ::android::internal::ToString(intEnumNullableMatrix);
+    os << ", longEnumNullableMatrix: " << ::android::internal::ToString(longEnumNullableMatrix);
+    os << ", binderNullableMatrix: " << ::android::internal::ToString(binderNullableMatrix);
+    os << ", pfdNullableMatrix: " << ::android::internal::ToString(pfdNullableMatrix);
+    os << ", parcelableNullableMatrix: " << ::android::internal::ToString(parcelableNullableMatrix);
+    os << ", interfaceNullableMatrix: " << ::android::internal::ToString(interfaceNullableMatrix);
+    os << "}";
+    return os.str();
+  }
+};  // class FixedSizeArrayExample
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+[[nodiscard]] static inline std::string toString(FixedSizeArrayExample::ByteEnum val) {
+  switch(val) {
+  case FixedSizeArrayExample::ByteEnum::A:
+    return "A";
+  default:
+    return std::to_string(static_cast<int8_t>(val));
+  }
+}
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace internal {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++17-extensions"
+template <>
+constexpr inline std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum, 1> enum_values<::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum> = {
+  ::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum::A,
+};
+#pragma clang diagnostic pop
+}  // namespace internal
+}  // namespace android
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+[[nodiscard]] static inline std::string toString(FixedSizeArrayExample::IntEnum val) {
+  switch(val) {
+  case FixedSizeArrayExample::IntEnum::A:
+    return "A";
+  default:
+    return std::to_string(static_cast<int32_t>(val));
+  }
+}
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace internal {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++17-extensions"
+template <>
+constexpr inline std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum, 1> enum_values<::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum> = {
+  ::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum::A,
+};
+#pragma clang diagnostic pop
+}  // namespace internal
+}  // namespace android
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+[[nodiscard]] static inline std::string toString(FixedSizeArrayExample::LongEnum val) {
+  switch(val) {
+  case FixedSizeArrayExample::LongEnum::A:
+    return "A";
+  default:
+    return std::to_string(static_cast<int64_t>(val));
+  }
+}
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace internal {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++17-extensions"
+template <>
+constexpr inline std::array<::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum, 1> enum_values<::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum> = {
+  ::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum::A,
+};
+#pragma clang diagnostic pop
+}  // namespace internal
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp b/tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/timestamp
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp
copy to tests/golden_output/aidl-test-fixedsizearray-cpp-source/gen/timestamp
diff --git a/tests/golden_output/aidl-test-fixedsizearray-java-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.java b/tests/golden_output/aidl-test-fixedsizearray-java-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.java
new file mode 100644
index 0000000..f28cc6a
--- /dev/null
+++ b/tests/golden_output/aidl-test-fixedsizearray-java-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.java
@@ -0,0 +1,822 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.fixedsizearray;
+public class FixedSizeArrayExample implements android.os.Parcelable
+{
+  // to see if NxM array works
+  public int[][] int2x3 = {{1, 2, 3}, {4, 5, 6}};
+  public boolean[] boolArray;
+  public byte[] byteArray;
+  public char[] charArray;
+  public int[] intArray;
+  public long[] longArray;
+  public float[] floatArray;
+  public double[] doubleArray;
+  public java.lang.String[] stringArray = {"hello", "world"};
+  public byte[] byteEnumArray;
+  public int[] intEnumArray;
+  public long[] longEnumArray;
+  public android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] parcelableArray;
+  // Following fields are not test-friendly because they should be initialized as non-null.
+  // IBinder[2] binderArray;
+  // ParcelFileDescriptor[2] pfdArray;
+  // IEmptyInterface[2] interfaceArray;
+  public boolean[][] boolMatrix;
+  public byte[][] byteMatrix;
+  public char[][] charMatrix;
+  public int[][] intMatrix;
+  public long[][] longMatrix;
+  public float[][] floatMatrix;
+  public double[][] doubleMatrix;
+  public java.lang.String[][] stringMatrix = {{"hello", "world"}, {"Ciao", "mondo"}};
+  public byte[][] byteEnumMatrix;
+  public int[][] intEnumMatrix;
+  public long[][] longEnumMatrix;
+  public android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] parcelableMatrix;
+  // Following fields are not test-friendly because they should be initialized as non-null.
+  // ParcelFileDescriptor[2][2] pfdMatrix;
+  // IBinder[2][2] binderMatrix;
+  // IEmptyInterface[2][2] interfaceMatrix;
+  public boolean[] boolNullableArray;
+  public byte[] byteNullableArray;
+  public char[] charNullableArray;
+  public int[] intNullableArray;
+  public long[] longNullableArray;
+  public float[] floatNullableArray;
+  public double[] doubleNullableArray;
+  public java.lang.String[] stringNullableArray = {"hello", "world"};
+  public byte[] byteEnumNullableArray;
+  public int[] intEnumNullableArray;
+  public long[] longEnumNullableArray;
+  public android.os.IBinder[] binderNullableArray;
+  public android.os.ParcelFileDescriptor[] pfdNullableArray;
+  public android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] parcelableNullableArray;
+  public android.aidl.fixedsizearray.FixedSizeArrayExample.IEmptyInterface[] interfaceNullableArray;
+  public boolean[][] boolNullableMatrix;
+  public byte[][] byteNullableMatrix;
+  public char[][] charNullableMatrix;
+  public int[][] intNullableMatrix;
+  public long[][] longNullableMatrix;
+  public float[][] floatNullableMatrix;
+  public double[][] doubleNullableMatrix;
+  public java.lang.String[][] stringNullableMatrix = {{"hello", "world"}, {"Ciao", "mondo"}};
+  public byte[][] byteEnumNullableMatrix;
+  public int[][] intEnumNullableMatrix;
+  public long[][] longEnumNullableMatrix;
+  public android.os.IBinder[][] binderNullableMatrix;
+  public android.os.ParcelFileDescriptor[][] pfdNullableMatrix;
+  public android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] parcelableNullableMatrix;
+  public android.aidl.fixedsizearray.FixedSizeArrayExample.IEmptyInterface[][] interfaceNullableMatrix;
+  public static final android.os.Parcelable.Creator<FixedSizeArrayExample> CREATOR = new android.os.Parcelable.Creator<FixedSizeArrayExample>() {
+    @Override
+    public FixedSizeArrayExample createFromParcel(android.os.Parcel _aidl_source) {
+      FixedSizeArrayExample _aidl_out = new FixedSizeArrayExample();
+      _aidl_out.readFromParcel(_aidl_source);
+      return _aidl_out;
+    }
+    @Override
+    public FixedSizeArrayExample[] newArray(int _aidl_size) {
+      return new FixedSizeArrayExample[_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.writeFixedArray(int2x3, 0, 2, 3);
+    _aidl_parcel.writeFixedArray(boolArray, 0, 2);
+    _aidl_parcel.writeFixedArray(byteArray, 0, 2);
+    _aidl_parcel.writeFixedArray(charArray, 0, 2);
+    _aidl_parcel.writeFixedArray(intArray, 0, 2);
+    _aidl_parcel.writeFixedArray(longArray, 0, 2);
+    _aidl_parcel.writeFixedArray(floatArray, 0, 2);
+    _aidl_parcel.writeFixedArray(doubleArray, 0, 2);
+    _aidl_parcel.writeFixedArray(stringArray, 0, 2);
+    _aidl_parcel.writeFixedArray(byteEnumArray, 0, 2);
+    _aidl_parcel.writeFixedArray(intEnumArray, 0, 2);
+    _aidl_parcel.writeFixedArray(longEnumArray, 0, 2);
+    _aidl_parcel.writeFixedArray(parcelableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(boolMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(byteMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(charMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(intMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(longMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(floatMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(doubleMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(stringMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(byteEnumMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(intEnumMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(longEnumMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(parcelableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(boolNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(byteNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(charNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(intNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(longNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(floatNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(doubleNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(stringNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(byteEnumNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(intEnumNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(longEnumNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(binderNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(pfdNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(parcelableNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(interfaceNullableArray, 0, 2);
+    _aidl_parcel.writeFixedArray(boolNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(byteNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(charNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(intNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(longNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(floatNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(doubleNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(stringNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(byteEnumNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(intEnumNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(longEnumNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(binderNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(pfdNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(parcelableNullableMatrix, 0, 2, 2);
+    _aidl_parcel.writeFixedArray(interfaceNullableMatrix, 0, 2, 2);
+    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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      int2x3 = _aidl_parcel.createFixedArray(int[][].class, 2, 3);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      boolArray = _aidl_parcel.createFixedArray(boolean[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      byteArray = _aidl_parcel.createFixedArray(byte[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      charArray = _aidl_parcel.createFixedArray(char[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      intArray = _aidl_parcel.createFixedArray(int[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      longArray = _aidl_parcel.createFixedArray(long[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      floatArray = _aidl_parcel.createFixedArray(float[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      doubleArray = _aidl_parcel.createFixedArray(double[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      stringArray = _aidl_parcel.createFixedArray(java.lang.String[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      byteEnumArray = _aidl_parcel.createFixedArray(byte[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      intEnumArray = _aidl_parcel.createFixedArray(int[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      longEnumArray = _aidl_parcel.createFixedArray(long[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      parcelableArray = _aidl_parcel.createFixedArray(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[].class, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable.CREATOR, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      boolMatrix = _aidl_parcel.createFixedArray(boolean[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      byteMatrix = _aidl_parcel.createFixedArray(byte[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      charMatrix = _aidl_parcel.createFixedArray(char[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      intMatrix = _aidl_parcel.createFixedArray(int[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      longMatrix = _aidl_parcel.createFixedArray(long[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      floatMatrix = _aidl_parcel.createFixedArray(float[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      doubleMatrix = _aidl_parcel.createFixedArray(double[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      stringMatrix = _aidl_parcel.createFixedArray(java.lang.String[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      byteEnumMatrix = _aidl_parcel.createFixedArray(byte[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      intEnumMatrix = _aidl_parcel.createFixedArray(int[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      longEnumMatrix = _aidl_parcel.createFixedArray(long[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      parcelableMatrix = _aidl_parcel.createFixedArray(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][].class, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable.CREATOR, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      boolNullableArray = _aidl_parcel.createFixedArray(boolean[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      byteNullableArray = _aidl_parcel.createFixedArray(byte[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      charNullableArray = _aidl_parcel.createFixedArray(char[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      intNullableArray = _aidl_parcel.createFixedArray(int[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      longNullableArray = _aidl_parcel.createFixedArray(long[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      floatNullableArray = _aidl_parcel.createFixedArray(float[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      doubleNullableArray = _aidl_parcel.createFixedArray(double[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      stringNullableArray = _aidl_parcel.createFixedArray(java.lang.String[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      byteEnumNullableArray = _aidl_parcel.createFixedArray(byte[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      intEnumNullableArray = _aidl_parcel.createFixedArray(int[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      longEnumNullableArray = _aidl_parcel.createFixedArray(long[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      binderNullableArray = _aidl_parcel.createFixedArray(android.os.IBinder[].class, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      pfdNullableArray = _aidl_parcel.createFixedArray(android.os.ParcelFileDescriptor[].class, android.os.ParcelFileDescriptor.CREATOR, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      parcelableNullableArray = _aidl_parcel.createFixedArray(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[].class, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable.CREATOR, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      interfaceNullableArray = _aidl_parcel.createFixedArray(android.aidl.fixedsizearray.FixedSizeArrayExample.IEmptyInterface[].class, android.aidl.fixedsizearray.FixedSizeArrayExample.IEmptyInterface.Stub::asInterface, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      boolNullableMatrix = _aidl_parcel.createFixedArray(boolean[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      byteNullableMatrix = _aidl_parcel.createFixedArray(byte[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      charNullableMatrix = _aidl_parcel.createFixedArray(char[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      intNullableMatrix = _aidl_parcel.createFixedArray(int[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      longNullableMatrix = _aidl_parcel.createFixedArray(long[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      floatNullableMatrix = _aidl_parcel.createFixedArray(float[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      doubleNullableMatrix = _aidl_parcel.createFixedArray(double[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      stringNullableMatrix = _aidl_parcel.createFixedArray(java.lang.String[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      byteEnumNullableMatrix = _aidl_parcel.createFixedArray(byte[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      intEnumNullableMatrix = _aidl_parcel.createFixedArray(int[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      longEnumNullableMatrix = _aidl_parcel.createFixedArray(long[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      binderNullableMatrix = _aidl_parcel.createFixedArray(android.os.IBinder[][].class, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      pfdNullableMatrix = _aidl_parcel.createFixedArray(android.os.ParcelFileDescriptor[][].class, android.os.ParcelFileDescriptor.CREATOR, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      parcelableNullableMatrix = _aidl_parcel.createFixedArray(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][].class, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable.CREATOR, 2, 2);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      interfaceNullableMatrix = _aidl_parcel.createFixedArray(android.aidl.fixedsizearray.FixedSizeArrayExample.IEmptyInterface[][].class, android.aidl.fixedsizearray.FixedSizeArrayExample.IEmptyInterface.Stub::asInterface, 2, 2);
+    } 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;
+    _mask |= describeContents(parcelableArray);
+    _mask |= describeContents(parcelableMatrix);
+    _mask |= describeContents(pfdNullableArray);
+    _mask |= describeContents(parcelableNullableArray);
+    _mask |= describeContents(pfdNullableMatrix);
+    _mask |= describeContents(parcelableNullableMatrix);
+    return _mask;
+  }
+  private int describeContents(Object _v) {
+    if (_v == null) return 0;
+    if (_v instanceof Object[]) {
+      int _mask = 0;
+      for (Object o : (Object[]) _v) {
+        _mask |= describeContents(o);
+      }
+      return _mask;
+    }
+    if (_v instanceof android.os.Parcelable) {
+      return ((android.os.Parcelable) _v).describeContents();
+    }
+    return 0;
+  }
+  public interface IRepeatFixedSizeArray extends android.os.IInterface
+  {
+    /** Default implementation for IRepeatFixedSizeArray. */
+    public static class Default implements android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray
+    {
+      @Override public byte[] RepeatBytes(byte[] input, byte[] repeated) throws android.os.RemoteException
+      {
+        return null;
+      }
+      @Override public int[] RepeatInts(int[] input, int[] repeated) throws android.os.RemoteException
+      {
+        return null;
+      }
+      @Override public android.os.IBinder[] RepeatBinders(android.os.IBinder[] input, android.os.IBinder[] repeated) throws android.os.RemoteException
+      {
+        return null;
+      }
+      @Override public android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] RepeatParcelables(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] input, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] repeated) throws android.os.RemoteException
+      {
+        return null;
+      }
+      @Override public byte[][] Repeat2dBytes(byte[][] input, byte[][] repeated) throws android.os.RemoteException
+      {
+        return null;
+      }
+      @Override public int[][] Repeat2dInts(int[][] input, int[][] repeated) throws android.os.RemoteException
+      {
+        return null;
+      }
+      @Override public android.os.IBinder[][] Repeat2dBinders(android.os.IBinder[][] input, android.os.IBinder[][] repeated) throws android.os.RemoteException
+      {
+        return null;
+      }
+      @Override public android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] Repeat2dParcelables(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] input, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] repeated) 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.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray
+    {
+      /** Construct the stub at attach it to the interface. */
+      public Stub()
+      {
+        this.attachInterface(this, DESCRIPTOR);
+      }
+      /**
+       * Cast an IBinder object into an android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray interface,
+       * generating a proxy if needed.
+       */
+      public static android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray asInterface(android.os.IBinder obj)
+      {
+        if ((obj==null)) {
+          return null;
+        }
+        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+        if (((iin!=null)&&(iin instanceof android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray))) {
+          return ((android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray)iin);
+        }
+        return new android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray.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_RepeatBytes:
+          {
+            byte[] _arg0;
+            _arg0 = data.createFixedArray(byte[].class, 3);
+            byte[] _arg1;
+            _arg1 = new byte[3];
+            data.enforceNoDataAvail();
+            byte[] _result = this.RepeatBytes(_arg0, _arg1);
+            reply.writeNoException();
+            reply.writeFixedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 3);
+            reply.writeFixedArray(_arg1, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 3);
+            break;
+          }
+          case TRANSACTION_RepeatInts:
+          {
+            int[] _arg0;
+            _arg0 = data.createFixedArray(int[].class, 3);
+            int[] _arg1;
+            _arg1 = new int[3];
+            data.enforceNoDataAvail();
+            int[] _result = this.RepeatInts(_arg0, _arg1);
+            reply.writeNoException();
+            reply.writeFixedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 3);
+            reply.writeFixedArray(_arg1, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 3);
+            break;
+          }
+          case TRANSACTION_RepeatBinders:
+          {
+            android.os.IBinder[] _arg0;
+            _arg0 = data.createFixedArray(android.os.IBinder[].class, 3);
+            android.os.IBinder[] _arg1;
+            _arg1 = new android.os.IBinder[3];
+            data.enforceNoDataAvail();
+            android.os.IBinder[] _result = this.RepeatBinders(_arg0, _arg1);
+            reply.writeNoException();
+            reply.writeFixedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 3);
+            reply.writeFixedArray(_arg1, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 3);
+            break;
+          }
+          case TRANSACTION_RepeatParcelables:
+          {
+            android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] _arg0;
+            _arg0 = data.createFixedArray(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[].class, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable.CREATOR, 3);
+            android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] _arg1;
+            _arg1 = new android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[3];
+            data.enforceNoDataAvail();
+            android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] _result = this.RepeatParcelables(_arg0, _arg1);
+            reply.writeNoException();
+            reply.writeFixedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 3);
+            reply.writeFixedArray(_arg1, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 3);
+            break;
+          }
+          case TRANSACTION_Repeat2dBytes:
+          {
+            byte[][] _arg0;
+            _arg0 = data.createFixedArray(byte[][].class, 2, 3);
+            byte[][] _arg1;
+            _arg1 = new byte[2][3];
+            data.enforceNoDataAvail();
+            byte[][] _result = this.Repeat2dBytes(_arg0, _arg1);
+            reply.writeNoException();
+            reply.writeFixedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 2, 3);
+            reply.writeFixedArray(_arg1, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 2, 3);
+            break;
+          }
+          case TRANSACTION_Repeat2dInts:
+          {
+            int[][] _arg0;
+            _arg0 = data.createFixedArray(int[][].class, 2, 3);
+            int[][] _arg1;
+            _arg1 = new int[2][3];
+            data.enforceNoDataAvail();
+            int[][] _result = this.Repeat2dInts(_arg0, _arg1);
+            reply.writeNoException();
+            reply.writeFixedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 2, 3);
+            reply.writeFixedArray(_arg1, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 2, 3);
+            break;
+          }
+          case TRANSACTION_Repeat2dBinders:
+          {
+            android.os.IBinder[][] _arg0;
+            _arg0 = data.createFixedArray(android.os.IBinder[][].class, 2, 3);
+            android.os.IBinder[][] _arg1;
+            _arg1 = new android.os.IBinder[2][3];
+            data.enforceNoDataAvail();
+            android.os.IBinder[][] _result = this.Repeat2dBinders(_arg0, _arg1);
+            reply.writeNoException();
+            reply.writeFixedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 2, 3);
+            reply.writeFixedArray(_arg1, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 2, 3);
+            break;
+          }
+          case TRANSACTION_Repeat2dParcelables:
+          {
+            android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] _arg0;
+            _arg0 = data.createFixedArray(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][].class, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable.CREATOR, 2, 3);
+            android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] _arg1;
+            _arg1 = new android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[2][3];
+            data.enforceNoDataAvail();
+            android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] _result = this.Repeat2dParcelables(_arg0, _arg1);
+            reply.writeNoException();
+            reply.writeFixedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 2, 3);
+            reply.writeFixedArray(_arg1, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE, 2, 3);
+            break;
+          }
+          default:
+          {
+            return super.onTransact(code, data, reply, flags);
+          }
+        }
+        return true;
+      }
+      private static class Proxy implements android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray
+      {
+        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 byte[] RepeatBytes(byte[] input, byte[] repeated) throws android.os.RemoteException
+        {
+          android.os.Parcel _data = android.os.Parcel.obtain();
+          android.os.Parcel _reply = android.os.Parcel.obtain();
+          byte[] _result;
+          try {
+            _data.writeInterfaceToken(DESCRIPTOR);
+            _data.writeFixedArray(input, 0, 3);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_RepeatBytes, _data, _reply, 0);
+            _reply.readException();
+            _result = _reply.createFixedArray(byte[].class, 3);
+            _reply.readFixedArray(repeated);
+          }
+          finally {
+            _reply.recycle();
+            _data.recycle();
+          }
+          return _result;
+        }
+        @Override public int[] RepeatInts(int[] input, int[] repeated) throws android.os.RemoteException
+        {
+          android.os.Parcel _data = android.os.Parcel.obtain();
+          android.os.Parcel _reply = android.os.Parcel.obtain();
+          int[] _result;
+          try {
+            _data.writeInterfaceToken(DESCRIPTOR);
+            _data.writeFixedArray(input, 0, 3);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_RepeatInts, _data, _reply, 0);
+            _reply.readException();
+            _result = _reply.createFixedArray(int[].class, 3);
+            _reply.readFixedArray(repeated);
+          }
+          finally {
+            _reply.recycle();
+            _data.recycle();
+          }
+          return _result;
+        }
+        @Override public android.os.IBinder[] RepeatBinders(android.os.IBinder[] input, android.os.IBinder[] repeated) throws android.os.RemoteException
+        {
+          android.os.Parcel _data = android.os.Parcel.obtain();
+          android.os.Parcel _reply = android.os.Parcel.obtain();
+          android.os.IBinder[] _result;
+          try {
+            _data.writeInterfaceToken(DESCRIPTOR);
+            _data.writeFixedArray(input, 0, 3);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_RepeatBinders, _data, _reply, 0);
+            _reply.readException();
+            _result = _reply.createFixedArray(android.os.IBinder[].class, 3);
+            _reply.readFixedArray(repeated);
+          }
+          finally {
+            _reply.recycle();
+            _data.recycle();
+          }
+          return _result;
+        }
+        @Override public android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] RepeatParcelables(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] input, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] repeated) throws android.os.RemoteException
+        {
+          android.os.Parcel _data = android.os.Parcel.obtain();
+          android.os.Parcel _reply = android.os.Parcel.obtain();
+          android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] _result;
+          try {
+            _data.writeInterfaceToken(DESCRIPTOR);
+            _data.writeFixedArray(input, 0, 3);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_RepeatParcelables, _data, _reply, 0);
+            _reply.readException();
+            _result = _reply.createFixedArray(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[].class, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable.CREATOR, 3);
+            _reply.readFixedArray(repeated, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable.CREATOR);
+          }
+          finally {
+            _reply.recycle();
+            _data.recycle();
+          }
+          return _result;
+        }
+        @Override public byte[][] Repeat2dBytes(byte[][] input, byte[][] repeated) throws android.os.RemoteException
+        {
+          android.os.Parcel _data = android.os.Parcel.obtain();
+          android.os.Parcel _reply = android.os.Parcel.obtain();
+          byte[][] _result;
+          try {
+            _data.writeInterfaceToken(DESCRIPTOR);
+            _data.writeFixedArray(input, 0, 2, 3);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_Repeat2dBytes, _data, _reply, 0);
+            _reply.readException();
+            _result = _reply.createFixedArray(byte[][].class, 2, 3);
+            _reply.readFixedArray(repeated);
+          }
+          finally {
+            _reply.recycle();
+            _data.recycle();
+          }
+          return _result;
+        }
+        @Override public int[][] Repeat2dInts(int[][] input, int[][] repeated) throws android.os.RemoteException
+        {
+          android.os.Parcel _data = android.os.Parcel.obtain();
+          android.os.Parcel _reply = android.os.Parcel.obtain();
+          int[][] _result;
+          try {
+            _data.writeInterfaceToken(DESCRIPTOR);
+            _data.writeFixedArray(input, 0, 2, 3);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_Repeat2dInts, _data, _reply, 0);
+            _reply.readException();
+            _result = _reply.createFixedArray(int[][].class, 2, 3);
+            _reply.readFixedArray(repeated);
+          }
+          finally {
+            _reply.recycle();
+            _data.recycle();
+          }
+          return _result;
+        }
+        @Override public android.os.IBinder[][] Repeat2dBinders(android.os.IBinder[][] input, android.os.IBinder[][] repeated) throws android.os.RemoteException
+        {
+          android.os.Parcel _data = android.os.Parcel.obtain();
+          android.os.Parcel _reply = android.os.Parcel.obtain();
+          android.os.IBinder[][] _result;
+          try {
+            _data.writeInterfaceToken(DESCRIPTOR);
+            _data.writeFixedArray(input, 0, 2, 3);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_Repeat2dBinders, _data, _reply, 0);
+            _reply.readException();
+            _result = _reply.createFixedArray(android.os.IBinder[][].class, 2, 3);
+            _reply.readFixedArray(repeated);
+          }
+          finally {
+            _reply.recycle();
+            _data.recycle();
+          }
+          return _result;
+        }
+        @Override public android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] Repeat2dParcelables(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] input, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] repeated) throws android.os.RemoteException
+        {
+          android.os.Parcel _data = android.os.Parcel.obtain();
+          android.os.Parcel _reply = android.os.Parcel.obtain();
+          android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] _result;
+          try {
+            _data.writeInterfaceToken(DESCRIPTOR);
+            _data.writeFixedArray(input, 0, 2, 3);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_Repeat2dParcelables, _data, _reply, 0);
+            _reply.readException();
+            _result = _reply.createFixedArray(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][].class, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable.CREATOR, 2, 3);
+            _reply.readFixedArray(repeated, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable.CREATOR);
+          }
+          finally {
+            _reply.recycle();
+            _data.recycle();
+          }
+          return _result;
+        }
+      }
+      static final int TRANSACTION_RepeatBytes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+      static final int TRANSACTION_RepeatInts = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
+      static final int TRANSACTION_RepeatBinders = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
+      static final int TRANSACTION_RepeatParcelables = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
+      static final int TRANSACTION_Repeat2dBytes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
+      static final int TRANSACTION_Repeat2dInts = (android.os.IBinder.FIRST_CALL_TRANSACTION + 5);
+      static final int TRANSACTION_Repeat2dBinders = (android.os.IBinder.FIRST_CALL_TRANSACTION + 6);
+      static final int TRANSACTION_Repeat2dParcelables = (android.os.IBinder.FIRST_CALL_TRANSACTION + 7);
+    }
+    public static final java.lang.String DESCRIPTOR = "android$aidl$fixedsizearray$FixedSizeArrayExample$IRepeatFixedSizeArray".replace('$', '.');
+    public byte[] RepeatBytes(byte[] input, byte[] repeated) throws android.os.RemoteException;
+    public int[] RepeatInts(int[] input, int[] repeated) throws android.os.RemoteException;
+    public android.os.IBinder[] RepeatBinders(android.os.IBinder[] input, android.os.IBinder[] repeated) throws android.os.RemoteException;
+    public android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] RepeatParcelables(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] input, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[] repeated) throws android.os.RemoteException;
+    public byte[][] Repeat2dBytes(byte[][] input, byte[][] repeated) throws android.os.RemoteException;
+    public int[][] Repeat2dInts(int[][] input, int[][] repeated) throws android.os.RemoteException;
+    public android.os.IBinder[][] Repeat2dBinders(android.os.IBinder[][] input, android.os.IBinder[][] repeated) throws android.os.RemoteException;
+    public android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] Repeat2dParcelables(android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] input, android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable[][] repeated) throws android.os.RemoteException;
+  }
+  public static @interface ByteEnum {
+    public static final byte A = 0;
+  }
+  public static @interface IntEnum {
+    public static final int A = 0;
+  }
+  public static @interface LongEnum {
+    public static final long A = 0L;
+  }
+  public static class IntParcelable implements android.os.Parcelable
+  {
+    public int value = 0;
+    public static final android.os.Parcelable.Creator<IntParcelable> CREATOR = new android.os.Parcelable.Creator<IntParcelable>() {
+      @Override
+      public IntParcelable createFromParcel(android.os.Parcel _aidl_source) {
+        IntParcelable _aidl_out = new IntParcelable();
+        _aidl_out.readFromParcel(_aidl_source);
+        return _aidl_out;
+      }
+      @Override
+      public IntParcelable[] newArray(int _aidl_size) {
+        return new IntParcelable[_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.writeInt(value);
+      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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        value = _aidl_parcel.readInt();
+      } 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 boolean equals(Object other) {
+      if (this == other) return true;
+      if (other == null) return false;
+      if (!(other instanceof IntParcelable)) return false;
+      IntParcelable that = (IntParcelable)other;
+      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(value).toArray());
+    }
+    @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.fixedsizearray.FixedSizeArrayExample.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.fixedsizearray.FixedSizeArrayExample.IEmptyInterface
+    {
+      /** Construct the stub at attach it to the interface. */
+      public Stub()
+      {
+        this.attachInterface(this, DESCRIPTOR);
+      }
+      /**
+       * Cast an IBinder object into an android.aidl.fixedsizearray.FixedSizeArrayExample.IEmptyInterface interface,
+       * generating a proxy if needed.
+       */
+      public static android.aidl.fixedsizearray.FixedSizeArrayExample.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.fixedsizearray.FixedSizeArrayExample.IEmptyInterface))) {
+          return ((android.aidl.fixedsizearray.FixedSizeArrayExample.IEmptyInterface)iin);
+        }
+        return new android.aidl.fixedsizearray.FixedSizeArrayExample.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.fixedsizearray.FixedSizeArrayExample.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 final java.lang.String DESCRIPTOR = "android$aidl$fixedsizearray$FixedSizeArrayExample$IEmptyInterface".replace('$', '.');
+  }
+}
diff --git a/tests/golden_output/aidl-test-fixedsizearray-java-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.java.d b/tests/golden_output/aidl-test-fixedsizearray-java-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.java.d
new file mode 100644
index 0000000..1ed6bda
--- /dev/null
+++ b/tests/golden_output/aidl-test-fixedsizearray-java-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-fixedsizearray-java-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.java : \
+  system/tools/aidl/tests/android/aidl/fixedsizearray/FixedSizeArrayExample.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp b/tests/golden_output/aidl-test-fixedsizearray-java-source/gen/timestamp
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp
copy to tests/golden_output/aidl-test-fixedsizearray-java-source/gen/timestamp
diff --git a/tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp b/tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp
new file mode 100644
index 0000000..00cdcad
--- /dev/null
+++ b/tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp
@@ -0,0 +1,1351 @@
+#include "aidl/android/aidl/fixedsizearray/FixedSizeArrayExample.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+const char* FixedSizeArrayExample::descriptor = "android.aidl.fixedsizearray.FixedSizeArrayExample";
+
+binder_status_t FixedSizeArrayExample::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &int2x3);
+  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_readData(_aidl_parcel, &boolArray);
+  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_readData(_aidl_parcel, &byteArray);
+  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_readData(_aidl_parcel, &charArray);
+  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_readData(_aidl_parcel, &intArray);
+  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_readData(_aidl_parcel, &longArray);
+  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_readData(_aidl_parcel, &floatArray);
+  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_readData(_aidl_parcel, &doubleArray);
+  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_readData(_aidl_parcel, &stringArray);
+  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_readData(_aidl_parcel, &byteEnumArray);
+  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_readData(_aidl_parcel, &intEnumArray);
+  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_readData(_aidl_parcel, &longEnumArray);
+  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_readData(_aidl_parcel, &parcelableArray);
+  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_readData(_aidl_parcel, &boolMatrix);
+  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_readData(_aidl_parcel, &byteMatrix);
+  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_readData(_aidl_parcel, &charMatrix);
+  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_readData(_aidl_parcel, &intMatrix);
+  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_readData(_aidl_parcel, &longMatrix);
+  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_readData(_aidl_parcel, &floatMatrix);
+  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_readData(_aidl_parcel, &doubleMatrix);
+  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_readData(_aidl_parcel, &stringMatrix);
+  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_readData(_aidl_parcel, &byteEnumMatrix);
+  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_readData(_aidl_parcel, &intEnumMatrix);
+  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_readData(_aidl_parcel, &longEnumMatrix);
+  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_readData(_aidl_parcel, &parcelableMatrix);
+  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_readNullableData(_aidl_parcel, &boolNullableArray);
+  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_readNullableData(_aidl_parcel, &byteNullableArray);
+  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_readNullableData(_aidl_parcel, &charNullableArray);
+  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_readNullableData(_aidl_parcel, &intNullableArray);
+  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_readNullableData(_aidl_parcel, &longNullableArray);
+  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_readNullableData(_aidl_parcel, &floatNullableArray);
+  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_readNullableData(_aidl_parcel, &doubleNullableArray);
+  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_readNullableData(_aidl_parcel, &stringNullableArray);
+  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_readNullableData(_aidl_parcel, &byteEnumNullableArray);
+  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_readNullableData(_aidl_parcel, &intEnumNullableArray);
+  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_readNullableData(_aidl_parcel, &longEnumNullableArray);
+  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_readNullableData(_aidl_parcel, &binderNullableArray);
+  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_readNullableData(_aidl_parcel, &pfdNullableArray);
+  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_readNullableData(_aidl_parcel, &parcelableNullableArray);
+  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_readNullableData(_aidl_parcel, &interfaceNullableArray);
+  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_readNullableData(_aidl_parcel, &boolNullableMatrix);
+  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_readNullableData(_aidl_parcel, &byteNullableMatrix);
+  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_readNullableData(_aidl_parcel, &charNullableMatrix);
+  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_readNullableData(_aidl_parcel, &intNullableMatrix);
+  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_readNullableData(_aidl_parcel, &longNullableMatrix);
+  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_readNullableData(_aidl_parcel, &floatNullableMatrix);
+  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_readNullableData(_aidl_parcel, &doubleNullableMatrix);
+  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_readNullableData(_aidl_parcel, &stringNullableMatrix);
+  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_readNullableData(_aidl_parcel, &byteEnumNullableMatrix);
+  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_readNullableData(_aidl_parcel, &intEnumNullableMatrix);
+  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_readNullableData(_aidl_parcel, &longEnumNullableMatrix);
+  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_readNullableData(_aidl_parcel, &binderNullableMatrix);
+  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_readNullableData(_aidl_parcel, &pfdNullableMatrix);
+  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_readNullableData(_aidl_parcel, &parcelableNullableMatrix);
+  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_readNullableData(_aidl_parcel, &interfaceNullableMatrix);
+  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 FixedSizeArrayExample::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 = ::ndk::AParcel_writeData(_aidl_parcel, int2x3);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, boolArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, byteArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, charArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, intArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, longArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, floatArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, doubleArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, stringArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, byteEnumArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, intEnumArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, longEnumArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, parcelableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, boolMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, byteMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, charMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, intMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, longMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, floatMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, doubleMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, stringMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, byteEnumMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, intEnumMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, longEnumMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, parcelableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, boolNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, byteNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, charNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, intNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, longNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, floatNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, doubleNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, stringNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, byteEnumNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, intEnumNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, longEnumNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, binderNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, pfdNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, parcelableNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, interfaceNullableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, boolNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, byteNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, charNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, intNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, longNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, floatNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, doubleNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, stringNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, byteEnumNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, intEnumNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, longEnumNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, binderNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, pfdNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, parcelableNullableMatrix);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, interfaceNullableMatrix);
+  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 fixedsizearray
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+static binder_status_t _aidl_android_aidl_fixedsizearray_FixedSizeArrayExample_IRepeatFixedSizeArray_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<FixedSizeArrayExample::BnRepeatFixedSizeArray> _aidl_impl = std::static_pointer_cast<FixedSizeArrayExample::BnRepeatFixedSizeArray>(::ndk::ICInterface::asInterface(_aidl_binder));
+  switch (_aidl_code) {
+    case (FIRST_CALL_TRANSACTION + 0 /*RepeatBytes*/): {
+      std::array<uint8_t, 3> in_input;
+      std::array<uint8_t, 3> out_repeated;
+      std::array<uint8_t, 3> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatBytes(in_input, &out_repeated, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 1 /*RepeatInts*/): {
+      std::array<int32_t, 3> in_input;
+      std::array<int32_t, 3> out_repeated;
+      std::array<int32_t, 3> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatInts(in_input, &out_repeated, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 2 /*RepeatBinders*/): {
+      std::array<::ndk::SpAIBinder, 3> in_input;
+      std::array<::ndk::SpAIBinder, 3> out_repeated;
+      std::array<::ndk::SpAIBinder, 3> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatBinders(in_input, &out_repeated, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 3 /*RepeatParcelables*/): {
+      std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3> in_input;
+      std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3> out_repeated;
+      std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatParcelables(in_input, &out_repeated, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 4 /*Repeat2dBytes*/): {
+      std::array<std::array<uint8_t, 3>, 2> in_input;
+      std::array<std::array<uint8_t, 3>, 2> out_repeated;
+      std::array<std::array<uint8_t, 3>, 2> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->Repeat2dBytes(in_input, &out_repeated, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 5 /*Repeat2dInts*/): {
+      std::array<std::array<int32_t, 3>, 2> in_input;
+      std::array<std::array<int32_t, 3>, 2> out_repeated;
+      std::array<std::array<int32_t, 3>, 2> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->Repeat2dInts(in_input, &out_repeated, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 6 /*Repeat2dBinders*/): {
+      std::array<std::array<::ndk::SpAIBinder, 3>, 2> in_input;
+      std::array<std::array<::ndk::SpAIBinder, 3>, 2> out_repeated;
+      std::array<std::array<::ndk::SpAIBinder, 3>, 2> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->Repeat2dBinders(in_input, &out_repeated, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 7 /*Repeat2dParcelables*/): {
+      std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2> in_input;
+      std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2> out_repeated;
+      std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->Repeat2dParcelables(in_input, &out_repeated, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+  }
+  return _aidl_ret_status;
+}
+
+static AIBinder_Class* _g_aidl_android_aidl_fixedsizearray_FixedSizeArrayExample_IRepeatFixedSizeArray_clazz = ::ndk::ICInterface::defineClass(FixedSizeArrayExample::IRepeatFixedSizeArray::descriptor, _aidl_android_aidl_fixedsizearray_FixedSizeArrayExample_IRepeatFixedSizeArray_onTransact);
+
+FixedSizeArrayExample::BpRepeatFixedSizeArray::BpRepeatFixedSizeArray(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
+FixedSizeArrayExample::BpRepeatFixedSizeArray::~BpRepeatFixedSizeArray() {}
+
+::ndk::ScopedAStatus FixedSizeArrayExample::BpRepeatFixedSizeArray::RepeatBytes(const std::array<uint8_t, 3>& in_input, std::array<uint8_t, 3>* out_repeated, std::array<uint8_t, 3>* _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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 0 /*RepeatBytes*/),
+    _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 && IRepeatFixedSizeArray::getDefaultImpl()) {
+    _aidl_status = IRepeatFixedSizeArray::getDefaultImpl()->RepeatBytes(in_input, out_repeated, _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_readData(_aidl_out.get(), _aidl_return);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
+  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;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::BpRepeatFixedSizeArray::RepeatInts(const std::array<int32_t, 3>& in_input, std::array<int32_t, 3>* out_repeated, std::array<int32_t, 3>* _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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 1 /*RepeatInts*/),
+    _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 && IRepeatFixedSizeArray::getDefaultImpl()) {
+    _aidl_status = IRepeatFixedSizeArray::getDefaultImpl()->RepeatInts(in_input, out_repeated, _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_readData(_aidl_out.get(), _aidl_return);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
+  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;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::BpRepeatFixedSizeArray::RepeatBinders(const std::array<::ndk::SpAIBinder, 3>& in_input, std::array<::ndk::SpAIBinder, 3>* out_repeated, std::array<::ndk::SpAIBinder, 3>* _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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 2 /*RepeatBinders*/),
+    _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 && IRepeatFixedSizeArray::getDefaultImpl()) {
+    _aidl_status = IRepeatFixedSizeArray::getDefaultImpl()->RepeatBinders(in_input, out_repeated, _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_readData(_aidl_out.get(), _aidl_return);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
+  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;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::BpRepeatFixedSizeArray::RepeatParcelables(const std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>& in_input, std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* out_repeated, std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* _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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 3 /*RepeatParcelables*/),
+    _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 && IRepeatFixedSizeArray::getDefaultImpl()) {
+    _aidl_status = IRepeatFixedSizeArray::getDefaultImpl()->RepeatParcelables(in_input, out_repeated, _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_readData(_aidl_out.get(), _aidl_return);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
+  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;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::BpRepeatFixedSizeArray::Repeat2dBytes(const std::array<std::array<uint8_t, 3>, 2>& in_input, std::array<std::array<uint8_t, 3>, 2>* out_repeated, std::array<std::array<uint8_t, 3>, 2>* _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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 4 /*Repeat2dBytes*/),
+    _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 && IRepeatFixedSizeArray::getDefaultImpl()) {
+    _aidl_status = IRepeatFixedSizeArray::getDefaultImpl()->Repeat2dBytes(in_input, out_repeated, _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_readData(_aidl_out.get(), _aidl_return);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
+  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;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::BpRepeatFixedSizeArray::Repeat2dInts(const std::array<std::array<int32_t, 3>, 2>& in_input, std::array<std::array<int32_t, 3>, 2>* out_repeated, std::array<std::array<int32_t, 3>, 2>* _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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 5 /*Repeat2dInts*/),
+    _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 && IRepeatFixedSizeArray::getDefaultImpl()) {
+    _aidl_status = IRepeatFixedSizeArray::getDefaultImpl()->Repeat2dInts(in_input, out_repeated, _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_readData(_aidl_out.get(), _aidl_return);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
+  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;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::BpRepeatFixedSizeArray::Repeat2dBinders(const std::array<std::array<::ndk::SpAIBinder, 3>, 2>& in_input, std::array<std::array<::ndk::SpAIBinder, 3>, 2>* out_repeated, std::array<std::array<::ndk::SpAIBinder, 3>, 2>* _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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 6 /*Repeat2dBinders*/),
+    _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 && IRepeatFixedSizeArray::getDefaultImpl()) {
+    _aidl_status = IRepeatFixedSizeArray::getDefaultImpl()->Repeat2dBinders(in_input, out_repeated, _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_readData(_aidl_out.get(), _aidl_return);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
+  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;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::BpRepeatFixedSizeArray::Repeat2dParcelables(const std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>& in_input, std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* out_repeated, std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* _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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 7 /*Repeat2dParcelables*/),
+    _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 && IRepeatFixedSizeArray::getDefaultImpl()) {
+    _aidl_status = IRepeatFixedSizeArray::getDefaultImpl()->Repeat2dParcelables(in_input, out_repeated, _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_readData(_aidl_out.get(), _aidl_return);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
+  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 BnRepeatFixedSizeArray
+FixedSizeArrayExample::BnRepeatFixedSizeArray::BnRepeatFixedSizeArray() {}
+FixedSizeArrayExample::BnRepeatFixedSizeArray::~BnRepeatFixedSizeArray() {}
+::ndk::SpAIBinder FixedSizeArrayExample::BnRepeatFixedSizeArray::createBinder() {
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_fixedsizearray_FixedSizeArrayExample_IRepeatFixedSizeArray_clazz, static_cast<void*>(this));
+  #ifdef BINDER_STABILITY_SUPPORT
+  AIBinder_markCompilationUnitStability(binder);
+  #endif  // BINDER_STABILITY_SUPPORT
+  return ::ndk::SpAIBinder(binder);
+}
+// Source for IRepeatFixedSizeArray
+const char* FixedSizeArrayExample::IRepeatFixedSizeArray::descriptor = "android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray";
+FixedSizeArrayExample::IRepeatFixedSizeArray::IRepeatFixedSizeArray() {}
+FixedSizeArrayExample::IRepeatFixedSizeArray::~IRepeatFixedSizeArray() {}
+
+
+std::shared_ptr<FixedSizeArrayExample::IRepeatFixedSizeArray> FixedSizeArrayExample::IRepeatFixedSizeArray::fromBinder(const ::ndk::SpAIBinder& binder) {
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_fixedsizearray_FixedSizeArrayExample_IRepeatFixedSizeArray_clazz)) { return nullptr; }
+  std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
+  if (interface) {
+    return std::static_pointer_cast<IRepeatFixedSizeArray>(interface);
+  }
+  return ::ndk::SharedRefBase::make<FixedSizeArrayExample::BpRepeatFixedSizeArray>(binder);
+}
+
+binder_status_t FixedSizeArrayExample::IRepeatFixedSizeArray::writeToParcel(AParcel* parcel, const std::shared_ptr<IRepeatFixedSizeArray>& instance) {
+  return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : nullptr);
+}
+binder_status_t FixedSizeArrayExample::IRepeatFixedSizeArray::readFromParcel(const AParcel* parcel, std::shared_ptr<IRepeatFixedSizeArray>* instance) {
+  ::ndk::SpAIBinder binder;
+  binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());
+  if (status != STATUS_OK) return status;
+  *instance = IRepeatFixedSizeArray::fromBinder(binder);
+  return STATUS_OK;
+}
+bool FixedSizeArrayExample::IRepeatFixedSizeArray::setDefaultImpl(const std::shared_ptr<IRepeatFixedSizeArray>& 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(!IRepeatFixedSizeArray::default_impl);
+  if (impl) {
+    IRepeatFixedSizeArray::default_impl = impl;
+    return true;
+  }
+  return false;
+}
+const std::shared_ptr<FixedSizeArrayExample::IRepeatFixedSizeArray>& FixedSizeArrayExample::IRepeatFixedSizeArray::getDefaultImpl() {
+  return IRepeatFixedSizeArray::default_impl;
+}
+std::shared_ptr<FixedSizeArrayExample::IRepeatFixedSizeArray> FixedSizeArrayExample::IRepeatFixedSizeArray::default_impl = nullptr;
+::ndk::ScopedAStatus FixedSizeArrayExample::IRepeatFixedSizeArrayDefault::RepeatBytes(const std::array<uint8_t, 3>& /*in_input*/, std::array<uint8_t, 3>* /*out_repeated*/, std::array<uint8_t, 3>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::IRepeatFixedSizeArrayDefault::RepeatInts(const std::array<int32_t, 3>& /*in_input*/, std::array<int32_t, 3>* /*out_repeated*/, std::array<int32_t, 3>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::IRepeatFixedSizeArrayDefault::RepeatBinders(const std::array<::ndk::SpAIBinder, 3>& /*in_input*/, std::array<::ndk::SpAIBinder, 3>* /*out_repeated*/, std::array<::ndk::SpAIBinder, 3>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::IRepeatFixedSizeArrayDefault::RepeatParcelables(const std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>& /*in_input*/, std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* /*out_repeated*/, std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::IRepeatFixedSizeArrayDefault::Repeat2dBytes(const std::array<std::array<uint8_t, 3>, 2>& /*in_input*/, std::array<std::array<uint8_t, 3>, 2>* /*out_repeated*/, std::array<std::array<uint8_t, 3>, 2>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::IRepeatFixedSizeArrayDefault::Repeat2dInts(const std::array<std::array<int32_t, 3>, 2>& /*in_input*/, std::array<std::array<int32_t, 3>, 2>* /*out_repeated*/, std::array<std::array<int32_t, 3>, 2>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::IRepeatFixedSizeArrayDefault::Repeat2dBinders(const std::array<std::array<::ndk::SpAIBinder, 3>, 2>& /*in_input*/, std::array<std::array<::ndk::SpAIBinder, 3>, 2>* /*out_repeated*/, std::array<std::array<::ndk::SpAIBinder, 3>, 2>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus FixedSizeArrayExample::IRepeatFixedSizeArrayDefault::Repeat2dParcelables(const std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>& /*in_input*/, std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* /*out_repeated*/, std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::SpAIBinder FixedSizeArrayExample::IRepeatFixedSizeArrayDefault::asBinder() {
+  return ::ndk::SpAIBinder();
+}
+bool FixedSizeArrayExample::IRepeatFixedSizeArrayDefault::isRemote() {
+  return false;
+}
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+const char* FixedSizeArrayExample::IntParcelable::descriptor = "android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable";
+
+binder_status_t FixedSizeArrayExample::IntParcelable::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &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 FixedSizeArrayExample::IntParcelable::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 = ::ndk::AParcel_writeData(_aidl_parcel, value);
+  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 fixedsizearray
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+static binder_status_t _aidl_android_aidl_fixedsizearray_FixedSizeArrayExample_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_fixedsizearray_FixedSizeArrayExample_IEmptyInterface_clazz = ::ndk::ICInterface::defineClass(FixedSizeArrayExample::IEmptyInterface::descriptor, _aidl_android_aidl_fixedsizearray_FixedSizeArrayExample_IEmptyInterface_onTransact);
+
+FixedSizeArrayExample::BpEmptyInterface::BpEmptyInterface(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
+FixedSizeArrayExample::BpEmptyInterface::~BpEmptyInterface() {}
+
+// Source for BnEmptyInterface
+FixedSizeArrayExample::BnEmptyInterface::BnEmptyInterface() {}
+FixedSizeArrayExample::BnEmptyInterface::~BnEmptyInterface() {}
+::ndk::SpAIBinder FixedSizeArrayExample::BnEmptyInterface::createBinder() {
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_fixedsizearray_FixedSizeArrayExample_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* FixedSizeArrayExample::IEmptyInterface::descriptor = "android.aidl.fixedsizearray.FixedSizeArrayExample.IEmptyInterface";
+FixedSizeArrayExample::IEmptyInterface::IEmptyInterface() {}
+FixedSizeArrayExample::IEmptyInterface::~IEmptyInterface() {}
+
+
+std::shared_ptr<FixedSizeArrayExample::IEmptyInterface> FixedSizeArrayExample::IEmptyInterface::fromBinder(const ::ndk::SpAIBinder& binder) {
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_fixedsizearray_FixedSizeArrayExample_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<FixedSizeArrayExample::BpEmptyInterface>(binder);
+}
+
+binder_status_t FixedSizeArrayExample::IEmptyInterface::writeToParcel(AParcel* parcel, const std::shared_ptr<IEmptyInterface>& instance) {
+  return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : nullptr);
+}
+binder_status_t FixedSizeArrayExample::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 FixedSizeArrayExample::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<FixedSizeArrayExample::IEmptyInterface>& FixedSizeArrayExample::IEmptyInterface::getDefaultImpl() {
+  return IEmptyInterface::default_impl;
+}
+std::shared_ptr<FixedSizeArrayExample::IEmptyInterface> FixedSizeArrayExample::IEmptyInterface::default_impl = nullptr;
+::ndk::SpAIBinder FixedSizeArrayExample::IEmptyInterfaceDefault::asBinder() {
+  return ::ndk::SpAIBinder();
+}
+bool FixedSizeArrayExample::IEmptyInterfaceDefault::isRemote() {
+  return false;
+}
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp.d b/tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp.d
new file mode 100644
index 0000000..1443490
--- /dev/null
+++ b/tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-fixedsizearray-ndk-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.cpp : \
+  system/tools/aidl/tests/android/aidl/fixedsizearray/FixedSizeArrayExample.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnDeprecatedParcelable.h b/tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/include/aidl/android/aidl/fixedsizearray/BnFixedSizeArrayExample.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnDeprecatedParcelable.h
copy to tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/include/aidl/android/aidl/fixedsizearray/BnFixedSizeArrayExample.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpDeprecatedParcelable.h b/tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/include/aidl/android/aidl/fixedsizearray/BpFixedSizeArrayExample.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpDeprecatedParcelable.h
copy to tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/include/aidl/android/aidl/fixedsizearray/BpFixedSizeArrayExample.h
diff --git a/tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/include/aidl/android/aidl/fixedsizearray/FixedSizeArrayExample.h b/tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/include/aidl/android/aidl/fixedsizearray/FixedSizeArrayExample.h
new file mode 100644
index 0000000..eecf292
--- /dev/null
+++ b/tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/include/aidl/android/aidl/fixedsizearray/FixedSizeArrayExample.h
@@ -0,0 +1,403 @@
+#pragma once
+
+#include <array>
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+#include <android/binder_enums.h>
+#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/fixedsizearray/FixedSizeArrayExample.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+class FixedSizeArrayExample {
+public:
+  typedef std::false_type fixed_size;
+  static const char* descriptor;
+
+  class IntParcelable {
+  public:
+    typedef std::false_type fixed_size;
+    static const char* descriptor;
+
+    int32_t value = 0;
+
+    binder_status_t readFromParcel(const AParcel* parcel);
+    binder_status_t writeToParcel(AParcel* parcel) const;
+
+    inline bool operator!=(const IntParcelable& rhs) const {
+      return std::tie(value) != std::tie(rhs.value);
+    }
+    inline bool operator<(const IntParcelable& rhs) const {
+      return std::tie(value) < std::tie(rhs.value);
+    }
+    inline bool operator<=(const IntParcelable& rhs) const {
+      return std::tie(value) <= std::tie(rhs.value);
+    }
+    inline bool operator==(const IntParcelable& rhs) const {
+      return std::tie(value) == std::tie(rhs.value);
+    }
+    inline bool operator>(const IntParcelable& rhs) const {
+      return std::tie(value) > std::tie(rhs.value);
+    }
+    inline bool operator>=(const IntParcelable& rhs) const {
+      return std::tie(value) >= std::tie(rhs.value);
+    }
+
+    static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "IntParcelable{";
+      os << "value: " << ::android::internal::ToString(value);
+      os << "}";
+      return os.str();
+    }
+  };
+  class IRepeatFixedSizeArray : public ::ndk::ICInterface {
+  public:
+    static const char* descriptor;
+    IRepeatFixedSizeArray();
+    virtual ~IRepeatFixedSizeArray();
+
+    static constexpr uint32_t TRANSACTION_RepeatBytes = FIRST_CALL_TRANSACTION + 0;
+    static constexpr uint32_t TRANSACTION_RepeatInts = FIRST_CALL_TRANSACTION + 1;
+    static constexpr uint32_t TRANSACTION_RepeatBinders = FIRST_CALL_TRANSACTION + 2;
+    static constexpr uint32_t TRANSACTION_RepeatParcelables = FIRST_CALL_TRANSACTION + 3;
+    static constexpr uint32_t TRANSACTION_Repeat2dBytes = FIRST_CALL_TRANSACTION + 4;
+    static constexpr uint32_t TRANSACTION_Repeat2dInts = FIRST_CALL_TRANSACTION + 5;
+    static constexpr uint32_t TRANSACTION_Repeat2dBinders = FIRST_CALL_TRANSACTION + 6;
+    static constexpr uint32_t TRANSACTION_Repeat2dParcelables = FIRST_CALL_TRANSACTION + 7;
+
+    static std::shared_ptr<IRepeatFixedSizeArray> fromBinder(const ::ndk::SpAIBinder& binder);
+    static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<IRepeatFixedSizeArray>& instance);
+    static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<IRepeatFixedSizeArray>* instance);
+    static bool setDefaultImpl(const std::shared_ptr<IRepeatFixedSizeArray>& impl);
+    static const std::shared_ptr<IRepeatFixedSizeArray>& getDefaultImpl();
+    virtual ::ndk::ScopedAStatus RepeatBytes(const std::array<uint8_t, 3>& in_input, std::array<uint8_t, 3>* out_repeated, std::array<uint8_t, 3>* _aidl_return) = 0;
+    virtual ::ndk::ScopedAStatus RepeatInts(const std::array<int32_t, 3>& in_input, std::array<int32_t, 3>* out_repeated, std::array<int32_t, 3>* _aidl_return) = 0;
+    virtual ::ndk::ScopedAStatus RepeatBinders(const std::array<::ndk::SpAIBinder, 3>& in_input, std::array<::ndk::SpAIBinder, 3>* out_repeated, std::array<::ndk::SpAIBinder, 3>* _aidl_return) = 0;
+    virtual ::ndk::ScopedAStatus RepeatParcelables(const std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>& in_input, std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* out_repeated, std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* _aidl_return) = 0;
+    virtual ::ndk::ScopedAStatus Repeat2dBytes(const std::array<std::array<uint8_t, 3>, 2>& in_input, std::array<std::array<uint8_t, 3>, 2>* out_repeated, std::array<std::array<uint8_t, 3>, 2>* _aidl_return) = 0;
+    virtual ::ndk::ScopedAStatus Repeat2dInts(const std::array<std::array<int32_t, 3>, 2>& in_input, std::array<std::array<int32_t, 3>, 2>* out_repeated, std::array<std::array<int32_t, 3>, 2>* _aidl_return) = 0;
+    virtual ::ndk::ScopedAStatus Repeat2dBinders(const std::array<std::array<::ndk::SpAIBinder, 3>, 2>& in_input, std::array<std::array<::ndk::SpAIBinder, 3>, 2>* out_repeated, std::array<std::array<::ndk::SpAIBinder, 3>, 2>* _aidl_return) = 0;
+    virtual ::ndk::ScopedAStatus Repeat2dParcelables(const std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>& in_input, std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* out_repeated, std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* _aidl_return) = 0;
+  private:
+    static std::shared_ptr<IRepeatFixedSizeArray> default_impl;
+  };
+  class IRepeatFixedSizeArrayDefault : public IRepeatFixedSizeArray {
+  public:
+    ::ndk::ScopedAStatus RepeatBytes(const std::array<uint8_t, 3>& in_input, std::array<uint8_t, 3>* out_repeated, std::array<uint8_t, 3>* _aidl_return) override;
+    ::ndk::ScopedAStatus RepeatInts(const std::array<int32_t, 3>& in_input, std::array<int32_t, 3>* out_repeated, std::array<int32_t, 3>* _aidl_return) override;
+    ::ndk::ScopedAStatus RepeatBinders(const std::array<::ndk::SpAIBinder, 3>& in_input, std::array<::ndk::SpAIBinder, 3>* out_repeated, std::array<::ndk::SpAIBinder, 3>* _aidl_return) override;
+    ::ndk::ScopedAStatus RepeatParcelables(const std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>& in_input, std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* out_repeated, std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* _aidl_return) override;
+    ::ndk::ScopedAStatus Repeat2dBytes(const std::array<std::array<uint8_t, 3>, 2>& in_input, std::array<std::array<uint8_t, 3>, 2>* out_repeated, std::array<std::array<uint8_t, 3>, 2>* _aidl_return) override;
+    ::ndk::ScopedAStatus Repeat2dInts(const std::array<std::array<int32_t, 3>, 2>& in_input, std::array<std::array<int32_t, 3>, 2>* out_repeated, std::array<std::array<int32_t, 3>, 2>* _aidl_return) override;
+    ::ndk::ScopedAStatus Repeat2dBinders(const std::array<std::array<::ndk::SpAIBinder, 3>, 2>& in_input, std::array<std::array<::ndk::SpAIBinder, 3>, 2>* out_repeated, std::array<std::array<::ndk::SpAIBinder, 3>, 2>* _aidl_return) override;
+    ::ndk::ScopedAStatus Repeat2dParcelables(const std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>& in_input, std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* out_repeated, std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* _aidl_return) override;
+    ::ndk::SpAIBinder asBinder() override;
+    bool isRemote() override;
+  };
+  class BpRepeatFixedSizeArray : public ::ndk::BpCInterface<IRepeatFixedSizeArray> {
+  public:
+    explicit BpRepeatFixedSizeArray(const ::ndk::SpAIBinder& binder);
+    virtual ~BpRepeatFixedSizeArray();
+
+    ::ndk::ScopedAStatus RepeatBytes(const std::array<uint8_t, 3>& in_input, std::array<uint8_t, 3>* out_repeated, std::array<uint8_t, 3>* _aidl_return) override;
+    ::ndk::ScopedAStatus RepeatInts(const std::array<int32_t, 3>& in_input, std::array<int32_t, 3>* out_repeated, std::array<int32_t, 3>* _aidl_return) override;
+    ::ndk::ScopedAStatus RepeatBinders(const std::array<::ndk::SpAIBinder, 3>& in_input, std::array<::ndk::SpAIBinder, 3>* out_repeated, std::array<::ndk::SpAIBinder, 3>* _aidl_return) override;
+    ::ndk::ScopedAStatus RepeatParcelables(const std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>& in_input, std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* out_repeated, std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>* _aidl_return) override;
+    ::ndk::ScopedAStatus Repeat2dBytes(const std::array<std::array<uint8_t, 3>, 2>& in_input, std::array<std::array<uint8_t, 3>, 2>* out_repeated, std::array<std::array<uint8_t, 3>, 2>* _aidl_return) override;
+    ::ndk::ScopedAStatus Repeat2dInts(const std::array<std::array<int32_t, 3>, 2>& in_input, std::array<std::array<int32_t, 3>, 2>* out_repeated, std::array<std::array<int32_t, 3>, 2>* _aidl_return) override;
+    ::ndk::ScopedAStatus Repeat2dBinders(const std::array<std::array<::ndk::SpAIBinder, 3>, 2>& in_input, std::array<std::array<::ndk::SpAIBinder, 3>, 2>* out_repeated, std::array<std::array<::ndk::SpAIBinder, 3>, 2>* _aidl_return) override;
+    ::ndk::ScopedAStatus Repeat2dParcelables(const std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>& in_input, std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* out_repeated, std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 3>, 2>* _aidl_return) override;
+  };
+  class BnRepeatFixedSizeArray : public ::ndk::BnCInterface<IRepeatFixedSizeArray> {
+  public:
+    BnRepeatFixedSizeArray();
+    virtual ~BnRepeatFixedSizeArray();
+  protected:
+    ::ndk::SpAIBinder createBinder() override;
+  private:
+  };
+  enum class ByteEnum : int8_t {
+    A = 0,
+  };
+
+  enum class IntEnum : int32_t {
+    A = 0,
+  };
+
+  enum class LongEnum : int64_t {
+    A = 0L,
+  };
+
+  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:
+  };
+  std::array<std::array<int32_t, 3>, 2> int2x3 = {{{{1, 2, 3}}, {{4, 5, 6}}}};
+  std::array<bool, 2> boolArray = {{}};
+  std::array<uint8_t, 2> byteArray = {{}};
+  std::array<char16_t, 2> charArray = {{}};
+  std::array<int32_t, 2> intArray = {{}};
+  std::array<int64_t, 2> longArray = {{}};
+  std::array<float, 2> floatArray = {{}};
+  std::array<double, 2> doubleArray = {{}};
+  std::array<std::string, 2> stringArray = {{"hello", "world"}};
+  std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum, 2> byteEnumArray = {{}};
+  std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum, 2> intEnumArray = {{}};
+  std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum, 2> longEnumArray = {{}};
+  std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 2> parcelableArray = {{}};
+  std::array<std::array<bool, 2>, 2> boolMatrix = {{}};
+  std::array<std::array<uint8_t, 2>, 2> byteMatrix = {{}};
+  std::array<std::array<char16_t, 2>, 2> charMatrix = {{}};
+  std::array<std::array<int32_t, 2>, 2> intMatrix = {{}};
+  std::array<std::array<int64_t, 2>, 2> longMatrix = {{}};
+  std::array<std::array<float, 2>, 2> floatMatrix = {{}};
+  std::array<std::array<double, 2>, 2> doubleMatrix = {{}};
+  std::array<std::array<std::string, 2>, 2> stringMatrix = {{{{"hello", "world"}}, {{"Ciao", "mondo"}}}};
+  std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum, 2>, 2> byteEnumMatrix = {{}};
+  std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum, 2>, 2> intEnumMatrix = {{}};
+  std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum, 2>, 2> longEnumMatrix = {{}};
+  std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable, 2>, 2> parcelableMatrix = {{}};
+  std::optional<std::array<bool, 2>> boolNullableArray;
+  std::optional<std::array<uint8_t, 2>> byteNullableArray;
+  std::optional<std::array<char16_t, 2>> charNullableArray;
+  std::optional<std::array<int32_t, 2>> intNullableArray;
+  std::optional<std::array<int64_t, 2>> longNullableArray;
+  std::optional<std::array<float, 2>> floatNullableArray;
+  std::optional<std::array<double, 2>> doubleNullableArray;
+  std::optional<std::array<std::optional<std::string>, 2>> stringNullableArray = {{{"hello", "world"}}};
+  std::optional<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum, 2>> byteEnumNullableArray;
+  std::optional<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum, 2>> intEnumNullableArray;
+  std::optional<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum, 2>> longEnumNullableArray;
+  std::optional<std::array<::ndk::SpAIBinder, 2>> binderNullableArray;
+  std::optional<std::array<::ndk::ScopedFileDescriptor, 2>> pfdNullableArray;
+  std::optional<std::array<std::optional<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable>, 2>> parcelableNullableArray;
+  std::optional<std::array<std::shared_ptr<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IEmptyInterface>, 2>> interfaceNullableArray;
+  std::optional<std::array<std::array<bool, 2>, 2>> boolNullableMatrix;
+  std::optional<std::array<std::array<uint8_t, 2>, 2>> byteNullableMatrix;
+  std::optional<std::array<std::array<char16_t, 2>, 2>> charNullableMatrix;
+  std::optional<std::array<std::array<int32_t, 2>, 2>> intNullableMatrix;
+  std::optional<std::array<std::array<int64_t, 2>, 2>> longNullableMatrix;
+  std::optional<std::array<std::array<float, 2>, 2>> floatNullableMatrix;
+  std::optional<std::array<std::array<double, 2>, 2>> doubleNullableMatrix;
+  std::optional<std::array<std::array<std::optional<std::string>, 2>, 2>> stringNullableMatrix = {{{{{"hello", "world"}}, {{"Ciao", "mondo"}}}}};
+  std::optional<std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum, 2>, 2>> byteEnumNullableMatrix;
+  std::optional<std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum, 2>, 2>> intEnumNullableMatrix;
+  std::optional<std::array<std::array<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum, 2>, 2>> longEnumNullableMatrix;
+  std::optional<std::array<std::array<::ndk::SpAIBinder, 2>, 2>> binderNullableMatrix;
+  std::optional<std::array<std::array<::ndk::ScopedFileDescriptor, 2>, 2>> pfdNullableMatrix;
+  std::optional<std::array<std::array<std::optional<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntParcelable>, 2>, 2>> parcelableNullableMatrix;
+  std::optional<std::array<std::array<std::shared_ptr<::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IEmptyInterface>, 2>, 2>> interfaceNullableMatrix;
+
+  binder_status_t readFromParcel(const AParcel* parcel);
+  binder_status_t writeToParcel(AParcel* parcel) const;
+
+  inline bool operator!=(const FixedSizeArrayExample& rhs) const {
+    return std::tie(int2x3, boolArray, byteArray, charArray, intArray, longArray, floatArray, doubleArray, stringArray, byteEnumArray, intEnumArray, longEnumArray, parcelableArray, boolMatrix, byteMatrix, charMatrix, intMatrix, longMatrix, floatMatrix, doubleMatrix, stringMatrix, byteEnumMatrix, intEnumMatrix, longEnumMatrix, parcelableMatrix, boolNullableArray, byteNullableArray, charNullableArray, intNullableArray, longNullableArray, floatNullableArray, doubleNullableArray, stringNullableArray, byteEnumNullableArray, intEnumNullableArray, longEnumNullableArray, binderNullableArray, pfdNullableArray, parcelableNullableArray, interfaceNullableArray, boolNullableMatrix, byteNullableMatrix, charNullableMatrix, intNullableMatrix, longNullableMatrix, floatNullableMatrix, doubleNullableMatrix, stringNullableMatrix, byteEnumNullableMatrix, intEnumNullableMatrix, longEnumNullableMatrix, binderNullableMatrix, pfdNullableMatrix, parcelableNullableMatrix, interfaceNullableMatrix) != std::tie(rhs.int2x3, rhs.boolArray, rhs.byteArray, rhs.charArray, rhs.intArray, rhs.longArray, rhs.floatArray, rhs.doubleArray, rhs.stringArray, rhs.byteEnumArray, rhs.intEnumArray, rhs.longEnumArray, rhs.parcelableArray, rhs.boolMatrix, rhs.byteMatrix, rhs.charMatrix, rhs.intMatrix, rhs.longMatrix, rhs.floatMatrix, rhs.doubleMatrix, rhs.stringMatrix, rhs.byteEnumMatrix, rhs.intEnumMatrix, rhs.longEnumMatrix, rhs.parcelableMatrix, rhs.boolNullableArray, rhs.byteNullableArray, rhs.charNullableArray, rhs.intNullableArray, rhs.longNullableArray, rhs.floatNullableArray, rhs.doubleNullableArray, rhs.stringNullableArray, rhs.byteEnumNullableArray, rhs.intEnumNullableArray, rhs.longEnumNullableArray, rhs.binderNullableArray, rhs.pfdNullableArray, rhs.parcelableNullableArray, rhs.interfaceNullableArray, rhs.boolNullableMatrix, rhs.byteNullableMatrix, rhs.charNullableMatrix, rhs.intNullableMatrix, rhs.longNullableMatrix, rhs.floatNullableMatrix, rhs.doubleNullableMatrix, rhs.stringNullableMatrix, rhs.byteEnumNullableMatrix, rhs.intEnumNullableMatrix, rhs.longEnumNullableMatrix, rhs.binderNullableMatrix, rhs.pfdNullableMatrix, rhs.parcelableNullableMatrix, rhs.interfaceNullableMatrix);
+  }
+  inline bool operator<(const FixedSizeArrayExample& rhs) const {
+    return std::tie(int2x3, boolArray, byteArray, charArray, intArray, longArray, floatArray, doubleArray, stringArray, byteEnumArray, intEnumArray, longEnumArray, parcelableArray, boolMatrix, byteMatrix, charMatrix, intMatrix, longMatrix, floatMatrix, doubleMatrix, stringMatrix, byteEnumMatrix, intEnumMatrix, longEnumMatrix, parcelableMatrix, boolNullableArray, byteNullableArray, charNullableArray, intNullableArray, longNullableArray, floatNullableArray, doubleNullableArray, stringNullableArray, byteEnumNullableArray, intEnumNullableArray, longEnumNullableArray, binderNullableArray, pfdNullableArray, parcelableNullableArray, interfaceNullableArray, boolNullableMatrix, byteNullableMatrix, charNullableMatrix, intNullableMatrix, longNullableMatrix, floatNullableMatrix, doubleNullableMatrix, stringNullableMatrix, byteEnumNullableMatrix, intEnumNullableMatrix, longEnumNullableMatrix, binderNullableMatrix, pfdNullableMatrix, parcelableNullableMatrix, interfaceNullableMatrix) < std::tie(rhs.int2x3, rhs.boolArray, rhs.byteArray, rhs.charArray, rhs.intArray, rhs.longArray, rhs.floatArray, rhs.doubleArray, rhs.stringArray, rhs.byteEnumArray, rhs.intEnumArray, rhs.longEnumArray, rhs.parcelableArray, rhs.boolMatrix, rhs.byteMatrix, rhs.charMatrix, rhs.intMatrix, rhs.longMatrix, rhs.floatMatrix, rhs.doubleMatrix, rhs.stringMatrix, rhs.byteEnumMatrix, rhs.intEnumMatrix, rhs.longEnumMatrix, rhs.parcelableMatrix, rhs.boolNullableArray, rhs.byteNullableArray, rhs.charNullableArray, rhs.intNullableArray, rhs.longNullableArray, rhs.floatNullableArray, rhs.doubleNullableArray, rhs.stringNullableArray, rhs.byteEnumNullableArray, rhs.intEnumNullableArray, rhs.longEnumNullableArray, rhs.binderNullableArray, rhs.pfdNullableArray, rhs.parcelableNullableArray, rhs.interfaceNullableArray, rhs.boolNullableMatrix, rhs.byteNullableMatrix, rhs.charNullableMatrix, rhs.intNullableMatrix, rhs.longNullableMatrix, rhs.floatNullableMatrix, rhs.doubleNullableMatrix, rhs.stringNullableMatrix, rhs.byteEnumNullableMatrix, rhs.intEnumNullableMatrix, rhs.longEnumNullableMatrix, rhs.binderNullableMatrix, rhs.pfdNullableMatrix, rhs.parcelableNullableMatrix, rhs.interfaceNullableMatrix);
+  }
+  inline bool operator<=(const FixedSizeArrayExample& rhs) const {
+    return std::tie(int2x3, boolArray, byteArray, charArray, intArray, longArray, floatArray, doubleArray, stringArray, byteEnumArray, intEnumArray, longEnumArray, parcelableArray, boolMatrix, byteMatrix, charMatrix, intMatrix, longMatrix, floatMatrix, doubleMatrix, stringMatrix, byteEnumMatrix, intEnumMatrix, longEnumMatrix, parcelableMatrix, boolNullableArray, byteNullableArray, charNullableArray, intNullableArray, longNullableArray, floatNullableArray, doubleNullableArray, stringNullableArray, byteEnumNullableArray, intEnumNullableArray, longEnumNullableArray, binderNullableArray, pfdNullableArray, parcelableNullableArray, interfaceNullableArray, boolNullableMatrix, byteNullableMatrix, charNullableMatrix, intNullableMatrix, longNullableMatrix, floatNullableMatrix, doubleNullableMatrix, stringNullableMatrix, byteEnumNullableMatrix, intEnumNullableMatrix, longEnumNullableMatrix, binderNullableMatrix, pfdNullableMatrix, parcelableNullableMatrix, interfaceNullableMatrix) <= std::tie(rhs.int2x3, rhs.boolArray, rhs.byteArray, rhs.charArray, rhs.intArray, rhs.longArray, rhs.floatArray, rhs.doubleArray, rhs.stringArray, rhs.byteEnumArray, rhs.intEnumArray, rhs.longEnumArray, rhs.parcelableArray, rhs.boolMatrix, rhs.byteMatrix, rhs.charMatrix, rhs.intMatrix, rhs.longMatrix, rhs.floatMatrix, rhs.doubleMatrix, rhs.stringMatrix, rhs.byteEnumMatrix, rhs.intEnumMatrix, rhs.longEnumMatrix, rhs.parcelableMatrix, rhs.boolNullableArray, rhs.byteNullableArray, rhs.charNullableArray, rhs.intNullableArray, rhs.longNullableArray, rhs.floatNullableArray, rhs.doubleNullableArray, rhs.stringNullableArray, rhs.byteEnumNullableArray, rhs.intEnumNullableArray, rhs.longEnumNullableArray, rhs.binderNullableArray, rhs.pfdNullableArray, rhs.parcelableNullableArray, rhs.interfaceNullableArray, rhs.boolNullableMatrix, rhs.byteNullableMatrix, rhs.charNullableMatrix, rhs.intNullableMatrix, rhs.longNullableMatrix, rhs.floatNullableMatrix, rhs.doubleNullableMatrix, rhs.stringNullableMatrix, rhs.byteEnumNullableMatrix, rhs.intEnumNullableMatrix, rhs.longEnumNullableMatrix, rhs.binderNullableMatrix, rhs.pfdNullableMatrix, rhs.parcelableNullableMatrix, rhs.interfaceNullableMatrix);
+  }
+  inline bool operator==(const FixedSizeArrayExample& rhs) const {
+    return std::tie(int2x3, boolArray, byteArray, charArray, intArray, longArray, floatArray, doubleArray, stringArray, byteEnumArray, intEnumArray, longEnumArray, parcelableArray, boolMatrix, byteMatrix, charMatrix, intMatrix, longMatrix, floatMatrix, doubleMatrix, stringMatrix, byteEnumMatrix, intEnumMatrix, longEnumMatrix, parcelableMatrix, boolNullableArray, byteNullableArray, charNullableArray, intNullableArray, longNullableArray, floatNullableArray, doubleNullableArray, stringNullableArray, byteEnumNullableArray, intEnumNullableArray, longEnumNullableArray, binderNullableArray, pfdNullableArray, parcelableNullableArray, interfaceNullableArray, boolNullableMatrix, byteNullableMatrix, charNullableMatrix, intNullableMatrix, longNullableMatrix, floatNullableMatrix, doubleNullableMatrix, stringNullableMatrix, byteEnumNullableMatrix, intEnumNullableMatrix, longEnumNullableMatrix, binderNullableMatrix, pfdNullableMatrix, parcelableNullableMatrix, interfaceNullableMatrix) == std::tie(rhs.int2x3, rhs.boolArray, rhs.byteArray, rhs.charArray, rhs.intArray, rhs.longArray, rhs.floatArray, rhs.doubleArray, rhs.stringArray, rhs.byteEnumArray, rhs.intEnumArray, rhs.longEnumArray, rhs.parcelableArray, rhs.boolMatrix, rhs.byteMatrix, rhs.charMatrix, rhs.intMatrix, rhs.longMatrix, rhs.floatMatrix, rhs.doubleMatrix, rhs.stringMatrix, rhs.byteEnumMatrix, rhs.intEnumMatrix, rhs.longEnumMatrix, rhs.parcelableMatrix, rhs.boolNullableArray, rhs.byteNullableArray, rhs.charNullableArray, rhs.intNullableArray, rhs.longNullableArray, rhs.floatNullableArray, rhs.doubleNullableArray, rhs.stringNullableArray, rhs.byteEnumNullableArray, rhs.intEnumNullableArray, rhs.longEnumNullableArray, rhs.binderNullableArray, rhs.pfdNullableArray, rhs.parcelableNullableArray, rhs.interfaceNullableArray, rhs.boolNullableMatrix, rhs.byteNullableMatrix, rhs.charNullableMatrix, rhs.intNullableMatrix, rhs.longNullableMatrix, rhs.floatNullableMatrix, rhs.doubleNullableMatrix, rhs.stringNullableMatrix, rhs.byteEnumNullableMatrix, rhs.intEnumNullableMatrix, rhs.longEnumNullableMatrix, rhs.binderNullableMatrix, rhs.pfdNullableMatrix, rhs.parcelableNullableMatrix, rhs.interfaceNullableMatrix);
+  }
+  inline bool operator>(const FixedSizeArrayExample& rhs) const {
+    return std::tie(int2x3, boolArray, byteArray, charArray, intArray, longArray, floatArray, doubleArray, stringArray, byteEnumArray, intEnumArray, longEnumArray, parcelableArray, boolMatrix, byteMatrix, charMatrix, intMatrix, longMatrix, floatMatrix, doubleMatrix, stringMatrix, byteEnumMatrix, intEnumMatrix, longEnumMatrix, parcelableMatrix, boolNullableArray, byteNullableArray, charNullableArray, intNullableArray, longNullableArray, floatNullableArray, doubleNullableArray, stringNullableArray, byteEnumNullableArray, intEnumNullableArray, longEnumNullableArray, binderNullableArray, pfdNullableArray, parcelableNullableArray, interfaceNullableArray, boolNullableMatrix, byteNullableMatrix, charNullableMatrix, intNullableMatrix, longNullableMatrix, floatNullableMatrix, doubleNullableMatrix, stringNullableMatrix, byteEnumNullableMatrix, intEnumNullableMatrix, longEnumNullableMatrix, binderNullableMatrix, pfdNullableMatrix, parcelableNullableMatrix, interfaceNullableMatrix) > std::tie(rhs.int2x3, rhs.boolArray, rhs.byteArray, rhs.charArray, rhs.intArray, rhs.longArray, rhs.floatArray, rhs.doubleArray, rhs.stringArray, rhs.byteEnumArray, rhs.intEnumArray, rhs.longEnumArray, rhs.parcelableArray, rhs.boolMatrix, rhs.byteMatrix, rhs.charMatrix, rhs.intMatrix, rhs.longMatrix, rhs.floatMatrix, rhs.doubleMatrix, rhs.stringMatrix, rhs.byteEnumMatrix, rhs.intEnumMatrix, rhs.longEnumMatrix, rhs.parcelableMatrix, rhs.boolNullableArray, rhs.byteNullableArray, rhs.charNullableArray, rhs.intNullableArray, rhs.longNullableArray, rhs.floatNullableArray, rhs.doubleNullableArray, rhs.stringNullableArray, rhs.byteEnumNullableArray, rhs.intEnumNullableArray, rhs.longEnumNullableArray, rhs.binderNullableArray, rhs.pfdNullableArray, rhs.parcelableNullableArray, rhs.interfaceNullableArray, rhs.boolNullableMatrix, rhs.byteNullableMatrix, rhs.charNullableMatrix, rhs.intNullableMatrix, rhs.longNullableMatrix, rhs.floatNullableMatrix, rhs.doubleNullableMatrix, rhs.stringNullableMatrix, rhs.byteEnumNullableMatrix, rhs.intEnumNullableMatrix, rhs.longEnumNullableMatrix, rhs.binderNullableMatrix, rhs.pfdNullableMatrix, rhs.parcelableNullableMatrix, rhs.interfaceNullableMatrix);
+  }
+  inline bool operator>=(const FixedSizeArrayExample& rhs) const {
+    return std::tie(int2x3, boolArray, byteArray, charArray, intArray, longArray, floatArray, doubleArray, stringArray, byteEnumArray, intEnumArray, longEnumArray, parcelableArray, boolMatrix, byteMatrix, charMatrix, intMatrix, longMatrix, floatMatrix, doubleMatrix, stringMatrix, byteEnumMatrix, intEnumMatrix, longEnumMatrix, parcelableMatrix, boolNullableArray, byteNullableArray, charNullableArray, intNullableArray, longNullableArray, floatNullableArray, doubleNullableArray, stringNullableArray, byteEnumNullableArray, intEnumNullableArray, longEnumNullableArray, binderNullableArray, pfdNullableArray, parcelableNullableArray, interfaceNullableArray, boolNullableMatrix, byteNullableMatrix, charNullableMatrix, intNullableMatrix, longNullableMatrix, floatNullableMatrix, doubleNullableMatrix, stringNullableMatrix, byteEnumNullableMatrix, intEnumNullableMatrix, longEnumNullableMatrix, binderNullableMatrix, pfdNullableMatrix, parcelableNullableMatrix, interfaceNullableMatrix) >= std::tie(rhs.int2x3, rhs.boolArray, rhs.byteArray, rhs.charArray, rhs.intArray, rhs.longArray, rhs.floatArray, rhs.doubleArray, rhs.stringArray, rhs.byteEnumArray, rhs.intEnumArray, rhs.longEnumArray, rhs.parcelableArray, rhs.boolMatrix, rhs.byteMatrix, rhs.charMatrix, rhs.intMatrix, rhs.longMatrix, rhs.floatMatrix, rhs.doubleMatrix, rhs.stringMatrix, rhs.byteEnumMatrix, rhs.intEnumMatrix, rhs.longEnumMatrix, rhs.parcelableMatrix, rhs.boolNullableArray, rhs.byteNullableArray, rhs.charNullableArray, rhs.intNullableArray, rhs.longNullableArray, rhs.floatNullableArray, rhs.doubleNullableArray, rhs.stringNullableArray, rhs.byteEnumNullableArray, rhs.intEnumNullableArray, rhs.longEnumNullableArray, rhs.binderNullableArray, rhs.pfdNullableArray, rhs.parcelableNullableArray, rhs.interfaceNullableArray, rhs.boolNullableMatrix, rhs.byteNullableMatrix, rhs.charNullableMatrix, rhs.intNullableMatrix, rhs.longNullableMatrix, rhs.floatNullableMatrix, rhs.doubleNullableMatrix, rhs.stringNullableMatrix, rhs.byteEnumNullableMatrix, rhs.intEnumNullableMatrix, rhs.longEnumNullableMatrix, rhs.binderNullableMatrix, rhs.pfdNullableMatrix, rhs.parcelableNullableMatrix, rhs.interfaceNullableMatrix);
+  }
+
+  static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "FixedSizeArrayExample{";
+    os << "int2x3: " << ::android::internal::ToString(int2x3);
+    os << ", boolArray: " << ::android::internal::ToString(boolArray);
+    os << ", byteArray: " << ::android::internal::ToString(byteArray);
+    os << ", charArray: " << ::android::internal::ToString(charArray);
+    os << ", intArray: " << ::android::internal::ToString(intArray);
+    os << ", longArray: " << ::android::internal::ToString(longArray);
+    os << ", floatArray: " << ::android::internal::ToString(floatArray);
+    os << ", doubleArray: " << ::android::internal::ToString(doubleArray);
+    os << ", stringArray: " << ::android::internal::ToString(stringArray);
+    os << ", byteEnumArray: " << ::android::internal::ToString(byteEnumArray);
+    os << ", intEnumArray: " << ::android::internal::ToString(intEnumArray);
+    os << ", longEnumArray: " << ::android::internal::ToString(longEnumArray);
+    os << ", parcelableArray: " << ::android::internal::ToString(parcelableArray);
+    os << ", boolMatrix: " << ::android::internal::ToString(boolMatrix);
+    os << ", byteMatrix: " << ::android::internal::ToString(byteMatrix);
+    os << ", charMatrix: " << ::android::internal::ToString(charMatrix);
+    os << ", intMatrix: " << ::android::internal::ToString(intMatrix);
+    os << ", longMatrix: " << ::android::internal::ToString(longMatrix);
+    os << ", floatMatrix: " << ::android::internal::ToString(floatMatrix);
+    os << ", doubleMatrix: " << ::android::internal::ToString(doubleMatrix);
+    os << ", stringMatrix: " << ::android::internal::ToString(stringMatrix);
+    os << ", byteEnumMatrix: " << ::android::internal::ToString(byteEnumMatrix);
+    os << ", intEnumMatrix: " << ::android::internal::ToString(intEnumMatrix);
+    os << ", longEnumMatrix: " << ::android::internal::ToString(longEnumMatrix);
+    os << ", parcelableMatrix: " << ::android::internal::ToString(parcelableMatrix);
+    os << ", boolNullableArray: " << ::android::internal::ToString(boolNullableArray);
+    os << ", byteNullableArray: " << ::android::internal::ToString(byteNullableArray);
+    os << ", charNullableArray: " << ::android::internal::ToString(charNullableArray);
+    os << ", intNullableArray: " << ::android::internal::ToString(intNullableArray);
+    os << ", longNullableArray: " << ::android::internal::ToString(longNullableArray);
+    os << ", floatNullableArray: " << ::android::internal::ToString(floatNullableArray);
+    os << ", doubleNullableArray: " << ::android::internal::ToString(doubleNullableArray);
+    os << ", stringNullableArray: " << ::android::internal::ToString(stringNullableArray);
+    os << ", byteEnumNullableArray: " << ::android::internal::ToString(byteEnumNullableArray);
+    os << ", intEnumNullableArray: " << ::android::internal::ToString(intEnumNullableArray);
+    os << ", longEnumNullableArray: " << ::android::internal::ToString(longEnumNullableArray);
+    os << ", binderNullableArray: " << ::android::internal::ToString(binderNullableArray);
+    os << ", pfdNullableArray: " << ::android::internal::ToString(pfdNullableArray);
+    os << ", parcelableNullableArray: " << ::android::internal::ToString(parcelableNullableArray);
+    os << ", interfaceNullableArray: " << ::android::internal::ToString(interfaceNullableArray);
+    os << ", boolNullableMatrix: " << ::android::internal::ToString(boolNullableMatrix);
+    os << ", byteNullableMatrix: " << ::android::internal::ToString(byteNullableMatrix);
+    os << ", charNullableMatrix: " << ::android::internal::ToString(charNullableMatrix);
+    os << ", intNullableMatrix: " << ::android::internal::ToString(intNullableMatrix);
+    os << ", longNullableMatrix: " << ::android::internal::ToString(longNullableMatrix);
+    os << ", floatNullableMatrix: " << ::android::internal::ToString(floatNullableMatrix);
+    os << ", doubleNullableMatrix: " << ::android::internal::ToString(doubleNullableMatrix);
+    os << ", stringNullableMatrix: " << ::android::internal::ToString(stringNullableMatrix);
+    os << ", byteEnumNullableMatrix: " << ::android::internal::ToString(byteEnumNullableMatrix);
+    os << ", intEnumNullableMatrix: " << ::android::internal::ToString(intEnumNullableMatrix);
+    os << ", longEnumNullableMatrix: " << ::android::internal::ToString(longEnumNullableMatrix);
+    os << ", binderNullableMatrix: " << ::android::internal::ToString(binderNullableMatrix);
+    os << ", pfdNullableMatrix: " << ::android::internal::ToString(pfdNullableMatrix);
+    os << ", parcelableNullableMatrix: " << ::android::internal::ToString(parcelableNullableMatrix);
+    os << ", interfaceNullableMatrix: " << ::android::internal::ToString(interfaceNullableMatrix);
+    os << "}";
+    return os.str();
+  }
+};
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+[[nodiscard]] static inline std::string toString(FixedSizeArrayExample::ByteEnum val) {
+  switch(val) {
+  case FixedSizeArrayExample::ByteEnum::A:
+    return "A";
+  default:
+    return std::to_string(static_cast<int8_t>(val));
+  }
+}
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace ndk {
+namespace internal {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++17-extensions"
+template <>
+constexpr inline std::array<aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum, 1> enum_values<aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum> = {
+  aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::ByteEnum::A,
+};
+#pragma clang diagnostic pop
+}  // namespace internal
+}  // namespace ndk
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+[[nodiscard]] static inline std::string toString(FixedSizeArrayExample::IntEnum val) {
+  switch(val) {
+  case FixedSizeArrayExample::IntEnum::A:
+    return "A";
+  default:
+    return std::to_string(static_cast<int32_t>(val));
+  }
+}
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace ndk {
+namespace internal {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++17-extensions"
+template <>
+constexpr inline std::array<aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum, 1> enum_values<aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum> = {
+  aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::IntEnum::A,
+};
+#pragma clang diagnostic pop
+}  // namespace internal
+}  // namespace ndk
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace fixedsizearray {
+[[nodiscard]] static inline std::string toString(FixedSizeArrayExample::LongEnum val) {
+  switch(val) {
+  case FixedSizeArrayExample::LongEnum::A:
+    return "A";
+  default:
+    return std::to_string(static_cast<int64_t>(val));
+  }
+}
+}  // namespace fixedsizearray
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace ndk {
+namespace internal {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++17-extensions"
+template <>
+constexpr inline std::array<aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum, 1> enum_values<aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum> = {
+  aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::LongEnum::A,
+};
+#pragma clang diagnostic pop
+}  // namespace internal
+}  // namespace ndk
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp b/tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/timestamp
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp
copy to tests/golden_output/aidl-test-fixedsizearray-ndk-source/gen/timestamp
diff --git a/tests/golden_output/aidl-test-fixedsizearray-rust-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.rs b/tests/golden_output/aidl-test-fixedsizearray-rust-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.rs
new file mode 100644
index 0000000..88f2387
--- /dev/null
+++ b/tests/golden_output/aidl-test-fixedsizearray-rust-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.rs
@@ -0,0 +1,1070 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#[derive(Debug, PartialEq)]
+pub struct FixedSizeArrayExample {
+  pub int2x3: [[i32; 3]; 2],
+  pub boolArray: [bool; 2],
+  pub byteArray: [u8; 2],
+  pub charArray: [u16; 2],
+  pub intArray: [i32; 2],
+  pub longArray: [i64; 2],
+  pub floatArray: [f32; 2],
+  pub doubleArray: [f64; 2],
+  pub stringArray: [String; 2],
+  pub byteEnumArray: [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_8_ByteEnum; 2],
+  pub intEnumArray: [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_7_IntEnum; 2],
+  pub longEnumArray: [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_8_LongEnum; 2],
+  pub parcelableArray: [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 2],
+  pub boolMatrix: [[bool; 2]; 2],
+  pub byteMatrix: [[u8; 2]; 2],
+  pub charMatrix: [[u16; 2]; 2],
+  pub intMatrix: [[i32; 2]; 2],
+  pub longMatrix: [[i64; 2]; 2],
+  pub floatMatrix: [[f32; 2]; 2],
+  pub doubleMatrix: [[f64; 2]; 2],
+  pub stringMatrix: [[String; 2]; 2],
+  pub byteEnumMatrix: [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_8_ByteEnum; 2]; 2],
+  pub intEnumMatrix: [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_7_IntEnum; 2]; 2],
+  pub longEnumMatrix: [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_8_LongEnum; 2]; 2],
+  pub parcelableMatrix: [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 2]; 2],
+  pub boolNullableArray: Option<[bool; 2]>,
+  pub byteNullableArray: Option<[u8; 2]>,
+  pub charNullableArray: Option<[u16; 2]>,
+  pub intNullableArray: Option<[i32; 2]>,
+  pub longNullableArray: Option<[i64; 2]>,
+  pub floatNullableArray: Option<[f32; 2]>,
+  pub doubleNullableArray: Option<[f64; 2]>,
+  pub stringNullableArray: Option<[Option<String>; 2]>,
+  pub byteEnumNullableArray: Option<[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_8_ByteEnum; 2]>,
+  pub intEnumNullableArray: Option<[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_7_IntEnum; 2]>,
+  pub longEnumNullableArray: Option<[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_8_LongEnum; 2]>,
+  pub binderNullableArray: Option<[Option<binder::SpIBinder>; 2]>,
+  pub pfdNullableArray: Option<[Option<binder::ParcelFileDescriptor>; 2]>,
+  pub parcelableNullableArray: Option<[Option<crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable>; 2]>,
+  pub interfaceNullableArray: Option<[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_15_IEmptyInterface>>; 2]>,
+  pub boolNullableMatrix: Option<[[bool; 2]; 2]>,
+  pub byteNullableMatrix: Option<[[u8; 2]; 2]>,
+  pub charNullableMatrix: Option<[[u16; 2]; 2]>,
+  pub intNullableMatrix: Option<[[i32; 2]; 2]>,
+  pub longNullableMatrix: Option<[[i64; 2]; 2]>,
+  pub floatNullableMatrix: Option<[[f32; 2]; 2]>,
+  pub doubleNullableMatrix: Option<[[f64; 2]; 2]>,
+  pub stringNullableMatrix: Option<[[Option<String>; 2]; 2]>,
+  pub byteEnumNullableMatrix: Option<[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_8_ByteEnum; 2]; 2]>,
+  pub intEnumNullableMatrix: Option<[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_7_IntEnum; 2]; 2]>,
+  pub longEnumNullableMatrix: Option<[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_8_LongEnum; 2]; 2]>,
+  pub binderNullableMatrix: Option<[[Option<binder::SpIBinder>; 2]; 2]>,
+  pub pfdNullableMatrix: Option<[[Option<binder::ParcelFileDescriptor>; 2]; 2]>,
+  pub parcelableNullableMatrix: Option<[[Option<crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable>; 2]; 2]>,
+  pub interfaceNullableMatrix: Option<[[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_15_IEmptyInterface>>; 2]; 2]>,
+}
+impl Default for FixedSizeArrayExample {
+  fn default() -> Self {
+    Self {
+      int2x3: [[1, 2, 3], [4, 5, 6]],
+      boolArray: [Default::default(), Default::default()],
+      byteArray: [Default::default(), Default::default()],
+      charArray: [Default::default(), Default::default()],
+      intArray: [Default::default(), Default::default()],
+      longArray: [Default::default(), Default::default()],
+      floatArray: [Default::default(), Default::default()],
+      doubleArray: [Default::default(), Default::default()],
+      stringArray: ["hello".into(), "world".into()],
+      byteEnumArray: [Default::default(), Default::default()],
+      intEnumArray: [Default::default(), Default::default()],
+      longEnumArray: [Default::default(), Default::default()],
+      parcelableArray: [Default::default(), Default::default()],
+      boolMatrix: [[Default::default(), Default::default()], [Default::default(), Default::default()]],
+      byteMatrix: [[Default::default(), Default::default()], [Default::default(), Default::default()]],
+      charMatrix: [[Default::default(), Default::default()], [Default::default(), Default::default()]],
+      intMatrix: [[Default::default(), Default::default()], [Default::default(), Default::default()]],
+      longMatrix: [[Default::default(), Default::default()], [Default::default(), Default::default()]],
+      floatMatrix: [[Default::default(), Default::default()], [Default::default(), Default::default()]],
+      doubleMatrix: [[Default::default(), Default::default()], [Default::default(), Default::default()]],
+      stringMatrix: [["hello".into(), "world".into()], ["Ciao".into(), "mondo".into()]],
+      byteEnumMatrix: [[Default::default(), Default::default()], [Default::default(), Default::default()]],
+      intEnumMatrix: [[Default::default(), Default::default()], [Default::default(), Default::default()]],
+      longEnumMatrix: [[Default::default(), Default::default()], [Default::default(), Default::default()]],
+      parcelableMatrix: [[Default::default(), Default::default()], [Default::default(), Default::default()]],
+      boolNullableArray: Default::default(),
+      byteNullableArray: Default::default(),
+      charNullableArray: Default::default(),
+      intNullableArray: Default::default(),
+      longNullableArray: Default::default(),
+      floatNullableArray: Default::default(),
+      doubleNullableArray: Default::default(),
+      stringNullableArray: Some([Some("hello".into()), Some("world".into())]),
+      byteEnumNullableArray: Default::default(),
+      intEnumNullableArray: Default::default(),
+      longEnumNullableArray: Default::default(),
+      binderNullableArray: Default::default(),
+      pfdNullableArray: Default::default(),
+      parcelableNullableArray: Default::default(),
+      interfaceNullableArray: Default::default(),
+      boolNullableMatrix: Default::default(),
+      byteNullableMatrix: Default::default(),
+      charNullableMatrix: Default::default(),
+      intNullableMatrix: Default::default(),
+      longNullableMatrix: Default::default(),
+      floatNullableMatrix: Default::default(),
+      doubleNullableMatrix: Default::default(),
+      stringNullableMatrix: Some([[Some("hello".into()), Some("world".into())], [Some("Ciao".into()), Some("mondo".into())]]),
+      byteEnumNullableMatrix: Default::default(),
+      intEnumNullableMatrix: Default::default(),
+      longEnumNullableMatrix: Default::default(),
+      binderNullableMatrix: Default::default(),
+      pfdNullableMatrix: Default::default(),
+      parcelableNullableMatrix: Default::default(),
+      interfaceNullableMatrix: Default::default(),
+    }
+  }
+}
+impl binder::Parcelable for FixedSizeArrayExample {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_write(|subparcel| {
+      subparcel.write(&self.int2x3)?;
+      subparcel.write(&self.boolArray)?;
+      subparcel.write(&self.byteArray)?;
+      subparcel.write(&self.charArray)?;
+      subparcel.write(&self.intArray)?;
+      subparcel.write(&self.longArray)?;
+      subparcel.write(&self.floatArray)?;
+      subparcel.write(&self.doubleArray)?;
+      subparcel.write(&self.stringArray)?;
+      subparcel.write(&self.byteEnumArray)?;
+      subparcel.write(&self.intEnumArray)?;
+      subparcel.write(&self.longEnumArray)?;
+      subparcel.write(&self.parcelableArray)?;
+      subparcel.write(&self.boolMatrix)?;
+      subparcel.write(&self.byteMatrix)?;
+      subparcel.write(&self.charMatrix)?;
+      subparcel.write(&self.intMatrix)?;
+      subparcel.write(&self.longMatrix)?;
+      subparcel.write(&self.floatMatrix)?;
+      subparcel.write(&self.doubleMatrix)?;
+      subparcel.write(&self.stringMatrix)?;
+      subparcel.write(&self.byteEnumMatrix)?;
+      subparcel.write(&self.intEnumMatrix)?;
+      subparcel.write(&self.longEnumMatrix)?;
+      subparcel.write(&self.parcelableMatrix)?;
+      subparcel.write(&self.boolNullableArray)?;
+      subparcel.write(&self.byteNullableArray)?;
+      subparcel.write(&self.charNullableArray)?;
+      subparcel.write(&self.intNullableArray)?;
+      subparcel.write(&self.longNullableArray)?;
+      subparcel.write(&self.floatNullableArray)?;
+      subparcel.write(&self.doubleNullableArray)?;
+      subparcel.write(&self.stringNullableArray)?;
+      subparcel.write(&self.byteEnumNullableArray)?;
+      subparcel.write(&self.intEnumNullableArray)?;
+      subparcel.write(&self.longEnumNullableArray)?;
+      subparcel.write(&self.binderNullableArray)?;
+      subparcel.write(&self.pfdNullableArray)?;
+      subparcel.write(&self.parcelableNullableArray)?;
+      subparcel.write(&self.interfaceNullableArray)?;
+      subparcel.write(&self.boolNullableMatrix)?;
+      subparcel.write(&self.byteNullableMatrix)?;
+      subparcel.write(&self.charNullableMatrix)?;
+      subparcel.write(&self.intNullableMatrix)?;
+      subparcel.write(&self.longNullableMatrix)?;
+      subparcel.write(&self.floatNullableMatrix)?;
+      subparcel.write(&self.doubleNullableMatrix)?;
+      subparcel.write(&self.stringNullableMatrix)?;
+      subparcel.write(&self.byteEnumNullableMatrix)?;
+      subparcel.write(&self.intEnumNullableMatrix)?;
+      subparcel.write(&self.longEnumNullableMatrix)?;
+      subparcel.write(&self.binderNullableMatrix)?;
+      subparcel.write(&self.pfdNullableMatrix)?;
+      subparcel.write(&self.parcelableNullableMatrix)?;
+      subparcel.write(&self.interfaceNullableMatrix)?;
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      if subparcel.has_more_data() {
+        self.int2x3 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.boolArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.byteArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.charArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.intArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.longArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.floatArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.doubleArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.stringArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.byteEnumArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.intEnumArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.longEnumArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.parcelableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.boolMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.byteMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.charMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.intMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.longMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.floatMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.doubleMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.stringMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.byteEnumMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.intEnumMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.longEnumMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.parcelableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.boolNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.byteNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.charNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.intNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.longNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.floatNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.doubleNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.stringNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.byteEnumNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.intEnumNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.longEnumNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.binderNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.pfdNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.parcelableNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.interfaceNullableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.boolNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.byteNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.charNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.intNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.longNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.floatNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.doubleNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.stringNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.byteEnumNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.intEnumNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.longEnumNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.binderNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.pfdNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.parcelableNullableMatrix = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.interfaceNullableMatrix = subparcel.read()?;
+      }
+      Ok(())
+    })
+  }
+}
+binder::impl_serialize_for_parcelable!(FixedSizeArrayExample);
+binder::impl_deserialize_for_parcelable!(FixedSizeArrayExample);
+impl binder::binder_impl::ParcelableMetadata for FixedSizeArrayExample {
+  fn get_descriptor() -> &'static str { "android.aidl.fixedsizearray.FixedSizeArrayExample" }
+}
+pub mod IRepeatFixedSizeArray {
+  #![allow(non_upper_case_globals)]
+  #![allow(non_snake_case)]
+  #[allow(unused_imports)] use binder::binder_impl::IBinderInternal;
+  use binder::declare_binder_interface;
+  declare_binder_interface! {
+    IRepeatFixedSizeArray["android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray"] {
+      native: BnRepeatFixedSizeArray(on_transact),
+      proxy: BpRepeatFixedSizeArray {
+      },
+      async: IRepeatFixedSizeArrayAsync,
+    }
+  }
+  pub trait IRepeatFixedSizeArray: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray" }
+    fn RepeatBytes(&self, _arg_input: &[u8; 3], _arg_repeated: &mut [u8; 3]) -> binder::Result<[u8; 3]>;
+    fn RepeatInts(&self, _arg_input: &[i32; 3], _arg_repeated: &mut [i32; 3]) -> binder::Result<[i32; 3]>;
+    fn RepeatBinders(&self, _arg_input: &[binder::SpIBinder; 3], _arg_repeated: &mut [Option<binder::SpIBinder>; 3]) -> binder::Result<[binder::SpIBinder; 3]>;
+    fn RepeatParcelables(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3], _arg_repeated: &mut [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]) -> binder::Result<[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]>;
+    fn Repeat2dBytes(&self, _arg_input: &[[u8; 3]; 2], _arg_repeated: &mut [[u8; 3]; 2]) -> binder::Result<[[u8; 3]; 2]>;
+    fn Repeat2dInts(&self, _arg_input: &[[i32; 3]; 2], _arg_repeated: &mut [[i32; 3]; 2]) -> binder::Result<[[i32; 3]; 2]>;
+    fn Repeat2dBinders(&self, _arg_input: &[[binder::SpIBinder; 3]; 2], _arg_repeated: &mut [[Option<binder::SpIBinder>; 3]; 2]) -> binder::Result<[[binder::SpIBinder; 3]; 2]>;
+    fn Repeat2dParcelables(&self, _arg_input: &[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2], _arg_repeated: &mut [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]) -> binder::Result<[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]>;
+    fn getDefaultImpl() -> IRepeatFixedSizeArrayDefaultRef where Self: Sized {
+      DEFAULT_IMPL.lock().unwrap().clone()
+    }
+    fn setDefaultImpl(d: IRepeatFixedSizeArrayDefaultRef) -> IRepeatFixedSizeArrayDefaultRef where Self: Sized {
+      std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+    }
+  }
+  pub trait IRepeatFixedSizeArrayAsync<P>: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray" }
+    fn RepeatBytes<'a>(&'a self, _arg_input: &'a [u8; 3], _arg_repeated: &'a mut [u8; 3]) -> binder::BoxFuture<'a, binder::Result<[u8; 3]>>;
+    fn RepeatInts<'a>(&'a self, _arg_input: &'a [i32; 3], _arg_repeated: &'a mut [i32; 3]) -> binder::BoxFuture<'a, binder::Result<[i32; 3]>>;
+    fn RepeatBinders<'a>(&'a self, _arg_input: &'a [binder::SpIBinder; 3], _arg_repeated: &'a mut [Option<binder::SpIBinder>; 3]) -> binder::BoxFuture<'a, binder::Result<[binder::SpIBinder; 3]>>;
+    fn RepeatParcelables<'a>(&'a self, _arg_input: &'a [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3], _arg_repeated: &'a mut [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]) -> binder::BoxFuture<'a, binder::Result<[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]>>;
+    fn Repeat2dBytes<'a>(&'a self, _arg_input: &'a [[u8; 3]; 2], _arg_repeated: &'a mut [[u8; 3]; 2]) -> binder::BoxFuture<'a, binder::Result<[[u8; 3]; 2]>>;
+    fn Repeat2dInts<'a>(&'a self, _arg_input: &'a [[i32; 3]; 2], _arg_repeated: &'a mut [[i32; 3]; 2]) -> binder::BoxFuture<'a, binder::Result<[[i32; 3]; 2]>>;
+    fn Repeat2dBinders<'a>(&'a self, _arg_input: &'a [[binder::SpIBinder; 3]; 2], _arg_repeated: &'a mut [[Option<binder::SpIBinder>; 3]; 2]) -> binder::BoxFuture<'a, binder::Result<[[binder::SpIBinder; 3]; 2]>>;
+    fn Repeat2dParcelables<'a>(&'a self, _arg_input: &'a [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2], _arg_repeated: &'a mut [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]) -> binder::BoxFuture<'a, binder::Result<[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]>>;
+  }
+  #[::async_trait::async_trait]
+  pub trait IRepeatFixedSizeArrayAsyncServer: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray" }
+    async fn RepeatBytes(&self, _arg_input: &[u8; 3], _arg_repeated: &mut [u8; 3]) -> binder::Result<[u8; 3]>;
+    async fn RepeatInts(&self, _arg_input: &[i32; 3], _arg_repeated: &mut [i32; 3]) -> binder::Result<[i32; 3]>;
+    async fn RepeatBinders(&self, _arg_input: &[binder::SpIBinder; 3], _arg_repeated: &mut [Option<binder::SpIBinder>; 3]) -> binder::Result<[binder::SpIBinder; 3]>;
+    async fn RepeatParcelables(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3], _arg_repeated: &mut [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]) -> binder::Result<[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]>;
+    async fn Repeat2dBytes(&self, _arg_input: &[[u8; 3]; 2], _arg_repeated: &mut [[u8; 3]; 2]) -> binder::Result<[[u8; 3]; 2]>;
+    async fn Repeat2dInts(&self, _arg_input: &[[i32; 3]; 2], _arg_repeated: &mut [[i32; 3]; 2]) -> binder::Result<[[i32; 3]; 2]>;
+    async fn Repeat2dBinders(&self, _arg_input: &[[binder::SpIBinder; 3]; 2], _arg_repeated: &mut [[Option<binder::SpIBinder>; 3]; 2]) -> binder::Result<[[binder::SpIBinder; 3]; 2]>;
+    async fn Repeat2dParcelables(&self, _arg_input: &[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2], _arg_repeated: &mut [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]) -> binder::Result<[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]>;
+  }
+  impl BnRepeatFixedSizeArray {
+    /// Create a new async binder service.
+    pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn IRepeatFixedSizeArray>
+    where
+      T: IRepeatFixedSizeArrayAsyncServer + binder::Interface + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      struct Wrapper<T, R> {
+        _inner: T,
+        _rt: R,
+      }
+      impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+        fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+        fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+      }
+      impl<T, R> IRepeatFixedSizeArray for Wrapper<T, R>
+      where
+        T: IRepeatFixedSizeArrayAsyncServer + Send + Sync + 'static,
+        R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+      {
+        fn RepeatBytes(&self, _arg_input: &[u8; 3], _arg_repeated: &mut [u8; 3]) -> binder::Result<[u8; 3]> {
+          self._rt.block_on(self._inner.RepeatBytes(_arg_input, _arg_repeated))
+        }
+        fn RepeatInts(&self, _arg_input: &[i32; 3], _arg_repeated: &mut [i32; 3]) -> binder::Result<[i32; 3]> {
+          self._rt.block_on(self._inner.RepeatInts(_arg_input, _arg_repeated))
+        }
+        fn RepeatBinders(&self, _arg_input: &[binder::SpIBinder; 3], _arg_repeated: &mut [Option<binder::SpIBinder>; 3]) -> binder::Result<[binder::SpIBinder; 3]> {
+          self._rt.block_on(self._inner.RepeatBinders(_arg_input, _arg_repeated))
+        }
+        fn RepeatParcelables(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3], _arg_repeated: &mut [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]) -> binder::Result<[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]> {
+          self._rt.block_on(self._inner.RepeatParcelables(_arg_input, _arg_repeated))
+        }
+        fn Repeat2dBytes(&self, _arg_input: &[[u8; 3]; 2], _arg_repeated: &mut [[u8; 3]; 2]) -> binder::Result<[[u8; 3]; 2]> {
+          self._rt.block_on(self._inner.Repeat2dBytes(_arg_input, _arg_repeated))
+        }
+        fn Repeat2dInts(&self, _arg_input: &[[i32; 3]; 2], _arg_repeated: &mut [[i32; 3]; 2]) -> binder::Result<[[i32; 3]; 2]> {
+          self._rt.block_on(self._inner.Repeat2dInts(_arg_input, _arg_repeated))
+        }
+        fn Repeat2dBinders(&self, _arg_input: &[[binder::SpIBinder; 3]; 2], _arg_repeated: &mut [[Option<binder::SpIBinder>; 3]; 2]) -> binder::Result<[[binder::SpIBinder; 3]; 2]> {
+          self._rt.block_on(self._inner.Repeat2dBinders(_arg_input, _arg_repeated))
+        }
+        fn Repeat2dParcelables(&self, _arg_input: &[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2], _arg_repeated: &mut [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]) -> binder::Result<[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]> {
+          self._rt.block_on(self._inner.Repeat2dParcelables(_arg_input, _arg_repeated))
+        }
+      }
+      let wrapped = Wrapper { _inner: inner, _rt: rt };
+      Self::new_binder(wrapped, features)
+    }
+  }
+  pub trait IRepeatFixedSizeArrayDefault: Send + Sync {
+    fn RepeatBytes(&self, _arg_input: &[u8; 3], _arg_repeated: &mut [u8; 3]) -> binder::Result<[u8; 3]> {
+      Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+    }
+    fn RepeatInts(&self, _arg_input: &[i32; 3], _arg_repeated: &mut [i32; 3]) -> binder::Result<[i32; 3]> {
+      Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+    }
+    fn RepeatBinders(&self, _arg_input: &[binder::SpIBinder; 3], _arg_repeated: &mut [Option<binder::SpIBinder>; 3]) -> binder::Result<[binder::SpIBinder; 3]> {
+      Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+    }
+    fn RepeatParcelables(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3], _arg_repeated: &mut [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]) -> binder::Result<[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]> {
+      Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+    }
+    fn Repeat2dBytes(&self, _arg_input: &[[u8; 3]; 2], _arg_repeated: &mut [[u8; 3]; 2]) -> binder::Result<[[u8; 3]; 2]> {
+      Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+    }
+    fn Repeat2dInts(&self, _arg_input: &[[i32; 3]; 2], _arg_repeated: &mut [[i32; 3]; 2]) -> binder::Result<[[i32; 3]; 2]> {
+      Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+    }
+    fn Repeat2dBinders(&self, _arg_input: &[[binder::SpIBinder; 3]; 2], _arg_repeated: &mut [[Option<binder::SpIBinder>; 3]; 2]) -> binder::Result<[[binder::SpIBinder; 3]; 2]> {
+      Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+    }
+    fn Repeat2dParcelables(&self, _arg_input: &[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2], _arg_repeated: &mut [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]) -> binder::Result<[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]> {
+      Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+    }
+  }
+  pub mod transactions {
+    pub const RepeatBytes: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 0;
+    pub const RepeatInts: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 1;
+    pub const RepeatBinders: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 2;
+    pub const RepeatParcelables: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 3;
+    pub const Repeat2dBytes: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 4;
+    pub const Repeat2dInts: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 5;
+    pub const Repeat2dBinders: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 6;
+    pub const Repeat2dParcelables: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 7;
+  }
+  pub type IRepeatFixedSizeArrayDefaultRef = Option<std::sync::Arc<dyn IRepeatFixedSizeArrayDefault>>;
+  use lazy_static::lazy_static;
+  lazy_static! {
+    static ref DEFAULT_IMPL: std::sync::Mutex<IRepeatFixedSizeArrayDefaultRef> = std::sync::Mutex::new(None);
+  }
+  impl BpRepeatFixedSizeArray {
+    fn build_parcel_RepeatBytes(&self, _arg_input: &[u8; 3], _arg_repeated: &mut [u8; 3]) -> binder::Result<binder::binder_impl::Parcel> {
+      let mut aidl_data = self.binder.prepare_transact()?;
+      aidl_data.write(_arg_input)?;
+      Ok(aidl_data)
+    }
+    fn read_response_RepeatBytes(&self, _arg_input: &[u8; 3], _arg_repeated: &mut [u8; 3], _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<[u8; 3]> {
+      if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+        if let Some(_aidl_default_impl) = <Self as IRepeatFixedSizeArray>::getDefaultImpl() {
+          return _aidl_default_impl.RepeatBytes(_arg_input, _arg_repeated);
+        }
+      }
+      let _aidl_reply = _aidl_reply?;
+      let _aidl_status: binder::Status = _aidl_reply.read()?;
+      if !_aidl_status.is_ok() { return Err(_aidl_status); }
+      let _aidl_return: [u8; 3] = _aidl_reply.read()?;
+      _aidl_reply.read_onto(_arg_repeated)?;
+      Ok(_aidl_return)
+    }
+    fn build_parcel_RepeatInts(&self, _arg_input: &[i32; 3], _arg_repeated: &mut [i32; 3]) -> binder::Result<binder::binder_impl::Parcel> {
+      let mut aidl_data = self.binder.prepare_transact()?;
+      aidl_data.write(_arg_input)?;
+      Ok(aidl_data)
+    }
+    fn read_response_RepeatInts(&self, _arg_input: &[i32; 3], _arg_repeated: &mut [i32; 3], _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<[i32; 3]> {
+      if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+        if let Some(_aidl_default_impl) = <Self as IRepeatFixedSizeArray>::getDefaultImpl() {
+          return _aidl_default_impl.RepeatInts(_arg_input, _arg_repeated);
+        }
+      }
+      let _aidl_reply = _aidl_reply?;
+      let _aidl_status: binder::Status = _aidl_reply.read()?;
+      if !_aidl_status.is_ok() { return Err(_aidl_status); }
+      let _aidl_return: [i32; 3] = _aidl_reply.read()?;
+      _aidl_reply.read_onto(_arg_repeated)?;
+      Ok(_aidl_return)
+    }
+    fn build_parcel_RepeatBinders(&self, _arg_input: &[binder::SpIBinder; 3], _arg_repeated: &mut [Option<binder::SpIBinder>; 3]) -> binder::Result<binder::binder_impl::Parcel> {
+      let mut aidl_data = self.binder.prepare_transact()?;
+      aidl_data.write(_arg_input)?;
+      Ok(aidl_data)
+    }
+    fn read_response_RepeatBinders(&self, _arg_input: &[binder::SpIBinder; 3], _arg_repeated: &mut [Option<binder::SpIBinder>; 3], _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<[binder::SpIBinder; 3]> {
+      if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+        if let Some(_aidl_default_impl) = <Self as IRepeatFixedSizeArray>::getDefaultImpl() {
+          return _aidl_default_impl.RepeatBinders(_arg_input, _arg_repeated);
+        }
+      }
+      let _aidl_reply = _aidl_reply?;
+      let _aidl_status: binder::Status = _aidl_reply.read()?;
+      if !_aidl_status.is_ok() { return Err(_aidl_status); }
+      let _aidl_return: [binder::SpIBinder; 3] = _aidl_reply.read()?;
+      _aidl_reply.read_onto(_arg_repeated)?;
+      Ok(_aidl_return)
+    }
+    fn build_parcel_RepeatParcelables(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3], _arg_repeated: &mut [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]) -> binder::Result<binder::binder_impl::Parcel> {
+      let mut aidl_data = self.binder.prepare_transact()?;
+      aidl_data.write(_arg_input)?;
+      Ok(aidl_data)
+    }
+    fn read_response_RepeatParcelables(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3], _arg_repeated: &mut [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3], _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]> {
+      if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+        if let Some(_aidl_default_impl) = <Self as IRepeatFixedSizeArray>::getDefaultImpl() {
+          return _aidl_default_impl.RepeatParcelables(_arg_input, _arg_repeated);
+        }
+      }
+      let _aidl_reply = _aidl_reply?;
+      let _aidl_status: binder::Status = _aidl_reply.read()?;
+      if !_aidl_status.is_ok() { return Err(_aidl_status); }
+      let _aidl_return: [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3] = _aidl_reply.read()?;
+      _aidl_reply.read_onto(_arg_repeated)?;
+      Ok(_aidl_return)
+    }
+    fn build_parcel_Repeat2dBytes(&self, _arg_input: &[[u8; 3]; 2], _arg_repeated: &mut [[u8; 3]; 2]) -> binder::Result<binder::binder_impl::Parcel> {
+      let mut aidl_data = self.binder.prepare_transact()?;
+      aidl_data.write(_arg_input)?;
+      Ok(aidl_data)
+    }
+    fn read_response_Repeat2dBytes(&self, _arg_input: &[[u8; 3]; 2], _arg_repeated: &mut [[u8; 3]; 2], _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<[[u8; 3]; 2]> {
+      if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+        if let Some(_aidl_default_impl) = <Self as IRepeatFixedSizeArray>::getDefaultImpl() {
+          return _aidl_default_impl.Repeat2dBytes(_arg_input, _arg_repeated);
+        }
+      }
+      let _aidl_reply = _aidl_reply?;
+      let _aidl_status: binder::Status = _aidl_reply.read()?;
+      if !_aidl_status.is_ok() { return Err(_aidl_status); }
+      let _aidl_return: [[u8; 3]; 2] = _aidl_reply.read()?;
+      _aidl_reply.read_onto(_arg_repeated)?;
+      Ok(_aidl_return)
+    }
+    fn build_parcel_Repeat2dInts(&self, _arg_input: &[[i32; 3]; 2], _arg_repeated: &mut [[i32; 3]; 2]) -> binder::Result<binder::binder_impl::Parcel> {
+      let mut aidl_data = self.binder.prepare_transact()?;
+      aidl_data.write(_arg_input)?;
+      Ok(aidl_data)
+    }
+    fn read_response_Repeat2dInts(&self, _arg_input: &[[i32; 3]; 2], _arg_repeated: &mut [[i32; 3]; 2], _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<[[i32; 3]; 2]> {
+      if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+        if let Some(_aidl_default_impl) = <Self as IRepeatFixedSizeArray>::getDefaultImpl() {
+          return _aidl_default_impl.Repeat2dInts(_arg_input, _arg_repeated);
+        }
+      }
+      let _aidl_reply = _aidl_reply?;
+      let _aidl_status: binder::Status = _aidl_reply.read()?;
+      if !_aidl_status.is_ok() { return Err(_aidl_status); }
+      let _aidl_return: [[i32; 3]; 2] = _aidl_reply.read()?;
+      _aidl_reply.read_onto(_arg_repeated)?;
+      Ok(_aidl_return)
+    }
+    fn build_parcel_Repeat2dBinders(&self, _arg_input: &[[binder::SpIBinder; 3]; 2], _arg_repeated: &mut [[Option<binder::SpIBinder>; 3]; 2]) -> binder::Result<binder::binder_impl::Parcel> {
+      let mut aidl_data = self.binder.prepare_transact()?;
+      aidl_data.write(_arg_input)?;
+      Ok(aidl_data)
+    }
+    fn read_response_Repeat2dBinders(&self, _arg_input: &[[binder::SpIBinder; 3]; 2], _arg_repeated: &mut [[Option<binder::SpIBinder>; 3]; 2], _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<[[binder::SpIBinder; 3]; 2]> {
+      if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+        if let Some(_aidl_default_impl) = <Self as IRepeatFixedSizeArray>::getDefaultImpl() {
+          return _aidl_default_impl.Repeat2dBinders(_arg_input, _arg_repeated);
+        }
+      }
+      let _aidl_reply = _aidl_reply?;
+      let _aidl_status: binder::Status = _aidl_reply.read()?;
+      if !_aidl_status.is_ok() { return Err(_aidl_status); }
+      let _aidl_return: [[binder::SpIBinder; 3]; 2] = _aidl_reply.read()?;
+      _aidl_reply.read_onto(_arg_repeated)?;
+      Ok(_aidl_return)
+    }
+    fn build_parcel_Repeat2dParcelables(&self, _arg_input: &[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2], _arg_repeated: &mut [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]) -> binder::Result<binder::binder_impl::Parcel> {
+      let mut aidl_data = self.binder.prepare_transact()?;
+      aidl_data.write(_arg_input)?;
+      Ok(aidl_data)
+    }
+    fn read_response_Repeat2dParcelables(&self, _arg_input: &[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2], _arg_repeated: &mut [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2], _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]> {
+      if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+        if let Some(_aidl_default_impl) = <Self as IRepeatFixedSizeArray>::getDefaultImpl() {
+          return _aidl_default_impl.Repeat2dParcelables(_arg_input, _arg_repeated);
+        }
+      }
+      let _aidl_reply = _aidl_reply?;
+      let _aidl_status: binder::Status = _aidl_reply.read()?;
+      if !_aidl_status.is_ok() { return Err(_aidl_status); }
+      let _aidl_return: [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2] = _aidl_reply.read()?;
+      _aidl_reply.read_onto(_arg_repeated)?;
+      Ok(_aidl_return)
+    }
+  }
+  impl IRepeatFixedSizeArray for BpRepeatFixedSizeArray {
+    fn RepeatBytes(&self, _arg_input: &[u8; 3], _arg_repeated: &mut [u8; 3]) -> binder::Result<[u8; 3]> {
+      let _aidl_data = self.build_parcel_RepeatBytes(_arg_input, _arg_repeated)?;
+      let _aidl_reply = self.binder.submit_transact(transactions::RepeatBytes, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+      self.read_response_RepeatBytes(_arg_input, _arg_repeated, _aidl_reply)
+    }
+    fn RepeatInts(&self, _arg_input: &[i32; 3], _arg_repeated: &mut [i32; 3]) -> binder::Result<[i32; 3]> {
+      let _aidl_data = self.build_parcel_RepeatInts(_arg_input, _arg_repeated)?;
+      let _aidl_reply = self.binder.submit_transact(transactions::RepeatInts, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+      self.read_response_RepeatInts(_arg_input, _arg_repeated, _aidl_reply)
+    }
+    fn RepeatBinders(&self, _arg_input: &[binder::SpIBinder; 3], _arg_repeated: &mut [Option<binder::SpIBinder>; 3]) -> binder::Result<[binder::SpIBinder; 3]> {
+      let _aidl_data = self.build_parcel_RepeatBinders(_arg_input, _arg_repeated)?;
+      let _aidl_reply = self.binder.submit_transact(transactions::RepeatBinders, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+      self.read_response_RepeatBinders(_arg_input, _arg_repeated, _aidl_reply)
+    }
+    fn RepeatParcelables(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3], _arg_repeated: &mut [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]) -> binder::Result<[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]> {
+      let _aidl_data = self.build_parcel_RepeatParcelables(_arg_input, _arg_repeated)?;
+      let _aidl_reply = self.binder.submit_transact(transactions::RepeatParcelables, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+      self.read_response_RepeatParcelables(_arg_input, _arg_repeated, _aidl_reply)
+    }
+    fn Repeat2dBytes(&self, _arg_input: &[[u8; 3]; 2], _arg_repeated: &mut [[u8; 3]; 2]) -> binder::Result<[[u8; 3]; 2]> {
+      let _aidl_data = self.build_parcel_Repeat2dBytes(_arg_input, _arg_repeated)?;
+      let _aidl_reply = self.binder.submit_transact(transactions::Repeat2dBytes, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+      self.read_response_Repeat2dBytes(_arg_input, _arg_repeated, _aidl_reply)
+    }
+    fn Repeat2dInts(&self, _arg_input: &[[i32; 3]; 2], _arg_repeated: &mut [[i32; 3]; 2]) -> binder::Result<[[i32; 3]; 2]> {
+      let _aidl_data = self.build_parcel_Repeat2dInts(_arg_input, _arg_repeated)?;
+      let _aidl_reply = self.binder.submit_transact(transactions::Repeat2dInts, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+      self.read_response_Repeat2dInts(_arg_input, _arg_repeated, _aidl_reply)
+    }
+    fn Repeat2dBinders(&self, _arg_input: &[[binder::SpIBinder; 3]; 2], _arg_repeated: &mut [[Option<binder::SpIBinder>; 3]; 2]) -> binder::Result<[[binder::SpIBinder; 3]; 2]> {
+      let _aidl_data = self.build_parcel_Repeat2dBinders(_arg_input, _arg_repeated)?;
+      let _aidl_reply = self.binder.submit_transact(transactions::Repeat2dBinders, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+      self.read_response_Repeat2dBinders(_arg_input, _arg_repeated, _aidl_reply)
+    }
+    fn Repeat2dParcelables(&self, _arg_input: &[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2], _arg_repeated: &mut [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]) -> binder::Result<[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]> {
+      let _aidl_data = self.build_parcel_Repeat2dParcelables(_arg_input, _arg_repeated)?;
+      let _aidl_reply = self.binder.submit_transact(transactions::Repeat2dParcelables, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+      self.read_response_Repeat2dParcelables(_arg_input, _arg_repeated, _aidl_reply)
+    }
+  }
+  impl<P: binder::BinderAsyncPool> IRepeatFixedSizeArrayAsync<P> for BpRepeatFixedSizeArray {
+    fn RepeatBytes<'a>(&'a self, _arg_input: &'a [u8; 3], _arg_repeated: &'a mut [u8; 3]) -> binder::BoxFuture<'a, binder::Result<[u8; 3]>> {
+      let _aidl_data = match self.build_parcel_RepeatBytes(_arg_input, _arg_repeated) {
+        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::RepeatBytes, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+        move |_aidl_reply| async move {
+          self.read_response_RepeatBytes(_arg_input, _arg_repeated, _aidl_reply)
+        }
+      )
+    }
+    fn RepeatInts<'a>(&'a self, _arg_input: &'a [i32; 3], _arg_repeated: &'a mut [i32; 3]) -> binder::BoxFuture<'a, binder::Result<[i32; 3]>> {
+      let _aidl_data = match self.build_parcel_RepeatInts(_arg_input, _arg_repeated) {
+        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::RepeatInts, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+        move |_aidl_reply| async move {
+          self.read_response_RepeatInts(_arg_input, _arg_repeated, _aidl_reply)
+        }
+      )
+    }
+    fn RepeatBinders<'a>(&'a self, _arg_input: &'a [binder::SpIBinder; 3], _arg_repeated: &'a mut [Option<binder::SpIBinder>; 3]) -> binder::BoxFuture<'a, binder::Result<[binder::SpIBinder; 3]>> {
+      let _aidl_data = match self.build_parcel_RepeatBinders(_arg_input, _arg_repeated) {
+        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::RepeatBinders, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+        move |_aidl_reply| async move {
+          self.read_response_RepeatBinders(_arg_input, _arg_repeated, _aidl_reply)
+        }
+      )
+    }
+    fn RepeatParcelables<'a>(&'a self, _arg_input: &'a [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3], _arg_repeated: &'a mut [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]) -> binder::BoxFuture<'a, binder::Result<[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]>> {
+      let _aidl_data = match self.build_parcel_RepeatParcelables(_arg_input, _arg_repeated) {
+        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::RepeatParcelables, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+        move |_aidl_reply| async move {
+          self.read_response_RepeatParcelables(_arg_input, _arg_repeated, _aidl_reply)
+        }
+      )
+    }
+    fn Repeat2dBytes<'a>(&'a self, _arg_input: &'a [[u8; 3]; 2], _arg_repeated: &'a mut [[u8; 3]; 2]) -> binder::BoxFuture<'a, binder::Result<[[u8; 3]; 2]>> {
+      let _aidl_data = match self.build_parcel_Repeat2dBytes(_arg_input, _arg_repeated) {
+        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::Repeat2dBytes, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+        move |_aidl_reply| async move {
+          self.read_response_Repeat2dBytes(_arg_input, _arg_repeated, _aidl_reply)
+        }
+      )
+    }
+    fn Repeat2dInts<'a>(&'a self, _arg_input: &'a [[i32; 3]; 2], _arg_repeated: &'a mut [[i32; 3]; 2]) -> binder::BoxFuture<'a, binder::Result<[[i32; 3]; 2]>> {
+      let _aidl_data = match self.build_parcel_Repeat2dInts(_arg_input, _arg_repeated) {
+        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::Repeat2dInts, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+        move |_aidl_reply| async move {
+          self.read_response_Repeat2dInts(_arg_input, _arg_repeated, _aidl_reply)
+        }
+      )
+    }
+    fn Repeat2dBinders<'a>(&'a self, _arg_input: &'a [[binder::SpIBinder; 3]; 2], _arg_repeated: &'a mut [[Option<binder::SpIBinder>; 3]; 2]) -> binder::BoxFuture<'a, binder::Result<[[binder::SpIBinder; 3]; 2]>> {
+      let _aidl_data = match self.build_parcel_Repeat2dBinders(_arg_input, _arg_repeated) {
+        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::Repeat2dBinders, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+        move |_aidl_reply| async move {
+          self.read_response_Repeat2dBinders(_arg_input, _arg_repeated, _aidl_reply)
+        }
+      )
+    }
+    fn Repeat2dParcelables<'a>(&'a self, _arg_input: &'a [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2], _arg_repeated: &'a mut [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]) -> binder::BoxFuture<'a, binder::Result<[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]>> {
+      let _aidl_data = match self.build_parcel_Repeat2dParcelables(_arg_input, _arg_repeated) {
+        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::Repeat2dParcelables, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+        move |_aidl_reply| async move {
+          self.read_response_Repeat2dParcelables(_arg_input, _arg_repeated, _aidl_reply)
+        }
+      )
+    }
+  }
+  impl IRepeatFixedSizeArray for binder::binder_impl::Binder<BnRepeatFixedSizeArray> {
+    fn RepeatBytes(&self, _arg_input: &[u8; 3], _arg_repeated: &mut [u8; 3]) -> binder::Result<[u8; 3]> { self.0.RepeatBytes(_arg_input, _arg_repeated) }
+    fn RepeatInts(&self, _arg_input: &[i32; 3], _arg_repeated: &mut [i32; 3]) -> binder::Result<[i32; 3]> { self.0.RepeatInts(_arg_input, _arg_repeated) }
+    fn RepeatBinders(&self, _arg_input: &[binder::SpIBinder; 3], _arg_repeated: &mut [Option<binder::SpIBinder>; 3]) -> binder::Result<[binder::SpIBinder; 3]> { self.0.RepeatBinders(_arg_input, _arg_repeated) }
+    fn RepeatParcelables(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3], _arg_repeated: &mut [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]) -> binder::Result<[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]> { self.0.RepeatParcelables(_arg_input, _arg_repeated) }
+    fn Repeat2dBytes(&self, _arg_input: &[[u8; 3]; 2], _arg_repeated: &mut [[u8; 3]; 2]) -> binder::Result<[[u8; 3]; 2]> { self.0.Repeat2dBytes(_arg_input, _arg_repeated) }
+    fn Repeat2dInts(&self, _arg_input: &[[i32; 3]; 2], _arg_repeated: &mut [[i32; 3]; 2]) -> binder::Result<[[i32; 3]; 2]> { self.0.Repeat2dInts(_arg_input, _arg_repeated) }
+    fn Repeat2dBinders(&self, _arg_input: &[[binder::SpIBinder; 3]; 2], _arg_repeated: &mut [[Option<binder::SpIBinder>; 3]; 2]) -> binder::Result<[[binder::SpIBinder; 3]; 2]> { self.0.Repeat2dBinders(_arg_input, _arg_repeated) }
+    fn Repeat2dParcelables(&self, _arg_input: &[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2], _arg_repeated: &mut [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]) -> binder::Result<[[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2]> { self.0.Repeat2dParcelables(_arg_input, _arg_repeated) }
+  }
+  fn on_transact(_aidl_service: &dyn IRepeatFixedSizeArray, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
+    match _aidl_code {
+      transactions::RepeatBytes => {
+        let _arg_input: [u8; 3] = _aidl_data.read()?;
+        let mut _arg_repeated: [u8; 3] = Default::default();
+        let _aidl_return = _aidl_service.RepeatBytes(&_arg_input, &mut _arg_repeated);
+        match &_aidl_return {
+          Ok(_aidl_return) => {
+            _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+            _aidl_reply.write(_aidl_return)?;
+            _aidl_reply.write(&_arg_repeated)?;
+          }
+          Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+        }
+        Ok(())
+      }
+      transactions::RepeatInts => {
+        let _arg_input: [i32; 3] = _aidl_data.read()?;
+        let mut _arg_repeated: [i32; 3] = Default::default();
+        let _aidl_return = _aidl_service.RepeatInts(&_arg_input, &mut _arg_repeated);
+        match &_aidl_return {
+          Ok(_aidl_return) => {
+            _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+            _aidl_reply.write(_aidl_return)?;
+            _aidl_reply.write(&_arg_repeated)?;
+          }
+          Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+        }
+        Ok(())
+      }
+      transactions::RepeatBinders => {
+        let _arg_input: [binder::SpIBinder; 3] = _aidl_data.read()?;
+        let mut _arg_repeated: [Option<binder::SpIBinder>; 3] = Default::default();
+        let _aidl_return = _aidl_service.RepeatBinders(&_arg_input, &mut _arg_repeated);
+        match &_aidl_return {
+          Ok(_aidl_return) => {
+            _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+            _aidl_reply.write(_aidl_return)?;
+            _aidl_reply.write(&_arg_repeated)?;
+          }
+          Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+        }
+        Ok(())
+      }
+      transactions::RepeatParcelables => {
+        let _arg_input: [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3] = _aidl_data.read()?;
+        let mut _arg_repeated: [crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3] = Default::default();
+        let _aidl_return = _aidl_service.RepeatParcelables(&_arg_input, &mut _arg_repeated);
+        match &_aidl_return {
+          Ok(_aidl_return) => {
+            _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+            _aidl_reply.write(_aidl_return)?;
+            _aidl_reply.write(&_arg_repeated)?;
+          }
+          Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+        }
+        Ok(())
+      }
+      transactions::Repeat2dBytes => {
+        let _arg_input: [[u8; 3]; 2] = _aidl_data.read()?;
+        let mut _arg_repeated: [[u8; 3]; 2] = Default::default();
+        let _aidl_return = _aidl_service.Repeat2dBytes(&_arg_input, &mut _arg_repeated);
+        match &_aidl_return {
+          Ok(_aidl_return) => {
+            _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+            _aidl_reply.write(_aidl_return)?;
+            _aidl_reply.write(&_arg_repeated)?;
+          }
+          Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+        }
+        Ok(())
+      }
+      transactions::Repeat2dInts => {
+        let _arg_input: [[i32; 3]; 2] = _aidl_data.read()?;
+        let mut _arg_repeated: [[i32; 3]; 2] = Default::default();
+        let _aidl_return = _aidl_service.Repeat2dInts(&_arg_input, &mut _arg_repeated);
+        match &_aidl_return {
+          Ok(_aidl_return) => {
+            _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+            _aidl_reply.write(_aidl_return)?;
+            _aidl_reply.write(&_arg_repeated)?;
+          }
+          Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+        }
+        Ok(())
+      }
+      transactions::Repeat2dBinders => {
+        let _arg_input: [[binder::SpIBinder; 3]; 2] = _aidl_data.read()?;
+        let mut _arg_repeated: [[Option<binder::SpIBinder>; 3]; 2] = Default::default();
+        let _aidl_return = _aidl_service.Repeat2dBinders(&_arg_input, &mut _arg_repeated);
+        match &_aidl_return {
+          Ok(_aidl_return) => {
+            _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+            _aidl_reply.write(_aidl_return)?;
+            _aidl_reply.write(&_arg_repeated)?;
+          }
+          Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+        }
+        Ok(())
+      }
+      transactions::Repeat2dParcelables => {
+        let _arg_input: [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2] = _aidl_data.read()?;
+        let mut _arg_repeated: [[crate::mangled::_7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable; 3]; 2] = Default::default();
+        let _aidl_return = _aidl_service.Repeat2dParcelables(&_arg_input, &mut _arg_repeated);
+        match &_aidl_return {
+          Ok(_aidl_return) => {
+            _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+            _aidl_reply.write(_aidl_return)?;
+            _aidl_reply.write(&_arg_repeated)?;
+          }
+          Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+        }
+        Ok(())
+      }
+      _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+    }
+  }
+}
+pub mod ByteEnum {
+  #![allow(non_upper_case_globals)]
+  use binder::declare_binder_enum;
+  declare_binder_enum! {
+    ByteEnum : [i8; 1] {
+      A = 0,
+    }
+  }
+}
+pub mod IntEnum {
+  #![allow(non_upper_case_globals)]
+  use binder::declare_binder_enum;
+  declare_binder_enum! {
+    IntEnum : [i32; 1] {
+      A = 0,
+    }
+  }
+}
+pub mod LongEnum {
+  #![allow(non_upper_case_globals)]
+  use binder::declare_binder_enum;
+  declare_binder_enum! {
+    LongEnum : [i64; 1] {
+      A = 0,
+    }
+  }
+}
+pub mod IntParcelable {
+  #[derive(Debug, Clone, Copy, PartialEq)]
+  pub struct IntParcelable {
+    pub value: i32,
+  }
+  impl Default for IntParcelable {
+    fn default() -> Self {
+      Self {
+        value: 0,
+      }
+    }
+  }
+  impl binder::Parcelable for IntParcelable {
+    fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_write(|subparcel| {
+        subparcel.write(&self.value)?;
+        Ok(())
+      })
+    }
+    fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_read(|subparcel| {
+        if subparcel.has_more_data() {
+          self.value = subparcel.read()?;
+        }
+        Ok(())
+      })
+    }
+  }
+  binder::impl_serialize_for_parcelable!(IntParcelable);
+  binder::impl_deserialize_for_parcelable!(IntParcelable);
+  impl binder::binder_impl::ParcelableMetadata for IntParcelable {
+    fn get_descriptor() -> &'static str { "android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable" }
+  }
+}
+pub mod IEmptyInterface {
+  #![allow(non_upper_case_globals)]
+  #![allow(non_snake_case)]
+  #[allow(unused_imports)] use binder::binder_impl::IBinderInternal;
+  use binder::declare_binder_interface;
+  declare_binder_interface! {
+    IEmptyInterface["android.aidl.fixedsizearray.FixedSizeArrayExample.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.fixedsizearray.FixedSizeArrayExample.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.fixedsizearray.FixedSizeArrayExample.IEmptyInterface" }
+  }
+  #[::async_trait::async_trait]
+  pub trait IEmptyInterfaceAsyncServer: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.fixedsizearray.FixedSizeArrayExample.IEmptyInterface" }
+  }
+  impl BnEmptyInterface {
+    /// Create a new async binder service.
+    pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn IEmptyInterface>
+    where
+      T: IEmptyInterfaceAsyncServer + binder::Interface + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      struct Wrapper<T, R> {
+        _inner: T,
+        _rt: R,
+      }
+      impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+        fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+        fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+      }
+      impl<T, R> IEmptyInterface for Wrapper<T, R>
+      where
+        T: IEmptyInterfaceAsyncServer + Send + Sync + 'static,
+        R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+      {
+      }
+      let wrapped = Wrapper { _inner: inner, _rt: rt };
+      Self::new_binder(wrapped, features)
+    }
+  }
+  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_impl::Binder<BnEmptyInterface> {
+  }
+  fn on_transact(_aidl_service: &dyn IEmptyInterface, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
+    match _aidl_code {
+      _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+    }
+  }
+}
+pub(crate) mod mangled {
+ pub use super::FixedSizeArrayExample as _7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample;
+ pub use super::IRepeatFixedSizeArray::IRepeatFixedSizeArray as _7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_21_IRepeatFixedSizeArray;
+ pub use super::ByteEnum::ByteEnum as _7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_8_ByteEnum;
+ pub use super::IntEnum::IntEnum as _7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_7_IntEnum;
+ pub use super::LongEnum::LongEnum as _7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_8_LongEnum;
+ pub use super::IntParcelable::IntParcelable as _7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_13_IntParcelable;
+ pub use super::IEmptyInterface::IEmptyInterface as _7_android_4_aidl_14_fixedsizearray_21_FixedSizeArrayExample_15_IEmptyInterface;
+}
diff --git a/tests/golden_output/aidl-test-fixedsizearray-rust-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.rs.d b/tests/golden_output/aidl-test-fixedsizearray-rust-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.rs.d
new file mode 100644
index 0000000..5811cd6
--- /dev/null
+++ b/tests/golden_output/aidl-test-fixedsizearray-rust-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.rs.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-fixedsizearray-rust-source/gen/android/aidl/fixedsizearray/FixedSizeArrayExample.rs : \
+  system/tools/aidl/tests/android/aidl/fixedsizearray/FixedSizeArrayExample.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp b/tests/golden_output/aidl-test-fixedsizearray-rust-source/gen/timestamp
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp
copy to tests/golden_output/aidl-test-fixedsizearray-rust-source/gen/timestamp
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..1973f8f
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp
@@ -0,0 +1,453 @@
+#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;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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).writeOverParcel(_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;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      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).writeOverParcel(_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;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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/DeprecatedParcelable.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/DeprecatedParcelable.cpp
index ba4b15b..67142b9 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/DeprecatedParcelable.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/DeprecatedParcelable.cpp
@@ -1,22 +1,22 @@
 #include <android/aidl/tests/DeprecatedParcelable.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 ::android::status_t DeprecatedParcelable::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);
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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 DeprecatedParcelable::writeToParcel(::android::Parcel* _aidl_parcel) const {
   ::android::status_t _aidl_ret_status = ::android::OK;
   auto _aidl_start_pos = _aidl_parcel->dataPosition();
@@ -27,9 +27,6 @@
   _aidl_parcel->setDataPosition(_aidl_end_pos);
   return _aidl_ret_status;
 }
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp
new file mode 100644
index 0000000..73fca2c
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp
@@ -0,0 +1,283 @@
+#include <android/aidl/tests/FixedSize.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t FixedSize::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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 FixedSize::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/FixedSize.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t FixedSize::FixedParcelable::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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->readBool(&booleanValue);
+  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->readByte(&byteValue);
+  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->readChar(&charValue);
+  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->readInt32(&intValue);
+  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->readInt64(&longValue);
+  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->readFloat(&floatValue);
+  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->readDouble(&doubleValue);
+  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->readInt64(reinterpret_cast<int64_t *>(&enumValue));
+  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->readParcelable(&parcelableValue);
+  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 FixedSize::FixedParcelable::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->writeBool(booleanValue);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeByte(byteValue);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeChar(charValue);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeInt32(intValue);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeInt64(longValue);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeFloat(floatValue);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeDouble(doubleValue);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeInt64(static_cast<int64_t>(enumValue));
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelable(parcelableValue);
+  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/FixedSize.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t FixedSize::FixedUnion::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 booleanValue: {
+    bool _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readBool(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<bool>) {
+      set<booleanValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<booleanValue>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  case byteValue: {
+    int8_t _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readByte(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<int8_t>) {
+      set<byteValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<byteValue>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  case charValue: {
+    char16_t _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readChar(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<char16_t>) {
+      set<charValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<charValue>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  case intValue: {
+    int32_t _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readInt32(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<int32_t>) {
+      set<intValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<intValue>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  case longValue: {
+    int64_t _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readInt64(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<int64_t>) {
+      set<longValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<longValue>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  case floatValue: {
+    float _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readFloat(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<float>) {
+      set<floatValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<floatValue>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  case doubleValue: {
+    double _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readDouble(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<double>) {
+      set<doubleValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<doubleValue>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  case enumValue: {
+    ::android::aidl::tests::LongEnum _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readInt64(reinterpret_cast<int64_t *>(&_aidl_value))) != ::android::OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<::android::aidl::tests::LongEnum>) {
+      set<enumValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<enumValue>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  }
+  return ::android::BAD_VALUE;
+}
+::android::status_t FixedSize::FixedUnion::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 booleanValue: return _aidl_parcel->writeBool(get<booleanValue>());
+  case byteValue: return _aidl_parcel->writeByte(get<byteValue>());
+  case charValue: return _aidl_parcel->writeChar(get<charValue>());
+  case intValue: return _aidl_parcel->writeInt32(get<intValue>());
+  case longValue: return _aidl_parcel->writeInt64(get<longValue>());
+  case floatValue: return _aidl_parcel->writeFloat(get<floatValue>());
+  case doubleValue: return _aidl_parcel->writeDouble(get<doubleValue>());
+  case enumValue: return _aidl_parcel->writeInt64(static_cast<int64_t>(get<enumValue>()));
+  }
+  __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/FixedSize.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp.d
new file mode 100644
index 0000000..b564041
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/FixedSize.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/FixedSize.aidl \
+  system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/IDeprecated.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/IDeprecated.cpp
index 4adb4e7..8be09c2 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/IDeprecated.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/IDeprecated.cpp
@@ -1,18 +1,11 @@
 #include <android/aidl/tests/IDeprecated.h>
 #include <android/aidl/tests/BpDeprecated.h>
-
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(Deprecated, "android.aidl.tests.IDeprecated")
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 #include <android/aidl/tests/BpDeprecated.h>
 #include <android/aidl/tests/BnDeprecated.h>
@@ -20,9 +13,7 @@
 #include <android-base/macros.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
 
 BpDeprecated::BpDeprecated(const ::android::sp<::android::IBinder>& _aidl_impl)
@@ -30,18 +21,14 @@
 }
 
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 #include <android/aidl/tests/BnDeprecated.h>
 #include <binder/Parcel.h>
 #include <binder/Stability.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
 
 BnDeprecated::BnDeprecated()
@@ -62,7 +49,7 @@
   break;
   }
   if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
-    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeToParcel(_aidl_reply);
+    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeOverParcel(_aidl_reply);
   }
   return _aidl_ret_status;
 }
@@ -70,7 +57,5 @@
 #pragma clang diagnostic pop
 
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/INamedCallback.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/INamedCallback.cpp
index a1bb651..1bc05dd 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/INamedCallback.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/INamedCallback.cpp
@@ -1,18 +1,11 @@
 #include <android/aidl/tests/INamedCallback.h>
 #include <android/aidl/tests/BpNamedCallback.h>
-
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(NamedCallback, "android.aidl.tests.INamedCallback")
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 #include <android/aidl/tests/BpNamedCallback.h>
 #include <android/aidl/tests/BnNamedCallback.h>
@@ -20,9 +13,7 @@
 #include <android-base/macros.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
 
 BpNamedCallback::BpNamedCallback(const ::android::sp<::android::IBinder>& _aidl_impl)
@@ -63,18 +54,14 @@
 }
 
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 #include <android/aidl/tests/BnNamedCallback.h>
 #include <binder/Parcel.h>
 #include <binder/Stability.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
 
 BnNamedCallback::BnNamedCallback()
@@ -113,13 +100,11 @@
   break;
   }
   if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
-    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeToParcel(_aidl_reply);
+    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeOverParcel(_aidl_reply);
   }
   return _aidl_ret_status;
 }
 
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/INewName.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/INewName.cpp
index 7dcc44f..b308856 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/INewName.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/INewName.cpp
@@ -1,18 +1,11 @@
 #include <android/aidl/tests/INewName.h>
 #include <android/aidl/tests/BpNewName.h>
-
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(NewName, "android.aidl.tests.IOldName")
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 #include <android/aidl/tests/BpNewName.h>
 #include <android/aidl/tests/BnNewName.h>
@@ -20,9 +13,7 @@
 #include <android-base/macros.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
 
 BpNewName::BpNewName(const ::android::sp<::android::IBinder>& _aidl_impl)
@@ -63,18 +54,14 @@
 }
 
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 #include <android/aidl/tests/BnNewName.h>
 #include <binder/Parcel.h>
 #include <binder/Stability.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
 
 BnNewName::BnNewName()
@@ -113,13 +100,11 @@
   break;
   }
   if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
-    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeToParcel(_aidl_reply);
+    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeOverParcel(_aidl_reply);
   }
   return _aidl_ret_status;
 }
 
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/IOldName.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/IOldName.cpp
index 2988407..ee04a4e 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/IOldName.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/IOldName.cpp
@@ -1,18 +1,11 @@
 #include <android/aidl/tests/IOldName.h>
 #include <android/aidl/tests/BpOldName.h>
-
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(OldName, "android.aidl.tests.IOldName")
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 #include <android/aidl/tests/BpOldName.h>
 #include <android/aidl/tests/BnOldName.h>
@@ -20,9 +13,7 @@
 #include <android-base/macros.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
 
 BpOldName::BpOldName(const ::android::sp<::android::IBinder>& _aidl_impl)
@@ -63,18 +54,14 @@
 }
 
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 #include <android/aidl/tests/BnOldName.h>
 #include <binder/Parcel.h>
 #include <binder/Stability.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
 
 BnOldName::BnOldName()
@@ -113,13 +100,11 @@
   break;
   }
   if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
-    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeToParcel(_aidl_reply);
+    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeOverParcel(_aidl_reply);
   }
   return _aidl_ret_status;
 }
 
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
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 f3cd198..40264c0 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
@@ -1,33 +1,23 @@
 #include <android/aidl/tests/ITestService.h>
 #include <android/aidl/tests/BpTestService.h>
-
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(TestService, "android.aidl.tests.ITestService")
-
 const ::android::String16& ITestService::STRING_TEST_CONSTANT() {
   static const ::android::String16 value(::android::String16("foo"));
   return value;
 }
-
 const ::android::String16& ITestService::STRING_TEST_CONSTANT2() {
   static const ::android::String16 value(::android::String16("bar"));
   return value;
 }
-
 const ::std::string& ITestService::STRING_TEST_CONSTANT_UTF8() {
   static const ::std::string value("baz");
   return value;
 }
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 #include <android/aidl/tests/BpTestService.h>
 #include <android/aidl/tests/BnTestService.h>
@@ -35,9 +25,7 @@
 #include <android-base/macros.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
 
 BpTestService::BpTestService(const ::android::sp<::android::IBinder>& _aidl_impl)
@@ -1108,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;
   }
@@ -1139,6 +1127,246 @@
   return _aidl_status;
 }
 
+::android::binder::Status BpTestService::GetInterfaceArray(const ::std::vector<::android::String16>& names, ::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>* _aidl_return) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeString16Vector(names);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_GetInterfaceArray, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->GetInterfaceArray(names, _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_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpTestService::VerifyNamesWithInterfaceArray(const ::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>& services, const ::std::vector<::android::String16>& names, bool* _aidl_return) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeStrongBinderVector(services);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeString16Vector(names);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_VerifyNamesWithInterfaceArray, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->VerifyNamesWithInterfaceArray(services, names, _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.readBool(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpTestService::GetNullableInterfaceArray(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>* _aidl_return) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeString16Vector(names);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_GetNullableInterfaceArray, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->GetNullableInterfaceArray(names, _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_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpTestService::VerifyNamesWithNullableInterfaceArray(const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>& services, const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, bool* _aidl_return) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeStrongBinderVector(services);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeString16Vector(names);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_VerifyNamesWithNullableInterfaceArray, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->VerifyNamesWithNullableInterfaceArray(services, names, _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.readBool(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpTestService::GetInterfaceList(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>* _aidl_return) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeString16Vector(names);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_GetInterfaceList, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->GetInterfaceList(names, _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_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpTestService::VerifyNamesWithInterfaceList(const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>& services, const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, bool* _aidl_return) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeStrongBinderVector(services);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeString16Vector(names);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_VerifyNamesWithInterfaceList, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->VerifyNamesWithInterfaceList(services, names, _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.readBool(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
 ::android::binder::Status BpTestService::ReverseStringList(const ::std::vector<::android::String16>& input, ::std::vector<::android::String16>* repeated, ::std::vector<::android::String16>* _aidl_return) {
   ::android::Parcel _aidl_data;
   _aidl_data.markSensitive();
@@ -1527,7 +1755,7 @@
   return _aidl_status;
 }
 
-::android::binder::Status BpTestService::RepeatNullableParcelable(const ::std::optional<::android::aidl::tests::StructuredParcelable>& input, ::std::optional<::android::aidl::tests::StructuredParcelable>* _aidl_return) {
+::android::binder::Status BpTestService::RepeatNullableParcelable(const ::std::optional<::android::aidl::tests::ITestService::Empty>& input, ::std::optional<::android::aidl::tests::ITestService::Empty>* _aidl_return) {
   ::android::Parcel _aidl_data;
   _aidl_data.markSensitive();
   _aidl_data.markForBinder(remoteStrong());
@@ -1565,6 +1793,82 @@
   return _aidl_status;
 }
 
+::android::binder::Status BpTestService::RepeatNullableParcelableArray(const ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>& input, ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>* _aidl_return) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeParcelableVector(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_RepeatNullableParcelableArray, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->RepeatNullableParcelableArray(input, _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.readParcelableVector(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpTestService::RepeatNullableParcelableList(const ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>& input, ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>* _aidl_return) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeParcelableVector(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_RepeatNullableParcelableList, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->RepeatNullableParcelableList(input, _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.readParcelableVector(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
 ::android::binder::Status BpTestService::TakesAnIBinder(const ::android::sp<::android::IBinder>& input) {
   ::android::Parcel _aidl_data;
   _aidl_data.markSensitive();
@@ -1633,6 +1937,74 @@
   return _aidl_status;
 }
 
+::android::binder::Status BpTestService::TakesAnIBinderList(const ::std::vector<::android::sp<::android::IBinder>>& input) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeStrongBinderVector(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_TakesAnIBinderList, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->TakesAnIBinderList(input);
+  }
+  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_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpTestService::TakesANullableIBinderList(const ::std::optional<::std::vector<::android::sp<::android::IBinder>>>& input) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeStrongBinderVector(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_TakesANullableIBinderList, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->TakesANullableIBinderList(input);
+  }
+  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_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
 ::android::binder::Status BpTestService::RepeatUtf8CppString(const ::std::string& token, ::std::string* _aidl_return) {
   ::android::Parcel _aidl_data;
   _aidl_data.markSensitive();
@@ -1919,6 +2291,174 @@
   return _aidl_status;
 }
 
+::android::binder::Status BpTestService::RepeatExtendableParcelable(const ::android::aidl::tests::extension::ExtendableParcelable& ep, ::android::aidl::tests::extension::ExtendableParcelable* ep2) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeParcelable(ep);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_RepeatExtendableParcelable, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->RepeatExtendableParcelable(ep, ep2);
+  }
+  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.readParcelable(ep2);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpTestService::ReverseList(const ::android::aidl::tests::RecursiveList& list, ::android::aidl::tests::RecursiveList* _aidl_return) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeParcelable(list);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_ReverseList, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->ReverseList(list, _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.readParcelable(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpTestService::ReverseIBinderArray(const ::std::vector<::android::sp<::android::IBinder>>& input, ::std::vector<::android::sp<::android::IBinder>>* repeated, ::std::vector<::android::sp<::android::IBinder>>* _aidl_return) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeStrongBinderVector(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeVectorSize(*repeated);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_ReverseIBinderArray, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->ReverseIBinderArray(input, repeated, _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(repeated);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpTestService::ReverseNullableIBinderArray(const ::std::optional<::std::vector<::android::sp<::android::IBinder>>>& input, ::std::optional<::std::vector<::android::sp<::android::IBinder>>>* repeated, ::std::optional<::std::vector<::android::sp<::android::IBinder>>>* _aidl_return) {
+  ::android::Parcel _aidl_data;
+  _aidl_data.markSensitive();
+  _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.writeStrongBinderVector(input);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeVectorSize(*repeated);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnTestService::TRANSACTION_ReverseNullableIBinderArray, _aidl_data, &_aidl_reply, ::android::IBinder::FLAG_CLEAR_BUF);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ITestService::getDefaultImpl())) {
+     return ITestService::getDefaultImpl()->ReverseNullableIBinderArray(input, repeated, _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(repeated);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
 ::android::binder::Status BpTestService::GetOldNameInterface(::android::sp<::android::aidl::tests::IOldName>* _aidl_return) {
   ::android::Parcel _aidl_data;
   _aidl_data.markSensitive();
@@ -2056,18 +2596,14 @@
 }
 
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 #include <android/aidl/tests/BnTestService.h>
 #include <binder/Parcel.h>
 #include <binder/Stability.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
 
 BnTestService::BnTestService()
@@ -2093,6 +2629,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(UnimplementedMethod(in_arg, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2144,6 +2684,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatBoolean(in_token, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2170,6 +2714,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatByte(in_token, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2196,6 +2744,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatChar(in_token, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2222,6 +2774,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatInt(in_token, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2248,6 +2804,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatLong(in_token, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2274,6 +2834,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatFloat(in_token, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2300,6 +2864,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatDouble(in_token, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2326,6 +2894,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatString(in_token, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2352,6 +2924,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatByteEnum(in_token, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2378,6 +2954,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatIntEnum(in_token, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2404,6 +2984,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatLongEnum(in_token, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2435,6 +3019,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseBoolean(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2470,6 +3058,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseByte(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2505,6 +3097,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseChar(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2540,6 +3136,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseInt(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2575,6 +3175,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseLong(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2610,6 +3214,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseFloat(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2645,6 +3253,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseDouble(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2680,6 +3292,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseString(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2715,6 +3331,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseByteEnum(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2750,6 +3370,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseIntEnum(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2785,6 +3409,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseLongEnum(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2815,6 +3443,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(GetOtherTestService(in_name, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2823,7 +3455,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;
     }
@@ -2846,6 +3478,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(VerifyName(in_service, in_name, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2860,6 +3496,201 @@
     }
   }
   break;
+  case BnTestService::TRANSACTION_GetInterfaceArray:
+  {
+    ::std::vector<::android::String16> in_names;
+    ::std::vector<::android::sp<::android::aidl::tests::INamedCallback>> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readString16Vector(&in_names);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(GetInterfaceArray(in_names, &_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;
+    }
+  }
+  break;
+  case BnTestService::TRANSACTION_VerifyNamesWithInterfaceArray:
+  {
+    ::std::vector<::android::sp<::android::aidl::tests::INamedCallback>> in_services;
+    ::std::vector<::android::String16> in_names;
+    bool _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_services);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readString16Vector(&in_names);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(VerifyNamesWithInterfaceArray(in_services, in_names, &_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->writeBool(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnTestService::TRANSACTION_GetNullableInterfaceArray:
+  {
+    ::std::optional<::std::vector<::std::optional<::android::String16>>> in_names;
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readString16Vector(&in_names);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(GetNullableInterfaceArray(in_names, &_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;
+    }
+  }
+  break;
+  case BnTestService::TRANSACTION_VerifyNamesWithNullableInterfaceArray:
+  {
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>> in_services;
+    ::std::optional<::std::vector<::std::optional<::android::String16>>> in_names;
+    bool _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_services);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readString16Vector(&in_names);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(VerifyNamesWithNullableInterfaceArray(in_services, in_names, &_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->writeBool(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnTestService::TRANSACTION_GetInterfaceList:
+  {
+    ::std::optional<::std::vector<::std::optional<::android::String16>>> in_names;
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readString16Vector(&in_names);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(GetInterfaceList(in_names, &_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;
+    }
+  }
+  break;
+  case BnTestService::TRANSACTION_VerifyNamesWithInterfaceList:
+  {
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>> in_services;
+    ::std::optional<::std::vector<::std::optional<::android::String16>>> in_names;
+    bool _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_services);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readString16Vector(&in_names);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(VerifyNamesWithInterfaceList(in_services, in_names, &_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->writeBool(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
   case BnTestService::TRANSACTION_ReverseStringList:
   {
     ::std::vector<::android::String16> in_input;
@@ -2873,6 +3704,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseStringList(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2903,6 +3738,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatParcelFileDescriptor(in_read, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2934,6 +3773,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseParcelFileDescriptorArray(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2963,6 +3806,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ThrowServiceException(in_code));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -2985,6 +3832,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatNullableIntArray(in_input, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3011,6 +3862,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatNullableByteEnumArray(in_input, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3037,6 +3892,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatNullableIntEnumArray(in_input, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3063,6 +3922,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatNullableLongEnumArray(in_input, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3089,6 +3952,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatNullableString(in_input, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3115,6 +3982,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatNullableStringList(in_input, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3131,8 +4002,8 @@
   break;
   case BnTestService::TRANSACTION_RepeatNullableParcelable:
   {
-    ::std::optional<::android::aidl::tests::StructuredParcelable> in_input;
-    ::std::optional<::android::aidl::tests::StructuredParcelable> _aidl_return;
+    ::std::optional<::android::aidl::tests::ITestService::Empty> in_input;
+    ::std::optional<::android::aidl::tests::ITestService::Empty> _aidl_return;
     if (!(_aidl_data.checkInterface(this))) {
       _aidl_ret_status = ::android::BAD_TYPE;
       break;
@@ -3141,6 +4012,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatNullableParcelable(in_input, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3155,6 +4030,66 @@
     }
   }
   break;
+  case BnTestService::TRANSACTION_RepeatNullableParcelableArray:
+  {
+    ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>> in_input;
+    ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readParcelableVector(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(RepeatNullableParcelableArray(in_input, &_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->writeParcelableVector(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnTestService::TRANSACTION_RepeatNullableParcelableList:
+  {
+    ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>> in_input;
+    ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readParcelableVector(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(RepeatNullableParcelableList(in_input, &_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->writeParcelableVector(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
   case BnTestService::TRANSACTION_TakesAnIBinder:
   {
     ::android::sp<::android::IBinder> in_input;
@@ -3166,6 +4101,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(TakesAnIBinder(in_input));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3187,6 +4126,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(TakesANullableIBinder(in_input));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3197,6 +4140,56 @@
     }
   }
   break;
+  case BnTestService::TRANSACTION_TakesAnIBinderList:
+  {
+    ::std::vector<::android::sp<::android::IBinder>> in_input;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(TakesAnIBinderList(in_input));
+    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (!_aidl_status.isOk()) {
+      break;
+    }
+  }
+  break;
+  case BnTestService::TRANSACTION_TakesANullableIBinderList:
+  {
+    ::std::optional<::std::vector<::android::sp<::android::IBinder>>> in_input;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(TakesANullableIBinderList(in_input));
+    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (!_aidl_status.isOk()) {
+      break;
+    }
+  }
+  break;
   case BnTestService::TRANSACTION_RepeatUtf8CppString:
   {
     ::std::string in_token;
@@ -3209,6 +4202,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatUtf8CppString(in_token, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3235,6 +4232,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(RepeatNullableUtf8CppString(in_token, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3266,6 +4267,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseUtf8CppString(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3301,6 +4306,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseNullableUtf8CppString(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3332,6 +4341,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(ReverseUtf8CppStringList(in_input, &out_repeated, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3362,6 +4375,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(GetCallback(in_return_null, &_aidl_return));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3370,7 +4387,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;
     }
@@ -3387,6 +4404,10 @@
     if (((_aidl_ret_status) != (::android::OK))) {
       break;
     }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(FillOutStructuredParcelable(&in_parcel));
     _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
     if (((_aidl_ret_status) != (::android::OK))) {
@@ -3401,6 +4422,144 @@
     }
   }
   break;
+  case BnTestService::TRANSACTION_RepeatExtendableParcelable:
+  {
+    ::android::aidl::tests::extension::ExtendableParcelable in_ep;
+    ::android::aidl::tests::extension::ExtendableParcelable out_ep2;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readParcelable(&in_ep);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(RepeatExtendableParcelable(in_ep, &out_ep2));
+    _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->writeParcelable(out_ep2);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnTestService::TRANSACTION_ReverseList:
+  {
+    ::android::aidl::tests::RecursiveList in_list;
+    ::android::aidl::tests::RecursiveList _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readParcelable(&in_list);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(ReverseList(in_list, &_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->writeParcelable(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnTestService::TRANSACTION_ReverseIBinderArray:
+  {
+    ::std::vector<::android::sp<::android::IBinder>> in_input;
+    ::std::vector<::android::sp<::android::IBinder>> out_repeated;
+    ::std::vector<::android::sp<::android::IBinder>> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.resizeOutVector(&out_repeated);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(ReverseIBinderArray(in_input, &out_repeated, &_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_repeated);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnTestService::TRANSACTION_ReverseNullableIBinderArray:
+  {
+    ::std::optional<::std::vector<::android::sp<::android::IBinder>>> in_input;
+    ::std::optional<::std::vector<::android::sp<::android::IBinder>>> out_repeated;
+    ::std::optional<::std::vector<::android::sp<::android::IBinder>>> _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_input);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.resizeOutVector(&out_repeated);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(ReverseNullableIBinderArray(in_input, &out_repeated, &_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_repeated);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
   case BnTestService::TRANSACTION_GetOldNameInterface:
   {
     ::android::sp<::android::aidl::tests::IOldName> _aidl_return;
@@ -3416,7 +4575,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;
     }
@@ -3437,7 +4596,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;
     }
@@ -3492,7 +4651,7 @@
   break;
   }
   if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
-    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeToParcel(_aidl_reply);
+    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeOverParcel(_aidl_reply);
   }
   return _aidl_ret_status;
 }
@@ -3500,7 +4659,285 @@
 #pragma clang diagnostic pop
 
 }  // namespace tests
-
 }  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ITestService.h>
 
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t ITestService::Empty::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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 ITestService::Empty::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/ITestService.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t ITestService::CompilerChecks::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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(&binder);
+  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_binder);
+  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(&binder_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_binder_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(&binder_list);
+  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_binder_list);
+  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->readParcelable(&pfd);
+  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->readParcelable(&nullable_pfd);
+  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->readParcelableVector(&pfd_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->readParcelableVector(&nullable_pfd_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->readParcelableVector(&pfd_list);
+  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->readParcelableVector(&nullable_pfd_list);
+  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->readParcelable(&parcel);
+  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->readParcelable(&nullable_parcel);
+  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->readParcelableVector(&parcel_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->readParcelableVector(&nullable_parcel_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->readParcelableVector(&parcel_list);
+  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->readParcelableVector(&nullable_parcel_list);
+  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 ITestService::CompilerChecks::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(binder);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeStrongBinder(nullable_binder);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeStrongBinderVector(binder_array);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeStrongBinderVector(nullable_binder_array);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeStrongBinderVector(binder_list);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeStrongBinderVector(nullable_binder_list);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelable(pfd);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeNullableParcelable(nullable_pfd);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelableVector(pfd_array);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelableVector(nullable_pfd_array);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelableVector(pfd_list);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelableVector(nullable_pfd_list);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelable(parcel);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeNullableParcelable(nullable_parcel);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelableVector(parcel_array);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelableVector(nullable_parcel_array);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelableVector(parcel_list);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelableVector(nullable_parcel_list);
+  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
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ITestService.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ITestService.cpp.d
index a88d7b3..f82081e 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ITestService.cpp.d
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ITestService.cpp.d
@@ -7,4 +7,8 @@
   system/tools/aidl/tests/android/aidl/tests/IOldName.aidl \
   system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
   system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl \
-  system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl
+  system/tools/aidl/tests/android/aidl/tests/RecursiveList.aidl \
+  system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl \
+  system/tools/aidl/tests/android/aidl/tests/extension/ExtendableParcelable.aidl \
+  system/tools/aidl/tests/android/aidl/tests/ConstantExpressionEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/Union.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ListOfInterfaces.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ListOfInterfaces.cpp
new file mode 100644
index 0000000..7a0e43e
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ListOfInterfaces.cpp
@@ -0,0 +1,437 @@
+#include <android/aidl/tests/ListOfInterfaces.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t ListOfInterfaces::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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 ListOfInterfaces::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/ListOfInterfaces.h>
+#include <android/aidl/tests/ListOfInterfaces.h>
+namespace android {
+namespace aidl {
+namespace tests {
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE(ListOfInterfaces, EmptyInterface, "android.aidl.tests.ListOfInterfaces.IEmptyInterface")
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ListOfInterfaces.h>
+#include <android/aidl/tests/ListOfInterfaces.h>
+#include <binder/Parcel.h>
+#include <android-base/macros.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+
+ListOfInterfaces::BpEmptyInterface::BpEmptyInterface(const ::android::sp<::android::IBinder>& _aidl_impl)
+    : BpInterface<IEmptyInterface>(_aidl_impl){
+}
+
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ListOfInterfaces.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+
+ListOfInterfaces::BnEmptyInterface::BnEmptyInterface()
+{
+  ::android::internal::Stability::markCompilationUnit(this);
+}
+
+::android::status_t ListOfInterfaces::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).writeOverParcel(_aidl_reply);
+  }
+  return _aidl_ret_status;
+}
+
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ListOfInterfaces.h>
+#include <android/aidl/tests/ListOfInterfaces.h>
+namespace android {
+namespace aidl {
+namespace tests {
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE(ListOfInterfaces, MyInterface, "android.aidl.tests.ListOfInterfaces.IMyInterface")
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ListOfInterfaces.h>
+#include <android/aidl/tests/ListOfInterfaces.h>
+#include <binder/Parcel.h>
+#include <android-base/macros.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+
+ListOfInterfaces::BpMyInterface::BpMyInterface(const ::android::sp<::android::IBinder>& _aidl_impl)
+    : BpInterface<IMyInterface>(_aidl_impl){
+}
+
+::android::binder::Status ListOfInterfaces::BpMyInterface::methodWithInterfaces(const ::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>& iface, const ::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>& nullable_iface, const ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>& iface_list_in, ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* iface_list_out, ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* iface_list_inout, const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>& nullable_iface_list_in, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* nullable_iface_list_out, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* nullable_iface_list_inout, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::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_list_in);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeStrongBinderVector(*iface_list_inout);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeStrongBinderVector(nullable_iface_list_in);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeStrongBinderVector(*nullable_iface_list_inout);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(ListOfInterfaces::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_list_in, iface_list_out, iface_list_inout, nullable_iface_list_in, nullable_iface_list_out, nullable_iface_list_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_list_out);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readStrongBinderVector(iface_list_inout);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readStrongBinderVector(nullable_iface_list_out);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_reply.readStrongBinderVector(nullable_iface_list_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/ListOfInterfaces.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+
+ListOfInterfaces::BnMyInterface::BnMyInterface()
+{
+  ::android::internal::Stability::markCompilationUnit(this);
+}
+
+::android::status_t ListOfInterfaces::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::ListOfInterfaces::IEmptyInterface> in_iface;
+    ::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface> in_nullable_iface;
+    ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>> in_iface_list_in;
+    ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>> out_iface_list_out;
+    ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>> in_iface_list_inout;
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>> in_nullable_iface_list_in;
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>> out_nullable_iface_list_out;
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>> in_nullable_iface_list_inout;
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::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_list_in);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_iface_list_inout);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_nullable_iface_list_in);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinderVector(&in_nullable_iface_list_inout);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(methodWithInterfaces(in_iface, in_nullable_iface, in_iface_list_in, &out_iface_list_out, &in_iface_list_inout, in_nullable_iface_list_in, &out_nullable_iface_list_out, &in_nullable_iface_list_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_list_out);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeStrongBinderVector(in_iface_list_inout);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeStrongBinderVector(out_nullable_iface_list_out);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_reply->writeStrongBinderVector(in_nullable_iface_list_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).writeOverParcel(_aidl_reply);
+  }
+  return _aidl_ret_status;
+}
+
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/ListOfInterfaces.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t ListOfInterfaces::MyParcelable::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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_list);
+  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_list);
+  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 ListOfInterfaces::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_list);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeStrongBinderVector(nullable_iface_list);
+  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/ListOfInterfaces.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t ListOfInterfaces::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::ListOfInterfaces::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::ListOfInterfaces::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::ListOfInterfaces::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::ListOfInterfaces::IEmptyInterface>>) {
+      set<nullable_iface>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<nullable_iface>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  case iface_list: {
+    ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::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::ListOfInterfaces::IEmptyInterface>>>) {
+      set<iface_list>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<iface_list>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  case nullable_iface_list: {
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::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::ListOfInterfaces::IEmptyInterface>>>>) {
+      set<nullable_iface_list>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<nullable_iface_list>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  }
+  return ::android::BAD_VALUE;
+}
+::android::status_t ListOfInterfaces::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_list: return _aidl_parcel->writeStrongBinderVector(get<iface_list>());
+  case nullable_iface_list: return _aidl_parcel->writeStrongBinderVector(get<nullable_iface_list>());
+  }
+  __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/ListOfInterfaces.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ListOfInterfaces.cpp.d
new file mode 100644
index 0000000..9d79d56
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ListOfInterfaces.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/ListOfInterfaces.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/ListOfInterfaces.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/OtherParcelableForToString.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/OtherParcelableForToString.cpp
index d6a7d64..a47a1b6 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/OtherParcelableForToString.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/OtherParcelableForToString.cpp
@@ -1,17 +1,18 @@
 #include <android/aidl/tests/OtherParcelableForToString.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 ::android::status_t OtherParcelableForToString::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);
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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);
@@ -24,7 +25,6 @@
   _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
   return _aidl_ret_status;
 }
-
 ::android::status_t OtherParcelableForToString::writeToParcel(::android::Parcel* _aidl_parcel) const {
   ::android::status_t _aidl_ret_status = ::android::OK;
   auto _aidl_start_pos = _aidl_parcel->dataPosition();
@@ -39,9 +39,6 @@
   _aidl_parcel->setDataPosition(_aidl_end_pos);
   return _aidl_ret_status;
 }
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ParcelableForToString.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ParcelableForToString.cpp
index 7b40910..bd3bdc2 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ParcelableForToString.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ParcelableForToString.cpp
@@ -1,17 +1,18 @@
 #include <android/aidl/tests/ParcelableForToString.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 ::android::status_t ParcelableForToString::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);
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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);
@@ -200,7 +201,6 @@
   _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
   return _aidl_ret_status;
 }
-
 ::android::status_t ParcelableForToString::writeToParcel(::android::Parcel* _aidl_parcel) const {
   ::android::status_t _aidl_ret_status = ::android::OK;
   auto _aidl_start_pos = _aidl_parcel->dataPosition();
@@ -303,9 +303,6 @@
   _aidl_parcel->setDataPosition(_aidl_end_pos);
   return _aidl_ret_status;
 }
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ParcelableForToString.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ParcelableForToString.cpp.d
index 995e55a..4043fd1 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ParcelableForToString.cpp.d
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/ParcelableForToString.cpp.d
@@ -4,4 +4,7 @@
   system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
   system/tools/aidl/tests/android/aidl/tests/OtherParcelableForToString.aidl \
   system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl \
-  system/tools/aidl/tests/android/aidl/tests/Union.aidl
+  system/tools/aidl/tests/android/aidl/tests/Union.aidl \
+  system/tools/aidl/tests/android/aidl/tests/ByteEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/ConstantExpressionEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/RecursiveList.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/RecursiveList.cpp
new file mode 100644
index 0000000..e740ce3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/RecursiveList.cpp
@@ -0,0 +1,56 @@
+#include <android/aidl/tests/RecursiveList.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t RecursiveList::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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->readInt32(&value);
+  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->readParcelable(&next);
+  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 RecursiveList::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->writeInt32(value);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeNullableParcelable(next);
+  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
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/RecursiveList.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/RecursiveList.cpp.d
new file mode 100644
index 0000000..a0d1ffd
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/RecursiveList.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/RecursiveList.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/RecursiveList.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/StructuredParcelable.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/StructuredParcelable.cpp
index cc0f2f1..73d8eff 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/StructuredParcelable.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/StructuredParcelable.cpp
@@ -1,17 +1,18 @@
 #include <android/aidl/tests/StructuredParcelable.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 ::android::status_t StructuredParcelable::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);
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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);
@@ -281,6 +282,22 @@
     _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
     return _aidl_ret_status;
   }
+  _aidl_ret_status = _aidl_parcel->readParcelable(&empty);
+  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->readByteVector(&int8_1);
+  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->readInt32Vector(&int32_1);
   if (((_aidl_ret_status) != (::android::OK))) {
     return _aidl_ret_status;
@@ -440,7 +457,6 @@
   _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
   return _aidl_ret_status;
 }
-
 ::android::status_t StructuredParcelable::writeToParcel(::android::Parcel* _aidl_parcel) const {
   ::android::status_t _aidl_ret_status = ::android::OK;
   auto _aidl_start_pos = _aidl_parcel->dataPosition();
@@ -577,6 +593,14 @@
   if (((_aidl_ret_status) != (::android::OK))) {
     return _aidl_ret_status;
   }
+  _aidl_ret_status = _aidl_parcel->writeParcelable(empty);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeByteVector(int8_1);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
   _aidl_ret_status = _aidl_parcel->writeInt32Vector(int32_1);
   if (((_aidl_ret_status) != (::android::OK))) {
     return _aidl_ret_status;
@@ -663,9 +687,38 @@
   _aidl_parcel->setDataPosition(_aidl_end_pos);
   return _aidl_ret_status;
 }
-
 }  // namespace tests
-
 }  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/StructuredParcelable.h>
 
+namespace android {
+namespace aidl {
+namespace tests {
+::android::status_t StructuredParcelable::Empty::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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 StructuredParcelable::Empty::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
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/Union.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/Union.cpp
index 06a3f37..36b8670 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/Union.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/Union.cpp
@@ -1,16 +1,12 @@
 #include <android/aidl/tests/Union.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 const ::std::string& Union::S1() {
   static const ::std::string value("a string constant in union");
   return value;
 }
-
 ::android::status_t Union::readFromParcel(const ::android::Parcel* _aidl_parcel) {
   ::android::status_t _aidl_ret_status;
   int32_t _aidl_tag;
@@ -89,7 +85,6 @@
   }
   return ::android::BAD_VALUE;
 }
-
 ::android::status_t Union::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;
@@ -104,9 +99,6 @@
   }
   __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/UnionWithFd.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/UnionWithFd.cpp
index 5fb2ddf..1006527 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/UnionWithFd.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/UnionWithFd.cpp
@@ -1,11 +1,8 @@
 #include <android/aidl/tests/UnionWithFd.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 ::android::status_t UnionWithFd::readFromParcel(const ::android::Parcel* _aidl_parcel) {
   ::android::status_t _aidl_ret_status;
   int32_t _aidl_tag;
@@ -34,7 +31,6 @@
   }
   return ::android::BAD_VALUE;
 }
-
 ::android::status_t UnionWithFd::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;
@@ -44,9 +40,6 @@
   }
   __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/extension/ExtendableParcelable.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/ExtendableParcelable.cpp
new file mode 100644
index 0000000..7935b08
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/ExtendableParcelable.cpp
@@ -0,0 +1,94 @@
+#include <android/aidl/tests/extension/ExtendableParcelable.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+::android::status_t ExtendableParcelable::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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->readInt32(&a);
+  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->readUtf8FromUtf16(&b);
+  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->readParcelable(&ext);
+  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->readInt64(&c);
+  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->readParcelable(&ext2);
+  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 ExtendableParcelable::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->writeInt32(a);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeUtf8AsUtf16(b);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelable(ext);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeInt64(c);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelable(ext2);
+  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 extension
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/ExtendableParcelable.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/ExtendableParcelable.cpp.d
new file mode 100644
index 0000000..1fce902
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/ExtendableParcelable.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/ExtendableParcelable.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/extension/ExtendableParcelable.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt.cpp
new file mode 100644
index 0000000..b14a6ea
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt.cpp
@@ -0,0 +1,58 @@
+#include <android/aidl/tests/extension/MyExt.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+::android::status_t MyExt::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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->readInt32(&a);
+  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->readUtf8FromUtf16(&b);
+  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 MyExt::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->writeInt32(a);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeUtf8AsUtf16(b);
+  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 extension
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt.cpp.d
new file mode 100644
index 0000000..37e34d3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExt.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt2.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt2.cpp
new file mode 100644
index 0000000..ec5c592
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt2.cpp
@@ -0,0 +1,70 @@
+#include <android/aidl/tests/extension/MyExt2.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+::android::status_t MyExt2::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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->readInt32(&a);
+  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->readParcelable(&b);
+  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->readUtf8FromUtf16(&c);
+  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 MyExt2::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->writeInt32(a);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeParcelable(b);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeUtf8AsUtf16(c);
+  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 extension
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt2.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt2.cpp.d
new file mode 100644
index 0000000..1c9e164
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt2.cpp.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExt2.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExt2.aidl \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExt.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExtLike.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExtLike.cpp
new file mode 100644
index 0000000..373bb6d
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExtLike.cpp
@@ -0,0 +1,58 @@
+#include <android/aidl/tests/extension/MyExtLike.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+::android::status_t MyExtLike::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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->readInt32(&a);
+  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->readString16(&b);
+  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 MyExtLike::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->writeInt32(a);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  _aidl_ret_status = _aidl_parcel->writeString16(b);
+  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 extension
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExtLike.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExtLike.cpp.d
new file mode 100644
index 0000000..3181128
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExtLike.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/extension/MyExtLike.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExtLike.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/DeeplyNested.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/DeeplyNested.cpp
new file mode 100644
index 0000000..a44388d
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/DeeplyNested.cpp
@@ -0,0 +1,182 @@
+#include <android/aidl/tests/nested/DeeplyNested.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+::android::status_t DeeplyNested::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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 DeeplyNested::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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/nested/DeeplyNested.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+::android::status_t DeeplyNested::A::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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->readByte(reinterpret_cast<int8_t *>(&e));
+  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 DeeplyNested::A::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->writeByte(static_cast<int8_t>(e));
+  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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/nested/DeeplyNested.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+::android::status_t DeeplyNested::B::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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 DeeplyNested::B::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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/nested/DeeplyNested.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+::android::status_t DeeplyNested::B::C::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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 DeeplyNested::B::C::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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/nested/DeeplyNested.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+::android::status_t DeeplyNested::B::C::D::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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 DeeplyNested::B::C::D::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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/DeeplyNested.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/DeeplyNested.cpp.d
new file mode 100644
index 0000000..2b84190
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/DeeplyNested.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/DeeplyNested.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/nested/DeeplyNested.aidl
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
new file mode 100644
index 0000000..b775900
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/INestedService.cpp
@@ -0,0 +1,362 @@
+#include <android/aidl/tests/nested/INestedService.h>
+#include <android/aidl/tests/nested/BpNestedService.h>
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(NestedService, "android.aidl.tests.nested.INestedService")
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/nested/BpNestedService.h>
+#include <android/aidl/tests/nested/BnNestedService.h>
+#include <binder/Parcel.h>
+#include <android-base/macros.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+
+BpNestedService::BpNestedService(const ::android::sp<::android::IBinder>& _aidl_impl)
+    : BpInterface<INestedService>(_aidl_impl){
+}
+
+::android::binder::Status BpNestedService::flipStatus(const ::android::aidl::tests::nested::ParcelableWithNested& p, ::android::aidl::tests::nested::INestedService::Result* _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.writeParcelable(p);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnNestedService::TRANSACTION_flipStatus, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && INestedService::getDefaultImpl())) {
+     return INestedService::getDefaultImpl()->flipStatus(p, _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.readParcelable(_aidl_return);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpNestedService::flipStatusWithCallback(::android::aidl::tests::nested::ParcelableWithNested::Status status, const ::android::sp<::android::aidl::tests::nested::INestedService::ICallback>& cb) {
+  ::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.writeByte(static_cast<int8_t>(status));
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeStrongBinder(cb);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(BnNestedService::TRANSACTION_flipStatusWithCallback, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && INestedService::getDefaultImpl())) {
+     return INestedService::getDefaultImpl()->flipStatusWithCallback(status, cb);
+  }
+  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_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/nested/BnNestedService.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+
+BnNestedService::BnNestedService()
+{
+  ::android::internal::Stability::markCompilationUnit(this);
+}
+
+::android::status_t BnNestedService::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 BnNestedService::TRANSACTION_flipStatus:
+  {
+    ::android::aidl::tests::nested::ParcelableWithNested in_p;
+    ::android::aidl::tests::nested::INestedService::Result _aidl_return;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readParcelable(&in_p);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(flipStatus(in_p, &_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->writeParcelable(_aidl_return);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+  }
+  break;
+  case BnNestedService::TRANSACTION_flipStatusWithCallback:
+  {
+    ::android::aidl::tests::nested::ParcelableWithNested::Status in_status;
+    ::android::sp<::android::aidl::tests::nested::INestedService::ICallback> in_cb;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readByte(reinterpret_cast<int8_t *>(&in_status));
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readStrongBinder(&in_cb);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(flipStatusWithCallback(in_status, in_cb));
+    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (!_aidl_status.isOk()) {
+      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).writeOverParcel(_aidl_reply);
+  }
+  return _aidl_ret_status;
+}
+
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/nested/INestedService.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+::android::status_t INestedService::Result::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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->readByte(reinterpret_cast<int8_t *>(&status));
+  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 INestedService::Result::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->writeByte(static_cast<int8_t>(status));
+  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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/nested/INestedService.h>
+#include <android/aidl/tests/nested/INestedService.h>
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE(INestedService, Callback, "android.aidl.tests.nested.INestedService.ICallback")
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/nested/INestedService.h>
+#include <android/aidl/tests/nested/INestedService.h>
+#include <binder/Parcel.h>
+#include <android-base/macros.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+
+INestedService::BpCallback::BpCallback(const ::android::sp<::android::IBinder>& _aidl_impl)
+    : BpInterface<ICallback>(_aidl_impl){
+}
+
+::android::binder::Status INestedService::BpCallback::done(::android::aidl::tests::nested::ParcelableWithNested::Status status) {
+  ::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.writeByte(static_cast<int8_t>(status));
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(INestedService::BnCallback::TRANSACTION_done, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ICallback::getDefaultImpl())) {
+     return ICallback::getDefaultImpl()->done(status);
+  }
+  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_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/nested/INestedService.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+
+INestedService::BnCallback::BnCallback()
+{
+  ::android::internal::Stability::markCompilationUnit(this);
+}
+
+::android::status_t INestedService::BnCallback::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 BnCallback::TRANSACTION_done:
+  {
+    ::android::aidl::tests::nested::ParcelableWithNested::Status in_status;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    _aidl_ret_status = _aidl_data.readByte(reinterpret_cast<int8_t *>(&in_status));
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(done(in_status));
+    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (!_aidl_status.isOk()) {
+      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).writeOverParcel(_aidl_reply);
+  }
+  return _aidl_ret_status;
+}
+
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/INestedService.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/INestedService.cpp.d
new file mode 100644
index 0000000..54177d3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/INestedService.cpp.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/INestedService.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/nested/INestedService.aidl \
+  system/tools/aidl/tests/android/aidl/tests/nested/ParcelableWithNested.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp
new file mode 100644
index 0000000..94a515f
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp
@@ -0,0 +1,46 @@
+#include <android/aidl/tests/nested/ParcelableWithNested.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+::android::status_t ParcelableWithNested::readFromParcel(const ::android::Parcel* _aidl_parcel) {
+  ::android::status_t _aidl_ret_status = ::android::OK;
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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->readByte(reinterpret_cast<int8_t *>(&status));
+  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 ParcelableWithNested::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->writeByte(static_cast<int8_t>(status));
+  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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp.d
new file mode 100644
index 0000000..44c21f5
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/nested/ParcelableWithNested.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtected.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtected.cpp
new file mode 100644
index 0000000..44ad7e3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtected.cpp
@@ -0,0 +1,197 @@
+#include <android/aidl/tests/permission/IProtected.h>
+#include <android/aidl/tests/permission/BpProtected.h>
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(Protected, "android.aidl.tests.permission.IProtected")
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/permission/BpProtected.h>
+#include <android/aidl/tests/permission/BnProtected.h>
+#include <binder/Parcel.h>
+#include <android-base/macros.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+
+BpProtected::BpProtected(const ::android::sp<::android::IBinder>& _aidl_impl)
+    : BpInterface<IProtected>(_aidl_impl){
+}
+
+::android::binder::Status BpProtected::PermissionProtected() {
+  ::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 = remote()->transact(BnProtected::TRANSACTION_PermissionProtected, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IProtected::getDefaultImpl())) {
+     return IProtected::getDefaultImpl()->PermissionProtected();
+  }
+  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_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpProtected::MultiplePermissionsAll() {
+  ::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 = remote()->transact(BnProtected::TRANSACTION_MultiplePermissionsAll, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IProtected::getDefaultImpl())) {
+     return IProtected::getDefaultImpl()->MultiplePermissionsAll();
+  }
+  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_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpProtected::MultiplePermissionsAny() {
+  ::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 = remote()->transact(BnProtected::TRANSACTION_MultiplePermissionsAny, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IProtected::getDefaultImpl())) {
+     return IProtected::getDefaultImpl()->MultiplePermissionsAny();
+  }
+  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_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/permission/BnProtected.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+
+BnProtected::BnProtected()
+{
+  ::android::internal::Stability::markCompilationUnit(this);
+}
+
+::android::status_t BnProtected::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 BnProtected::TRANSACTION_PermissionProtected:
+  {
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    ::android::binder::Status _aidl_status(PermissionProtected());
+    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (!_aidl_status.isOk()) {
+      break;
+    }
+  }
+  break;
+  case BnProtected::TRANSACTION_MultiplePermissionsAll:
+  {
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    ::android::binder::Status _aidl_status(MultiplePermissionsAll());
+    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (!_aidl_status.isOk()) {
+      break;
+    }
+  }
+  break;
+  case BnProtected::TRANSACTION_MultiplePermissionsAny:
+  {
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    ::android::binder::Status _aidl_status(MultiplePermissionsAny());
+    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (!_aidl_status.isOk()) {
+      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).writeOverParcel(_aidl_reply);
+  }
+  return _aidl_ret_status;
+}
+
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtected.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtected.cpp.d
new file mode 100644
index 0000000..3fb3aee
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtected.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtected.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/permission/IProtected.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp
new file mode 100644
index 0000000..bd9fe9d
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp
@@ -0,0 +1,152 @@
+#include <android/aidl/tests/permission/IProtectedInterface.h>
+#include <android/aidl/tests/permission/BpProtectedInterface.h>
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(ProtectedInterface, "android.aidl.tests.permission.IProtectedInterface")
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/permission/BpProtectedInterface.h>
+#include <android/aidl/tests/permission/BnProtectedInterface.h>
+#include <binder/Parcel.h>
+#include <android-base/macros.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+
+BpProtectedInterface::BpProtectedInterface(const ::android::sp<::android::IBinder>& _aidl_impl)
+    : BpInterface<IProtectedInterface>(_aidl_impl){
+}
+
+::android::binder::Status BpProtectedInterface::Method1() {
+  ::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 = remote()->transact(BnProtectedInterface::TRANSACTION_Method1, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IProtectedInterface::getDefaultImpl())) {
+     return IProtectedInterface::getDefaultImpl()->Method1();
+  }
+  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_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+::android::binder::Status BpProtectedInterface::Method2() {
+  ::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 = remote()->transact(BnProtectedInterface::TRANSACTION_Method2, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && IProtectedInterface::getDefaultImpl())) {
+     return IProtectedInterface::getDefaultImpl()->Method2();
+  }
+  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_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  return _aidl_status;
+}
+
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/tests/permission/BnProtectedInterface.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+
+BnProtectedInterface::BnProtectedInterface()
+{
+  ::android::internal::Stability::markCompilationUnit(this);
+}
+
+::android::status_t BnProtectedInterface::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 BnProtectedInterface::TRANSACTION_Method1:
+  {
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    ::android::binder::Status _aidl_status(Method1());
+    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (!_aidl_status.isOk()) {
+      break;
+    }
+  }
+  break;
+  case BnProtectedInterface::TRANSACTION_Method2:
+  {
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    ::android::binder::Status _aidl_status(Method2());
+    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (!_aidl_status.isOk()) {
+      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).writeOverParcel(_aidl_reply);
+  }
+  return _aidl_ret_status;
+}
+
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp.d
new file mode 100644
index 0000000..1841b65
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/permission/IProtectedInterface.aidl
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/EnumUnion.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/EnumUnion.cpp
index 9c3493a..e780a45 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/EnumUnion.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/EnumUnion.cpp
@@ -1,13 +1,9 @@
 #include <android/aidl/tests/unions/EnumUnion.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 namespace unions {
-
 ::android::status_t EnumUnion::readFromParcel(const ::android::Parcel* _aidl_parcel) {
   ::android::status_t _aidl_ret_status;
   int32_t _aidl_tag;
@@ -36,7 +32,6 @@
   }
   return ::android::BAD_VALUE;
 }
-
 ::android::status_t EnumUnion::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;
@@ -46,11 +41,7 @@
   }
   __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
 }
-
 }  // namespace unions
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/UnionInUnion.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/UnionInUnion.cpp
index 8268de8..06f668e 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/UnionInUnion.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/UnionInUnion.cpp
@@ -1,13 +1,9 @@
 #include <android/aidl/tests/unions/UnionInUnion.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 namespace unions {
-
 ::android::status_t UnionInUnion::readFromParcel(const ::android::Parcel* _aidl_parcel) {
   ::android::status_t _aidl_ret_status;
   int32_t _aidl_tag;
@@ -36,7 +32,6 @@
   }
   return ::android::BAD_VALUE;
 }
-
 ::android::status_t UnionInUnion::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;
@@ -46,11 +41,7 @@
   }
   __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
 }
-
 }  // namespace unions
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/UnionInUnion.cpp.d b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/UnionInUnion.cpp.d
index 6df64b5..470d9ea 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/UnionInUnion.cpp.d
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/UnionInUnion.cpp.d
@@ -1,3 +1,5 @@
 out/soong/.intermediates/system/tools/aidl/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/UnionInUnion.cpp : \
   system/tools/aidl/tests/android/aidl/tests/unions/UnionInUnion.aidl \
-  system/tools/aidl/tests/android/aidl/tests/unions/EnumUnion.aidl
+  system/tools/aidl/tests/android/aidl/tests/unions/EnumUnion.aidl \
+  system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl
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..6932199
--- /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:
+  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>& /*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 ::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:
+    ::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;
+    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::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:
+    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)...);
+    }
+
+    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;
+    }
+
+    ::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
+  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();
+  }
+
+  ::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/BackendType.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BackendType.h
index a87dc2e..5fa2a29 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BackendType.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BackendType.h
@@ -6,18 +6,20 @@
 #include <string>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 enum class BackendType : int8_t {
   CPP = 0,
   JAVA = 1,
   NDK = 2,
   RUST = 3,
 };
-
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace aidl {
+namespace tests {
 [[nodiscard]] static inline std::string toString(BackendType val) {
   switch(val) {
   case BackendType::CPP:
@@ -32,16 +34,11 @@
     return std::to_string(static_cast<int8_t>(val));
   }
 }
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 namespace android {
-
 namespace internal {
-
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wc++17-extensions"
 template <>
@@ -52,7 +49,5 @@
   ::android::aidl::tests::BackendType::RUST,
 };
 #pragma clang diagnostic pop
-
 }  // namespace internal
-
 }  // 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/BnDeprecated.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnDeprecated.h
index fc82d8b..36f42ef 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnDeprecated.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnDeprecated.h
@@ -4,19 +4,21 @@
 #include <android/aidl/tests/IDeprecated.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class __attribute__((deprecated("test"))) BnDeprecated : public ::android::BnInterface<IDeprecated> {
 public:
   explicit BnDeprecated();
   ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
 };  // class BnDeprecated
 
+class __attribute__((deprecated("test"))) IDeprecatedDelegator : public BnDeprecated {
+public:
+  explicit IDeprecatedDelegator(::android::sp<IDeprecated> &impl) : _aidl_delegate(impl) {}
+
+private:
+  ::android::sp<IDeprecated> _aidl_delegate;
+};  // class IDeprecatedDelegator
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnFixedSize.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnFixedSize.h
new file mode 100644
index 0000000..ce72aa3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnFixedSize.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/BnListOfInterfaces.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnListOfInterfaces.h
new file mode 100644
index 0000000..ce72aa3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnListOfInterfaces.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/BnNamedCallback.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnNamedCallback.h
index 85c0443..4044de8 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnNamedCallback.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnNamedCallback.h
@@ -4,11 +4,8 @@
 #include <android/aidl/tests/INamedCallback.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class BnNamedCallback : public ::android::BnInterface<INamedCallback> {
 public:
   static constexpr uint32_t TRANSACTION_GetName = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
@@ -16,8 +13,16 @@
   ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
 };  // class BnNamedCallback
 
+class INamedCallbackDelegator : public BnNamedCallback {
+public:
+  explicit INamedCallbackDelegator(::android::sp<INamedCallback> &impl) : _aidl_delegate(impl) {}
+
+  ::android::binder::Status GetName(::android::String16* _aidl_return) override {
+    return _aidl_delegate->GetName(_aidl_return);
+  }
+private:
+  ::android::sp<INamedCallback> _aidl_delegate;
+};  // class INamedCallbackDelegator
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnNewName.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnNewName.h
index fecf1a6..0db6524 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnNewName.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnNewName.h
@@ -4,11 +4,8 @@
 #include <android/aidl/tests/INewName.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class BnNewName : public ::android::BnInterface<INewName> {
 public:
   static constexpr uint32_t TRANSACTION_RealName = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
@@ -16,8 +13,16 @@
   ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
 };  // class BnNewName
 
+class INewNameDelegator : public BnNewName {
+public:
+  explicit INewNameDelegator(::android::sp<INewName> &impl) : _aidl_delegate(impl) {}
+
+  ::android::binder::Status RealName(::android::String16* _aidl_return) override {
+    return _aidl_delegate->RealName(_aidl_return);
+  }
+private:
+  ::android::sp<INewName> _aidl_delegate;
+};  // class INewNameDelegator
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnOldName.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnOldName.h
index a0381ac..aa9e3b0 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnOldName.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnOldName.h
@@ -4,11 +4,8 @@
 #include <android/aidl/tests/IOldName.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class BnOldName : public ::android::BnInterface<IOldName> {
 public:
   static constexpr uint32_t TRANSACTION_RealName = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
@@ -16,8 +13,16 @@
   ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
 };  // class BnOldName
 
+class IOldNameDelegator : public BnOldName {
+public:
+  explicit IOldNameDelegator(::android::sp<IOldName> &impl) : _aidl_delegate(impl) {}
+
+  ::android::binder::Status RealName(::android::String16* _aidl_return) override {
+    return _aidl_delegate->RealName(_aidl_return);
+  }
+private:
+  ::android::sp<IOldName> _aidl_delegate;
+};  // class IOldNameDelegator
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnRecursiveList.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnRecursiveList.h
new file mode 100644
index 0000000..ce72aa3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnRecursiveList.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/BnTestService.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnTestService.h
index 7035616..2d2a864 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnTestService.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BnTestService.h
@@ -4,11 +4,8 @@
 #include <android/aidl/tests/ITestService.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class BnTestService : public ::android::BnInterface<ITestService> {
 public:
   static constexpr uint32_t TRANSACTION_UnimplementedMethod = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
@@ -38,36 +35,250 @@
   static constexpr uint32_t TRANSACTION_ReverseLongEnum = ::android::IBinder::FIRST_CALL_TRANSACTION + 24;
   static constexpr uint32_t TRANSACTION_GetOtherTestService = ::android::IBinder::FIRST_CALL_TRANSACTION + 25;
   static constexpr uint32_t TRANSACTION_VerifyName = ::android::IBinder::FIRST_CALL_TRANSACTION + 26;
-  static constexpr uint32_t TRANSACTION_ReverseStringList = ::android::IBinder::FIRST_CALL_TRANSACTION + 27;
-  static constexpr uint32_t TRANSACTION_RepeatParcelFileDescriptor = ::android::IBinder::FIRST_CALL_TRANSACTION + 28;
-  static constexpr uint32_t TRANSACTION_ReverseParcelFileDescriptorArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 29;
-  static constexpr uint32_t TRANSACTION_ThrowServiceException = ::android::IBinder::FIRST_CALL_TRANSACTION + 30;
-  static constexpr uint32_t TRANSACTION_RepeatNullableIntArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 31;
-  static constexpr uint32_t TRANSACTION_RepeatNullableByteEnumArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 32;
-  static constexpr uint32_t TRANSACTION_RepeatNullableIntEnumArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 33;
-  static constexpr uint32_t TRANSACTION_RepeatNullableLongEnumArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 34;
-  static constexpr uint32_t TRANSACTION_RepeatNullableString = ::android::IBinder::FIRST_CALL_TRANSACTION + 35;
-  static constexpr uint32_t TRANSACTION_RepeatNullableStringList = ::android::IBinder::FIRST_CALL_TRANSACTION + 36;
-  static constexpr uint32_t TRANSACTION_RepeatNullableParcelable = ::android::IBinder::FIRST_CALL_TRANSACTION + 37;
-  static constexpr uint32_t TRANSACTION_TakesAnIBinder = ::android::IBinder::FIRST_CALL_TRANSACTION + 38;
-  static constexpr uint32_t TRANSACTION_TakesANullableIBinder = ::android::IBinder::FIRST_CALL_TRANSACTION + 39;
-  static constexpr uint32_t TRANSACTION_RepeatUtf8CppString = ::android::IBinder::FIRST_CALL_TRANSACTION + 40;
-  static constexpr uint32_t TRANSACTION_RepeatNullableUtf8CppString = ::android::IBinder::FIRST_CALL_TRANSACTION + 41;
-  static constexpr uint32_t TRANSACTION_ReverseUtf8CppString = ::android::IBinder::FIRST_CALL_TRANSACTION + 42;
-  static constexpr uint32_t TRANSACTION_ReverseNullableUtf8CppString = ::android::IBinder::FIRST_CALL_TRANSACTION + 43;
-  static constexpr uint32_t TRANSACTION_ReverseUtf8CppStringList = ::android::IBinder::FIRST_CALL_TRANSACTION + 44;
-  static constexpr uint32_t TRANSACTION_GetCallback = ::android::IBinder::FIRST_CALL_TRANSACTION + 45;
-  static constexpr uint32_t TRANSACTION_FillOutStructuredParcelable = ::android::IBinder::FIRST_CALL_TRANSACTION + 46;
-  static constexpr uint32_t TRANSACTION_GetOldNameInterface = ::android::IBinder::FIRST_CALL_TRANSACTION + 47;
-  static constexpr uint32_t TRANSACTION_GetNewNameInterface = ::android::IBinder::FIRST_CALL_TRANSACTION + 48;
-  static constexpr uint32_t TRANSACTION_GetCppJavaTests = ::android::IBinder::FIRST_CALL_TRANSACTION + 49;
-  static constexpr uint32_t TRANSACTION_getBackendType = ::android::IBinder::FIRST_CALL_TRANSACTION + 50;
+  static constexpr uint32_t TRANSACTION_GetInterfaceArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 27;
+  static constexpr uint32_t TRANSACTION_VerifyNamesWithInterfaceArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 28;
+  static constexpr uint32_t TRANSACTION_GetNullableInterfaceArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 29;
+  static constexpr uint32_t TRANSACTION_VerifyNamesWithNullableInterfaceArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 30;
+  static constexpr uint32_t TRANSACTION_GetInterfaceList = ::android::IBinder::FIRST_CALL_TRANSACTION + 31;
+  static constexpr uint32_t TRANSACTION_VerifyNamesWithInterfaceList = ::android::IBinder::FIRST_CALL_TRANSACTION + 32;
+  static constexpr uint32_t TRANSACTION_ReverseStringList = ::android::IBinder::FIRST_CALL_TRANSACTION + 33;
+  static constexpr uint32_t TRANSACTION_RepeatParcelFileDescriptor = ::android::IBinder::FIRST_CALL_TRANSACTION + 34;
+  static constexpr uint32_t TRANSACTION_ReverseParcelFileDescriptorArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 35;
+  static constexpr uint32_t TRANSACTION_ThrowServiceException = ::android::IBinder::FIRST_CALL_TRANSACTION + 36;
+  static constexpr uint32_t TRANSACTION_RepeatNullableIntArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 37;
+  static constexpr uint32_t TRANSACTION_RepeatNullableByteEnumArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 38;
+  static constexpr uint32_t TRANSACTION_RepeatNullableIntEnumArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 39;
+  static constexpr uint32_t TRANSACTION_RepeatNullableLongEnumArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 40;
+  static constexpr uint32_t TRANSACTION_RepeatNullableString = ::android::IBinder::FIRST_CALL_TRANSACTION + 41;
+  static constexpr uint32_t TRANSACTION_RepeatNullableStringList = ::android::IBinder::FIRST_CALL_TRANSACTION + 42;
+  static constexpr uint32_t TRANSACTION_RepeatNullableParcelable = ::android::IBinder::FIRST_CALL_TRANSACTION + 43;
+  static constexpr uint32_t TRANSACTION_RepeatNullableParcelableArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 44;
+  static constexpr uint32_t TRANSACTION_RepeatNullableParcelableList = ::android::IBinder::FIRST_CALL_TRANSACTION + 45;
+  static constexpr uint32_t TRANSACTION_TakesAnIBinder = ::android::IBinder::FIRST_CALL_TRANSACTION + 46;
+  static constexpr uint32_t TRANSACTION_TakesANullableIBinder = ::android::IBinder::FIRST_CALL_TRANSACTION + 47;
+  static constexpr uint32_t TRANSACTION_TakesAnIBinderList = ::android::IBinder::FIRST_CALL_TRANSACTION + 48;
+  static constexpr uint32_t TRANSACTION_TakesANullableIBinderList = ::android::IBinder::FIRST_CALL_TRANSACTION + 49;
+  static constexpr uint32_t TRANSACTION_RepeatUtf8CppString = ::android::IBinder::FIRST_CALL_TRANSACTION + 50;
+  static constexpr uint32_t TRANSACTION_RepeatNullableUtf8CppString = ::android::IBinder::FIRST_CALL_TRANSACTION + 51;
+  static constexpr uint32_t TRANSACTION_ReverseUtf8CppString = ::android::IBinder::FIRST_CALL_TRANSACTION + 52;
+  static constexpr uint32_t TRANSACTION_ReverseNullableUtf8CppString = ::android::IBinder::FIRST_CALL_TRANSACTION + 53;
+  static constexpr uint32_t TRANSACTION_ReverseUtf8CppStringList = ::android::IBinder::FIRST_CALL_TRANSACTION + 54;
+  static constexpr uint32_t TRANSACTION_GetCallback = ::android::IBinder::FIRST_CALL_TRANSACTION + 55;
+  static constexpr uint32_t TRANSACTION_FillOutStructuredParcelable = ::android::IBinder::FIRST_CALL_TRANSACTION + 56;
+  static constexpr uint32_t TRANSACTION_RepeatExtendableParcelable = ::android::IBinder::FIRST_CALL_TRANSACTION + 57;
+  static constexpr uint32_t TRANSACTION_ReverseList = ::android::IBinder::FIRST_CALL_TRANSACTION + 58;
+  static constexpr uint32_t TRANSACTION_ReverseIBinderArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 59;
+  static constexpr uint32_t TRANSACTION_ReverseNullableIBinderArray = ::android::IBinder::FIRST_CALL_TRANSACTION + 60;
+  static constexpr uint32_t TRANSACTION_GetOldNameInterface = ::android::IBinder::FIRST_CALL_TRANSACTION + 61;
+  static constexpr uint32_t TRANSACTION_GetNewNameInterface = ::android::IBinder::FIRST_CALL_TRANSACTION + 62;
+  static constexpr uint32_t TRANSACTION_GetCppJavaTests = ::android::IBinder::FIRST_CALL_TRANSACTION + 63;
+  static constexpr uint32_t TRANSACTION_getBackendType = ::android::IBinder::FIRST_CALL_TRANSACTION + 64;
   explicit BnTestService();
   ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
 };  // class BnTestService
 
+class ITestServiceDelegator : public BnTestService {
+public:
+  explicit ITestServiceDelegator(::android::sp<ITestService> &impl) : _aidl_delegate(impl) {}
+
+  ::android::binder::Status UnimplementedMethod(int32_t arg, int32_t* _aidl_return) override {
+    return _aidl_delegate->UnimplementedMethod(arg, _aidl_return);
+  }
+  ::android::binder::Status Deprecated() override __attribute__((deprecated("to make sure we have something in system/tools/aidl which does a compile check of deprecated and make sure this is reflected in goldens"))) {
+    return _aidl_delegate->Deprecated();
+  }
+  ::android::binder::Status TestOneway() override {
+    return _aidl_delegate->TestOneway();
+  }
+  ::android::binder::Status RepeatBoolean(bool token, bool* _aidl_return) override {
+    return _aidl_delegate->RepeatBoolean(token, _aidl_return);
+  }
+  ::android::binder::Status RepeatByte(int8_t token, int8_t* _aidl_return) override {
+    return _aidl_delegate->RepeatByte(token, _aidl_return);
+  }
+  ::android::binder::Status RepeatChar(char16_t token, char16_t* _aidl_return) override {
+    return _aidl_delegate->RepeatChar(token, _aidl_return);
+  }
+  ::android::binder::Status RepeatInt(int32_t token, int32_t* _aidl_return) override {
+    return _aidl_delegate->RepeatInt(token, _aidl_return);
+  }
+  ::android::binder::Status RepeatLong(int64_t token, int64_t* _aidl_return) override {
+    return _aidl_delegate->RepeatLong(token, _aidl_return);
+  }
+  ::android::binder::Status RepeatFloat(float token, float* _aidl_return) override {
+    return _aidl_delegate->RepeatFloat(token, _aidl_return);
+  }
+  ::android::binder::Status RepeatDouble(double token, double* _aidl_return) override {
+    return _aidl_delegate->RepeatDouble(token, _aidl_return);
+  }
+  ::android::binder::Status RepeatString(const ::android::String16& token, ::android::String16* _aidl_return) override {
+    return _aidl_delegate->RepeatString(token, _aidl_return);
+  }
+  ::android::binder::Status RepeatByteEnum(::android::aidl::tests::ByteEnum token, ::android::aidl::tests::ByteEnum* _aidl_return) override {
+    return _aidl_delegate->RepeatByteEnum(token, _aidl_return);
+  }
+  ::android::binder::Status RepeatIntEnum(::android::aidl::tests::IntEnum token, ::android::aidl::tests::IntEnum* _aidl_return) override {
+    return _aidl_delegate->RepeatIntEnum(token, _aidl_return);
+  }
+  ::android::binder::Status RepeatLongEnum(::android::aidl::tests::LongEnum token, ::android::aidl::tests::LongEnum* _aidl_return) override {
+    return _aidl_delegate->RepeatLongEnum(token, _aidl_return);
+  }
+  ::android::binder::Status ReverseBoolean(const ::std::vector<bool>& input, ::std::vector<bool>* repeated, ::std::vector<bool>* _aidl_return) override {
+    return _aidl_delegate->ReverseBoolean(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ReverseByte(const ::std::vector<uint8_t>& input, ::std::vector<uint8_t>* repeated, ::std::vector<uint8_t>* _aidl_return) override {
+    return _aidl_delegate->ReverseByte(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ReverseChar(const ::std::vector<char16_t>& input, ::std::vector<char16_t>* repeated, ::std::vector<char16_t>* _aidl_return) override {
+    return _aidl_delegate->ReverseChar(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ReverseInt(const ::std::vector<int32_t>& input, ::std::vector<int32_t>* repeated, ::std::vector<int32_t>* _aidl_return) override {
+    return _aidl_delegate->ReverseInt(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ReverseLong(const ::std::vector<int64_t>& input, ::std::vector<int64_t>* repeated, ::std::vector<int64_t>* _aidl_return) override {
+    return _aidl_delegate->ReverseLong(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ReverseFloat(const ::std::vector<float>& input, ::std::vector<float>* repeated, ::std::vector<float>* _aidl_return) override {
+    return _aidl_delegate->ReverseFloat(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ReverseDouble(const ::std::vector<double>& input, ::std::vector<double>* repeated, ::std::vector<double>* _aidl_return) override {
+    return _aidl_delegate->ReverseDouble(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ReverseString(const ::std::vector<::android::String16>& input, ::std::vector<::android::String16>* repeated, ::std::vector<::android::String16>* _aidl_return) override {
+    return _aidl_delegate->ReverseString(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ReverseByteEnum(const ::std::vector<::android::aidl::tests::ByteEnum>& input, ::std::vector<::android::aidl::tests::ByteEnum>* repeated, ::std::vector<::android::aidl::tests::ByteEnum>* _aidl_return) override {
+    return _aidl_delegate->ReverseByteEnum(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ReverseIntEnum(const ::std::vector<::android::aidl::tests::IntEnum>& input, ::std::vector<::android::aidl::tests::IntEnum>* repeated, ::std::vector<::android::aidl::tests::IntEnum>* _aidl_return) override {
+    return _aidl_delegate->ReverseIntEnum(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ReverseLongEnum(const ::std::vector<::android::aidl::tests::LongEnum>& input, ::std::vector<::android::aidl::tests::LongEnum>* repeated, ::std::vector<::android::aidl::tests::LongEnum>* _aidl_return) override {
+    return _aidl_delegate->ReverseLongEnum(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status GetOtherTestService(const ::android::String16& name, ::android::sp<::android::aidl::tests::INamedCallback>* _aidl_return) override {
+    return _aidl_delegate->GetOtherTestService(name, _aidl_return);
+  }
+  ::android::binder::Status VerifyName(const ::android::sp<::android::aidl::tests::INamedCallback>& service, const ::android::String16& name, bool* _aidl_return) override {
+    return _aidl_delegate->VerifyName(service, name, _aidl_return);
+  }
+  ::android::binder::Status GetInterfaceArray(const ::std::vector<::android::String16>& names, ::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>* _aidl_return) override {
+    return _aidl_delegate->GetInterfaceArray(names, _aidl_return);
+  }
+  ::android::binder::Status VerifyNamesWithInterfaceArray(const ::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>& services, const ::std::vector<::android::String16>& names, bool* _aidl_return) override {
+    return _aidl_delegate->VerifyNamesWithInterfaceArray(services, names, _aidl_return);
+  }
+  ::android::binder::Status GetNullableInterfaceArray(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>* _aidl_return) override {
+    return _aidl_delegate->GetNullableInterfaceArray(names, _aidl_return);
+  }
+  ::android::binder::Status VerifyNamesWithNullableInterfaceArray(const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>& services, const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, bool* _aidl_return) override {
+    return _aidl_delegate->VerifyNamesWithNullableInterfaceArray(services, names, _aidl_return);
+  }
+  ::android::binder::Status GetInterfaceList(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>* _aidl_return) override {
+    return _aidl_delegate->GetInterfaceList(names, _aidl_return);
+  }
+  ::android::binder::Status VerifyNamesWithInterfaceList(const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>& services, const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, bool* _aidl_return) override {
+    return _aidl_delegate->VerifyNamesWithInterfaceList(services, names, _aidl_return);
+  }
+  ::android::binder::Status ReverseStringList(const ::std::vector<::android::String16>& input, ::std::vector<::android::String16>* repeated, ::std::vector<::android::String16>* _aidl_return) override {
+    return _aidl_delegate->ReverseStringList(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status RepeatParcelFileDescriptor(const ::android::os::ParcelFileDescriptor& read, ::android::os::ParcelFileDescriptor* _aidl_return) override {
+    return _aidl_delegate->RepeatParcelFileDescriptor(read, _aidl_return);
+  }
+  ::android::binder::Status ReverseParcelFileDescriptorArray(const ::std::vector<::android::os::ParcelFileDescriptor>& input, ::std::vector<::android::os::ParcelFileDescriptor>* repeated, ::std::vector<::android::os::ParcelFileDescriptor>* _aidl_return) override {
+    return _aidl_delegate->ReverseParcelFileDescriptorArray(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ThrowServiceException(int32_t code) override {
+    return _aidl_delegate->ThrowServiceException(code);
+  }
+  ::android::binder::Status RepeatNullableIntArray(const ::std::optional<::std::vector<int32_t>>& input, ::std::optional<::std::vector<int32_t>>* _aidl_return) override {
+    return _aidl_delegate->RepeatNullableIntArray(input, _aidl_return);
+  }
+  ::android::binder::Status RepeatNullableByteEnumArray(const ::std::optional<::std::vector<::android::aidl::tests::ByteEnum>>& input, ::std::optional<::std::vector<::android::aidl::tests::ByteEnum>>* _aidl_return) override {
+    return _aidl_delegate->RepeatNullableByteEnumArray(input, _aidl_return);
+  }
+  ::android::binder::Status RepeatNullableIntEnumArray(const ::std::optional<::std::vector<::android::aidl::tests::IntEnum>>& input, ::std::optional<::std::vector<::android::aidl::tests::IntEnum>>* _aidl_return) override {
+    return _aidl_delegate->RepeatNullableIntEnumArray(input, _aidl_return);
+  }
+  ::android::binder::Status RepeatNullableLongEnumArray(const ::std::optional<::std::vector<::android::aidl::tests::LongEnum>>& input, ::std::optional<::std::vector<::android::aidl::tests::LongEnum>>* _aidl_return) override {
+    return _aidl_delegate->RepeatNullableLongEnumArray(input, _aidl_return);
+  }
+  ::android::binder::Status RepeatNullableString(const ::std::optional<::android::String16>& input, ::std::optional<::android::String16>* _aidl_return) override {
+    return _aidl_delegate->RepeatNullableString(input, _aidl_return);
+  }
+  ::android::binder::Status RepeatNullableStringList(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& input, ::std::optional<::std::vector<::std::optional<::android::String16>>>* _aidl_return) override {
+    return _aidl_delegate->RepeatNullableStringList(input, _aidl_return);
+  }
+  ::android::binder::Status RepeatNullableParcelable(const ::std::optional<::android::aidl::tests::ITestService::Empty>& input, ::std::optional<::android::aidl::tests::ITestService::Empty>* _aidl_return) override {
+    return _aidl_delegate->RepeatNullableParcelable(input, _aidl_return);
+  }
+  ::android::binder::Status RepeatNullableParcelableArray(const ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>& input, ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>* _aidl_return) override {
+    return _aidl_delegate->RepeatNullableParcelableArray(input, _aidl_return);
+  }
+  ::android::binder::Status RepeatNullableParcelableList(const ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>& input, ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>* _aidl_return) override {
+    return _aidl_delegate->RepeatNullableParcelableList(input, _aidl_return);
+  }
+  ::android::binder::Status TakesAnIBinder(const ::android::sp<::android::IBinder>& input) override {
+    return _aidl_delegate->TakesAnIBinder(input);
+  }
+  ::android::binder::Status TakesANullableIBinder(const ::android::sp<::android::IBinder>& input) override {
+    return _aidl_delegate->TakesANullableIBinder(input);
+  }
+  ::android::binder::Status TakesAnIBinderList(const ::std::vector<::android::sp<::android::IBinder>>& input) override {
+    return _aidl_delegate->TakesAnIBinderList(input);
+  }
+  ::android::binder::Status TakesANullableIBinderList(const ::std::optional<::std::vector<::android::sp<::android::IBinder>>>& input) override {
+    return _aidl_delegate->TakesANullableIBinderList(input);
+  }
+  ::android::binder::Status RepeatUtf8CppString(const ::std::string& token, ::std::string* _aidl_return) override {
+    return _aidl_delegate->RepeatUtf8CppString(token, _aidl_return);
+  }
+  ::android::binder::Status RepeatNullableUtf8CppString(const ::std::optional<::std::string>& token, ::std::optional<::std::string>* _aidl_return) override {
+    return _aidl_delegate->RepeatNullableUtf8CppString(token, _aidl_return);
+  }
+  ::android::binder::Status ReverseUtf8CppString(const ::std::vector<::std::string>& input, ::std::vector<::std::string>* repeated, ::std::vector<::std::string>* _aidl_return) override {
+    return _aidl_delegate->ReverseUtf8CppString(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ReverseNullableUtf8CppString(const ::std::optional<::std::vector<::std::optional<::std::string>>>& input, ::std::optional<::std::vector<::std::optional<::std::string>>>* repeated, ::std::optional<::std::vector<::std::optional<::std::string>>>* _aidl_return) override {
+    return _aidl_delegate->ReverseNullableUtf8CppString(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ReverseUtf8CppStringList(const ::std::optional<::std::vector<::std::optional<::std::string>>>& input, ::std::optional<::std::vector<::std::optional<::std::string>>>* repeated, ::std::optional<::std::vector<::std::optional<::std::string>>>* _aidl_return) override {
+    return _aidl_delegate->ReverseUtf8CppStringList(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status GetCallback(bool return_null, ::android::sp<::android::aidl::tests::INamedCallback>* _aidl_return) override {
+    return _aidl_delegate->GetCallback(return_null, _aidl_return);
+  }
+  ::android::binder::Status FillOutStructuredParcelable(::android::aidl::tests::StructuredParcelable* parcel) override {
+    return _aidl_delegate->FillOutStructuredParcelable(parcel);
+  }
+  ::android::binder::Status RepeatExtendableParcelable(const ::android::aidl::tests::extension::ExtendableParcelable& ep, ::android::aidl::tests::extension::ExtendableParcelable* ep2) override {
+    return _aidl_delegate->RepeatExtendableParcelable(ep, ep2);
+  }
+  ::android::binder::Status ReverseList(const ::android::aidl::tests::RecursiveList& list, ::android::aidl::tests::RecursiveList* _aidl_return) override {
+    return _aidl_delegate->ReverseList(list, _aidl_return);
+  }
+  ::android::binder::Status ReverseIBinderArray(const ::std::vector<::android::sp<::android::IBinder>>& input, ::std::vector<::android::sp<::android::IBinder>>* repeated, ::std::vector<::android::sp<::android::IBinder>>* _aidl_return) override {
+    return _aidl_delegate->ReverseIBinderArray(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status ReverseNullableIBinderArray(const ::std::optional<::std::vector<::android::sp<::android::IBinder>>>& input, ::std::optional<::std::vector<::android::sp<::android::IBinder>>>* repeated, ::std::optional<::std::vector<::android::sp<::android::IBinder>>>* _aidl_return) override {
+    return _aidl_delegate->ReverseNullableIBinderArray(input, repeated, _aidl_return);
+  }
+  ::android::binder::Status GetOldNameInterface(::android::sp<::android::aidl::tests::IOldName>* _aidl_return) override {
+    return _aidl_delegate->GetOldNameInterface(_aidl_return);
+  }
+  ::android::binder::Status GetNewNameInterface(::android::sp<::android::aidl::tests::INewName>* _aidl_return) override {
+    return _aidl_delegate->GetNewNameInterface(_aidl_return);
+  }
+  ::android::binder::Status GetCppJavaTests(::android::sp<::android::IBinder>* _aidl_return) override {
+    return _aidl_delegate->GetCppJavaTests(_aidl_return);
+  }
+  ::android::binder::Status getBackendType(::android::aidl::tests::BackendType* _aidl_return) override {
+    return _aidl_delegate->getBackendType(_aidl_return);
+  }
+private:
+  ::android::sp<ITestService> _aidl_delegate;
+};  // class ITestServiceDelegator
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
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-cpp-source/gen/include/android/aidl/tests/BpDeprecated.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpDeprecated.h
index 88fb62d..628c570 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpDeprecated.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpDeprecated.h
@@ -6,19 +6,13 @@
 #include <android/aidl/tests/IDeprecated.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class __attribute__((deprecated("test"))) BpDeprecated : public ::android::BpInterface<IDeprecated> {
 public:
   explicit BpDeprecated(const ::android::sp<::android::IBinder>& _aidl_impl);
   virtual ~BpDeprecated() = default;
 };  // class BpDeprecated
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpFixedSize.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpFixedSize.h
new file mode 100644
index 0000000..27af6b1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpFixedSize.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-cpp-source/gen/include/android/aidl/tests/BpListOfInterfaces.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpListOfInterfaces.h
new file mode 100644
index 0000000..27af6b1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpListOfInterfaces.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-cpp-source/gen/include/android/aidl/tests/BpNamedCallback.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpNamedCallback.h
index 4c3eb91..9072313 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpNamedCallback.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpNamedCallback.h
@@ -6,20 +6,14 @@
 #include <android/aidl/tests/INamedCallback.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class BpNamedCallback : public ::android::BpInterface<INamedCallback> {
 public:
   explicit BpNamedCallback(const ::android::sp<::android::IBinder>& _aidl_impl);
   virtual ~BpNamedCallback() = default;
   ::android::binder::Status GetName(::android::String16* _aidl_return) override;
 };  // class BpNamedCallback
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpNewName.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpNewName.h
index d9ba90e..0702be5 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpNewName.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpNewName.h
@@ -6,20 +6,14 @@
 #include <android/aidl/tests/INewName.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class BpNewName : public ::android::BpInterface<INewName> {
 public:
   explicit BpNewName(const ::android::sp<::android::IBinder>& _aidl_impl);
   virtual ~BpNewName() = default;
   ::android::binder::Status RealName(::android::String16* _aidl_return) override;
 };  // class BpNewName
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpOldName.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpOldName.h
index a362664..5ee85b2 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpOldName.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpOldName.h
@@ -6,20 +6,14 @@
 #include <android/aidl/tests/IOldName.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class BpOldName : public ::android::BpInterface<IOldName> {
 public:
   explicit BpOldName(const ::android::sp<::android::IBinder>& _aidl_impl);
   virtual ~BpOldName() = default;
   ::android::binder::Status RealName(::android::String16* _aidl_return) override;
 };  // class BpOldName
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpRecursiveList.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpRecursiveList.h
new file mode 100644
index 0000000..27af6b1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpRecursiveList.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-cpp-source/gen/include/android/aidl/tests/BpTestService.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpTestService.h
index bee25bf..c1cbaa8 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpTestService.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/BpTestService.h
@@ -6,11 +6,8 @@
 #include <android/aidl/tests/ITestService.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class BpTestService : public ::android::BpInterface<ITestService> {
 public:
   explicit BpTestService(const ::android::sp<::android::IBinder>& _aidl_impl);
@@ -42,6 +39,12 @@
   ::android::binder::Status ReverseLongEnum(const ::std::vector<::android::aidl::tests::LongEnum>& input, ::std::vector<::android::aidl::tests::LongEnum>* repeated, ::std::vector<::android::aidl::tests::LongEnum>* _aidl_return) override;
   ::android::binder::Status GetOtherTestService(const ::android::String16& name, ::android::sp<::android::aidl::tests::INamedCallback>* _aidl_return) override;
   ::android::binder::Status VerifyName(const ::android::sp<::android::aidl::tests::INamedCallback>& service, const ::android::String16& name, bool* _aidl_return) override;
+  ::android::binder::Status GetInterfaceArray(const ::std::vector<::android::String16>& names, ::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>* _aidl_return) override;
+  ::android::binder::Status VerifyNamesWithInterfaceArray(const ::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>& services, const ::std::vector<::android::String16>& names, bool* _aidl_return) override;
+  ::android::binder::Status GetNullableInterfaceArray(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>* _aidl_return) override;
+  ::android::binder::Status VerifyNamesWithNullableInterfaceArray(const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>& services, const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, bool* _aidl_return) override;
+  ::android::binder::Status GetInterfaceList(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>* _aidl_return) override;
+  ::android::binder::Status VerifyNamesWithInterfaceList(const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>& services, const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, bool* _aidl_return) override;
   ::android::binder::Status ReverseStringList(const ::std::vector<::android::String16>& input, ::std::vector<::android::String16>* repeated, ::std::vector<::android::String16>* _aidl_return) override;
   ::android::binder::Status RepeatParcelFileDescriptor(const ::android::os::ParcelFileDescriptor& read, ::android::os::ParcelFileDescriptor* _aidl_return) override;
   ::android::binder::Status ReverseParcelFileDescriptorArray(const ::std::vector<::android::os::ParcelFileDescriptor>& input, ::std::vector<::android::os::ParcelFileDescriptor>* repeated, ::std::vector<::android::os::ParcelFileDescriptor>* _aidl_return) override;
@@ -52,9 +55,13 @@
   ::android::binder::Status RepeatNullableLongEnumArray(const ::std::optional<::std::vector<::android::aidl::tests::LongEnum>>& input, ::std::optional<::std::vector<::android::aidl::tests::LongEnum>>* _aidl_return) override;
   ::android::binder::Status RepeatNullableString(const ::std::optional<::android::String16>& input, ::std::optional<::android::String16>* _aidl_return) override;
   ::android::binder::Status RepeatNullableStringList(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& input, ::std::optional<::std::vector<::std::optional<::android::String16>>>* _aidl_return) override;
-  ::android::binder::Status RepeatNullableParcelable(const ::std::optional<::android::aidl::tests::StructuredParcelable>& input, ::std::optional<::android::aidl::tests::StructuredParcelable>* _aidl_return) override;
+  ::android::binder::Status RepeatNullableParcelable(const ::std::optional<::android::aidl::tests::ITestService::Empty>& input, ::std::optional<::android::aidl::tests::ITestService::Empty>* _aidl_return) override;
+  ::android::binder::Status RepeatNullableParcelableArray(const ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>& input, ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>* _aidl_return) override;
+  ::android::binder::Status RepeatNullableParcelableList(const ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>& input, ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>* _aidl_return) override;
   ::android::binder::Status TakesAnIBinder(const ::android::sp<::android::IBinder>& input) override;
   ::android::binder::Status TakesANullableIBinder(const ::android::sp<::android::IBinder>& input) override;
+  ::android::binder::Status TakesAnIBinderList(const ::std::vector<::android::sp<::android::IBinder>>& input) override;
+  ::android::binder::Status TakesANullableIBinderList(const ::std::optional<::std::vector<::android::sp<::android::IBinder>>>& input) override;
   ::android::binder::Status RepeatUtf8CppString(const ::std::string& token, ::std::string* _aidl_return) override;
   ::android::binder::Status RepeatNullableUtf8CppString(const ::std::optional<::std::string>& token, ::std::optional<::std::string>* _aidl_return) override;
   ::android::binder::Status ReverseUtf8CppString(const ::std::vector<::std::string>& input, ::std::vector<::std::string>* repeated, ::std::vector<::std::string>* _aidl_return) override;
@@ -62,14 +69,15 @@
   ::android::binder::Status ReverseUtf8CppStringList(const ::std::optional<::std::vector<::std::optional<::std::string>>>& input, ::std::optional<::std::vector<::std::optional<::std::string>>>* repeated, ::std::optional<::std::vector<::std::optional<::std::string>>>* _aidl_return) override;
   ::android::binder::Status GetCallback(bool return_null, ::android::sp<::android::aidl::tests::INamedCallback>* _aidl_return) override;
   ::android::binder::Status FillOutStructuredParcelable(::android::aidl::tests::StructuredParcelable* parcel) override;
+  ::android::binder::Status RepeatExtendableParcelable(const ::android::aidl::tests::extension::ExtendableParcelable& ep, ::android::aidl::tests::extension::ExtendableParcelable* ep2) override;
+  ::android::binder::Status ReverseList(const ::android::aidl::tests::RecursiveList& list, ::android::aidl::tests::RecursiveList* _aidl_return) override;
+  ::android::binder::Status ReverseIBinderArray(const ::std::vector<::android::sp<::android::IBinder>>& input, ::std::vector<::android::sp<::android::IBinder>>* repeated, ::std::vector<::android::sp<::android::IBinder>>* _aidl_return) override;
+  ::android::binder::Status ReverseNullableIBinderArray(const ::std::optional<::std::vector<::android::sp<::android::IBinder>>>& input, ::std::optional<::std::vector<::android::sp<::android::IBinder>>>* repeated, ::std::optional<::std::vector<::android::sp<::android::IBinder>>>* _aidl_return) override;
   ::android::binder::Status GetOldNameInterface(::android::sp<::android::aidl::tests::IOldName>* _aidl_return) override;
   ::android::binder::Status GetNewNameInterface(::android::sp<::android::aidl::tests::INewName>* _aidl_return) override;
   ::android::binder::Status GetCppJavaTests(::android::sp<::android::IBinder>* _aidl_return) override;
   ::android::binder::Status getBackendType(::android::aidl::tests::BackendType* _aidl_return) override;
 };  // class BpTestService
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ByteEnum.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ByteEnum.h
index 7b50010..6ee09d8 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ByteEnum.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ByteEnum.h
@@ -6,17 +6,19 @@
 #include <string>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 enum class ByteEnum : int8_t {
   FOO = 1,
   BAR = 2,
   BAZ = 3,
 };
-
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace aidl {
+namespace tests {
 [[nodiscard]] static inline std::string toString(ByteEnum val) {
   switch(val) {
   case ByteEnum::FOO:
@@ -29,16 +31,11 @@
     return std::to_string(static_cast<int8_t>(val));
   }
 }
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 namespace android {
-
 namespace internal {
-
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wc++17-extensions"
 template <>
@@ -48,7 +45,5 @@
   ::android::aidl::tests::ByteEnum::BAZ,
 };
 #pragma clang diagnostic pop
-
 }  // namespace internal
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ConstantExpressionEnum.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ConstantExpressionEnum.h
index b9abcb3..65131a0 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ConstantExpressionEnum.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ConstantExpressionEnum.h
@@ -6,11 +6,8 @@
 #include <string>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 enum class ConstantExpressionEnum : int32_t {
   decInt32_1 = 1,
   decInt32_2 = 1,
@@ -23,7 +20,12 @@
   hexInt32_3 = 1,
   hexInt64_1 = 1,
 };
-
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace aidl {
+namespace tests {
 [[nodiscard]] static inline std::string toString(ConstantExpressionEnum val) {
   switch(val) {
   case ConstantExpressionEnum::decInt32_1:
@@ -32,16 +34,11 @@
     return std::to_string(static_cast<int32_t>(val));
   }
 }
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 namespace android {
-
 namespace internal {
-
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wc++17-extensions"
 template <>
@@ -58,7 +55,5 @@
   ::android::aidl::tests::ConstantExpressionEnum::hexInt64_1,
 };
 #pragma clang diagnostic pop
-
 }  // namespace internal
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/DeprecatedEnum.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/DeprecatedEnum.h
index 8de53cf..c89b38f 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/DeprecatedEnum.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/DeprecatedEnum.h
@@ -6,18 +6,21 @@
 #include <string>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 enum class __attribute__((deprecated("test"))) DeprecatedEnum : int32_t {
   A = 0,
   B = 1,
   C = 2,
 };
-
-[[nodiscard]] __attribute__((deprecated("test"))) static inline std::string toString(DeprecatedEnum val) {
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace aidl {
+namespace tests {
+[[nodiscard]] static inline std::string toString(DeprecatedEnum val) __attribute__((deprecated("test")));
+[[nodiscard]] static inline std::string toString(DeprecatedEnum val) {
   switch(val) {
   case DeprecatedEnum::A:
     return "A";
@@ -29,16 +32,11 @@
     return std::to_string(static_cast<int32_t>(val));
   }
 }
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 namespace android {
-
 namespace internal {
-
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wc++17-extensions"
 template <>
@@ -48,7 +46,5 @@
   ::android::aidl::tests::DeprecatedEnum::C,
 };
 #pragma clang diagnostic pop
-
 }  // namespace internal
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/DeprecatedParcelable.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/DeprecatedParcelable.h
index 59c7f20..aab5089 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/DeprecatedParcelable.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/DeprecatedParcelable.h
@@ -7,11 +7,8 @@
 #include <utils/String16.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class __attribute__((deprecated("test"))) DeprecatedParcelable : public ::android::Parcelable {
 public:
   inline bool operator!=(const DeprecatedParcelable&) const {
@@ -46,9 +43,6 @@
     return os.str();
   }
 };  // class DeprecatedParcelable
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/FixedSize.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/FixedSize.h
new file mode 100644
index 0000000..2e670e3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/FixedSize.h
@@ -0,0 +1,222 @@
+#pragma once
+
+#include <android/aidl/tests/FixedSize.h>
+#include <android/aidl/tests/LongEnum.h>
+#include <android/binder_to_string.h>
+#include <binder/Parcel.h>
+#include <binder/Status.h>
+#include <cassert>
+#include <cstdint>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <utils/String16.h>
+#include <variant>
+
+#ifndef __BIONIC__
+#define __assert2(a,b,c,d) ((void)0)
+#endif
+
+namespace android {
+namespace aidl {
+namespace tests {
+class FixedSize : public ::android::Parcelable {
+public:
+  class FixedUnion : public ::android::Parcelable {
+  public:
+    enum Tag : uint8_t {
+      booleanValue = 0,  // boolean booleanValue;
+      byteValue,  // byte byteValue;
+      charValue,  // char charValue;
+      intValue,  // int intValue;
+      longValue,  // long longValue;
+      floatValue,  // float floatValue;
+      doubleValue,  // double doubleValue;
+      enumValue,  // android.aidl.tests.LongEnum enumValue;
+    };
+
+    template <Tag _Tag>
+    using _at = typename std::tuple_element<_Tag, std::tuple<bool, int8_t, char16_t, int32_t, int64_t, float, double, ::android::aidl::tests::LongEnum>>::type;
+    template <Tag _Tag, typename _Type>
+    static FixedUnion make(_Type&& _arg) {
+      FixedUnion _inst;
+      _inst.set<_Tag>(std::forward<_Type>(_arg));
+      return _inst;
+    }
+    constexpr Tag getTag() const {
+      return _tag;
+    }
+    template <Tag _Tag>
+    const _at<_Tag>& get() const {
+      if (_Tag != _tag) { __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }
+      return *(_at<_Tag>*)(&_value);
+    }
+    template <Tag _Tag>
+    _at<_Tag>& get() {
+      if (_Tag != _tag) { __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }
+      return *(_at<_Tag>*)(&_value);
+    }
+    template <Tag _Tag, typename _Type>
+    void set(_Type&& _arg) {
+      _tag = _Tag;
+      get<_Tag>() = std::forward<_Type>(_arg);
+    }
+    static int _cmp(const FixedUnion& _lhs, const FixedUnion& _rhs) {
+      return _cmp_value(_lhs.getTag(), _rhs.getTag()) || _cmp_value_at<enumValue>(_lhs, _rhs);
+    }
+    template <Tag _Tag>
+    static int _cmp_value_at(const FixedUnion& _lhs, const FixedUnion& _rhs) {
+      if constexpr (_Tag == booleanValue) {
+        return _cmp_value(_lhs.get<_Tag>(), _rhs.get<_Tag>());
+      } else {
+        return (_lhs.getTag() == _Tag)
+          ? _cmp_value(_lhs.get<_Tag>(), _rhs.get<_Tag>())
+          : _cmp_value_at<(Tag)(_Tag-1)>(_lhs, _rhs);
+      }
+    }
+    template <typename _Type>
+    static int _cmp_value(const _Type& _lhs, const _Type& _rhs) {
+      return (_lhs == _rhs) ? 0 : (_lhs < _rhs) ? -1 : 1;
+    }
+    inline bool operator!=(const FixedUnion&_rhs) const {
+      return _cmp(*this, _rhs) != 0;
+    }
+    inline bool operator<(const FixedUnion&_rhs) const {
+      return _cmp(*this, _rhs) < 0;
+    }
+    inline bool operator<=(const FixedUnion&_rhs) const {
+      return _cmp(*this, _rhs) <= 0;
+    }
+    inline bool operator==(const FixedUnion&_rhs) const {
+      return _cmp(*this, _rhs) == 0;
+    }
+    inline bool operator>(const FixedUnion&_rhs) const {
+      return _cmp(*this, _rhs) > 0;
+    }
+    inline bool operator>=(const FixedUnion&_rhs) const {
+      return _cmp(*this, _rhs) >= 0;
+    }
+    ::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.FixedSize.FixedUnion");
+      return DESCIPTOR;
+    }
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "FixedUnion{";
+      switch (getTag()) {
+      case booleanValue: os << "booleanValue: " << ::android::internal::ToString(get<booleanValue>()); break;
+      case byteValue: os << "byteValue: " << ::android::internal::ToString(get<byteValue>()); break;
+      case charValue: os << "charValue: " << ::android::internal::ToString(get<charValue>()); break;
+      case intValue: os << "intValue: " << ::android::internal::ToString(get<intValue>()); break;
+      case longValue: os << "longValue: " << ::android::internal::ToString(get<longValue>()); break;
+      case floatValue: os << "floatValue: " << ::android::internal::ToString(get<floatValue>()); break;
+      case doubleValue: os << "doubleValue: " << ::android::internal::ToString(get<doubleValue>()); break;
+      case enumValue: os << "enumValue: " << ::android::internal::ToString(get<enumValue>()); break;
+      }
+      os << "}";
+      return os.str();
+    }
+  private:
+    Tag _tag __attribute__((aligned (1))) = booleanValue;
+    union _value_t {
+      _value_t() {}
+      ~_value_t() {}
+      bool booleanValue __attribute__((aligned (1))) = bool(false);
+      int8_t byteValue __attribute__((aligned (1)));
+      char16_t charValue __attribute__((aligned (2)));
+      int32_t intValue __attribute__((aligned (4)));
+      int64_t longValue __attribute__((aligned (8)));
+      float floatValue __attribute__((aligned (4)));
+      double doubleValue __attribute__((aligned (8)));
+      ::android::aidl::tests::LongEnum enumValue __attribute__((aligned (8)));
+    } _value;
+  };  // class FixedUnion
+  class FixedParcelable : public ::android::Parcelable {
+  public:
+    bool booleanValue = false;
+    int8_t byteValue = 0;
+    char16_t charValue = '\0';
+    int32_t intValue = 0;
+    int64_t longValue = 0L;
+    float floatValue = 0.000000f;
+    double doubleValue = 0.000000;
+    ::android::aidl::tests::LongEnum enumValue = ::android::aidl::tests::LongEnum::FOO;
+    ::android::aidl::tests::FixedSize::FixedUnion parcelableValue;
+    inline bool operator!=(const FixedParcelable& rhs) const {
+      return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) != std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+    }
+    inline bool operator<(const FixedParcelable& rhs) const {
+      return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) < std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+    }
+    inline bool operator<=(const FixedParcelable& rhs) const {
+      return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) <= std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+    }
+    inline bool operator==(const FixedParcelable& rhs) const {
+      return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) == std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+    }
+    inline bool operator>(const FixedParcelable& rhs) const {
+      return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) > std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+    }
+    inline bool operator>=(const FixedParcelable& rhs) const {
+      return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) >= std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+    }
+
+    ::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.FixedSize.FixedParcelable");
+      return DESCIPTOR;
+    }
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "FixedParcelable{";
+      os << "booleanValue: " << ::android::internal::ToString(booleanValue);
+      os << ", byteValue: " << ::android::internal::ToString(byteValue);
+      os << ", charValue: " << ::android::internal::ToString(charValue);
+      os << ", intValue: " << ::android::internal::ToString(intValue);
+      os << ", longValue: " << ::android::internal::ToString(longValue);
+      os << ", floatValue: " << ::android::internal::ToString(floatValue);
+      os << ", doubleValue: " << ::android::internal::ToString(doubleValue);
+      os << ", enumValue: " << ::android::internal::ToString(enumValue);
+      os << ", parcelableValue: " << ::android::internal::ToString(parcelableValue);
+      os << "}";
+      return os.str();
+    }
+  };  // class FixedParcelable
+  inline bool operator!=(const FixedSize&) const {
+    return std::tie() != std::tie();
+  }
+  inline bool operator<(const FixedSize&) const {
+    return std::tie() < std::tie();
+  }
+  inline bool operator<=(const FixedSize&) const {
+    return std::tie() <= std::tie();
+  }
+  inline bool operator==(const FixedSize&) const {
+    return std::tie() == std::tie();
+  }
+  inline bool operator>(const FixedSize&) const {
+    return std::tie() > std::tie();
+  }
+  inline bool operator>=(const FixedSize&) const {
+    return std::tie() >= std::tie();
+  }
+
+  ::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.FixedSize");
+    return DESCIPTOR;
+  }
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "FixedSize{";
+    os << "}";
+    return os.str();
+  }
+};  // class FixedSize
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/GenericStructuredParcelable.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/GenericStructuredParcelable.h
index e655ee1..7a86f81 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/GenericStructuredParcelable.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/GenericStructuredParcelable.h
@@ -8,14 +8,13 @@
 #include <utils/String16.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 template <typename T, typename U, typename B>
 class GenericStructuredParcelable : public ::android::Parcelable {
 public:
+  int32_t a = 0;
+  int32_t b = 0;
   inline bool operator!=(const GenericStructuredParcelable& rhs) const {
     return std::tie(a, b) != std::tie(rhs.a, rhs.b);
   }
@@ -35,8 +34,6 @@
     return std::tie(a, b) >= std::tie(rhs.a, rhs.b);
   }
 
-  int32_t a = int32_t(0);
-  int32_t b = int32_t(0);
   ::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() {
@@ -52,27 +49,25 @@
     return os.str();
   }
 };  // class GenericStructuredParcelable
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 #include <android/aidl/tests/GenericStructuredParcelable.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 template <typename T, typename U, typename B>
 ::android::status_t GenericStructuredParcelable<T,U,B>::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);
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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);
@@ -93,7 +88,6 @@
   _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
   return _aidl_ret_status;
 }
-
 template <typename T, typename U, typename B>
 ::android::status_t GenericStructuredParcelable<T,U,B>::writeToParcel(::android::Parcel* _aidl_parcel) const {
   ::android::status_t _aidl_ret_status = ::android::OK;
@@ -113,9 +107,6 @@
   _aidl_parcel->setDataPosition(_aidl_end_pos);
   return _aidl_ret_status;
 }
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/IDeprecated.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/IDeprecated.h
index 73931ea..195b47c 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/IDeprecated.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/IDeprecated.h
@@ -6,11 +6,8 @@
 #include <utils/StrongPointer.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class __attribute__((deprecated("test"))) IDeprecated : public ::android::IInterface {
 public:
   DECLARE_META_INTERFACE(Deprecated)
@@ -22,9 +19,6 @@
     return nullptr;
   }
 };  // class IDeprecatedDefault
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/INamedCallback.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/INamedCallback.h
index 910294c..2b27774 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/INamedCallback.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/INamedCallback.h
@@ -7,11 +7,8 @@
 #include <utils/StrongPointer.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class INamedCallback : public ::android::IInterface {
 public:
   DECLARE_META_INTERFACE(NamedCallback)
@@ -23,13 +20,10 @@
   ::android::IBinder* onAsBinder() override {
     return nullptr;
   }
-  ::android::binder::Status GetName(::android::String16*) override {
+  ::android::binder::Status GetName(::android::String16* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
 };  // class INamedCallbackDefault
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/INewName.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/INewName.h
index a3d911c..693f88b 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/INewName.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/INewName.h
@@ -7,11 +7,8 @@
 #include <utils/StrongPointer.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class INewName : public ::android::IInterface {
 public:
   DECLARE_META_INTERFACE(NewName)
@@ -23,13 +20,10 @@
   ::android::IBinder* onAsBinder() override {
     return nullptr;
   }
-  ::android::binder::Status RealName(::android::String16*) override {
+  ::android::binder::Status RealName(::android::String16* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
 };  // class INewNameDefault
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/IOldName.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/IOldName.h
index ab5530b..2142d88 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/IOldName.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/IOldName.h
@@ -7,11 +7,8 @@
 #include <utils/StrongPointer.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class IOldName : public ::android::IInterface {
 public:
   DECLARE_META_INTERFACE(OldName)
@@ -23,13 +20,10 @@
   ::android::IBinder* onAsBinder() override {
     return nullptr;
   }
-  ::android::binder::Status RealName(::android::String16*) override {
+  ::android::binder::Status RealName(::android::String16* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
 };  // class IOldNameDefault
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ITestService.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ITestService.h
index 9d91e0e..dd0e7f1 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ITestService.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ITestService.h
@@ -5,109 +5,210 @@
 #include <android/aidl/tests/INamedCallback.h>
 #include <android/aidl/tests/INewName.h>
 #include <android/aidl/tests/IOldName.h>
+#include <android/aidl/tests/ITestService.h>
 #include <android/aidl/tests/IntEnum.h>
 #include <android/aidl/tests/LongEnum.h>
+#include <android/aidl/tests/RecursiveList.h>
 #include <android/aidl/tests/StructuredParcelable.h>
+#include <android/aidl/tests/extension/ExtendableParcelable.h>
+#include <android/binder_to_string.h>
 #include <binder/IBinder.h>
 #include <binder/IInterface.h>
+#include <binder/Parcel.h>
 #include <binder/ParcelFileDescriptor.h>
 #include <binder/Status.h>
 #include <cstdint>
 #include <optional>
 #include <string>
+#include <tuple>
 #include <utils/String16.h>
 #include <utils/StrongPointer.h>
 #include <vector>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class ITestService : public ::android::IInterface {
 public:
   DECLARE_META_INTERFACE(TestService)
-  enum  : int8_t {
-    BYTE_TEST_CONSTANT = 17,
-  };
-  enum  : int32_t {
-    TEST_CONSTANT = 42,
-    TEST_CONSTANT2 = -42,
-    TEST_CONSTANT3 = 42,
-    TEST_CONSTANT4 = 4,
-    TEST_CONSTANT5 = -4,
-    TEST_CONSTANT6 = 0,
-    TEST_CONSTANT7 = 0,
-    TEST_CONSTANT8 = 0,
-    TEST_CONSTANT9 = 86,
-    TEST_CONSTANT10 = 165,
-    TEST_CONSTANT11 = 250,
-    TEST_CONSTANT12 = -1,
-    A1 = 1,
-    A2 = 1,
-    A3 = 1,
-    A4 = 1,
-    A5 = 1,
-    A6 = 1,
-    A7 = 1,
-    A8 = 1,
-    A9 = 1,
-    A10 = 1,
-    A11 = 1,
-    A12 = 1,
-    A13 = 1,
-    A14 = 1,
-    A15 = 1,
-    A16 = 1,
-    A17 = 1,
-    A18 = 1,
-    A19 = 1,
-    A20 = 1,
-    A21 = 1,
-    A22 = 1,
-    A23 = 1,
-    A24 = 1,
-    A25 = 1,
-    A26 = 1,
-    A27 = 1,
-    A28 = 1,
-    A29 = 1,
-    A30 = 1,
-    A31 = 1,
-    A32 = 1,
-    A33 = 1,
-    A34 = 1,
-    A35 = 1,
-    A36 = 1,
-    A37 = 1,
-    A38 = 1,
-    A39 = 1,
-    A40 = 1,
-    A41 = 1,
-    A42 = 1,
-    A43 = 1,
-    A44 = 1,
-    A45 = 1,
-    A46 = 1,
-    A47 = 1,
-    A48 = 1,
-    A49 = 1,
-    A50 = 1,
-    A51 = 1,
-    A52 = 1,
-    A53 = 1,
-    A54 = 1,
-    A55 = 1,
-    A56 = 1,
-    A57 = 1,
-  };
-  enum  : int64_t {
-    LONG_TEST_CONSTANT = 1099511627776L,
-  };
+  class Empty : public ::android::Parcelable {
+  public:
+    inline bool operator!=(const Empty&) const {
+      return std::tie() != std::tie();
+    }
+    inline bool operator<(const Empty&) const {
+      return std::tie() < std::tie();
+    }
+    inline bool operator<=(const Empty&) const {
+      return std::tie() <= std::tie();
+    }
+    inline bool operator==(const Empty&) const {
+      return std::tie() == std::tie();
+    }
+    inline bool operator>(const Empty&) const {
+      return std::tie() > std::tie();
+    }
+    inline bool operator>=(const Empty&) const {
+      return std::tie() >= std::tie();
+    }
+
+    ::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.ITestService.Empty");
+      return DESCIPTOR;
+    }
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "Empty{";
+      os << "}";
+      return os.str();
+    }
+  };  // class Empty
+  class CompilerChecks : public ::android::Parcelable {
+  public:
+    ::android::sp<::android::IBinder> binder;
+    ::android::sp<::android::IBinder> nullable_binder;
+    ::std::vector<::android::sp<::android::IBinder>> binder_array;
+    ::std::optional<::std::vector<::android::sp<::android::IBinder>>> nullable_binder_array;
+    ::std::vector<::android::sp<::android::IBinder>> binder_list;
+    ::std::optional<::std::vector<::android::sp<::android::IBinder>>> nullable_binder_list;
+    ::android::os::ParcelFileDescriptor pfd;
+    ::std::optional<::android::os::ParcelFileDescriptor> nullable_pfd;
+    ::std::vector<::android::os::ParcelFileDescriptor> pfd_array;
+    ::std::optional<::std::vector<::std::optional<::android::os::ParcelFileDescriptor>>> nullable_pfd_array;
+    ::std::vector<::android::os::ParcelFileDescriptor> pfd_list;
+    ::std::optional<::std::vector<::std::optional<::android::os::ParcelFileDescriptor>>> nullable_pfd_list;
+    ::android::aidl::tests::ITestService::Empty parcel;
+    ::std::optional<::android::aidl::tests::ITestService::Empty> nullable_parcel;
+    ::std::vector<::android::aidl::tests::ITestService::Empty> parcel_array;
+    ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>> nullable_parcel_array;
+    ::std::vector<::android::aidl::tests::ITestService::Empty> parcel_list;
+    ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>> nullable_parcel_list;
+    inline bool operator!=(const CompilerChecks& rhs) const {
+      return std::tie(binder, nullable_binder, binder_array, nullable_binder_array, binder_list, nullable_binder_list, pfd, nullable_pfd, pfd_array, nullable_pfd_array, pfd_list, nullable_pfd_list, parcel, nullable_parcel, parcel_array, nullable_parcel_array, parcel_list, nullable_parcel_list) != std::tie(rhs.binder, rhs.nullable_binder, rhs.binder_array, rhs.nullable_binder_array, rhs.binder_list, rhs.nullable_binder_list, rhs.pfd, rhs.nullable_pfd, rhs.pfd_array, rhs.nullable_pfd_array, rhs.pfd_list, rhs.nullable_pfd_list, rhs.parcel, rhs.nullable_parcel, rhs.parcel_array, rhs.nullable_parcel_array, rhs.parcel_list, rhs.nullable_parcel_list);
+    }
+    inline bool operator<(const CompilerChecks& rhs) const {
+      return std::tie(binder, nullable_binder, binder_array, nullable_binder_array, binder_list, nullable_binder_list, pfd, nullable_pfd, pfd_array, nullable_pfd_array, pfd_list, nullable_pfd_list, parcel, nullable_parcel, parcel_array, nullable_parcel_array, parcel_list, nullable_parcel_list) < std::tie(rhs.binder, rhs.nullable_binder, rhs.binder_array, rhs.nullable_binder_array, rhs.binder_list, rhs.nullable_binder_list, rhs.pfd, rhs.nullable_pfd, rhs.pfd_array, rhs.nullable_pfd_array, rhs.pfd_list, rhs.nullable_pfd_list, rhs.parcel, rhs.nullable_parcel, rhs.parcel_array, rhs.nullable_parcel_array, rhs.parcel_list, rhs.nullable_parcel_list);
+    }
+    inline bool operator<=(const CompilerChecks& rhs) const {
+      return std::tie(binder, nullable_binder, binder_array, nullable_binder_array, binder_list, nullable_binder_list, pfd, nullable_pfd, pfd_array, nullable_pfd_array, pfd_list, nullable_pfd_list, parcel, nullable_parcel, parcel_array, nullable_parcel_array, parcel_list, nullable_parcel_list) <= std::tie(rhs.binder, rhs.nullable_binder, rhs.binder_array, rhs.nullable_binder_array, rhs.binder_list, rhs.nullable_binder_list, rhs.pfd, rhs.nullable_pfd, rhs.pfd_array, rhs.nullable_pfd_array, rhs.pfd_list, rhs.nullable_pfd_list, rhs.parcel, rhs.nullable_parcel, rhs.parcel_array, rhs.nullable_parcel_array, rhs.parcel_list, rhs.nullable_parcel_list);
+    }
+    inline bool operator==(const CompilerChecks& rhs) const {
+      return std::tie(binder, nullable_binder, binder_array, nullable_binder_array, binder_list, nullable_binder_list, pfd, nullable_pfd, pfd_array, nullable_pfd_array, pfd_list, nullable_pfd_list, parcel, nullable_parcel, parcel_array, nullable_parcel_array, parcel_list, nullable_parcel_list) == std::tie(rhs.binder, rhs.nullable_binder, rhs.binder_array, rhs.nullable_binder_array, rhs.binder_list, rhs.nullable_binder_list, rhs.pfd, rhs.nullable_pfd, rhs.pfd_array, rhs.nullable_pfd_array, rhs.pfd_list, rhs.nullable_pfd_list, rhs.parcel, rhs.nullable_parcel, rhs.parcel_array, rhs.nullable_parcel_array, rhs.parcel_list, rhs.nullable_parcel_list);
+    }
+    inline bool operator>(const CompilerChecks& rhs) const {
+      return std::tie(binder, nullable_binder, binder_array, nullable_binder_array, binder_list, nullable_binder_list, pfd, nullable_pfd, pfd_array, nullable_pfd_array, pfd_list, nullable_pfd_list, parcel, nullable_parcel, parcel_array, nullable_parcel_array, parcel_list, nullable_parcel_list) > std::tie(rhs.binder, rhs.nullable_binder, rhs.binder_array, rhs.nullable_binder_array, rhs.binder_list, rhs.nullable_binder_list, rhs.pfd, rhs.nullable_pfd, rhs.pfd_array, rhs.nullable_pfd_array, rhs.pfd_list, rhs.nullable_pfd_list, rhs.parcel, rhs.nullable_parcel, rhs.parcel_array, rhs.nullable_parcel_array, rhs.parcel_list, rhs.nullable_parcel_list);
+    }
+    inline bool operator>=(const CompilerChecks& rhs) const {
+      return std::tie(binder, nullable_binder, binder_array, nullable_binder_array, binder_list, nullable_binder_list, pfd, nullable_pfd, pfd_array, nullable_pfd_array, pfd_list, nullable_pfd_list, parcel, nullable_parcel, parcel_array, nullable_parcel_array, parcel_list, nullable_parcel_list) >= std::tie(rhs.binder, rhs.nullable_binder, rhs.binder_array, rhs.nullable_binder_array, rhs.binder_list, rhs.nullable_binder_list, rhs.pfd, rhs.nullable_pfd, rhs.pfd_array, rhs.nullable_pfd_array, rhs.pfd_list, rhs.nullable_pfd_list, rhs.parcel, rhs.nullable_parcel, rhs.parcel_array, rhs.nullable_parcel_array, rhs.parcel_list, rhs.nullable_parcel_list);
+    }
+
+    ::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.ITestService.CompilerChecks");
+      return DESCIPTOR;
+    }
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "CompilerChecks{";
+      os << "binder: " << ::android::internal::ToString(binder);
+      os << ", nullable_binder: " << ::android::internal::ToString(nullable_binder);
+      os << ", binder_array: " << ::android::internal::ToString(binder_array);
+      os << ", nullable_binder_array: " << ::android::internal::ToString(nullable_binder_array);
+      os << ", binder_list: " << ::android::internal::ToString(binder_list);
+      os << ", nullable_binder_list: " << ::android::internal::ToString(nullable_binder_list);
+      os << ", pfd: " << ::android::internal::ToString(pfd);
+      os << ", nullable_pfd: " << ::android::internal::ToString(nullable_pfd);
+      os << ", pfd_array: " << ::android::internal::ToString(pfd_array);
+      os << ", nullable_pfd_array: " << ::android::internal::ToString(nullable_pfd_array);
+      os << ", pfd_list: " << ::android::internal::ToString(pfd_list);
+      os << ", nullable_pfd_list: " << ::android::internal::ToString(nullable_pfd_list);
+      os << ", parcel: " << ::android::internal::ToString(parcel);
+      os << ", nullable_parcel: " << ::android::internal::ToString(nullable_parcel);
+      os << ", parcel_array: " << ::android::internal::ToString(parcel_array);
+      os << ", nullable_parcel_array: " << ::android::internal::ToString(nullable_parcel_array);
+      os << ", parcel_list: " << ::android::internal::ToString(parcel_list);
+      os << ", nullable_parcel_list: " << ::android::internal::ToString(nullable_parcel_list);
+      os << "}";
+      return os.str();
+    }
+  };  // class CompilerChecks
+  enum : int32_t { TEST_CONSTANT = 42 };
+  enum : int32_t { TEST_CONSTANT2 = -42 };
+  enum : int32_t { TEST_CONSTANT3 = 42 };
+  enum : int32_t { TEST_CONSTANT4 = 4 };
+  enum : int32_t { TEST_CONSTANT5 = -4 };
+  enum : int32_t { TEST_CONSTANT6 = 0 };
+  enum : int32_t { TEST_CONSTANT7 = 0 };
+  enum : int32_t { TEST_CONSTANT8 = 0 };
+  enum : int32_t { TEST_CONSTANT9 = 86 };
+  enum : int32_t { TEST_CONSTANT10 = 165 };
+  enum : int32_t { TEST_CONSTANT11 = 250 };
+  enum : int32_t { TEST_CONSTANT12 = -1 };
+  enum : int8_t { BYTE_TEST_CONSTANT = 17 };
+  enum : int64_t { LONG_TEST_CONSTANT = 1099511627776L };
   static const ::android::String16& STRING_TEST_CONSTANT();
   static const ::android::String16& STRING_TEST_CONSTANT2();
   static const ::std::string& STRING_TEST_CONSTANT_UTF8();
+  enum : int32_t { A1 = 1 };
+  enum : int32_t { A2 = 1 };
+  enum : int32_t { A3 = 1 };
+  enum : int32_t { A4 = 1 };
+  enum : int32_t { A5 = 1 };
+  enum : int32_t { A6 = 1 };
+  enum : int32_t { A7 = 1 };
+  enum : int32_t { A8 = 1 };
+  enum : int32_t { A9 = 1 };
+  enum : int32_t { A10 = 1 };
+  enum : int32_t { A11 = 1 };
+  enum : int32_t { A12 = 1 };
+  enum : int32_t { A13 = 1 };
+  enum : int32_t { A14 = 1 };
+  enum : int32_t { A15 = 1 };
+  enum : int32_t { A16 = 1 };
+  enum : int32_t { A17 = 1 };
+  enum : int32_t { A18 = 1 };
+  enum : int32_t { A19 = 1 };
+  enum : int32_t { A20 = 1 };
+  enum : int32_t { A21 = 1 };
+  enum : int32_t { A22 = 1 };
+  enum : int32_t { A23 = 1 };
+  enum : int32_t { A24 = 1 };
+  enum : int32_t { A25 = 1 };
+  enum : int32_t { A26 = 1 };
+  enum : int32_t { A27 = 1 };
+  enum : int32_t { A28 = 1 };
+  enum : int32_t { A29 = 1 };
+  enum : int32_t { A30 = 1 };
+  enum : int32_t { A31 = 1 };
+  enum : int32_t { A32 = 1 };
+  enum : int32_t { A33 = 1 };
+  enum : int32_t { A34 = 1 };
+  enum : int32_t { A35 = 1 };
+  enum : int32_t { A36 = 1 };
+  enum : int32_t { A37 = 1 };
+  enum : int32_t { A38 = 1 };
+  enum : int32_t { A39 = 1 };
+  enum : int32_t { A40 = 1 };
+  enum : int32_t { A41 = 1 };
+  enum : int32_t { A42 = 1 };
+  enum : int32_t { A43 = 1 };
+  enum : int32_t { A44 = 1 };
+  enum : int32_t { A45 = 1 };
+  enum : int32_t { A46 = 1 };
+  enum : int32_t { A47 = 1 };
+  enum : int32_t { A48 = 1 };
+  enum : int32_t { A49 = 1 };
+  enum : int32_t { A50 = 1 };
+  enum : int32_t { A51 = 1 };
+  enum : int32_t { A52 = 1 };
+  enum : int32_t { A53 = 1 };
+  enum : int32_t { A54 = 1 };
+  enum : int32_t { A55 = 1 };
+  enum : int32_t { A56 = 1 };
+  enum : int32_t { A57 = 1 };
   virtual ::android::binder::Status UnimplementedMethod(int32_t arg, int32_t* _aidl_return) = 0;
   virtual ::android::binder::Status Deprecated() __attribute__((deprecated("to make sure we have something in system/tools/aidl which does a compile check of deprecated and make sure this is reflected in goldens"))) = 0;
   virtual ::android::binder::Status TestOneway() = 0;
@@ -135,6 +236,12 @@
   virtual ::android::binder::Status ReverseLongEnum(const ::std::vector<::android::aidl::tests::LongEnum>& input, ::std::vector<::android::aidl::tests::LongEnum>* repeated, ::std::vector<::android::aidl::tests::LongEnum>* _aidl_return) = 0;
   virtual ::android::binder::Status GetOtherTestService(const ::android::String16& name, ::android::sp<::android::aidl::tests::INamedCallback>* _aidl_return) = 0;
   virtual ::android::binder::Status VerifyName(const ::android::sp<::android::aidl::tests::INamedCallback>& service, const ::android::String16& name, bool* _aidl_return) = 0;
+  virtual ::android::binder::Status GetInterfaceArray(const ::std::vector<::android::String16>& names, ::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>* _aidl_return) = 0;
+  virtual ::android::binder::Status VerifyNamesWithInterfaceArray(const ::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>& services, const ::std::vector<::android::String16>& names, bool* _aidl_return) = 0;
+  virtual ::android::binder::Status GetNullableInterfaceArray(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>* _aidl_return) = 0;
+  virtual ::android::binder::Status VerifyNamesWithNullableInterfaceArray(const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>& services, const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, bool* _aidl_return) = 0;
+  virtual ::android::binder::Status GetInterfaceList(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>* _aidl_return) = 0;
+  virtual ::android::binder::Status VerifyNamesWithInterfaceList(const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>& services, const ::std::optional<::std::vector<::std::optional<::android::String16>>>& names, bool* _aidl_return) = 0;
   virtual ::android::binder::Status ReverseStringList(const ::std::vector<::android::String16>& input, ::std::vector<::android::String16>* repeated, ::std::vector<::android::String16>* _aidl_return) = 0;
   virtual ::android::binder::Status RepeatParcelFileDescriptor(const ::android::os::ParcelFileDescriptor& read, ::android::os::ParcelFileDescriptor* _aidl_return) = 0;
   virtual ::android::binder::Status ReverseParcelFileDescriptorArray(const ::std::vector<::android::os::ParcelFileDescriptor>& input, ::std::vector<::android::os::ParcelFileDescriptor>* repeated, ::std::vector<::android::os::ParcelFileDescriptor>* _aidl_return) = 0;
@@ -145,9 +252,13 @@
   virtual ::android::binder::Status RepeatNullableLongEnumArray(const ::std::optional<::std::vector<::android::aidl::tests::LongEnum>>& input, ::std::optional<::std::vector<::android::aidl::tests::LongEnum>>* _aidl_return) = 0;
   virtual ::android::binder::Status RepeatNullableString(const ::std::optional<::android::String16>& input, ::std::optional<::android::String16>* _aidl_return) = 0;
   virtual ::android::binder::Status RepeatNullableStringList(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& input, ::std::optional<::std::vector<::std::optional<::android::String16>>>* _aidl_return) = 0;
-  virtual ::android::binder::Status RepeatNullableParcelable(const ::std::optional<::android::aidl::tests::StructuredParcelable>& input, ::std::optional<::android::aidl::tests::StructuredParcelable>* _aidl_return) = 0;
+  virtual ::android::binder::Status RepeatNullableParcelable(const ::std::optional<::android::aidl::tests::ITestService::Empty>& input, ::std::optional<::android::aidl::tests::ITestService::Empty>* _aidl_return) = 0;
+  virtual ::android::binder::Status RepeatNullableParcelableArray(const ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>& input, ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>* _aidl_return) = 0;
+  virtual ::android::binder::Status RepeatNullableParcelableList(const ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>& input, ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>* _aidl_return) = 0;
   virtual ::android::binder::Status TakesAnIBinder(const ::android::sp<::android::IBinder>& input) = 0;
   virtual ::android::binder::Status TakesANullableIBinder(const ::android::sp<::android::IBinder>& input) = 0;
+  virtual ::android::binder::Status TakesAnIBinderList(const ::std::vector<::android::sp<::android::IBinder>>& input) = 0;
+  virtual ::android::binder::Status TakesANullableIBinderList(const ::std::optional<::std::vector<::android::sp<::android::IBinder>>>& input) = 0;
   virtual ::android::binder::Status RepeatUtf8CppString(const ::std::string& token, ::std::string* _aidl_return) = 0;
   virtual ::android::binder::Status RepeatNullableUtf8CppString(const ::std::optional<::std::string>& token, ::std::optional<::std::string>* _aidl_return) = 0;
   virtual ::android::binder::Status ReverseUtf8CppString(const ::std::vector<::std::string>& input, ::std::vector<::std::string>* repeated, ::std::vector<::std::string>* _aidl_return) = 0;
@@ -155,6 +266,10 @@
   virtual ::android::binder::Status ReverseUtf8CppStringList(const ::std::optional<::std::vector<::std::optional<::std::string>>>& input, ::std::optional<::std::vector<::std::optional<::std::string>>>* repeated, ::std::optional<::std::vector<::std::optional<::std::string>>>* _aidl_return) = 0;
   virtual ::android::binder::Status GetCallback(bool return_null, ::android::sp<::android::aidl::tests::INamedCallback>* _aidl_return) = 0;
   virtual ::android::binder::Status FillOutStructuredParcelable(::android::aidl::tests::StructuredParcelable* parcel) = 0;
+  virtual ::android::binder::Status RepeatExtendableParcelable(const ::android::aidl::tests::extension::ExtendableParcelable& ep, ::android::aidl::tests::extension::ExtendableParcelable* ep2) = 0;
+  virtual ::android::binder::Status ReverseList(const ::android::aidl::tests::RecursiveList& list, ::android::aidl::tests::RecursiveList* _aidl_return) = 0;
+  virtual ::android::binder::Status ReverseIBinderArray(const ::std::vector<::android::sp<::android::IBinder>>& input, ::std::vector<::android::sp<::android::IBinder>>* repeated, ::std::vector<::android::sp<::android::IBinder>>* _aidl_return) = 0;
+  virtual ::android::binder::Status ReverseNullableIBinderArray(const ::std::optional<::std::vector<::android::sp<::android::IBinder>>>& input, ::std::optional<::std::vector<::android::sp<::android::IBinder>>>* repeated, ::std::optional<::std::vector<::android::sp<::android::IBinder>>>* _aidl_return) = 0;
   virtual ::android::binder::Status GetOldNameInterface(::android::sp<::android::aidl::tests::IOldName>* _aidl_return) = 0;
   virtual ::android::binder::Status GetNewNameInterface(::android::sp<::android::aidl::tests::INewName>* _aidl_return) = 0;
   virtual ::android::binder::Status GetCppJavaTests(::android::sp<::android::IBinder>* _aidl_return) = 0;
@@ -166,7 +281,7 @@
   ::android::IBinder* onAsBinder() override {
     return nullptr;
   }
-  ::android::binder::Status UnimplementedMethod(int32_t, int32_t*) override {
+  ::android::binder::Status UnimplementedMethod(int32_t /*arg*/, int32_t* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
   ::android::binder::Status Deprecated() override __attribute__((deprecated("to make sure we have something in system/tools/aidl which does a compile check of deprecated and make sure this is reflected in goldens"))) {
@@ -175,154 +290,193 @@
   ::android::binder::Status TestOneway() override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatBoolean(bool, bool*) override {
+  ::android::binder::Status RepeatBoolean(bool /*token*/, bool* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatByte(int8_t, int8_t*) override {
+  ::android::binder::Status RepeatByte(int8_t /*token*/, int8_t* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatChar(char16_t, char16_t*) override {
+  ::android::binder::Status RepeatChar(char16_t /*token*/, char16_t* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatInt(int32_t, int32_t*) override {
+  ::android::binder::Status RepeatInt(int32_t /*token*/, int32_t* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatLong(int64_t, int64_t*) override {
+  ::android::binder::Status RepeatLong(int64_t /*token*/, int64_t* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatFloat(float, float*) override {
+  ::android::binder::Status RepeatFloat(float /*token*/, float* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatDouble(double, double*) override {
+  ::android::binder::Status RepeatDouble(double /*token*/, double* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatString(const ::android::String16&, ::android::String16*) override {
+  ::android::binder::Status RepeatString(const ::android::String16& /*token*/, ::android::String16* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatByteEnum(::android::aidl::tests::ByteEnum, ::android::aidl::tests::ByteEnum*) override {
+  ::android::binder::Status RepeatByteEnum(::android::aidl::tests::ByteEnum /*token*/, ::android::aidl::tests::ByteEnum* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatIntEnum(::android::aidl::tests::IntEnum, ::android::aidl::tests::IntEnum*) override {
+  ::android::binder::Status RepeatIntEnum(::android::aidl::tests::IntEnum /*token*/, ::android::aidl::tests::IntEnum* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatLongEnum(::android::aidl::tests::LongEnum, ::android::aidl::tests::LongEnum*) override {
+  ::android::binder::Status RepeatLongEnum(::android::aidl::tests::LongEnum /*token*/, ::android::aidl::tests::LongEnum* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseBoolean(const ::std::vector<bool>&, ::std::vector<bool>*, ::std::vector<bool>*) override {
+  ::android::binder::Status ReverseBoolean(const ::std::vector<bool>& /*input*/, ::std::vector<bool>* /*repeated*/, ::std::vector<bool>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseByte(const ::std::vector<uint8_t>&, ::std::vector<uint8_t>*, ::std::vector<uint8_t>*) override {
+  ::android::binder::Status ReverseByte(const ::std::vector<uint8_t>& /*input*/, ::std::vector<uint8_t>* /*repeated*/, ::std::vector<uint8_t>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseChar(const ::std::vector<char16_t>&, ::std::vector<char16_t>*, ::std::vector<char16_t>*) override {
+  ::android::binder::Status ReverseChar(const ::std::vector<char16_t>& /*input*/, ::std::vector<char16_t>* /*repeated*/, ::std::vector<char16_t>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseInt(const ::std::vector<int32_t>&, ::std::vector<int32_t>*, ::std::vector<int32_t>*) override {
+  ::android::binder::Status ReverseInt(const ::std::vector<int32_t>& /*input*/, ::std::vector<int32_t>* /*repeated*/, ::std::vector<int32_t>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseLong(const ::std::vector<int64_t>&, ::std::vector<int64_t>*, ::std::vector<int64_t>*) override {
+  ::android::binder::Status ReverseLong(const ::std::vector<int64_t>& /*input*/, ::std::vector<int64_t>* /*repeated*/, ::std::vector<int64_t>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseFloat(const ::std::vector<float>&, ::std::vector<float>*, ::std::vector<float>*) override {
+  ::android::binder::Status ReverseFloat(const ::std::vector<float>& /*input*/, ::std::vector<float>* /*repeated*/, ::std::vector<float>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseDouble(const ::std::vector<double>&, ::std::vector<double>*, ::std::vector<double>*) override {
+  ::android::binder::Status ReverseDouble(const ::std::vector<double>& /*input*/, ::std::vector<double>* /*repeated*/, ::std::vector<double>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseString(const ::std::vector<::android::String16>&, ::std::vector<::android::String16>*, ::std::vector<::android::String16>*) override {
+  ::android::binder::Status ReverseString(const ::std::vector<::android::String16>& /*input*/, ::std::vector<::android::String16>* /*repeated*/, ::std::vector<::android::String16>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseByteEnum(const ::std::vector<::android::aidl::tests::ByteEnum>&, ::std::vector<::android::aidl::tests::ByteEnum>*, ::std::vector<::android::aidl::tests::ByteEnum>*) override {
+  ::android::binder::Status ReverseByteEnum(const ::std::vector<::android::aidl::tests::ByteEnum>& /*input*/, ::std::vector<::android::aidl::tests::ByteEnum>* /*repeated*/, ::std::vector<::android::aidl::tests::ByteEnum>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseIntEnum(const ::std::vector<::android::aidl::tests::IntEnum>&, ::std::vector<::android::aidl::tests::IntEnum>*, ::std::vector<::android::aidl::tests::IntEnum>*) override {
+  ::android::binder::Status ReverseIntEnum(const ::std::vector<::android::aidl::tests::IntEnum>& /*input*/, ::std::vector<::android::aidl::tests::IntEnum>* /*repeated*/, ::std::vector<::android::aidl::tests::IntEnum>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseLongEnum(const ::std::vector<::android::aidl::tests::LongEnum>&, ::std::vector<::android::aidl::tests::LongEnum>*, ::std::vector<::android::aidl::tests::LongEnum>*) override {
+  ::android::binder::Status ReverseLongEnum(const ::std::vector<::android::aidl::tests::LongEnum>& /*input*/, ::std::vector<::android::aidl::tests::LongEnum>* /*repeated*/, ::std::vector<::android::aidl::tests::LongEnum>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status GetOtherTestService(const ::android::String16&, ::android::sp<::android::aidl::tests::INamedCallback>*) override {
+  ::android::binder::Status GetOtherTestService(const ::android::String16& /*name*/, ::android::sp<::android::aidl::tests::INamedCallback>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status VerifyName(const ::android::sp<::android::aidl::tests::INamedCallback>&, const ::android::String16&, bool*) override {
+  ::android::binder::Status VerifyName(const ::android::sp<::android::aidl::tests::INamedCallback>& /*service*/, const ::android::String16& /*name*/, bool* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseStringList(const ::std::vector<::android::String16>&, ::std::vector<::android::String16>*, ::std::vector<::android::String16>*) override {
+  ::android::binder::Status GetInterfaceArray(const ::std::vector<::android::String16>& /*names*/, ::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatParcelFileDescriptor(const ::android::os::ParcelFileDescriptor&, ::android::os::ParcelFileDescriptor*) override {
+  ::android::binder::Status VerifyNamesWithInterfaceArray(const ::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>& /*services*/, const ::std::vector<::android::String16>& /*names*/, bool* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseParcelFileDescriptorArray(const ::std::vector<::android::os::ParcelFileDescriptor>&, ::std::vector<::android::os::ParcelFileDescriptor>*, ::std::vector<::android::os::ParcelFileDescriptor>*) override {
+  ::android::binder::Status GetNullableInterfaceArray(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& /*names*/, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ThrowServiceException(int32_t) override {
+  ::android::binder::Status VerifyNamesWithNullableInterfaceArray(const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>& /*services*/, const ::std::optional<::std::vector<::std::optional<::android::String16>>>& /*names*/, bool* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatNullableIntArray(const ::std::optional<::std::vector<int32_t>>&, ::std::optional<::std::vector<int32_t>>*) override {
+  ::android::binder::Status GetInterfaceList(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& /*names*/, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatNullableByteEnumArray(const ::std::optional<::std::vector<::android::aidl::tests::ByteEnum>>&, ::std::optional<::std::vector<::android::aidl::tests::ByteEnum>>*) override {
+  ::android::binder::Status VerifyNamesWithInterfaceList(const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::INamedCallback>>>& /*services*/, const ::std::optional<::std::vector<::std::optional<::android::String16>>>& /*names*/, bool* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatNullableIntEnumArray(const ::std::optional<::std::vector<::android::aidl::tests::IntEnum>>&, ::std::optional<::std::vector<::android::aidl::tests::IntEnum>>*) override {
+  ::android::binder::Status ReverseStringList(const ::std::vector<::android::String16>& /*input*/, ::std::vector<::android::String16>* /*repeated*/, ::std::vector<::android::String16>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatNullableLongEnumArray(const ::std::optional<::std::vector<::android::aidl::tests::LongEnum>>&, ::std::optional<::std::vector<::android::aidl::tests::LongEnum>>*) override {
+  ::android::binder::Status RepeatParcelFileDescriptor(const ::android::os::ParcelFileDescriptor& /*read*/, ::android::os::ParcelFileDescriptor* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatNullableString(const ::std::optional<::android::String16>&, ::std::optional<::android::String16>*) override {
+  ::android::binder::Status ReverseParcelFileDescriptorArray(const ::std::vector<::android::os::ParcelFileDescriptor>& /*input*/, ::std::vector<::android::os::ParcelFileDescriptor>* /*repeated*/, ::std::vector<::android::os::ParcelFileDescriptor>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatNullableStringList(const ::std::optional<::std::vector<::std::optional<::android::String16>>>&, ::std::optional<::std::vector<::std::optional<::android::String16>>>*) override {
+  ::android::binder::Status ThrowServiceException(int32_t /*code*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatNullableParcelable(const ::std::optional<::android::aidl::tests::StructuredParcelable>&, ::std::optional<::android::aidl::tests::StructuredParcelable>*) override {
+  ::android::binder::Status RepeatNullableIntArray(const ::std::optional<::std::vector<int32_t>>& /*input*/, ::std::optional<::std::vector<int32_t>>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status TakesAnIBinder(const ::android::sp<::android::IBinder>&) override {
+  ::android::binder::Status RepeatNullableByteEnumArray(const ::std::optional<::std::vector<::android::aidl::tests::ByteEnum>>& /*input*/, ::std::optional<::std::vector<::android::aidl::tests::ByteEnum>>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status TakesANullableIBinder(const ::android::sp<::android::IBinder>&) override {
+  ::android::binder::Status RepeatNullableIntEnumArray(const ::std::optional<::std::vector<::android::aidl::tests::IntEnum>>& /*input*/, ::std::optional<::std::vector<::android::aidl::tests::IntEnum>>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatUtf8CppString(const ::std::string&, ::std::string*) override {
+  ::android::binder::Status RepeatNullableLongEnumArray(const ::std::optional<::std::vector<::android::aidl::tests::LongEnum>>& /*input*/, ::std::optional<::std::vector<::android::aidl::tests::LongEnum>>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status RepeatNullableUtf8CppString(const ::std::optional<::std::string>&, ::std::optional<::std::string>*) override {
+  ::android::binder::Status RepeatNullableString(const ::std::optional<::android::String16>& /*input*/, ::std::optional<::android::String16>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseUtf8CppString(const ::std::vector<::std::string>&, ::std::vector<::std::string>*, ::std::vector<::std::string>*) override {
+  ::android::binder::Status RepeatNullableStringList(const ::std::optional<::std::vector<::std::optional<::android::String16>>>& /*input*/, ::std::optional<::std::vector<::std::optional<::android::String16>>>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseNullableUtf8CppString(const ::std::optional<::std::vector<::std::optional<::std::string>>>&, ::std::optional<::std::vector<::std::optional<::std::string>>>*, ::std::optional<::std::vector<::std::optional<::std::string>>>*) override {
+  ::android::binder::Status RepeatNullableParcelable(const ::std::optional<::android::aidl::tests::ITestService::Empty>& /*input*/, ::std::optional<::android::aidl::tests::ITestService::Empty>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status ReverseUtf8CppStringList(const ::std::optional<::std::vector<::std::optional<::std::string>>>&, ::std::optional<::std::vector<::std::optional<::std::string>>>*, ::std::optional<::std::vector<::std::optional<::std::string>>>*) override {
+  ::android::binder::Status RepeatNullableParcelableArray(const ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>& /*input*/, ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status GetCallback(bool, ::android::sp<::android::aidl::tests::INamedCallback>*) override {
+  ::android::binder::Status RepeatNullableParcelableList(const ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>& /*input*/, ::std::optional<::std::vector<::std::optional<::android::aidl::tests::ITestService::Empty>>>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status FillOutStructuredParcelable(::android::aidl::tests::StructuredParcelable*) override {
+  ::android::binder::Status TakesAnIBinder(const ::android::sp<::android::IBinder>& /*input*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status GetOldNameInterface(::android::sp<::android::aidl::tests::IOldName>*) override {
+  ::android::binder::Status TakesANullableIBinder(const ::android::sp<::android::IBinder>& /*input*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status GetNewNameInterface(::android::sp<::android::aidl::tests::INewName>*) override {
+  ::android::binder::Status TakesAnIBinderList(const ::std::vector<::android::sp<::android::IBinder>>& /*input*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status GetCppJavaTests(::android::sp<::android::IBinder>*) override {
+  ::android::binder::Status TakesANullableIBinderList(const ::std::optional<::std::vector<::android::sp<::android::IBinder>>>& /*input*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
-  ::android::binder::Status getBackendType(::android::aidl::tests::BackendType*) override {
+  ::android::binder::Status RepeatUtf8CppString(const ::std::string& /*token*/, ::std::string* /*_aidl_return*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status RepeatNullableUtf8CppString(const ::std::optional<::std::string>& /*token*/, ::std::optional<::std::string>* /*_aidl_return*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status ReverseUtf8CppString(const ::std::vector<::std::string>& /*input*/, ::std::vector<::std::string>* /*repeated*/, ::std::vector<::std::string>* /*_aidl_return*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status ReverseNullableUtf8CppString(const ::std::optional<::std::vector<::std::optional<::std::string>>>& /*input*/, ::std::optional<::std::vector<::std::optional<::std::string>>>* /*repeated*/, ::std::optional<::std::vector<::std::optional<::std::string>>>* /*_aidl_return*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status ReverseUtf8CppStringList(const ::std::optional<::std::vector<::std::optional<::std::string>>>& /*input*/, ::std::optional<::std::vector<::std::optional<::std::string>>>* /*repeated*/, ::std::optional<::std::vector<::std::optional<::std::string>>>* /*_aidl_return*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status GetCallback(bool /*return_null*/, ::android::sp<::android::aidl::tests::INamedCallback>* /*_aidl_return*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status FillOutStructuredParcelable(::android::aidl::tests::StructuredParcelable* /*parcel*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status RepeatExtendableParcelable(const ::android::aidl::tests::extension::ExtendableParcelable& /*ep*/, ::android::aidl::tests::extension::ExtendableParcelable* /*ep2*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status ReverseList(const ::android::aidl::tests::RecursiveList& /*list*/, ::android::aidl::tests::RecursiveList* /*_aidl_return*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status ReverseIBinderArray(const ::std::vector<::android::sp<::android::IBinder>>& /*input*/, ::std::vector<::android::sp<::android::IBinder>>* /*repeated*/, ::std::vector<::android::sp<::android::IBinder>>* /*_aidl_return*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status ReverseNullableIBinderArray(const ::std::optional<::std::vector<::android::sp<::android::IBinder>>>& /*input*/, ::std::optional<::std::vector<::android::sp<::android::IBinder>>>* /*repeated*/, ::std::optional<::std::vector<::android::sp<::android::IBinder>>>* /*_aidl_return*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status GetOldNameInterface(::android::sp<::android::aidl::tests::IOldName>* /*_aidl_return*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status GetNewNameInterface(::android::sp<::android::aidl::tests::INewName>* /*_aidl_return*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status GetCppJavaTests(::android::sp<::android::IBinder>* /*_aidl_return*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status getBackendType(::android::aidl::tests::BackendType* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
 };  // class ITestServiceDefault
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/IntEnum.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/IntEnum.h
index 50b1b60..00e8738 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/IntEnum.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/IntEnum.h
@@ -6,17 +6,19 @@
 #include <string>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 enum class IntEnum : int32_t {
   FOO = 1000,
   BAR = 2000,
   BAZ = 2001,
 };
-
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace aidl {
+namespace tests {
 [[nodiscard]] static inline std::string toString(IntEnum val) {
   switch(val) {
   case IntEnum::FOO:
@@ -29,16 +31,11 @@
     return std::to_string(static_cast<int32_t>(val));
   }
 }
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 namespace android {
-
 namespace internal {
-
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wc++17-extensions"
 template <>
@@ -48,7 +45,5 @@
   ::android::aidl::tests::IntEnum::BAZ,
 };
 #pragma clang diagnostic pop
-
 }  // namespace internal
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ListOfInterfaces.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ListOfInterfaces.h
new file mode 100644
index 0000000..696c816
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ListOfInterfaces.h
@@ -0,0 +1,265 @@
+#pragma once
+
+#include <android/aidl/tests/ListOfInterfaces.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 ListOfInterfaces : public ::android::Parcelable {
+public:
+  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::ListOfInterfaces::IEmptyInterface>& iface, const ::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>& nullable_iface, const ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>& iface_list_in, ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* iface_list_out, ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* iface_list_inout, const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>& nullable_iface_list_in, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* nullable_iface_list_out, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* nullable_iface_list_inout, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::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::ListOfInterfaces::IEmptyInterface>& /*iface*/, const ::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>& /*nullable_iface*/, const ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>& /*iface_list_in*/, ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* /*iface_list_out*/, ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* /*iface_list_inout*/, const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>& /*nullable_iface_list_in*/, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* /*nullable_iface_list_out*/, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* /*nullable_iface_list_inout*/, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* /*_aidl_return*/) 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::ListOfInterfaces::IEmptyInterface>& iface, const ::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>& nullable_iface, const ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>& iface_list_in, ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* iface_list_out, ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* iface_list_inout, const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>& nullable_iface_list_in, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* nullable_iface_list_out, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* nullable_iface_list_inout, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::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::ListOfInterfaces::IEmptyInterface>& iface, const ::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>& nullable_iface, const ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>& iface_list_in, ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* iface_list_out, ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* iface_list_inout, const ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>& nullable_iface_list_in, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* nullable_iface_list_out, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* nullable_iface_list_inout, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* _aidl_return) override {
+      return _aidl_delegate->methodWithInterfaces(iface, nullable_iface, iface_list_in, iface_list_out, iface_list_inout, nullable_iface_list_in, nullable_iface_list_out, nullable_iface_list_inout, _aidl_return);
+    }
+  private:
+    ::android::sp<IMyInterface> _aidl_delegate;
+  };  // class IMyInterfaceDelegator
+  class MyParcelable : public ::android::Parcelable {
+  public:
+    ::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface> iface;
+    ::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface> nullable_iface;
+    ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>> iface_list;
+    ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>> nullable_iface_list;
+    inline bool operator!=(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_list, nullable_iface_list) != std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_list, rhs.nullable_iface_list);
+    }
+    inline bool operator<(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_list, nullable_iface_list) < std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_list, rhs.nullable_iface_list);
+    }
+    inline bool operator<=(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_list, nullable_iface_list) <= std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_list, rhs.nullable_iface_list);
+    }
+    inline bool operator==(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_list, nullable_iface_list) == std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_list, rhs.nullable_iface_list);
+    }
+    inline bool operator>(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_list, nullable_iface_list) > std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_list, rhs.nullable_iface_list);
+    }
+    inline bool operator>=(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_list, nullable_iface_list) >= std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_list, rhs.nullable_iface_list);
+    }
+
+    ::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.ListOfInterfaces.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_list: " << ::android::internal::ToString(iface_list);
+      os << ", nullable_iface_list: " << ::android::internal::ToString(nullable_iface_list);
+      os << "}";
+      return os.str();
+    }
+  };  // class MyParcelable
+  class MyUnion : public ::android::Parcelable {
+  public:
+    enum Tag : int32_t {
+      iface = 0,  // android.aidl.tests.ListOfInterfaces.IEmptyInterface iface;
+      nullable_iface,  // android.aidl.tests.ListOfInterfaces.IEmptyInterface nullable_iface;
+      iface_list,  // List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list;
+      nullable_iface_list,  // List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list;
+    };
+
+    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::ListOfInterfaces::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)...);
+    }
+
+    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;
+    }
+
+    ::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.ListOfInterfaces.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_list: os << "iface_list: " << ::android::internal::ToString(get<iface_list>()); break;
+      case nullable_iface_list: os << "nullable_iface_list: " << ::android::internal::ToString(get<nullable_iface_list>()); break;
+      }
+      os << "}";
+      return os.str();
+    }
+  private:
+    std::variant<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>, ::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>, ::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>, ::std::optional<::std::vector<::android::sp<::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>> _value;
+  };  // class MyUnion
+  inline bool operator!=(const ListOfInterfaces&) const {
+    return std::tie() != std::tie();
+  }
+  inline bool operator<(const ListOfInterfaces&) const {
+    return std::tie() < std::tie();
+  }
+  inline bool operator<=(const ListOfInterfaces&) const {
+    return std::tie() <= std::tie();
+  }
+  inline bool operator==(const ListOfInterfaces&) const {
+    return std::tie() == std::tie();
+  }
+  inline bool operator>(const ListOfInterfaces&) const {
+    return std::tie() > std::tie();
+  }
+  inline bool operator>=(const ListOfInterfaces&) const {
+    return std::tie() >= std::tie();
+  }
+
+  ::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.ListOfInterfaces");
+    return DESCIPTOR;
+  }
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "ListOfInterfaces{";
+    os << "}";
+    return os.str();
+  }
+};  // class ListOfInterfaces
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/LongEnum.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/LongEnum.h
index 8caa3aa..8022f6b 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/LongEnum.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/LongEnum.h
@@ -6,17 +6,19 @@
 #include <string>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 enum class LongEnum : int64_t {
   FOO = 100000000000L,
   BAR = 200000000000L,
   BAZ = 200000000001L,
 };
-
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace aidl {
+namespace tests {
 [[nodiscard]] static inline std::string toString(LongEnum val) {
   switch(val) {
   case LongEnum::FOO:
@@ -29,16 +31,11 @@
     return std::to_string(static_cast<int64_t>(val));
   }
 }
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
 namespace android {
-
 namespace internal {
-
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wc++17-extensions"
 template <>
@@ -48,7 +45,5 @@
   ::android::aidl::tests::LongEnum::BAZ,
 };
 #pragma clang diagnostic pop
-
 }  // namespace internal
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/OtherParcelableForToString.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/OtherParcelableForToString.h
index 7eb72e9..fa05b15 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/OtherParcelableForToString.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/OtherParcelableForToString.h
@@ -7,13 +7,11 @@
 #include <utils/String16.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class OtherParcelableForToString : public ::android::Parcelable {
 public:
+  ::android::String16 field;
   inline bool operator!=(const OtherParcelableForToString& rhs) const {
     return std::tie(field) != std::tie(rhs.field);
   }
@@ -33,7 +31,6 @@
     return std::tie(field) >= std::tie(rhs.field);
   }
 
-  ::android::String16 field;
   ::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() {
@@ -48,9 +45,6 @@
     return os.str();
   }
 };  // class OtherParcelableForToString
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ParcelableForToString.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ParcelableForToString.h
index 39e64be..7f3adf7 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ParcelableForToString.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/ParcelableForToString.h
@@ -14,13 +14,33 @@
 #include <vector>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class ParcelableForToString : public ::android::Parcelable {
 public:
+  int32_t intValue = 0;
+  ::std::vector<int32_t> intArray;
+  int64_t longValue = 0L;
+  ::std::vector<int64_t> longArray;
+  double doubleValue = 0.000000;
+  ::std::vector<double> doubleArray;
+  float floatValue = 0.000000f;
+  ::std::vector<float> floatArray;
+  int8_t byteValue = 0;
+  ::std::vector<uint8_t> byteArray;
+  bool booleanValue = false;
+  ::std::vector<bool> booleanArray;
+  ::android::String16 stringValue;
+  ::std::vector<::android::String16> stringArray;
+  ::std::vector<::android::String16> stringList;
+  ::android::aidl::tests::OtherParcelableForToString parcelableValue;
+  ::std::vector<::android::aidl::tests::OtherParcelableForToString> parcelableArray;
+  ::android::aidl::tests::IntEnum enumValue = ::android::aidl::tests::IntEnum::FOO;
+  ::std::vector<::android::aidl::tests::IntEnum> enumArray;
+  ::std::vector<::android::String16> nullArray;
+  ::std::vector<::android::String16> nullList;
+  ::android::aidl::tests::GenericStructuredParcelable<int32_t, ::android::aidl::tests::StructuredParcelable, ::android::aidl::tests::IntEnum> parcelableGeneric;
+  ::android::aidl::tests::Union unionValue;
   inline bool operator!=(const ParcelableForToString& rhs) const {
     return std::tie(intValue, intArray, longValue, longArray, doubleValue, doubleArray, floatValue, floatArray, byteValue, byteArray, booleanValue, booleanArray, stringValue, stringArray, stringList, parcelableValue, parcelableArray, enumValue, enumArray, nullArray, nullList, parcelableGeneric, unionValue) != std::tie(rhs.intValue, rhs.intArray, rhs.longValue, rhs.longArray, rhs.doubleValue, rhs.doubleArray, rhs.floatValue, rhs.floatArray, rhs.byteValue, rhs.byteArray, rhs.booleanValue, rhs.booleanArray, rhs.stringValue, rhs.stringArray, rhs.stringList, rhs.parcelableValue, rhs.parcelableArray, rhs.enumValue, rhs.enumArray, rhs.nullArray, rhs.nullList, rhs.parcelableGeneric, rhs.unionValue);
   }
@@ -40,29 +60,6 @@
     return std::tie(intValue, intArray, longValue, longArray, doubleValue, doubleArray, floatValue, floatArray, byteValue, byteArray, booleanValue, booleanArray, stringValue, stringArray, stringList, parcelableValue, parcelableArray, enumValue, enumArray, nullArray, nullList, parcelableGeneric, unionValue) >= std::tie(rhs.intValue, rhs.intArray, rhs.longValue, rhs.longArray, rhs.doubleValue, rhs.doubleArray, rhs.floatValue, rhs.floatArray, rhs.byteValue, rhs.byteArray, rhs.booleanValue, rhs.booleanArray, rhs.stringValue, rhs.stringArray, rhs.stringList, rhs.parcelableValue, rhs.parcelableArray, rhs.enumValue, rhs.enumArray, rhs.nullArray, rhs.nullList, rhs.parcelableGeneric, rhs.unionValue);
   }
 
-  int32_t intValue = int32_t(0);
-  ::std::vector<int32_t> intArray;
-  int64_t longValue = int64_t(0L);
-  ::std::vector<int64_t> longArray;
-  double doubleValue = double(0.000000);
-  ::std::vector<double> doubleArray;
-  float floatValue = float(0.000000f);
-  ::std::vector<float> floatArray;
-  int8_t byteValue = int8_t(0);
-  ::std::vector<uint8_t> byteArray;
-  bool booleanValue = bool(false);
-  ::std::vector<bool> booleanArray;
-  ::android::String16 stringValue;
-  ::std::vector<::android::String16> stringArray;
-  ::std::vector<::android::String16> stringList;
-  ::android::aidl::tests::OtherParcelableForToString parcelableValue;
-  ::std::vector<::android::aidl::tests::OtherParcelableForToString> parcelableArray;
-  ::android::aidl::tests::IntEnum enumValue = ::android::aidl::tests::IntEnum(::android::aidl::tests::IntEnum::FOO);
-  ::std::vector<::android::aidl::tests::IntEnum> enumArray;
-  ::std::vector<::android::String16> nullArray;
-  ::std::vector<::android::String16> nullList;
-  ::android::aidl::tests::GenericStructuredParcelable<int32_t, ::android::aidl::tests::StructuredParcelable, ::android::aidl::tests::IntEnum> parcelableGeneric;
-  ::android::aidl::tests::Union unionValue;
   ::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() {
@@ -99,9 +96,6 @@
     return os.str();
   }
 };  // class ParcelableForToString
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/RecursiveList.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/RecursiveList.h
new file mode 100644
index 0000000..d874d9f
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/RecursiveList.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <android/aidl/tests/RecursiveList.h>
+#include <android/binder_to_string.h>
+#include <binder/Parcel.h>
+#include <binder/Status.h>
+#include <cstdint>
+#include <optional>
+#include <tuple>
+#include <utils/String16.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+class RecursiveList : public ::android::Parcelable {
+public:
+  int32_t value = 0;
+  ::std::unique_ptr<::android::aidl::tests::RecursiveList> next;
+  inline bool operator!=(const RecursiveList& rhs) const {
+    return std::tie(value, next) != std::tie(rhs.value, rhs.next);
+  }
+  inline bool operator<(const RecursiveList& rhs) const {
+    return std::tie(value, next) < std::tie(rhs.value, rhs.next);
+  }
+  inline bool operator<=(const RecursiveList& rhs) const {
+    return std::tie(value, next) <= std::tie(rhs.value, rhs.next);
+  }
+  inline bool operator==(const RecursiveList& rhs) const {
+    return std::tie(value, next) == std::tie(rhs.value, rhs.next);
+  }
+  inline bool operator>(const RecursiveList& rhs) const {
+    return std::tie(value, next) > std::tie(rhs.value, rhs.next);
+  }
+  inline bool operator>=(const RecursiveList& rhs) const {
+    return std::tie(value, next) >= std::tie(rhs.value, rhs.next);
+  }
+
+  ::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.RecursiveList");
+    return DESCIPTOR;
+  }
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "RecursiveList{";
+    os << "value: " << ::android::internal::ToString(value);
+    os << ", next: " << ::android::internal::ToString(next);
+    os << "}";
+    return os.str();
+  }
+};  // class RecursiveList
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/StructuredParcelable.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/StructuredParcelable.h
index bfd1e58..339c516 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/StructuredParcelable.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/StructuredParcelable.h
@@ -4,6 +4,7 @@
 #include <android/aidl/tests/ConstantExpressionEnum.h>
 #include <android/aidl/tests/IntEnum.h>
 #include <android/aidl/tests/LongEnum.h>
+#include <android/aidl/tests/StructuredParcelable.h>
 #include <android/aidl/tests/Union.h>
 #include <android/binder_to_string.h>
 #include <binder/IBinder.h>
@@ -17,34 +18,46 @@
 #include <vector>
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class StructuredParcelable : public ::android::Parcelable {
 public:
-  inline bool operator!=(const StructuredParcelable& rhs) const {
-    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) != std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
-  }
-  inline bool operator<(const StructuredParcelable& rhs) const {
-    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) < std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
-  }
-  inline bool operator<=(const StructuredParcelable& rhs) const {
-    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) <= std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
-  }
-  inline bool operator==(const StructuredParcelable& rhs) const {
-    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) == std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
-  }
-  inline bool operator>(const StructuredParcelable& rhs) const {
-    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) > std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
-  }
-  inline bool operator>=(const StructuredParcelable& rhs) const {
-    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) >= std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
-  }
+  class Empty : public ::android::Parcelable {
+  public:
+    inline bool operator!=(const Empty&) const {
+      return std::tie() != std::tie();
+    }
+    inline bool operator<(const Empty&) const {
+      return std::tie() < std::tie();
+    }
+    inline bool operator<=(const Empty&) const {
+      return std::tie() <= std::tie();
+    }
+    inline bool operator==(const Empty&) const {
+      return std::tie() == std::tie();
+    }
+    inline bool operator>(const Empty&) const {
+      return std::tie() > std::tie();
+    }
+    inline bool operator>=(const Empty&) const {
+      return std::tie() >= std::tie();
+    }
 
+    ::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.StructuredParcelable.Empty");
+      return DESCIPTOR;
+    }
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "Empty{";
+      os << "}";
+      return os.str();
+    }
+  };  // class Empty
   ::std::vector<int32_t> shouldContainThreeFs;
-  int32_t f = int32_t(0);
+  int32_t f = 0;
   ::std::string shouldBeJerry;
   ::android::aidl::tests::ByteEnum shouldBeByteBar = ::android::aidl::tests::ByteEnum(0);
   ::android::aidl::tests::IntEnum shouldBeIntBar = ::android::aidl::tests::IntEnum(0);
@@ -52,34 +65,36 @@
   ::std::vector<::android::aidl::tests::ByteEnum> shouldContainTwoByteFoos;
   ::std::vector<::android::aidl::tests::IntEnum> shouldContainTwoIntFoos;
   ::std::vector<::android::aidl::tests::LongEnum> shouldContainTwoLongFoos;
-  ::android::String16 stringDefaultsToFoo = ::android::String16(::android::String16("foo"));
-  int8_t byteDefaultsToFour = int8_t(4);
-  int32_t intDefaultsToFive = int32_t(5);
-  int64_t longDefaultsToNegativeSeven = int64_t(-7L);
-  bool booleanDefaultsToTrue = bool(true);
-  char16_t charDefaultsToC = char16_t('C');
-  float floatDefaultsToPi = float(3.140000f);
-  double doubleWithDefault = double(-314000000000000000.000000);
-  ::std::vector<int32_t> arrayDefaultsTo123 = ::std::vector<int32_t>({1, 2, 3});
-  ::std::vector<int32_t> arrayDefaultsToEmpty = ::std::vector<int32_t>({});
-  bool boolDefault = bool(false);
-  int8_t byteDefault = int8_t(0);
-  int32_t intDefault = int32_t(0);
-  int64_t longDefault = int64_t(0L);
-  float floatDefault = float(0.000000f);
-  double doubleDefault = double(0.000000);
-  double checkDoubleFromFloat = double(3.140000);
-  ::std::vector<::android::String16> checkStringArray1 = ::std::vector<::android::String16>({::android::String16("a"), ::android::String16("b")});
-  ::std::vector<::std::string> checkStringArray2 = ::std::vector<::std::string>({"a", "b"});
-  int32_t int32_min = int32_t(-2147483648);
-  int32_t int32_max = int32_t(2147483647);
-  int64_t int64_max = int64_t(9223372036854775807L);
-  int32_t hexInt32_neg_1 = int32_t(-1);
+  ::android::String16 stringDefaultsToFoo = ::android::String16("foo");
+  int8_t byteDefaultsToFour = 4;
+  int32_t intDefaultsToFive = 5;
+  int64_t longDefaultsToNegativeSeven = -7L;
+  bool booleanDefaultsToTrue = true;
+  char16_t charDefaultsToC = 'C';
+  float floatDefaultsToPi = 3.140000f;
+  double doubleWithDefault = -314000000000000000.000000;
+  ::std::vector<int32_t> arrayDefaultsTo123 = {1, 2, 3};
+  ::std::vector<int32_t> arrayDefaultsToEmpty = {};
+  bool boolDefault = false;
+  int8_t byteDefault = 0;
+  int32_t intDefault = 0;
+  int64_t longDefault = 0L;
+  float floatDefault = 0.000000f;
+  double doubleDefault = 0.000000;
+  double checkDoubleFromFloat = 3.140000;
+  ::std::vector<::android::String16> checkStringArray1 = {::android::String16("a"), ::android::String16("b")};
+  ::std::vector<::std::string> checkStringArray2 = {"a", "b"};
+  int32_t int32_min = -2147483648;
+  int32_t int32_max = 2147483647;
+  int64_t int64_max = 9223372036854775807L;
+  int32_t hexInt32_neg_1 = -1;
   ::android::sp<::android::IBinder> ibinder;
-  ::std::vector<int32_t> int32_1 = ::std::vector<int32_t>({1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
-  ::std::vector<int64_t> int64_1 = ::std::vector<int64_t>({1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L});
-  int32_t hexInt32_pos_1 = int32_t(1);
-  int32_t hexInt64_pos_1 = int32_t(1);
+  ::android::aidl::tests::StructuredParcelable::Empty empty;
+  ::std::vector<uint8_t> int8_1 = {1, 1, 1, 1, 1};
+  ::std::vector<int32_t> int32_1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+  ::std::vector<int64_t> int64_1 = {1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L};
+  int32_t hexInt32_pos_1 = 1;
+  int32_t hexInt64_pos_1 = 1;
   ::android::aidl::tests::ConstantExpressionEnum const_exprs_1 = ::android::aidl::tests::ConstantExpressionEnum(0);
   ::android::aidl::tests::ConstantExpressionEnum const_exprs_2 = ::android::aidl::tests::ConstantExpressionEnum(0);
   ::android::aidl::tests::ConstantExpressionEnum const_exprs_3 = ::android::aidl::tests::ConstantExpressionEnum(0);
@@ -90,17 +105,34 @@
   ::android::aidl::tests::ConstantExpressionEnum const_exprs_8 = ::android::aidl::tests::ConstantExpressionEnum(0);
   ::android::aidl::tests::ConstantExpressionEnum const_exprs_9 = ::android::aidl::tests::ConstantExpressionEnum(0);
   ::android::aidl::tests::ConstantExpressionEnum const_exprs_10 = ::android::aidl::tests::ConstantExpressionEnum(0);
-  ::std::string addString1 = ::std::string("hello world!");
-  ::std::string addString2 = ::std::string("The quick brown fox jumps over the lazy dog.");
-  int32_t shouldSetBit0AndBit2 = int32_t(0);
+  ::std::string addString1 = "hello world!";
+  ::std::string addString2 = "The quick brown fox jumps over the lazy dog.";
+  int32_t shouldSetBit0AndBit2 = 0;
   ::std::optional<::android::aidl::tests::Union> u;
   ::std::optional<::android::aidl::tests::Union> shouldBeConstS1;
-  ::android::aidl::tests::IntEnum defaultWithFoo = ::android::aidl::tests::IntEnum(::android::aidl::tests::IntEnum::FOO);
-  enum  : int32_t {
-    BIT0 = 1,
-    BIT1 = 2,
-    BIT2 = 4,
-  };
+  ::android::aidl::tests::IntEnum defaultWithFoo = ::android::aidl::tests::IntEnum::FOO;
+  inline bool operator!=(const StructuredParcelable& rhs) const {
+    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, empty, int8_1, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) != std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.empty, rhs.int8_1, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
+  }
+  inline bool operator<(const StructuredParcelable& rhs) const {
+    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, empty, int8_1, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) < std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.empty, rhs.int8_1, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
+  }
+  inline bool operator<=(const StructuredParcelable& rhs) const {
+    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, empty, int8_1, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) <= std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.empty, rhs.int8_1, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
+  }
+  inline bool operator==(const StructuredParcelable& rhs) const {
+    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, empty, int8_1, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) == std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.empty, rhs.int8_1, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
+  }
+  inline bool operator>(const StructuredParcelable& rhs) const {
+    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, empty, int8_1, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) > std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.empty, rhs.int8_1, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
+  }
+  inline bool operator>=(const StructuredParcelable& rhs) const {
+    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, empty, int8_1, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) >= std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.empty, rhs.int8_1, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
+  }
+
+  enum : int32_t { BIT0 = 1 };
+  enum : int32_t { BIT1 = 2 };
+  enum : int32_t { BIT2 = 4 };
   ::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() {
@@ -143,6 +175,8 @@
     os << ", int64_max: " << ::android::internal::ToString(int64_max);
     os << ", hexInt32_neg_1: " << ::android::internal::ToString(hexInt32_neg_1);
     os << ", ibinder: " << ::android::internal::ToString(ibinder);
+    os << ", empty: " << ::android::internal::ToString(empty);
+    os << ", int8_1: " << ::android::internal::ToString(int8_1);
     os << ", int32_1: " << ::android::internal::ToString(int32_1);
     os << ", int64_1: " << ::android::internal::ToString(int64_1);
     os << ", hexInt32_pos_1: " << ::android::internal::ToString(hexInt32_pos_1);
@@ -167,9 +201,6 @@
     return os.str();
   }
 };  // class StructuredParcelable
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/Union.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/Union.h
index 1dffabb..62c1bf4 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/Union.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/Union.h
@@ -19,32 +19,10 @@
 #endif
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class Union : public ::android::Parcelable {
 public:
-  inline bool operator!=(const Union& rhs) const {
-    return _value != rhs._value;
-  }
-  inline bool operator<(const Union& rhs) const {
-    return _value < rhs._value;
-  }
-  inline bool operator<=(const Union& rhs) const {
-    return _value <= rhs._value;
-  }
-  inline bool operator==(const Union& rhs) const {
-    return _value == rhs._value;
-  }
-  inline bool operator>(const Union& rhs) const {
-    return _value > rhs._value;
-  }
-  inline bool operator>=(const Union& rhs) const {
-    return _value >= rhs._value;
-  }
-
   enum Tag : int32_t {
     ns = 0,  // int[] ns;
     n,  // int n;
@@ -59,10 +37,6 @@
   static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, Union>;
 
   Union() : _value(std::in_place_index<ns>, ::std::vector<int32_t>({})) { }
-  Union(const Union&) = default;
-  Union(Union&&) = default;
-  Union& operator=(const Union&) = default;
-  Union& operator=(Union&&) = default;
 
   template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
   // NOLINTNEXTLINE(google-explicit-constructor)
@@ -104,6 +78,25 @@
     _value.emplace<_tag>(std::forward<_Tp>(_args)...);
   }
 
+  inline bool operator!=(const Union& rhs) const {
+    return _value != rhs._value;
+  }
+  inline bool operator<(const Union& rhs) const {
+    return _value < rhs._value;
+  }
+  inline bool operator<=(const Union& rhs) const {
+    return _value <= rhs._value;
+  }
+  inline bool operator==(const Union& rhs) const {
+    return _value == rhs._value;
+  }
+  inline bool operator>(const Union& rhs) const {
+    return _value > rhs._value;
+  }
+  inline bool operator>=(const Union& rhs) const {
+    return _value >= rhs._value;
+  }
+
   static const ::std::string& S1();
   ::android::status_t readFromParcel(const ::android::Parcel* _aidl_parcel) final;
   ::android::status_t writeToParcel(::android::Parcel* _aidl_parcel) const final;
@@ -129,9 +122,6 @@
 private:
   std::variant<::std::vector<int32_t>, int32_t, int32_t, ::std::string, ::android::sp<::android::IBinder>, ::std::vector<::std::string>, ::android::aidl::tests::ByteEnum> _value;
 };  // class Union
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/UnionWithFd.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/UnionWithFd.h
index 7e4021f..373aba7 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/UnionWithFd.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/UnionWithFd.h
@@ -16,32 +16,10 @@
 #endif
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 class UnionWithFd : public ::android::Parcelable {
 public:
-  inline bool operator!=(const UnionWithFd& rhs) const {
-    return _value != rhs._value;
-  }
-  inline bool operator<(const UnionWithFd& rhs) const {
-    return _value < rhs._value;
-  }
-  inline bool operator<=(const UnionWithFd& rhs) const {
-    return _value <= rhs._value;
-  }
-  inline bool operator==(const UnionWithFd& rhs) const {
-    return _value == rhs._value;
-  }
-  inline bool operator>(const UnionWithFd& rhs) const {
-    return _value > rhs._value;
-  }
-  inline bool operator>=(const UnionWithFd& rhs) const {
-    return _value >= rhs._value;
-  }
-
   enum Tag : int32_t {
     num = 0,  // int num;
     pfd,  // ParcelFileDescriptor pfd;
@@ -51,10 +29,6 @@
   static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, UnionWithFd>;
 
   UnionWithFd() : _value(std::in_place_index<num>, int32_t(0)) { }
-  UnionWithFd(const UnionWithFd&) = default;
-  UnionWithFd(UnionWithFd&&) = default;
-  UnionWithFd& operator=(const UnionWithFd&) = default;
-  UnionWithFd& operator=(UnionWithFd&&) = default;
 
   template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
   // NOLINTNEXTLINE(google-explicit-constructor)
@@ -96,6 +70,25 @@
     _value.emplace<_tag>(std::forward<_Tp>(_args)...);
   }
 
+  inline bool operator!=(const UnionWithFd& rhs) const {
+    return _value != rhs._value;
+  }
+  inline bool operator<(const UnionWithFd& rhs) const {
+    return _value < rhs._value;
+  }
+  inline bool operator<=(const UnionWithFd& rhs) const {
+    return _value <= rhs._value;
+  }
+  inline bool operator==(const UnionWithFd& rhs) const {
+    return _value == rhs._value;
+  }
+  inline bool operator>(const UnionWithFd& rhs) const {
+    return _value > rhs._value;
+  }
+  inline bool operator>=(const UnionWithFd& rhs) const {
+    return _value >= rhs._value;
+  }
+
   ::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() {
@@ -115,9 +108,6 @@
 private:
   std::variant<int32_t, ::android::os::ParcelFileDescriptor> _value;
 };  // class UnionWithFd
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BnExtendableParcelable.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BnExtendableParcelable.h
new file mode 100644
index 0000000..ce72aa3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BnExtendableParcelable.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/extension/BnMyExt.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BnMyExt.h
new file mode 100644
index 0000000..ce72aa3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BnMyExt.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/extension/BnMyExt2.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BnMyExt2.h
new file mode 100644
index 0000000..ce72aa3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BnMyExt2.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/extension/BnMyExtLike.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BnMyExtLike.h
new file mode 100644
index 0000000..ce72aa3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BnMyExtLike.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/extension/BpExtendableParcelable.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BpExtendableParcelable.h
new file mode 100644
index 0000000..27af6b1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BpExtendableParcelable.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-cpp-source/gen/include/android/aidl/tests/extension/BpMyExt.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BpMyExt.h
new file mode 100644
index 0000000..27af6b1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BpMyExt.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-cpp-source/gen/include/android/aidl/tests/extension/BpMyExt2.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BpMyExt2.h
new file mode 100644
index 0000000..27af6b1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BpMyExt2.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-cpp-source/gen/include/android/aidl/tests/extension/BpMyExtLike.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BpMyExtLike.h
new file mode 100644
index 0000000..27af6b1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/BpMyExtLike.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-cpp-source/gen/include/android/aidl/tests/extension/ExtendableParcelable.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/ExtendableParcelable.h
new file mode 100644
index 0000000..cf709f1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/ExtendableParcelable.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include <android/binder_to_string.h>
+#include <binder/Parcel.h>
+#include <binder/ParcelableHolder.h>
+#include <binder/Status.h>
+#include <cstdint>
+#include <string>
+#include <tuple>
+#include <utils/String16.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+class ExtendableParcelable : public ::android::Parcelable {
+public:
+  int32_t a = 0;
+  ::std::string b;
+  ::android::os::ParcelableHolder ext { ::android::Parcelable::Stability::STABILITY_LOCAL };
+  int64_t c = 0L;
+  ::android::os::ParcelableHolder ext2 { ::android::Parcelable::Stability::STABILITY_LOCAL };
+  inline bool operator!=(const ExtendableParcelable& rhs) const {
+    return std::tie(a, b, ext, c, ext2) != std::tie(rhs.a, rhs.b, rhs.ext, rhs.c, rhs.ext2);
+  }
+  inline bool operator<(const ExtendableParcelable& rhs) const {
+    return std::tie(a, b, ext, c, ext2) < std::tie(rhs.a, rhs.b, rhs.ext, rhs.c, rhs.ext2);
+  }
+  inline bool operator<=(const ExtendableParcelable& rhs) const {
+    return std::tie(a, b, ext, c, ext2) <= std::tie(rhs.a, rhs.b, rhs.ext, rhs.c, rhs.ext2);
+  }
+  inline bool operator==(const ExtendableParcelable& rhs) const {
+    return std::tie(a, b, ext, c, ext2) == std::tie(rhs.a, rhs.b, rhs.ext, rhs.c, rhs.ext2);
+  }
+  inline bool operator>(const ExtendableParcelable& rhs) const {
+    return std::tie(a, b, ext, c, ext2) > std::tie(rhs.a, rhs.b, rhs.ext, rhs.c, rhs.ext2);
+  }
+  inline bool operator>=(const ExtendableParcelable& rhs) const {
+    return std::tie(a, b, ext, c, ext2) >= std::tie(rhs.a, rhs.b, rhs.ext, rhs.c, rhs.ext2);
+  }
+
+  ::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.extension.ExtendableParcelable");
+    return DESCIPTOR;
+  }
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "ExtendableParcelable{";
+    os << "a: " << ::android::internal::ToString(a);
+    os << ", b: " << ::android::internal::ToString(b);
+    os << ", ext: " << ::android::internal::ToString(ext);
+    os << ", c: " << ::android::internal::ToString(c);
+    os << ", ext2: " << ::android::internal::ToString(ext2);
+    os << "}";
+    return os.str();
+  }
+};  // class ExtendableParcelable
+}  // namespace extension
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/MyExt.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/MyExt.h
new file mode 100644
index 0000000..f89954a
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/MyExt.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <android/binder_to_string.h>
+#include <binder/Parcel.h>
+#include <binder/Status.h>
+#include <cstdint>
+#include <string>
+#include <tuple>
+#include <utils/String16.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+class MyExt : public ::android::Parcelable {
+public:
+  int32_t a = 0;
+  ::std::string b;
+  inline bool operator!=(const MyExt& rhs) const {
+    return std::tie(a, b) != std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator<(const MyExt& rhs) const {
+    return std::tie(a, b) < std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator<=(const MyExt& rhs) const {
+    return std::tie(a, b) <= std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator==(const MyExt& rhs) const {
+    return std::tie(a, b) == std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator>(const MyExt& rhs) const {
+    return std::tie(a, b) > std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator>=(const MyExt& rhs) const {
+    return std::tie(a, b) >= std::tie(rhs.a, rhs.b);
+  }
+
+  ::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.extension.MyExt");
+    return DESCIPTOR;
+  }
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "MyExt{";
+    os << "a: " << ::android::internal::ToString(a);
+    os << ", b: " << ::android::internal::ToString(b);
+    os << "}";
+    return os.str();
+  }
+};  // class MyExt
+}  // namespace extension
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/MyExt2.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/MyExt2.h
new file mode 100644
index 0000000..93fcd01
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/MyExt2.h
@@ -0,0 +1,59 @@
+#pragma once
+
+#include <android/aidl/tests/extension/MyExt.h>
+#include <android/binder_to_string.h>
+#include <binder/Parcel.h>
+#include <binder/Status.h>
+#include <cstdint>
+#include <string>
+#include <tuple>
+#include <utils/String16.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+class MyExt2 : public ::android::Parcelable {
+public:
+  int32_t a = 0;
+  ::android::aidl::tests::extension::MyExt b;
+  ::std::string c;
+  inline bool operator!=(const MyExt2& rhs) const {
+    return std::tie(a, b, c) != std::tie(rhs.a, rhs.b, rhs.c);
+  }
+  inline bool operator<(const MyExt2& rhs) const {
+    return std::tie(a, b, c) < std::tie(rhs.a, rhs.b, rhs.c);
+  }
+  inline bool operator<=(const MyExt2& rhs) const {
+    return std::tie(a, b, c) <= std::tie(rhs.a, rhs.b, rhs.c);
+  }
+  inline bool operator==(const MyExt2& rhs) const {
+    return std::tie(a, b, c) == std::tie(rhs.a, rhs.b, rhs.c);
+  }
+  inline bool operator>(const MyExt2& rhs) const {
+    return std::tie(a, b, c) > std::tie(rhs.a, rhs.b, rhs.c);
+  }
+  inline bool operator>=(const MyExt2& rhs) const {
+    return std::tie(a, b, c) >= std::tie(rhs.a, rhs.b, rhs.c);
+  }
+
+  ::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.extension.MyExt2");
+    return DESCIPTOR;
+  }
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "MyExt2{";
+    os << "a: " << ::android::internal::ToString(a);
+    os << ", b: " << ::android::internal::ToString(b);
+    os << ", c: " << ::android::internal::ToString(c);
+    os << "}";
+    return os.str();
+  }
+};  // class MyExt2
+}  // namespace extension
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/MyExtLike.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/MyExtLike.h
new file mode 100644
index 0000000..0ac2bf7
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/extension/MyExtLike.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <android/binder_to_string.h>
+#include <binder/Parcel.h>
+#include <binder/Status.h>
+#include <cstdint>
+#include <tuple>
+#include <utils/String16.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+class MyExtLike : public ::android::Parcelable {
+public:
+  int32_t a = 0;
+  ::android::String16 b;
+  inline bool operator!=(const MyExtLike& rhs) const {
+    return std::tie(a, b) != std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator<(const MyExtLike& rhs) const {
+    return std::tie(a, b) < std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator<=(const MyExtLike& rhs) const {
+    return std::tie(a, b) <= std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator==(const MyExtLike& rhs) const {
+    return std::tie(a, b) == std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator>(const MyExtLike& rhs) const {
+    return std::tie(a, b) > std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator>=(const MyExtLike& rhs) const {
+    return std::tie(a, b) >= std::tie(rhs.a, rhs.b);
+  }
+
+  ::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.extension.MyExtLike");
+    return DESCIPTOR;
+  }
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "MyExtLike{";
+    os << "a: " << ::android::internal::ToString(a);
+    os << ", b: " << ::android::internal::ToString(b);
+    os << "}";
+    return os.str();
+  }
+};  // class MyExtLike
+}  // namespace extension
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BnDeeplyNested.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BnDeeplyNested.h
new file mode 100644
index 0000000..ce72aa3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BnDeeplyNested.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/nested/BnNestedService.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BnNestedService.h
new file mode 100644
index 0000000..1878af0
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BnNestedService.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <binder/IInterface.h>
+#include <android/aidl/tests/nested/INestedService.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+class BnNestedService : public ::android::BnInterface<INestedService> {
+public:
+  static constexpr uint32_t TRANSACTION_flipStatus = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
+  static constexpr uint32_t TRANSACTION_flipStatusWithCallback = ::android::IBinder::FIRST_CALL_TRANSACTION + 1;
+  explicit BnNestedService();
+  ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
+};  // class BnNestedService
+
+class INestedServiceDelegator : public BnNestedService {
+public:
+  explicit INestedServiceDelegator(::android::sp<INestedService> &impl) : _aidl_delegate(impl) {}
+
+  ::android::binder::Status flipStatus(const ::android::aidl::tests::nested::ParcelableWithNested& p, ::android::aidl::tests::nested::INestedService::Result* _aidl_return) override {
+    return _aidl_delegate->flipStatus(p, _aidl_return);
+  }
+  ::android::binder::Status flipStatusWithCallback(::android::aidl::tests::nested::ParcelableWithNested::Status status, const ::android::sp<::android::aidl::tests::nested::INestedService::ICallback>& cb) override {
+    return _aidl_delegate->flipStatusWithCallback(status, cb);
+  }
+private:
+  ::android::sp<INestedService> _aidl_delegate;
+};  // class INestedServiceDelegator
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BnParcelableWithNested.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BnParcelableWithNested.h
new file mode 100644
index 0000000..ce72aa3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BnParcelableWithNested.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/nested/BpDeeplyNested.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BpDeeplyNested.h
new file mode 100644
index 0000000..27af6b1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BpDeeplyNested.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-cpp-source/gen/include/android/aidl/tests/nested/BpNestedService.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BpNestedService.h
new file mode 100644
index 0000000..8e69a40
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BpNestedService.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <utils/Errors.h>
+#include <android/aidl/tests/nested/INestedService.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+class BpNestedService : public ::android::BpInterface<INestedService> {
+public:
+  explicit BpNestedService(const ::android::sp<::android::IBinder>& _aidl_impl);
+  virtual ~BpNestedService() = default;
+  ::android::binder::Status flipStatus(const ::android::aidl::tests::nested::ParcelableWithNested& p, ::android::aidl::tests::nested::INestedService::Result* _aidl_return) override;
+  ::android::binder::Status flipStatusWithCallback(::android::aidl::tests::nested::ParcelableWithNested::Status status, const ::android::sp<::android::aidl::tests::nested::INestedService::ICallback>& cb) override;
+};  // class BpNestedService
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BpParcelableWithNested.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BpParcelableWithNested.h
new file mode 100644
index 0000000..27af6b1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/BpParcelableWithNested.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-cpp-source/gen/include/android/aidl/tests/nested/DeeplyNested.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/DeeplyNested.h
new file mode 100644
index 0000000..6e280b4
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/DeeplyNested.h
@@ -0,0 +1,223 @@
+#pragma once
+
+#include <android/aidl/tests/nested/DeeplyNested.h>
+#include <android/binder_to_string.h>
+#include <array>
+#include <binder/Enums.h>
+#include <binder/Parcel.h>
+#include <binder/Status.h>
+#include <cstdint>
+#include <string>
+#include <tuple>
+#include <utils/String16.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+class DeeplyNested : public ::android::Parcelable {
+public:
+  class B : public ::android::Parcelable {
+  public:
+    class C : public ::android::Parcelable {
+    public:
+      class D : public ::android::Parcelable {
+      public:
+        enum class E : int8_t {
+          OK = 0,
+        };
+        inline bool operator!=(const D&) const {
+          return std::tie() != std::tie();
+        }
+        inline bool operator<(const D&) const {
+          return std::tie() < std::tie();
+        }
+        inline bool operator<=(const D&) const {
+          return std::tie() <= std::tie();
+        }
+        inline bool operator==(const D&) const {
+          return std::tie() == std::tie();
+        }
+        inline bool operator>(const D&) const {
+          return std::tie() > std::tie();
+        }
+        inline bool operator>=(const D&) const {
+          return std::tie() >= std::tie();
+        }
+
+        ::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.nested.DeeplyNested.B.C.D");
+          return DESCIPTOR;
+        }
+        inline std::string toString() const {
+          std::ostringstream os;
+          os << "D{";
+          os << "}";
+          return os.str();
+        }
+      };  // class D
+      inline bool operator!=(const C&) const {
+        return std::tie() != std::tie();
+      }
+      inline bool operator<(const C&) const {
+        return std::tie() < std::tie();
+      }
+      inline bool operator<=(const C&) const {
+        return std::tie() <= std::tie();
+      }
+      inline bool operator==(const C&) const {
+        return std::tie() == std::tie();
+      }
+      inline bool operator>(const C&) const {
+        return std::tie() > std::tie();
+      }
+      inline bool operator>=(const C&) const {
+        return std::tie() >= std::tie();
+      }
+
+      ::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.nested.DeeplyNested.B.C");
+        return DESCIPTOR;
+      }
+      inline std::string toString() const {
+        std::ostringstream os;
+        os << "C{";
+        os << "}";
+        return os.str();
+      }
+    };  // class C
+    inline bool operator!=(const B&) const {
+      return std::tie() != std::tie();
+    }
+    inline bool operator<(const B&) const {
+      return std::tie() < std::tie();
+    }
+    inline bool operator<=(const B&) const {
+      return std::tie() <= std::tie();
+    }
+    inline bool operator==(const B&) const {
+      return std::tie() == std::tie();
+    }
+    inline bool operator>(const B&) const {
+      return std::tie() > std::tie();
+    }
+    inline bool operator>=(const B&) const {
+      return std::tie() >= std::tie();
+    }
+
+    ::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.nested.DeeplyNested.B");
+      return DESCIPTOR;
+    }
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "B{";
+      os << "}";
+      return os.str();
+    }
+  };  // class B
+  class A : public ::android::Parcelable {
+  public:
+    ::android::aidl::tests::nested::DeeplyNested::B::C::D::E e = ::android::aidl::tests::nested::DeeplyNested::B::C::D::E::OK;
+    inline bool operator!=(const A& rhs) const {
+      return std::tie(e) != std::tie(rhs.e);
+    }
+    inline bool operator<(const A& rhs) const {
+      return std::tie(e) < std::tie(rhs.e);
+    }
+    inline bool operator<=(const A& rhs) const {
+      return std::tie(e) <= std::tie(rhs.e);
+    }
+    inline bool operator==(const A& rhs) const {
+      return std::tie(e) == std::tie(rhs.e);
+    }
+    inline bool operator>(const A& rhs) const {
+      return std::tie(e) > std::tie(rhs.e);
+    }
+    inline bool operator>=(const A& rhs) const {
+      return std::tie(e) >= std::tie(rhs.e);
+    }
+
+    ::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.nested.DeeplyNested.A");
+      return DESCIPTOR;
+    }
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "A{";
+      os << "e: " << ::android::internal::ToString(e);
+      os << "}";
+      return os.str();
+    }
+  };  // class A
+  inline bool operator!=(const DeeplyNested&) const {
+    return std::tie() != std::tie();
+  }
+  inline bool operator<(const DeeplyNested&) const {
+    return std::tie() < std::tie();
+  }
+  inline bool operator<=(const DeeplyNested&) const {
+    return std::tie() <= std::tie();
+  }
+  inline bool operator==(const DeeplyNested&) const {
+    return std::tie() == std::tie();
+  }
+  inline bool operator>(const DeeplyNested&) const {
+    return std::tie() > std::tie();
+  }
+  inline bool operator>=(const DeeplyNested&) const {
+    return std::tie() >= std::tie();
+  }
+
+  ::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.nested.DeeplyNested");
+    return DESCIPTOR;
+  }
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "DeeplyNested{";
+    os << "}";
+    return os.str();
+  }
+};  // class DeeplyNested
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+[[nodiscard]] static inline std::string toString(DeeplyNested::B::C::D::E val) {
+  switch(val) {
+  case DeeplyNested::B::C::D::E::OK:
+    return "OK";
+  default:
+    return std::to_string(static_cast<int8_t>(val));
+  }
+}
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace internal {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++17-extensions"
+template <>
+constexpr inline std::array<::android::aidl::tests::nested::DeeplyNested::B::C::D::E, 1> enum_values<::android::aidl::tests::nested::DeeplyNested::B::C::D::E> = {
+  ::android::aidl::tests::nested::DeeplyNested::B::C::D::E::OK,
+};
+#pragma clang diagnostic pop
+}  // namespace internal
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/INestedService.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/INestedService.h
new file mode 100644
index 0000000..eab7264
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/INestedService.h
@@ -0,0 +1,114 @@
+#pragma once
+
+#include <android/aidl/tests/nested/INestedService.h>
+#include <android/aidl/tests/nested/ParcelableWithNested.h>
+#include <android/binder_to_string.h>
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <binder/Parcel.h>
+#include <binder/Status.h>
+#include <tuple>
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+class INestedService : public ::android::IInterface {
+public:
+  DECLARE_META_INTERFACE(NestedService)
+  class Result : public ::android::Parcelable {
+  public:
+    ::android::aidl::tests::nested::ParcelableWithNested::Status status = ::android::aidl::tests::nested::ParcelableWithNested::Status::OK;
+    inline bool operator!=(const Result& rhs) const {
+      return std::tie(status) != std::tie(rhs.status);
+    }
+    inline bool operator<(const Result& rhs) const {
+      return std::tie(status) < std::tie(rhs.status);
+    }
+    inline bool operator<=(const Result& rhs) const {
+      return std::tie(status) <= std::tie(rhs.status);
+    }
+    inline bool operator==(const Result& rhs) const {
+      return std::tie(status) == std::tie(rhs.status);
+    }
+    inline bool operator>(const Result& rhs) const {
+      return std::tie(status) > std::tie(rhs.status);
+    }
+    inline bool operator>=(const Result& rhs) const {
+      return std::tie(status) >= std::tie(rhs.status);
+    }
+
+    ::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.nested.INestedService.Result");
+      return DESCIPTOR;
+    }
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "Result{";
+      os << "status: " << ::android::internal::ToString(status);
+      os << "}";
+      return os.str();
+    }
+  };  // class Result
+  class ICallback : public ::android::IInterface {
+  public:
+    DECLARE_META_INTERFACE(Callback)
+    virtual ::android::binder::Status done(::android::aidl::tests::nested::ParcelableWithNested::Status status) = 0;
+  };  // class ICallback
+
+  class ICallbackDefault : public ICallback {
+  public:
+    ::android::IBinder* onAsBinder() override {
+      return nullptr;
+    }
+    ::android::binder::Status done(::android::aidl::tests::nested::ParcelableWithNested::Status /*status*/) override {
+      return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+  };  // class ICallbackDefault
+  class BpCallback : public ::android::BpInterface<ICallback> {
+  public:
+    explicit BpCallback(const ::android::sp<::android::IBinder>& _aidl_impl);
+    virtual ~BpCallback() = default;
+    ::android::binder::Status done(::android::aidl::tests::nested::ParcelableWithNested::Status status) override;
+  };  // class BpCallback
+  class BnCallback : public ::android::BnInterface<ICallback> {
+  public:
+    static constexpr uint32_t TRANSACTION_done = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
+    explicit BnCallback();
+    ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
+  };  // class BnCallback
+
+  class ICallbackDelegator : public BnCallback {
+  public:
+    explicit ICallbackDelegator(::android::sp<ICallback> &impl) : _aidl_delegate(impl) {}
+
+    ::android::binder::Status done(::android::aidl::tests::nested::ParcelableWithNested::Status status) override {
+      return _aidl_delegate->done(status);
+    }
+  private:
+    ::android::sp<ICallback> _aidl_delegate;
+  };  // class ICallbackDelegator
+  virtual ::android::binder::Status flipStatus(const ::android::aidl::tests::nested::ParcelableWithNested& p, ::android::aidl::tests::nested::INestedService::Result* _aidl_return) = 0;
+  virtual ::android::binder::Status flipStatusWithCallback(::android::aidl::tests::nested::ParcelableWithNested::Status status, const ::android::sp<::android::aidl::tests::nested::INestedService::ICallback>& cb) = 0;
+};  // class INestedService
+
+class INestedServiceDefault : public INestedService {
+public:
+  ::android::IBinder* onAsBinder() override {
+    return nullptr;
+  }
+  ::android::binder::Status flipStatus(const ::android::aidl::tests::nested::ParcelableWithNested& /*p*/, ::android::aidl::tests::nested::INestedService::Result* /*_aidl_return*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status flipStatusWithCallback(::android::aidl::tests::nested::ParcelableWithNested::Status /*status*/, const ::android::sp<::android::aidl::tests::nested::INestedService::ICallback>& /*cb*/) override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+};  // class INestedServiceDefault
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/ParcelableWithNested.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/ParcelableWithNested.h
new file mode 100644
index 0000000..56a3c4d
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/nested/ParcelableWithNested.h
@@ -0,0 +1,91 @@
+#pragma once
+
+#include <android/aidl/tests/nested/ParcelableWithNested.h>
+#include <android/binder_to_string.h>
+#include <array>
+#include <binder/Enums.h>
+#include <binder/Parcel.h>
+#include <binder/Status.h>
+#include <cstdint>
+#include <string>
+#include <tuple>
+#include <utils/String16.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+class ParcelableWithNested : public ::android::Parcelable {
+public:
+  enum class Status : int8_t {
+    OK = 0,
+    NOT_OK = 1,
+  };
+  ::android::aidl::tests::nested::ParcelableWithNested::Status status = ::android::aidl::tests::nested::ParcelableWithNested::Status::OK;
+  inline bool operator!=(const ParcelableWithNested& rhs) const {
+    return std::tie(status) != std::tie(rhs.status);
+  }
+  inline bool operator<(const ParcelableWithNested& rhs) const {
+    return std::tie(status) < std::tie(rhs.status);
+  }
+  inline bool operator<=(const ParcelableWithNested& rhs) const {
+    return std::tie(status) <= std::tie(rhs.status);
+  }
+  inline bool operator==(const ParcelableWithNested& rhs) const {
+    return std::tie(status) == std::tie(rhs.status);
+  }
+  inline bool operator>(const ParcelableWithNested& rhs) const {
+    return std::tie(status) > std::tie(rhs.status);
+  }
+  inline bool operator>=(const ParcelableWithNested& rhs) const {
+    return std::tie(status) >= std::tie(rhs.status);
+  }
+
+  ::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.nested.ParcelableWithNested");
+    return DESCIPTOR;
+  }
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "ParcelableWithNested{";
+    os << "status: " << ::android::internal::ToString(status);
+    os << "}";
+    return os.str();
+  }
+};  // class ParcelableWithNested
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+[[nodiscard]] static inline std::string toString(ParcelableWithNested::Status val) {
+  switch(val) {
+  case ParcelableWithNested::Status::OK:
+    return "OK";
+  case ParcelableWithNested::Status::NOT_OK:
+    return "NOT_OK";
+  default:
+    return std::to_string(static_cast<int8_t>(val));
+  }
+}
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace internal {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++17-extensions"
+template <>
+constexpr inline std::array<::android::aidl::tests::nested::ParcelableWithNested::Status, 2> enum_values<::android::aidl::tests::nested::ParcelableWithNested::Status> = {
+  ::android::aidl::tests::nested::ParcelableWithNested::Status::OK,
+  ::android::aidl::tests::nested::ParcelableWithNested::Status::NOT_OK,
+};
+#pragma clang diagnostic pop
+}  // namespace internal
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/BnProtected.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/BnProtected.h
new file mode 100644
index 0000000..82340aa
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/BnProtected.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <binder/IInterface.h>
+#include <android/aidl/tests/permission/IProtected.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+class BnProtected : public ::android::BnInterface<IProtected> {
+public:
+  static constexpr uint32_t TRANSACTION_PermissionProtected = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
+  static constexpr uint32_t TRANSACTION_MultiplePermissionsAll = ::android::IBinder::FIRST_CALL_TRANSACTION + 1;
+  static constexpr uint32_t TRANSACTION_MultiplePermissionsAny = ::android::IBinder::FIRST_CALL_TRANSACTION + 2;
+  explicit BnProtected();
+  ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
+};  // class BnProtected
+
+class IProtectedDelegator : public BnProtected {
+public:
+  explicit IProtectedDelegator(::android::sp<IProtected> &impl) : _aidl_delegate(impl) {}
+
+  ::android::binder::Status PermissionProtected() override {
+    return _aidl_delegate->PermissionProtected();
+  }
+  ::android::binder::Status MultiplePermissionsAll() override {
+    return _aidl_delegate->MultiplePermissionsAll();
+  }
+  ::android::binder::Status MultiplePermissionsAny() override {
+    return _aidl_delegate->MultiplePermissionsAny();
+  }
+private:
+  ::android::sp<IProtected> _aidl_delegate;
+};  // class IProtectedDelegator
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/BnProtectedInterface.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/BnProtectedInterface.h
new file mode 100644
index 0000000..7516a17
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/BnProtectedInterface.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <binder/IInterface.h>
+#include <android/aidl/tests/permission/IProtectedInterface.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+class BnProtectedInterface : public ::android::BnInterface<IProtectedInterface> {
+public:
+  static constexpr uint32_t TRANSACTION_Method1 = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
+  static constexpr uint32_t TRANSACTION_Method2 = ::android::IBinder::FIRST_CALL_TRANSACTION + 1;
+  explicit BnProtectedInterface();
+  ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
+};  // class BnProtectedInterface
+
+class IProtectedInterfaceDelegator : public BnProtectedInterface {
+public:
+  explicit IProtectedInterfaceDelegator(::android::sp<IProtectedInterface> &impl) : _aidl_delegate(impl) {}
+
+  ::android::binder::Status Method1() override {
+    return _aidl_delegate->Method1();
+  }
+  ::android::binder::Status Method2() override {
+    return _aidl_delegate->Method2();
+  }
+private:
+  ::android::sp<IProtectedInterface> _aidl_delegate;
+};  // class IProtectedInterfaceDelegator
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/BpProtected.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/BpProtected.h
new file mode 100644
index 0000000..fa83ef0
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/BpProtected.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <utils/Errors.h>
+#include <android/aidl/tests/permission/IProtected.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+class BpProtected : public ::android::BpInterface<IProtected> {
+public:
+  explicit BpProtected(const ::android::sp<::android::IBinder>& _aidl_impl);
+  virtual ~BpProtected() = default;
+  ::android::binder::Status PermissionProtected() override;
+  ::android::binder::Status MultiplePermissionsAll() override;
+  ::android::binder::Status MultiplePermissionsAny() override;
+};  // class BpProtected
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/BpProtectedInterface.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/BpProtectedInterface.h
new file mode 100644
index 0000000..c77b59a
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/BpProtectedInterface.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <utils/Errors.h>
+#include <android/aidl/tests/permission/IProtectedInterface.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+class BpProtectedInterface : public ::android::BpInterface<IProtectedInterface> {
+public:
+  explicit BpProtectedInterface(const ::android::sp<::android::IBinder>& _aidl_impl);
+  virtual ~BpProtectedInterface() = default;
+  ::android::binder::Status Method1() override;
+  ::android::binder::Status Method2() override;
+};  // class BpProtectedInterface
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/IProtected.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/IProtected.h
new file mode 100644
index 0000000..d8b05b9
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/IProtected.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <binder/Status.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+class IProtected : public ::android::IInterface {
+public:
+  DECLARE_META_INTERFACE(Protected)
+  virtual ::android::binder::Status PermissionProtected() = 0;
+  virtual ::android::binder::Status MultiplePermissionsAll() = 0;
+  virtual ::android::binder::Status MultiplePermissionsAny() = 0;
+};  // class IProtected
+
+class IProtectedDefault : public IProtected {
+public:
+  ::android::IBinder* onAsBinder() override {
+    return nullptr;
+  }
+  ::android::binder::Status PermissionProtected() override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status MultiplePermissionsAll() override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status MultiplePermissionsAny() override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+};  // class IProtectedDefault
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/IProtectedInterface.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/IProtectedInterface.h
new file mode 100644
index 0000000..82aaceb
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/permission/IProtectedInterface.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <binder/Status.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+class IProtectedInterface : public ::android::IInterface {
+public:
+  DECLARE_META_INTERFACE(ProtectedInterface)
+  virtual ::android::binder::Status Method1() = 0;
+  virtual ::android::binder::Status Method2() = 0;
+};  // class IProtectedInterface
+
+class IProtectedInterfaceDefault : public IProtectedInterface {
+public:
+  ::android::IBinder* onAsBinder() override {
+    return nullptr;
+  }
+  ::android::binder::Status Method1() override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+  ::android::binder::Status Method2() override {
+    return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+  }
+};  // class IProtectedInterfaceDefault
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/unions/EnumUnion.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/unions/EnumUnion.h
index 3df7de2..348e34d 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/unions/EnumUnion.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/unions/EnumUnion.h
@@ -16,34 +16,11 @@
 #endif
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 namespace unions {
-
 class EnumUnion : public ::android::Parcelable {
 public:
-  inline bool operator!=(const EnumUnion& rhs) const {
-    return _value != rhs._value;
-  }
-  inline bool operator<(const EnumUnion& rhs) const {
-    return _value < rhs._value;
-  }
-  inline bool operator<=(const EnumUnion& rhs) const {
-    return _value <= rhs._value;
-  }
-  inline bool operator==(const EnumUnion& rhs) const {
-    return _value == rhs._value;
-  }
-  inline bool operator>(const EnumUnion& rhs) const {
-    return _value > rhs._value;
-  }
-  inline bool operator>=(const EnumUnion& rhs) const {
-    return _value >= rhs._value;
-  }
-
   enum Tag : int32_t {
     intEnum = 0,  // android.aidl.tests.IntEnum intEnum;
     longEnum,  // android.aidl.tests.LongEnum longEnum;
@@ -53,10 +30,6 @@
   static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, EnumUnion>;
 
   EnumUnion() : _value(std::in_place_index<intEnum>, ::android::aidl::tests::IntEnum(::android::aidl::tests::IntEnum::FOO)) { }
-  EnumUnion(const EnumUnion&) = default;
-  EnumUnion(EnumUnion&&) = default;
-  EnumUnion& operator=(const EnumUnion&) = default;
-  EnumUnion& operator=(EnumUnion&&) = default;
 
   template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
   // NOLINTNEXTLINE(google-explicit-constructor)
@@ -98,6 +71,25 @@
     _value.emplace<_tag>(std::forward<_Tp>(_args)...);
   }
 
+  inline bool operator!=(const EnumUnion& rhs) const {
+    return _value != rhs._value;
+  }
+  inline bool operator<(const EnumUnion& rhs) const {
+    return _value < rhs._value;
+  }
+  inline bool operator<=(const EnumUnion& rhs) const {
+    return _value <= rhs._value;
+  }
+  inline bool operator==(const EnumUnion& rhs) const {
+    return _value == rhs._value;
+  }
+  inline bool operator>(const EnumUnion& rhs) const {
+    return _value > rhs._value;
+  }
+  inline bool operator>=(const EnumUnion& rhs) const {
+    return _value >= rhs._value;
+  }
+
   ::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() {
@@ -117,11 +109,7 @@
 private:
   std::variant<::android::aidl::tests::IntEnum, ::android::aidl::tests::LongEnum> _value;
 };  // class EnumUnion
-
 }  // namespace unions
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/unions/UnionInUnion.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/unions/UnionInUnion.h
index 592cfe3..d83935c 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/unions/UnionInUnion.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/unions/UnionInUnion.h
@@ -16,34 +16,11 @@
 #endif
 
 namespace android {
-
 namespace aidl {
-
 namespace tests {
-
 namespace unions {
-
 class UnionInUnion : public ::android::Parcelable {
 public:
-  inline bool operator!=(const UnionInUnion& rhs) const {
-    return _value != rhs._value;
-  }
-  inline bool operator<(const UnionInUnion& rhs) const {
-    return _value < rhs._value;
-  }
-  inline bool operator<=(const UnionInUnion& rhs) const {
-    return _value <= rhs._value;
-  }
-  inline bool operator==(const UnionInUnion& rhs) const {
-    return _value == rhs._value;
-  }
-  inline bool operator>(const UnionInUnion& rhs) const {
-    return _value > rhs._value;
-  }
-  inline bool operator>=(const UnionInUnion& rhs) const {
-    return _value >= rhs._value;
-  }
-
   enum Tag : int32_t {
     first = 0,  // android.aidl.tests.unions.EnumUnion first;
     second,  // int second;
@@ -53,10 +30,6 @@
   static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, UnionInUnion>;
 
   UnionInUnion() : _value(std::in_place_index<first>, ::android::aidl::tests::unions::EnumUnion()) { }
-  UnionInUnion(const UnionInUnion&) = default;
-  UnionInUnion(UnionInUnion&&) = default;
-  UnionInUnion& operator=(const UnionInUnion&) = default;
-  UnionInUnion& operator=(UnionInUnion&&) = default;
 
   template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
   // NOLINTNEXTLINE(google-explicit-constructor)
@@ -98,6 +71,25 @@
     _value.emplace<_tag>(std::forward<_Tp>(_args)...);
   }
 
+  inline bool operator!=(const UnionInUnion& rhs) const {
+    return _value != rhs._value;
+  }
+  inline bool operator<(const UnionInUnion& rhs) const {
+    return _value < rhs._value;
+  }
+  inline bool operator<=(const UnionInUnion& rhs) const {
+    return _value <= rhs._value;
+  }
+  inline bool operator==(const UnionInUnion& rhs) const {
+    return _value == rhs._value;
+  }
+  inline bool operator>(const UnionInUnion& rhs) const {
+    return _value > rhs._value;
+  }
+  inline bool operator>=(const UnionInUnion& rhs) const {
+    return _value >= rhs._value;
+  }
+
   ::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() {
@@ -117,11 +109,7 @@
 private:
   std::variant<::android::aidl::tests::unions::EnumUnion, int32_t> _value;
 };  // class UnionInUnion
-
 }  // namespace unions
-
 }  // namespace tests
-
 }  // namespace aidl
-
 }  // namespace android
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..5c86379
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ArrayOfInterfaces.java
@@ -0,0 +1,569 @@
+/*
+ * 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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+    } 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 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;
+            _arg2 = data.createInterfaceArray(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[]::new, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
+            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;
+            _arg4 = data.createInterfaceArray(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[]::new, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
+            android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _arg5;
+            _arg5 = data.createInterfaceArray(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[]::new, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
+            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;
+            _arg7 = data.createInterfaceArray(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[]::new, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
+            data.enforceNoDataAvail();
+            android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _result = this.methodWithInterfaces(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7);
+            reply.writeNoException();
+            reply.writeInterfaceArray(_result);
+            reply.writeInterfaceArray(_arg3);
+            reply.writeInterfaceArray(_arg4);
+            reply.writeInterfaceArray(_arg6);
+            reply.writeInterfaceArray(_arg7);
+            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.writeStrongInterface(iface);
+            _data.writeStrongInterface(nullable_iface);
+            _data.writeInterfaceArray(iface_array_in);
+            if ((iface_array_out==null)) {
+              _data.writeInt(-1);
+            }
+            else {
+              _data.writeInt(iface_array_out.length);
+            }
+            _data.writeInterfaceArray(iface_array_inout);
+            _data.writeInterfaceArray(nullable_iface_array_in);
+            if ((nullable_iface_array_out==null)) {
+              _data.writeInt(-1);
+            }
+            else {
+              _data.writeInt(nullable_iface_array_out.length);
+            }
+            _data.writeInterfaceArray(nullable_iface_array_inout);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_methodWithInterfaces, _data, _reply, 0);
+            _reply.readException();
+            _result = _reply.createInterfaceArray(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[]::new, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
+            _reply.readInterfaceArray(iface_array_out, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
+            _reply.readInterfaceArray(iface_array_inout, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
+            _reply.readInterfaceArray(nullable_iface_array_out, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
+            _reply.readInterfaceArray(nullable_iface_array_inout, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
+          }
+          finally {
+            _reply.recycle();
+            _data.recycle();
+          }
+          return _result;
+        }
+      }
+      static final int TRANSACTION_methodWithInterfaces = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+    }
+    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.writeStrongInterface(iface);
+      _aidl_parcel.writeStrongInterface(nullable_iface);
+      _aidl_parcel.writeInterfaceArray(iface_array);
+      _aidl_parcel.writeInterfaceArray(nullable_iface_array);
+      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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+        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;
+        iface_array = _aidl_parcel.createInterfaceArray(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[]::new, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        nullable_iface_array = _aidl_parcel.createInterfaceArray(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[]::new, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
+      } 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.writeStrongInterface(getIface());
+        break;
+      case nullable_iface:
+        _aidl_parcel.writeStrongInterface(getNullable_iface());
+        break;
+      case iface_array:
+        _aidl_parcel.writeInterfaceArray(getIface_array());
+        break;
+      case nullable_iface_array:
+        _aidl_parcel.writeInterfaceArray(getNullable_iface_array());
+        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;
+        _aidl_value = _aidl_parcel.createInterfaceArray(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[]::new, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case nullable_iface_array: {
+        android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[] _aidl_value;
+        _aidl_value = _aidl_parcel.createInterfaceArray(android.aidl.tests.ArrayOfInterfaces.IEmptyInterface[]::new, android.aidl.tests.ArrayOfInterfaces.IEmptyInterface.Stub::asInterface);
+        _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-java-source/gen/android/aidl/tests/ByteEnum.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ByteEnum.java
index 0f5a3ea..42fe1ed 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ByteEnum.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ByteEnum.java
@@ -2,9 +2,7 @@
  * This file is auto-generated.  DO NOT MODIFY.
  */
 package android.aidl.tests;
-/**
- * Hello, world!
- */
+/** Hello, world! */
 public @interface ByteEnum {
   // Comment about FOO.
   public static final byte FOO = 1;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/DeprecatedParcelable.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/DeprecatedParcelable.java
index f1444ba..cb17367 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/DeprecatedParcelable.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/DeprecatedParcelable.java
@@ -32,7 +32,7 @@
     int _aidl_start_pos = _aidl_parcel.dataPosition();
     int _aidl_parcelable_size = _aidl_parcel.readInt();
     try {
-      if (_aidl_parcelable_size < 0) return;
+      if (_aidl_parcelable_size < 4) throw new android.os.BadParcelableException("Parcelable too small");;
     } finally {
       if (_aidl_start_pos > (Integer.MAX_VALUE - _aidl_parcelable_size)) {
         throw new android.os.BadParcelableException("Overflow in the size of parcelable");
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java
new file mode 100644
index 0000000..1b4ca32
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java
@@ -0,0 +1,408 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests;
+public class FixedSize implements android.os.Parcelable
+{
+  public static final android.os.Parcelable.Creator<FixedSize> CREATOR = new android.os.Parcelable.Creator<FixedSize>() {
+    @Override
+    public FixedSize createFromParcel(android.os.Parcel _aidl_source) {
+      FixedSize _aidl_out = new FixedSize();
+      _aidl_out.readFromParcel(_aidl_source);
+      return _aidl_out;
+    }
+    @Override
+    public FixedSize[] newArray(int _aidl_size) {
+      return new FixedSize[_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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+    } 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 static class FixedParcelable implements android.os.Parcelable
+  {
+    public boolean booleanValue = false;
+    public byte byteValue = 0;
+    public char charValue = '\0';
+    public int intValue = 0;
+    public long longValue = 0L;
+    public float floatValue = 0.000000f;
+    public double doubleValue = 0.000000;
+    public long enumValue = android.aidl.tests.LongEnum.FOO;
+    public android.aidl.tests.FixedSize.FixedUnion parcelableValue;
+    public static final android.os.Parcelable.Creator<FixedParcelable> CREATOR = new android.os.Parcelable.Creator<FixedParcelable>() {
+      @Override
+      public FixedParcelable createFromParcel(android.os.Parcel _aidl_source) {
+        FixedParcelable _aidl_out = new FixedParcelable();
+        _aidl_out.readFromParcel(_aidl_source);
+        return _aidl_out;
+      }
+      @Override
+      public FixedParcelable[] newArray(int _aidl_size) {
+        return new FixedParcelable[_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.writeBoolean(booleanValue);
+      _aidl_parcel.writeByte(byteValue);
+      _aidl_parcel.writeInt(((int)charValue));
+      _aidl_parcel.writeInt(intValue);
+      _aidl_parcel.writeLong(longValue);
+      _aidl_parcel.writeFloat(floatValue);
+      _aidl_parcel.writeDouble(doubleValue);
+      _aidl_parcel.writeLong(enumValue);
+      _aidl_parcel.writeTypedObject(parcelableValue, 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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        booleanValue = _aidl_parcel.readBoolean();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        byteValue = _aidl_parcel.readByte();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        charValue = (char)_aidl_parcel.readInt();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        intValue = _aidl_parcel.readInt();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        longValue = _aidl_parcel.readLong();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        floatValue = _aidl_parcel.readFloat();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        doubleValue = _aidl_parcel.readDouble();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        enumValue = _aidl_parcel.readLong();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        parcelableValue = _aidl_parcel.readTypedObject(android.aidl.tests.FixedSize.FixedUnion.CREATOR);
+      } 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;
+      _mask |= describeContents(parcelableValue);
+      return _mask;
+    }
+    private int describeContents(Object _v) {
+      if (_v == null) return 0;
+      if (_v instanceof android.os.Parcelable) {
+        return ((android.os.Parcelable) _v).describeContents();
+      }
+      return 0;
+    }
+  }
+  public static final class FixedUnion implements android.os.Parcelable {
+    // tags for union fields
+    public final static int booleanValue = 0;  // boolean booleanValue;
+    public final static int byteValue = 1;  // byte byteValue;
+    public final static int charValue = 2;  // char charValue;
+    public final static int intValue = 3;  // int intValue;
+    public final static int longValue = 4;  // long longValue;
+    public final static int floatValue = 5;  // float floatValue;
+    public final static int doubleValue = 6;  // double doubleValue;
+    public final static int enumValue = 7;  // android.aidl.tests.LongEnum enumValue;
+
+    private int _tag;
+    private Object _value;
+
+    public FixedUnion() {
+      boolean _value = false;
+      this._tag = booleanValue;
+      this._value = _value;
+    }
+
+    private FixedUnion(android.os.Parcel _aidl_parcel) {
+      readFromParcel(_aidl_parcel);
+    }
+
+    private FixedUnion(int _tag, Object _value) {
+      this._tag = _tag;
+      this._value = _value;
+    }
+
+    public int getTag() {
+      return _tag;
+    }
+
+    // boolean booleanValue;
+
+    public static FixedUnion booleanValue(boolean _value) {
+      return new FixedUnion(booleanValue, _value);
+    }
+
+    public boolean getBooleanValue() {
+      _assertTag(booleanValue);
+      return (boolean) _value;
+    }
+
+    public void setBooleanValue(boolean _value) {
+      _set(booleanValue, _value);
+    }
+
+    // byte byteValue;
+
+    public static FixedUnion byteValue(byte _value) {
+      return new FixedUnion(byteValue, _value);
+    }
+
+    public byte getByteValue() {
+      _assertTag(byteValue);
+      return (byte) _value;
+    }
+
+    public void setByteValue(byte _value) {
+      _set(byteValue, _value);
+    }
+
+    // char charValue;
+
+    public static FixedUnion charValue(char _value) {
+      return new FixedUnion(charValue, _value);
+    }
+
+    public char getCharValue() {
+      _assertTag(charValue);
+      return (char) _value;
+    }
+
+    public void setCharValue(char _value) {
+      _set(charValue, _value);
+    }
+
+    // int intValue;
+
+    public static FixedUnion intValue(int _value) {
+      return new FixedUnion(intValue, _value);
+    }
+
+    public int getIntValue() {
+      _assertTag(intValue);
+      return (int) _value;
+    }
+
+    public void setIntValue(int _value) {
+      _set(intValue, _value);
+    }
+
+    // long longValue;
+
+    public static FixedUnion longValue(long _value) {
+      return new FixedUnion(longValue, _value);
+    }
+
+    public long getLongValue() {
+      _assertTag(longValue);
+      return (long) _value;
+    }
+
+    public void setLongValue(long _value) {
+      _set(longValue, _value);
+    }
+
+    // float floatValue;
+
+    public static FixedUnion floatValue(float _value) {
+      return new FixedUnion(floatValue, _value);
+    }
+
+    public float getFloatValue() {
+      _assertTag(floatValue);
+      return (float) _value;
+    }
+
+    public void setFloatValue(float _value) {
+      _set(floatValue, _value);
+    }
+
+    // double doubleValue;
+
+    public static FixedUnion doubleValue(double _value) {
+      return new FixedUnion(doubleValue, _value);
+    }
+
+    public double getDoubleValue() {
+      _assertTag(doubleValue);
+      return (double) _value;
+    }
+
+    public void setDoubleValue(double _value) {
+      _set(doubleValue, _value);
+    }
+
+    // android.aidl.tests.LongEnum enumValue;
+
+    public static FixedUnion enumValue(long _value) {
+      return new FixedUnion(enumValue, _value);
+    }
+
+    public long getEnumValue() {
+      _assertTag(enumValue);
+      return (long) _value;
+    }
+
+    public void setEnumValue(long _value) {
+      _set(enumValue, _value);
+    }
+
+    public static final android.os.Parcelable.Creator<FixedUnion> CREATOR = new android.os.Parcelable.Creator<FixedUnion>() {
+      @Override
+      public FixedUnion createFromParcel(android.os.Parcel _aidl_source) {
+        return new FixedUnion(_aidl_source);
+      }
+      @Override
+      public FixedUnion[] newArray(int _aidl_size) {
+        return new FixedUnion[_aidl_size];
+      }
+    };
+
+    @Override
+    public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag) {
+      _aidl_parcel.writeInt(_tag);
+      switch (_tag) {
+      case booleanValue:
+        _aidl_parcel.writeBoolean(getBooleanValue());
+        break;
+      case byteValue:
+        _aidl_parcel.writeByte(getByteValue());
+        break;
+      case charValue:
+        _aidl_parcel.writeInt(((int)getCharValue()));
+        break;
+      case intValue:
+        _aidl_parcel.writeInt(getIntValue());
+        break;
+      case longValue:
+        _aidl_parcel.writeLong(getLongValue());
+        break;
+      case floatValue:
+        _aidl_parcel.writeFloat(getFloatValue());
+        break;
+      case doubleValue:
+        _aidl_parcel.writeDouble(getDoubleValue());
+        break;
+      case enumValue:
+        _aidl_parcel.writeLong(getEnumValue());
+        break;
+      }
+    }
+
+    public void readFromParcel(android.os.Parcel _aidl_parcel) {
+      int _aidl_tag;
+      _aidl_tag = _aidl_parcel.readInt();
+      switch (_aidl_tag) {
+      case booleanValue: {
+        boolean _aidl_value;
+        _aidl_value = _aidl_parcel.readBoolean();
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case byteValue: {
+        byte _aidl_value;
+        _aidl_value = _aidl_parcel.readByte();
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case charValue: {
+        char _aidl_value;
+        _aidl_value = (char)_aidl_parcel.readInt();
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case intValue: {
+        int _aidl_value;
+        _aidl_value = _aidl_parcel.readInt();
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case longValue: {
+        long _aidl_value;
+        _aidl_value = _aidl_parcel.readLong();
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case floatValue: {
+        float _aidl_value;
+        _aidl_value = _aidl_parcel.readFloat();
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case doubleValue: {
+        double _aidl_value;
+        _aidl_value = _aidl_parcel.readDouble();
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case enumValue: {
+        long _aidl_value;
+        _aidl_value = _aidl_parcel.readLong();
+        _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;
+    }
+
+    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 booleanValue: return "booleanValue";
+      case byteValue: return "byteValue";
+      case charValue: return "charValue";
+      case intValue: return "intValue";
+      case longValue: return "longValue";
+      case floatValue: return "floatValue";
+      case doubleValue: return "doubleValue";
+      case enumValue: return "enumValue";
+      }
+      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/FixedSize.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java.d
new file mode 100644
index 0000000..74b092c
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/FixedSize.java : \
+  system/tools/aidl/tests/android/aidl/tests/FixedSize.aidl \
+  system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/GenericStructuredParcelable.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/GenericStructuredParcelable.java
index 94b6a2e..ee93956 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/GenericStructuredParcelable.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/GenericStructuredParcelable.java
@@ -34,7 +34,7 @@
     int _aidl_start_pos = _aidl_parcel.dataPosition();
     int _aidl_parcelable_size = _aidl_parcel.readInt();
     try {
-      if (_aidl_parcelable_size < 0) return;
+      if (_aidl_parcelable_size < 4) throw new android.os.BadParcelableException("Parcelable too small");;
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       a = _aidl_parcel.readInt();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IDeprecated.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IDeprecated.java
index 0290c7a..09578f5 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IDeprecated.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IDeprecated.java
@@ -75,23 +75,6 @@
       {
         return DESCRIPTOR;
       }
-      public static android.aidl.tests.IDeprecated sDefaultImpl;
-    }
-    public static boolean setDefaultImpl(android.aidl.tests.IDeprecated 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.IDeprecated getDefaultImpl() {
-      return Stub.Proxy.sDefaultImpl;
     }
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$tests$IDeprecated".replace('$', '.');
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INamedCallback.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INamedCallback.java
index 60ddc7a..3500271 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INamedCallback.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INamedCallback.java
@@ -46,6 +46,9 @@
     @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:
@@ -58,17 +61,17 @@
       {
         case TRANSACTION_GetName:
         {
-          data.enforceInterface(descriptor);
           java.lang.String _result = this.GetName();
           reply.writeNoException();
           reply.writeString(_result);
-          return true;
+          break;
         }
         default:
         {
           return super.onTransact(code, data, reply, flags);
         }
       }
+      return true;
     }
     private static class Proxy implements android.aidl.tests.INamedCallback
     {
@@ -87,17 +90,12 @@
       }
       @Override public java.lang.String GetName() throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
         android.os.Parcel _reply = android.os.Parcel.obtain();
         java.lang.String _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_GetName, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              return getDefaultImpl().GetName();
-            }
-          }
           _reply.readException();
           _result = _reply.readString();
         }
@@ -107,25 +105,8 @@
         }
         return _result;
       }
-      public static android.aidl.tests.INamedCallback sDefaultImpl;
     }
     static final int TRANSACTION_GetName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
-    public static boolean setDefaultImpl(android.aidl.tests.INamedCallback 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.INamedCallback getDefaultImpl() {
-      return Stub.Proxy.sDefaultImpl;
-    }
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$tests$INamedCallback".replace('$', '.');
   public java.lang.String GetName() throws android.os.RemoteException;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INewName.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INewName.java
index 893e43f..265f8ef 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INewName.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/INewName.java
@@ -46,6 +46,9 @@
     @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:
@@ -58,17 +61,17 @@
       {
         case TRANSACTION_RealName:
         {
-          data.enforceInterface(descriptor);
           java.lang.String _result = this.RealName();
           reply.writeNoException();
           reply.writeString(_result);
-          return true;
+          break;
         }
         default:
         {
           return super.onTransact(code, data, reply, flags);
         }
       }
+      return true;
     }
     private static class Proxy implements android.aidl.tests.INewName
     {
@@ -87,17 +90,12 @@
       }
       @Override public java.lang.String RealName() throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
         android.os.Parcel _reply = android.os.Parcel.obtain();
         java.lang.String _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_RealName, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              return getDefaultImpl().RealName();
-            }
-          }
           _reply.readException();
           _result = _reply.readString();
         }
@@ -107,25 +105,8 @@
         }
         return _result;
       }
-      public static android.aidl.tests.INewName sDefaultImpl;
     }
     static final int TRANSACTION_RealName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
-    public static boolean setDefaultImpl(android.aidl.tests.INewName 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.INewName getDefaultImpl() {
-      return Stub.Proxy.sDefaultImpl;
-    }
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$tests$IOldName".replace('$', '.');
   public java.lang.String RealName() throws android.os.RemoteException;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IOldName.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IOldName.java
index c52387c..7013fce 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IOldName.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/IOldName.java
@@ -46,6 +46,9 @@
     @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:
@@ -58,17 +61,17 @@
       {
         case TRANSACTION_RealName:
         {
-          data.enforceInterface(descriptor);
           java.lang.String _result = this.RealName();
           reply.writeNoException();
           reply.writeString(_result);
-          return true;
+          break;
         }
         default:
         {
           return super.onTransact(code, data, reply, flags);
         }
       }
+      return true;
     }
     private static class Proxy implements android.aidl.tests.IOldName
     {
@@ -87,17 +90,12 @@
       }
       @Override public java.lang.String RealName() throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
         android.os.Parcel _reply = android.os.Parcel.obtain();
         java.lang.String _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_RealName, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              return getDefaultImpl().RealName();
-            }
-          }
           _reply.readException();
           _result = _reply.readString();
         }
@@ -107,25 +105,8 @@
         }
         return _result;
       }
-      public static android.aidl.tests.IOldName sDefaultImpl;
     }
     static final int TRANSACTION_RealName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
-    public static boolean setDefaultImpl(android.aidl.tests.IOldName 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.IOldName getDefaultImpl() {
-      return Stub.Proxy.sDefaultImpl;
-    }
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$tests$IOldName".replace('$', '.');
   public java.lang.String RealName() throws android.os.RemoteException;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ITestService.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ITestService.java
index 4d6f9fd..50d65a6 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ITestService.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ITestService.java
@@ -2,6 +2,7 @@
  * This file is auto-generated.  DO NOT MODIFY.
  */
 package android.aidl.tests;
+/** interface comment */
 public interface ITestService extends android.os.IInterface
 {
   /** Default implementation for ITestService. */
@@ -23,9 +24,9 @@
       return 0;
     }
     /**
-         * @deprecated to make sure we have something in system/tools/aidl which does a compile check
-         *     of deprecated and make sure this is reflected in goldens
-         */
+     * @deprecated to make sure we have something in system/tools/aidl which does a compile check
+     *     of deprecated and make sure this is reflected in goldens
+     */
     @Override public void Deprecated() throws android.os.RemoteException
     {
     }
@@ -131,6 +132,30 @@
     {
       return false;
     }
+    @Override public android.aidl.tests.INamedCallback[] GetInterfaceArray(java.lang.String[] names) throws android.os.RemoteException
+    {
+      return null;
+    }
+    @Override public boolean VerifyNamesWithInterfaceArray(android.aidl.tests.INamedCallback[] services, java.lang.String[] names) throws android.os.RemoteException
+    {
+      return false;
+    }
+    @Override public android.aidl.tests.INamedCallback[] GetNullableInterfaceArray(java.lang.String[] names) throws android.os.RemoteException
+    {
+      return null;
+    }
+    @Override public boolean VerifyNamesWithNullableInterfaceArray(android.aidl.tests.INamedCallback[] services, java.lang.String[] names) throws android.os.RemoteException
+    {
+      return false;
+    }
+    @Override public java.util.List<android.aidl.tests.INamedCallback> GetInterfaceList(java.lang.String[] names) throws android.os.RemoteException
+    {
+      return null;
+    }
+    @Override public boolean VerifyNamesWithInterfaceList(java.util.List<android.aidl.tests.INamedCallback> services, java.lang.String[] names) throws android.os.RemoteException
+    {
+      return false;
+    }
     // Test that List<T> types work correctly.
     @Override public java.util.List<java.lang.String> ReverseStringList(java.util.List<java.lang.String> input, java.util.List<java.lang.String> repeated) throws android.os.RemoteException
     {
@@ -173,7 +198,15 @@
     {
       return null;
     }
-    @Override public android.aidl.tests.StructuredParcelable RepeatNullableParcelable(android.aidl.tests.StructuredParcelable input) throws android.os.RemoteException
+    @Override public android.aidl.tests.ITestService.Empty RepeatNullableParcelable(android.aidl.tests.ITestService.Empty input) throws android.os.RemoteException
+    {
+      return null;
+    }
+    @Override public android.aidl.tests.ITestService.Empty[] RepeatNullableParcelableArray(android.aidl.tests.ITestService.Empty[] input) throws android.os.RemoteException
+    {
+      return null;
+    }
+    @Override public java.util.List<android.aidl.tests.ITestService.Empty> RepeatNullableParcelableList(java.util.List<android.aidl.tests.ITestService.Empty> input) throws android.os.RemoteException
     {
       return null;
     }
@@ -183,6 +216,12 @@
     @Override public void TakesANullableIBinder(android.os.IBinder input) throws android.os.RemoteException
     {
     }
+    @Override public void TakesAnIBinderList(java.util.List<android.os.IBinder> input) throws android.os.RemoteException
+    {
+    }
+    @Override public void TakesANullableIBinderList(java.util.List<android.os.IBinder> input) throws android.os.RemoteException
+    {
+    }
     // Test utf8 decoding from utf16 wire format
     @Override public java.lang.String RepeatUtf8CppString(java.lang.String token) throws android.os.RemoteException
     {
@@ -204,6 +243,7 @@
     {
       return null;
     }
+    /** comment before annotation */
     @Override public android.aidl.tests.INamedCallback GetCallback(boolean return_null) throws android.os.RemoteException
     {
       return null;
@@ -213,6 +253,21 @@
     @Override public void FillOutStructuredParcelable(android.aidl.tests.StructuredParcelable parcel) throws android.os.RemoteException
     {
     }
+    @Override public void RepeatExtendableParcelable(android.aidl.tests.extension.ExtendableParcelable ep, android.aidl.tests.extension.ExtendableParcelable ep2) throws android.os.RemoteException
+    {
+    }
+    @Override public android.aidl.tests.RecursiveList ReverseList(android.aidl.tests.RecursiveList list) throws android.os.RemoteException
+    {
+      return null;
+    }
+    @Override public android.os.IBinder[] ReverseIBinderArray(android.os.IBinder[] input, android.os.IBinder[] repeated) throws android.os.RemoteException
+    {
+      return null;
+    }
+    @Override public android.os.IBinder[] ReverseNullableIBinderArray(android.os.IBinder[] input, android.os.IBinder[] repeated) throws android.os.RemoteException
+    {
+      return null;
+    }
     @Override public android.aidl.tests.IOldName GetOldNameInterface() throws android.os.RemoteException
     {
       return null;
@@ -235,6 +290,300 @@
       return null;
     }
   }
+  /** Delegator implementation for ITestService. */
+  public static class Delegator extends android.aidl.tests.ITestService.Stub
+  {
+    public Delegator(android.aidl.tests.ITestService impl) {
+      this.mImpl = impl;
+    }
+    // This is to emulate a method that is added after the service is implemented.
+    // So the client cannot assume that a call to this method will be successful
+    // or not. However, inside the test environment, we can't build client and
+    // the server with different version of this AIDL file. So, we let the server
+    // actually implement this and intercept the dispatch to the method
+    // inside onTransact().
+    // WARNING: Must be first method.
+    // This requires hard coding the transaction number. As long as this method is
+    // the first in this interface, it can keep the
+    // "::android::IBinder::FIRST_CALL_TRANSACTION + 0" value and allow
+    // methods to be added and removed.
+    @Override public int UnimplementedMethod(int arg) throws android.os.RemoteException
+    {
+      return mImpl.UnimplementedMethod(arg);
+    }
+    /**
+     * @deprecated to make sure we have something in system/tools/aidl which does a compile check
+     *     of deprecated and make sure this is reflected in goldens
+     */
+    @Override public void Deprecated() throws android.os.RemoteException
+    {
+      mImpl.Deprecated();
+    }
+    @Override public void TestOneway() throws android.os.RemoteException
+    {
+      mImpl.TestOneway();
+    }
+    // Test that primitives work as parameters and return types.
+    @Override public boolean RepeatBoolean(boolean token) throws android.os.RemoteException
+    {
+      return mImpl.RepeatBoolean(token);
+    }
+    @Override public byte RepeatByte(byte token) throws android.os.RemoteException
+    {
+      return mImpl.RepeatByte(token);
+    }
+    @Override public char RepeatChar(char token) throws android.os.RemoteException
+    {
+      return mImpl.RepeatChar(token);
+    }
+    @Override public int RepeatInt(int token) throws android.os.RemoteException
+    {
+      return mImpl.RepeatInt(token);
+    }
+    @Override public long RepeatLong(long token) throws android.os.RemoteException
+    {
+      return mImpl.RepeatLong(token);
+    }
+    @Override public float RepeatFloat(float token) throws android.os.RemoteException
+    {
+      return mImpl.RepeatFloat(token);
+    }
+    @Override public double RepeatDouble(double token) throws android.os.RemoteException
+    {
+      return mImpl.RepeatDouble(token);
+    }
+    @Override public java.lang.String RepeatString(java.lang.String token) throws android.os.RemoteException
+    {
+      return mImpl.RepeatString(token);
+    }
+    @Override public byte RepeatByteEnum(byte token) throws android.os.RemoteException
+    {
+      return mImpl.RepeatByteEnum(token);
+    }
+    @Override public int RepeatIntEnum(int token) throws android.os.RemoteException
+    {
+      return mImpl.RepeatIntEnum(token);
+    }
+    @Override public long RepeatLongEnum(long token) throws android.os.RemoteException
+    {
+      return mImpl.RepeatLongEnum(token);
+    }
+    // Test that arrays work as parameters and return types.
+    @Override public boolean[] ReverseBoolean(boolean[] input, boolean[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseBoolean(input,repeated);
+    }
+    @Override public byte[] ReverseByte(byte[] input, byte[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseByte(input,repeated);
+    }
+    @Override public char[] ReverseChar(char[] input, char[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseChar(input,repeated);
+    }
+    @Override public int[] ReverseInt(int[] input, int[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseInt(input,repeated);
+    }
+    @Override public long[] ReverseLong(long[] input, long[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseLong(input,repeated);
+    }
+    @Override public float[] ReverseFloat(float[] input, float[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseFloat(input,repeated);
+    }
+    @Override public double[] ReverseDouble(double[] input, double[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseDouble(input,repeated);
+    }
+    @Override public java.lang.String[] ReverseString(java.lang.String[] input, java.lang.String[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseString(input,repeated);
+    }
+    @Override public byte[] ReverseByteEnum(byte[] input, byte[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseByteEnum(input,repeated);
+    }
+    @Override public int[] ReverseIntEnum(int[] input, int[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseIntEnum(input,repeated);
+    }
+    @Override public long[] ReverseLongEnum(long[] input, long[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseLongEnum(input,repeated);
+    }
+    // Test that clients can send and receive Binders.
+    @Override public android.aidl.tests.INamedCallback GetOtherTestService(java.lang.String name) throws android.os.RemoteException
+    {
+      return mImpl.GetOtherTestService(name);
+    }
+    @Override public boolean VerifyName(android.aidl.tests.INamedCallback service, java.lang.String name) throws android.os.RemoteException
+    {
+      return mImpl.VerifyName(service,name);
+    }
+    @Override public android.aidl.tests.INamedCallback[] GetInterfaceArray(java.lang.String[] names) throws android.os.RemoteException
+    {
+      return mImpl.GetInterfaceArray(names);
+    }
+    @Override public boolean VerifyNamesWithInterfaceArray(android.aidl.tests.INamedCallback[] services, java.lang.String[] names) throws android.os.RemoteException
+    {
+      return mImpl.VerifyNamesWithInterfaceArray(services,names);
+    }
+    @Override public android.aidl.tests.INamedCallback[] GetNullableInterfaceArray(java.lang.String[] names) throws android.os.RemoteException
+    {
+      return mImpl.GetNullableInterfaceArray(names);
+    }
+    @Override public boolean VerifyNamesWithNullableInterfaceArray(android.aidl.tests.INamedCallback[] services, java.lang.String[] names) throws android.os.RemoteException
+    {
+      return mImpl.VerifyNamesWithNullableInterfaceArray(services,names);
+    }
+    @Override public java.util.List<android.aidl.tests.INamedCallback> GetInterfaceList(java.lang.String[] names) throws android.os.RemoteException
+    {
+      return mImpl.GetInterfaceList(names);
+    }
+    @Override public boolean VerifyNamesWithInterfaceList(java.util.List<android.aidl.tests.INamedCallback> services, java.lang.String[] names) throws android.os.RemoteException
+    {
+      return mImpl.VerifyNamesWithInterfaceList(services,names);
+    }
+    // Test that List<T> types work correctly.
+    @Override public java.util.List<java.lang.String> ReverseStringList(java.util.List<java.lang.String> input, java.util.List<java.lang.String> repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseStringList(input,repeated);
+    }
+    @Override public android.os.ParcelFileDescriptor RepeatParcelFileDescriptor(android.os.ParcelFileDescriptor read) throws android.os.RemoteException
+    {
+      return mImpl.RepeatParcelFileDescriptor(read);
+    }
+    @Override public android.os.ParcelFileDescriptor[] ReverseParcelFileDescriptorArray(android.os.ParcelFileDescriptor[] input, android.os.ParcelFileDescriptor[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseParcelFileDescriptorArray(input,repeated);
+    }
+    // Test that service specific exceptions work correctly.
+    @Override public void ThrowServiceException(int code) throws android.os.RemoteException
+    {
+      mImpl.ThrowServiceException(code);
+    }
+    // Test nullability
+    @Override public int[] RepeatNullableIntArray(int[] input) throws android.os.RemoteException
+    {
+      return mImpl.RepeatNullableIntArray(input);
+    }
+    @Override public byte[] RepeatNullableByteEnumArray(byte[] input) throws android.os.RemoteException
+    {
+      return mImpl.RepeatNullableByteEnumArray(input);
+    }
+    @Override public int[] RepeatNullableIntEnumArray(int[] input) throws android.os.RemoteException
+    {
+      return mImpl.RepeatNullableIntEnumArray(input);
+    }
+    @Override public long[] RepeatNullableLongEnumArray(long[] input) throws android.os.RemoteException
+    {
+      return mImpl.RepeatNullableLongEnumArray(input);
+    }
+    @Override public java.lang.String RepeatNullableString(java.lang.String input) throws android.os.RemoteException
+    {
+      return mImpl.RepeatNullableString(input);
+    }
+    @Override public java.util.List<java.lang.String> RepeatNullableStringList(java.util.List<java.lang.String> input) throws android.os.RemoteException
+    {
+      return mImpl.RepeatNullableStringList(input);
+    }
+    @Override public android.aidl.tests.ITestService.Empty RepeatNullableParcelable(android.aidl.tests.ITestService.Empty input) throws android.os.RemoteException
+    {
+      return mImpl.RepeatNullableParcelable(input);
+    }
+    @Override public android.aidl.tests.ITestService.Empty[] RepeatNullableParcelableArray(android.aidl.tests.ITestService.Empty[] input) throws android.os.RemoteException
+    {
+      return mImpl.RepeatNullableParcelableArray(input);
+    }
+    @Override public java.util.List<android.aidl.tests.ITestService.Empty> RepeatNullableParcelableList(java.util.List<android.aidl.tests.ITestService.Empty> input) throws android.os.RemoteException
+    {
+      return mImpl.RepeatNullableParcelableList(input);
+    }
+    @Override public void TakesAnIBinder(android.os.IBinder input) throws android.os.RemoteException
+    {
+      mImpl.TakesAnIBinder(input);
+    }
+    @Override public void TakesANullableIBinder(android.os.IBinder input) throws android.os.RemoteException
+    {
+      mImpl.TakesANullableIBinder(input);
+    }
+    @Override public void TakesAnIBinderList(java.util.List<android.os.IBinder> input) throws android.os.RemoteException
+    {
+      mImpl.TakesAnIBinderList(input);
+    }
+    @Override public void TakesANullableIBinderList(java.util.List<android.os.IBinder> input) throws android.os.RemoteException
+    {
+      mImpl.TakesANullableIBinderList(input);
+    }
+    // Test utf8 decoding from utf16 wire format
+    @Override public java.lang.String RepeatUtf8CppString(java.lang.String token) throws android.os.RemoteException
+    {
+      return mImpl.RepeatUtf8CppString(token);
+    }
+    @Override public java.lang.String RepeatNullableUtf8CppString(java.lang.String token) throws android.os.RemoteException
+    {
+      return mImpl.RepeatNullableUtf8CppString(token);
+    }
+    @Override public java.lang.String[] ReverseUtf8CppString(java.lang.String[] input, java.lang.String[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseUtf8CppString(input,repeated);
+    }
+    @Override public java.lang.String[] ReverseNullableUtf8CppString(java.lang.String[] input, java.lang.String[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseNullableUtf8CppString(input,repeated);
+    }
+    @Override public java.util.List<java.lang.String> ReverseUtf8CppStringList(java.util.List<java.lang.String> input, java.util.List<java.lang.String> repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseUtf8CppStringList(input,repeated);
+    }
+    /** comment before annotation */
+    @Override public android.aidl.tests.INamedCallback GetCallback(boolean return_null) throws android.os.RemoteException
+    {
+      return mImpl.GetCallback(return_null);
+    }
+    // Since this paracelable has clearly defined default values, it would be
+    // inefficient to use an IPC to fill it out in practice.
+    @Override public void FillOutStructuredParcelable(android.aidl.tests.StructuredParcelable parcel) throws android.os.RemoteException
+    {
+      mImpl.FillOutStructuredParcelable(parcel);
+    }
+    @Override public void RepeatExtendableParcelable(android.aidl.tests.extension.ExtendableParcelable ep, android.aidl.tests.extension.ExtendableParcelable ep2) throws android.os.RemoteException
+    {
+      mImpl.RepeatExtendableParcelable(ep,ep2);
+    }
+    @Override public android.aidl.tests.RecursiveList ReverseList(android.aidl.tests.RecursiveList list) throws android.os.RemoteException
+    {
+      return mImpl.ReverseList(list);
+    }
+    @Override public android.os.IBinder[] ReverseIBinderArray(android.os.IBinder[] input, android.os.IBinder[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseIBinderArray(input,repeated);
+    }
+    @Override public android.os.IBinder[] ReverseNullableIBinderArray(android.os.IBinder[] input, android.os.IBinder[] repeated) throws android.os.RemoteException
+    {
+      return mImpl.ReverseNullableIBinderArray(input,repeated);
+    }
+    @Override public android.aidl.tests.IOldName GetOldNameInterface() throws android.os.RemoteException
+    {
+      return mImpl.GetOldNameInterface();
+    }
+    @Override public android.aidl.tests.INewName GetNewNameInterface() throws android.os.RemoteException
+    {
+      return mImpl.GetNewNameInterface();
+    }
+    // Retrieve the ICppJavaTests if the server supports it
+    @Override public android.os.IBinder GetCppJavaTests() throws android.os.RemoteException
+    {
+      return mImpl.GetCppJavaTests();
+    }
+    @Override public byte getBackendType() throws android.os.RemoteException
+    {
+      return mImpl.getBackendType();
+    }
+    android.aidl.tests.ITestService mImpl;
+  }
   /** Local-side IPC implementation stub class. */
   public static abstract class Stub extends android.os.Binder implements android.aidl.tests.ITestService
   {
@@ -265,6 +614,9 @@
     @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:
@@ -277,668 +629,778 @@
       {
         case TRANSACTION_UnimplementedMethod:
         {
-          data.enforceInterface(descriptor);
           int _arg0;
           _arg0 = data.readInt();
+          data.enforceNoDataAvail();
           int _result = this.UnimplementedMethod(_arg0);
           reply.writeNoException();
           reply.writeInt(_result);
-          return true;
+          break;
         }
         case TRANSACTION_Deprecated:
         {
-          data.enforceInterface(descriptor);
           this.Deprecated();
           reply.writeNoException();
-          return true;
+          break;
         }
         case TRANSACTION_TestOneway:
         {
-          data.enforceInterface(descriptor);
           this.TestOneway();
-          return true;
+          break;
         }
         case TRANSACTION_RepeatBoolean:
         {
-          data.enforceInterface(descriptor);
           boolean _arg0;
-          _arg0 = (0!=data.readInt());
+          _arg0 = data.readBoolean();
+          data.enforceNoDataAvail();
           boolean _result = this.RepeatBoolean(_arg0);
           reply.writeNoException();
-          reply.writeInt(((_result)?(1):(0)));
-          return true;
+          reply.writeBoolean(_result);
+          break;
         }
         case TRANSACTION_RepeatByte:
         {
-          data.enforceInterface(descriptor);
           byte _arg0;
           _arg0 = data.readByte();
+          data.enforceNoDataAvail();
           byte _result = this.RepeatByte(_arg0);
           reply.writeNoException();
           reply.writeByte(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatChar:
         {
-          data.enforceInterface(descriptor);
           char _arg0;
           _arg0 = (char)data.readInt();
+          data.enforceNoDataAvail();
           char _result = this.RepeatChar(_arg0);
           reply.writeNoException();
           reply.writeInt(((int)_result));
-          return true;
+          break;
         }
         case TRANSACTION_RepeatInt:
         {
-          data.enforceInterface(descriptor);
           int _arg0;
           _arg0 = data.readInt();
+          data.enforceNoDataAvail();
           int _result = this.RepeatInt(_arg0);
           reply.writeNoException();
           reply.writeInt(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatLong:
         {
-          data.enforceInterface(descriptor);
           long _arg0;
           _arg0 = data.readLong();
+          data.enforceNoDataAvail();
           long _result = this.RepeatLong(_arg0);
           reply.writeNoException();
           reply.writeLong(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatFloat:
         {
-          data.enforceInterface(descriptor);
           float _arg0;
           _arg0 = data.readFloat();
+          data.enforceNoDataAvail();
           float _result = this.RepeatFloat(_arg0);
           reply.writeNoException();
           reply.writeFloat(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatDouble:
         {
-          data.enforceInterface(descriptor);
           double _arg0;
           _arg0 = data.readDouble();
+          data.enforceNoDataAvail();
           double _result = this.RepeatDouble(_arg0);
           reply.writeNoException();
           reply.writeDouble(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatString:
         {
-          data.enforceInterface(descriptor);
           java.lang.String _arg0;
           _arg0 = data.readString();
+          data.enforceNoDataAvail();
           java.lang.String _result = this.RepeatString(_arg0);
           reply.writeNoException();
           reply.writeString(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatByteEnum:
         {
-          data.enforceInterface(descriptor);
           byte _arg0;
           _arg0 = data.readByte();
+          data.enforceNoDataAvail();
           byte _result = this.RepeatByteEnum(_arg0);
           reply.writeNoException();
           reply.writeByte(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatIntEnum:
         {
-          data.enforceInterface(descriptor);
           int _arg0;
           _arg0 = data.readInt();
+          data.enforceNoDataAvail();
           int _result = this.RepeatIntEnum(_arg0);
           reply.writeNoException();
           reply.writeInt(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatLongEnum:
         {
-          data.enforceInterface(descriptor);
           long _arg0;
           _arg0 = data.readLong();
+          data.enforceNoDataAvail();
           long _result = this.RepeatLongEnum(_arg0);
           reply.writeNoException();
           reply.writeLong(_result);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseBoolean:
         {
-          data.enforceInterface(descriptor);
           boolean[] _arg0;
           _arg0 = data.createBooleanArray();
           boolean[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new boolean[_arg1_length];
           }
+          data.enforceNoDataAvail();
           boolean[] _result = this.ReverseBoolean(_arg0, _arg1);
           reply.writeNoException();
           reply.writeBooleanArray(_result);
           reply.writeBooleanArray(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseByte:
         {
-          data.enforceInterface(descriptor);
           byte[] _arg0;
           _arg0 = data.createByteArray();
           byte[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new byte[_arg1_length];
           }
+          data.enforceNoDataAvail();
           byte[] _result = this.ReverseByte(_arg0, _arg1);
           reply.writeNoException();
           reply.writeByteArray(_result);
           reply.writeByteArray(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseChar:
         {
-          data.enforceInterface(descriptor);
           char[] _arg0;
           _arg0 = data.createCharArray();
           char[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new char[_arg1_length];
           }
+          data.enforceNoDataAvail();
           char[] _result = this.ReverseChar(_arg0, _arg1);
           reply.writeNoException();
           reply.writeCharArray(_result);
           reply.writeCharArray(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseInt:
         {
-          data.enforceInterface(descriptor);
           int[] _arg0;
           _arg0 = data.createIntArray();
           int[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new int[_arg1_length];
           }
+          data.enforceNoDataAvail();
           int[] _result = this.ReverseInt(_arg0, _arg1);
           reply.writeNoException();
           reply.writeIntArray(_result);
           reply.writeIntArray(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseLong:
         {
-          data.enforceInterface(descriptor);
           long[] _arg0;
           _arg0 = data.createLongArray();
           long[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new long[_arg1_length];
           }
+          data.enforceNoDataAvail();
           long[] _result = this.ReverseLong(_arg0, _arg1);
           reply.writeNoException();
           reply.writeLongArray(_result);
           reply.writeLongArray(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseFloat:
         {
-          data.enforceInterface(descriptor);
           float[] _arg0;
           _arg0 = data.createFloatArray();
           float[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new float[_arg1_length];
           }
+          data.enforceNoDataAvail();
           float[] _result = this.ReverseFloat(_arg0, _arg1);
           reply.writeNoException();
           reply.writeFloatArray(_result);
           reply.writeFloatArray(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseDouble:
         {
-          data.enforceInterface(descriptor);
           double[] _arg0;
           _arg0 = data.createDoubleArray();
           double[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new double[_arg1_length];
           }
+          data.enforceNoDataAvail();
           double[] _result = this.ReverseDouble(_arg0, _arg1);
           reply.writeNoException();
           reply.writeDoubleArray(_result);
           reply.writeDoubleArray(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseString:
         {
-          data.enforceInterface(descriptor);
           java.lang.String[] _arg0;
           _arg0 = data.createStringArray();
           java.lang.String[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new java.lang.String[_arg1_length];
           }
+          data.enforceNoDataAvail();
           java.lang.String[] _result = this.ReverseString(_arg0, _arg1);
           reply.writeNoException();
           reply.writeStringArray(_result);
           reply.writeStringArray(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseByteEnum:
         {
-          data.enforceInterface(descriptor);
           byte[] _arg0;
           _arg0 = data.createByteArray();
           byte[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new byte[_arg1_length];
           }
+          data.enforceNoDataAvail();
           byte[] _result = this.ReverseByteEnum(_arg0, _arg1);
           reply.writeNoException();
           reply.writeByteArray(_result);
           reply.writeByteArray(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseIntEnum:
         {
-          data.enforceInterface(descriptor);
           int[] _arg0;
           _arg0 = data.createIntArray();
           int[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new int[_arg1_length];
           }
+          data.enforceNoDataAvail();
           int[] _result = this.ReverseIntEnum(_arg0, _arg1);
           reply.writeNoException();
           reply.writeIntArray(_result);
           reply.writeIntArray(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseLongEnum:
         {
-          data.enforceInterface(descriptor);
           long[] _arg0;
           _arg0 = data.createLongArray();
           long[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new long[_arg1_length];
           }
+          data.enforceNoDataAvail();
           long[] _result = this.ReverseLongEnum(_arg0, _arg1);
           reply.writeNoException();
           reply.writeLongArray(_result);
           reply.writeLongArray(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_GetOtherTestService:
         {
-          data.enforceInterface(descriptor);
           java.lang.String _arg0;
           _arg0 = data.readString();
+          data.enforceNoDataAvail();
           android.aidl.tests.INamedCallback _result = this.GetOtherTestService(_arg0);
           reply.writeNoException();
-          reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));
-          return true;
+          reply.writeStrongInterface(_result);
+          break;
         }
         case TRANSACTION_VerifyName:
         {
-          data.enforceInterface(descriptor);
           android.aidl.tests.INamedCallback _arg0;
           _arg0 = android.aidl.tests.INamedCallback.Stub.asInterface(data.readStrongBinder());
           java.lang.String _arg1;
           _arg1 = data.readString();
+          data.enforceNoDataAvail();
           boolean _result = this.VerifyName(_arg0, _arg1);
           reply.writeNoException();
-          reply.writeInt(((_result)?(1):(0)));
-          return true;
+          reply.writeBoolean(_result);
+          break;
+        }
+        case TRANSACTION_GetInterfaceArray:
+        {
+          java.lang.String[] _arg0;
+          _arg0 = data.createStringArray();
+          data.enforceNoDataAvail();
+          android.aidl.tests.INamedCallback[] _result = this.GetInterfaceArray(_arg0);
+          reply.writeNoException();
+          reply.writeInterfaceArray(_result);
+          break;
+        }
+        case TRANSACTION_VerifyNamesWithInterfaceArray:
+        {
+          android.aidl.tests.INamedCallback[] _arg0;
+          _arg0 = data.createInterfaceArray(android.aidl.tests.INamedCallback[]::new, android.aidl.tests.INamedCallback.Stub::asInterface);
+          java.lang.String[] _arg1;
+          _arg1 = data.createStringArray();
+          data.enforceNoDataAvail();
+          boolean _result = this.VerifyNamesWithInterfaceArray(_arg0, _arg1);
+          reply.writeNoException();
+          reply.writeBoolean(_result);
+          break;
+        }
+        case TRANSACTION_GetNullableInterfaceArray:
+        {
+          java.lang.String[] _arg0;
+          _arg0 = data.createStringArray();
+          data.enforceNoDataAvail();
+          android.aidl.tests.INamedCallback[] _result = this.GetNullableInterfaceArray(_arg0);
+          reply.writeNoException();
+          reply.writeInterfaceArray(_result);
+          break;
+        }
+        case TRANSACTION_VerifyNamesWithNullableInterfaceArray:
+        {
+          android.aidl.tests.INamedCallback[] _arg0;
+          _arg0 = data.createInterfaceArray(android.aidl.tests.INamedCallback[]::new, android.aidl.tests.INamedCallback.Stub::asInterface);
+          java.lang.String[] _arg1;
+          _arg1 = data.createStringArray();
+          data.enforceNoDataAvail();
+          boolean _result = this.VerifyNamesWithNullableInterfaceArray(_arg0, _arg1);
+          reply.writeNoException();
+          reply.writeBoolean(_result);
+          break;
+        }
+        case TRANSACTION_GetInterfaceList:
+        {
+          java.lang.String[] _arg0;
+          _arg0 = data.createStringArray();
+          data.enforceNoDataAvail();
+          java.util.List<android.aidl.tests.INamedCallback> _result = this.GetInterfaceList(_arg0);
+          reply.writeNoException();
+          reply.writeInterfaceList(_result);
+          break;
+        }
+        case TRANSACTION_VerifyNamesWithInterfaceList:
+        {
+          java.util.List<android.aidl.tests.INamedCallback> _arg0;
+          _arg0 = data.createInterfaceArrayList(android.aidl.tests.INamedCallback.Stub::asInterface);
+          java.lang.String[] _arg1;
+          _arg1 = data.createStringArray();
+          data.enforceNoDataAvail();
+          boolean _result = this.VerifyNamesWithInterfaceList(_arg0, _arg1);
+          reply.writeNoException();
+          reply.writeBoolean(_result);
+          break;
         }
         case TRANSACTION_ReverseStringList:
         {
-          data.enforceInterface(descriptor);
           java.util.List<java.lang.String> _arg0;
           _arg0 = data.createStringArrayList();
           java.util.List<java.lang.String> _arg1;
           _arg1 = new java.util.ArrayList<java.lang.String>();
+          data.enforceNoDataAvail();
           java.util.List<java.lang.String> _result = this.ReverseStringList(_arg0, _arg1);
           reply.writeNoException();
           reply.writeStringList(_result);
           reply.writeStringList(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatParcelFileDescriptor:
         {
-          data.enforceInterface(descriptor);
           android.os.ParcelFileDescriptor _arg0;
-          if ((0!=data.readInt())) {
-            _arg0 = android.os.ParcelFileDescriptor.CREATOR.createFromParcel(data);
-          }
-          else {
-            _arg0 = null;
-          }
+          _arg0 = data.readTypedObject(android.os.ParcelFileDescriptor.CREATOR);
+          data.enforceNoDataAvail();
           android.os.ParcelFileDescriptor _result = this.RepeatParcelFileDescriptor(_arg0);
           reply.writeNoException();
-          if ((_result!=null)) {
-            reply.writeInt(1);
-            _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-          }
-          else {
-            reply.writeInt(0);
-          }
-          return true;
+          reply.writeTypedObject(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+          break;
         }
         case TRANSACTION_ReverseParcelFileDescriptorArray:
         {
-          data.enforceInterface(descriptor);
           android.os.ParcelFileDescriptor[] _arg0;
           _arg0 = data.createTypedArray(android.os.ParcelFileDescriptor.CREATOR);
           android.os.ParcelFileDescriptor[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new android.os.ParcelFileDescriptor[_arg1_length];
           }
+          data.enforceNoDataAvail();
           android.os.ParcelFileDescriptor[] _result = this.ReverseParcelFileDescriptorArray(_arg0, _arg1);
           reply.writeNoException();
           reply.writeTypedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
           reply.writeTypedArray(_arg1, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-          return true;
+          break;
         }
         case TRANSACTION_ThrowServiceException:
         {
-          data.enforceInterface(descriptor);
           int _arg0;
           _arg0 = data.readInt();
+          data.enforceNoDataAvail();
           this.ThrowServiceException(_arg0);
           reply.writeNoException();
-          return true;
+          break;
         }
         case TRANSACTION_RepeatNullableIntArray:
         {
-          data.enforceInterface(descriptor);
           int[] _arg0;
           _arg0 = data.createIntArray();
+          data.enforceNoDataAvail();
           int[] _result = this.RepeatNullableIntArray(_arg0);
           reply.writeNoException();
           reply.writeIntArray(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatNullableByteEnumArray:
         {
-          data.enforceInterface(descriptor);
           byte[] _arg0;
           _arg0 = data.createByteArray();
+          data.enforceNoDataAvail();
           byte[] _result = this.RepeatNullableByteEnumArray(_arg0);
           reply.writeNoException();
           reply.writeByteArray(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatNullableIntEnumArray:
         {
-          data.enforceInterface(descriptor);
           int[] _arg0;
           _arg0 = data.createIntArray();
+          data.enforceNoDataAvail();
           int[] _result = this.RepeatNullableIntEnumArray(_arg0);
           reply.writeNoException();
           reply.writeIntArray(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatNullableLongEnumArray:
         {
-          data.enforceInterface(descriptor);
           long[] _arg0;
           _arg0 = data.createLongArray();
+          data.enforceNoDataAvail();
           long[] _result = this.RepeatNullableLongEnumArray(_arg0);
           reply.writeNoException();
           reply.writeLongArray(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatNullableString:
         {
-          data.enforceInterface(descriptor);
           java.lang.String _arg0;
           _arg0 = data.readString();
+          data.enforceNoDataAvail();
           java.lang.String _result = this.RepeatNullableString(_arg0);
           reply.writeNoException();
           reply.writeString(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatNullableStringList:
         {
-          data.enforceInterface(descriptor);
           java.util.List<java.lang.String> _arg0;
           _arg0 = data.createStringArrayList();
+          data.enforceNoDataAvail();
           java.util.List<java.lang.String> _result = this.RepeatNullableStringList(_arg0);
           reply.writeNoException();
           reply.writeStringList(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatNullableParcelable:
         {
-          data.enforceInterface(descriptor);
-          android.aidl.tests.StructuredParcelable _arg0;
-          if ((0!=data.readInt())) {
-            _arg0 = android.aidl.tests.StructuredParcelable.CREATOR.createFromParcel(data);
-          }
-          else {
-            _arg0 = null;
-          }
-          android.aidl.tests.StructuredParcelable _result = this.RepeatNullableParcelable(_arg0);
+          android.aidl.tests.ITestService.Empty _arg0;
+          _arg0 = data.readTypedObject(android.aidl.tests.ITestService.Empty.CREATOR);
+          data.enforceNoDataAvail();
+          android.aidl.tests.ITestService.Empty _result = this.RepeatNullableParcelable(_arg0);
           reply.writeNoException();
-          if ((_result!=null)) {
-            reply.writeInt(1);
-            _result.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-          }
-          else {
-            reply.writeInt(0);
-          }
-          return true;
+          reply.writeTypedObject(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+          break;
+        }
+        case TRANSACTION_RepeatNullableParcelableArray:
+        {
+          android.aidl.tests.ITestService.Empty[] _arg0;
+          _arg0 = data.createTypedArray(android.aidl.tests.ITestService.Empty.CREATOR);
+          data.enforceNoDataAvail();
+          android.aidl.tests.ITestService.Empty[] _result = this.RepeatNullableParcelableArray(_arg0);
+          reply.writeNoException();
+          reply.writeTypedArray(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+          break;
+        }
+        case TRANSACTION_RepeatNullableParcelableList:
+        {
+          java.util.List<android.aidl.tests.ITestService.Empty> _arg0;
+          _arg0 = data.createTypedArrayList(android.aidl.tests.ITestService.Empty.CREATOR);
+          data.enforceNoDataAvail();
+          java.util.List<android.aidl.tests.ITestService.Empty> _result = this.RepeatNullableParcelableList(_arg0);
+          reply.writeNoException();
+          reply.writeTypedList(_result);
+          break;
         }
         case TRANSACTION_TakesAnIBinder:
         {
-          data.enforceInterface(descriptor);
           android.os.IBinder _arg0;
           _arg0 = data.readStrongBinder();
+          data.enforceNoDataAvail();
           this.TakesAnIBinder(_arg0);
           reply.writeNoException();
-          return true;
+          break;
         }
         case TRANSACTION_TakesANullableIBinder:
         {
-          data.enforceInterface(descriptor);
           android.os.IBinder _arg0;
           _arg0 = data.readStrongBinder();
+          data.enforceNoDataAvail();
           this.TakesANullableIBinder(_arg0);
           reply.writeNoException();
-          return true;
+          break;
+        }
+        case TRANSACTION_TakesAnIBinderList:
+        {
+          java.util.List<android.os.IBinder> _arg0;
+          _arg0 = data.createBinderArrayList();
+          data.enforceNoDataAvail();
+          this.TakesAnIBinderList(_arg0);
+          reply.writeNoException();
+          break;
+        }
+        case TRANSACTION_TakesANullableIBinderList:
+        {
+          java.util.List<android.os.IBinder> _arg0;
+          _arg0 = data.createBinderArrayList();
+          data.enforceNoDataAvail();
+          this.TakesANullableIBinderList(_arg0);
+          reply.writeNoException();
+          break;
         }
         case TRANSACTION_RepeatUtf8CppString:
         {
-          data.enforceInterface(descriptor);
           java.lang.String _arg0;
           _arg0 = data.readString();
+          data.enforceNoDataAvail();
           java.lang.String _result = this.RepeatUtf8CppString(_arg0);
           reply.writeNoException();
           reply.writeString(_result);
-          return true;
+          break;
         }
         case TRANSACTION_RepeatNullableUtf8CppString:
         {
-          data.enforceInterface(descriptor);
           java.lang.String _arg0;
           _arg0 = data.readString();
+          data.enforceNoDataAvail();
           java.lang.String _result = this.RepeatNullableUtf8CppString(_arg0);
           reply.writeNoException();
           reply.writeString(_result);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseUtf8CppString:
         {
-          data.enforceInterface(descriptor);
           java.lang.String[] _arg0;
           _arg0 = data.createStringArray();
           java.lang.String[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new java.lang.String[_arg1_length];
           }
+          data.enforceNoDataAvail();
           java.lang.String[] _result = this.ReverseUtf8CppString(_arg0, _arg1);
           reply.writeNoException();
           reply.writeStringArray(_result);
           reply.writeStringArray(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseNullableUtf8CppString:
         {
-          data.enforceInterface(descriptor);
           java.lang.String[] _arg0;
           _arg0 = data.createStringArray();
           java.lang.String[] _arg1;
           int _arg1_length = data.readInt();
-          if ((_arg1_length<0)) {
+          if (_arg1_length < 0) {
             _arg1 = null;
-          }
-          else {
+          } else {
             _arg1 = new java.lang.String[_arg1_length];
           }
+          data.enforceNoDataAvail();
           java.lang.String[] _result = this.ReverseNullableUtf8CppString(_arg0, _arg1);
           reply.writeNoException();
           reply.writeStringArray(_result);
           reply.writeStringArray(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_ReverseUtf8CppStringList:
         {
-          data.enforceInterface(descriptor);
           java.util.List<java.lang.String> _arg0;
           _arg0 = data.createStringArrayList();
           java.util.List<java.lang.String> _arg1;
           _arg1 = new java.util.ArrayList<java.lang.String>();
+          data.enforceNoDataAvail();
           java.util.List<java.lang.String> _result = this.ReverseUtf8CppStringList(_arg0, _arg1);
           reply.writeNoException();
           reply.writeStringList(_result);
           reply.writeStringList(_arg1);
-          return true;
+          break;
         }
         case TRANSACTION_GetCallback:
         {
-          data.enforceInterface(descriptor);
           boolean _arg0;
-          _arg0 = (0!=data.readInt());
+          _arg0 = data.readBoolean();
+          data.enforceNoDataAvail();
           android.aidl.tests.INamedCallback _result = this.GetCallback(_arg0);
           reply.writeNoException();
-          reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));
-          return true;
+          reply.writeStrongInterface(_result);
+          break;
         }
         case TRANSACTION_FillOutStructuredParcelable:
         {
-          data.enforceInterface(descriptor);
           android.aidl.tests.StructuredParcelable _arg0;
-          if ((0!=data.readInt())) {
-            _arg0 = android.aidl.tests.StructuredParcelable.CREATOR.createFromParcel(data);
-          }
-          else {
-            _arg0 = null;
-          }
+          _arg0 = data.readTypedObject(android.aidl.tests.StructuredParcelable.CREATOR);
+          data.enforceNoDataAvail();
           this.FillOutStructuredParcelable(_arg0);
           reply.writeNoException();
-          if ((_arg0!=null)) {
-            reply.writeInt(1);
-            _arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+          reply.writeTypedObject(_arg0, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+          break;
+        }
+        case TRANSACTION_RepeatExtendableParcelable:
+        {
+          android.aidl.tests.extension.ExtendableParcelable _arg0;
+          _arg0 = data.readTypedObject(android.aidl.tests.extension.ExtendableParcelable.CREATOR);
+          android.aidl.tests.extension.ExtendableParcelable _arg1;
+          _arg1 = new android.aidl.tests.extension.ExtendableParcelable();
+          data.enforceNoDataAvail();
+          this.RepeatExtendableParcelable(_arg0, _arg1);
+          reply.writeNoException();
+          reply.writeTypedObject(_arg1, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+          break;
+        }
+        case TRANSACTION_ReverseList:
+        {
+          android.aidl.tests.RecursiveList _arg0;
+          _arg0 = data.readTypedObject(android.aidl.tests.RecursiveList.CREATOR);
+          data.enforceNoDataAvail();
+          android.aidl.tests.RecursiveList _result = this.ReverseList(_arg0);
+          reply.writeNoException();
+          reply.writeTypedObject(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+          break;
+        }
+        case TRANSACTION_ReverseIBinderArray:
+        {
+          android.os.IBinder[] _arg0;
+          _arg0 = data.createBinderArray();
+          android.os.IBinder[] _arg1;
+          int _arg1_length = data.readInt();
+          if (_arg1_length < 0) {
+            _arg1 = null;
+          } else {
+            _arg1 = new android.os.IBinder[_arg1_length];
           }
-          else {
-            reply.writeInt(0);
+          data.enforceNoDataAvail();
+          android.os.IBinder[] _result = this.ReverseIBinderArray(_arg0, _arg1);
+          reply.writeNoException();
+          reply.writeBinderArray(_result);
+          reply.writeBinderArray(_arg1);
+          break;
+        }
+        case TRANSACTION_ReverseNullableIBinderArray:
+        {
+          android.os.IBinder[] _arg0;
+          _arg0 = data.createBinderArray();
+          android.os.IBinder[] _arg1;
+          int _arg1_length = data.readInt();
+          if (_arg1_length < 0) {
+            _arg1 = null;
+          } else {
+            _arg1 = new android.os.IBinder[_arg1_length];
           }
-          return true;
+          data.enforceNoDataAvail();
+          android.os.IBinder[] _result = this.ReverseNullableIBinderArray(_arg0, _arg1);
+          reply.writeNoException();
+          reply.writeBinderArray(_result);
+          reply.writeBinderArray(_arg1);
+          break;
         }
         case TRANSACTION_GetOldNameInterface:
         {
-          data.enforceInterface(descriptor);
           android.aidl.tests.IOldName _result = this.GetOldNameInterface();
           reply.writeNoException();
-          reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));
-          return true;
+          reply.writeStrongInterface(_result);
+          break;
         }
         case TRANSACTION_GetNewNameInterface:
         {
-          data.enforceInterface(descriptor);
           android.aidl.tests.INewName _result = this.GetNewNameInterface();
           reply.writeNoException();
-          reply.writeStrongBinder((((_result!=null))?(_result.asBinder()):(null)));
-          return true;
+          reply.writeStrongInterface(_result);
+          break;
         }
         case TRANSACTION_GetCppJavaTests:
         {
-          data.enforceInterface(descriptor);
           android.os.IBinder _result = this.GetCppJavaTests();
           reply.writeNoException();
           reply.writeStrongBinder(_result);
-          return true;
+          break;
         }
         case TRANSACTION_getBackendType:
         {
-          data.enforceInterface(descriptor);
           byte _result = this.getBackendType();
           reply.writeNoException();
           reply.writeByte(_result);
-          return true;
+          break;
         }
         default:
         {
           return super.onTransact(code, data, reply, flags);
         }
       }
+      return true;
     }
     private static class Proxy implements android.aidl.tests.ITestService
     {
@@ -968,8 +1430,9 @@
       // methods to be added and removed.
       @Override public int UnimplementedMethod(int arg) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         int _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -990,13 +1453,14 @@
         return _result;
       }
       /**
-           * @deprecated to make sure we have something in system/tools/aidl which does a compile check
-           *     of deprecated and make sure this is reflected in goldens
-           */
+       * @deprecated to make sure we have something in system/tools/aidl which does a compile check
+       *     of deprecated and make sure this is reflected in goldens
+       */
       @Override public void Deprecated() throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_Deprecated, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
@@ -1015,8 +1479,9 @@
       }
       @Override public void TestOneway() throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();try {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        try {
           _data.writeInterfaceToken(DESCRIPTOR);
           boolean _status = mRemote.transact(Stub.TRANSACTION_TestOneway, _data, null, android.os.IBinder.FLAG_ONEWAY | android.os.IBinder.FLAG_CLEAR_BUF);
           if (!_status) {
@@ -1033,12 +1498,13 @@
       // Test that primitives work as parameters and return types.
       @Override public boolean RepeatBoolean(boolean token) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         boolean _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
-          _data.writeInt(((token)?(1):(0)));
+          _data.writeBoolean(token);
           boolean _status = mRemote.transact(Stub.TRANSACTION_RepeatBoolean, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
           if (!_status) {
             if (getDefaultImpl() != null) {
@@ -1046,7 +1512,7 @@
             }
           }
           _reply.readException();
-          _result = (0!=_reply.readInt());
+          _result = _reply.readBoolean();
         }
         finally {
           _reply.recycle();
@@ -1056,8 +1522,9 @@
       }
       @Override public byte RepeatByte(byte token) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         byte _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1079,8 +1546,9 @@
       }
       @Override public char RepeatChar(char token) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         char _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1102,8 +1570,9 @@
       }
       @Override public int RepeatInt(int token) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         int _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1125,8 +1594,9 @@
       }
       @Override public long RepeatLong(long token) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         long _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1148,8 +1618,9 @@
       }
       @Override public float RepeatFloat(float token) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         float _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1171,8 +1642,9 @@
       }
       @Override public double RepeatDouble(double token) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         double _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1194,8 +1666,9 @@
       }
       @Override public java.lang.String RepeatString(java.lang.String token) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         java.lang.String _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1217,8 +1690,9 @@
       }
       @Override public byte RepeatByteEnum(byte token) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         byte _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1240,8 +1714,9 @@
       }
       @Override public int RepeatIntEnum(int token) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         int _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1263,8 +1738,9 @@
       }
       @Override public long RepeatLongEnum(long token) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         long _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1287,8 +1763,9 @@
       // Test that arrays work as parameters and return types.
       @Override public boolean[] ReverseBoolean(boolean[] input, boolean[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         boolean[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1317,8 +1794,9 @@
       }
       @Override public byte[] ReverseByte(byte[] input, byte[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         byte[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1347,8 +1825,9 @@
       }
       @Override public char[] ReverseChar(char[] input, char[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         char[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1377,8 +1856,9 @@
       }
       @Override public int[] ReverseInt(int[] input, int[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         int[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1407,8 +1887,9 @@
       }
       @Override public long[] ReverseLong(long[] input, long[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         long[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1437,8 +1918,9 @@
       }
       @Override public float[] ReverseFloat(float[] input, float[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         float[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1467,8 +1949,9 @@
       }
       @Override public double[] ReverseDouble(double[] input, double[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         double[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1497,8 +1980,9 @@
       }
       @Override public java.lang.String[] ReverseString(java.lang.String[] input, java.lang.String[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         java.lang.String[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1527,8 +2011,9 @@
       }
       @Override public byte[] ReverseByteEnum(byte[] input, byte[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         byte[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1557,8 +2042,9 @@
       }
       @Override public int[] ReverseIntEnum(int[] input, int[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         int[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1587,8 +2073,9 @@
       }
       @Override public long[] ReverseLongEnum(long[] input, long[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         long[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1618,13 +2105,15 @@
       // Test that clients can send and receive Binders.
       @Override public android.aidl.tests.INamedCallback GetOtherTestService(java.lang.String name) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         android.aidl.tests.INamedCallback _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           _data.writeString(name);
           boolean _status = mRemote.transact(Stub.TRANSACTION_GetOtherTestService, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          _reply.setPropagateAllowBlocking();
           if (!_status) {
             if (getDefaultImpl() != null) {
               return getDefaultImpl().GetOtherTestService(name);
@@ -1641,12 +2130,13 @@
       }
       @Override public boolean VerifyName(android.aidl.tests.INamedCallback service, java.lang.String name) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         boolean _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
-          _data.writeStrongBinder((((service!=null))?(service.asBinder()):(null)));
+          _data.writeStrongInterface(service);
           _data.writeString(name);
           boolean _status = mRemote.transact(Stub.TRANSACTION_VerifyName, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
           if (!_status) {
@@ -1655,7 +2145,154 @@
             }
           }
           _reply.readException();
-          _result = (0!=_reply.readInt());
+          _result = _reply.readBoolean();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public android.aidl.tests.INamedCallback[] GetInterfaceArray(java.lang.String[] names) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.aidl.tests.INamedCallback[] _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeStringArray(names);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_GetInterfaceArray, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              return getDefaultImpl().GetInterfaceArray(names);
+            }
+          }
+          _reply.readException();
+          _result = _reply.createInterfaceArray(android.aidl.tests.INamedCallback[]::new, android.aidl.tests.INamedCallback.Stub::asInterface);
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public boolean VerifyNamesWithInterfaceArray(android.aidl.tests.INamedCallback[] services, java.lang.String[] names) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        boolean _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeInterfaceArray(services);
+          _data.writeStringArray(names);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_VerifyNamesWithInterfaceArray, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              return getDefaultImpl().VerifyNamesWithInterfaceArray(services, names);
+            }
+          }
+          _reply.readException();
+          _result = _reply.readBoolean();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public android.aidl.tests.INamedCallback[] GetNullableInterfaceArray(java.lang.String[] names) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.aidl.tests.INamedCallback[] _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeStringArray(names);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_GetNullableInterfaceArray, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              return getDefaultImpl().GetNullableInterfaceArray(names);
+            }
+          }
+          _reply.readException();
+          _result = _reply.createInterfaceArray(android.aidl.tests.INamedCallback[]::new, android.aidl.tests.INamedCallback.Stub::asInterface);
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public boolean VerifyNamesWithNullableInterfaceArray(android.aidl.tests.INamedCallback[] services, java.lang.String[] names) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        boolean _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeInterfaceArray(services);
+          _data.writeStringArray(names);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_VerifyNamesWithNullableInterfaceArray, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              return getDefaultImpl().VerifyNamesWithNullableInterfaceArray(services, names);
+            }
+          }
+          _reply.readException();
+          _result = _reply.readBoolean();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public java.util.List<android.aidl.tests.INamedCallback> GetInterfaceList(java.lang.String[] names) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        java.util.List<android.aidl.tests.INamedCallback> _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeStringArray(names);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_GetInterfaceList, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              return getDefaultImpl().GetInterfaceList(names);
+            }
+          }
+          _reply.readException();
+          _result = _reply.createInterfaceArrayList(android.aidl.tests.INamedCallback.Stub::asInterface);
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public boolean VerifyNamesWithInterfaceList(java.util.List<android.aidl.tests.INamedCallback> services, java.lang.String[] names) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        boolean _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeInterfaceList(services);
+          _data.writeStringArray(names);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_VerifyNamesWithInterfaceList, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              return getDefaultImpl().VerifyNamesWithInterfaceList(services, names);
+            }
+          }
+          _reply.readException();
+          _result = _reply.readBoolean();
         }
         finally {
           _reply.recycle();
@@ -1666,8 +2303,9 @@
       // Test that List<T> types work correctly.
       @Override public java.util.List<java.lang.String> ReverseStringList(java.util.List<java.lang.String> input, java.util.List<java.lang.String> repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         java.util.List<java.lang.String> _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1690,18 +2328,13 @@
       }
       @Override public android.os.ParcelFileDescriptor RepeatParcelFileDescriptor(android.os.ParcelFileDescriptor read) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         android.os.ParcelFileDescriptor _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
-          if ((read!=null)) {
-            _data.writeInt(1);
-            read.writeToParcel(_data, 0);
-          }
-          else {
-            _data.writeInt(0);
-          }
+          _data.writeTypedObject(read, 0);
           boolean _status = mRemote.transact(Stub.TRANSACTION_RepeatParcelFileDescriptor, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
           if (!_status) {
             if (getDefaultImpl() != null) {
@@ -1709,12 +2342,7 @@
             }
           }
           _reply.readException();
-          if ((0!=_reply.readInt())) {
-            _result = android.os.ParcelFileDescriptor.CREATOR.createFromParcel(_reply);
-          }
-          else {
-            _result = null;
-          }
+          _result = _reply.readTypedObject(android.os.ParcelFileDescriptor.CREATOR);
         }
         finally {
           _reply.recycle();
@@ -1724,8 +2352,9 @@
       }
       @Override public android.os.ParcelFileDescriptor[] ReverseParcelFileDescriptorArray(android.os.ParcelFileDescriptor[] input, android.os.ParcelFileDescriptor[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         android.os.ParcelFileDescriptor[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1755,8 +2384,9 @@
       // Test that service specific exceptions work correctly.
       @Override public void ThrowServiceException(int code) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           _data.writeInt(code);
@@ -1777,8 +2407,9 @@
       // Test nullability
       @Override public int[] RepeatNullableIntArray(int[] input) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         int[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1800,8 +2431,9 @@
       }
       @Override public byte[] RepeatNullableByteEnumArray(byte[] input) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         byte[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1823,8 +2455,9 @@
       }
       @Override public int[] RepeatNullableIntEnumArray(int[] input) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         int[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1846,8 +2479,9 @@
       }
       @Override public long[] RepeatNullableLongEnumArray(long[] input) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         long[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1869,8 +2503,9 @@
       }
       @Override public java.lang.String RepeatNullableString(java.lang.String input) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         java.lang.String _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1892,8 +2527,9 @@
       }
       @Override public java.util.List<java.lang.String> RepeatNullableStringList(java.util.List<java.lang.String> input) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         java.util.List<java.lang.String> _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -1913,20 +2549,15 @@
         }
         return _result;
       }
-      @Override public android.aidl.tests.StructuredParcelable RepeatNullableParcelable(android.aidl.tests.StructuredParcelable input) throws android.os.RemoteException
+      @Override public android.aidl.tests.ITestService.Empty RepeatNullableParcelable(android.aidl.tests.ITestService.Empty input) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
-        android.aidl.tests.StructuredParcelable _result;
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.aidl.tests.ITestService.Empty _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
-          if ((input!=null)) {
-            _data.writeInt(1);
-            input.writeToParcel(_data, 0);
-          }
-          else {
-            _data.writeInt(0);
-          }
+          _data.writeTypedObject(input, 0);
           boolean _status = mRemote.transact(Stub.TRANSACTION_RepeatNullableParcelable, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
           if (!_status) {
             if (getDefaultImpl() != null) {
@@ -1934,12 +2565,55 @@
             }
           }
           _reply.readException();
-          if ((0!=_reply.readInt())) {
-            _result = android.aidl.tests.StructuredParcelable.CREATOR.createFromParcel(_reply);
+          _result = _reply.readTypedObject(android.aidl.tests.ITestService.Empty.CREATOR);
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public android.aidl.tests.ITestService.Empty[] RepeatNullableParcelableArray(android.aidl.tests.ITestService.Empty[] input) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.aidl.tests.ITestService.Empty[] _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeTypedArray(input, 0);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_RepeatNullableParcelableArray, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              return getDefaultImpl().RepeatNullableParcelableArray(input);
+            }
           }
-          else {
-            _result = null;
+          _reply.readException();
+          _result = _reply.createTypedArray(android.aidl.tests.ITestService.Empty.CREATOR);
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public java.util.List<android.aidl.tests.ITestService.Empty> RepeatNullableParcelableList(java.util.List<android.aidl.tests.ITestService.Empty> input) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        java.util.List<android.aidl.tests.ITestService.Empty> _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeTypedList(input);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_RepeatNullableParcelableList, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              return getDefaultImpl().RepeatNullableParcelableList(input);
+            }
           }
+          _reply.readException();
+          _result = _reply.createTypedArrayList(android.aidl.tests.ITestService.Empty.CREATOR);
         }
         finally {
           _reply.recycle();
@@ -1949,8 +2623,9 @@
       }
       @Override public void TakesAnIBinder(android.os.IBinder input) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           _data.writeStrongBinder(input);
@@ -1970,8 +2645,9 @@
       }
       @Override public void TakesANullableIBinder(android.os.IBinder input) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
           _data.writeStrongBinder(input);
@@ -1989,11 +2665,56 @@
           _data.recycle();
         }
       }
+      @Override public void TakesAnIBinderList(java.util.List<android.os.IBinder> input) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeBinderList(input);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_TakesAnIBinderList, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              getDefaultImpl().TakesAnIBinderList(input);
+              return;
+            }
+          }
+          _reply.readException();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
+      @Override public void TakesANullableIBinderList(java.util.List<android.os.IBinder> input) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeBinderList(input);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_TakesANullableIBinderList, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              getDefaultImpl().TakesANullableIBinderList(input);
+              return;
+            }
+          }
+          _reply.readException();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
       // Test utf8 decoding from utf16 wire format
       @Override public java.lang.String RepeatUtf8CppString(java.lang.String token) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         java.lang.String _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -2015,8 +2736,9 @@
       }
       @Override public java.lang.String RepeatNullableUtf8CppString(java.lang.String token) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         java.lang.String _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -2038,8 +2760,9 @@
       }
       @Override public java.lang.String[] ReverseUtf8CppString(java.lang.String[] input, java.lang.String[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         java.lang.String[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -2068,8 +2791,9 @@
       }
       @Override public java.lang.String[] ReverseNullableUtf8CppString(java.lang.String[] input, java.lang.String[] repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         java.lang.String[] _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -2098,8 +2822,9 @@
       }
       @Override public java.util.List<java.lang.String> ReverseUtf8CppStringList(java.util.List<java.lang.String> input, java.util.List<java.lang.String> repeated) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         java.util.List<java.lang.String> _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -2120,14 +2845,16 @@
         }
         return _result;
       }
+      /** comment before annotation */
       @Override public android.aidl.tests.INamedCallback GetCallback(boolean return_null) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         android.aidl.tests.INamedCallback _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
-          _data.writeInt(((return_null)?(1):(0)));
+          _data.writeBoolean(return_null);
           boolean _status = mRemote.transact(Stub.TRANSACTION_GetCallback, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
           if (!_status) {
             if (getDefaultImpl() != null) {
@@ -2147,17 +2874,12 @@
       // inefficient to use an IPC to fill it out in practice.
       @Override public void FillOutStructuredParcelable(android.aidl.tests.StructuredParcelable parcel) throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
-          if ((parcel!=null)) {
-            _data.writeInt(1);
-            parcel.writeToParcel(_data, 0);
-          }
-          else {
-            _data.writeInt(0);
-          }
+          _data.writeTypedObject(parcel, 0);
           boolean _status = mRemote.transact(Stub.TRANSACTION_FillOutStructuredParcelable, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
           if (!_status) {
             if (getDefaultImpl() != null) {
@@ -2175,10 +2897,122 @@
           _data.recycle();
         }
       }
+      @Override public void RepeatExtendableParcelable(android.aidl.tests.extension.ExtendableParcelable ep, android.aidl.tests.extension.ExtendableParcelable ep2) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeTypedObject(ep, 0);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_RepeatExtendableParcelable, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              getDefaultImpl().RepeatExtendableParcelable(ep, ep2);
+              return;
+            }
+          }
+          _reply.readException();
+          if ((0!=_reply.readInt())) {
+            ep2.readFromParcel(_reply);
+          }
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
+      @Override public android.aidl.tests.RecursiveList ReverseList(android.aidl.tests.RecursiveList list) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.aidl.tests.RecursiveList _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeTypedObject(list, 0);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_ReverseList, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              return getDefaultImpl().ReverseList(list);
+            }
+          }
+          _reply.readException();
+          _result = _reply.readTypedObject(android.aidl.tests.RecursiveList.CREATOR);
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public android.os.IBinder[] ReverseIBinderArray(android.os.IBinder[] input, android.os.IBinder[] repeated) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.IBinder[] _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeBinderArray(input);
+          if ((repeated==null)) {
+            _data.writeInt(-1);
+          }
+          else {
+            _data.writeInt(repeated.length);
+          }
+          boolean _status = mRemote.transact(Stub.TRANSACTION_ReverseIBinderArray, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              return getDefaultImpl().ReverseIBinderArray(input, repeated);
+            }
+          }
+          _reply.readException();
+          _result = _reply.createBinderArray();
+          _reply.readBinderArray(repeated);
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public android.os.IBinder[] ReverseNullableIBinderArray(android.os.IBinder[] input, android.os.IBinder[] repeated) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.IBinder[] _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeBinderArray(input);
+          if ((repeated==null)) {
+            _data.writeInt(-1);
+          }
+          else {
+            _data.writeInt(repeated.length);
+          }
+          boolean _status = mRemote.transact(Stub.TRANSACTION_ReverseNullableIBinderArray, _data, _reply, android.os.IBinder.FLAG_CLEAR_BUF);
+          if (!_status) {
+            if (getDefaultImpl() != null) {
+              return getDefaultImpl().ReverseNullableIBinderArray(input, repeated);
+            }
+          }
+          _reply.readException();
+          _result = _reply.createBinderArray();
+          _reply.readBinderArray(repeated);
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
       @Override public android.aidl.tests.IOldName GetOldNameInterface() throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         android.aidl.tests.IOldName _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -2199,8 +3033,9 @@
       }
       @Override public android.aidl.tests.INewName GetNewNameInterface() throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         android.aidl.tests.INewName _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -2222,8 +3057,9 @@
       // Retrieve the ICppJavaTests if the server supports it
       @Override public android.os.IBinder GetCppJavaTests() throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         android.os.IBinder _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -2244,8 +3080,9 @@
       }
       @Override public byte getBackendType() throws android.os.RemoteException
       {
-        android.os.Parcel _data = android.os.Parcel.obtain();
-        _data.markSensitive();android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        _data.markSensitive();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
         byte _result;
         try {
           _data.writeInterfaceToken(DESCRIPTOR);
@@ -2293,30 +3130,44 @@
     static final int TRANSACTION_ReverseLongEnum = (android.os.IBinder.FIRST_CALL_TRANSACTION + 24);
     static final int TRANSACTION_GetOtherTestService = (android.os.IBinder.FIRST_CALL_TRANSACTION + 25);
     static final int TRANSACTION_VerifyName = (android.os.IBinder.FIRST_CALL_TRANSACTION + 26);
-    static final int TRANSACTION_ReverseStringList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 27);
-    static final int TRANSACTION_RepeatParcelFileDescriptor = (android.os.IBinder.FIRST_CALL_TRANSACTION + 28);
-    static final int TRANSACTION_ReverseParcelFileDescriptorArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 29);
-    static final int TRANSACTION_ThrowServiceException = (android.os.IBinder.FIRST_CALL_TRANSACTION + 30);
-    static final int TRANSACTION_RepeatNullableIntArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 31);
-    static final int TRANSACTION_RepeatNullableByteEnumArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 32);
-    static final int TRANSACTION_RepeatNullableIntEnumArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 33);
-    static final int TRANSACTION_RepeatNullableLongEnumArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 34);
-    static final int TRANSACTION_RepeatNullableString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 35);
-    static final int TRANSACTION_RepeatNullableStringList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 36);
-    static final int TRANSACTION_RepeatNullableParcelable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 37);
-    static final int TRANSACTION_TakesAnIBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 38);
-    static final int TRANSACTION_TakesANullableIBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 39);
-    static final int TRANSACTION_RepeatUtf8CppString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 40);
-    static final int TRANSACTION_RepeatNullableUtf8CppString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 41);
-    static final int TRANSACTION_ReverseUtf8CppString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 42);
-    static final int TRANSACTION_ReverseNullableUtf8CppString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 43);
-    static final int TRANSACTION_ReverseUtf8CppStringList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 44);
-    static final int TRANSACTION_GetCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 45);
-    static final int TRANSACTION_FillOutStructuredParcelable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 46);
-    static final int TRANSACTION_GetOldNameInterface = (android.os.IBinder.FIRST_CALL_TRANSACTION + 47);
-    static final int TRANSACTION_GetNewNameInterface = (android.os.IBinder.FIRST_CALL_TRANSACTION + 48);
-    static final int TRANSACTION_GetCppJavaTests = (android.os.IBinder.FIRST_CALL_TRANSACTION + 49);
-    static final int TRANSACTION_getBackendType = (android.os.IBinder.FIRST_CALL_TRANSACTION + 50);
+    static final int TRANSACTION_GetInterfaceArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 27);
+    static final int TRANSACTION_VerifyNamesWithInterfaceArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 28);
+    static final int TRANSACTION_GetNullableInterfaceArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 29);
+    static final int TRANSACTION_VerifyNamesWithNullableInterfaceArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 30);
+    static final int TRANSACTION_GetInterfaceList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 31);
+    static final int TRANSACTION_VerifyNamesWithInterfaceList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 32);
+    static final int TRANSACTION_ReverseStringList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 33);
+    static final int TRANSACTION_RepeatParcelFileDescriptor = (android.os.IBinder.FIRST_CALL_TRANSACTION + 34);
+    static final int TRANSACTION_ReverseParcelFileDescriptorArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 35);
+    static final int TRANSACTION_ThrowServiceException = (android.os.IBinder.FIRST_CALL_TRANSACTION + 36);
+    static final int TRANSACTION_RepeatNullableIntArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 37);
+    static final int TRANSACTION_RepeatNullableByteEnumArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 38);
+    static final int TRANSACTION_RepeatNullableIntEnumArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 39);
+    static final int TRANSACTION_RepeatNullableLongEnumArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 40);
+    static final int TRANSACTION_RepeatNullableString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 41);
+    static final int TRANSACTION_RepeatNullableStringList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 42);
+    static final int TRANSACTION_RepeatNullableParcelable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 43);
+    static final int TRANSACTION_RepeatNullableParcelableArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 44);
+    static final int TRANSACTION_RepeatNullableParcelableList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 45);
+    static final int TRANSACTION_TakesAnIBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 46);
+    static final int TRANSACTION_TakesANullableIBinder = (android.os.IBinder.FIRST_CALL_TRANSACTION + 47);
+    static final int TRANSACTION_TakesAnIBinderList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 48);
+    static final int TRANSACTION_TakesANullableIBinderList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 49);
+    static final int TRANSACTION_RepeatUtf8CppString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 50);
+    static final int TRANSACTION_RepeatNullableUtf8CppString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 51);
+    static final int TRANSACTION_ReverseUtf8CppString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 52);
+    static final int TRANSACTION_ReverseNullableUtf8CppString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 53);
+    static final int TRANSACTION_ReverseUtf8CppStringList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 54);
+    static final int TRANSACTION_GetCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 55);
+    static final int TRANSACTION_FillOutStructuredParcelable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 56);
+    static final int TRANSACTION_RepeatExtendableParcelable = (android.os.IBinder.FIRST_CALL_TRANSACTION + 57);
+    static final int TRANSACTION_ReverseList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 58);
+    static final int TRANSACTION_ReverseIBinderArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 59);
+    static final int TRANSACTION_ReverseNullableIBinderArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 60);
+    static final int TRANSACTION_GetOldNameInterface = (android.os.IBinder.FIRST_CALL_TRANSACTION + 61);
+    static final int TRANSACTION_GetNewNameInterface = (android.os.IBinder.FIRST_CALL_TRANSACTION + 62);
+    static final int TRANSACTION_GetCppJavaTests = (android.os.IBinder.FIRST_CALL_TRANSACTION + 63);
+    static final int TRANSACTION_getBackendType = (android.os.IBinder.FIRST_CALL_TRANSACTION + 64);
     public static boolean setDefaultImpl(android.aidl.tests.ITestService impl) {
       // Only one user of this interface can use this function
       // at a time. This is a heuristic to detect if two different
@@ -2336,6 +3187,10 @@
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$tests$ITestService".replace('$', '.');
   // Test that constants are accessible
+  /** extra doc comment */
+  // extra line comment
+  /* extra regular comment */
+  /** const comment */
   public static final int TEST_CONSTANT = 42;
   public static final int TEST_CONSTANT2 = -42;
   public static final int TEST_CONSTANT3 = 42;
@@ -2426,9 +3281,9 @@
   // methods to be added and removed.
   public int UnimplementedMethod(int arg) throws android.os.RemoteException;
   /**
-       * @deprecated to make sure we have something in system/tools/aidl which does a compile check
-       *     of deprecated and make sure this is reflected in goldens
-       */
+   * @deprecated to make sure we have something in system/tools/aidl which does a compile check
+   *     of deprecated and make sure this is reflected in goldens
+   */
   @Deprecated
   public void Deprecated() throws android.os.RemoteException;
   public void TestOneway() throws android.os.RemoteException;
@@ -2459,6 +3314,12 @@
   // Test that clients can send and receive Binders.
   public android.aidl.tests.INamedCallback GetOtherTestService(java.lang.String name) throws android.os.RemoteException;
   public boolean VerifyName(android.aidl.tests.INamedCallback service, java.lang.String name) throws android.os.RemoteException;
+  public android.aidl.tests.INamedCallback[] GetInterfaceArray(java.lang.String[] names) throws android.os.RemoteException;
+  public boolean VerifyNamesWithInterfaceArray(android.aidl.tests.INamedCallback[] services, java.lang.String[] names) throws android.os.RemoteException;
+  public android.aidl.tests.INamedCallback[] GetNullableInterfaceArray(java.lang.String[] names) throws android.os.RemoteException;
+  public boolean VerifyNamesWithNullableInterfaceArray(android.aidl.tests.INamedCallback[] services, java.lang.String[] names) throws android.os.RemoteException;
+  public java.util.List<android.aidl.tests.INamedCallback> GetInterfaceList(java.lang.String[] names) throws android.os.RemoteException;
+  public boolean VerifyNamesWithInterfaceList(java.util.List<android.aidl.tests.INamedCallback> services, java.lang.String[] names) throws android.os.RemoteException;
   // Test that List<T> types work correctly.
   public java.util.List<java.lang.String> ReverseStringList(java.util.List<java.lang.String> input, java.util.List<java.lang.String> repeated) throws android.os.RemoteException;
   public android.os.ParcelFileDescriptor RepeatParcelFileDescriptor(android.os.ParcelFileDescriptor read) throws android.os.RemoteException;
@@ -2472,22 +3333,237 @@
   public long[] RepeatNullableLongEnumArray(long[] input) throws android.os.RemoteException;
   public java.lang.String RepeatNullableString(java.lang.String input) throws android.os.RemoteException;
   public java.util.List<java.lang.String> RepeatNullableStringList(java.util.List<java.lang.String> input) throws android.os.RemoteException;
-  public android.aidl.tests.StructuredParcelable RepeatNullableParcelable(android.aidl.tests.StructuredParcelable input) throws android.os.RemoteException;
+  public android.aidl.tests.ITestService.Empty RepeatNullableParcelable(android.aidl.tests.ITestService.Empty input) throws android.os.RemoteException;
+  public android.aidl.tests.ITestService.Empty[] RepeatNullableParcelableArray(android.aidl.tests.ITestService.Empty[] input) throws android.os.RemoteException;
+  public java.util.List<android.aidl.tests.ITestService.Empty> RepeatNullableParcelableList(java.util.List<android.aidl.tests.ITestService.Empty> input) throws android.os.RemoteException;
   public void TakesAnIBinder(android.os.IBinder input) throws android.os.RemoteException;
   public void TakesANullableIBinder(android.os.IBinder input) throws android.os.RemoteException;
+  public void TakesAnIBinderList(java.util.List<android.os.IBinder> input) throws android.os.RemoteException;
+  public void TakesANullableIBinderList(java.util.List<android.os.IBinder> input) throws android.os.RemoteException;
   // Test utf8 decoding from utf16 wire format
   public java.lang.String RepeatUtf8CppString(java.lang.String token) throws android.os.RemoteException;
   public java.lang.String RepeatNullableUtf8CppString(java.lang.String token) throws android.os.RemoteException;
   public java.lang.String[] ReverseUtf8CppString(java.lang.String[] input, java.lang.String[] repeated) throws android.os.RemoteException;
   public java.lang.String[] ReverseNullableUtf8CppString(java.lang.String[] input, java.lang.String[] repeated) throws android.os.RemoteException;
   public java.util.List<java.lang.String> ReverseUtf8CppStringList(java.util.List<java.lang.String> input, java.util.List<java.lang.String> repeated) throws android.os.RemoteException;
+  /** comment before annotation */
   public android.aidl.tests.INamedCallback GetCallback(boolean return_null) throws android.os.RemoteException;
   // Since this paracelable has clearly defined default values, it would be
   // inefficient to use an IPC to fill it out in practice.
   public void FillOutStructuredParcelable(android.aidl.tests.StructuredParcelable parcel) throws android.os.RemoteException;
+  public void RepeatExtendableParcelable(android.aidl.tests.extension.ExtendableParcelable ep, android.aidl.tests.extension.ExtendableParcelable ep2) throws android.os.RemoteException;
+  public android.aidl.tests.RecursiveList ReverseList(android.aidl.tests.RecursiveList list) throws android.os.RemoteException;
+  public android.os.IBinder[] ReverseIBinderArray(android.os.IBinder[] input, android.os.IBinder[] repeated) throws android.os.RemoteException;
+  public android.os.IBinder[] ReverseNullableIBinderArray(android.os.IBinder[] input, android.os.IBinder[] repeated) throws android.os.RemoteException;
   public android.aidl.tests.IOldName GetOldNameInterface() throws android.os.RemoteException;
   public android.aidl.tests.INewName GetNewNameInterface() throws android.os.RemoteException;
   // Retrieve the ICppJavaTests if the server supports it
   public android.os.IBinder GetCppJavaTests() throws android.os.RemoteException;
   public byte getBackendType() throws android.os.RemoteException;
+  // Small empty parcelable for nullability check
+  public static class Empty implements android.os.Parcelable
+  {
+    public static final android.os.Parcelable.Creator<Empty> CREATOR = new android.os.Parcelable.Creator<Empty>() {
+      @Override
+      public Empty createFromParcel(android.os.Parcel _aidl_source) {
+        Empty _aidl_out = new Empty();
+        _aidl_out.readFromParcel(_aidl_source);
+        return _aidl_out;
+      }
+      @Override
+      public Empty[] newArray(int _aidl_size) {
+        return new Empty[_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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+      } 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 boolean equals(Object other) {
+      if (this == other) return true;
+      if (other == null) return false;
+      if (!(other instanceof Empty)) return false;
+      Empty that = (Empty)other;
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return java.util.Arrays.deepHashCode(java.util.Arrays.asList().toArray());
+    }
+    @Override
+    public int describeContents() {
+      int _mask = 0;
+      return _mask;
+    }
+  }
+  public static class CompilerChecks implements android.os.Parcelable
+  {
+    // IBinder
+    public android.os.IBinder binder;
+    public android.os.IBinder nullable_binder;
+    public android.os.IBinder[] binder_array;
+    public android.os.IBinder[] nullable_binder_array;
+    public java.util.List<android.os.IBinder> binder_list;
+    public java.util.List<android.os.IBinder> nullable_binder_list;
+    // ParcelFileDescriptor
+    public android.os.ParcelFileDescriptor pfd;
+    public android.os.ParcelFileDescriptor nullable_pfd;
+    public android.os.ParcelFileDescriptor[] pfd_array;
+    public android.os.ParcelFileDescriptor[] nullable_pfd_array;
+    public java.util.List<android.os.ParcelFileDescriptor> pfd_list;
+    public java.util.List<android.os.ParcelFileDescriptor> nullable_pfd_list;
+    // parcelable
+    public android.aidl.tests.ITestService.Empty parcel;
+    public android.aidl.tests.ITestService.Empty nullable_parcel;
+    public android.aidl.tests.ITestService.Empty[] parcel_array;
+    public android.aidl.tests.ITestService.Empty[] nullable_parcel_array;
+    public java.util.List<android.aidl.tests.ITestService.Empty> parcel_list;
+    public java.util.List<android.aidl.tests.ITestService.Empty> nullable_parcel_list;
+    public static final android.os.Parcelable.Creator<CompilerChecks> CREATOR = new android.os.Parcelable.Creator<CompilerChecks>() {
+      @Override
+      public CompilerChecks createFromParcel(android.os.Parcel _aidl_source) {
+        CompilerChecks _aidl_out = new CompilerChecks();
+        _aidl_out.readFromParcel(_aidl_source);
+        return _aidl_out;
+      }
+      @Override
+      public CompilerChecks[] newArray(int _aidl_size) {
+        return new CompilerChecks[_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(binder);
+      _aidl_parcel.writeStrongBinder(nullable_binder);
+      _aidl_parcel.writeBinderArray(binder_array);
+      _aidl_parcel.writeBinderArray(nullable_binder_array);
+      _aidl_parcel.writeBinderList(binder_list);
+      _aidl_parcel.writeBinderList(nullable_binder_list);
+      _aidl_parcel.writeTypedObject(pfd, 0);
+      _aidl_parcel.writeTypedObject(nullable_pfd, 0);
+      _aidl_parcel.writeTypedArray(pfd_array, 0);
+      _aidl_parcel.writeTypedArray(nullable_pfd_array, 0);
+      _aidl_parcel.writeTypedList(pfd_list);
+      _aidl_parcel.writeTypedList(nullable_pfd_list);
+      _aidl_parcel.writeTypedObject(parcel, 0);
+      _aidl_parcel.writeTypedObject(nullable_parcel, 0);
+      _aidl_parcel.writeTypedArray(parcel_array, 0);
+      _aidl_parcel.writeTypedArray(nullable_parcel_array, 0);
+      _aidl_parcel.writeTypedList(parcel_list);
+      _aidl_parcel.writeTypedList(nullable_parcel_list);
+      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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        binder = _aidl_parcel.readStrongBinder();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        nullable_binder = _aidl_parcel.readStrongBinder();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        binder_array = _aidl_parcel.createBinderArray();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        nullable_binder_array = _aidl_parcel.createBinderArray();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        binder_list = _aidl_parcel.createBinderArrayList();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        nullable_binder_list = _aidl_parcel.createBinderArrayList();
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        pfd = _aidl_parcel.readTypedObject(android.os.ParcelFileDescriptor.CREATOR);
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        nullable_pfd = _aidl_parcel.readTypedObject(android.os.ParcelFileDescriptor.CREATOR);
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        pfd_array = _aidl_parcel.createTypedArray(android.os.ParcelFileDescriptor.CREATOR);
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        nullable_pfd_array = _aidl_parcel.createTypedArray(android.os.ParcelFileDescriptor.CREATOR);
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        pfd_list = _aidl_parcel.createTypedArrayList(android.os.ParcelFileDescriptor.CREATOR);
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        nullable_pfd_list = _aidl_parcel.createTypedArrayList(android.os.ParcelFileDescriptor.CREATOR);
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        parcel = _aidl_parcel.readTypedObject(android.aidl.tests.ITestService.Empty.CREATOR);
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        nullable_parcel = _aidl_parcel.readTypedObject(android.aidl.tests.ITestService.Empty.CREATOR);
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        parcel_array = _aidl_parcel.createTypedArray(android.aidl.tests.ITestService.Empty.CREATOR);
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        nullable_parcel_array = _aidl_parcel.createTypedArray(android.aidl.tests.ITestService.Empty.CREATOR);
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        parcel_list = _aidl_parcel.createTypedArrayList(android.aidl.tests.ITestService.Empty.CREATOR);
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        nullable_parcel_list = _aidl_parcel.createTypedArrayList(android.aidl.tests.ITestService.Empty.CREATOR);
+      } 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;
+      _mask |= describeContents(pfd);
+      _mask |= describeContents(nullable_pfd);
+      _mask |= describeContents(pfd_array);
+      _mask |= describeContents(nullable_pfd_array);
+      _mask |= describeContents(pfd_list);
+      _mask |= describeContents(nullable_pfd_list);
+      _mask |= describeContents(parcel);
+      _mask |= describeContents(nullable_parcel);
+      _mask |= describeContents(parcel_array);
+      _mask |= describeContents(nullable_parcel_array);
+      _mask |= describeContents(parcel_list);
+      _mask |= describeContents(nullable_parcel_list);
+      return _mask;
+    }
+    private int describeContents(Object _v) {
+      if (_v == null) return 0;
+      if (_v instanceof Object[]) {
+        int _mask = 0;
+        for (Object o : (Object[]) _v) {
+          _mask |= describeContents(o);
+        }
+        return _mask;
+      }
+      if (_v instanceof java.util.Collection) {
+        int _mask = 0;
+        for (Object o : (java.util.Collection) _v) {
+          _mask |= describeContents(o);
+        }
+        return _mask;
+      }
+      if (_v instanceof android.os.Parcelable) {
+        return ((android.os.Parcelable) _v).describeContents();
+      }
+      return 0;
+    }
+  }
 }
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ITestService.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ITestService.java.d
index 1dc525b..f82b264 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ITestService.java.d
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ITestService.java.d
@@ -7,4 +7,8 @@
   system/tools/aidl/tests/android/aidl/tests/IOldName.aidl \
   system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
   system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl \
-  system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl
+  system/tools/aidl/tests/android/aidl/tests/RecursiveList.aidl \
+  system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl \
+  system/tools/aidl/tests/android/aidl/tests/extension/ExtendableParcelable.aidl \
+  system/tools/aidl/tests/android/aidl/tests/ConstantExpressionEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/Union.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ListOfInterfaces.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ListOfInterfaces.java
new file mode 100644
index 0000000..fafba0c
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ListOfInterfaces.java
@@ -0,0 +1,549 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests;
+public class ListOfInterfaces implements android.os.Parcelable
+{
+  public static final android.os.Parcelable.Creator<ListOfInterfaces> CREATOR = new android.os.Parcelable.Creator<ListOfInterfaces>() {
+    @Override
+    public ListOfInterfaces createFromParcel(android.os.Parcel _aidl_source) {
+      ListOfInterfaces _aidl_out = new ListOfInterfaces();
+      _aidl_out.readFromParcel(_aidl_source);
+      return _aidl_out;
+    }
+    @Override
+    public ListOfInterfaces[] newArray(int _aidl_size) {
+      return new ListOfInterfaces[_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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+    } 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.ListOfInterfaces.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.ListOfInterfaces.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.ListOfInterfaces.IEmptyInterface interface,
+       * generating a proxy if needed.
+       */
+      public static android.aidl.tests.ListOfInterfaces.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.ListOfInterfaces.IEmptyInterface))) {
+          return ((android.aidl.tests.ListOfInterfaces.IEmptyInterface)iin);
+        }
+        return new android.aidl.tests.ListOfInterfaces.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.ListOfInterfaces.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 final java.lang.String DESCRIPTOR = "android$aidl$tests$ListOfInterfaces$IEmptyInterface".replace('$', '.');
+  }
+  public interface IMyInterface extends android.os.IInterface
+  {
+    /** Default implementation for IMyInterface. */
+    public static class Default implements android.aidl.tests.ListOfInterfaces.IMyInterface
+    {
+      @Override public java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> methodWithInterfaces(android.aidl.tests.ListOfInterfaces.IEmptyInterface iface, android.aidl.tests.ListOfInterfaces.IEmptyInterface nullable_iface, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list_in, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list_out, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list_inout, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list_in, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list_out, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list_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.ListOfInterfaces.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.ListOfInterfaces.IMyInterface interface,
+       * generating a proxy if needed.
+       */
+      public static android.aidl.tests.ListOfInterfaces.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.ListOfInterfaces.IMyInterface))) {
+          return ((android.aidl.tests.ListOfInterfaces.IMyInterface)iin);
+        }
+        return new android.aidl.tests.ListOfInterfaces.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.ListOfInterfaces.IEmptyInterface _arg0;
+            _arg0 = android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub.asInterface(data.readStrongBinder());
+            android.aidl.tests.ListOfInterfaces.IEmptyInterface _arg1;
+            _arg1 = android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub.asInterface(data.readStrongBinder());
+            java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _arg2;
+            _arg2 = data.createInterfaceArrayList(android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
+            java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _arg3;
+            _arg3 = new java.util.ArrayList<android.aidl.tests.ListOfInterfaces.IEmptyInterface>();
+            java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _arg4;
+            _arg4 = data.createInterfaceArrayList(android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
+            java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _arg5;
+            _arg5 = data.createInterfaceArrayList(android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
+            java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _arg6;
+            _arg6 = new java.util.ArrayList<android.aidl.tests.ListOfInterfaces.IEmptyInterface>();
+            java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _arg7;
+            _arg7 = data.createInterfaceArrayList(android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
+            data.enforceNoDataAvail();
+            java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _result = this.methodWithInterfaces(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7);
+            reply.writeNoException();
+            reply.writeInterfaceList(_result);
+            reply.writeInterfaceList(_arg3);
+            reply.writeInterfaceList(_arg4);
+            reply.writeInterfaceList(_arg6);
+            reply.writeInterfaceList(_arg7);
+            break;
+          }
+          default:
+          {
+            return super.onTransact(code, data, reply, flags);
+          }
+        }
+        return true;
+      }
+      private static class Proxy implements android.aidl.tests.ListOfInterfaces.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 java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> methodWithInterfaces(android.aidl.tests.ListOfInterfaces.IEmptyInterface iface, android.aidl.tests.ListOfInterfaces.IEmptyInterface nullable_iface, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list_in, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list_out, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list_inout, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list_in, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list_out, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list_inout) throws android.os.RemoteException
+        {
+          android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+          android.os.Parcel _reply = android.os.Parcel.obtain();
+          java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _result;
+          try {
+            _data.writeInterfaceToken(DESCRIPTOR);
+            _data.writeStrongInterface(iface);
+            _data.writeStrongInterface(nullable_iface);
+            _data.writeInterfaceList(iface_list_in);
+            _data.writeInterfaceList(iface_list_inout);
+            _data.writeInterfaceList(nullable_iface_list_in);
+            _data.writeInterfaceList(nullable_iface_list_inout);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_methodWithInterfaces, _data, _reply, 0);
+            _reply.readException();
+            _result = _reply.createInterfaceArrayList(android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
+            _reply.readInterfaceList(iface_list_out, android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
+            _reply.readInterfaceList(iface_list_inout, android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
+            _reply.readInterfaceList(nullable_iface_list_out, android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
+            _reply.readInterfaceList(nullable_iface_list_inout, android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
+          }
+          finally {
+            _reply.recycle();
+            _data.recycle();
+          }
+          return _result;
+        }
+      }
+      static final int TRANSACTION_methodWithInterfaces = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+    }
+    public static final java.lang.String DESCRIPTOR = "android$aidl$tests$ListOfInterfaces$IMyInterface".replace('$', '.');
+    public java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> methodWithInterfaces(android.aidl.tests.ListOfInterfaces.IEmptyInterface iface, android.aidl.tests.ListOfInterfaces.IEmptyInterface nullable_iface, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list_in, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list_out, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list_inout, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list_in, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list_out, java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list_inout) throws android.os.RemoteException;
+  }
+  public static class MyParcelable implements android.os.Parcelable
+  {
+    public android.aidl.tests.ListOfInterfaces.IEmptyInterface iface;
+    public android.aidl.tests.ListOfInterfaces.IEmptyInterface nullable_iface;
+    public java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list;
+    public java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list;
+    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.writeStrongInterface(iface);
+      _aidl_parcel.writeStrongInterface(nullable_iface);
+      _aidl_parcel.writeInterfaceList(iface_list);
+      _aidl_parcel.writeInterfaceList(nullable_iface_list);
+      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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        iface = android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub.asInterface(_aidl_parcel.readStrongBinder());
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        nullable_iface = android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub.asInterface(_aidl_parcel.readStrongBinder());
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        iface_list = _aidl_parcel.createInterfaceArrayList(android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        nullable_iface_list = _aidl_parcel.createInterfaceArrayList(android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
+      } 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_list: " + (java.util.Objects.toString(iface_list)));
+      _aidl_sj.add("nullable_iface_list: " + (java.util.Objects.toString(nullable_iface_list)));
+      return "android.aidl.tests.ListOfInterfaces.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_list, that.iface_list)) return false;
+      if (!java.util.Objects.deepEquals(nullable_iface_list, that.nullable_iface_list)) return false;
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return java.util.Arrays.deepHashCode(java.util.Arrays.asList(iface, nullable_iface, iface_list, nullable_iface_list).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.ListOfInterfaces.IEmptyInterface iface;
+    public final static int nullable_iface = 1;  // android.aidl.tests.ListOfInterfaces.IEmptyInterface nullable_iface;
+    public final static int iface_list = 2;  // List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list;
+    public final static int nullable_iface_list = 3;  // List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list;
+
+    private int _tag;
+    private Object _value;
+
+    public MyUnion() {
+      android.aidl.tests.ListOfInterfaces.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.ListOfInterfaces.IEmptyInterface iface;
+
+    public static MyUnion iface(android.aidl.tests.ListOfInterfaces.IEmptyInterface _value) {
+      return new MyUnion(iface, _value);
+    }
+
+    public android.aidl.tests.ListOfInterfaces.IEmptyInterface getIface() {
+      _assertTag(iface);
+      return (android.aidl.tests.ListOfInterfaces.IEmptyInterface) _value;
+    }
+
+    public void setIface(android.aidl.tests.ListOfInterfaces.IEmptyInterface _value) {
+      _set(iface, _value);
+    }
+
+    // android.aidl.tests.ListOfInterfaces.IEmptyInterface nullable_iface;
+
+    public static MyUnion nullable_iface(android.aidl.tests.ListOfInterfaces.IEmptyInterface _value) {
+      return new MyUnion(nullable_iface, _value);
+    }
+
+    public android.aidl.tests.ListOfInterfaces.IEmptyInterface getNullable_iface() {
+      _assertTag(nullable_iface);
+      return (android.aidl.tests.ListOfInterfaces.IEmptyInterface) _value;
+    }
+
+    public void setNullable_iface(android.aidl.tests.ListOfInterfaces.IEmptyInterface _value) {
+      _set(nullable_iface, _value);
+    }
+
+    // List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list;
+
+    public static MyUnion iface_list(java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _value) {
+      return new MyUnion(iface_list, _value);
+    }
+
+    @SuppressWarnings("unchecked")
+    public java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> getIface_list() {
+      _assertTag(iface_list);
+      return (java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface>) _value;
+    }
+
+    public void setIface_list(java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _value) {
+      _set(iface_list, _value);
+    }
+
+    // List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list;
+
+    public static MyUnion nullable_iface_list(java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _value) {
+      return new MyUnion(nullable_iface_list, _value);
+    }
+
+    @SuppressWarnings("unchecked")
+    public java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> getNullable_iface_list() {
+      _assertTag(nullable_iface_list);
+      return (java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface>) _value;
+    }
+
+    public void setNullable_iface_list(java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _value) {
+      _set(nullable_iface_list, _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.writeStrongInterface(getIface());
+        break;
+      case nullable_iface:
+        _aidl_parcel.writeStrongInterface(getNullable_iface());
+        break;
+      case iface_list:
+        _aidl_parcel.writeInterfaceList(getIface_list());
+        break;
+      case nullable_iface_list:
+        _aidl_parcel.writeInterfaceList(getNullable_iface_list());
+        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.ListOfInterfaces.IEmptyInterface _aidl_value;
+        _aidl_value = android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub.asInterface(_aidl_parcel.readStrongBinder());
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case nullable_iface: {
+        android.aidl.tests.ListOfInterfaces.IEmptyInterface _aidl_value;
+        _aidl_value = android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub.asInterface(_aidl_parcel.readStrongBinder());
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case iface_list: {
+        java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _aidl_value;
+        _aidl_value = _aidl_parcel.createInterfaceArrayList(android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
+        _set(_aidl_tag, _aidl_value);
+        return; }
+      case nullable_iface_list: {
+        java.util.List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> _aidl_value;
+        _aidl_value = _aidl_parcel.createInterfaceArrayList(android.aidl.tests.ListOfInterfaces.IEmptyInterface.Stub::asInterface);
+        _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.ListOfInterfaces.MyUnion.iface(" + (java.util.Objects.toString(getIface())) + ")";
+      case nullable_iface: return "android.aidl.tests.ListOfInterfaces.MyUnion.nullable_iface(" + (java.util.Objects.toString(getNullable_iface())) + ")";
+      case iface_list: return "android.aidl.tests.ListOfInterfaces.MyUnion.iface_list(" + (java.util.Objects.toString(getIface_list())) + ")";
+      case nullable_iface_list: return "android.aidl.tests.ListOfInterfaces.MyUnion.nullable_iface_list(" + (java.util.Objects.toString(getNullable_iface_list())) + ")";
+      }
+      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_list: return "iface_list";
+      case nullable_iface_list: return "nullable_iface_list";
+      }
+      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/ListOfInterfaces.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ListOfInterfaces.java.d
new file mode 100644
index 0000000..3387036
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ListOfInterfaces.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/ListOfInterfaces.java : \
+  system/tools/aidl/tests/android/aidl/tests/ListOfInterfaces.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/OtherParcelableForToString.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/OtherParcelableForToString.java
index a2824ee..46a11e7 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/OtherParcelableForToString.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/OtherParcelableForToString.java
@@ -32,7 +32,7 @@
     int _aidl_start_pos = _aidl_parcel.dataPosition();
     int _aidl_parcelable_size = _aidl_parcel.readInt();
     try {
-      if (_aidl_parcelable_size < 0) return;
+      if (_aidl_parcelable_size < 4) throw new android.os.BadParcelableException("Parcelable too small");;
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       field = _aidl_parcel.readString();
     } finally {
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ParcelableForToString.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ParcelableForToString.java
index 9c1bb13..c588be1 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ParcelableForToString.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ParcelableForToString.java
@@ -53,37 +53,19 @@
     _aidl_parcel.writeFloatArray(floatArray);
     _aidl_parcel.writeByte(byteValue);
     _aidl_parcel.writeByteArray(byteArray);
-    _aidl_parcel.writeInt(((booleanValue)?(1):(0)));
+    _aidl_parcel.writeBoolean(booleanValue);
     _aidl_parcel.writeBooleanArray(booleanArray);
     _aidl_parcel.writeString(stringValue);
     _aidl_parcel.writeStringArray(stringArray);
     _aidl_parcel.writeStringList(stringList);
-    if ((parcelableValue!=null)) {
-      _aidl_parcel.writeInt(1);
-      parcelableValue.writeToParcel(_aidl_parcel, 0);
-    }
-    else {
-      _aidl_parcel.writeInt(0);
-    }
+    _aidl_parcel.writeTypedObject(parcelableValue, 0);
     _aidl_parcel.writeTypedArray(parcelableArray, 0);
     _aidl_parcel.writeInt(enumValue);
     _aidl_parcel.writeIntArray(enumArray);
     _aidl_parcel.writeStringArray(nullArray);
     _aidl_parcel.writeStringList(nullList);
-    if ((parcelableGeneric!=null)) {
-      _aidl_parcel.writeInt(1);
-      parcelableGeneric.writeToParcel(_aidl_parcel, 0);
-    }
-    else {
-      _aidl_parcel.writeInt(0);
-    }
-    if ((unionValue!=null)) {
-      _aidl_parcel.writeInt(1);
-      unionValue.writeToParcel(_aidl_parcel, 0);
-    }
-    else {
-      _aidl_parcel.writeInt(0);
-    }
+    _aidl_parcel.writeTypedObject(parcelableGeneric, 0);
+    _aidl_parcel.writeTypedObject(unionValue, 0);
     int _aidl_end_pos = _aidl_parcel.dataPosition();
     _aidl_parcel.setDataPosition(_aidl_start_pos);
     _aidl_parcel.writeInt(_aidl_end_pos - _aidl_start_pos);
@@ -94,7 +76,7 @@
     int _aidl_start_pos = _aidl_parcel.dataPosition();
     int _aidl_parcelable_size = _aidl_parcel.readInt();
     try {
-      if (_aidl_parcelable_size < 0) return;
+      if (_aidl_parcelable_size < 4) throw new android.os.BadParcelableException("Parcelable too small");;
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       intValue = _aidl_parcel.readInt();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
@@ -116,7 +98,7 @@
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       byteArray = _aidl_parcel.createByteArray();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
-      booleanValue = (0!=_aidl_parcel.readInt());
+      booleanValue = _aidl_parcel.readBoolean();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       booleanArray = _aidl_parcel.createBooleanArray();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
@@ -126,12 +108,7 @@
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       stringList = _aidl_parcel.createStringArrayList();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
-      if ((0!=_aidl_parcel.readInt())) {
-        parcelableValue = android.aidl.tests.OtherParcelableForToString.CREATOR.createFromParcel(_aidl_parcel);
-      }
-      else {
-        parcelableValue = null;
-      }
+      parcelableValue = _aidl_parcel.readTypedObject(android.aidl.tests.OtherParcelableForToString.CREATOR);
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       parcelableArray = _aidl_parcel.createTypedArray(android.aidl.tests.OtherParcelableForToString.CREATOR);
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
@@ -143,19 +120,9 @@
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       nullList = _aidl_parcel.createStringArrayList();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
-      if ((0!=_aidl_parcel.readInt())) {
-        parcelableGeneric = android.aidl.tests.GenericStructuredParcelable.CREATOR.createFromParcel(_aidl_parcel);
-      }
-      else {
-        parcelableGeneric = null;
-      }
+      parcelableGeneric = _aidl_parcel.readTypedObject(android.aidl.tests.GenericStructuredParcelable.CREATOR);
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
-      if ((0!=_aidl_parcel.readInt())) {
-        unionValue = android.aidl.tests.Union.CREATOR.createFromParcel(_aidl_parcel);
-      }
-      else {
-        unionValue = null;
-      }
+      unionValue = _aidl_parcel.readTypedObject(android.aidl.tests.Union.CREATOR);
     } finally {
       if (_aidl_start_pos > (Integer.MAX_VALUE - _aidl_parcelable_size)) {
         throw new android.os.BadParcelableException("Overflow in the size of parcelable");
@@ -202,8 +169,7 @@
   }
   private int describeContents(Object _v) {
     if (_v == null) return 0;
-    Class<?> _clazz = _v.getClass();
-    if (_clazz.isArray() && _clazz.getComponentType() == Object.class) {
+    if (_v instanceof Object[]) {
       int _mask = 0;
       for (Object o : (Object[]) _v) {
         _mask |= describeContents(o);
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ParcelableForToString.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ParcelableForToString.java.d
index 9a19eb6..013e62c 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ParcelableForToString.java.d
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/ParcelableForToString.java.d
@@ -4,4 +4,7 @@
   system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
   system/tools/aidl/tests/android/aidl/tests/OtherParcelableForToString.aidl \
   system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl \
-  system/tools/aidl/tests/android/aidl/tests/Union.aidl
+  system/tools/aidl/tests/android/aidl/tests/Union.aidl \
+  system/tools/aidl/tests/android/aidl/tests/ByteEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/ConstantExpressionEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/RecursiveList.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/RecursiveList.java
new file mode 100644
index 0000000..a0c6bb6
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/RecursiveList.java
@@ -0,0 +1,62 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests;
+public class RecursiveList implements android.os.Parcelable
+{
+  public int value = 0;
+  public android.aidl.tests.RecursiveList next;
+  public static final android.os.Parcelable.Creator<RecursiveList> CREATOR = new android.os.Parcelable.Creator<RecursiveList>() {
+    @Override
+    public RecursiveList createFromParcel(android.os.Parcel _aidl_source) {
+      RecursiveList _aidl_out = new RecursiveList();
+      _aidl_out.readFromParcel(_aidl_source);
+      return _aidl_out;
+    }
+    @Override
+    public RecursiveList[] newArray(int _aidl_size) {
+      return new RecursiveList[_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.writeInt(value);
+    _aidl_parcel.writeTypedObject(next, 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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      value = _aidl_parcel.readInt();
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      next = _aidl_parcel.readTypedObject(android.aidl.tests.RecursiveList.CREATOR);
+    } 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;
+    _mask |= describeContents(next);
+    return _mask;
+  }
+  private int describeContents(Object _v) {
+    if (_v == null) return 0;
+    if (_v instanceof android.os.Parcelable) {
+      return ((android.os.Parcelable) _v).describeContents();
+    }
+    return 0;
+  }
+}
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/RecursiveList.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/RecursiveList.java.d
new file mode 100644
index 0000000..826c4ea
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/RecursiveList.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/RecursiveList.java : \
+  system/tools/aidl/tests/android/aidl/tests/RecursiveList.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/StructuredParcelable.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/StructuredParcelable.java
index 806a634..b90fe2c 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/StructuredParcelable.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/StructuredParcelable.java
@@ -39,7 +39,9 @@
   public long int64_max = 9223372036854775807L;
   public int hexInt32_neg_1 = -1;
   public android.os.IBinder ibinder;
+  public android.aidl.tests.StructuredParcelable.Empty empty;
   // Constant expressions that evaluate to 1
+  public byte[] int8_1 = {1, 1, 1, 1, 1};
   public int[] int32_1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
   public long[] int64_1 = {1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L};
   public int hexInt32_pos_1 = 1;
@@ -90,13 +92,13 @@
     _aidl_parcel.writeByte(byteDefaultsToFour);
     _aidl_parcel.writeInt(intDefaultsToFive);
     _aidl_parcel.writeLong(longDefaultsToNegativeSeven);
-    _aidl_parcel.writeInt(((booleanDefaultsToTrue)?(1):(0)));
+    _aidl_parcel.writeBoolean(booleanDefaultsToTrue);
     _aidl_parcel.writeInt(((int)charDefaultsToC));
     _aidl_parcel.writeFloat(floatDefaultsToPi);
     _aidl_parcel.writeDouble(doubleWithDefault);
     _aidl_parcel.writeIntArray(arrayDefaultsTo123);
     _aidl_parcel.writeIntArray(arrayDefaultsToEmpty);
-    _aidl_parcel.writeInt(((boolDefault)?(1):(0)));
+    _aidl_parcel.writeBoolean(boolDefault);
     _aidl_parcel.writeByte(byteDefault);
     _aidl_parcel.writeInt(intDefault);
     _aidl_parcel.writeLong(longDefault);
@@ -110,6 +112,8 @@
     _aidl_parcel.writeLong(int64_max);
     _aidl_parcel.writeInt(hexInt32_neg_1);
     _aidl_parcel.writeStrongBinder(ibinder);
+    _aidl_parcel.writeTypedObject(empty, 0);
+    _aidl_parcel.writeByteArray(int8_1);
     _aidl_parcel.writeIntArray(int32_1);
     _aidl_parcel.writeLongArray(int64_1);
     _aidl_parcel.writeInt(hexInt32_pos_1);
@@ -127,20 +131,8 @@
     _aidl_parcel.writeString(addString1);
     _aidl_parcel.writeString(addString2);
     _aidl_parcel.writeInt(shouldSetBit0AndBit2);
-    if ((u!=null)) {
-      _aidl_parcel.writeInt(1);
-      u.writeToParcel(_aidl_parcel, 0);
-    }
-    else {
-      _aidl_parcel.writeInt(0);
-    }
-    if ((shouldBeConstS1!=null)) {
-      _aidl_parcel.writeInt(1);
-      shouldBeConstS1.writeToParcel(_aidl_parcel, 0);
-    }
-    else {
-      _aidl_parcel.writeInt(0);
-    }
+    _aidl_parcel.writeTypedObject(u, 0);
+    _aidl_parcel.writeTypedObject(shouldBeConstS1, 0);
     _aidl_parcel.writeInt(defaultWithFoo);
     int _aidl_end_pos = _aidl_parcel.dataPosition();
     _aidl_parcel.setDataPosition(_aidl_start_pos);
@@ -152,7 +144,7 @@
     int _aidl_start_pos = _aidl_parcel.dataPosition();
     int _aidl_parcelable_size = _aidl_parcel.readInt();
     try {
-      if (_aidl_parcelable_size < 0) return;
+      if (_aidl_parcelable_size < 4) throw new android.os.BadParcelableException("Parcelable too small");;
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       shouldContainThreeFs = _aidl_parcel.createIntArray();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
@@ -180,7 +172,7 @@
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       longDefaultsToNegativeSeven = _aidl_parcel.readLong();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
-      booleanDefaultsToTrue = (0!=_aidl_parcel.readInt());
+      booleanDefaultsToTrue = _aidl_parcel.readBoolean();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       charDefaultsToC = (char)_aidl_parcel.readInt();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
@@ -192,7 +184,7 @@
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       arrayDefaultsToEmpty = _aidl_parcel.createIntArray();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
-      boolDefault = (0!=_aidl_parcel.readInt());
+      boolDefault = _aidl_parcel.readBoolean();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       byteDefault = _aidl_parcel.readByte();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
@@ -220,6 +212,10 @@
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       ibinder = _aidl_parcel.readStrongBinder();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      empty = _aidl_parcel.readTypedObject(android.aidl.tests.StructuredParcelable.Empty.CREATOR);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      int8_1 = _aidl_parcel.createByteArray();
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       int32_1 = _aidl_parcel.createIntArray();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       int64_1 = _aidl_parcel.createLongArray();
@@ -254,19 +250,9 @@
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       shouldSetBit0AndBit2 = _aidl_parcel.readInt();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
-      if ((0!=_aidl_parcel.readInt())) {
-        u = android.aidl.tests.Union.CREATOR.createFromParcel(_aidl_parcel);
-      }
-      else {
-        u = null;
-      }
+      u = _aidl_parcel.readTypedObject(android.aidl.tests.Union.CREATOR);
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
-      if ((0!=_aidl_parcel.readInt())) {
-        shouldBeConstS1 = android.aidl.tests.Union.CREATOR.createFromParcel(_aidl_parcel);
-      }
-      else {
-        shouldBeConstS1 = null;
-      }
+      shouldBeConstS1 = _aidl_parcel.readTypedObject(android.aidl.tests.Union.CREATOR);
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       defaultWithFoo = _aidl_parcel.readInt();
     } finally {
@@ -315,6 +301,8 @@
     _aidl_sj.add("int64_max: " + (int64_max));
     _aidl_sj.add("hexInt32_neg_1: " + (hexInt32_neg_1));
     _aidl_sj.add("ibinder: " + (java.util.Objects.toString(ibinder)));
+    _aidl_sj.add("empty: " + (java.util.Objects.toString(empty)));
+    _aidl_sj.add("int8_1: " + (java.util.Arrays.toString(int8_1)));
     _aidl_sj.add("int32_1: " + (java.util.Arrays.toString(int32_1)));
     _aidl_sj.add("int64_1: " + (java.util.Arrays.toString(int64_1)));
     _aidl_sj.add("hexInt32_pos_1: " + (hexInt32_pos_1));
@@ -376,6 +364,8 @@
     if (!java.util.Objects.deepEquals(int64_max, that.int64_max)) return false;
     if (!java.util.Objects.deepEquals(hexInt32_neg_1, that.hexInt32_neg_1)) return false;
     if (!java.util.Objects.deepEquals(ibinder, that.ibinder)) return false;
+    if (!java.util.Objects.deepEquals(empty, that.empty)) return false;
+    if (!java.util.Objects.deepEquals(int8_1, that.int8_1)) return false;
     if (!java.util.Objects.deepEquals(int32_1, that.int32_1)) return false;
     if (!java.util.Objects.deepEquals(int64_1, that.int64_1)) return false;
     if (!java.util.Objects.deepEquals(hexInt32_pos_1, that.hexInt32_pos_1)) return false;
@@ -401,11 +391,12 @@
 
   @Override
   public int hashCode() {
-    return java.util.Arrays.deepHashCode(java.util.Arrays.asList(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo).toArray());
+    return java.util.Arrays.deepHashCode(java.util.Arrays.asList(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, empty, int8_1, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo).toArray());
   }
   @Override
   public int describeContents() {
     int _mask = 0;
+    _mask |= describeContents(empty);
     _mask |= describeContents(u);
     _mask |= describeContents(shouldBeConstS1);
     return _mask;
@@ -417,4 +408,65 @@
     }
     return 0;
   }
+  // Make sure we can send an empty parcelable
+  public static class Empty implements android.os.Parcelable
+  {
+    public static final android.os.Parcelable.Creator<Empty> CREATOR = new android.os.Parcelable.Creator<Empty>() {
+      @Override
+      public Empty createFromParcel(android.os.Parcel _aidl_source) {
+        Empty _aidl_out = new Empty();
+        _aidl_out.readFromParcel(_aidl_source);
+        return _aidl_out;
+      }
+      @Override
+      public Empty[] newArray(int _aidl_size) {
+        return new Empty[_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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+      } 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(", ", "{", "}");
+      return "android.aidl.tests.StructuredParcelable.Empty" + _aidl_sj.toString()  ;
+    }
+    @Override
+    public boolean equals(Object other) {
+      if (this == other) return true;
+      if (other == null) return false;
+      if (!(other instanceof Empty)) return false;
+      Empty that = (Empty)other;
+      return true;
+    }
+
+    @Override
+    public int hashCode() {
+      return java.util.Arrays.deepHashCode(java.util.Arrays.asList().toArray());
+    }
+    @Override
+    public int describeContents() {
+      int _mask = 0;
+      return _mask;
+    }
+  }
 }
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/Union.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/Union.java
index 2e1def2..50688a6 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/Union.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/Union.java
@@ -2,7 +2,6 @@
  * This file is auto-generated.  DO NOT MODIFY.
  */
 package android.aidl.tests;
-
 public final class Union implements android.os.Parcelable {
   // tags for union fields
   public final static int ns = 0;  // int[] ns;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/UnionWithFd.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/UnionWithFd.java
index ba025ad..941c947 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/UnionWithFd.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/UnionWithFd.java
@@ -2,7 +2,6 @@
  * This file is auto-generated.  DO NOT MODIFY.
  */
 package android.aidl.tests;
-
 public final class UnionWithFd implements android.os.Parcelable {
   // tags for union fields
   public final static int num = 0;  // int num;
@@ -79,13 +78,7 @@
       _aidl_parcel.writeInt(getNum());
       break;
     case pfd:
-      if ((getPfd()!=null)) {
-        _aidl_parcel.writeInt(1);
-        getPfd().writeToParcel(_aidl_parcel, 0);
-      }
-      else {
-        _aidl_parcel.writeInt(0);
-      }
+      _aidl_parcel.writeTypedObject(getPfd(), 0);
       break;
     }
   }
@@ -101,12 +94,7 @@
       return; }
     case pfd: {
       android.os.ParcelFileDescriptor _aidl_value;
-      if ((0!=_aidl_parcel.readInt())) {
-        _aidl_value = android.os.ParcelFileDescriptor.CREATOR.createFromParcel(_aidl_parcel);
-      }
-      else {
-        _aidl_value = null;
-      }
+      _aidl_value = _aidl_parcel.readTypedObject(android.os.ParcelFileDescriptor.CREATOR);
       _set(_aidl_tag, _aidl_value);
       return; }
     }
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/ExtendableParcelable.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/ExtendableParcelable.java
new file mode 100644
index 0000000..769649f
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/ExtendableParcelable.java
@@ -0,0 +1,79 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests.extension;
+public class ExtendableParcelable implements android.os.Parcelable
+{
+  public int a = 0;
+  public java.lang.String b;
+  public final android.os.ParcelableHolder ext = new android.os.ParcelableHolder(android.os.Parcelable.PARCELABLE_STABILITY_LOCAL);
+  public long c = 0L;
+  public final android.os.ParcelableHolder ext2 = new android.os.ParcelableHolder(android.os.Parcelable.PARCELABLE_STABILITY_LOCAL);
+  public static final android.os.Parcelable.Creator<ExtendableParcelable> CREATOR = new android.os.Parcelable.Creator<ExtendableParcelable>() {
+    @Override
+    public ExtendableParcelable createFromParcel(android.os.Parcel _aidl_source) {
+      ExtendableParcelable _aidl_out = new ExtendableParcelable();
+      _aidl_out.readFromParcel(_aidl_source);
+      return _aidl_out;
+    }
+    @Override
+    public ExtendableParcelable[] newArray(int _aidl_size) {
+      return new ExtendableParcelable[_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.writeInt(a);
+    _aidl_parcel.writeString(b);
+    _aidl_parcel.writeTypedObject(ext, 0);
+    _aidl_parcel.writeLong(c);
+    _aidl_parcel.writeTypedObject(ext2, 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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      a = _aidl_parcel.readInt();
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      b = _aidl_parcel.readString();
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      if ((0!=_aidl_parcel.readInt())) {
+        ext.readFromParcel(_aidl_parcel);
+      }
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      c = _aidl_parcel.readLong();
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      if ((0!=_aidl_parcel.readInt())) {
+        ext2.readFromParcel(_aidl_parcel);
+      }
+    } 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;
+    _mask |= describeContents(ext);
+    _mask |= describeContents(ext2);
+    return _mask;
+  }
+  private int describeContents(Object _v) {
+    if (_v == null) return 0;
+    if (_v instanceof android.os.Parcelable) {
+      return ((android.os.Parcelable) _v).describeContents();
+    }
+    return 0;
+  }
+}
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/ExtendableParcelable.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/ExtendableParcelable.java.d
new file mode 100644
index 0000000..18ee116
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/ExtendableParcelable.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/extension/ExtendableParcelable.java : \
+  system/tools/aidl/tests/android/aidl/tests/extension/ExtendableParcelable.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt.java
new file mode 100644
index 0000000..3b56b92
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt.java
@@ -0,0 +1,54 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests.extension;
+public class MyExt implements android.os.Parcelable
+{
+  public int a = 0;
+  public java.lang.String b;
+  public static final android.os.Parcelable.Creator<MyExt> CREATOR = new android.os.Parcelable.Creator<MyExt>() {
+    @Override
+    public MyExt createFromParcel(android.os.Parcel _aidl_source) {
+      MyExt _aidl_out = new MyExt();
+      _aidl_out.readFromParcel(_aidl_source);
+      return _aidl_out;
+    }
+    @Override
+    public MyExt[] newArray(int _aidl_size) {
+      return new MyExt[_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.writeInt(a);
+    _aidl_parcel.writeString(b);
+    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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      a = _aidl_parcel.readInt();
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      b = _aidl_parcel.readString();
+    } 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;
+  }
+}
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt.java.d
new file mode 100644
index 0000000..3a1efb9
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt.java : \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExt.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt2.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt2.java
new file mode 100644
index 0000000..54acb1f
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt2.java
@@ -0,0 +1,66 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests.extension;
+public class MyExt2 implements android.os.Parcelable
+{
+  public int a = 0;
+  public android.aidl.tests.extension.MyExt b;
+  public java.lang.String c;
+  public static final android.os.Parcelable.Creator<MyExt2> CREATOR = new android.os.Parcelable.Creator<MyExt2>() {
+    @Override
+    public MyExt2 createFromParcel(android.os.Parcel _aidl_source) {
+      MyExt2 _aidl_out = new MyExt2();
+      _aidl_out.readFromParcel(_aidl_source);
+      return _aidl_out;
+    }
+    @Override
+    public MyExt2[] newArray(int _aidl_size) {
+      return new MyExt2[_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.writeInt(a);
+    _aidl_parcel.writeTypedObject(b, 0);
+    _aidl_parcel.writeString(c);
+    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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      a = _aidl_parcel.readInt();
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      b = _aidl_parcel.readTypedObject(android.aidl.tests.extension.MyExt.CREATOR);
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      c = _aidl_parcel.readString();
+    } 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;
+    _mask |= describeContents(b);
+    return _mask;
+  }
+  private int describeContents(Object _v) {
+    if (_v == null) return 0;
+    if (_v instanceof android.os.Parcelable) {
+      return ((android.os.Parcelable) _v).describeContents();
+    }
+    return 0;
+  }
+}
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt2.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt2.java.d
new file mode 100644
index 0000000..bac99f4
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt2.java.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExt2.java : \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExt2.aidl \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExt.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExtLike.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExtLike.java
new file mode 100644
index 0000000..85a485b
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExtLike.java
@@ -0,0 +1,54 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests.extension;
+public class MyExtLike implements android.os.Parcelable
+{
+  public int a = 0;
+  public java.lang.String b;
+  public static final android.os.Parcelable.Creator<MyExtLike> CREATOR = new android.os.Parcelable.Creator<MyExtLike>() {
+    @Override
+    public MyExtLike createFromParcel(android.os.Parcel _aidl_source) {
+      MyExtLike _aidl_out = new MyExtLike();
+      _aidl_out.readFromParcel(_aidl_source);
+      return _aidl_out;
+    }
+    @Override
+    public MyExtLike[] newArray(int _aidl_size) {
+      return new MyExtLike[_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.writeInt(a);
+    _aidl_parcel.writeString(b);
+    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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      a = _aidl_parcel.readInt();
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      b = _aidl_parcel.readString();
+    } 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;
+  }
+}
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExtLike.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExtLike.java.d
new file mode 100644
index 0000000..87f852f
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExtLike.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/extension/MyExtLike.java : \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExtLike.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/DeeplyNested.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/DeeplyNested.java
new file mode 100644
index 0000000..67db9db
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/DeeplyNested.java
@@ -0,0 +1,222 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests.nested;
+public class DeeplyNested implements android.os.Parcelable
+{
+  public static final android.os.Parcelable.Creator<DeeplyNested> CREATOR = new android.os.Parcelable.Creator<DeeplyNested>() {
+    @Override
+    public DeeplyNested createFromParcel(android.os.Parcel _aidl_source) {
+      DeeplyNested _aidl_out = new DeeplyNested();
+      _aidl_out.readFromParcel(_aidl_source);
+      return _aidl_out;
+    }
+    @Override
+    public DeeplyNested[] newArray(int _aidl_size) {
+      return new DeeplyNested[_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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+    } 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 static class A implements android.os.Parcelable
+  {
+    // Can reference deeply nested type of a sibling type.
+    public byte e = android.aidl.tests.nested.DeeplyNested.B.C.D.E.OK;
+    public static final android.os.Parcelable.Creator<A> CREATOR = new android.os.Parcelable.Creator<A>() {
+      @Override
+      public A createFromParcel(android.os.Parcel _aidl_source) {
+        A _aidl_out = new A();
+        _aidl_out.readFromParcel(_aidl_source);
+        return _aidl_out;
+      }
+      @Override
+      public A[] newArray(int _aidl_size) {
+        return new A[_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.writeByte(e);
+      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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        e = _aidl_parcel.readByte();
+      } 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 static class B implements android.os.Parcelable
+  {
+    public static final android.os.Parcelable.Creator<B> CREATOR = new android.os.Parcelable.Creator<B>() {
+      @Override
+      public B createFromParcel(android.os.Parcel _aidl_source) {
+        B _aidl_out = new B();
+        _aidl_out.readFromParcel(_aidl_source);
+        return _aidl_out;
+      }
+      @Override
+      public B[] newArray(int _aidl_size) {
+        return new B[_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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+      } 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 static class C implements android.os.Parcelable
+    {
+      public static final android.os.Parcelable.Creator<C> CREATOR = new android.os.Parcelable.Creator<C>() {
+        @Override
+        public C createFromParcel(android.os.Parcel _aidl_source) {
+          C _aidl_out = new C();
+          _aidl_out.readFromParcel(_aidl_source);
+          return _aidl_out;
+        }
+        @Override
+        public C[] newArray(int _aidl_size) {
+          return new C[_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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+        } 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 static class D implements android.os.Parcelable
+      {
+        public static final android.os.Parcelable.Creator<D> CREATOR = new android.os.Parcelable.Creator<D>() {
+          @Override
+          public D createFromParcel(android.os.Parcel _aidl_source) {
+            D _aidl_out = new D();
+            _aidl_out.readFromParcel(_aidl_source);
+            return _aidl_out;
+          }
+          @Override
+          public D[] newArray(int _aidl_size) {
+            return new D[_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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+          } 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 static @interface E {
+          public static final byte OK = 0;
+        }
+      }
+    }
+  }
+}
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/DeeplyNested.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/DeeplyNested.java.d
new file mode 100644
index 0000000..8576ab7
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/DeeplyNested.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/nested/DeeplyNested.java : \
+  system/tools/aidl/tests/android/aidl/tests/nested/DeeplyNested.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/INestedService.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/INestedService.java
new file mode 100644
index 0000000..7fdce35
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/INestedService.java
@@ -0,0 +1,303 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests.nested;
+public interface INestedService extends android.os.IInterface
+{
+  /** Default implementation for INestedService. */
+  public static class Default implements android.aidl.tests.nested.INestedService
+  {
+    @Override public android.aidl.tests.nested.INestedService.Result flipStatus(android.aidl.tests.nested.ParcelableWithNested p) throws android.os.RemoteException
+    {
+      return null;
+    }
+    @Override public void flipStatusWithCallback(byte status, android.aidl.tests.nested.INestedService.ICallback cb) throws android.os.RemoteException
+    {
+    }
+    @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.nested.INestedService
+  {
+    /** Construct the stub at attach it to the interface. */
+    public Stub()
+    {
+      this.attachInterface(this, DESCRIPTOR);
+    }
+    /**
+     * Cast an IBinder object into an android.aidl.tests.nested.INestedService interface,
+     * generating a proxy if needed.
+     */
+    public static android.aidl.tests.nested.INestedService 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.nested.INestedService))) {
+        return ((android.aidl.tests.nested.INestedService)iin);
+      }
+      return new android.aidl.tests.nested.INestedService.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_flipStatus:
+        {
+          android.aidl.tests.nested.ParcelableWithNested _arg0;
+          _arg0 = data.readTypedObject(android.aidl.tests.nested.ParcelableWithNested.CREATOR);
+          data.enforceNoDataAvail();
+          android.aidl.tests.nested.INestedService.Result _result = this.flipStatus(_arg0);
+          reply.writeNoException();
+          reply.writeTypedObject(_result, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+          break;
+        }
+        case TRANSACTION_flipStatusWithCallback:
+        {
+          byte _arg0;
+          _arg0 = data.readByte();
+          android.aidl.tests.nested.INestedService.ICallback _arg1;
+          _arg1 = android.aidl.tests.nested.INestedService.ICallback.Stub.asInterface(data.readStrongBinder());
+          data.enforceNoDataAvail();
+          this.flipStatusWithCallback(_arg0, _arg1);
+          reply.writeNoException();
+          break;
+        }
+        default:
+        {
+          return super.onTransact(code, data, reply, flags);
+        }
+      }
+      return true;
+    }
+    private static class Proxy implements android.aidl.tests.nested.INestedService
+    {
+      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.nested.INestedService.Result flipStatus(android.aidl.tests.nested.ParcelableWithNested p) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        android.aidl.tests.nested.INestedService.Result _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeTypedObject(p, 0);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_flipStatus, _data, _reply, 0);
+          _reply.readException();
+          _result = _reply.readTypedObject(android.aidl.tests.nested.INestedService.Result.CREATOR);
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public void flipStatusWithCallback(byte status, android.aidl.tests.nested.INestedService.ICallback cb) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeByte(status);
+          _data.writeStrongInterface(cb);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_flipStatusWithCallback, _data, _reply, 0);
+          _reply.readException();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
+    }
+    static final int TRANSACTION_flipStatus = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+    static final int TRANSACTION_flipStatusWithCallback = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
+  }
+  public static final java.lang.String DESCRIPTOR = "android$aidl$tests$nested$INestedService".replace('$', '.');
+  public android.aidl.tests.nested.INestedService.Result flipStatus(android.aidl.tests.nested.ParcelableWithNested p) throws android.os.RemoteException;
+  public void flipStatusWithCallback(byte status, android.aidl.tests.nested.INestedService.ICallback cb) throws android.os.RemoteException;
+  public static class Result implements android.os.Parcelable
+  {
+    public byte status = android.aidl.tests.nested.ParcelableWithNested.Status.OK;
+    public static final android.os.Parcelable.Creator<Result> CREATOR = new android.os.Parcelable.Creator<Result>() {
+      @Override
+      public Result createFromParcel(android.os.Parcel _aidl_source) {
+        Result _aidl_out = new Result();
+        _aidl_out.readFromParcel(_aidl_source);
+        return _aidl_out;
+      }
+      @Override
+      public Result[] newArray(int _aidl_size) {
+        return new Result[_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.writeByte(status);
+      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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+        if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+        status = _aidl_parcel.readByte();
+      } 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 ICallback extends android.os.IInterface
+  {
+    /** Default implementation for ICallback. */
+    public static class Default implements android.aidl.tests.nested.INestedService.ICallback
+    {
+      @Override public void done(byte status) throws android.os.RemoteException
+      {
+      }
+      @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.nested.INestedService.ICallback
+    {
+      /** Construct the stub at attach it to the interface. */
+      public Stub()
+      {
+        this.attachInterface(this, DESCRIPTOR);
+      }
+      /**
+       * Cast an IBinder object into an android.aidl.tests.nested.INestedService.ICallback interface,
+       * generating a proxy if needed.
+       */
+      public static android.aidl.tests.nested.INestedService.ICallback 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.nested.INestedService.ICallback))) {
+          return ((android.aidl.tests.nested.INestedService.ICallback)iin);
+        }
+        return new android.aidl.tests.nested.INestedService.ICallback.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_done:
+          {
+            byte _arg0;
+            _arg0 = data.readByte();
+            data.enforceNoDataAvail();
+            this.done(_arg0);
+            reply.writeNoException();
+            break;
+          }
+          default:
+          {
+            return super.onTransact(code, data, reply, flags);
+          }
+        }
+        return true;
+      }
+      private static class Proxy implements android.aidl.tests.nested.INestedService.ICallback
+      {
+        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 void done(byte status) throws android.os.RemoteException
+        {
+          android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+          android.os.Parcel _reply = android.os.Parcel.obtain();
+          try {
+            _data.writeInterfaceToken(DESCRIPTOR);
+            _data.writeByte(status);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_done, _data, _reply, 0);
+            _reply.readException();
+          }
+          finally {
+            _reply.recycle();
+            _data.recycle();
+          }
+        }
+      }
+      static final int TRANSACTION_done = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+    }
+    public static final java.lang.String DESCRIPTOR = "android$aidl$tests$nested$INestedService$ICallback".replace('$', '.');
+    public void done(byte status) throws android.os.RemoteException;
+  }
+}
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/INestedService.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/INestedService.java.d
new file mode 100644
index 0000000..83a9e41
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/INestedService.java.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/nested/INestedService.java : \
+  system/tools/aidl/tests/android/aidl/tests/nested/INestedService.aidl \
+  system/tools/aidl/tests/android/aidl/tests/nested/ParcelableWithNested.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/ParcelableWithNested.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/ParcelableWithNested.java
new file mode 100644
index 0000000..eed2fc8
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/ParcelableWithNested.java
@@ -0,0 +1,54 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests.nested;
+public class ParcelableWithNested implements android.os.Parcelable
+{
+  public byte status = android.aidl.tests.nested.ParcelableWithNested.Status.OK;
+  public static final android.os.Parcelable.Creator<ParcelableWithNested> CREATOR = new android.os.Parcelable.Creator<ParcelableWithNested>() {
+    @Override
+    public ParcelableWithNested createFromParcel(android.os.Parcel _aidl_source) {
+      ParcelableWithNested _aidl_out = new ParcelableWithNested();
+      _aidl_out.readFromParcel(_aidl_source);
+      return _aidl_out;
+    }
+    @Override
+    public ParcelableWithNested[] newArray(int _aidl_size) {
+      return new ParcelableWithNested[_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.writeByte(status);
+    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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      status = _aidl_parcel.readByte();
+    } 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 static @interface Status {
+    public static final byte OK = 0;
+    public static final byte NOT_OK = 1;
+  }
+}
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/ParcelableWithNested.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/ParcelableWithNested.java.d
new file mode 100644
index 0000000..0f7a8c4
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/nested/ParcelableWithNested.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/nested/ParcelableWithNested.java : \
+  system/tools/aidl/tests/android/aidl/tests/nested/ParcelableWithNested.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtected.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtected.java
new file mode 100644
index 0000000..0a3ad19
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtected.java
@@ -0,0 +1,178 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests.permission;
+public interface IProtected extends android.os.IInterface
+{
+  /** Default implementation for IProtected. */
+  public static class Default implements android.aidl.tests.permission.IProtected
+  {
+    @Override public void PermissionProtected() throws android.os.RemoteException
+    {
+    }
+    @Override public void MultiplePermissionsAll() throws android.os.RemoteException
+    {
+    }
+    @Override public void MultiplePermissionsAny() throws android.os.RemoteException
+    {
+    }
+    @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.permission.IProtected
+  {
+    /** Construct the stub at attach it to the interface. */
+    public Stub()
+    {
+      this.attachInterface(this, DESCRIPTOR);
+    }
+    /**
+     * Cast an IBinder object into an android.aidl.tests.permission.IProtected interface,
+     * generating a proxy if needed.
+     */
+    public static android.aidl.tests.permission.IProtected 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.permission.IProtected))) {
+        return ((android.aidl.tests.permission.IProtected)iin);
+      }
+      return new android.aidl.tests.permission.IProtected.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_PermissionProtected:
+        {
+          if ((this.permissionCheckerWrapper(android.Manifest.permission.READ_PHONE_STATE, this.getCallingPid(), new android.content.AttributionSource(getCallingUid(), null, null))!=true)) {
+            throw new SecurityException("Access denied, requires: android.Manifest.permission.READ_PHONE_STATE");
+          }
+          this.PermissionProtected();
+          reply.writeNoException();
+          break;
+        }
+        case TRANSACTION_MultiplePermissionsAll:
+        {
+          if (((this.permissionCheckerWrapper(android.Manifest.permission.INTERNET, this.getCallingPid(), new android.content.AttributionSource(getCallingUid(), null, null))&&this.permissionCheckerWrapper(android.Manifest.permission.VIBRATE, this.getCallingPid(), new android.content.AttributionSource(getCallingUid(), null, null)))!=true)) {
+            throw new SecurityException("Access denied, requires: allOf = {android.Manifest.permission.INTERNET, android.Manifest.permission.VIBRATE}");
+          }
+          this.MultiplePermissionsAll();
+          reply.writeNoException();
+          break;
+        }
+        case TRANSACTION_MultiplePermissionsAny:
+        {
+          if (((this.permissionCheckerWrapper(android.Manifest.permission.INTERNET, this.getCallingPid(), new android.content.AttributionSource(getCallingUid(), null, null))||this.permissionCheckerWrapper(android.Manifest.permission.VIBRATE, this.getCallingPid(), new android.content.AttributionSource(getCallingUid(), null, null)))!=true)) {
+            throw new SecurityException("Access denied, requires: anyOf = {android.Manifest.permission.INTERNET, android.Manifest.permission.VIBRATE}");
+          }
+          this.MultiplePermissionsAny();
+          reply.writeNoException();
+          break;
+        }
+        default:
+        {
+          return super.onTransact(code, data, reply, flags);
+        }
+      }
+      return true;
+    }
+    private static class Proxy implements android.aidl.tests.permission.IProtected
+    {
+      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 void PermissionProtected() throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_PermissionProtected, _data, _reply, 0);
+          _reply.readException();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
+      @Override public void MultiplePermissionsAll() throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_MultiplePermissionsAll, _data, _reply, 0);
+          _reply.readException();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
+      @Override public void MultiplePermissionsAny() throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_MultiplePermissionsAny, _data, _reply, 0);
+          _reply.readException();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
+    }
+    private boolean permissionCheckerWrapper(
+        String permission, int pid, android.content.AttributionSource attributionSource) {
+      android.content.Context ctx =
+          android.app.ActivityThread.currentActivityThread().getSystemContext();
+      return (android.content.PermissionChecker.checkPermissionForDataDelivery(
+              ctx, permission, pid, attributionSource, "" /*message*/) ==
+          android.content.PermissionChecker.PERMISSION_GRANTED);
+    }
+    static final int TRANSACTION_PermissionProtected = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+    static final int TRANSACTION_MultiplePermissionsAll = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
+    static final int TRANSACTION_MultiplePermissionsAny = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
+  }
+  public static final java.lang.String DESCRIPTOR = "android$aidl$tests$permission$IProtected".replace('$', '.');
+  @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE)
+  public void PermissionProtected() throws android.os.RemoteException;
+  @android.annotation.EnforcePermission(allOf = {android.Manifest.permission.INTERNET, android.Manifest.permission.VIBRATE})
+  public void MultiplePermissionsAll() throws android.os.RemoteException;
+  @android.annotation.EnforcePermission(anyOf = {android.Manifest.permission.INTERNET, android.Manifest.permission.VIBRATE})
+  public void MultiplePermissionsAny() throws android.os.RemoteException;
+}
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtected.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtected.java.d
new file mode 100644
index 0000000..9eb7054
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtected.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtected.java : \
+  system/tools/aidl/tests/android/aidl/tests/permission/IProtected.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtectedInterface.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtectedInterface.java
new file mode 100644
index 0000000..13392fd
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtectedInterface.java
@@ -0,0 +1,152 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests.permission;
+@android.annotation.EnforcePermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
+public interface IProtectedInterface extends android.os.IInterface
+{
+  /** Default implementation for IProtectedInterface. */
+  public static class Default implements android.aidl.tests.permission.IProtectedInterface
+  {
+    @Override public void Method1() throws android.os.RemoteException
+    {
+    }
+    @Override public void Method2() throws android.os.RemoteException
+    {
+    }
+    @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.permission.IProtectedInterface
+  {
+    /** Construct the stub at attach it to the interface. */
+    public Stub()
+    {
+      this.attachInterface(this, DESCRIPTOR);
+    }
+    /**
+     * Cast an IBinder object into an android.aidl.tests.permission.IProtectedInterface interface,
+     * generating a proxy if needed.
+     */
+    public static android.aidl.tests.permission.IProtectedInterface 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.permission.IProtectedInterface))) {
+        return ((android.aidl.tests.permission.IProtectedInterface)iin);
+      }
+      return new android.aidl.tests.permission.IProtectedInterface.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_Method1:
+        {
+          if ((this.permissionCheckerWrapper(android.Manifest.permission.ACCESS_FINE_LOCATION, this.getCallingPid(), new android.content.AttributionSource(getCallingUid(), null, null))!=true)) {
+            throw new SecurityException("Access denied, requires: android.Manifest.permission.ACCESS_FINE_LOCATION");
+          }
+          this.Method1();
+          reply.writeNoException();
+          break;
+        }
+        case TRANSACTION_Method2:
+        {
+          if ((this.permissionCheckerWrapper(android.Manifest.permission.ACCESS_FINE_LOCATION, this.getCallingPid(), new android.content.AttributionSource(getCallingUid(), null, null))!=true)) {
+            throw new SecurityException("Access denied, requires: android.Manifest.permission.ACCESS_FINE_LOCATION");
+          }
+          if ((this.permissionCheckerWrapper(android.Manifest.permission.INTERNET, this.getCallingPid(), new android.content.AttributionSource(getCallingUid(), null, null))!=true)) {
+            throw new SecurityException("Access denied, requires: android.Manifest.permission.INTERNET");
+          }
+          this.Method2();
+          reply.writeNoException();
+          break;
+        }
+        default:
+        {
+          return super.onTransact(code, data, reply, flags);
+        }
+      }
+      return true;
+    }
+    private static class Proxy implements android.aidl.tests.permission.IProtectedInterface
+    {
+      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 void Method1() throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_Method1, _data, _reply, 0);
+          _reply.readException();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
+      @Override public void Method2() throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain(asBinder());
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_Method2, _data, _reply, 0);
+          _reply.readException();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
+    }
+    private boolean permissionCheckerWrapper(
+        String permission, int pid, android.content.AttributionSource attributionSource) {
+      android.content.Context ctx =
+          android.app.ActivityThread.currentActivityThread().getSystemContext();
+      return (android.content.PermissionChecker.checkPermissionForDataDelivery(
+              ctx, permission, pid, attributionSource, "" /*message*/) ==
+          android.content.PermissionChecker.PERMISSION_GRANTED);
+    }
+    static final int TRANSACTION_Method1 = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+    static final int TRANSACTION_Method2 = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
+  }
+  public static final java.lang.String DESCRIPTOR = "android$aidl$tests$permission$IProtectedInterface".replace('$', '.');
+  public void Method1() throws android.os.RemoteException;
+  @android.annotation.EnforcePermission(android.Manifest.permission.INTERNET)
+  public void Method2() throws android.os.RemoteException;
+}
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtectedInterface.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtectedInterface.java.d
new file mode 100644
index 0000000..4f04f76
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtectedInterface.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/permission/IProtectedInterface.java : \
+  system/tools/aidl/tests/android/aidl/tests/permission/IProtectedInterface.aidl
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/EnumUnion.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/EnumUnion.java
index 0e8ac93..28df6de 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/EnumUnion.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/EnumUnion.java
@@ -2,7 +2,6 @@
  * This file is auto-generated.  DO NOT MODIFY.
  */
 package android.aidl.tests.unions;
-
 public final class EnumUnion implements android.os.Parcelable {
   // tags for union fields
   public final static int intEnum = 0;  // android.aidl.tests.IntEnum intEnum;
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/UnionInUnion.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/UnionInUnion.java
index a1457e0..241511e 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/UnionInUnion.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/UnionInUnion.java
@@ -2,7 +2,6 @@
  * This file is auto-generated.  DO NOT MODIFY.
  */
 package android.aidl.tests.unions;
-
 public final class UnionInUnion implements android.os.Parcelable {
   // tags for union fields
   public final static int first = 0;  // android.aidl.tests.unions.EnumUnion first;
@@ -76,13 +75,7 @@
     _aidl_parcel.writeInt(_tag);
     switch (_tag) {
     case first:
-      if ((getFirst()!=null)) {
-        _aidl_parcel.writeInt(1);
-        getFirst().writeToParcel(_aidl_parcel, 0);
-      }
-      else {
-        _aidl_parcel.writeInt(0);
-      }
+      _aidl_parcel.writeTypedObject(getFirst(), 0);
       break;
     case second:
       _aidl_parcel.writeInt(getSecond());
@@ -96,12 +89,7 @@
     switch (_aidl_tag) {
     case first: {
       android.aidl.tests.unions.EnumUnion _aidl_value;
-      if ((0!=_aidl_parcel.readInt())) {
-        _aidl_value = android.aidl.tests.unions.EnumUnion.CREATOR.createFromParcel(_aidl_parcel);
-      }
-      else {
-        _aidl_value = null;
-      }
+      _aidl_value = _aidl_parcel.readTypedObject(android.aidl.tests.unions.EnumUnion.CREATOR);
       _set(_aidl_tag, _aidl_value);
       return; }
     case second: {
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/UnionInUnion.java.d b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/UnionInUnion.java.d
index f5c2123..7d27fdd 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/UnionInUnion.java.d
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/UnionInUnion.java.d
@@ -1,3 +1,5 @@
 out/soong/.intermediates/system/tools/aidl/aidl-test-interface-java-source/gen/android/aidl/tests/unions/UnionInUnion.java : \
   system/tools/aidl/tests/android/aidl/tests/unions/UnionInUnion.aidl \
-  system/tools/aidl/tests/android/aidl/tests/unions/EnumUnion.aidl
+  system/tools/aidl/tests/android/aidl/tests/unions/EnumUnion.aidl \
+  system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/LongEnum.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..e3f691a
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ArrayOfInterfaces.cpp
@@ -0,0 +1,477 @@
+#include "aidl/android/aidl/tests/ArrayOfInterfaces.h"
+
+#include <android/binder_parcel_utils.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) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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
+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
+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 = ::ndk::AParcel_readData(_aidl_in, &in_iface);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_nullable_iface);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_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_readData(_aidl_in, &in_iface_array_inout);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_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_readNullableData(_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_writeNullableData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_iface_array_out);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, in_iface_array_inout);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, out_nullable_iface_array_out);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_iface);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_nullable_iface);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_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_writeData(_aidl_in.get(), *in_iface_array_inout);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_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_writeNullableData(_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_readNullableData(_aidl_out.get(), _aidl_return);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_iface_array_out);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), in_iface_array_inout);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), out_nullable_iface_array_out);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_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
+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) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_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 = ::ndk::AParcel_readNullableData(_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_readData(_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_readNullableData(_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 = ::ndk::AParcel_writeData(_aidl_parcel, iface);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, nullable_iface);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, iface_array);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_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
+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 = ::ndk::AParcel_readData(_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 = ::ndk::AParcel_readData(_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 = ::ndk::AParcel_readNullableData(_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_readData(_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_readNullableData(_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 = ::ndk::AParcel_writeData(_parcel, getTag());
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+  switch (getTag()) {
+  case iface: return ::ndk::AParcel_writeData(_parcel, get<iface>());
+  case nullable_iface: return ::ndk::AParcel_writeNullableData(_parcel, get<nullable_iface>());
+  case iface_array: return ::ndk::AParcel_writeData(_parcel, get<iface_array>());
+  case nullable_iface_array: return ::ndk::AParcel_writeNullableData(_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_platform-source/gen/android/aidl/tests/BackendType.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/BackendType.cpp
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/BackendType.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/BackendType.cpp
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/BackendType.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/BackendType.cpp.d
similarity index 67%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/BackendType.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/BackendType.cpp.d
index 74e47f9..89a9bf9 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/BackendType.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/BackendType.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/BackendType.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/BackendType.cpp : \
   system/tools/aidl/tests/android/aidl/tests/BackendType.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ByteEnum.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ByteEnum.cpp
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ByteEnum.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ByteEnum.cpp
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ByteEnum.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ByteEnum.cpp.d
similarity index 67%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ByteEnum.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ByteEnum.cpp.d
index 510012a..c858c80 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ByteEnum.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ByteEnum.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ByteEnum.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/ByteEnum.cpp : \
   system/tools/aidl/tests/android/aidl/tests/ByteEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ConstantExpressionEnum.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ConstantExpressionEnum.cpp
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ConstantExpressionEnum.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ConstantExpressionEnum.cpp
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ConstantExpressionEnum.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ConstantExpressionEnum.cpp.d
similarity index 65%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ConstantExpressionEnum.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ConstantExpressionEnum.cpp.d
index a195c09..d0ab502 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ConstantExpressionEnum.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ConstantExpressionEnum.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ConstantExpressionEnum.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/ConstantExpressionEnum.cpp : \
   system/tools/aidl/tests/android/aidl/tests/ConstantExpressionEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/DeprecatedEnum.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/DeprecatedEnum.cpp
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/DeprecatedEnum.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/DeprecatedEnum.cpp
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/DeprecatedEnum.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/DeprecatedEnum.cpp.d
similarity index 66%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/DeprecatedEnum.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/DeprecatedEnum.cpp.d
index 42ac6a3..e25ec9e 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/DeprecatedEnum.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/DeprecatedEnum.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/DeprecatedEnum.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/DeprecatedEnum.cpp : \
   system/tools/aidl/tests/android/aidl/tests/DeprecatedEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/DeprecatedParcelable.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/DeprecatedParcelable.cpp
new file mode 100644
index 0000000..a12c4a8
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/DeprecatedParcelable.cpp
@@ -0,0 +1,39 @@
+#include "aidl/android/aidl/tests/DeprecatedParcelable.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* DeprecatedParcelable::descriptor = "android.aidl.tests.DeprecatedParcelable";
+
+binder_status_t DeprecatedParcelable::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+  return _aidl_ret_status;
+}
+binder_status_t DeprecatedParcelable::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
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/DeprecatedParcelable.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/DeprecatedParcelable.cpp.d
similarity index 65%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/DeprecatedParcelable.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/DeprecatedParcelable.cpp.d
index 168cf66..fcc436c 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/DeprecatedParcelable.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/DeprecatedParcelable.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/DeprecatedParcelable.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/DeprecatedParcelable.cpp : \
   system/tools/aidl/tests/android/aidl/tests/DeprecatedParcelable.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp
new file mode 100644
index 0000000..b5a6115
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp
@@ -0,0 +1,278 @@
+#include "aidl/android/aidl/tests/FixedSize.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* FixedSize::descriptor = "android.aidl.tests.FixedSize";
+
+binder_status_t FixedSize::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+  return _aidl_ret_status;
+}
+binder_status_t FixedSize::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
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* FixedSize::FixedParcelable::descriptor = "android.aidl.tests.FixedSize.FixedParcelable";
+
+binder_status_t FixedSize::FixedParcelable::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &booleanValue);
+  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_readData(_aidl_parcel, &byteValue);
+  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_readData(_aidl_parcel, &charValue);
+  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_readData(_aidl_parcel, &intValue);
+  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_readData(_aidl_parcel, &longValue);
+  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_readData(_aidl_parcel, &floatValue);
+  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_readData(_aidl_parcel, &doubleValue);
+  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_readData(_aidl_parcel, &enumValue);
+  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_readData(_aidl_parcel, &parcelableValue);
+  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 FixedSize::FixedParcelable::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 = ::ndk::AParcel_writeData(_aidl_parcel, booleanValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, byteValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, charValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, intValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, longValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, floatValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, doubleValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, enumValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, parcelableValue);
+  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
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* FixedSize::FixedUnion::descriptor = "android.aidl.tests.FixedSize.FixedUnion";
+
+binder_status_t FixedSize::FixedUnion::readFromParcel(const AParcel* _parcel) {
+  binder_status_t _aidl_ret_status;
+  int32_t _aidl_tag;
+  if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_tag)) != STATUS_OK) return _aidl_ret_status;
+  switch (_aidl_tag) {
+  case booleanValue: {
+    bool _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<bool>) {
+      set<booleanValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<booleanValue>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  case byteValue: {
+    int8_t _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<int8_t>) {
+      set<byteValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<byteValue>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  case charValue: {
+    char16_t _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<char16_t>) {
+      set<charValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<charValue>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  case intValue: {
+    int32_t _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<int32_t>) {
+      set<intValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<intValue>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  case longValue: {
+    int64_t _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<int64_t>) {
+      set<longValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<longValue>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  case floatValue: {
+    float _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<float>) {
+      set<floatValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<floatValue>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  case doubleValue: {
+    double _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<double>) {
+      set<doubleValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<doubleValue>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  case enumValue: {
+    ::aidl::android::aidl::tests::LongEnum _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<::aidl::android::aidl::tests::LongEnum>) {
+      set<enumValue>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<enumValue>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  }
+  return STATUS_BAD_VALUE;
+}
+binder_status_t FixedSize::FixedUnion::writeToParcel(AParcel* _parcel) const {
+  binder_status_t _aidl_ret_status = ::ndk::AParcel_writeData(_parcel, getTag());
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+  switch (getTag()) {
+  case booleanValue: return ::ndk::AParcel_writeData(_parcel, get<booleanValue>());
+  case byteValue: return ::ndk::AParcel_writeData(_parcel, get<byteValue>());
+  case charValue: return ::ndk::AParcel_writeData(_parcel, get<charValue>());
+  case intValue: return ::ndk::AParcel_writeData(_parcel, get<intValue>());
+  case longValue: return ::ndk::AParcel_writeData(_parcel, get<longValue>());
+  case floatValue: return ::ndk::AParcel_writeData(_parcel, get<floatValue>());
+  case doubleValue: return ::ndk::AParcel_writeData(_parcel, get<doubleValue>());
+  case enumValue: return ::ndk::AParcel_writeData(_parcel, get<enumValue>());
+  }
+  __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/FixedSize.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp.d
new file mode 100644
index 0000000..b27ad3e
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/FixedSize.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/FixedSize.aidl \
+  system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/GenericStructuredParcelable.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/GenericStructuredParcelable.cpp
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/GenericStructuredParcelable.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/GenericStructuredParcelable.cpp
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/GenericStructuredParcelable.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/GenericStructuredParcelable.cpp.d
similarity index 64%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/GenericStructuredParcelable.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/GenericStructuredParcelable.cpp.d
index 10c0013..06b2f5d 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/GenericStructuredParcelable.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/GenericStructuredParcelable.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/GenericStructuredParcelable.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/GenericStructuredParcelable.cpp : \
   system/tools/aidl/tests/android/aidl/tests/GenericStructuredParcelable.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IDeprecated.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IDeprecated.cpp
similarity index 81%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IDeprecated.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IDeprecated.cpp
index a6513c2..e4fb510 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IDeprecated.cpp
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IDeprecated.cpp
@@ -1,7 +1,8 @@
+#include "aidl/android/aidl/tests/IDeprecated.h"
+
 #include <android/binder_parcel_utils.h>
-#include <aidl/android/aidl/tests/BpDeprecated.h>
 #include <aidl/android/aidl/tests/BnDeprecated.h>
-#include <aidl/android/aidl/tests/IDeprecated.h>
+#include <aidl/android/aidl/tests/BpDeprecated.h>
 
 namespace aidl {
 namespace android {
@@ -9,7 +10,7 @@
 namespace tests {
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated"
-static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, AParcel* _aidl_out) {
+static binder_status_t _aidl_android_aidl_tests_IDeprecated_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;
@@ -18,7 +19,7 @@
   return _aidl_ret_status;
 }
 
-static AIBinder_Class* _g_aidl_clazz = ::ndk::ICInterface::defineClass(IDeprecated::descriptor, _aidl_onTransact);
+static AIBinder_Class* _g_aidl_android_aidl_tests_IDeprecated_clazz = ::ndk::ICInterface::defineClass(IDeprecated::descriptor, _aidl_android_aidl_tests_IDeprecated_onTransact);
 
 #pragma clang diagnostic pop
 BpDeprecated::BpDeprecated(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
@@ -28,7 +29,7 @@
 BnDeprecated::BnDeprecated() {}
 BnDeprecated::~BnDeprecated() {}
 ::ndk::SpAIBinder BnDeprecated::createBinder() {
-  AIBinder* binder = AIBinder_new(_g_aidl_clazz, static_cast<void*>(this));
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_tests_IDeprecated_clazz, static_cast<void*>(this));
   #ifdef BINDER_STABILITY_SUPPORT
   AIBinder_markCompilationUnitStability(binder);
   #endif  // BINDER_STABILITY_SUPPORT
@@ -41,7 +42,7 @@
 
 
 std::shared_ptr<IDeprecated> IDeprecated::fromBinder(const ::ndk::SpAIBinder& binder) {
-  if (!AIBinder_associateClass(binder.get(), _g_aidl_clazz)) { return nullptr; }
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_tests_IDeprecated_clazz)) { return nullptr; }
   std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
   if (interface) {
     return std::static_pointer_cast<IDeprecated>(interface);
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IDeprecated.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IDeprecated.cpp.d
similarity index 67%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IDeprecated.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IDeprecated.cpp.d
index 5bc40c0..d92d4e5 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IDeprecated.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IDeprecated.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IDeprecated.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/IDeprecated.cpp : \
   system/tools/aidl/tests/android/aidl/tests/IDeprecated.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INamedCallback.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/INamedCallback.cpp
similarity index 85%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INamedCallback.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/INamedCallback.cpp
index 17f6da2..d441106 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INamedCallback.cpp
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/INamedCallback.cpp
@@ -1,13 +1,14 @@
+#include "aidl/android/aidl/tests/INamedCallback.h"
+
 #include <android/binder_parcel_utils.h>
-#include <aidl/android/aidl/tests/BpNamedCallback.h>
 #include <aidl/android/aidl/tests/BnNamedCallback.h>
-#include <aidl/android/aidl/tests/INamedCallback.h>
+#include <aidl/android/aidl/tests/BpNamedCallback.h>
 
 namespace aidl {
 namespace android {
 namespace aidl {
 namespace tests {
-static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, AParcel* _aidl_out) {
+static binder_status_t _aidl_android_aidl_tests_INamedCallback_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;
@@ -22,7 +23,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -31,7 +32,7 @@
   return _aidl_ret_status;
 }
 
-static AIBinder_Class* _g_aidl_clazz = ::ndk::ICInterface::defineClass(INamedCallback::descriptor, _aidl_onTransact);
+static AIBinder_Class* _g_aidl_android_aidl_tests_INamedCallback_clazz = ::ndk::ICInterface::defineClass(INamedCallback::descriptor, _aidl_android_aidl_tests_INamedCallback_onTransact);
 
 BpNamedCallback::BpNamedCallback(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
 BpNamedCallback::~BpNamedCallback() {}
@@ -65,7 +66,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::ndk::AParcel_readString(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -77,7 +78,7 @@
 BnNamedCallback::BnNamedCallback() {}
 BnNamedCallback::~BnNamedCallback() {}
 ::ndk::SpAIBinder BnNamedCallback::createBinder() {
-  AIBinder* binder = AIBinder_new(_g_aidl_clazz, static_cast<void*>(this));
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_tests_INamedCallback_clazz, static_cast<void*>(this));
   #ifdef BINDER_STABILITY_SUPPORT
   AIBinder_markCompilationUnitStability(binder);
   #endif  // BINDER_STABILITY_SUPPORT
@@ -90,7 +91,7 @@
 
 
 std::shared_ptr<INamedCallback> INamedCallback::fromBinder(const ::ndk::SpAIBinder& binder) {
-  if (!AIBinder_associateClass(binder.get(), _g_aidl_clazz)) { return nullptr; }
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_tests_INamedCallback_clazz)) { return nullptr; }
   std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
   if (interface) {
     return std::static_pointer_cast<INamedCallback>(interface);
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INamedCallback.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/INamedCallback.cpp.d
similarity index 66%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INamedCallback.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/INamedCallback.cpp.d
index 2eceb33..b6ec5e6 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INamedCallback.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/INamedCallback.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INamedCallback.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/INamedCallback.cpp : \
   system/tools/aidl/tests/android/aidl/tests/INamedCallback.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INewName.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/INewName.cpp
similarity index 85%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INewName.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/INewName.cpp
index 8f48442..e408258 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INewName.cpp
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/INewName.cpp
@@ -1,13 +1,14 @@
+#include "aidl/android/aidl/tests/INewName.h"
+
 #include <android/binder_parcel_utils.h>
-#include <aidl/android/aidl/tests/BpNewName.h>
 #include <aidl/android/aidl/tests/BnNewName.h>
-#include <aidl/android/aidl/tests/INewName.h>
+#include <aidl/android/aidl/tests/BpNewName.h>
 
 namespace aidl {
 namespace android {
 namespace aidl {
 namespace tests {
-static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, AParcel* _aidl_out) {
+static binder_status_t _aidl_android_aidl_tests_INewName_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;
@@ -22,7 +23,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -31,7 +32,7 @@
   return _aidl_ret_status;
 }
 
-static AIBinder_Class* _g_aidl_clazz = ::ndk::ICInterface::defineClass(INewName::descriptor, _aidl_onTransact);
+static AIBinder_Class* _g_aidl_android_aidl_tests_INewName_clazz = ::ndk::ICInterface::defineClass(INewName::descriptor, _aidl_android_aidl_tests_INewName_onTransact);
 
 BpNewName::BpNewName(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
 BpNewName::~BpNewName() {}
@@ -65,7 +66,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::ndk::AParcel_readString(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -77,7 +78,7 @@
 BnNewName::BnNewName() {}
 BnNewName::~BnNewName() {}
 ::ndk::SpAIBinder BnNewName::createBinder() {
-  AIBinder* binder = AIBinder_new(_g_aidl_clazz, static_cast<void*>(this));
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_tests_INewName_clazz, static_cast<void*>(this));
   #ifdef BINDER_STABILITY_SUPPORT
   AIBinder_markCompilationUnitStability(binder);
   #endif  // BINDER_STABILITY_SUPPORT
@@ -90,7 +91,7 @@
 
 
 std::shared_ptr<INewName> INewName::fromBinder(const ::ndk::SpAIBinder& binder) {
-  if (!AIBinder_associateClass(binder.get(), _g_aidl_clazz)) { return nullptr; }
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_tests_INewName_clazz)) { return nullptr; }
   std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
   if (interface) {
     return std::static_pointer_cast<INewName>(interface);
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INewName.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/INewName.cpp.d
similarity index 67%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INewName.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/INewName.cpp.d
index 0c569c5..459e176 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INewName.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/INewName.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/INewName.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/INewName.cpp : \
   system/tools/aidl/tests/android/aidl/tests/INewName.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IOldName.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IOldName.cpp
similarity index 85%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IOldName.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IOldName.cpp
index 6f54ec6..ff40499 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IOldName.cpp
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IOldName.cpp
@@ -1,13 +1,14 @@
+#include "aidl/android/aidl/tests/IOldName.h"
+
 #include <android/binder_parcel_utils.h>
-#include <aidl/android/aidl/tests/BpOldName.h>
 #include <aidl/android/aidl/tests/BnOldName.h>
-#include <aidl/android/aidl/tests/IOldName.h>
+#include <aidl/android/aidl/tests/BpOldName.h>
 
 namespace aidl {
 namespace android {
 namespace aidl {
 namespace tests {
-static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, AParcel* _aidl_out) {
+static binder_status_t _aidl_android_aidl_tests_IOldName_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;
@@ -22,7 +23,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -31,7 +32,7 @@
   return _aidl_ret_status;
 }
 
-static AIBinder_Class* _g_aidl_clazz = ::ndk::ICInterface::defineClass(IOldName::descriptor, _aidl_onTransact);
+static AIBinder_Class* _g_aidl_android_aidl_tests_IOldName_clazz = ::ndk::ICInterface::defineClass(IOldName::descriptor, _aidl_android_aidl_tests_IOldName_onTransact);
 
 BpOldName::BpOldName(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
 BpOldName::~BpOldName() {}
@@ -65,7 +66,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::ndk::AParcel_readString(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -77,7 +78,7 @@
 BnOldName::BnOldName() {}
 BnOldName::~BnOldName() {}
 ::ndk::SpAIBinder BnOldName::createBinder() {
-  AIBinder* binder = AIBinder_new(_g_aidl_clazz, static_cast<void*>(this));
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_tests_IOldName_clazz, static_cast<void*>(this));
   #ifdef BINDER_STABILITY_SUPPORT
   AIBinder_markCompilationUnitStability(binder);
   #endif  // BINDER_STABILITY_SUPPORT
@@ -90,7 +91,7 @@
 
 
 std::shared_ptr<IOldName> IOldName::fromBinder(const ::ndk::SpAIBinder& binder) {
-  if (!AIBinder_associateClass(binder.get(), _g_aidl_clazz)) { return nullptr; }
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_tests_IOldName_clazz)) { return nullptr; }
   std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
   if (interface) {
     return std::static_pointer_cast<IOldName>(interface);
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IOldName.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IOldName.cpp.d
similarity index 67%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IOldName.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IOldName.cpp.d
index 8e4435e..1ca4239 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IOldName.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IOldName.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IOldName.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/IOldName.cpp : \
   system/tools/aidl/tests/android/aidl/tests/IOldName.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ITestService.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ITestService.cpp
similarity index 62%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ITestService.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ITestService.cpp
index 515707a..0268aaa 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ITestService.cpp
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ITestService.cpp
@@ -1,16 +1,17 @@
+#include "aidl/android/aidl/tests/ITestService.h"
+
 #include <android/binder_parcel_utils.h>
-#include <aidl/android/aidl/tests/BpNamedCallback.h>
 #include <aidl/android/aidl/tests/BnNamedCallback.h>
-#include <aidl/android/aidl/tests/INamedCallback.h>
-#include <aidl/android/aidl/tests/BpNewName.h>
 #include <aidl/android/aidl/tests/BnNewName.h>
-#include <aidl/android/aidl/tests/INewName.h>
-#include <aidl/android/aidl/tests/BpOldName.h>
 #include <aidl/android/aidl/tests/BnOldName.h>
-#include <aidl/android/aidl/tests/IOldName.h>
-#include <aidl/android/aidl/tests/BpTestService.h>
 #include <aidl/android/aidl/tests/BnTestService.h>
-#include <aidl/android/aidl/tests/ITestService.h>
+#include <aidl/android/aidl/tests/BpNamedCallback.h>
+#include <aidl/android/aidl/tests/BpNewName.h>
+#include <aidl/android/aidl/tests/BpOldName.h>
+#include <aidl/android/aidl/tests/BpTestService.h>
+#include <aidl/android/aidl/tests/INamedCallback.h>
+#include <aidl/android/aidl/tests/INewName.h>
+#include <aidl/android/aidl/tests/IOldName.h>
 
 namespace aidl {
 namespace android {
@@ -18,7 +19,7 @@
 namespace tests {
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdeprecated"
-static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, AParcel* _aidl_out) {
+static binder_status_t _aidl_android_aidl_tests_ITestService_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;
@@ -28,7 +29,7 @@
       int32_t in_arg;
       int32_t _aidl_return;
 
-      _aidl_ret_status = AParcel_readInt32(_aidl_in, &in_arg);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_arg);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->UnimplementedMethod(in_arg, &_aidl_return);
@@ -37,7 +38,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeInt32(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -62,7 +63,7 @@
       bool in_token;
       bool _aidl_return;
 
-      _aidl_ret_status = AParcel_readBool(_aidl_in, &in_token);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_token);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatBoolean(in_token, &_aidl_return);
@@ -71,7 +72,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeBool(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -80,7 +81,7 @@
       int8_t in_token;
       int8_t _aidl_return;
 
-      _aidl_ret_status = AParcel_readByte(_aidl_in, &in_token);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_token);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatByte(in_token, &_aidl_return);
@@ -89,7 +90,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeByte(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -98,7 +99,7 @@
       char16_t in_token;
       char16_t _aidl_return;
 
-      _aidl_ret_status = AParcel_readChar(_aidl_in, &in_token);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_token);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatChar(in_token, &_aidl_return);
@@ -107,7 +108,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeChar(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -116,7 +117,7 @@
       int32_t in_token;
       int32_t _aidl_return;
 
-      _aidl_ret_status = AParcel_readInt32(_aidl_in, &in_token);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_token);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatInt(in_token, &_aidl_return);
@@ -125,7 +126,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeInt32(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -134,7 +135,7 @@
       int64_t in_token;
       int64_t _aidl_return;
 
-      _aidl_ret_status = AParcel_readInt64(_aidl_in, &in_token);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_token);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatLong(in_token, &_aidl_return);
@@ -143,7 +144,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeInt64(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -152,7 +153,7 @@
       float in_token;
       float _aidl_return;
 
-      _aidl_ret_status = AParcel_readFloat(_aidl_in, &in_token);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_token);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatFloat(in_token, &_aidl_return);
@@ -161,7 +162,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeFloat(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -170,7 +171,7 @@
       double in_token;
       double _aidl_return;
 
-      _aidl_ret_status = AParcel_readDouble(_aidl_in, &in_token);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_token);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatDouble(in_token, &_aidl_return);
@@ -179,7 +180,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeDouble(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -188,7 +189,7 @@
       std::string in_token;
       std::string _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readString(_aidl_in, &in_token);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_token);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatString(in_token, &_aidl_return);
@@ -197,7 +198,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -206,7 +207,7 @@
       ::aidl::android::aidl::tests::ByteEnum in_token;
       ::aidl::android::aidl::tests::ByteEnum _aidl_return;
 
-      _aidl_ret_status = AParcel_readByte(_aidl_in, reinterpret_cast<int8_t*>(&in_token));
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_token);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatByteEnum(in_token, &_aidl_return);
@@ -215,7 +216,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeByte(_aidl_out, static_cast<int8_t>(_aidl_return));
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -224,7 +225,7 @@
       ::aidl::android::aidl::tests::IntEnum in_token;
       ::aidl::android::aidl::tests::IntEnum _aidl_return;
 
-      _aidl_ret_status = AParcel_readInt32(_aidl_in, reinterpret_cast<int32_t*>(&in_token));
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_token);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatIntEnum(in_token, &_aidl_return);
@@ -233,7 +234,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeInt32(_aidl_out, static_cast<int32_t>(_aidl_return));
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -242,7 +243,7 @@
       ::aidl::android::aidl::tests::LongEnum in_token;
       ::aidl::android::aidl::tests::LongEnum _aidl_return;
 
-      _aidl_ret_status = AParcel_readInt64(_aidl_in, reinterpret_cast<int64_t*>(&in_token));
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_token);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatLongEnum(in_token, &_aidl_return);
@@ -251,7 +252,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeInt64(_aidl_out, static_cast<int64_t>(_aidl_return));
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -261,7 +262,7 @@
       std::vector<bool> out_repeated;
       std::vector<bool> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -273,10 +274,10 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_repeated);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -286,7 +287,7 @@
       std::vector<uint8_t> out_repeated;
       std::vector<uint8_t> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -298,10 +299,10 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_repeated);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -311,7 +312,7 @@
       std::vector<char16_t> out_repeated;
       std::vector<char16_t> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -323,10 +324,10 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_repeated);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -336,7 +337,7 @@
       std::vector<int32_t> out_repeated;
       std::vector<int32_t> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -348,10 +349,10 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_repeated);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -361,7 +362,7 @@
       std::vector<int64_t> out_repeated;
       std::vector<int64_t> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -373,10 +374,10 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_repeated);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -386,7 +387,7 @@
       std::vector<float> out_repeated;
       std::vector<float> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -398,10 +399,10 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_repeated);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -411,7 +412,7 @@
       std::vector<double> out_repeated;
       std::vector<double> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -423,10 +424,10 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_repeated);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -436,7 +437,7 @@
       std::vector<std::string> out_repeated;
       std::vector<std::string> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -448,10 +449,10 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_repeated);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -461,7 +462,7 @@
       std::vector<::aidl::android::aidl::tests::ByteEnum> out_repeated;
       std::vector<::aidl::android::aidl::tests::ByteEnum> _aidl_return;
 
-      _aidl_ret_status = AParcel_readByteArray(_aidl_in, static_cast<void*>(&in_input), ndk::AParcel_stdVectorAllocator<int8_t>);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -473,10 +474,10 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeByteArray(_aidl_out, reinterpret_cast<const int8_t*>(_aidl_return.data()), _aidl_return.size());
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = AParcel_writeByteArray(_aidl_out, reinterpret_cast<const int8_t*>(out_repeated.data()), out_repeated.size());
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -486,7 +487,7 @@
       std::vector<::aidl::android::aidl::tests::IntEnum> out_repeated;
       std::vector<::aidl::android::aidl::tests::IntEnum> _aidl_return;
 
-      _aidl_ret_status = AParcel_readInt32Array(_aidl_in, static_cast<void*>(&in_input), ndk::AParcel_stdVectorAllocator<int32_t>);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -498,10 +499,10 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeInt32Array(_aidl_out, reinterpret_cast<const int32_t*>(_aidl_return.data()), _aidl_return.size());
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = AParcel_writeInt32Array(_aidl_out, reinterpret_cast<const int32_t*>(out_repeated.data()), out_repeated.size());
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -511,7 +512,7 @@
       std::vector<::aidl::android::aidl::tests::LongEnum> out_repeated;
       std::vector<::aidl::android::aidl::tests::LongEnum> _aidl_return;
 
-      _aidl_ret_status = AParcel_readInt64Array(_aidl_in, static_cast<void*>(&in_input), ndk::AParcel_stdVectorAllocator<int64_t>);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -523,10 +524,10 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeInt64Array(_aidl_out, reinterpret_cast<const int64_t*>(_aidl_return.data()), _aidl_return.size());
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = AParcel_writeInt64Array(_aidl_out, reinterpret_cast<const int64_t*>(out_repeated.data()), out_repeated.size());
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -535,7 +536,7 @@
       std::string in_name;
       std::shared_ptr<::aidl::android::aidl::tests::INamedCallback> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readString(_aidl_in, &in_name);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_name);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->GetOtherTestService(in_name, &_aidl_return);
@@ -544,7 +545,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::aidl::android::aidl::tests::INamedCallback::writeToParcel(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -554,10 +555,10 @@
       std::string in_name;
       bool _aidl_return;
 
-      _aidl_ret_status = ::aidl::android::aidl::tests::INamedCallback::readFromParcel(_aidl_in, &in_service);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_service);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readString(_aidl_in, &in_name);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_name);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->VerifyName(in_service, in_name, &_aidl_return);
@@ -566,17 +567,137 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeBool(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 27 /*ReverseStringList*/): {
+    case (FIRST_CALL_TRANSACTION + 27 /*GetInterfaceArray*/): {
+      std::vector<std::string> in_names;
+      std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_names);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->GetInterfaceArray(in_names, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 28 /*VerifyNamesWithInterfaceArray*/): {
+      std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>> in_services;
+      std::vector<std::string> in_names;
+      bool _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_services);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_names);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->VerifyNamesWithInterfaceArray(in_services, in_names, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 29 /*GetNullableInterfaceArray*/): {
+      std::optional<std::vector<std::optional<std::string>>> in_names;
+      std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_names);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->GetNullableInterfaceArray(in_names, &_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_writeNullableData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 30 /*VerifyNamesWithNullableInterfaceArray*/): {
+      std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>> in_services;
+      std::optional<std::vector<std::optional<std::string>>> in_names;
+      bool _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_services);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_names);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->VerifyNamesWithNullableInterfaceArray(in_services, in_names, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 31 /*GetInterfaceList*/): {
+      std::optional<std::vector<std::optional<std::string>>> in_names;
+      std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_names);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->GetInterfaceList(in_names, &_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_writeNullableData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 32 /*VerifyNamesWithInterfaceList*/): {
+      std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>> in_services;
+      std::optional<std::vector<std::optional<std::string>>> in_names;
+      bool _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_services);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_names);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->VerifyNamesWithInterfaceList(in_services, in_names, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 33 /*ReverseStringList*/): {
       std::vector<std::string> in_input;
       std::vector<std::string> out_repeated;
       std::vector<std::string> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->ReverseStringList(in_input, &out_repeated, &_aidl_return);
@@ -585,19 +706,19 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_repeated);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 28 /*RepeatParcelFileDescriptor*/): {
+    case (FIRST_CALL_TRANSACTION + 34 /*RepeatParcelFileDescriptor*/): {
       ::ndk::ScopedFileDescriptor in_read;
       ::ndk::ScopedFileDescriptor _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readRequiredParcelFileDescriptor(_aidl_in, &in_read);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_read);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatParcelFileDescriptor(in_read, &_aidl_return);
@@ -606,17 +727,17 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeRequiredParcelFileDescriptor(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 29 /*ReverseParcelFileDescriptorArray*/): {
+    case (FIRST_CALL_TRANSACTION + 35 /*ReverseParcelFileDescriptorArray*/): {
       std::vector<::ndk::ScopedFileDescriptor> in_input;
       std::vector<::ndk::ScopedFileDescriptor> out_repeated;
       std::vector<::ndk::ScopedFileDescriptor> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -628,18 +749,18 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_repeated);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 30 /*ThrowServiceException*/): {
+    case (FIRST_CALL_TRANSACTION + 36 /*ThrowServiceException*/): {
       int32_t in_code;
 
-      _aidl_ret_status = AParcel_readInt32(_aidl_in, &in_code);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_code);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->ThrowServiceException(in_code);
@@ -650,11 +771,11 @@
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 31 /*RepeatNullableIntArray*/): {
+    case (FIRST_CALL_TRANSACTION + 37 /*RepeatNullableIntArray*/): {
       std::optional<std::vector<int32_t>> in_input;
       std::optional<std::vector<int32_t>> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatNullableIntArray(in_input, &_aidl_return);
@@ -663,16 +784,16 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 32 /*RepeatNullableByteEnumArray*/): {
+    case (FIRST_CALL_TRANSACTION + 38 /*RepeatNullableByteEnumArray*/): {
       std::optional<std::vector<::aidl::android::aidl::tests::ByteEnum>> in_input;
       std::optional<std::vector<::aidl::android::aidl::tests::ByteEnum>> _aidl_return;
 
-      _aidl_ret_status = AParcel_readByteArray(_aidl_in, static_cast<void*>(&in_input), ndk::AParcel_nullableStdVectorAllocator<int8_t>);
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatNullableByteEnumArray(in_input, &_aidl_return);
@@ -681,16 +802,16 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeByteArray(_aidl_out, (_aidl_return ? reinterpret_cast<const int8_t*>(_aidl_return->data()) : nullptr), (_aidl_return ? _aidl_return->size() : -1));
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 33 /*RepeatNullableIntEnumArray*/): {
+    case (FIRST_CALL_TRANSACTION + 39 /*RepeatNullableIntEnumArray*/): {
       std::optional<std::vector<::aidl::android::aidl::tests::IntEnum>> in_input;
       std::optional<std::vector<::aidl::android::aidl::tests::IntEnum>> _aidl_return;
 
-      _aidl_ret_status = AParcel_readInt32Array(_aidl_in, static_cast<void*>(&in_input), ndk::AParcel_nullableStdVectorAllocator<int32_t>);
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatNullableIntEnumArray(in_input, &_aidl_return);
@@ -699,16 +820,16 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeInt32Array(_aidl_out, (_aidl_return ? reinterpret_cast<const int32_t*>(_aidl_return->data()) : nullptr), (_aidl_return ? _aidl_return->size() : -1));
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 34 /*RepeatNullableLongEnumArray*/): {
+    case (FIRST_CALL_TRANSACTION + 40 /*RepeatNullableLongEnumArray*/): {
       std::optional<std::vector<::aidl::android::aidl::tests::LongEnum>> in_input;
       std::optional<std::vector<::aidl::android::aidl::tests::LongEnum>> _aidl_return;
 
-      _aidl_ret_status = AParcel_readInt64Array(_aidl_in, static_cast<void*>(&in_input), ndk::AParcel_nullableStdVectorAllocator<int64_t>);
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatNullableLongEnumArray(in_input, &_aidl_return);
@@ -717,16 +838,16 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeInt64Array(_aidl_out, (_aidl_return ? reinterpret_cast<const int64_t*>(_aidl_return->data()) : nullptr), (_aidl_return ? _aidl_return->size() : -1));
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 35 /*RepeatNullableString*/): {
+    case (FIRST_CALL_TRANSACTION + 41 /*RepeatNullableString*/): {
       std::optional<std::string> in_input;
       std::optional<std::string> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readString(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatNullableString(in_input, &_aidl_return);
@@ -735,16 +856,16 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 36 /*RepeatNullableStringList*/): {
-      std::vector<std::string> in_input;
-      std::vector<std::string> _aidl_return;
+    case (FIRST_CALL_TRANSACTION + 42 /*RepeatNullableStringList*/): {
+      std::optional<std::vector<std::optional<std::string>>> in_input;
+      std::optional<std::vector<std::optional<std::string>>> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatNullableStringList(in_input, &_aidl_return);
@@ -753,16 +874,16 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 37 /*RepeatNullableParcelable*/): {
-      std::optional<::aidl::android::aidl::tests::StructuredParcelable> in_input;
-      std::optional<::aidl::android::aidl::tests::StructuredParcelable> _aidl_return;
+    case (FIRST_CALL_TRANSACTION + 43 /*RepeatNullableParcelable*/): {
+      std::optional<::aidl::android::aidl::tests::ITestService::Empty> in_input;
+      std::optional<::aidl::android::aidl::tests::ITestService::Empty> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readNullableParcelable(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatNullableParcelable(in_input, &_aidl_return);
@@ -771,15 +892,51 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeNullableParcelable(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 38 /*TakesAnIBinder*/): {
+    case (FIRST_CALL_TRANSACTION + 44 /*RepeatNullableParcelableArray*/): {
+      std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>> in_input;
+      std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatNullableParcelableArray(in_input, &_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_writeNullableData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 45 /*RepeatNullableParcelableList*/): {
+      std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>> in_input;
+      std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatNullableParcelableList(in_input, &_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_writeNullableData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 46 /*TakesAnIBinder*/): {
       ::ndk::SpAIBinder in_input;
 
-      _aidl_ret_status = ::ndk::AParcel_readRequiredStrongBinder(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->TakesAnIBinder(in_input);
@@ -790,10 +947,10 @@
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 39 /*TakesANullableIBinder*/): {
+    case (FIRST_CALL_TRANSACTION + 47 /*TakesANullableIBinder*/): {
       ::ndk::SpAIBinder in_input;
 
-      _aidl_ret_status = ::ndk::AParcel_readNullableStrongBinder(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->TakesANullableIBinder(in_input);
@@ -804,11 +961,39 @@
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 40 /*RepeatUtf8CppString*/): {
+    case (FIRST_CALL_TRANSACTION + 48 /*TakesAnIBinderList*/): {
+      std::vector<::ndk::SpAIBinder> in_input;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->TakesAnIBinderList(in_input);
+      _aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      if (!AStatus_isOk(_aidl_status.get())) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 49 /*TakesANullableIBinderList*/): {
+      std::optional<std::vector<::ndk::SpAIBinder>> in_input;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->TakesANullableIBinderList(in_input);
+      _aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      if (!AStatus_isOk(_aidl_status.get())) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 50 /*RepeatUtf8CppString*/): {
       std::string in_token;
       std::string _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readString(_aidl_in, &in_token);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_token);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatUtf8CppString(in_token, &_aidl_return);
@@ -817,16 +1002,16 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 41 /*RepeatNullableUtf8CppString*/): {
+    case (FIRST_CALL_TRANSACTION + 51 /*RepeatNullableUtf8CppString*/): {
       std::optional<std::string> in_token;
       std::optional<std::string> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readString(_aidl_in, &in_token);
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_token);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatNullableUtf8CppString(in_token, &_aidl_return);
@@ -835,17 +1020,17 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 42 /*ReverseUtf8CppString*/): {
+    case (FIRST_CALL_TRANSACTION + 52 /*ReverseUtf8CppString*/): {
       std::vector<std::string> in_input;
       std::vector<std::string> out_repeated;
       std::vector<std::string> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -857,20 +1042,20 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_repeated);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 43 /*ReverseNullableUtf8CppString*/): {
+    case (FIRST_CALL_TRANSACTION + 53 /*ReverseNullableUtf8CppString*/): {
       std::optional<std::vector<std::optional<std::string>>> in_input;
       std::optional<std::vector<std::optional<std::string>>> out_repeated;
       std::optional<std::vector<std::optional<std::string>>> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
@@ -882,20 +1067,20 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_repeated);
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 44 /*ReverseUtf8CppStringList*/): {
-      std::vector<std::string> in_input;
-      std::vector<std::string> out_repeated;
-      std::vector<std::string> _aidl_return;
+    case (FIRST_CALL_TRANSACTION + 54 /*ReverseUtf8CppStringList*/): {
+      std::optional<std::vector<std::optional<std::string>>> in_input;
+      std::optional<std::vector<std::optional<std::string>>> out_repeated;
+      std::optional<std::vector<std::optional<std::string>>> _aidl_return;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_input);
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->ReverseUtf8CppStringList(in_input, &out_repeated, &_aidl_return);
@@ -904,19 +1089,19 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, out_repeated);
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, out_repeated);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 45 /*GetCallback*/): {
+    case (FIRST_CALL_TRANSACTION + 55 /*GetCallback*/): {
       bool in_return_null;
       std::shared_ptr<::aidl::android::aidl::tests::INamedCallback> _aidl_return;
 
-      _aidl_ret_status = AParcel_readBool(_aidl_in, &in_return_null);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_return_null);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->GetCallback(in_return_null, &_aidl_return);
@@ -925,15 +1110,15 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::aidl::android::aidl::tests::INamedCallback::writeToParcel(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 46 /*FillOutStructuredParcelable*/): {
+    case (FIRST_CALL_TRANSACTION + 56 /*FillOutStructuredParcelable*/): {
       ::aidl::android::aidl::tests::StructuredParcelable in_parcel;
 
-      _aidl_ret_status = ::ndk::AParcel_readParcelable(_aidl_in, &in_parcel);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_parcel);
       if (_aidl_ret_status != STATUS_OK) break;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->FillOutStructuredParcelable(&in_parcel);
@@ -942,12 +1127,98 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeParcelable(_aidl_out, in_parcel);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, in_parcel);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 47 /*GetOldNameInterface*/): {
+    case (FIRST_CALL_TRANSACTION + 57 /*RepeatExtendableParcelable*/): {
+      ::aidl::android::aidl::tests::extension::ExtendableParcelable in_ep;
+      ::aidl::android::aidl::tests::extension::ExtendableParcelable out_ep2;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_ep);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->RepeatExtendableParcelable(in_ep, &out_ep2);
+      _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_writeData(_aidl_out, out_ep2);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 58 /*ReverseList*/): {
+      ::aidl::android::aidl::tests::RecursiveList in_list;
+      ::aidl::android::aidl::tests::RecursiveList _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_list);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->ReverseList(in_list, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 59 /*ReverseIBinderArray*/): {
+      std::vector<::ndk::SpAIBinder> in_input;
+      std::vector<::ndk::SpAIBinder> out_repeated;
+      std::vector<::ndk::SpAIBinder> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->ReverseIBinderArray(in_input, &out_repeated, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_repeated);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 60 /*ReverseNullableIBinderArray*/): {
+      std::optional<std::vector<::ndk::SpAIBinder>> in_input;
+      std::optional<std::vector<::ndk::SpAIBinder>> out_repeated;
+      std::optional<std::vector<::ndk::SpAIBinder>> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_input);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_resizeVector(_aidl_in, &out_repeated);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->ReverseNullableIBinderArray(in_input, &out_repeated, &_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_writeNullableData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, out_repeated);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 61 /*GetOldNameInterface*/): {
       std::shared_ptr<::aidl::android::aidl::tests::IOldName> _aidl_return;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->GetOldNameInterface(&_aidl_return);
@@ -956,12 +1227,12 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::aidl::android::aidl::tests::IOldName::writeToParcel(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 48 /*GetNewNameInterface*/): {
+    case (FIRST_CALL_TRANSACTION + 62 /*GetNewNameInterface*/): {
       std::shared_ptr<::aidl::android::aidl::tests::INewName> _aidl_return;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->GetNewNameInterface(&_aidl_return);
@@ -970,12 +1241,12 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::aidl::android::aidl::tests::INewName::writeToParcel(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 49 /*GetCppJavaTests*/): {
+    case (FIRST_CALL_TRANSACTION + 63 /*GetCppJavaTests*/): {
       ::ndk::SpAIBinder _aidl_return;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->GetCppJavaTests(&_aidl_return);
@@ -984,12 +1255,12 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeNullableStrongBinder(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
     }
-    case (FIRST_CALL_TRANSACTION + 50 /*getBackendType*/): {
+    case (FIRST_CALL_TRANSACTION + 64 /*getBackendType*/): {
       ::aidl::android::aidl::tests::BackendType _aidl_return;
 
       ::ndk::ScopedAStatus _aidl_status = _aidl_impl->getBackendType(&_aidl_return);
@@ -998,7 +1269,7 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = AParcel_writeByte(_aidl_out, static_cast<int8_t>(_aidl_return));
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -1007,7 +1278,7 @@
   return _aidl_ret_status;
 }
 
-static AIBinder_Class* _g_aidl_clazz = ::ndk::ICInterface::defineClass(ITestService::descriptor, _aidl_onTransact);
+static AIBinder_Class* _g_aidl_android_aidl_tests_ITestService_clazz = ::ndk::ICInterface::defineClass(ITestService::descriptor, _aidl_android_aidl_tests_ITestService_onTransact);
 
 #pragma clang diagnostic pop
 BpTestService::BpTestService(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
@@ -1023,7 +1294,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeInt32(_aidl_in.get(), in_arg);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_arg);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -1046,7 +1317,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readInt32(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1130,7 +1401,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeBool(_aidl_in.get(), in_token);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_token);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -1153,7 +1424,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readBool(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1171,7 +1442,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeByte(_aidl_in.get(), in_token);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_token);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -1194,7 +1465,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readByte(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1212,7 +1483,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeChar(_aidl_in.get(), in_token);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_token);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -1235,7 +1506,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readChar(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1253,7 +1524,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeInt32(_aidl_in.get(), in_token);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_token);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -1276,7 +1547,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readInt32(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1294,7 +1565,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeInt64(_aidl_in.get(), in_token);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_token);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -1317,7 +1588,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readInt64(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1335,7 +1606,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeFloat(_aidl_in.get(), in_token);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_token);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -1358,7 +1629,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readFloat(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1376,7 +1647,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeDouble(_aidl_in.get(), in_token);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_token);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -1399,7 +1670,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readDouble(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1417,7 +1688,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_in.get(), in_token);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_token);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -1440,7 +1711,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::ndk::AParcel_readString(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1458,7 +1729,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeByte(_aidl_in.get(), static_cast<int8_t>(in_token));
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_token);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -1481,7 +1752,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readByte(_aidl_out.get(), reinterpret_cast<int8_t*>(_aidl_return));
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1499,7 +1770,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeInt32(_aidl_in.get(), static_cast<int32_t>(in_token));
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_token);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -1522,7 +1793,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readInt32(_aidl_out.get(), reinterpret_cast<int32_t*>(_aidl_return));
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1540,7 +1811,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeInt64(_aidl_in.get(), static_cast<int64_t>(in_token));
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_token);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -1563,7 +1834,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readInt64(_aidl_out.get(), reinterpret_cast<int64_t*>(_aidl_return));
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1581,7 +1852,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -1607,10 +1878,10 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_repeated);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1628,7 +1899,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -1654,10 +1925,10 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_repeated);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1675,7 +1946,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -1701,10 +1972,10 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_repeated);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1722,7 +1993,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -1748,10 +2019,10 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_repeated);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1769,7 +2040,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -1795,10 +2066,10 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_repeated);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1816,7 +2087,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -1842,10 +2113,10 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_repeated);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1863,7 +2134,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -1889,10 +2160,10 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_repeated);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1910,7 +2181,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -1936,10 +2207,10 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_repeated);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -1957,7 +2228,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeByteArray(_aidl_in.get(), reinterpret_cast<const int8_t*>(in_input.data()), in_input.size());
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -1983,10 +2254,10 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readByteArray(_aidl_out.get(), static_cast<void*>(_aidl_return), ndk::AParcel_stdVectorAllocator<int8_t>);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_readByteArray(_aidl_out.get(), static_cast<void*>(out_repeated), ndk::AParcel_stdVectorAllocator<int8_t>);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2004,7 +2275,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeInt32Array(_aidl_in.get(), reinterpret_cast<const int32_t*>(in_input.data()), in_input.size());
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -2030,10 +2301,10 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readInt32Array(_aidl_out.get(), static_cast<void*>(_aidl_return), ndk::AParcel_stdVectorAllocator<int32_t>);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_readInt32Array(_aidl_out.get(), static_cast<void*>(out_repeated), ndk::AParcel_stdVectorAllocator<int32_t>);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2051,7 +2322,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeInt64Array(_aidl_in.get(), reinterpret_cast<const int64_t*>(in_input.data()), in_input.size());
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -2077,10 +2348,10 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readInt64Array(_aidl_out.get(), static_cast<void*>(_aidl_return), ndk::AParcel_stdVectorAllocator<int64_t>);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_readInt64Array(_aidl_out.get(), static_cast<void*>(out_repeated), ndk::AParcel_stdVectorAllocator<int64_t>);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2098,7 +2369,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_in.get(), in_name);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_name);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -2121,7 +2392,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::aidl::android::aidl::tests::INamedCallback::readFromParcel(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2139,10 +2410,10 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::aidl::android::aidl::tests::INamedCallback::writeToParcel(_aidl_in.get(), in_service);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_service);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_in.get(), in_name);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_name);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -2165,7 +2436,262 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readBool(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
+  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;
+}
+::ndk::ScopedAStatus BpTestService::GetInterfaceArray(const std::vector<std::string>& in_names, std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>* _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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_names);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 27 /*GetInterfaceArray*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->GetInterfaceArray(in_names, _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_readData(_aidl_out.get(), _aidl_return);
+  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;
+}
+::ndk::ScopedAStatus BpTestService::VerifyNamesWithInterfaceArray(const std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>& in_services, const std::vector<std::string>& in_names, bool* _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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_services);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_names);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 28 /*VerifyNamesWithInterfaceArray*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->VerifyNamesWithInterfaceArray(in_services, in_names, _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_readData(_aidl_out.get(), _aidl_return);
+  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;
+}
+::ndk::ScopedAStatus BpTestService::GetNullableInterfaceArray(const std::optional<std::vector<std::optional<std::string>>>& in_names, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>* _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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_names);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 29 /*GetNullableInterfaceArray*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->GetNullableInterfaceArray(in_names, _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_readNullableData(_aidl_out.get(), _aidl_return);
+  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;
+}
+::ndk::ScopedAStatus BpTestService::VerifyNamesWithNullableInterfaceArray(const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>& in_services, const std::optional<std::vector<std::optional<std::string>>>& in_names, bool* _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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_services);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_names);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 30 /*VerifyNamesWithNullableInterfaceArray*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->VerifyNamesWithNullableInterfaceArray(in_services, in_names, _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_readData(_aidl_out.get(), _aidl_return);
+  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;
+}
+::ndk::ScopedAStatus BpTestService::GetInterfaceList(const std::optional<std::vector<std::optional<std::string>>>& in_names, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>* _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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_names);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 31 /*GetInterfaceList*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->GetInterfaceList(in_names, _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_readNullableData(_aidl_out.get(), _aidl_return);
+  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;
+}
+::ndk::ScopedAStatus BpTestService::VerifyNamesWithInterfaceList(const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>& in_services, const std::optional<std::vector<std::optional<std::string>>>& in_names, bool* _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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_services);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_names);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 32 /*VerifyNamesWithInterfaceList*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->VerifyNamesWithInterfaceList(in_services, in_names, _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_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2183,12 +2709,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 27 /*ReverseStringList*/),
+    (FIRST_CALL_TRANSACTION + 33 /*ReverseStringList*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2206,10 +2732,10 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_repeated);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2227,12 +2753,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeRequiredParcelFileDescriptor(_aidl_in.get(), in_read);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_read);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 28 /*RepeatParcelFileDescriptor*/),
+    (FIRST_CALL_TRANSACTION + 34 /*RepeatParcelFileDescriptor*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2250,7 +2776,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::ndk::AParcel_readRequiredParcelFileDescriptor(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2268,7 +2794,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -2276,7 +2802,7 @@
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 29 /*ReverseParcelFileDescriptorArray*/),
+    (FIRST_CALL_TRANSACTION + 35 /*ReverseParcelFileDescriptorArray*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2294,10 +2820,10 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_repeated);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2315,12 +2841,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeInt32(_aidl_in.get(), in_code);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_code);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 30 /*ThrowServiceException*/),
+    (FIRST_CALL_TRANSACTION + 36 /*ThrowServiceException*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2353,12 +2879,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 31 /*RepeatNullableIntArray*/),
+    (FIRST_CALL_TRANSACTION + 37 /*RepeatNullableIntArray*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2376,7 +2902,7 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2394,12 +2920,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeByteArray(_aidl_in.get(), (in_input ? reinterpret_cast<const int8_t*>(in_input->data()) : nullptr), (in_input ? in_input->size() : -1));
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 32 /*RepeatNullableByteEnumArray*/),
+    (FIRST_CALL_TRANSACTION + 38 /*RepeatNullableByteEnumArray*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2417,7 +2943,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readByteArray(_aidl_out.get(), static_cast<void*>(_aidl_return), ndk::AParcel_nullableStdVectorAllocator<int8_t>);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2435,12 +2961,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeInt32Array(_aidl_in.get(), (in_input ? reinterpret_cast<const int32_t*>(in_input->data()) : nullptr), (in_input ? in_input->size() : -1));
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 33 /*RepeatNullableIntEnumArray*/),
+    (FIRST_CALL_TRANSACTION + 39 /*RepeatNullableIntEnumArray*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2458,7 +2984,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readInt32Array(_aidl_out.get(), static_cast<void*>(_aidl_return), ndk::AParcel_nullableStdVectorAllocator<int32_t>);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2476,12 +3002,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeInt64Array(_aidl_in.get(), (in_input ? reinterpret_cast<const int64_t*>(in_input->data()) : nullptr), (in_input ? in_input->size() : -1));
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 34 /*RepeatNullableLongEnumArray*/),
+    (FIRST_CALL_TRANSACTION + 40 /*RepeatNullableLongEnumArray*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2499,7 +3025,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readInt64Array(_aidl_out.get(), static_cast<void*>(_aidl_return), ndk::AParcel_nullableStdVectorAllocator<int64_t>);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2517,12 +3043,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 35 /*RepeatNullableString*/),
+    (FIRST_CALL_TRANSACTION + 41 /*RepeatNullableString*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2540,7 +3066,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::ndk::AParcel_readString(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2548,7 +3074,7 @@
   _aidl_status_return:
   return _aidl_status;
 }
-::ndk::ScopedAStatus BpTestService::RepeatNullableStringList(const std::vector<std::string>& in_input, std::vector<std::string>* _aidl_return) {
+::ndk::ScopedAStatus BpTestService::RepeatNullableStringList(const std::optional<std::vector<std::optional<std::string>>>& in_input, std::optional<std::vector<std::optional<std::string>>>* _aidl_return) {
   binder_status_t _aidl_ret_status = STATUS_OK;
   ::ndk::ScopedAStatus _aidl_status;
   ::ndk::ScopedAParcel _aidl_in;
@@ -2558,12 +3084,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 36 /*RepeatNullableStringList*/),
+    (FIRST_CALL_TRANSACTION + 42 /*RepeatNullableStringList*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2581,7 +3107,7 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2589,7 +3115,7 @@
   _aidl_status_return:
   return _aidl_status;
 }
-::ndk::ScopedAStatus BpTestService::RepeatNullableParcelable(const std::optional<::aidl::android::aidl::tests::StructuredParcelable>& in_input, std::optional<::aidl::android::aidl::tests::StructuredParcelable>* _aidl_return) {
+::ndk::ScopedAStatus BpTestService::RepeatNullableParcelable(const std::optional<::aidl::android::aidl::tests::ITestService::Empty>& in_input, std::optional<::aidl::android::aidl::tests::ITestService::Empty>* _aidl_return) {
   binder_status_t _aidl_ret_status = STATUS_OK;
   ::ndk::ScopedAStatus _aidl_status;
   ::ndk::ScopedAParcel _aidl_in;
@@ -2599,12 +3125,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeNullableParcelable(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 37 /*RepeatNullableParcelable*/),
+    (FIRST_CALL_TRANSACTION + 43 /*RepeatNullableParcelable*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2622,7 +3148,89 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::ndk::AParcel_readNullableParcelable(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), _aidl_return);
+  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;
+}
+::ndk::ScopedAStatus BpTestService::RepeatNullableParcelableArray(const std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>& in_input, std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>* _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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 44 /*RepeatNullableParcelableArray*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->RepeatNullableParcelableArray(in_input, _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_readNullableData(_aidl_out.get(), _aidl_return);
+  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;
+}
+::ndk::ScopedAStatus BpTestService::RepeatNullableParcelableList(const std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>& in_input, std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>* _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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 45 /*RepeatNullableParcelableList*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->RepeatNullableParcelableList(in_input, _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_readNullableData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2640,12 +3248,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeRequiredStrongBinder(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 38 /*TakesAnIBinder*/),
+    (FIRST_CALL_TRANSACTION + 46 /*TakesAnIBinder*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2678,12 +3286,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeNullableStrongBinder(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 39 /*TakesANullableIBinder*/),
+    (FIRST_CALL_TRANSACTION + 47 /*TakesANullableIBinder*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2706,6 +3314,82 @@
   _aidl_status_return:
   return _aidl_status;
 }
+::ndk::ScopedAStatus BpTestService::TakesAnIBinderList(const std::vector<::ndk::SpAIBinder>& in_input) {
+  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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 48 /*TakesAnIBinderList*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->TakesAnIBinderList(in_input);
+    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_error:
+  _aidl_status.set(AStatus_fromStatus(_aidl_ret_status));
+  _aidl_status_return:
+  return _aidl_status;
+}
+::ndk::ScopedAStatus BpTestService::TakesANullableIBinderList(const std::optional<std::vector<::ndk::SpAIBinder>>& in_input) {
+  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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 49 /*TakesANullableIBinderList*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->TakesANullableIBinderList(in_input);
+    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_error:
+  _aidl_status.set(AStatus_fromStatus(_aidl_ret_status));
+  _aidl_status_return:
+  return _aidl_status;
+}
 ::ndk::ScopedAStatus BpTestService::RepeatUtf8CppString(const std::string& in_token, std::string* _aidl_return) {
   binder_status_t _aidl_ret_status = STATUS_OK;
   ::ndk::ScopedAStatus _aidl_status;
@@ -2716,12 +3400,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_in.get(), in_token);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_token);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 40 /*RepeatUtf8CppString*/),
+    (FIRST_CALL_TRANSACTION + 50 /*RepeatUtf8CppString*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2739,7 +3423,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::ndk::AParcel_readString(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2757,12 +3441,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_in.get(), in_token);
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_token);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 41 /*RepeatNullableUtf8CppString*/),
+    (FIRST_CALL_TRANSACTION + 51 /*RepeatNullableUtf8CppString*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2780,7 +3464,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::ndk::AParcel_readString(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2798,7 +3482,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -2806,7 +3490,7 @@
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 42 /*ReverseUtf8CppString*/),
+    (FIRST_CALL_TRANSACTION + 52 /*ReverseUtf8CppString*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2824,10 +3508,10 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_repeated);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2845,7 +3529,7 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
@@ -2853,7 +3537,7 @@
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 43 /*ReverseNullableUtf8CppString*/),
+    (FIRST_CALL_TRANSACTION + 53 /*ReverseNullableUtf8CppString*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2871,10 +3555,10 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_repeated);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2882,7 +3566,7 @@
   _aidl_status_return:
   return _aidl_status;
 }
-::ndk::ScopedAStatus BpTestService::ReverseUtf8CppStringList(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) {
+::ndk::ScopedAStatus BpTestService::ReverseUtf8CppStringList(const std::optional<std::vector<std::optional<std::string>>>& in_input, std::optional<std::vector<std::optional<std::string>>>* out_repeated, std::optional<std::vector<std::optional<std::string>>>* _aidl_return) {
   binder_status_t _aidl_ret_status = STATUS_OK;
   ::ndk::ScopedAStatus _aidl_status;
   ::ndk::ScopedAParcel _aidl_in;
@@ -2892,12 +3576,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), in_input);
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 44 /*ReverseUtf8CppStringList*/),
+    (FIRST_CALL_TRANSACTION + 54 /*ReverseUtf8CppStringList*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2915,10 +3599,10 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), out_repeated);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2936,12 +3620,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeBool(_aidl_in.get(), in_return_null);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_return_null);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 45 /*GetCallback*/),
+    (FIRST_CALL_TRANSACTION + 55 /*GetCallback*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -2959,7 +3643,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::aidl::android::aidl::tests::INamedCallback::readFromParcel(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -2977,12 +3661,12 @@
   AParcel_markSensitive(_aidl_in.get());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeParcelable(_aidl_in.get(), *in_parcel);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), *in_parcel);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 46 /*FillOutStructuredParcelable*/),
+    (FIRST_CALL_TRANSACTION + 56 /*FillOutStructuredParcelable*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -3000,7 +3684,183 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::ndk::AParcel_readParcelable(_aidl_out.get(), in_parcel);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), in_parcel);
+  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;
+}
+::ndk::ScopedAStatus BpTestService::RepeatExtendableParcelable(const ::aidl::android::aidl::tests::extension::ExtendableParcelable& in_ep, ::aidl::android::aidl::tests::extension::ExtendableParcelable* out_ep2) {
+  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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_ep);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 57 /*RepeatExtendableParcelable*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->RepeatExtendableParcelable(in_ep, out_ep2);
+    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_readData(_aidl_out.get(), out_ep2);
+  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;
+}
+::ndk::ScopedAStatus BpTestService::ReverseList(const ::aidl::android::aidl::tests::RecursiveList& in_list, ::aidl::android::aidl::tests::RecursiveList* _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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_list);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 58 /*ReverseList*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->ReverseList(in_list, _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_readData(_aidl_out.get(), _aidl_return);
+  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;
+}
+::ndk::ScopedAStatus BpTestService::ReverseIBinderArray(const std::vector<::ndk::SpAIBinder>& in_input, std::vector<::ndk::SpAIBinder>* out_repeated, std::vector<::ndk::SpAIBinder>* _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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 59 /*ReverseIBinderArray*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->ReverseIBinderArray(in_input, out_repeated, _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_readData(_aidl_out.get(), _aidl_return);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_repeated);
+  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;
+}
+::ndk::ScopedAStatus BpTestService::ReverseNullableIBinderArray(const std::optional<std::vector<::ndk::SpAIBinder>>& in_input, std::optional<std::vector<::ndk::SpAIBinder>>* out_repeated, std::optional<std::vector<::ndk::SpAIBinder>>* _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());
+  AParcel_markSensitive(_aidl_in.get());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_input);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeVectorSize(_aidl_in.get(), *out_repeated);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 60 /*ReverseNullableIBinderArray*/),
+    _aidl_in.getR(),
+    _aidl_out.getR(),
+    FLAG_CLEAR_BUF
+    #ifdef BINDER_STABILITY_SUPPORT
+    | FLAG_PRIVATE_LOCAL
+    #endif  // BINDER_STABILITY_SUPPORT
+    );
+  if (_aidl_ret_status == STATUS_UNKNOWN_TRANSACTION && ITestService::getDefaultImpl()) {
+    _aidl_status = ITestService::getDefaultImpl()->ReverseNullableIBinderArray(in_input, out_repeated, _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_readNullableData(_aidl_out.get(), _aidl_return);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), out_repeated);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -3020,7 +3880,7 @@
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 47 /*GetOldNameInterface*/),
+    (FIRST_CALL_TRANSACTION + 61 /*GetOldNameInterface*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -3038,7 +3898,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::aidl::android::aidl::tests::IOldName::readFromParcel(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -3058,7 +3918,7 @@
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 48 /*GetNewNameInterface*/),
+    (FIRST_CALL_TRANSACTION + 62 /*GetNewNameInterface*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -3076,7 +3936,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::aidl::android::aidl::tests::INewName::readFromParcel(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -3096,7 +3956,7 @@
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 49 /*GetCppJavaTests*/),
+    (FIRST_CALL_TRANSACTION + 63 /*GetCppJavaTests*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -3114,7 +3974,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = ::ndk::AParcel_readNullableStrongBinder(_aidl_out.get(), _aidl_return);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -3134,7 +3994,7 @@
 
   _aidl_ret_status = AIBinder_transact(
     asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 50 /*getBackendType*/),
+    (FIRST_CALL_TRANSACTION + 64 /*getBackendType*/),
     _aidl_in.getR(),
     _aidl_out.getR(),
     FLAG_CLEAR_BUF
@@ -3152,7 +4012,7 @@
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   if (!AStatus_isOk(_aidl_status.get())) goto _aidl_status_return;
-  _aidl_ret_status = AParcel_readByte(_aidl_out.get(), reinterpret_cast<int8_t*>(_aidl_return));
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -3164,7 +4024,7 @@
 BnTestService::BnTestService() {}
 BnTestService::~BnTestService() {}
 ::ndk::SpAIBinder BnTestService::createBinder() {
-  AIBinder* binder = AIBinder_new(_g_aidl_clazz, static_cast<void*>(this));
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_tests_ITestService_clazz, static_cast<void*>(this));
   #ifdef BINDER_STABILITY_SUPPORT
   AIBinder_markCompilationUnitStability(binder);
   #endif  // BINDER_STABILITY_SUPPORT
@@ -3180,7 +4040,7 @@
 const char* ITestService::STRING_TEST_CONSTANT_UTF8 = "baz";
 
 std::shared_ptr<ITestService> ITestService::fromBinder(const ::ndk::SpAIBinder& binder) {
-  if (!AIBinder_associateClass(binder.get(), _g_aidl_clazz)) { return nullptr; }
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_tests_ITestService_clazz)) { return nullptr; }
   std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
   if (interface) {
     return std::static_pointer_cast<ITestService>(interface);
@@ -3348,6 +4208,36 @@
   _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
   return _aidl_status;
 }
+::ndk::ScopedAStatus ITestServiceDefault::GetInterfaceArray(const std::vector<std::string>& /*in_names*/, std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus ITestServiceDefault::VerifyNamesWithInterfaceArray(const std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>& /*in_services*/, const std::vector<std::string>& /*in_names*/, bool* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus ITestServiceDefault::GetNullableInterfaceArray(const std::optional<std::vector<std::optional<std::string>>>& /*in_names*/, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus ITestServiceDefault::VerifyNamesWithNullableInterfaceArray(const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>& /*in_services*/, const std::optional<std::vector<std::optional<std::string>>>& /*in_names*/, bool* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus ITestServiceDefault::GetInterfaceList(const std::optional<std::vector<std::optional<std::string>>>& /*in_names*/, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus ITestServiceDefault::VerifyNamesWithInterfaceList(const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>& /*in_services*/, const std::optional<std::vector<std::optional<std::string>>>& /*in_names*/, bool* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
 ::ndk::ScopedAStatus ITestServiceDefault::ReverseStringList(const std::vector<std::string>& /*in_input*/, std::vector<std::string>* /*out_repeated*/, std::vector<std::string>* /*_aidl_return*/) {
   ::ndk::ScopedAStatus _aidl_status;
   _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
@@ -3393,12 +4283,22 @@
   _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
   return _aidl_status;
 }
-::ndk::ScopedAStatus ITestServiceDefault::RepeatNullableStringList(const std::vector<std::string>& /*in_input*/, std::vector<std::string>* /*_aidl_return*/) {
+::ndk::ScopedAStatus ITestServiceDefault::RepeatNullableStringList(const std::optional<std::vector<std::optional<std::string>>>& /*in_input*/, std::optional<std::vector<std::optional<std::string>>>* /*_aidl_return*/) {
   ::ndk::ScopedAStatus _aidl_status;
   _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
   return _aidl_status;
 }
-::ndk::ScopedAStatus ITestServiceDefault::RepeatNullableParcelable(const std::optional<::aidl::android::aidl::tests::StructuredParcelable>& /*in_input*/, std::optional<::aidl::android::aidl::tests::StructuredParcelable>* /*_aidl_return*/) {
+::ndk::ScopedAStatus ITestServiceDefault::RepeatNullableParcelable(const std::optional<::aidl::android::aidl::tests::ITestService::Empty>& /*in_input*/, std::optional<::aidl::android::aidl::tests::ITestService::Empty>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus ITestServiceDefault::RepeatNullableParcelableArray(const std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>& /*in_input*/, std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus ITestServiceDefault::RepeatNullableParcelableList(const std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>& /*in_input*/, std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>* /*_aidl_return*/) {
   ::ndk::ScopedAStatus _aidl_status;
   _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
   return _aidl_status;
@@ -3413,6 +4313,16 @@
   _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
   return _aidl_status;
 }
+::ndk::ScopedAStatus ITestServiceDefault::TakesAnIBinderList(const std::vector<::ndk::SpAIBinder>& /*in_input*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus ITestServiceDefault::TakesANullableIBinderList(const std::optional<std::vector<::ndk::SpAIBinder>>& /*in_input*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
 ::ndk::ScopedAStatus ITestServiceDefault::RepeatUtf8CppString(const std::string& /*in_token*/, std::string* /*_aidl_return*/) {
   ::ndk::ScopedAStatus _aidl_status;
   _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
@@ -3433,7 +4343,7 @@
   _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
   return _aidl_status;
 }
-::ndk::ScopedAStatus ITestServiceDefault::ReverseUtf8CppStringList(const std::vector<std::string>& /*in_input*/, std::vector<std::string>* /*out_repeated*/, std::vector<std::string>* /*_aidl_return*/) {
+::ndk::ScopedAStatus ITestServiceDefault::ReverseUtf8CppStringList(const std::optional<std::vector<std::optional<std::string>>>& /*in_input*/, std::optional<std::vector<std::optional<std::string>>>* /*out_repeated*/, std::optional<std::vector<std::optional<std::string>>>* /*_aidl_return*/) {
   ::ndk::ScopedAStatus _aidl_status;
   _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
   return _aidl_status;
@@ -3448,6 +4358,26 @@
   _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
   return _aidl_status;
 }
+::ndk::ScopedAStatus ITestServiceDefault::RepeatExtendableParcelable(const ::aidl::android::aidl::tests::extension::ExtendableParcelable& /*in_ep*/, ::aidl::android::aidl::tests::extension::ExtendableParcelable* /*out_ep2*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus ITestServiceDefault::ReverseList(const ::aidl::android::aidl::tests::RecursiveList& /*in_list*/, ::aidl::android::aidl::tests::RecursiveList* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus ITestServiceDefault::ReverseIBinderArray(const std::vector<::ndk::SpAIBinder>& /*in_input*/, std::vector<::ndk::SpAIBinder>* /*out_repeated*/, std::vector<::ndk::SpAIBinder>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus ITestServiceDefault::ReverseNullableIBinderArray(const std::optional<std::vector<::ndk::SpAIBinder>>& /*in_input*/, std::optional<std::vector<::ndk::SpAIBinder>>* /*out_repeated*/, std::optional<std::vector<::ndk::SpAIBinder>>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
 ::ndk::ScopedAStatus ITestServiceDefault::GetOldNameInterface(std::shared_ptr<::aidl::android::aidl::tests::IOldName>* /*_aidl_return*/) {
   ::ndk::ScopedAStatus _aidl_status;
   _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
@@ -3478,3 +4408,253 @@
 }  // namespace aidl
 }  // namespace android
 }  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* ITestService::Empty::descriptor = "android.aidl.tests.ITestService.Empty";
+
+binder_status_t ITestService::Empty::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+  return _aidl_ret_status;
+}
+binder_status_t ITestService::Empty::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
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* ITestService::CompilerChecks::descriptor = "android.aidl.tests.ITestService.CompilerChecks";
+
+binder_status_t ITestService::CompilerChecks::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &binder);
+  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_readNullableData(_aidl_parcel, &nullable_binder);
+  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_readData(_aidl_parcel, &binder_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_readNullableData(_aidl_parcel, &nullable_binder_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_readData(_aidl_parcel, &binder_list);
+  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_readNullableData(_aidl_parcel, &nullable_binder_list);
+  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_readData(_aidl_parcel, &pfd);
+  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_readNullableData(_aidl_parcel, &nullable_pfd);
+  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_readData(_aidl_parcel, &pfd_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_readNullableData(_aidl_parcel, &nullable_pfd_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_readData(_aidl_parcel, &pfd_list);
+  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_readNullableData(_aidl_parcel, &nullable_pfd_list);
+  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_readData(_aidl_parcel, &parcel);
+  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_readNullableData(_aidl_parcel, &nullable_parcel);
+  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_readData(_aidl_parcel, &parcel_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_readNullableData(_aidl_parcel, &nullable_parcel_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_readData(_aidl_parcel, &parcel_list);
+  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_readNullableData(_aidl_parcel, &nullable_parcel_list);
+  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 ITestService::CompilerChecks::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 = ::ndk::AParcel_writeData(_aidl_parcel, binder);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, nullable_binder);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, binder_array);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, nullable_binder_array);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, binder_list);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, nullable_binder_list);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, pfd);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, nullable_pfd);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, pfd_array);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, nullable_pfd_array);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, pfd_list);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, nullable_pfd_list);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, parcel);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, nullable_parcel);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, parcel_array);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, nullable_parcel_array);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, parcel_list);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, nullable_parcel_list);
+  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
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ITestService.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ITestService.cpp.d
similarity index 64%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ITestService.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ITestService.cpp.d
index 6014d3f..b46066a 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ITestService.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ITestService.cpp.d
@@ -1,4 +1,4 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ITestService.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/ITestService.cpp : \
   system/tools/aidl/tests/android/aidl/tests/ITestService.aidl \
   system/tools/aidl/tests/android/aidl/tests/BackendType.aidl \
   system/tools/aidl/tests/android/aidl/tests/ByteEnum.aidl \
@@ -7,4 +7,8 @@
   system/tools/aidl/tests/android/aidl/tests/IOldName.aidl \
   system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
   system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl \
-  system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl
+  system/tools/aidl/tests/android/aidl/tests/RecursiveList.aidl \
+  system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl \
+  system/tools/aidl/tests/android/aidl/tests/extension/ExtendableParcelable.aidl \
+  system/tools/aidl/tests/android/aidl/tests/ConstantExpressionEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/Union.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IntEnum.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IntEnum.cpp
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IntEnum.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IntEnum.cpp
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IntEnum.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IntEnum.cpp.d
similarity index 67%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IntEnum.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IntEnum.cpp.d
index f2b30c3..65e3972 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IntEnum.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/IntEnum.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/IntEnum.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/IntEnum.cpp : \
   system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ListOfInterfaces.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ListOfInterfaces.cpp
new file mode 100644
index 0000000..e1eda40
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ListOfInterfaces.cpp
@@ -0,0 +1,465 @@
+#include "aidl/android/aidl/tests/ListOfInterfaces.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* ListOfInterfaces::descriptor = "android.aidl.tests.ListOfInterfaces";
+
+binder_status_t ListOfInterfaces::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+  return _aidl_ret_status;
+}
+binder_status_t ListOfInterfaces::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
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+static binder_status_t _aidl_android_aidl_tests_ListOfInterfaces_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_ListOfInterfaces_IEmptyInterface_clazz = ::ndk::ICInterface::defineClass(ListOfInterfaces::IEmptyInterface::descriptor, _aidl_android_aidl_tests_ListOfInterfaces_IEmptyInterface_onTransact);
+
+ListOfInterfaces::BpEmptyInterface::BpEmptyInterface(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
+ListOfInterfaces::BpEmptyInterface::~BpEmptyInterface() {}
+
+// Source for BnEmptyInterface
+ListOfInterfaces::BnEmptyInterface::BnEmptyInterface() {}
+ListOfInterfaces::BnEmptyInterface::~BnEmptyInterface() {}
+::ndk::SpAIBinder ListOfInterfaces::BnEmptyInterface::createBinder() {
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_tests_ListOfInterfaces_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* ListOfInterfaces::IEmptyInterface::descriptor = "android.aidl.tests.ListOfInterfaces.IEmptyInterface";
+ListOfInterfaces::IEmptyInterface::IEmptyInterface() {}
+ListOfInterfaces::IEmptyInterface::~IEmptyInterface() {}
+
+
+std::shared_ptr<ListOfInterfaces::IEmptyInterface> ListOfInterfaces::IEmptyInterface::fromBinder(const ::ndk::SpAIBinder& binder) {
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_tests_ListOfInterfaces_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<ListOfInterfaces::BpEmptyInterface>(binder);
+}
+
+binder_status_t ListOfInterfaces::IEmptyInterface::writeToParcel(AParcel* parcel, const std::shared_ptr<IEmptyInterface>& instance) {
+  return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : nullptr);
+}
+binder_status_t ListOfInterfaces::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 ListOfInterfaces::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<ListOfInterfaces::IEmptyInterface>& ListOfInterfaces::IEmptyInterface::getDefaultImpl() {
+  return IEmptyInterface::default_impl;
+}
+std::shared_ptr<ListOfInterfaces::IEmptyInterface> ListOfInterfaces::IEmptyInterface::default_impl = nullptr;
+::ndk::SpAIBinder ListOfInterfaces::IEmptyInterfaceDefault::asBinder() {
+  return ::ndk::SpAIBinder();
+}
+bool ListOfInterfaces::IEmptyInterfaceDefault::isRemote() {
+  return false;
+}
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+static binder_status_t _aidl_android_aidl_tests_ListOfInterfaces_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<ListOfInterfaces::BnMyInterface> _aidl_impl = std::static_pointer_cast<ListOfInterfaces::BnMyInterface>(::ndk::ICInterface::asInterface(_aidl_binder));
+  switch (_aidl_code) {
+    case (FIRST_CALL_TRANSACTION + 0 /*methodWithInterfaces*/): {
+      std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface> in_iface;
+      std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface> in_nullable_iface;
+      std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>> in_iface_list_in;
+      std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>> out_iface_list_out;
+      std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>> in_iface_list_inout;
+      std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>> in_nullable_iface_list_in;
+      std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>> out_nullable_iface_list_out;
+      std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>> in_nullable_iface_list_inout;
+      std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>> _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_iface);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_nullable_iface);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_iface_list_in);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_iface_list_inout);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_nullable_iface_list_in);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_nullable_iface_list_inout);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->methodWithInterfaces(in_iface, in_nullable_iface, in_iface_list_in, &out_iface_list_out, &in_iface_list_inout, in_nullable_iface_list_in, &out_nullable_iface_list_out, &in_nullable_iface_list_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_writeNullableData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, out_iface_list_out);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, in_iface_list_inout);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, out_nullable_iface_list_out);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, in_nullable_iface_list_inout);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+  }
+  return _aidl_ret_status;
+}
+
+static AIBinder_Class* _g_aidl_android_aidl_tests_ListOfInterfaces_IMyInterface_clazz = ::ndk::ICInterface::defineClass(ListOfInterfaces::IMyInterface::descriptor, _aidl_android_aidl_tests_ListOfInterfaces_IMyInterface_onTransact);
+
+ListOfInterfaces::BpMyInterface::BpMyInterface(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
+ListOfInterfaces::BpMyInterface::~BpMyInterface() {}
+
+::ndk::ScopedAStatus ListOfInterfaces::BpMyInterface::methodWithInterfaces(const std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>& in_iface, const std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>& in_nullable_iface, const std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>& in_iface_list_in, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* out_iface_list_out, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* in_iface_list_inout, const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>& in_nullable_iface_list_in, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* out_nullable_iface_list_out, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* in_nullable_iface_list_inout, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_iface);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_nullable_iface);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_iface_list_in);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), *in_iface_list_inout);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_nullable_iface_list_in);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), *in_nullable_iface_list_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_list_in, out_iface_list_out, in_iface_list_inout, in_nullable_iface_list_in, out_nullable_iface_list_out, in_nullable_iface_list_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_readNullableData(_aidl_out.get(), _aidl_return);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), out_iface_list_out);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), in_iface_list_inout);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), out_nullable_iface_list_out);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), in_nullable_iface_list_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
+ListOfInterfaces::BnMyInterface::BnMyInterface() {}
+ListOfInterfaces::BnMyInterface::~BnMyInterface() {}
+::ndk::SpAIBinder ListOfInterfaces::BnMyInterface::createBinder() {
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_tests_ListOfInterfaces_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* ListOfInterfaces::IMyInterface::descriptor = "android.aidl.tests.ListOfInterfaces.IMyInterface";
+ListOfInterfaces::IMyInterface::IMyInterface() {}
+ListOfInterfaces::IMyInterface::~IMyInterface() {}
+
+
+std::shared_ptr<ListOfInterfaces::IMyInterface> ListOfInterfaces::IMyInterface::fromBinder(const ::ndk::SpAIBinder& binder) {
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_tests_ListOfInterfaces_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<ListOfInterfaces::BpMyInterface>(binder);
+}
+
+binder_status_t ListOfInterfaces::IMyInterface::writeToParcel(AParcel* parcel, const std::shared_ptr<IMyInterface>& instance) {
+  return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : nullptr);
+}
+binder_status_t ListOfInterfaces::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 ListOfInterfaces::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<ListOfInterfaces::IMyInterface>& ListOfInterfaces::IMyInterface::getDefaultImpl() {
+  return IMyInterface::default_impl;
+}
+std::shared_ptr<ListOfInterfaces::IMyInterface> ListOfInterfaces::IMyInterface::default_impl = nullptr;
+::ndk::ScopedAStatus ListOfInterfaces::IMyInterfaceDefault::methodWithInterfaces(const std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>& /*in_iface*/, const std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>& /*in_nullable_iface*/, const std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>& /*in_iface_list_in*/, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* /*out_iface_list_out*/, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* /*in_iface_list_inout*/, const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>& /*in_nullable_iface_list_in*/, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* /*out_nullable_iface_list_out*/, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* /*in_nullable_iface_list_inout*/, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::SpAIBinder ListOfInterfaces::IMyInterfaceDefault::asBinder() {
+  return ::ndk::SpAIBinder();
+}
+bool ListOfInterfaces::IMyInterfaceDefault::isRemote() {
+  return false;
+}
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* ListOfInterfaces::MyParcelable::descriptor = "android.aidl.tests.ListOfInterfaces.MyParcelable";
+
+binder_status_t ListOfInterfaces::MyParcelable::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_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 = ::ndk::AParcel_readNullableData(_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_readData(_aidl_parcel, &iface_list);
+  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_readNullableData(_aidl_parcel, &nullable_iface_list);
+  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 ListOfInterfaces::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 = ::ndk::AParcel_writeData(_aidl_parcel, iface);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, nullable_iface);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, iface_list);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, nullable_iface_list);
+  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
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* ListOfInterfaces::MyUnion::descriptor = "android.aidl.tests.ListOfInterfaces.MyUnion";
+
+binder_status_t ListOfInterfaces::MyUnion::readFromParcel(const AParcel* _parcel) {
+  binder_status_t _aidl_ret_status;
+  int32_t _aidl_tag;
+  if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_tag)) != STATUS_OK) return _aidl_ret_status;
+  switch (_aidl_tag) {
+  case iface: {
+    std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface> _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::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::ListOfInterfaces::IEmptyInterface> _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readNullableData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>) {
+      set<nullable_iface>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<nullable_iface>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  case iface_list: {
+    std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>> _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_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::ListOfInterfaces::IEmptyInterface>>>) {
+      set<iface_list>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<iface_list>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  case nullable_iface_list: {
+    std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>> _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readNullableData(_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::ListOfInterfaces::IEmptyInterface>>>>) {
+      set<nullable_iface_list>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<nullable_iface_list>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  }
+  return STATUS_BAD_VALUE;
+}
+binder_status_t ListOfInterfaces::MyUnion::writeToParcel(AParcel* _parcel) const {
+  binder_status_t _aidl_ret_status = ::ndk::AParcel_writeData(_parcel, getTag());
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+  switch (getTag()) {
+  case iface: return ::ndk::AParcel_writeData(_parcel, get<iface>());
+  case nullable_iface: return ::ndk::AParcel_writeNullableData(_parcel, get<nullable_iface>());
+  case iface_list: return ::ndk::AParcel_writeData(_parcel, get<iface_list>());
+  case nullable_iface_list: return ::ndk::AParcel_writeNullableData(_parcel, get<nullable_iface_list>());
+  }
+  __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/ListOfInterfaces.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ListOfInterfaces.cpp.d
new file mode 100644
index 0000000..29da8d1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ListOfInterfaces.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/ListOfInterfaces.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/ListOfInterfaces.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/LongEnum.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/LongEnum.cpp
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/LongEnum.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/LongEnum.cpp
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/LongEnum.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/LongEnum.cpp.d
similarity index 67%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/LongEnum.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/LongEnum.cpp.d
index f07b41d..e26849e 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/LongEnum.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/LongEnum.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/LongEnum.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/LongEnum.cpp : \
   system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/OtherParcelableForToString.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/OtherParcelableForToString.cpp
new file mode 100644
index 0000000..d082385
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/OtherParcelableForToString.cpp
@@ -0,0 +1,49 @@
+#include "aidl/android/aidl/tests/OtherParcelableForToString.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* OtherParcelableForToString::descriptor = "android.aidl.tests.OtherParcelableForToString";
+
+binder_status_t OtherParcelableForToString::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &field);
+  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 OtherParcelableForToString::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 = ::ndk::AParcel_writeData(_aidl_parcel, field);
+  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
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/OtherParcelableForToString.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/OtherParcelableForToString.cpp.d
similarity index 64%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/OtherParcelableForToString.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/OtherParcelableForToString.cpp.d
index 53179cf..d8682ff 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/OtherParcelableForToString.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/OtherParcelableForToString.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/OtherParcelableForToString.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/OtherParcelableForToString.cpp : \
   system/tools/aidl/tests/android/aidl/tests/OtherParcelableForToString.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ParcelableForToString.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ParcelableForToString.cpp
new file mode 100644
index 0000000..8cac145
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ParcelableForToString.cpp
@@ -0,0 +1,269 @@
+#include "aidl/android/aidl/tests/ParcelableForToString.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* ParcelableForToString::descriptor = "android.aidl.tests.ParcelableForToString";
+
+binder_status_t ParcelableForToString::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &intValue);
+  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_readData(_aidl_parcel, &intArray);
+  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_readData(_aidl_parcel, &longValue);
+  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_readData(_aidl_parcel, &longArray);
+  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_readData(_aidl_parcel, &doubleValue);
+  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_readData(_aidl_parcel, &doubleArray);
+  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_readData(_aidl_parcel, &floatValue);
+  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_readData(_aidl_parcel, &floatArray);
+  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_readData(_aidl_parcel, &byteValue);
+  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_readData(_aidl_parcel, &byteArray);
+  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_readData(_aidl_parcel, &booleanValue);
+  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_readData(_aidl_parcel, &booleanArray);
+  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_readData(_aidl_parcel, &stringValue);
+  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_readData(_aidl_parcel, &stringArray);
+  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_readData(_aidl_parcel, &stringList);
+  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_readData(_aidl_parcel, &parcelableValue);
+  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_readData(_aidl_parcel, &parcelableArray);
+  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_readData(_aidl_parcel, &enumValue);
+  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_readData(_aidl_parcel, &enumArray);
+  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_readData(_aidl_parcel, &nullArray);
+  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_readData(_aidl_parcel, &nullList);
+  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_readData(_aidl_parcel, &parcelableGeneric);
+  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_readData(_aidl_parcel, &unionValue);
+  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 ParcelableForToString::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 = ::ndk::AParcel_writeData(_aidl_parcel, intValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, intArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, longValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, longArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, doubleValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, doubleArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, floatValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, floatArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, byteValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, byteArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, booleanValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, booleanArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, stringValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, stringArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, stringList);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, parcelableValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, parcelableArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, enumValue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, enumArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, nullArray);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, nullList);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, parcelableGeneric);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, unionValue);
+  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
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ParcelableForToString.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ParcelableForToString.cpp.d
new file mode 100644
index 0000000..1d654df
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/ParcelableForToString.cpp.d
@@ -0,0 +1,10 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/ParcelableForToString.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/ParcelableForToString.aidl \
+  system/tools/aidl/tests/android/aidl/tests/GenericStructuredParcelable.aidl \
+  system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/OtherParcelableForToString.aidl \
+  system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl \
+  system/tools/aidl/tests/android/aidl/tests/Union.aidl \
+  system/tools/aidl/tests/android/aidl/tests/ByteEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/ConstantExpressionEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/RecursiveList.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/RecursiveList.cpp
new file mode 100644
index 0000000..a4a428e
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/RecursiveList.cpp
@@ -0,0 +1,59 @@
+#include "aidl/android/aidl/tests/RecursiveList.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* RecursiveList::descriptor = "android.aidl.tests.RecursiveList";
+
+binder_status_t RecursiveList::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &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 = ::ndk::AParcel_readNullableData(_aidl_parcel, &next);
+  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 RecursiveList::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 = ::ndk::AParcel_writeData(_aidl_parcel, value);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, next);
+  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
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/RecursiveList.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/RecursiveList.cpp.d
new file mode 100644
index 0000000..d413961
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/RecursiveList.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/RecursiveList.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/RecursiveList.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/StructuredParcelable.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/StructuredParcelable.cpp
new file mode 100644
index 0000000..8199e72
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/StructuredParcelable.cpp
@@ -0,0 +1,624 @@
+#include "aidl/android/aidl/tests/StructuredParcelable.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* StructuredParcelable::descriptor = "android.aidl.tests.StructuredParcelable";
+
+binder_status_t StructuredParcelable::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &shouldContainThreeFs);
+  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_readData(_aidl_parcel, &f);
+  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_readData(_aidl_parcel, &shouldBeJerry);
+  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_readData(_aidl_parcel, &shouldBeByteBar);
+  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_readData(_aidl_parcel, &shouldBeIntBar);
+  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_readData(_aidl_parcel, &shouldBeLongBar);
+  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_readData(_aidl_parcel, &shouldContainTwoByteFoos);
+  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_readData(_aidl_parcel, &shouldContainTwoIntFoos);
+  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_readData(_aidl_parcel, &shouldContainTwoLongFoos);
+  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_readData(_aidl_parcel, &stringDefaultsToFoo);
+  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_readData(_aidl_parcel, &byteDefaultsToFour);
+  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_readData(_aidl_parcel, &intDefaultsToFive);
+  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_readData(_aidl_parcel, &longDefaultsToNegativeSeven);
+  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_readData(_aidl_parcel, &booleanDefaultsToTrue);
+  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_readData(_aidl_parcel, &charDefaultsToC);
+  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_readData(_aidl_parcel, &floatDefaultsToPi);
+  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_readData(_aidl_parcel, &doubleWithDefault);
+  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_readData(_aidl_parcel, &arrayDefaultsTo123);
+  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_readData(_aidl_parcel, &arrayDefaultsToEmpty);
+  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_readData(_aidl_parcel, &boolDefault);
+  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_readData(_aidl_parcel, &byteDefault);
+  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_readData(_aidl_parcel, &intDefault);
+  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_readData(_aidl_parcel, &longDefault);
+  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_readData(_aidl_parcel, &floatDefault);
+  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_readData(_aidl_parcel, &doubleDefault);
+  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_readData(_aidl_parcel, &checkDoubleFromFloat);
+  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_readData(_aidl_parcel, &checkStringArray1);
+  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_readData(_aidl_parcel, &checkStringArray2);
+  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_readData(_aidl_parcel, &int32_min);
+  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_readData(_aidl_parcel, &int32_max);
+  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_readData(_aidl_parcel, &int64_max);
+  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_readData(_aidl_parcel, &hexInt32_neg_1);
+  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_readNullableData(_aidl_parcel, &ibinder);
+  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_readData(_aidl_parcel, &empty);
+  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_readData(_aidl_parcel, &int8_1);
+  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_readData(_aidl_parcel, &int32_1);
+  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_readData(_aidl_parcel, &int64_1);
+  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_readData(_aidl_parcel, &hexInt32_pos_1);
+  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_readData(_aidl_parcel, &hexInt64_pos_1);
+  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_readData(_aidl_parcel, &const_exprs_1);
+  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_readData(_aidl_parcel, &const_exprs_2);
+  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_readData(_aidl_parcel, &const_exprs_3);
+  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_readData(_aidl_parcel, &const_exprs_4);
+  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_readData(_aidl_parcel, &const_exprs_5);
+  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_readData(_aidl_parcel, &const_exprs_6);
+  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_readData(_aidl_parcel, &const_exprs_7);
+  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_readData(_aidl_parcel, &const_exprs_8);
+  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_readData(_aidl_parcel, &const_exprs_9);
+  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_readData(_aidl_parcel, &const_exprs_10);
+  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_readData(_aidl_parcel, &addString1);
+  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_readData(_aidl_parcel, &addString2);
+  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_readData(_aidl_parcel, &shouldSetBit0AndBit2);
+  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_readNullableData(_aidl_parcel, &u);
+  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_readNullableData(_aidl_parcel, &shouldBeConstS1);
+  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_readData(_aidl_parcel, &defaultWithFoo);
+  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 StructuredParcelable::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 = ::ndk::AParcel_writeData(_aidl_parcel, shouldContainThreeFs);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, f);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, shouldBeJerry);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, shouldBeByteBar);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, shouldBeIntBar);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, shouldBeLongBar);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, shouldContainTwoByteFoos);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, shouldContainTwoIntFoos);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, shouldContainTwoLongFoos);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, stringDefaultsToFoo);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, byteDefaultsToFour);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, intDefaultsToFive);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, longDefaultsToNegativeSeven);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, booleanDefaultsToTrue);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, charDefaultsToC);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, floatDefaultsToPi);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, doubleWithDefault);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, arrayDefaultsTo123);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, arrayDefaultsToEmpty);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, boolDefault);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, byteDefault);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, intDefault);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, longDefault);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, floatDefault);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, doubleDefault);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, checkDoubleFromFloat);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, checkStringArray1);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, checkStringArray2);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, int32_min);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, int32_max);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, int64_max);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, hexInt32_neg_1);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, ibinder);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, empty);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, int8_1);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, int32_1);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, int64_1);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, hexInt32_pos_1);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, hexInt64_pos_1);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, const_exprs_1);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, const_exprs_2);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, const_exprs_3);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, const_exprs_4);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, const_exprs_5);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, const_exprs_6);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, const_exprs_7);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, const_exprs_8);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, const_exprs_9);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, const_exprs_10);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, addString1);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, addString2);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, shouldSetBit0AndBit2);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, u);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_parcel, shouldBeConstS1);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, defaultWithFoo);
+  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
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+const char* StructuredParcelable::Empty::descriptor = "android.aidl.tests.StructuredParcelable.Empty";
+
+binder_status_t StructuredParcelable::Empty::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+  return _aidl_ret_status;
+}
+binder_status_t StructuredParcelable::Empty::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
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/StructuredParcelable.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/StructuredParcelable.cpp.d
similarity index 86%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/StructuredParcelable.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/StructuredParcelable.cpp.d
index 1b902e6..7e7bdf7 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/StructuredParcelable.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/StructuredParcelable.cpp.d
@@ -1,4 +1,4 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/StructuredParcelable.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/StructuredParcelable.cpp : \
   system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl \
   system/tools/aidl/tests/android/aidl/tests/ByteEnum.aidl \
   system/tools/aidl/tests/android/aidl/tests/ConstantExpressionEnum.aidl \
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/Union.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/Union.cpp
similarity index 64%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/Union.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/Union.cpp
index a838fe0..6941c03 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/Union.cpp
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/Union.cpp
@@ -12,11 +12,11 @@
 binder_status_t Union::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;
+  if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_tag)) != STATUS_OK) return _aidl_ret_status;
   switch (_aidl_tag) {
   case ns: {
     std::vector<int32_t> _aidl_value;
-    if ((_aidl_ret_status = ::ndk::AParcel_readVector(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<std::vector<int32_t>>) {
       set<ns>(_aidl_value);
     } else {
@@ -26,7 +26,7 @@
     return STATUS_OK; }
   case n: {
     int32_t _aidl_value;
-    if ((_aidl_ret_status = AParcel_readInt32(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<int32_t>) {
       set<n>(_aidl_value);
     } else {
@@ -36,7 +36,7 @@
     return STATUS_OK; }
   case m: {
     int32_t _aidl_value;
-    if ((_aidl_ret_status = AParcel_readInt32(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<int32_t>) {
       set<m>(_aidl_value);
     } else {
@@ -46,7 +46,7 @@
     return STATUS_OK; }
   case s: {
     std::string _aidl_value;
-    if ((_aidl_ret_status = ::ndk::AParcel_readString(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<std::string>) {
       set<s>(_aidl_value);
     } else {
@@ -56,7 +56,7 @@
     return STATUS_OK; }
   case ibinder: {
     ::ndk::SpAIBinder _aidl_value;
-    if ((_aidl_ret_status = ::ndk::AParcel_readNullableStrongBinder(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readNullableData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<::ndk::SpAIBinder>) {
       set<ibinder>(_aidl_value);
     } else {
@@ -66,7 +66,7 @@
     return STATUS_OK; }
   case ss: {
     std::vector<std::string> _aidl_value;
-    if ((_aidl_ret_status = ::ndk::AParcel_readVector(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<std::vector<std::string>>) {
       set<ss>(_aidl_value);
     } else {
@@ -76,7 +76,7 @@
     return STATUS_OK; }
   case be: {
     ::aidl::android::aidl::tests::ByteEnum _aidl_value;
-    if ((_aidl_ret_status = AParcel_readByte(_parcel, reinterpret_cast<int8_t*>(&_aidl_value))) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<::aidl::android::aidl::tests::ByteEnum>) {
       set<be>(_aidl_value);
     } else {
@@ -88,16 +88,16 @@
   return STATUS_BAD_VALUE;
 }
 binder_status_t Union::writeToParcel(AParcel* _parcel) const {
-  binder_status_t _aidl_ret_status = AParcel_writeInt32(_parcel, getTag());
+  binder_status_t _aidl_ret_status = ::ndk::AParcel_writeData(_parcel, getTag());
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
   switch (getTag()) {
-  case ns: return ::ndk::AParcel_writeVector(_parcel, get<ns>());
-  case n: return AParcel_writeInt32(_parcel, get<n>());
-  case m: return AParcel_writeInt32(_parcel, get<m>());
-  case s: return ::ndk::AParcel_writeString(_parcel, get<s>());
-  case ibinder: return ::ndk::AParcel_writeNullableStrongBinder(_parcel, get<ibinder>());
-  case ss: return ::ndk::AParcel_writeVector(_parcel, get<ss>());
-  case be: return AParcel_writeByte(_parcel, static_cast<int8_t>(get<be>()));
+  case ns: return ::ndk::AParcel_writeData(_parcel, get<ns>());
+  case n: return ::ndk::AParcel_writeData(_parcel, get<n>());
+  case m: return ::ndk::AParcel_writeData(_parcel, get<m>());
+  case s: return ::ndk::AParcel_writeData(_parcel, get<s>());
+  case ibinder: return ::ndk::AParcel_writeNullableData(_parcel, get<ibinder>());
+  case ss: return ::ndk::AParcel_writeData(_parcel, get<ss>());
+  case be: return ::ndk::AParcel_writeData(_parcel, get<be>());
   }
   __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
 }
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/Union.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/Union.cpp.d
similarity index 76%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/Union.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/Union.cpp.d
index 1bddc90..2892180 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/Union.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/Union.cpp.d
@@ -1,3 +1,3 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/Union.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/Union.cpp : \
   system/tools/aidl/tests/android/aidl/tests/Union.aidl \
   system/tools/aidl/tests/android/aidl/tests/ByteEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/UnionWithFd.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/UnionWithFd.cpp
similarity index 69%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/UnionWithFd.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/UnionWithFd.cpp
index 153cc06..223d64c 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/UnionWithFd.cpp
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/UnionWithFd.cpp
@@ -11,11 +11,11 @@
 binder_status_t UnionWithFd::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;
+  if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_tag)) != STATUS_OK) return _aidl_ret_status;
   switch (_aidl_tag) {
   case num: {
     int32_t _aidl_value;
-    if ((_aidl_ret_status = AParcel_readInt32(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<int32_t>) {
       set<num>(_aidl_value);
     } else {
@@ -25,7 +25,7 @@
     return STATUS_OK; }
   case pfd: {
     ::ndk::ScopedFileDescriptor _aidl_value;
-    if ((_aidl_ret_status = ::ndk::AParcel_readRequiredParcelFileDescriptor(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<::ndk::ScopedFileDescriptor>) {
       set<pfd>(_aidl_value);
     } else {
@@ -37,11 +37,11 @@
   return STATUS_BAD_VALUE;
 }
 binder_status_t UnionWithFd::writeToParcel(AParcel* _parcel) const {
-  binder_status_t _aidl_ret_status = AParcel_writeInt32(_parcel, getTag());
+  binder_status_t _aidl_ret_status = ::ndk::AParcel_writeData(_parcel, getTag());
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
   switch (getTag()) {
-  case num: return AParcel_writeInt32(_parcel, get<num>());
-  case pfd: return ::ndk::AParcel_writeRequiredParcelFileDescriptor(_parcel, get<pfd>());
+  case num: return ::ndk::AParcel_writeData(_parcel, get<num>());
+  case pfd: return ::ndk::AParcel_writeData(_parcel, get<pfd>());
   }
   __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
 }
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/UnionWithFd.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/UnionWithFd.cpp.d
similarity index 67%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/UnionWithFd.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/UnionWithFd.cpp.d
index 5247a74..a696bc6 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/UnionWithFd.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/UnionWithFd.cpp.d
@@ -1,2 +1,2 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/UnionWithFd.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/UnionWithFd.cpp : \
   system/tools/aidl/tests/android/aidl/tests/UnionWithFd.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/ExtendableParcelable.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/ExtendableParcelable.cpp
new file mode 100644
index 0000000..b5803bb
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/ExtendableParcelable.cpp
@@ -0,0 +1,91 @@
+#include "aidl/android/aidl/tests/extension/ExtendableParcelable.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+const char* ExtendableParcelable::descriptor = "android.aidl.tests.extension.ExtendableParcelable";
+
+binder_status_t ExtendableParcelable::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &a);
+  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_readData(_aidl_parcel, &b);
+  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_readData(_aidl_parcel, &ext);
+  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_readData(_aidl_parcel, &c);
+  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_readData(_aidl_parcel, &ext2);
+  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 ExtendableParcelable::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 = ::ndk::AParcel_writeData(_aidl_parcel, a);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, b);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, ext);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, c);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, ext2);
+  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 extension
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/ExtendableParcelable.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/ExtendableParcelable.cpp.d
new file mode 100644
index 0000000..92a1e5e
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/ExtendableParcelable.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/ExtendableParcelable.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/extension/ExtendableParcelable.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt.cpp
new file mode 100644
index 0000000..727e519
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt.cpp
@@ -0,0 +1,61 @@
+#include "aidl/android/aidl/tests/extension/MyExt.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+const char* MyExt::descriptor = "android.aidl.tests.extension.MyExt";
+
+binder_status_t MyExt::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &a);
+  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_readData(_aidl_parcel, &b);
+  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 MyExt::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 = ::ndk::AParcel_writeData(_aidl_parcel, a);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, b);
+  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 extension
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt.cpp.d
new file mode 100644
index 0000000..c15eb09
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExt.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt2.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt2.cpp
new file mode 100644
index 0000000..9f33357
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt2.cpp
@@ -0,0 +1,71 @@
+#include "aidl/android/aidl/tests/extension/MyExt2.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+const char* MyExt2::descriptor = "android.aidl.tests.extension.MyExt2";
+
+binder_status_t MyExt2::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &a);
+  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_readData(_aidl_parcel, &b);
+  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_readData(_aidl_parcel, &c);
+  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 MyExt2::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 = ::ndk::AParcel_writeData(_aidl_parcel, a);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, b);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, c);
+  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 extension
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt2.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt2.cpp.d
new file mode 100644
index 0000000..4d6062c
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt2.cpp.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExt2.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExt2.aidl \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExt.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExtLike.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExtLike.cpp
new file mode 100644
index 0000000..0d759ec
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExtLike.cpp
@@ -0,0 +1,61 @@
+#include "aidl/android/aidl/tests/extension/MyExtLike.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+const char* MyExtLike::descriptor = "android.aidl.tests.extension.MyExtLike";
+
+binder_status_t MyExtLike::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &a);
+  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_readData(_aidl_parcel, &b);
+  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 MyExtLike::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 = ::ndk::AParcel_writeData(_aidl_parcel, a);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, b);
+  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 extension
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExtLike.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExtLike.cpp.d
new file mode 100644
index 0000000..512292d
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExtLike.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/extension/MyExtLike.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExtLike.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/DeeplyNested.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/DeeplyNested.cpp
new file mode 100644
index 0000000..5c243a9
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/DeeplyNested.cpp
@@ -0,0 +1,199 @@
+#include "aidl/android/aidl/tests/nested/DeeplyNested.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+const char* DeeplyNested::descriptor = "android.aidl.tests.nested.DeeplyNested";
+
+binder_status_t DeeplyNested::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+  return _aidl_ret_status;
+}
+binder_status_t DeeplyNested::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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+const char* DeeplyNested::A::descriptor = "android.aidl.tests.nested.DeeplyNested.A";
+
+binder_status_t DeeplyNested::A::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &e);
+  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 DeeplyNested::A::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 = ::ndk::AParcel_writeData(_aidl_parcel, e);
+  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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+const char* DeeplyNested::B::descriptor = "android.aidl.tests.nested.DeeplyNested.B";
+
+binder_status_t DeeplyNested::B::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+  return _aidl_ret_status;
+}
+binder_status_t DeeplyNested::B::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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+const char* DeeplyNested::B::C::descriptor = "android.aidl.tests.nested.DeeplyNested.B.C";
+
+binder_status_t DeeplyNested::B::C::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+  return _aidl_ret_status;
+}
+binder_status_t DeeplyNested::B::C::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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+const char* DeeplyNested::B::C::D::descriptor = "android.aidl.tests.nested.DeeplyNested.B.C.D";
+
+binder_status_t DeeplyNested::B::C::D::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
+  return _aidl_ret_status;
+}
+binder_status_t DeeplyNested::B::C::D::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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/DeeplyNested.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/DeeplyNested.cpp.d
new file mode 100644
index 0000000..5965970
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/DeeplyNested.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/DeeplyNested.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/nested/DeeplyNested.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/INestedService.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/INestedService.cpp
new file mode 100644
index 0000000..7b87070
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/INestedService.cpp
@@ -0,0 +1,397 @@
+#include "aidl/android/aidl/tests/nested/INestedService.h"
+
+#include <android/binder_parcel_utils.h>
+#include <aidl/android/aidl/tests/nested/BnNestedService.h>
+#include <aidl/android/aidl/tests/nested/BpNestedService.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+static binder_status_t _aidl_android_aidl_tests_nested_INestedService_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<BnNestedService> _aidl_impl = std::static_pointer_cast<BnNestedService>(::ndk::ICInterface::asInterface(_aidl_binder));
+  switch (_aidl_code) {
+    case (FIRST_CALL_TRANSACTION + 0 /*flipStatus*/): {
+      ::aidl::android::aidl::tests::nested::ParcelableWithNested in_p;
+      ::aidl::android::aidl::tests::nested::INestedService::Result _aidl_return;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_p);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->flipStatus(in_p, &_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_writeData(_aidl_out, _aidl_return);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 1 /*flipStatusWithCallback*/): {
+      ::aidl::android::aidl::tests::nested::ParcelableWithNested::Status in_status;
+      std::shared_ptr<::aidl::android::aidl::tests::nested::INestedService::ICallback> in_cb;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_status);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_cb);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->flipStatusWithCallback(in_status, in_cb);
+      _aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      if (!AStatus_isOk(_aidl_status.get())) break;
+
+      break;
+    }
+  }
+  return _aidl_ret_status;
+}
+
+static AIBinder_Class* _g_aidl_android_aidl_tests_nested_INestedService_clazz = ::ndk::ICInterface::defineClass(INestedService::descriptor, _aidl_android_aidl_tests_nested_INestedService_onTransact);
+
+BpNestedService::BpNestedService(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
+BpNestedService::~BpNestedService() {}
+
+::ndk::ScopedAStatus BpNestedService::flipStatus(const ::aidl::android::aidl::tests::nested::ParcelableWithNested& in_p, ::aidl::android::aidl::tests::nested::INestedService::Result* _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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_p);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 0 /*flipStatus*/),
+    _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 && INestedService::getDefaultImpl()) {
+    _aidl_status = INestedService::getDefaultImpl()->flipStatus(in_p, _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_readData(_aidl_out.get(), _aidl_return);
+  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;
+}
+::ndk::ScopedAStatus BpNestedService::flipStatusWithCallback(::aidl::android::aidl::tests::nested::ParcelableWithNested::Status in_status, const std::shared_ptr<::aidl::android::aidl::tests::nested::INestedService::ICallback>& in_cb) {
+  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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_status);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_cb);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 1 /*flipStatusWithCallback*/),
+    _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 && INestedService::getDefaultImpl()) {
+    _aidl_status = INestedService::getDefaultImpl()->flipStatusWithCallback(in_status, in_cb);
+    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_error:
+  _aidl_status.set(AStatus_fromStatus(_aidl_ret_status));
+  _aidl_status_return:
+  return _aidl_status;
+}
+// Source for BnNestedService
+BnNestedService::BnNestedService() {}
+BnNestedService::~BnNestedService() {}
+::ndk::SpAIBinder BnNestedService::createBinder() {
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_tests_nested_INestedService_clazz, static_cast<void*>(this));
+  #ifdef BINDER_STABILITY_SUPPORT
+  AIBinder_markCompilationUnitStability(binder);
+  #endif  // BINDER_STABILITY_SUPPORT
+  return ::ndk::SpAIBinder(binder);
+}
+// Source for INestedService
+const char* INestedService::descriptor = "android.aidl.tests.nested.INestedService";
+INestedService::INestedService() {}
+INestedService::~INestedService() {}
+
+
+std::shared_ptr<INestedService> INestedService::fromBinder(const ::ndk::SpAIBinder& binder) {
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_tests_nested_INestedService_clazz)) { return nullptr; }
+  std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
+  if (interface) {
+    return std::static_pointer_cast<INestedService>(interface);
+  }
+  return ::ndk::SharedRefBase::make<BpNestedService>(binder);
+}
+
+binder_status_t INestedService::writeToParcel(AParcel* parcel, const std::shared_ptr<INestedService>& instance) {
+  return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : nullptr);
+}
+binder_status_t INestedService::readFromParcel(const AParcel* parcel, std::shared_ptr<INestedService>* instance) {
+  ::ndk::SpAIBinder binder;
+  binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());
+  if (status != STATUS_OK) return status;
+  *instance = INestedService::fromBinder(binder);
+  return STATUS_OK;
+}
+bool INestedService::setDefaultImpl(const std::shared_ptr<INestedService>& 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(!INestedService::default_impl);
+  if (impl) {
+    INestedService::default_impl = impl;
+    return true;
+  }
+  return false;
+}
+const std::shared_ptr<INestedService>& INestedService::getDefaultImpl() {
+  return INestedService::default_impl;
+}
+std::shared_ptr<INestedService> INestedService::default_impl = nullptr;
+::ndk::ScopedAStatus INestedServiceDefault::flipStatus(const ::aidl::android::aidl::tests::nested::ParcelableWithNested& /*in_p*/, ::aidl::android::aidl::tests::nested::INestedService::Result* /*_aidl_return*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus INestedServiceDefault::flipStatusWithCallback(::aidl::android::aidl::tests::nested::ParcelableWithNested::Status /*in_status*/, const std::shared_ptr<::aidl::android::aidl::tests::nested::INestedService::ICallback>& /*in_cb*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::SpAIBinder INestedServiceDefault::asBinder() {
+  return ::ndk::SpAIBinder();
+}
+bool INestedServiceDefault::isRemote() {
+  return false;
+}
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+const char* INestedService::Result::descriptor = "android.aidl.tests.nested.INestedService.Result";
+
+binder_status_t INestedService::Result::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &status);
+  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 INestedService::Result::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 = ::ndk::AParcel_writeData(_aidl_parcel, status);
+  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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+static binder_status_t _aidl_android_aidl_tests_nested_INestedService_ICallback_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<INestedService::BnCallback> _aidl_impl = std::static_pointer_cast<INestedService::BnCallback>(::ndk::ICInterface::asInterface(_aidl_binder));
+  switch (_aidl_code) {
+    case (FIRST_CALL_TRANSACTION + 0 /*done*/): {
+      ::aidl::android::aidl::tests::nested::ParcelableWithNested::Status in_status;
+
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_status);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->done(in_status);
+      _aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      if (!AStatus_isOk(_aidl_status.get())) break;
+
+      break;
+    }
+  }
+  return _aidl_ret_status;
+}
+
+static AIBinder_Class* _g_aidl_android_aidl_tests_nested_INestedService_ICallback_clazz = ::ndk::ICInterface::defineClass(INestedService::ICallback::descriptor, _aidl_android_aidl_tests_nested_INestedService_ICallback_onTransact);
+
+INestedService::BpCallback::BpCallback(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
+INestedService::BpCallback::~BpCallback() {}
+
+::ndk::ScopedAStatus INestedService::BpCallback::done(::aidl::android::aidl::tests::nested::ParcelableWithNested::Status in_status) {
+  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 = ::ndk::AParcel_writeData(_aidl_in.get(), in_status);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 0 /*done*/),
+    _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 && ICallback::getDefaultImpl()) {
+    _aidl_status = ICallback::getDefaultImpl()->done(in_status);
+    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_error:
+  _aidl_status.set(AStatus_fromStatus(_aidl_ret_status));
+  _aidl_status_return:
+  return _aidl_status;
+}
+// Source for BnCallback
+INestedService::BnCallback::BnCallback() {}
+INestedService::BnCallback::~BnCallback() {}
+::ndk::SpAIBinder INestedService::BnCallback::createBinder() {
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_tests_nested_INestedService_ICallback_clazz, static_cast<void*>(this));
+  #ifdef BINDER_STABILITY_SUPPORT
+  AIBinder_markCompilationUnitStability(binder);
+  #endif  // BINDER_STABILITY_SUPPORT
+  return ::ndk::SpAIBinder(binder);
+}
+// Source for ICallback
+const char* INestedService::ICallback::descriptor = "android.aidl.tests.nested.INestedService.ICallback";
+INestedService::ICallback::ICallback() {}
+INestedService::ICallback::~ICallback() {}
+
+
+std::shared_ptr<INestedService::ICallback> INestedService::ICallback::fromBinder(const ::ndk::SpAIBinder& binder) {
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_tests_nested_INestedService_ICallback_clazz)) { return nullptr; }
+  std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
+  if (interface) {
+    return std::static_pointer_cast<ICallback>(interface);
+  }
+  return ::ndk::SharedRefBase::make<INestedService::BpCallback>(binder);
+}
+
+binder_status_t INestedService::ICallback::writeToParcel(AParcel* parcel, const std::shared_ptr<ICallback>& instance) {
+  return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : nullptr);
+}
+binder_status_t INestedService::ICallback::readFromParcel(const AParcel* parcel, std::shared_ptr<ICallback>* instance) {
+  ::ndk::SpAIBinder binder;
+  binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());
+  if (status != STATUS_OK) return status;
+  *instance = ICallback::fromBinder(binder);
+  return STATUS_OK;
+}
+bool INestedService::ICallback::setDefaultImpl(const std::shared_ptr<ICallback>& 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(!ICallback::default_impl);
+  if (impl) {
+    ICallback::default_impl = impl;
+    return true;
+  }
+  return false;
+}
+const std::shared_ptr<INestedService::ICallback>& INestedService::ICallback::getDefaultImpl() {
+  return ICallback::default_impl;
+}
+std::shared_ptr<INestedService::ICallback> INestedService::ICallback::default_impl = nullptr;
+::ndk::ScopedAStatus INestedService::ICallbackDefault::done(::aidl::android::aidl::tests::nested::ParcelableWithNested::Status /*in_status*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::SpAIBinder INestedService::ICallbackDefault::asBinder() {
+  return ::ndk::SpAIBinder();
+}
+bool INestedService::ICallbackDefault::isRemote() {
+  return false;
+}
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/INestedService.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/INestedService.cpp.d
new file mode 100644
index 0000000..0481ef2
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/INestedService.cpp.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/INestedService.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/nested/INestedService.aidl \
+  system/tools/aidl/tests/android/aidl/tests/nested/ParcelableWithNested.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp
new file mode 100644
index 0000000..8c66d17
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp
@@ -0,0 +1,51 @@
+#include "aidl/android/aidl/tests/nested/ParcelableWithNested.h"
+
+#include <android/binder_parcel_utils.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+const char* ParcelableWithNested::descriptor = "android.aidl.tests.nested.ParcelableWithNested";
+
+binder_status_t ParcelableWithNested::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
+  if (_aidl_start_pos > INT32_MAX - _aidl_parcelable_size) return STATUS_BAD_VALUE;
+  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_readData(_aidl_parcel, &status);
+  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 ParcelableWithNested::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 = ::ndk::AParcel_writeData(_aidl_parcel, status);
+  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 nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp.d
new file mode 100644
index 0000000..ce5f36a
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/nested/ParcelableWithNested.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/nested/ParcelableWithNested.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtected.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtected.cpp
new file mode 100644
index 0000000..15e7a78
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtected.cpp
@@ -0,0 +1,234 @@
+#include "aidl/android/aidl/tests/permission/IProtected.h"
+
+#include <android/binder_parcel_utils.h>
+#include <aidl/android/aidl/tests/permission/BnProtected.h>
+#include <aidl/android/aidl/tests/permission/BpProtected.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+static binder_status_t _aidl_android_aidl_tests_permission_IProtected_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<BnProtected> _aidl_impl = std::static_pointer_cast<BnProtected>(::ndk::ICInterface::asInterface(_aidl_binder));
+  switch (_aidl_code) {
+    case (FIRST_CALL_TRANSACTION + 0 /*PermissionProtected*/): {
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->PermissionProtected();
+      _aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      if (!AStatus_isOk(_aidl_status.get())) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 1 /*MultiplePermissionsAll*/): {
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->MultiplePermissionsAll();
+      _aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      if (!AStatus_isOk(_aidl_status.get())) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 2 /*MultiplePermissionsAny*/): {
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->MultiplePermissionsAny();
+      _aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      if (!AStatus_isOk(_aidl_status.get())) break;
+
+      break;
+    }
+  }
+  return _aidl_ret_status;
+}
+
+static AIBinder_Class* _g_aidl_android_aidl_tests_permission_IProtected_clazz = ::ndk::ICInterface::defineClass(IProtected::descriptor, _aidl_android_aidl_tests_permission_IProtected_onTransact);
+
+BpProtected::BpProtected(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
+BpProtected::~BpProtected() {}
+
+::ndk::ScopedAStatus BpProtected::PermissionProtected() {
+  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 = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 0 /*PermissionProtected*/),
+    _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 && IProtected::getDefaultImpl()) {
+    _aidl_status = IProtected::getDefaultImpl()->PermissionProtected();
+    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_error:
+  _aidl_status.set(AStatus_fromStatus(_aidl_ret_status));
+  _aidl_status_return:
+  return _aidl_status;
+}
+::ndk::ScopedAStatus BpProtected::MultiplePermissionsAll() {
+  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 = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 1 /*MultiplePermissionsAll*/),
+    _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 && IProtected::getDefaultImpl()) {
+    _aidl_status = IProtected::getDefaultImpl()->MultiplePermissionsAll();
+    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_error:
+  _aidl_status.set(AStatus_fromStatus(_aidl_ret_status));
+  _aidl_status_return:
+  return _aidl_status;
+}
+::ndk::ScopedAStatus BpProtected::MultiplePermissionsAny() {
+  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 = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 2 /*MultiplePermissionsAny*/),
+    _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 && IProtected::getDefaultImpl()) {
+    _aidl_status = IProtected::getDefaultImpl()->MultiplePermissionsAny();
+    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_error:
+  _aidl_status.set(AStatus_fromStatus(_aidl_ret_status));
+  _aidl_status_return:
+  return _aidl_status;
+}
+// Source for BnProtected
+BnProtected::BnProtected() {}
+BnProtected::~BnProtected() {}
+::ndk::SpAIBinder BnProtected::createBinder() {
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_tests_permission_IProtected_clazz, static_cast<void*>(this));
+  #ifdef BINDER_STABILITY_SUPPORT
+  AIBinder_markCompilationUnitStability(binder);
+  #endif  // BINDER_STABILITY_SUPPORT
+  return ::ndk::SpAIBinder(binder);
+}
+// Source for IProtected
+const char* IProtected::descriptor = "android.aidl.tests.permission.IProtected";
+IProtected::IProtected() {}
+IProtected::~IProtected() {}
+
+
+std::shared_ptr<IProtected> IProtected::fromBinder(const ::ndk::SpAIBinder& binder) {
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_tests_permission_IProtected_clazz)) { return nullptr; }
+  std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
+  if (interface) {
+    return std::static_pointer_cast<IProtected>(interface);
+  }
+  return ::ndk::SharedRefBase::make<BpProtected>(binder);
+}
+
+binder_status_t IProtected::writeToParcel(AParcel* parcel, const std::shared_ptr<IProtected>& instance) {
+  return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : nullptr);
+}
+binder_status_t IProtected::readFromParcel(const AParcel* parcel, std::shared_ptr<IProtected>* instance) {
+  ::ndk::SpAIBinder binder;
+  binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());
+  if (status != STATUS_OK) return status;
+  *instance = IProtected::fromBinder(binder);
+  return STATUS_OK;
+}
+bool IProtected::setDefaultImpl(const std::shared_ptr<IProtected>& 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(!IProtected::default_impl);
+  if (impl) {
+    IProtected::default_impl = impl;
+    return true;
+  }
+  return false;
+}
+const std::shared_ptr<IProtected>& IProtected::getDefaultImpl() {
+  return IProtected::default_impl;
+}
+std::shared_ptr<IProtected> IProtected::default_impl = nullptr;
+::ndk::ScopedAStatus IProtectedDefault::PermissionProtected() {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus IProtectedDefault::MultiplePermissionsAll() {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus IProtectedDefault::MultiplePermissionsAny() {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::SpAIBinder IProtectedDefault::asBinder() {
+  return ::ndk::SpAIBinder();
+}
+bool IProtectedDefault::isRemote() {
+  return false;
+}
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtected.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtected.cpp.d
new file mode 100644
index 0000000..7db52de
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtected.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtected.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/permission/IProtected.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp
new file mode 100644
index 0000000..454f6a4
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp
@@ -0,0 +1,185 @@
+#include "aidl/android/aidl/tests/permission/IProtectedInterface.h"
+
+#include <android/binder_parcel_utils.h>
+#include <aidl/android/aidl/tests/permission/BnProtectedInterface.h>
+#include <aidl/android/aidl/tests/permission/BpProtectedInterface.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+static binder_status_t _aidl_android_aidl_tests_permission_IProtectedInterface_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<BnProtectedInterface> _aidl_impl = std::static_pointer_cast<BnProtectedInterface>(::ndk::ICInterface::asInterface(_aidl_binder));
+  switch (_aidl_code) {
+    case (FIRST_CALL_TRANSACTION + 0 /*Method1*/): {
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->Method1();
+      _aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      if (!AStatus_isOk(_aidl_status.get())) break;
+
+      break;
+    }
+    case (FIRST_CALL_TRANSACTION + 1 /*Method2*/): {
+
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->Method2();
+      _aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      if (!AStatus_isOk(_aidl_status.get())) break;
+
+      break;
+    }
+  }
+  return _aidl_ret_status;
+}
+
+static AIBinder_Class* _g_aidl_android_aidl_tests_permission_IProtectedInterface_clazz = ::ndk::ICInterface::defineClass(IProtectedInterface::descriptor, _aidl_android_aidl_tests_permission_IProtectedInterface_onTransact);
+
+BpProtectedInterface::BpProtectedInterface(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
+BpProtectedInterface::~BpProtectedInterface() {}
+
+::ndk::ScopedAStatus BpProtectedInterface::Method1() {
+  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 = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 0 /*Method1*/),
+    _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 && IProtectedInterface::getDefaultImpl()) {
+    _aidl_status = IProtectedInterface::getDefaultImpl()->Method1();
+    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_error:
+  _aidl_status.set(AStatus_fromStatus(_aidl_ret_status));
+  _aidl_status_return:
+  return _aidl_status;
+}
+::ndk::ScopedAStatus BpProtectedInterface::Method2() {
+  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 = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 1 /*Method2*/),
+    _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 && IProtectedInterface::getDefaultImpl()) {
+    _aidl_status = IProtectedInterface::getDefaultImpl()->Method2();
+    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_error:
+  _aidl_status.set(AStatus_fromStatus(_aidl_ret_status));
+  _aidl_status_return:
+  return _aidl_status;
+}
+// Source for BnProtectedInterface
+BnProtectedInterface::BnProtectedInterface() {}
+BnProtectedInterface::~BnProtectedInterface() {}
+::ndk::SpAIBinder BnProtectedInterface::createBinder() {
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_tests_permission_IProtectedInterface_clazz, static_cast<void*>(this));
+  #ifdef BINDER_STABILITY_SUPPORT
+  AIBinder_markCompilationUnitStability(binder);
+  #endif  // BINDER_STABILITY_SUPPORT
+  return ::ndk::SpAIBinder(binder);
+}
+// Source for IProtectedInterface
+const char* IProtectedInterface::descriptor = "android.aidl.tests.permission.IProtectedInterface";
+IProtectedInterface::IProtectedInterface() {}
+IProtectedInterface::~IProtectedInterface() {}
+
+
+std::shared_ptr<IProtectedInterface> IProtectedInterface::fromBinder(const ::ndk::SpAIBinder& binder) {
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_tests_permission_IProtectedInterface_clazz)) { return nullptr; }
+  std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
+  if (interface) {
+    return std::static_pointer_cast<IProtectedInterface>(interface);
+  }
+  return ::ndk::SharedRefBase::make<BpProtectedInterface>(binder);
+}
+
+binder_status_t IProtectedInterface::writeToParcel(AParcel* parcel, const std::shared_ptr<IProtectedInterface>& instance) {
+  return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : nullptr);
+}
+binder_status_t IProtectedInterface::readFromParcel(const AParcel* parcel, std::shared_ptr<IProtectedInterface>* instance) {
+  ::ndk::SpAIBinder binder;
+  binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());
+  if (status != STATUS_OK) return status;
+  *instance = IProtectedInterface::fromBinder(binder);
+  return STATUS_OK;
+}
+bool IProtectedInterface::setDefaultImpl(const std::shared_ptr<IProtectedInterface>& 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(!IProtectedInterface::default_impl);
+  if (impl) {
+    IProtectedInterface::default_impl = impl;
+    return true;
+  }
+  return false;
+}
+const std::shared_ptr<IProtectedInterface>& IProtectedInterface::getDefaultImpl() {
+  return IProtectedInterface::default_impl;
+}
+std::shared_ptr<IProtectedInterface> IProtectedInterface::default_impl = nullptr;
+::ndk::ScopedAStatus IProtectedInterfaceDefault::Method1() {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::ScopedAStatus IProtectedInterfaceDefault::Method2() {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::SpAIBinder IProtectedInterfaceDefault::asBinder() {
+  return ::ndk::SpAIBinder();
+}
+bool IProtectedInterfaceDefault::isRemote() {
+  return false;
+}
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp.d
new file mode 100644
index 0000000..0dbab58
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/permission/IProtectedInterface.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/permission/IProtectedInterface.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/EnumUnion.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/EnumUnion.cpp
similarity index 69%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/EnumUnion.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/EnumUnion.cpp
index 25f7c68..08bcd8c 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/EnumUnion.cpp
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/EnumUnion.cpp
@@ -12,11 +12,11 @@
 binder_status_t EnumUnion::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;
+  if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_tag)) != STATUS_OK) return _aidl_ret_status;
   switch (_aidl_tag) {
   case intEnum: {
     ::aidl::android::aidl::tests::IntEnum _aidl_value;
-    if ((_aidl_ret_status = AParcel_readInt32(_parcel, reinterpret_cast<int32_t*>(&_aidl_value))) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<::aidl::android::aidl::tests::IntEnum>) {
       set<intEnum>(_aidl_value);
     } else {
@@ -26,7 +26,7 @@
     return STATUS_OK; }
   case longEnum: {
     ::aidl::android::aidl::tests::LongEnum _aidl_value;
-    if ((_aidl_ret_status = AParcel_readInt64(_parcel, reinterpret_cast<int64_t*>(&_aidl_value))) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<::aidl::android::aidl::tests::LongEnum>) {
       set<longEnum>(_aidl_value);
     } else {
@@ -38,11 +38,11 @@
   return STATUS_BAD_VALUE;
 }
 binder_status_t EnumUnion::writeToParcel(AParcel* _parcel) const {
-  binder_status_t _aidl_ret_status = AParcel_writeInt32(_parcel, getTag());
+  binder_status_t _aidl_ret_status = ::ndk::AParcel_writeData(_parcel, getTag());
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
   switch (getTag()) {
-  case intEnum: return AParcel_writeInt32(_parcel, static_cast<int32_t>(get<intEnum>()));
-  case longEnum: return AParcel_writeInt64(_parcel, static_cast<int64_t>(get<longEnum>()));
+  case intEnum: return ::ndk::AParcel_writeData(_parcel, get<intEnum>());
+  case longEnum: return ::ndk::AParcel_writeData(_parcel, get<longEnum>());
   }
   __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
 }
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/EnumUnion.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/EnumUnion.cpp.d
similarity index 78%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/EnumUnion.cpp.d
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/EnumUnion.cpp.d
index 0781df9..9ad133c 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/EnumUnion.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/EnumUnion.cpp.d
@@ -1,4 +1,4 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/EnumUnion.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/EnumUnion.cpp : \
   system/tools/aidl/tests/android/aidl/tests/unions/EnumUnion.aidl \
   system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
   system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/UnionInUnion.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/UnionInUnion.cpp
similarity index 71%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/UnionInUnion.cpp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/UnionInUnion.cpp
index 79c36ff..5db5c98 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/UnionInUnion.cpp
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/UnionInUnion.cpp
@@ -12,11 +12,11 @@
 binder_status_t UnionInUnion::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;
+  if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_tag)) != STATUS_OK) return _aidl_ret_status;
   switch (_aidl_tag) {
   case first: {
     ::aidl::android::aidl::tests::unions::EnumUnion _aidl_value;
-    if ((_aidl_ret_status = ::ndk::AParcel_readParcelable(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<::aidl::android::aidl::tests::unions::EnumUnion>) {
       set<first>(_aidl_value);
     } else {
@@ -26,7 +26,7 @@
     return STATUS_OK; }
   case second: {
     int32_t _aidl_value;
-    if ((_aidl_ret_status = AParcel_readInt32(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<int32_t>) {
       set<second>(_aidl_value);
     } else {
@@ -38,11 +38,11 @@
   return STATUS_BAD_VALUE;
 }
 binder_status_t UnionInUnion::writeToParcel(AParcel* _parcel) const {
-  binder_status_t _aidl_ret_status = AParcel_writeInt32(_parcel, getTag());
+  binder_status_t _aidl_ret_status = ::ndk::AParcel_writeData(_parcel, getTag());
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
   switch (getTag()) {
-  case first: return ::ndk::AParcel_writeParcelable(_parcel, get<first>());
-  case second: return AParcel_writeInt32(_parcel, get<second>());
+  case first: return ::ndk::AParcel_writeData(_parcel, get<first>());
+  case second: return ::ndk::AParcel_writeData(_parcel, get<second>());
   }
   __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
 }
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/EnumUnion.cpp.d b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/UnionInUnion.cpp.d
similarity index 65%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/EnumUnion.cpp.d
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/UnionInUnion.cpp.d
index 0781df9..37113d9 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/EnumUnion.cpp.d
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/UnionInUnion.cpp.d
@@ -1,4 +1,5 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/EnumUnion.cpp : \
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/UnionInUnion.cpp : \
+  system/tools/aidl/tests/android/aidl/tests/unions/UnionInUnion.aidl \
   system/tools/aidl/tests/android/aidl/tests/unions/EnumUnion.aidl \
   system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
   system/tools/aidl/tests/android/aidl/tests/LongEnum.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_platform-source/gen/include/aidl/android/aidl/tests/BackendType.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BackendType.h
similarity index 89%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BackendType.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BackendType.h
index 6838ca7..f69e433 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BackendType.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BackendType.h
@@ -1,15 +1,16 @@
 #pragma once
 
+#include <array>
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_enums.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
-#include <array>
-#include <android/binder_enums.h>
+
 namespace aidl {
 namespace android {
 namespace aidl {
@@ -21,6 +22,14 @@
   RUST = 3,
 };
 
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
 [[nodiscard]] static inline std::string toString(BackendType val) {
   switch(val) {
   case BackendType::CPP:
@@ -52,4 +61,4 @@
 };
 #pragma clang diagnostic pop
 }  // namespace internal
-}  // namespace android
+}  // namespace ndk
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnDeprecatedParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnArrayOfInterfaces.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnDeprecatedParcelable.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnArrayOfInterfaces.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnBackendType.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnBackendType.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnBackendType.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnBackendType.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnByteEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnByteEnum.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnByteEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnByteEnum.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnConstantExpressionEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnConstantExpressionEnum.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnConstantExpressionEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnConstantExpressionEnum.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnDeprecated.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnDeprecated.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnDeprecated.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnDeprecated.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnDeprecatedEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnDeprecatedEnum.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnDeprecatedEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnDeprecatedEnum.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnDeprecatedParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnDeprecatedParcelable.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnDeprecatedParcelable.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnDeprecatedParcelable.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnFixedSize.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnFixedSize.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnGenericStructuredParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnGenericStructuredParcelable.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnGenericStructuredParcelable.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnGenericStructuredParcelable.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnIntEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnIntEnum.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnIntEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnIntEnum.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnListOfInterfaces.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnListOfInterfaces.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnLongEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnLongEnum.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnLongEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnLongEnum.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnNamedCallback.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnNamedCallback.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnNamedCallback.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnNamedCallback.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnNewName.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnNewName.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnNewName.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnNewName.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnOldName.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnOldName.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnOldName.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnOldName.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnOtherParcelableForToString.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnOtherParcelableForToString.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnOtherParcelableForToString.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnOtherParcelableForToString.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnParcelableForToString.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnParcelableForToString.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnParcelableForToString.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnParcelableForToString.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnRecursiveList.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnRecursiveList.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnStructuredParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnStructuredParcelable.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnStructuredParcelable.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnStructuredParcelable.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnTestService.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnTestService.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnTestService.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnTestService.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnUnion.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnUnion.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnionWithFd.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnUnionWithFd.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnionWithFd.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BnUnionWithFd.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpDeprecatedParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpArrayOfInterfaces.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpDeprecatedParcelable.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpArrayOfInterfaces.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpBackendType.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpBackendType.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpBackendType.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpBackendType.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpByteEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpByteEnum.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpByteEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpByteEnum.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpConstantExpressionEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpConstantExpressionEnum.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpConstantExpressionEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpConstantExpressionEnum.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpDeprecated.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpDeprecated.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpDeprecated.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpDeprecated.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpDeprecatedEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpDeprecatedEnum.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpDeprecatedEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpDeprecatedEnum.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpDeprecatedParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpDeprecatedParcelable.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpDeprecatedParcelable.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpDeprecatedParcelable.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpFixedSize.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpFixedSize.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpGenericStructuredParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpGenericStructuredParcelable.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpGenericStructuredParcelable.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpGenericStructuredParcelable.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpIntEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpIntEnum.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpIntEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpIntEnum.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpListOfInterfaces.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpListOfInterfaces.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpLongEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpLongEnum.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpLongEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpLongEnum.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpNamedCallback.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpNamedCallback.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpNamedCallback.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpNamedCallback.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpNewName.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpNewName.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpNewName.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpNewName.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpOldName.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpOldName.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpOldName.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpOldName.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpOtherParcelableForToString.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpOtherParcelableForToString.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpOtherParcelableForToString.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpOtherParcelableForToString.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpParcelableForToString.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpParcelableForToString.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpParcelableForToString.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpParcelableForToString.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpRecursiveList.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpRecursiveList.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpStructuredParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpStructuredParcelable.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpStructuredParcelable.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpStructuredParcelable.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpTestService.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpTestService.h
similarity index 67%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpTestService.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpTestService.h
index 30b0fa0..71b75be 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpTestService.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpTestService.h
@@ -40,6 +40,12 @@
   ::ndk::ScopedAStatus ReverseLongEnum(const std::vector<::aidl::android::aidl::tests::LongEnum>& in_input, std::vector<::aidl::android::aidl::tests::LongEnum>* out_repeated, std::vector<::aidl::android::aidl::tests::LongEnum>* _aidl_return) override;
   ::ndk::ScopedAStatus GetOtherTestService(const std::string& in_name, std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>* _aidl_return) override;
   ::ndk::ScopedAStatus VerifyName(const std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>& in_service, const std::string& in_name, bool* _aidl_return) override;
+  ::ndk::ScopedAStatus GetInterfaceArray(const std::vector<std::string>& in_names, std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>* _aidl_return) override;
+  ::ndk::ScopedAStatus VerifyNamesWithInterfaceArray(const std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>& in_services, const std::vector<std::string>& in_names, bool* _aidl_return) override;
+  ::ndk::ScopedAStatus GetNullableInterfaceArray(const std::optional<std::vector<std::optional<std::string>>>& in_names, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>* _aidl_return) override;
+  ::ndk::ScopedAStatus VerifyNamesWithNullableInterfaceArray(const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>& in_services, const std::optional<std::vector<std::optional<std::string>>>& in_names, bool* _aidl_return) override;
+  ::ndk::ScopedAStatus GetInterfaceList(const std::optional<std::vector<std::optional<std::string>>>& in_names, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>* _aidl_return) override;
+  ::ndk::ScopedAStatus VerifyNamesWithInterfaceList(const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>& in_services, const std::optional<std::vector<std::optional<std::string>>>& in_names, bool* _aidl_return) override;
   ::ndk::ScopedAStatus ReverseStringList(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) override;
   ::ndk::ScopedAStatus RepeatParcelFileDescriptor(const ::ndk::ScopedFileDescriptor& in_read, ::ndk::ScopedFileDescriptor* _aidl_return) override;
   ::ndk::ScopedAStatus ReverseParcelFileDescriptorArray(const std::vector<::ndk::ScopedFileDescriptor>& in_input, std::vector<::ndk::ScopedFileDescriptor>* out_repeated, std::vector<::ndk::ScopedFileDescriptor>* _aidl_return) override;
@@ -49,17 +55,25 @@
   ::ndk::ScopedAStatus RepeatNullableIntEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::IntEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::IntEnum>>* _aidl_return) override;
   ::ndk::ScopedAStatus RepeatNullableLongEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::LongEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::LongEnum>>* _aidl_return) override;
   ::ndk::ScopedAStatus RepeatNullableString(const std::optional<std::string>& in_input, std::optional<std::string>* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatNullableStringList(const std::vector<std::string>& in_input, std::vector<std::string>* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatNullableParcelable(const std::optional<::aidl::android::aidl::tests::StructuredParcelable>& in_input, std::optional<::aidl::android::aidl::tests::StructuredParcelable>* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatNullableStringList(const std::optional<std::vector<std::optional<std::string>>>& in_input, std::optional<std::vector<std::optional<std::string>>>* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatNullableParcelable(const std::optional<::aidl::android::aidl::tests::ITestService::Empty>& in_input, std::optional<::aidl::android::aidl::tests::ITestService::Empty>* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatNullableParcelableArray(const std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>& in_input, std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatNullableParcelableList(const std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>& in_input, std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>* _aidl_return) override;
   ::ndk::ScopedAStatus TakesAnIBinder(const ::ndk::SpAIBinder& in_input) override;
   ::ndk::ScopedAStatus TakesANullableIBinder(const ::ndk::SpAIBinder& in_input) override;
+  ::ndk::ScopedAStatus TakesAnIBinderList(const std::vector<::ndk::SpAIBinder>& in_input) override;
+  ::ndk::ScopedAStatus TakesANullableIBinderList(const std::optional<std::vector<::ndk::SpAIBinder>>& in_input) override;
   ::ndk::ScopedAStatus RepeatUtf8CppString(const std::string& in_token, std::string* _aidl_return) override;
   ::ndk::ScopedAStatus RepeatNullableUtf8CppString(const std::optional<std::string>& in_token, std::optional<std::string>* _aidl_return) override;
   ::ndk::ScopedAStatus ReverseUtf8CppString(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) override;
   ::ndk::ScopedAStatus ReverseNullableUtf8CppString(const std::optional<std::vector<std::optional<std::string>>>& in_input, std::optional<std::vector<std::optional<std::string>>>* out_repeated, std::optional<std::vector<std::optional<std::string>>>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseUtf8CppStringList(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseUtf8CppStringList(const std::optional<std::vector<std::optional<std::string>>>& in_input, std::optional<std::vector<std::optional<std::string>>>* out_repeated, std::optional<std::vector<std::optional<std::string>>>* _aidl_return) override;
   ::ndk::ScopedAStatus GetCallback(bool in_return_null, std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>* _aidl_return) override;
   ::ndk::ScopedAStatus FillOutStructuredParcelable(::aidl::android::aidl::tests::StructuredParcelable* in_parcel) override;
+  ::ndk::ScopedAStatus RepeatExtendableParcelable(const ::aidl::android::aidl::tests::extension::ExtendableParcelable& in_ep, ::aidl::android::aidl::tests::extension::ExtendableParcelable* out_ep2) override;
+  ::ndk::ScopedAStatus ReverseList(const ::aidl::android::aidl::tests::RecursiveList& in_list, ::aidl::android::aidl::tests::RecursiveList* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseIBinderArray(const std::vector<::ndk::SpAIBinder>& in_input, std::vector<::ndk::SpAIBinder>* out_repeated, std::vector<::ndk::SpAIBinder>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseNullableIBinderArray(const std::optional<std::vector<::ndk::SpAIBinder>>& in_input, std::optional<std::vector<::ndk::SpAIBinder>>* out_repeated, std::optional<std::vector<::ndk::SpAIBinder>>* _aidl_return) override;
   ::ndk::ScopedAStatus GetOldNameInterface(std::shared_ptr<::aidl::android::aidl::tests::IOldName>* _aidl_return) override;
   ::ndk::ScopedAStatus GetNewNameInterface(std::shared_ptr<::aidl::android::aidl::tests::INewName>* _aidl_return) override;
   ::ndk::ScopedAStatus GetCppJavaTests(::ndk::SpAIBinder* _aidl_return) override;
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpUnion.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpUnion.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnionWithFd.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpUnionWithFd.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnionWithFd.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/BpUnionWithFd.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/ByteEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ByteEnum.h
similarity index 88%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/ByteEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ByteEnum.h
index 30ac9e5..9cb0146 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/ByteEnum.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ByteEnum.h
@@ -1,15 +1,16 @@
 #pragma once
 
+#include <array>
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_enums.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
-#include <array>
-#include <android/binder_enums.h>
+
 namespace aidl {
 namespace android {
 namespace aidl {
@@ -20,6 +21,14 @@
   BAZ = 3,
 };
 
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
 [[nodiscard]] static inline std::string toString(ByteEnum val) {
   switch(val) {
   case ByteEnum::FOO:
@@ -48,4 +57,4 @@
 };
 #pragma clang diagnostic pop
 }  // namespace internal
-}  // namespace android
+}  // namespace ndk
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/ConstantExpressionEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ConstantExpressionEnum.h
similarity index 92%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/ConstantExpressionEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ConstantExpressionEnum.h
index 1802d84..5fbcc00 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/ConstantExpressionEnum.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ConstantExpressionEnum.h
@@ -1,15 +1,16 @@
 #pragma once
 
+#include <array>
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_enums.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
-#include <array>
-#include <android/binder_enums.h>
+
 namespace aidl {
 namespace android {
 namespace aidl {
@@ -27,6 +28,14 @@
   hexInt64_1 = 1,
 };
 
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
 [[nodiscard]] static inline std::string toString(ConstantExpressionEnum val) {
   switch(val) {
   case ConstantExpressionEnum::decInt32_1:
@@ -58,4 +67,4 @@
 };
 #pragma clang diagnostic pop
 }  // namespace internal
-}  // namespace android
+}  // namespace ndk
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/DeprecatedEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/DeprecatedEnum.h
similarity index 90%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/DeprecatedEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/DeprecatedEnum.h
index 853c808..299874c 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/DeprecatedEnum.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/DeprecatedEnum.h
@@ -1,15 +1,16 @@
 #pragma once
 
+#include <array>
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_enums.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
-#include <array>
-#include <android/binder_enums.h>
+
 namespace aidl {
 namespace android {
 namespace aidl {
@@ -20,6 +21,14 @@
   C = 2,
 };
 
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
 [[nodiscard]] static inline std::string toString(DeprecatedEnum val) __attribute__((deprecated("test")));
 [[nodiscard]] static inline std::string toString(DeprecatedEnum val) {
   switch(val) {
@@ -49,4 +58,4 @@
 };
 #pragma clang diagnostic pop
 }  // namespace internal
-}  // namespace android
+}  // namespace ndk
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/DeprecatedParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/DeprecatedParcelable.h
similarity index 99%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/DeprecatedParcelable.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/DeprecatedParcelable.h
index 52719bc..5ccedc2 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/DeprecatedParcelable.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/DeprecatedParcelable.h
@@ -1,15 +1,17 @@
 #pragma once
-#include <android/binder_interface_utils.h>
-#include <android/binder_parcelable_utils.h>
-#include <android/binder_to_string.h>
+
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
+
 namespace aidl {
 namespace android {
 namespace aidl {
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/FixedSize.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/FixedSize.h
new file mode 100644
index 0000000..2a78374
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/FixedSize.h
@@ -0,0 +1,235 @@
+#pragma once
+
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+#include <variant>
+#include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#include <aidl/android/aidl/tests/FixedSize.h>
+#include <aidl/android/aidl/tests/LongEnum.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 FixedSize {
+public:
+  typedef std::false_type fixed_size;
+  static const char* descriptor;
+
+  class FixedUnion {
+  public:
+    typedef std::true_type fixed_size;
+    static const char* descriptor;
+
+    enum Tag : uint8_t {
+      booleanValue = 0,  // boolean booleanValue;
+      byteValue,  // byte byteValue;
+      charValue,  // char charValue;
+      intValue,  // int intValue;
+      longValue,  // long longValue;
+      floatValue,  // float floatValue;
+      doubleValue,  // double doubleValue;
+      enumValue,  // android.aidl.tests.LongEnum enumValue;
+    };
+
+    template <Tag _Tag>
+    using _at = typename std::tuple_element<_Tag, std::tuple<bool, int8_t, char16_t, int32_t, int64_t, float, double, ::aidl::android::aidl::tests::LongEnum>>::type;
+    template <Tag _Tag, typename _Type>
+    static FixedUnion make(_Type&& _arg) {
+      FixedUnion _inst;
+      _inst.set<_Tag>(std::forward<_Type>(_arg));
+      return _inst;
+    }
+    constexpr Tag getTag() const {
+      return _tag;
+    }
+    template <Tag _Tag>
+    const _at<_Tag>& get() const {
+      if (_Tag != _tag) { __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }
+      return *(_at<_Tag>*)(&_value);
+    }
+    template <Tag _Tag>
+    _at<_Tag>& get() {
+      if (_Tag != _tag) { __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "bad access: a wrong tag"); }
+      return *(_at<_Tag>*)(&_value);
+    }
+    template <Tag _Tag, typename _Type>
+    void set(_Type&& _arg) {
+      _tag = _Tag;
+      get<_Tag>() = std::forward<_Type>(_arg);
+    }
+    binder_status_t readFromParcel(const AParcel* _parcel);
+    binder_status_t writeToParcel(AParcel* _parcel) const;
+
+    static int _cmp(const FixedUnion& _lhs, const FixedUnion& _rhs) {
+      return _cmp_value(_lhs.getTag(), _rhs.getTag()) || _cmp_value_at<enumValue>(_lhs, _rhs);
+    }
+    template <Tag _Tag>
+    static int _cmp_value_at(const FixedUnion& _lhs, const FixedUnion& _rhs) {
+      if constexpr (_Tag == booleanValue) {
+        return _cmp_value(_lhs.get<_Tag>(), _rhs.get<_Tag>());
+      } else {
+        return (_lhs.getTag() == _Tag)
+          ? _cmp_value(_lhs.get<_Tag>(), _rhs.get<_Tag>())
+          : _cmp_value_at<(Tag)(_Tag-1)>(_lhs, _rhs);
+      }
+    }
+    template <typename _Type>
+    static int _cmp_value(const _Type& _lhs, const _Type& _rhs) {
+      return (_lhs == _rhs) ? 0 : (_lhs < _rhs) ? -1 : 1;
+    }
+    inline bool operator!=(const FixedUnion&_rhs) const {
+      return _cmp(*this, _rhs) != 0;
+    }
+    inline bool operator<(const FixedUnion&_rhs) const {
+      return _cmp(*this, _rhs) < 0;
+    }
+    inline bool operator<=(const FixedUnion&_rhs) const {
+      return _cmp(*this, _rhs) <= 0;
+    }
+    inline bool operator==(const FixedUnion&_rhs) const {
+      return _cmp(*this, _rhs) == 0;
+    }
+    inline bool operator>(const FixedUnion&_rhs) const {
+      return _cmp(*this, _rhs) > 0;
+    }
+    inline bool operator>=(const FixedUnion&_rhs) const {
+      return _cmp(*this, _rhs) >= 0;
+    }
+    static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "FixedUnion{";
+      switch (getTag()) {
+      case booleanValue: os << "booleanValue: " << ::android::internal::ToString(get<booleanValue>()); break;
+      case byteValue: os << "byteValue: " << ::android::internal::ToString(get<byteValue>()); break;
+      case charValue: os << "charValue: " << ::android::internal::ToString(get<charValue>()); break;
+      case intValue: os << "intValue: " << ::android::internal::ToString(get<intValue>()); break;
+      case longValue: os << "longValue: " << ::android::internal::ToString(get<longValue>()); break;
+      case floatValue: os << "floatValue: " << ::android::internal::ToString(get<floatValue>()); break;
+      case doubleValue: os << "doubleValue: " << ::android::internal::ToString(get<doubleValue>()); break;
+      case enumValue: os << "enumValue: " << ::android::internal::ToString(get<enumValue>()); break;
+      }
+      os << "}";
+      return os.str();
+    }
+  private:
+    Tag _tag __attribute__((aligned (1))) = booleanValue;
+    union _value_t {
+      _value_t() {}
+      ~_value_t() {}
+      bool booleanValue __attribute__((aligned (1))) = bool(false);
+      int8_t byteValue __attribute__((aligned (1)));
+      char16_t charValue __attribute__((aligned (2)));
+      int32_t intValue __attribute__((aligned (4)));
+      int64_t longValue __attribute__((aligned (8)));
+      float floatValue __attribute__((aligned (4)));
+      double doubleValue __attribute__((aligned (8)));
+      ::aidl::android::aidl::tests::LongEnum enumValue __attribute__((aligned (8)));
+    } _value;
+  };
+  class FixedParcelable {
+  public:
+    typedef std::true_type fixed_size;
+    static const char* descriptor;
+
+    bool booleanValue __attribute__((aligned (1))) = false;
+    int8_t byteValue __attribute__((aligned (1))) = 0;
+    char16_t charValue __attribute__((aligned (2))) = '\0';
+    int32_t intValue __attribute__((aligned (4))) = 0;
+    int64_t longValue __attribute__((aligned (8))) = 0L;
+    float floatValue __attribute__((aligned (4))) = 0.000000f;
+    double doubleValue __attribute__((aligned (8))) = 0.000000;
+    ::aidl::android::aidl::tests::LongEnum enumValue __attribute__((aligned (8))) = ::aidl::android::aidl::tests::LongEnum::FOO;
+    ::aidl::android::aidl::tests::FixedSize::FixedUnion parcelableValue;
+
+    binder_status_t readFromParcel(const AParcel* parcel);
+    binder_status_t writeToParcel(AParcel* parcel) const;
+
+    inline bool operator!=(const FixedParcelable& rhs) const {
+      return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) != std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+    }
+    inline bool operator<(const FixedParcelable& rhs) const {
+      return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) < std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+    }
+    inline bool operator<=(const FixedParcelable& rhs) const {
+      return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) <= std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+    }
+    inline bool operator==(const FixedParcelable& rhs) const {
+      return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) == std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+    }
+    inline bool operator>(const FixedParcelable& rhs) const {
+      return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) > std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+    }
+    inline bool operator>=(const FixedParcelable& rhs) const {
+      return std::tie(booleanValue, byteValue, charValue, intValue, longValue, floatValue, doubleValue, enumValue, parcelableValue) >= std::tie(rhs.booleanValue, rhs.byteValue, rhs.charValue, rhs.intValue, rhs.longValue, rhs.floatValue, rhs.doubleValue, rhs.enumValue, rhs.parcelableValue);
+    }
+
+    static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "FixedParcelable{";
+      os << "booleanValue: " << ::android::internal::ToString(booleanValue);
+      os << ", byteValue: " << ::android::internal::ToString(byteValue);
+      os << ", charValue: " << ::android::internal::ToString(charValue);
+      os << ", intValue: " << ::android::internal::ToString(intValue);
+      os << ", longValue: " << ::android::internal::ToString(longValue);
+      os << ", floatValue: " << ::android::internal::ToString(floatValue);
+      os << ", doubleValue: " << ::android::internal::ToString(doubleValue);
+      os << ", enumValue: " << ::android::internal::ToString(enumValue);
+      os << ", parcelableValue: " << ::android::internal::ToString(parcelableValue);
+      os << "}";
+      return os.str();
+    }
+  };
+
+  binder_status_t readFromParcel(const AParcel* parcel);
+  binder_status_t writeToParcel(AParcel* parcel) const;
+
+  inline bool operator!=(const FixedSize&) const {
+    return std::tie() != std::tie();
+  }
+  inline bool operator<(const FixedSize&) const {
+    return std::tie() < std::tie();
+  }
+  inline bool operator<=(const FixedSize&) const {
+    return std::tie() <= std::tie();
+  }
+  inline bool operator==(const FixedSize&) const {
+    return std::tie() == std::tie();
+  }
+  inline bool operator>(const FixedSize&) const {
+    return std::tie() > std::tie();
+  }
+  inline bool operator>=(const FixedSize&) 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 << "FixedSize{";
+    os << "}";
+    return os.str();
+  }
+};
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/GenericStructuredParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/GenericStructuredParcelable.h
similarity index 69%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/GenericStructuredParcelable.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/GenericStructuredParcelable.h
index 113aff4..ec01899 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/GenericStructuredParcelable.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/GenericStructuredParcelable.h
@@ -1,15 +1,17 @@
 #pragma once
-#include <android/binder_interface_utils.h>
-#include <android/binder_parcelable_utils.h>
-#include <android/binder_to_string.h>
+
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
+
 namespace aidl {
 namespace android {
 namespace aidl {
@@ -71,48 +73,49 @@
 const char* GenericStructuredParcelable<T, U, B>::descriptor = "android.aidl.tests.GenericStructuredParcelable";
 
 template <typename T, typename U, typename B>
-binder_status_t GenericStructuredParcelable<T, U, B>::readFromParcel(const AParcel* parcel) {
-  int32_t _aidl_parcelable_size;
-  int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  binder_status_t _aidl_ret_status = AParcel_readInt32(parcel, &_aidl_parcelable_size);
+binder_status_t GenericStructuredParcelable<T, U, B>::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
   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(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
+  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 = AParcel_readInt32(parcel, &a);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_parcel, &a);
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
 
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
+  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 = AParcel_readInt32(parcel, &b);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_parcel, &b);
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
 
-  AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
   return _aidl_ret_status;
 }
 template <typename T, typename U, typename B>
-binder_status_t GenericStructuredParcelable<T, U, B>::writeToParcel(AParcel* parcel) const {
+binder_status_t GenericStructuredParcelable<T, U, B>::writeToParcel(AParcel* _aidl_parcel) const {
   binder_status_t _aidl_ret_status;
-  size_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  _aidl_ret_status = AParcel_writeInt32(parcel, 0);
+  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 = AParcel_writeInt32(parcel, a);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, a);
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
 
-  _aidl_ret_status = AParcel_writeInt32(parcel, b);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, b);
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
 
-  size_t _aidl_end_pos = AParcel_getDataPosition(parcel);
-  AParcel_setDataPosition(parcel, _aidl_start_pos);
-  AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);
-  AParcel_setDataPosition(parcel, _aidl_end_pos);
+  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;
 }
 
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/IDeprecated.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/IDeprecated.h
similarity index 99%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/IDeprecated.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/IDeprecated.h
index 80d5589..4c8c67c 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/IDeprecated.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/IDeprecated.h
@@ -1,12 +1,11 @@
 #pragma once
 
-#include <android/binder_interface_utils.h>
-
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_interface_utils.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/INamedCallback.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/INamedCallback.h
similarity index 99%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/INamedCallback.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/INamedCallback.h
index d38c7e1..ca14c0f 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/INamedCallback.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/INamedCallback.h
@@ -1,12 +1,11 @@
 #pragma once
 
-#include <android/binder_interface_utils.h>
-
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_interface_utils.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/INewName.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/INewName.h
similarity index 99%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/INewName.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/INewName.h
index 1f93d5f..5c42f9d 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/INewName.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/INewName.h
@@ -1,12 +1,11 @@
 #pragma once
 
-#include <android/binder_interface_utils.h>
-
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_interface_utils.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/IOldName.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/IOldName.h
similarity index 99%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/IOldName.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/IOldName.h
index c4a4f79..bff905d 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/IOldName.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/IOldName.h
@@ -1,12 +1,11 @@
 #pragma once
 
-#include <android/binder_interface_utils.h>
-
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_interface_utils.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ITestService.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ITestService.h
new file mode 100644
index 0000000..dfa1692
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ITestService.h
@@ -0,0 +1,432 @@
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+#include <android/binder_ibinder_platform.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcel_platform.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#include <aidl/android/aidl/tests/BackendType.h>
+#include <aidl/android/aidl/tests/ByteEnum.h>
+#include <aidl/android/aidl/tests/INamedCallback.h>
+#include <aidl/android/aidl/tests/INewName.h>
+#include <aidl/android/aidl/tests/IOldName.h>
+#include <aidl/android/aidl/tests/ITestService.h>
+#include <aidl/android/aidl/tests/IntEnum.h>
+#include <aidl/android/aidl/tests/LongEnum.h>
+#include <aidl/android/aidl/tests/RecursiveList.h>
+#include <aidl/android/aidl/tests/StructuredParcelable.h>
+#include <aidl/android/aidl/tests/extension/ExtendableParcelable.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+class ITestService : public ::ndk::ICInterface {
+public:
+  static const char* descriptor;
+  ITestService();
+  virtual ~ITestService();
+
+  class Empty {
+  public:
+    typedef std::false_type fixed_size;
+    static const char* descriptor;
+
+
+    binder_status_t readFromParcel(const AParcel* parcel);
+    binder_status_t writeToParcel(AParcel* parcel) const;
+
+    inline bool operator!=(const Empty&) const {
+      return std::tie() != std::tie();
+    }
+    inline bool operator<(const Empty&) const {
+      return std::tie() < std::tie();
+    }
+    inline bool operator<=(const Empty&) const {
+      return std::tie() <= std::tie();
+    }
+    inline bool operator==(const Empty&) const {
+      return std::tie() == std::tie();
+    }
+    inline bool operator>(const Empty&) const {
+      return std::tie() > std::tie();
+    }
+    inline bool operator>=(const Empty&) 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 << "Empty{";
+      os << "}";
+      return os.str();
+    }
+  };
+  class CompilerChecks {
+  public:
+    typedef std::false_type fixed_size;
+    static const char* descriptor;
+
+    ::ndk::SpAIBinder binder;
+    ::ndk::SpAIBinder nullable_binder;
+    std::vector<::ndk::SpAIBinder> binder_array;
+    std::optional<std::vector<::ndk::SpAIBinder>> nullable_binder_array;
+    std::vector<::ndk::SpAIBinder> binder_list;
+    std::optional<std::vector<::ndk::SpAIBinder>> nullable_binder_list;
+    ::ndk::ScopedFileDescriptor pfd;
+    ::ndk::ScopedFileDescriptor nullable_pfd;
+    std::vector<::ndk::ScopedFileDescriptor> pfd_array;
+    std::optional<std::vector<::ndk::ScopedFileDescriptor>> nullable_pfd_array;
+    std::vector<::ndk::ScopedFileDescriptor> pfd_list;
+    std::optional<std::vector<::ndk::ScopedFileDescriptor>> nullable_pfd_list;
+    ::aidl::android::aidl::tests::ITestService::Empty parcel;
+    std::optional<::aidl::android::aidl::tests::ITestService::Empty> nullable_parcel;
+    std::vector<::aidl::android::aidl::tests::ITestService::Empty> parcel_array;
+    std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>> nullable_parcel_array;
+    std::vector<::aidl::android::aidl::tests::ITestService::Empty> parcel_list;
+    std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>> nullable_parcel_list;
+
+    binder_status_t readFromParcel(const AParcel* parcel);
+    binder_status_t writeToParcel(AParcel* parcel) const;
+
+    inline bool operator!=(const CompilerChecks& rhs) const {
+      return std::tie(binder, nullable_binder, binder_array, nullable_binder_array, binder_list, nullable_binder_list, pfd, nullable_pfd, pfd_array, nullable_pfd_array, pfd_list, nullable_pfd_list, parcel, nullable_parcel, parcel_array, nullable_parcel_array, parcel_list, nullable_parcel_list) != std::tie(rhs.binder, rhs.nullable_binder, rhs.binder_array, rhs.nullable_binder_array, rhs.binder_list, rhs.nullable_binder_list, rhs.pfd, rhs.nullable_pfd, rhs.pfd_array, rhs.nullable_pfd_array, rhs.pfd_list, rhs.nullable_pfd_list, rhs.parcel, rhs.nullable_parcel, rhs.parcel_array, rhs.nullable_parcel_array, rhs.parcel_list, rhs.nullable_parcel_list);
+    }
+    inline bool operator<(const CompilerChecks& rhs) const {
+      return std::tie(binder, nullable_binder, binder_array, nullable_binder_array, binder_list, nullable_binder_list, pfd, nullable_pfd, pfd_array, nullable_pfd_array, pfd_list, nullable_pfd_list, parcel, nullable_parcel, parcel_array, nullable_parcel_array, parcel_list, nullable_parcel_list) < std::tie(rhs.binder, rhs.nullable_binder, rhs.binder_array, rhs.nullable_binder_array, rhs.binder_list, rhs.nullable_binder_list, rhs.pfd, rhs.nullable_pfd, rhs.pfd_array, rhs.nullable_pfd_array, rhs.pfd_list, rhs.nullable_pfd_list, rhs.parcel, rhs.nullable_parcel, rhs.parcel_array, rhs.nullable_parcel_array, rhs.parcel_list, rhs.nullable_parcel_list);
+    }
+    inline bool operator<=(const CompilerChecks& rhs) const {
+      return std::tie(binder, nullable_binder, binder_array, nullable_binder_array, binder_list, nullable_binder_list, pfd, nullable_pfd, pfd_array, nullable_pfd_array, pfd_list, nullable_pfd_list, parcel, nullable_parcel, parcel_array, nullable_parcel_array, parcel_list, nullable_parcel_list) <= std::tie(rhs.binder, rhs.nullable_binder, rhs.binder_array, rhs.nullable_binder_array, rhs.binder_list, rhs.nullable_binder_list, rhs.pfd, rhs.nullable_pfd, rhs.pfd_array, rhs.nullable_pfd_array, rhs.pfd_list, rhs.nullable_pfd_list, rhs.parcel, rhs.nullable_parcel, rhs.parcel_array, rhs.nullable_parcel_array, rhs.parcel_list, rhs.nullable_parcel_list);
+    }
+    inline bool operator==(const CompilerChecks& rhs) const {
+      return std::tie(binder, nullable_binder, binder_array, nullable_binder_array, binder_list, nullable_binder_list, pfd, nullable_pfd, pfd_array, nullable_pfd_array, pfd_list, nullable_pfd_list, parcel, nullable_parcel, parcel_array, nullable_parcel_array, parcel_list, nullable_parcel_list) == std::tie(rhs.binder, rhs.nullable_binder, rhs.binder_array, rhs.nullable_binder_array, rhs.binder_list, rhs.nullable_binder_list, rhs.pfd, rhs.nullable_pfd, rhs.pfd_array, rhs.nullable_pfd_array, rhs.pfd_list, rhs.nullable_pfd_list, rhs.parcel, rhs.nullable_parcel, rhs.parcel_array, rhs.nullable_parcel_array, rhs.parcel_list, rhs.nullable_parcel_list);
+    }
+    inline bool operator>(const CompilerChecks& rhs) const {
+      return std::tie(binder, nullable_binder, binder_array, nullable_binder_array, binder_list, nullable_binder_list, pfd, nullable_pfd, pfd_array, nullable_pfd_array, pfd_list, nullable_pfd_list, parcel, nullable_parcel, parcel_array, nullable_parcel_array, parcel_list, nullable_parcel_list) > std::tie(rhs.binder, rhs.nullable_binder, rhs.binder_array, rhs.nullable_binder_array, rhs.binder_list, rhs.nullable_binder_list, rhs.pfd, rhs.nullable_pfd, rhs.pfd_array, rhs.nullable_pfd_array, rhs.pfd_list, rhs.nullable_pfd_list, rhs.parcel, rhs.nullable_parcel, rhs.parcel_array, rhs.nullable_parcel_array, rhs.parcel_list, rhs.nullable_parcel_list);
+    }
+    inline bool operator>=(const CompilerChecks& rhs) const {
+      return std::tie(binder, nullable_binder, binder_array, nullable_binder_array, binder_list, nullable_binder_list, pfd, nullable_pfd, pfd_array, nullable_pfd_array, pfd_list, nullable_pfd_list, parcel, nullable_parcel, parcel_array, nullable_parcel_array, parcel_list, nullable_parcel_list) >= std::tie(rhs.binder, rhs.nullable_binder, rhs.binder_array, rhs.nullable_binder_array, rhs.binder_list, rhs.nullable_binder_list, rhs.pfd, rhs.nullable_pfd, rhs.pfd_array, rhs.nullable_pfd_array, rhs.pfd_list, rhs.nullable_pfd_list, rhs.parcel, rhs.nullable_parcel, rhs.parcel_array, rhs.nullable_parcel_array, rhs.parcel_list, rhs.nullable_parcel_list);
+    }
+
+    static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "CompilerChecks{";
+      os << "binder: " << ::android::internal::ToString(binder);
+      os << ", nullable_binder: " << ::android::internal::ToString(nullable_binder);
+      os << ", binder_array: " << ::android::internal::ToString(binder_array);
+      os << ", nullable_binder_array: " << ::android::internal::ToString(nullable_binder_array);
+      os << ", binder_list: " << ::android::internal::ToString(binder_list);
+      os << ", nullable_binder_list: " << ::android::internal::ToString(nullable_binder_list);
+      os << ", pfd: " << ::android::internal::ToString(pfd);
+      os << ", nullable_pfd: " << ::android::internal::ToString(nullable_pfd);
+      os << ", pfd_array: " << ::android::internal::ToString(pfd_array);
+      os << ", nullable_pfd_array: " << ::android::internal::ToString(nullable_pfd_array);
+      os << ", pfd_list: " << ::android::internal::ToString(pfd_list);
+      os << ", nullable_pfd_list: " << ::android::internal::ToString(nullable_pfd_list);
+      os << ", parcel: " << ::android::internal::ToString(parcel);
+      os << ", nullable_parcel: " << ::android::internal::ToString(nullable_parcel);
+      os << ", parcel_array: " << ::android::internal::ToString(parcel_array);
+      os << ", nullable_parcel_array: " << ::android::internal::ToString(nullable_parcel_array);
+      os << ", parcel_list: " << ::android::internal::ToString(parcel_list);
+      os << ", nullable_parcel_list: " << ::android::internal::ToString(nullable_parcel_list);
+      os << "}";
+      return os.str();
+    }
+  };
+  enum : int32_t { TEST_CONSTANT = 42 };
+  enum : int32_t { TEST_CONSTANT2 = -42 };
+  enum : int32_t { TEST_CONSTANT3 = 42 };
+  enum : int32_t { TEST_CONSTANT4 = 4 };
+  enum : int32_t { TEST_CONSTANT5 = -4 };
+  enum : int32_t { TEST_CONSTANT6 = 0 };
+  enum : int32_t { TEST_CONSTANT7 = 0 };
+  enum : int32_t { TEST_CONSTANT8 = 0 };
+  enum : int32_t { TEST_CONSTANT9 = 86 };
+  enum : int32_t { TEST_CONSTANT10 = 165 };
+  enum : int32_t { TEST_CONSTANT11 = 250 };
+  enum : int32_t { TEST_CONSTANT12 = -1 };
+  enum : int8_t { BYTE_TEST_CONSTANT = 17 };
+  enum : int64_t { LONG_TEST_CONSTANT = 1099511627776L };
+  static const char* STRING_TEST_CONSTANT;
+  static const char* STRING_TEST_CONSTANT2;
+  static const char* STRING_TEST_CONSTANT_UTF8;
+  enum : int32_t { A1 = 1 };
+  enum : int32_t { A2 = 1 };
+  enum : int32_t { A3 = 1 };
+  enum : int32_t { A4 = 1 };
+  enum : int32_t { A5 = 1 };
+  enum : int32_t { A6 = 1 };
+  enum : int32_t { A7 = 1 };
+  enum : int32_t { A8 = 1 };
+  enum : int32_t { A9 = 1 };
+  enum : int32_t { A10 = 1 };
+  enum : int32_t { A11 = 1 };
+  enum : int32_t { A12 = 1 };
+  enum : int32_t { A13 = 1 };
+  enum : int32_t { A14 = 1 };
+  enum : int32_t { A15 = 1 };
+  enum : int32_t { A16 = 1 };
+  enum : int32_t { A17 = 1 };
+  enum : int32_t { A18 = 1 };
+  enum : int32_t { A19 = 1 };
+  enum : int32_t { A20 = 1 };
+  enum : int32_t { A21 = 1 };
+  enum : int32_t { A22 = 1 };
+  enum : int32_t { A23 = 1 };
+  enum : int32_t { A24 = 1 };
+  enum : int32_t { A25 = 1 };
+  enum : int32_t { A26 = 1 };
+  enum : int32_t { A27 = 1 };
+  enum : int32_t { A28 = 1 };
+  enum : int32_t { A29 = 1 };
+  enum : int32_t { A30 = 1 };
+  enum : int32_t { A31 = 1 };
+  enum : int32_t { A32 = 1 };
+  enum : int32_t { A33 = 1 };
+  enum : int32_t { A34 = 1 };
+  enum : int32_t { A35 = 1 };
+  enum : int32_t { A36 = 1 };
+  enum : int32_t { A37 = 1 };
+  enum : int32_t { A38 = 1 };
+  enum : int32_t { A39 = 1 };
+  enum : int32_t { A40 = 1 };
+  enum : int32_t { A41 = 1 };
+  enum : int32_t { A42 = 1 };
+  enum : int32_t { A43 = 1 };
+  enum : int32_t { A44 = 1 };
+  enum : int32_t { A45 = 1 };
+  enum : int32_t { A46 = 1 };
+  enum : int32_t { A47 = 1 };
+  enum : int32_t { A48 = 1 };
+  enum : int32_t { A49 = 1 };
+  enum : int32_t { A50 = 1 };
+  enum : int32_t { A51 = 1 };
+  enum : int32_t { A52 = 1 };
+  enum : int32_t { A53 = 1 };
+  enum : int32_t { A54 = 1 };
+  enum : int32_t { A55 = 1 };
+  enum : int32_t { A56 = 1 };
+  enum : int32_t { A57 = 1 };
+  static constexpr uint32_t TRANSACTION_UnimplementedMethod = FIRST_CALL_TRANSACTION + 0;
+  static constexpr uint32_t TRANSACTION_Deprecated = FIRST_CALL_TRANSACTION + 1;
+  static constexpr uint32_t TRANSACTION_TestOneway = FIRST_CALL_TRANSACTION + 2;
+  static constexpr uint32_t TRANSACTION_RepeatBoolean = FIRST_CALL_TRANSACTION + 3;
+  static constexpr uint32_t TRANSACTION_RepeatByte = FIRST_CALL_TRANSACTION + 4;
+  static constexpr uint32_t TRANSACTION_RepeatChar = FIRST_CALL_TRANSACTION + 5;
+  static constexpr uint32_t TRANSACTION_RepeatInt = FIRST_CALL_TRANSACTION + 6;
+  static constexpr uint32_t TRANSACTION_RepeatLong = FIRST_CALL_TRANSACTION + 7;
+  static constexpr uint32_t TRANSACTION_RepeatFloat = FIRST_CALL_TRANSACTION + 8;
+  static constexpr uint32_t TRANSACTION_RepeatDouble = FIRST_CALL_TRANSACTION + 9;
+  static constexpr uint32_t TRANSACTION_RepeatString = FIRST_CALL_TRANSACTION + 10;
+  static constexpr uint32_t TRANSACTION_RepeatByteEnum = FIRST_CALL_TRANSACTION + 11;
+  static constexpr uint32_t TRANSACTION_RepeatIntEnum = FIRST_CALL_TRANSACTION + 12;
+  static constexpr uint32_t TRANSACTION_RepeatLongEnum = FIRST_CALL_TRANSACTION + 13;
+  static constexpr uint32_t TRANSACTION_ReverseBoolean = FIRST_CALL_TRANSACTION + 14;
+  static constexpr uint32_t TRANSACTION_ReverseByte = FIRST_CALL_TRANSACTION + 15;
+  static constexpr uint32_t TRANSACTION_ReverseChar = FIRST_CALL_TRANSACTION + 16;
+  static constexpr uint32_t TRANSACTION_ReverseInt = FIRST_CALL_TRANSACTION + 17;
+  static constexpr uint32_t TRANSACTION_ReverseLong = FIRST_CALL_TRANSACTION + 18;
+  static constexpr uint32_t TRANSACTION_ReverseFloat = FIRST_CALL_TRANSACTION + 19;
+  static constexpr uint32_t TRANSACTION_ReverseDouble = FIRST_CALL_TRANSACTION + 20;
+  static constexpr uint32_t TRANSACTION_ReverseString = FIRST_CALL_TRANSACTION + 21;
+  static constexpr uint32_t TRANSACTION_ReverseByteEnum = FIRST_CALL_TRANSACTION + 22;
+  static constexpr uint32_t TRANSACTION_ReverseIntEnum = FIRST_CALL_TRANSACTION + 23;
+  static constexpr uint32_t TRANSACTION_ReverseLongEnum = FIRST_CALL_TRANSACTION + 24;
+  static constexpr uint32_t TRANSACTION_GetOtherTestService = FIRST_CALL_TRANSACTION + 25;
+  static constexpr uint32_t TRANSACTION_VerifyName = FIRST_CALL_TRANSACTION + 26;
+  static constexpr uint32_t TRANSACTION_GetInterfaceArray = FIRST_CALL_TRANSACTION + 27;
+  static constexpr uint32_t TRANSACTION_VerifyNamesWithInterfaceArray = FIRST_CALL_TRANSACTION + 28;
+  static constexpr uint32_t TRANSACTION_GetNullableInterfaceArray = FIRST_CALL_TRANSACTION + 29;
+  static constexpr uint32_t TRANSACTION_VerifyNamesWithNullableInterfaceArray = FIRST_CALL_TRANSACTION + 30;
+  static constexpr uint32_t TRANSACTION_GetInterfaceList = FIRST_CALL_TRANSACTION + 31;
+  static constexpr uint32_t TRANSACTION_VerifyNamesWithInterfaceList = FIRST_CALL_TRANSACTION + 32;
+  static constexpr uint32_t TRANSACTION_ReverseStringList = FIRST_CALL_TRANSACTION + 33;
+  static constexpr uint32_t TRANSACTION_RepeatParcelFileDescriptor = FIRST_CALL_TRANSACTION + 34;
+  static constexpr uint32_t TRANSACTION_ReverseParcelFileDescriptorArray = FIRST_CALL_TRANSACTION + 35;
+  static constexpr uint32_t TRANSACTION_ThrowServiceException = FIRST_CALL_TRANSACTION + 36;
+  static constexpr uint32_t TRANSACTION_RepeatNullableIntArray = FIRST_CALL_TRANSACTION + 37;
+  static constexpr uint32_t TRANSACTION_RepeatNullableByteEnumArray = FIRST_CALL_TRANSACTION + 38;
+  static constexpr uint32_t TRANSACTION_RepeatNullableIntEnumArray = FIRST_CALL_TRANSACTION + 39;
+  static constexpr uint32_t TRANSACTION_RepeatNullableLongEnumArray = FIRST_CALL_TRANSACTION + 40;
+  static constexpr uint32_t TRANSACTION_RepeatNullableString = FIRST_CALL_TRANSACTION + 41;
+  static constexpr uint32_t TRANSACTION_RepeatNullableStringList = FIRST_CALL_TRANSACTION + 42;
+  static constexpr uint32_t TRANSACTION_RepeatNullableParcelable = FIRST_CALL_TRANSACTION + 43;
+  static constexpr uint32_t TRANSACTION_RepeatNullableParcelableArray = FIRST_CALL_TRANSACTION + 44;
+  static constexpr uint32_t TRANSACTION_RepeatNullableParcelableList = FIRST_CALL_TRANSACTION + 45;
+  static constexpr uint32_t TRANSACTION_TakesAnIBinder = FIRST_CALL_TRANSACTION + 46;
+  static constexpr uint32_t TRANSACTION_TakesANullableIBinder = FIRST_CALL_TRANSACTION + 47;
+  static constexpr uint32_t TRANSACTION_TakesAnIBinderList = FIRST_CALL_TRANSACTION + 48;
+  static constexpr uint32_t TRANSACTION_TakesANullableIBinderList = FIRST_CALL_TRANSACTION + 49;
+  static constexpr uint32_t TRANSACTION_RepeatUtf8CppString = FIRST_CALL_TRANSACTION + 50;
+  static constexpr uint32_t TRANSACTION_RepeatNullableUtf8CppString = FIRST_CALL_TRANSACTION + 51;
+  static constexpr uint32_t TRANSACTION_ReverseUtf8CppString = FIRST_CALL_TRANSACTION + 52;
+  static constexpr uint32_t TRANSACTION_ReverseNullableUtf8CppString = FIRST_CALL_TRANSACTION + 53;
+  static constexpr uint32_t TRANSACTION_ReverseUtf8CppStringList = FIRST_CALL_TRANSACTION + 54;
+  static constexpr uint32_t TRANSACTION_GetCallback = FIRST_CALL_TRANSACTION + 55;
+  static constexpr uint32_t TRANSACTION_FillOutStructuredParcelable = FIRST_CALL_TRANSACTION + 56;
+  static constexpr uint32_t TRANSACTION_RepeatExtendableParcelable = FIRST_CALL_TRANSACTION + 57;
+  static constexpr uint32_t TRANSACTION_ReverseList = FIRST_CALL_TRANSACTION + 58;
+  static constexpr uint32_t TRANSACTION_ReverseIBinderArray = FIRST_CALL_TRANSACTION + 59;
+  static constexpr uint32_t TRANSACTION_ReverseNullableIBinderArray = FIRST_CALL_TRANSACTION + 60;
+  static constexpr uint32_t TRANSACTION_GetOldNameInterface = FIRST_CALL_TRANSACTION + 61;
+  static constexpr uint32_t TRANSACTION_GetNewNameInterface = FIRST_CALL_TRANSACTION + 62;
+  static constexpr uint32_t TRANSACTION_GetCppJavaTests = FIRST_CALL_TRANSACTION + 63;
+  static constexpr uint32_t TRANSACTION_getBackendType = FIRST_CALL_TRANSACTION + 64;
+
+  static std::shared_ptr<ITestService> fromBinder(const ::ndk::SpAIBinder& binder);
+  static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<ITestService>& instance);
+  static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<ITestService>* instance);
+  static bool setDefaultImpl(const std::shared_ptr<ITestService>& impl);
+  static const std::shared_ptr<ITestService>& getDefaultImpl();
+  virtual ::ndk::ScopedAStatus UnimplementedMethod(int32_t in_arg, int32_t* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus Deprecated() __attribute__((deprecated("to make sure we have something in system/tools/aidl which does a compile check of deprecated and make sure this is reflected in goldens"))) = 0;
+  virtual ::ndk::ScopedAStatus TestOneway() = 0;
+  virtual ::ndk::ScopedAStatus RepeatBoolean(bool in_token, bool* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatByte(int8_t in_token, int8_t* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatChar(char16_t in_token, char16_t* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatInt(int32_t in_token, int32_t* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatLong(int64_t in_token, int64_t* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatFloat(float in_token, float* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatDouble(double in_token, double* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatString(const std::string& in_token, std::string* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatByteEnum(::aidl::android::aidl::tests::ByteEnum in_token, ::aidl::android::aidl::tests::ByteEnum* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatIntEnum(::aidl::android::aidl::tests::IntEnum in_token, ::aidl::android::aidl::tests::IntEnum* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatLongEnum(::aidl::android::aidl::tests::LongEnum in_token, ::aidl::android::aidl::tests::LongEnum* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseBoolean(const std::vector<bool>& in_input, std::vector<bool>* out_repeated, std::vector<bool>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseByte(const std::vector<uint8_t>& in_input, std::vector<uint8_t>* out_repeated, std::vector<uint8_t>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseChar(const std::vector<char16_t>& in_input, std::vector<char16_t>* out_repeated, std::vector<char16_t>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseInt(const std::vector<int32_t>& in_input, std::vector<int32_t>* out_repeated, std::vector<int32_t>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseLong(const std::vector<int64_t>& in_input, std::vector<int64_t>* out_repeated, std::vector<int64_t>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseFloat(const std::vector<float>& in_input, std::vector<float>* out_repeated, std::vector<float>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseDouble(const std::vector<double>& in_input, std::vector<double>* out_repeated, std::vector<double>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseString(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseByteEnum(const std::vector<::aidl::android::aidl::tests::ByteEnum>& in_input, std::vector<::aidl::android::aidl::tests::ByteEnum>* out_repeated, std::vector<::aidl::android::aidl::tests::ByteEnum>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseIntEnum(const std::vector<::aidl::android::aidl::tests::IntEnum>& in_input, std::vector<::aidl::android::aidl::tests::IntEnum>* out_repeated, std::vector<::aidl::android::aidl::tests::IntEnum>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseLongEnum(const std::vector<::aidl::android::aidl::tests::LongEnum>& in_input, std::vector<::aidl::android::aidl::tests::LongEnum>* out_repeated, std::vector<::aidl::android::aidl::tests::LongEnum>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus GetOtherTestService(const std::string& in_name, std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus VerifyName(const std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>& in_service, const std::string& in_name, bool* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus GetInterfaceArray(const std::vector<std::string>& in_names, std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus VerifyNamesWithInterfaceArray(const std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>& in_services, const std::vector<std::string>& in_names, bool* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus GetNullableInterfaceArray(const std::optional<std::vector<std::optional<std::string>>>& in_names, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus VerifyNamesWithNullableInterfaceArray(const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>& in_services, const std::optional<std::vector<std::optional<std::string>>>& in_names, bool* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus GetInterfaceList(const std::optional<std::vector<std::optional<std::string>>>& in_names, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus VerifyNamesWithInterfaceList(const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>& in_services, const std::optional<std::vector<std::optional<std::string>>>& in_names, bool* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseStringList(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatParcelFileDescriptor(const ::ndk::ScopedFileDescriptor& in_read, ::ndk::ScopedFileDescriptor* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseParcelFileDescriptorArray(const std::vector<::ndk::ScopedFileDescriptor>& in_input, std::vector<::ndk::ScopedFileDescriptor>* out_repeated, std::vector<::ndk::ScopedFileDescriptor>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ThrowServiceException(int32_t in_code) = 0;
+  virtual ::ndk::ScopedAStatus RepeatNullableIntArray(const std::optional<std::vector<int32_t>>& in_input, std::optional<std::vector<int32_t>>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatNullableByteEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::ByteEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::ByteEnum>>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatNullableIntEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::IntEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::IntEnum>>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatNullableLongEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::LongEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::LongEnum>>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatNullableString(const std::optional<std::string>& in_input, std::optional<std::string>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatNullableStringList(const std::optional<std::vector<std::optional<std::string>>>& in_input, std::optional<std::vector<std::optional<std::string>>>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatNullableParcelable(const std::optional<::aidl::android::aidl::tests::ITestService::Empty>& in_input, std::optional<::aidl::android::aidl::tests::ITestService::Empty>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatNullableParcelableArray(const std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>& in_input, std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatNullableParcelableList(const std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>& in_input, std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus TakesAnIBinder(const ::ndk::SpAIBinder& in_input) = 0;
+  virtual ::ndk::ScopedAStatus TakesANullableIBinder(const ::ndk::SpAIBinder& in_input) = 0;
+  virtual ::ndk::ScopedAStatus TakesAnIBinderList(const std::vector<::ndk::SpAIBinder>& in_input) = 0;
+  virtual ::ndk::ScopedAStatus TakesANullableIBinderList(const std::optional<std::vector<::ndk::SpAIBinder>>& in_input) = 0;
+  virtual ::ndk::ScopedAStatus RepeatUtf8CppString(const std::string& in_token, std::string* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus RepeatNullableUtf8CppString(const std::optional<std::string>& in_token, std::optional<std::string>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseUtf8CppString(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseNullableUtf8CppString(const std::optional<std::vector<std::optional<std::string>>>& in_input, std::optional<std::vector<std::optional<std::string>>>* out_repeated, std::optional<std::vector<std::optional<std::string>>>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseUtf8CppStringList(const std::optional<std::vector<std::optional<std::string>>>& in_input, std::optional<std::vector<std::optional<std::string>>>* out_repeated, std::optional<std::vector<std::optional<std::string>>>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus GetCallback(bool in_return_null, std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus FillOutStructuredParcelable(::aidl::android::aidl::tests::StructuredParcelable* in_parcel) = 0;
+  virtual ::ndk::ScopedAStatus RepeatExtendableParcelable(const ::aidl::android::aidl::tests::extension::ExtendableParcelable& in_ep, ::aidl::android::aidl::tests::extension::ExtendableParcelable* out_ep2) = 0;
+  virtual ::ndk::ScopedAStatus ReverseList(const ::aidl::android::aidl::tests::RecursiveList& in_list, ::aidl::android::aidl::tests::RecursiveList* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseIBinderArray(const std::vector<::ndk::SpAIBinder>& in_input, std::vector<::ndk::SpAIBinder>* out_repeated, std::vector<::ndk::SpAIBinder>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus ReverseNullableIBinderArray(const std::optional<std::vector<::ndk::SpAIBinder>>& in_input, std::optional<std::vector<::ndk::SpAIBinder>>* out_repeated, std::optional<std::vector<::ndk::SpAIBinder>>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus GetOldNameInterface(std::shared_ptr<::aidl::android::aidl::tests::IOldName>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus GetNewNameInterface(std::shared_ptr<::aidl::android::aidl::tests::INewName>* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus GetCppJavaTests(::ndk::SpAIBinder* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus getBackendType(::aidl::android::aidl::tests::BackendType* _aidl_return) = 0;
+private:
+  static std::shared_ptr<ITestService> default_impl;
+};
+class ITestServiceDefault : public ITestService {
+public:
+  ::ndk::ScopedAStatus UnimplementedMethod(int32_t in_arg, int32_t* _aidl_return) override;
+  ::ndk::ScopedAStatus Deprecated() override __attribute__((deprecated("to make sure we have something in system/tools/aidl which does a compile check of deprecated and make sure this is reflected in goldens")));
+  ::ndk::ScopedAStatus TestOneway() override;
+  ::ndk::ScopedAStatus RepeatBoolean(bool in_token, bool* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatByte(int8_t in_token, int8_t* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatChar(char16_t in_token, char16_t* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatInt(int32_t in_token, int32_t* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatLong(int64_t in_token, int64_t* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatFloat(float in_token, float* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatDouble(double in_token, double* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatString(const std::string& in_token, std::string* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatByteEnum(::aidl::android::aidl::tests::ByteEnum in_token, ::aidl::android::aidl::tests::ByteEnum* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatIntEnum(::aidl::android::aidl::tests::IntEnum in_token, ::aidl::android::aidl::tests::IntEnum* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatLongEnum(::aidl::android::aidl::tests::LongEnum in_token, ::aidl::android::aidl::tests::LongEnum* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseBoolean(const std::vector<bool>& in_input, std::vector<bool>* out_repeated, std::vector<bool>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseByte(const std::vector<uint8_t>& in_input, std::vector<uint8_t>* out_repeated, std::vector<uint8_t>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseChar(const std::vector<char16_t>& in_input, std::vector<char16_t>* out_repeated, std::vector<char16_t>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseInt(const std::vector<int32_t>& in_input, std::vector<int32_t>* out_repeated, std::vector<int32_t>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseLong(const std::vector<int64_t>& in_input, std::vector<int64_t>* out_repeated, std::vector<int64_t>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseFloat(const std::vector<float>& in_input, std::vector<float>* out_repeated, std::vector<float>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseDouble(const std::vector<double>& in_input, std::vector<double>* out_repeated, std::vector<double>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseString(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseByteEnum(const std::vector<::aidl::android::aidl::tests::ByteEnum>& in_input, std::vector<::aidl::android::aidl::tests::ByteEnum>* out_repeated, std::vector<::aidl::android::aidl::tests::ByteEnum>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseIntEnum(const std::vector<::aidl::android::aidl::tests::IntEnum>& in_input, std::vector<::aidl::android::aidl::tests::IntEnum>* out_repeated, std::vector<::aidl::android::aidl::tests::IntEnum>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseLongEnum(const std::vector<::aidl::android::aidl::tests::LongEnum>& in_input, std::vector<::aidl::android::aidl::tests::LongEnum>* out_repeated, std::vector<::aidl::android::aidl::tests::LongEnum>* _aidl_return) override;
+  ::ndk::ScopedAStatus GetOtherTestService(const std::string& in_name, std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>* _aidl_return) override;
+  ::ndk::ScopedAStatus VerifyName(const std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>& in_service, const std::string& in_name, bool* _aidl_return) override;
+  ::ndk::ScopedAStatus GetInterfaceArray(const std::vector<std::string>& in_names, std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>* _aidl_return) override;
+  ::ndk::ScopedAStatus VerifyNamesWithInterfaceArray(const std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>& in_services, const std::vector<std::string>& in_names, bool* _aidl_return) override;
+  ::ndk::ScopedAStatus GetNullableInterfaceArray(const std::optional<std::vector<std::optional<std::string>>>& in_names, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>* _aidl_return) override;
+  ::ndk::ScopedAStatus VerifyNamesWithNullableInterfaceArray(const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>& in_services, const std::optional<std::vector<std::optional<std::string>>>& in_names, bool* _aidl_return) override;
+  ::ndk::ScopedAStatus GetInterfaceList(const std::optional<std::vector<std::optional<std::string>>>& in_names, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>* _aidl_return) override;
+  ::ndk::ScopedAStatus VerifyNamesWithInterfaceList(const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>>& in_services, const std::optional<std::vector<std::optional<std::string>>>& in_names, bool* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseStringList(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatParcelFileDescriptor(const ::ndk::ScopedFileDescriptor& in_read, ::ndk::ScopedFileDescriptor* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseParcelFileDescriptorArray(const std::vector<::ndk::ScopedFileDescriptor>& in_input, std::vector<::ndk::ScopedFileDescriptor>* out_repeated, std::vector<::ndk::ScopedFileDescriptor>* _aidl_return) override;
+  ::ndk::ScopedAStatus ThrowServiceException(int32_t in_code) override;
+  ::ndk::ScopedAStatus RepeatNullableIntArray(const std::optional<std::vector<int32_t>>& in_input, std::optional<std::vector<int32_t>>* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatNullableByteEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::ByteEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::ByteEnum>>* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatNullableIntEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::IntEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::IntEnum>>* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatNullableLongEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::LongEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::LongEnum>>* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatNullableString(const std::optional<std::string>& in_input, std::optional<std::string>* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatNullableStringList(const std::optional<std::vector<std::optional<std::string>>>& in_input, std::optional<std::vector<std::optional<std::string>>>* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatNullableParcelable(const std::optional<::aidl::android::aidl::tests::ITestService::Empty>& in_input, std::optional<::aidl::android::aidl::tests::ITestService::Empty>* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatNullableParcelableArray(const std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>& in_input, std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatNullableParcelableList(const std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>& in_input, std::optional<std::vector<std::optional<::aidl::android::aidl::tests::ITestService::Empty>>>* _aidl_return) override;
+  ::ndk::ScopedAStatus TakesAnIBinder(const ::ndk::SpAIBinder& in_input) override;
+  ::ndk::ScopedAStatus TakesANullableIBinder(const ::ndk::SpAIBinder& in_input) override;
+  ::ndk::ScopedAStatus TakesAnIBinderList(const std::vector<::ndk::SpAIBinder>& in_input) override;
+  ::ndk::ScopedAStatus TakesANullableIBinderList(const std::optional<std::vector<::ndk::SpAIBinder>>& in_input) override;
+  ::ndk::ScopedAStatus RepeatUtf8CppString(const std::string& in_token, std::string* _aidl_return) override;
+  ::ndk::ScopedAStatus RepeatNullableUtf8CppString(const std::optional<std::string>& in_token, std::optional<std::string>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseUtf8CppString(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseNullableUtf8CppString(const std::optional<std::vector<std::optional<std::string>>>& in_input, std::optional<std::vector<std::optional<std::string>>>* out_repeated, std::optional<std::vector<std::optional<std::string>>>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseUtf8CppStringList(const std::optional<std::vector<std::optional<std::string>>>& in_input, std::optional<std::vector<std::optional<std::string>>>* out_repeated, std::optional<std::vector<std::optional<std::string>>>* _aidl_return) override;
+  ::ndk::ScopedAStatus GetCallback(bool in_return_null, std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>* _aidl_return) override;
+  ::ndk::ScopedAStatus FillOutStructuredParcelable(::aidl::android::aidl::tests::StructuredParcelable* in_parcel) override;
+  ::ndk::ScopedAStatus RepeatExtendableParcelable(const ::aidl::android::aidl::tests::extension::ExtendableParcelable& in_ep, ::aidl::android::aidl::tests::extension::ExtendableParcelable* out_ep2) override;
+  ::ndk::ScopedAStatus ReverseList(const ::aidl::android::aidl::tests::RecursiveList& in_list, ::aidl::android::aidl::tests::RecursiveList* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseIBinderArray(const std::vector<::ndk::SpAIBinder>& in_input, std::vector<::ndk::SpAIBinder>* out_repeated, std::vector<::ndk::SpAIBinder>* _aidl_return) override;
+  ::ndk::ScopedAStatus ReverseNullableIBinderArray(const std::optional<std::vector<::ndk::SpAIBinder>>& in_input, std::optional<std::vector<::ndk::SpAIBinder>>* out_repeated, std::optional<std::vector<::ndk::SpAIBinder>>* _aidl_return) override;
+  ::ndk::ScopedAStatus GetOldNameInterface(std::shared_ptr<::aidl::android::aidl::tests::IOldName>* _aidl_return) override;
+  ::ndk::ScopedAStatus GetNewNameInterface(std::shared_ptr<::aidl::android::aidl::tests::INewName>* _aidl_return) override;
+  ::ndk::ScopedAStatus GetCppJavaTests(::ndk::SpAIBinder* _aidl_return) override;
+  ::ndk::ScopedAStatus getBackendType(::aidl::android::aidl::tests::BackendType* _aidl_return) override;
+  ::ndk::SpAIBinder asBinder() override;
+  bool isRemote() override;
+};
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/IntEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/IntEnum.h
similarity index 88%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/IntEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/IntEnum.h
index b5f9ac9..7d29fd4 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/IntEnum.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/IntEnum.h
@@ -1,15 +1,16 @@
 #pragma once
 
+#include <array>
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_enums.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
-#include <array>
-#include <android/binder_enums.h>
+
 namespace aidl {
 namespace android {
 namespace aidl {
@@ -20,6 +21,14 @@
   BAZ = 2001,
 };
 
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
 [[nodiscard]] static inline std::string toString(IntEnum val) {
   switch(val) {
   case IntEnum::FOO:
@@ -48,4 +57,4 @@
 };
 #pragma clang diagnostic pop
 }  // namespace internal
-}  // namespace android
+}  // namespace ndk
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ListOfInterfaces.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ListOfInterfaces.h
new file mode 100644
index 0000000..a669820
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ListOfInterfaces.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/ListOfInterfaces.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 ListOfInterfaces {
+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::ListOfInterfaces::IEmptyInterface>& in_iface, const std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>& in_nullable_iface, const std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>& in_iface_list_in, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* out_iface_list_out, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* in_iface_list_inout, const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>& in_nullable_iface_list_in, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* out_nullable_iface_list_out, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* in_nullable_iface_list_inout, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::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::ListOfInterfaces::IEmptyInterface>& in_iface, const std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>& in_nullable_iface, const std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>& in_iface_list_in, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* out_iface_list_out, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* in_iface_list_inout, const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>& in_nullable_iface_list_in, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* out_nullable_iface_list_out, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* in_nullable_iface_list_inout, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::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::ListOfInterfaces::IEmptyInterface>& in_iface, const std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>& in_nullable_iface, const std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>& in_iface_list_in, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* out_iface_list_out, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>* in_iface_list_inout, const std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>& in_nullable_iface_list_in, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* out_nullable_iface_list_out, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>* in_nullable_iface_list_inout, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::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::ListOfInterfaces::IEmptyInterface> iface;
+    std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface> nullable_iface;
+    std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>> iface_list;
+    std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>> nullable_iface_list;
+
+    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_list, nullable_iface_list) != std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_list, rhs.nullable_iface_list);
+    }
+    inline bool operator<(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_list, nullable_iface_list) < std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_list, rhs.nullable_iface_list);
+    }
+    inline bool operator<=(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_list, nullable_iface_list) <= std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_list, rhs.nullable_iface_list);
+    }
+    inline bool operator==(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_list, nullable_iface_list) == std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_list, rhs.nullable_iface_list);
+    }
+    inline bool operator>(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_list, nullable_iface_list) > std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_list, rhs.nullable_iface_list);
+    }
+    inline bool operator>=(const MyParcelable& rhs) const {
+      return std::tie(iface, nullable_iface, iface_list, nullable_iface_list) >= std::tie(rhs.iface, rhs.nullable_iface, rhs.iface_list, rhs.nullable_iface_list);
+    }
+
+    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_list: " << ::android::internal::ToString(iface_list);
+      os << ", nullable_iface_list: " << ::android::internal::ToString(nullable_iface_list);
+      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.ListOfInterfaces.IEmptyInterface iface;
+      nullable_iface,  // android.aidl.tests.ListOfInterfaces.IEmptyInterface nullable_iface;
+      iface_list,  // List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> iface_list;
+      nullable_iface_list,  // List<android.aidl.tests.ListOfInterfaces.IEmptyInterface> nullable_iface_list;
+    };
+
+    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::ListOfInterfaces::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_list: os << "iface_list: " << ::android::internal::ToString(get<iface_list>()); break;
+      case nullable_iface_list: os << "nullable_iface_list: " << ::android::internal::ToString(get<nullable_iface_list>()); break;
+      }
+      os << "}";
+      return os.str();
+    }
+  private:
+    std::variant<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>, std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>, std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>, std::optional<std::vector<std::shared_ptr<::aidl::android::aidl::tests::ListOfInterfaces::IEmptyInterface>>>> _value;
+  };
+
+  binder_status_t readFromParcel(const AParcel* parcel);
+  binder_status_t writeToParcel(AParcel* parcel) const;
+
+  inline bool operator!=(const ListOfInterfaces&) const {
+    return std::tie() != std::tie();
+  }
+  inline bool operator<(const ListOfInterfaces&) const {
+    return std::tie() < std::tie();
+  }
+  inline bool operator<=(const ListOfInterfaces&) const {
+    return std::tie() <= std::tie();
+  }
+  inline bool operator==(const ListOfInterfaces&) const {
+    return std::tie() == std::tie();
+  }
+  inline bool operator>(const ListOfInterfaces&) const {
+    return std::tie() > std::tie();
+  }
+  inline bool operator>=(const ListOfInterfaces&) 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 << "ListOfInterfaces{";
+    os << "}";
+    return os.str();
+  }
+};
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/LongEnum.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/LongEnum.h
similarity index 88%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/LongEnum.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/LongEnum.h
index 5081c89..97ec3a0 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/LongEnum.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/LongEnum.h
@@ -1,15 +1,16 @@
 #pragma once
 
+#include <array>
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_enums.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
-#include <array>
-#include <android/binder_enums.h>
+
 namespace aidl {
 namespace android {
 namespace aidl {
@@ -20,6 +21,14 @@
   BAZ = 200000000001L,
 };
 
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
 [[nodiscard]] static inline std::string toString(LongEnum val) {
   switch(val) {
   case LongEnum::FOO:
@@ -48,4 +57,4 @@
 };
 #pragma clang diagnostic pop
 }  // namespace internal
-}  // namespace android
+}  // namespace ndk
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/OtherParcelableForToString.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/OtherParcelableForToString.h
similarity index 99%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/OtherParcelableForToString.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/OtherParcelableForToString.h
index ef75d71..904d269 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/OtherParcelableForToString.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/OtherParcelableForToString.h
@@ -1,15 +1,17 @@
 #pragma once
-#include <android/binder_interface_utils.h>
-#include <android/binder_parcelable_utils.h>
-#include <android/binder_to_string.h>
+
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
+
 namespace aidl {
 namespace android {
 namespace aidl {
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/ParcelableForToString.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ParcelableForToString.h
similarity index 99%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/ParcelableForToString.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ParcelableForToString.h
index c74001d..29de79d 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/ParcelableForToString.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/ParcelableForToString.h
@@ -1,20 +1,22 @@
 #pragma once
-#include <android/binder_interface_utils.h>
-#include <android/binder_parcelable_utils.h>
-#include <android/binder_to_string.h>
+
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
-#ifdef BINDER_STABILITY_SUPPORT
-#include <android/binder_stability.h>
-#endif  // BINDER_STABILITY_SUPPORT
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
 #include <aidl/android/aidl/tests/GenericStructuredParcelable.h>
 #include <aidl/android/aidl/tests/IntEnum.h>
 #include <aidl/android/aidl/tests/OtherParcelableForToString.h>
 #include <aidl/android/aidl/tests/StructuredParcelable.h>
 #include <aidl/android/aidl/tests/Union.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
 namespace aidl {
 namespace android {
 namespace aidl {
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/RecursiveList.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/RecursiveList.h
new file mode 100644
index 0000000..1abd135
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/RecursiveList.h
@@ -0,0 +1,63 @@
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#include <aidl/android/aidl/tests/RecursiveList.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+class RecursiveList {
+public:
+  typedef std::false_type fixed_size;
+  static const char* descriptor;
+
+  int32_t value = 0;
+  std::unique_ptr<::aidl::android::aidl::tests::RecursiveList> next;
+
+  binder_status_t readFromParcel(const AParcel* parcel);
+  binder_status_t writeToParcel(AParcel* parcel) const;
+
+  inline bool operator!=(const RecursiveList& rhs) const {
+    return std::tie(value, next) != std::tie(rhs.value, rhs.next);
+  }
+  inline bool operator<(const RecursiveList& rhs) const {
+    return std::tie(value, next) < std::tie(rhs.value, rhs.next);
+  }
+  inline bool operator<=(const RecursiveList& rhs) const {
+    return std::tie(value, next) <= std::tie(rhs.value, rhs.next);
+  }
+  inline bool operator==(const RecursiveList& rhs) const {
+    return std::tie(value, next) == std::tie(rhs.value, rhs.next);
+  }
+  inline bool operator>(const RecursiveList& rhs) const {
+    return std::tie(value, next) > std::tie(rhs.value, rhs.next);
+  }
+  inline bool operator>=(const RecursiveList& rhs) const {
+    return std::tie(value, next) >= std::tie(rhs.value, rhs.next);
+  }
+
+  static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "RecursiveList{";
+    os << "value: " << ::android::internal::ToString(value);
+    os << ", next: " << ::android::internal::ToString(next);
+    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/StructuredParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/StructuredParcelable.h
new file mode 100644
index 0000000..d5c7d5b
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/StructuredParcelable.h
@@ -0,0 +1,213 @@
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#include <aidl/android/aidl/tests/ByteEnum.h>
+#include <aidl/android/aidl/tests/ConstantExpressionEnum.h>
+#include <aidl/android/aidl/tests/IntEnum.h>
+#include <aidl/android/aidl/tests/LongEnum.h>
+#include <aidl/android/aidl/tests/StructuredParcelable.h>
+#include <aidl/android/aidl/tests/Union.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+class StructuredParcelable {
+public:
+  typedef std::false_type fixed_size;
+  static const char* descriptor;
+
+  class Empty {
+  public:
+    typedef std::false_type fixed_size;
+    static const char* descriptor;
+
+
+    binder_status_t readFromParcel(const AParcel* parcel);
+    binder_status_t writeToParcel(AParcel* parcel) const;
+
+    inline bool operator!=(const Empty&) const {
+      return std::tie() != std::tie();
+    }
+    inline bool operator<(const Empty&) const {
+      return std::tie() < std::tie();
+    }
+    inline bool operator<=(const Empty&) const {
+      return std::tie() <= std::tie();
+    }
+    inline bool operator==(const Empty&) const {
+      return std::tie() == std::tie();
+    }
+    inline bool operator>(const Empty&) const {
+      return std::tie() > std::tie();
+    }
+    inline bool operator>=(const Empty&) 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 << "Empty{";
+      os << "}";
+      return os.str();
+    }
+  };
+  std::vector<int32_t> shouldContainThreeFs;
+  int32_t f = 0;
+  std::string shouldBeJerry;
+  ::aidl::android::aidl::tests::ByteEnum shouldBeByteBar = ::aidl::android::aidl::tests::ByteEnum(0);
+  ::aidl::android::aidl::tests::IntEnum shouldBeIntBar = ::aidl::android::aidl::tests::IntEnum(0);
+  ::aidl::android::aidl::tests::LongEnum shouldBeLongBar = ::aidl::android::aidl::tests::LongEnum(0);
+  std::vector<::aidl::android::aidl::tests::ByteEnum> shouldContainTwoByteFoos;
+  std::vector<::aidl::android::aidl::tests::IntEnum> shouldContainTwoIntFoos;
+  std::vector<::aidl::android::aidl::tests::LongEnum> shouldContainTwoLongFoos;
+  std::string stringDefaultsToFoo = "foo";
+  int8_t byteDefaultsToFour = 4;
+  int32_t intDefaultsToFive = 5;
+  int64_t longDefaultsToNegativeSeven = -7L;
+  bool booleanDefaultsToTrue = true;
+  char16_t charDefaultsToC = 'C';
+  float floatDefaultsToPi = 3.140000f;
+  double doubleWithDefault = -314000000000000000.000000;
+  std::vector<int32_t> arrayDefaultsTo123 = {1, 2, 3};
+  std::vector<int32_t> arrayDefaultsToEmpty = {};
+  bool boolDefault = false;
+  int8_t byteDefault = 0;
+  int32_t intDefault = 0;
+  int64_t longDefault = 0L;
+  float floatDefault = 0.000000f;
+  double doubleDefault = 0.000000;
+  double checkDoubleFromFloat = 3.140000;
+  std::vector<std::string> checkStringArray1 = {"a", "b"};
+  std::vector<std::string> checkStringArray2 = {"a", "b"};
+  int32_t int32_min = -2147483648;
+  int32_t int32_max = 2147483647;
+  int64_t int64_max = 9223372036854775807L;
+  int32_t hexInt32_neg_1 = -1;
+  ::ndk::SpAIBinder ibinder;
+  ::aidl::android::aidl::tests::StructuredParcelable::Empty empty;
+  std::vector<uint8_t> int8_1 = {1, 1, 1, 1, 1};
+  std::vector<int32_t> int32_1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+  std::vector<int64_t> int64_1 = {1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L};
+  int32_t hexInt32_pos_1 = 1;
+  int32_t hexInt64_pos_1 = 1;
+  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_1 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
+  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_2 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
+  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_3 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
+  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_4 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
+  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_5 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
+  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_6 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
+  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_7 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
+  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_8 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
+  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_9 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
+  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_10 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
+  std::string addString1 = "hello world!";
+  std::string addString2 = "The quick brown fox jumps over the lazy dog.";
+  int32_t shouldSetBit0AndBit2 = 0;
+  std::optional<::aidl::android::aidl::tests::Union> u;
+  std::optional<::aidl::android::aidl::tests::Union> shouldBeConstS1;
+  ::aidl::android::aidl::tests::IntEnum defaultWithFoo = ::aidl::android::aidl::tests::IntEnum::FOO;
+
+  binder_status_t readFromParcel(const AParcel* parcel);
+  binder_status_t writeToParcel(AParcel* parcel) const;
+
+  inline bool operator!=(const StructuredParcelable& rhs) const {
+    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, empty, int8_1, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) != std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.empty, rhs.int8_1, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
+  }
+  inline bool operator<(const StructuredParcelable& rhs) const {
+    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, empty, int8_1, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) < std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.empty, rhs.int8_1, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
+  }
+  inline bool operator<=(const StructuredParcelable& rhs) const {
+    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, empty, int8_1, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) <= std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.empty, rhs.int8_1, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
+  }
+  inline bool operator==(const StructuredParcelable& rhs) const {
+    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, empty, int8_1, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) == std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.empty, rhs.int8_1, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
+  }
+  inline bool operator>(const StructuredParcelable& rhs) const {
+    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, empty, int8_1, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) > std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.empty, rhs.int8_1, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
+  }
+  inline bool operator>=(const StructuredParcelable& rhs) const {
+    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, empty, int8_1, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) >= std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.empty, rhs.int8_1, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
+  }
+
+  static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+  enum : int32_t { BIT0 = 1 };
+  enum : int32_t { BIT1 = 2 };
+  enum : int32_t { BIT2 = 4 };
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "StructuredParcelable{";
+    os << "shouldContainThreeFs: " << ::android::internal::ToString(shouldContainThreeFs);
+    os << ", f: " << ::android::internal::ToString(f);
+    os << ", shouldBeJerry: " << ::android::internal::ToString(shouldBeJerry);
+    os << ", shouldBeByteBar: " << ::android::internal::ToString(shouldBeByteBar);
+    os << ", shouldBeIntBar: " << ::android::internal::ToString(shouldBeIntBar);
+    os << ", shouldBeLongBar: " << ::android::internal::ToString(shouldBeLongBar);
+    os << ", shouldContainTwoByteFoos: " << ::android::internal::ToString(shouldContainTwoByteFoos);
+    os << ", shouldContainTwoIntFoos: " << ::android::internal::ToString(shouldContainTwoIntFoos);
+    os << ", shouldContainTwoLongFoos: " << ::android::internal::ToString(shouldContainTwoLongFoos);
+    os << ", stringDefaultsToFoo: " << ::android::internal::ToString(stringDefaultsToFoo);
+    os << ", byteDefaultsToFour: " << ::android::internal::ToString(byteDefaultsToFour);
+    os << ", intDefaultsToFive: " << ::android::internal::ToString(intDefaultsToFive);
+    os << ", longDefaultsToNegativeSeven: " << ::android::internal::ToString(longDefaultsToNegativeSeven);
+    os << ", booleanDefaultsToTrue: " << ::android::internal::ToString(booleanDefaultsToTrue);
+    os << ", charDefaultsToC: " << ::android::internal::ToString(charDefaultsToC);
+    os << ", floatDefaultsToPi: " << ::android::internal::ToString(floatDefaultsToPi);
+    os << ", doubleWithDefault: " << ::android::internal::ToString(doubleWithDefault);
+    os << ", arrayDefaultsTo123: " << ::android::internal::ToString(arrayDefaultsTo123);
+    os << ", arrayDefaultsToEmpty: " << ::android::internal::ToString(arrayDefaultsToEmpty);
+    os << ", boolDefault: " << ::android::internal::ToString(boolDefault);
+    os << ", byteDefault: " << ::android::internal::ToString(byteDefault);
+    os << ", intDefault: " << ::android::internal::ToString(intDefault);
+    os << ", longDefault: " << ::android::internal::ToString(longDefault);
+    os << ", floatDefault: " << ::android::internal::ToString(floatDefault);
+    os << ", doubleDefault: " << ::android::internal::ToString(doubleDefault);
+    os << ", checkDoubleFromFloat: " << ::android::internal::ToString(checkDoubleFromFloat);
+    os << ", checkStringArray1: " << ::android::internal::ToString(checkStringArray1);
+    os << ", checkStringArray2: " << ::android::internal::ToString(checkStringArray2);
+    os << ", int32_min: " << ::android::internal::ToString(int32_min);
+    os << ", int32_max: " << ::android::internal::ToString(int32_max);
+    os << ", int64_max: " << ::android::internal::ToString(int64_max);
+    os << ", hexInt32_neg_1: " << ::android::internal::ToString(hexInt32_neg_1);
+    os << ", ibinder: " << ::android::internal::ToString(ibinder);
+    os << ", empty: " << ::android::internal::ToString(empty);
+    os << ", int8_1: " << ::android::internal::ToString(int8_1);
+    os << ", int32_1: " << ::android::internal::ToString(int32_1);
+    os << ", int64_1: " << ::android::internal::ToString(int64_1);
+    os << ", hexInt32_pos_1: " << ::android::internal::ToString(hexInt32_pos_1);
+    os << ", hexInt64_pos_1: " << ::android::internal::ToString(hexInt64_pos_1);
+    os << ", const_exprs_1: " << ::android::internal::ToString(const_exprs_1);
+    os << ", const_exprs_2: " << ::android::internal::ToString(const_exprs_2);
+    os << ", const_exprs_3: " << ::android::internal::ToString(const_exprs_3);
+    os << ", const_exprs_4: " << ::android::internal::ToString(const_exprs_4);
+    os << ", const_exprs_5: " << ::android::internal::ToString(const_exprs_5);
+    os << ", const_exprs_6: " << ::android::internal::ToString(const_exprs_6);
+    os << ", const_exprs_7: " << ::android::internal::ToString(const_exprs_7);
+    os << ", const_exprs_8: " << ::android::internal::ToString(const_exprs_8);
+    os << ", const_exprs_9: " << ::android::internal::ToString(const_exprs_9);
+    os << ", const_exprs_10: " << ::android::internal::ToString(const_exprs_10);
+    os << ", addString1: " << ::android::internal::ToString(addString1);
+    os << ", addString2: " << ::android::internal::ToString(addString2);
+    os << ", shouldSetBit0AndBit2: " << ::android::internal::ToString(shouldSetBit0AndBit2);
+    os << ", u: " << ::android::internal::ToString(u);
+    os << ", shouldBeConstS1: " << ::android::internal::ToString(shouldBeConstS1);
+    os << ", defaultWithFoo: " << ::android::internal::ToString(defaultWithFoo);
+    os << "}";
+    return os.str();
+  }
+};
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/Union.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/Union.h
similarity index 96%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/Union.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/Union.h
index b90f6c4..7b6c7f8 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/Union.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/Union.h
@@ -1,21 +1,21 @@
 #pragma once
-#include <android/binder_interface_utils.h>
-#include <android/binder_parcelable_utils.h>
-#include <android/binder_to_string.h>
 
 #include <cassert>
-#include <type_traits>
-#include <utility>
-#include <variant>
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
+#include <type_traits>
+#include <utility>
+#include <variant>
 #include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#include <aidl/android/aidl/tests/ByteEnum.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
-#include <aidl/android/aidl/tests/ByteEnum.h>
 
 #ifndef __BIONIC__
 #define __assert2(a,b,c,d) ((void)0)
@@ -44,10 +44,6 @@
   static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, Union>;
 
   Union() : _value(std::in_place_index<ns>, std::vector<int32_t>({})) { }
-  Union(const Union&) = default;
-  Union(Union&&) = default;
-  Union& operator=(const Union&) = default;
-  Union& operator=(Union&&) = default;
 
   template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
   // NOLINTNEXTLINE(google-explicit-constructor)
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/UnionWithFd.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/UnionWithFd.h
similarity index 94%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/UnionWithFd.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/UnionWithFd.h
index 7d045ec..e1929bf 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/UnionWithFd.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/UnionWithFd.h
@@ -1,17 +1,17 @@
 #pragma once
-#include <android/binder_interface_utils.h>
-#include <android/binder_parcelable_utils.h>
-#include <android/binder_to_string.h>
 
 #include <cassert>
-#include <type_traits>
-#include <utility>
-#include <variant>
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
+#include <type_traits>
+#include <utility>
+#include <variant>
 #include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
@@ -38,10 +38,6 @@
   static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, UnionWithFd>;
 
   UnionWithFd() : _value(std::in_place_index<num>, int32_t(0)) { }
-  UnionWithFd(const UnionWithFd&) = default;
-  UnionWithFd(UnionWithFd&&) = default;
-  UnionWithFd& operator=(const UnionWithFd&) = default;
-  UnionWithFd& operator=(UnionWithFd&&) = default;
 
   template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
   // NOLINTNEXTLINE(google-explicit-constructor)
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnDeprecatedParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BnExtendableParcelable.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnDeprecatedParcelable.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BnExtendableParcelable.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BnMyExt.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BnMyExt.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BnMyExt2.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BnMyExt2.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BnMyExtLike.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnion.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BnMyExtLike.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpDeprecatedParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BpExtendableParcelable.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpDeprecatedParcelable.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BpExtendableParcelable.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BpMyExt.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BpMyExt.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BpMyExt2.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BpMyExt2.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BpMyExtLike.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnion.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/BpMyExtLike.h
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/ExtendableParcelable.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/ExtendableParcelable.h
new file mode 100644
index 0000000..cefe36e
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/ExtendableParcelable.h
@@ -0,0 +1,70 @@
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+class ExtendableParcelable {
+public:
+  typedef std::false_type fixed_size;
+  static const char* descriptor;
+
+  int32_t a = 0;
+  std::string b;
+  ::ndk::AParcelableHolder ext{::ndk::STABILITY_LOCAL};
+  int64_t c = 0L;
+  ::ndk::AParcelableHolder ext2{::ndk::STABILITY_LOCAL};
+
+  binder_status_t readFromParcel(const AParcel* parcel);
+  binder_status_t writeToParcel(AParcel* parcel) const;
+
+  inline bool operator!=(const ExtendableParcelable& rhs) const {
+    return std::tie(a, b, ext, c, ext2) != std::tie(rhs.a, rhs.b, rhs.ext, rhs.c, rhs.ext2);
+  }
+  inline bool operator<(const ExtendableParcelable& rhs) const {
+    return std::tie(a, b, ext, c, ext2) < std::tie(rhs.a, rhs.b, rhs.ext, rhs.c, rhs.ext2);
+  }
+  inline bool operator<=(const ExtendableParcelable& rhs) const {
+    return std::tie(a, b, ext, c, ext2) <= std::tie(rhs.a, rhs.b, rhs.ext, rhs.c, rhs.ext2);
+  }
+  inline bool operator==(const ExtendableParcelable& rhs) const {
+    return std::tie(a, b, ext, c, ext2) == std::tie(rhs.a, rhs.b, rhs.ext, rhs.c, rhs.ext2);
+  }
+  inline bool operator>(const ExtendableParcelable& rhs) const {
+    return std::tie(a, b, ext, c, ext2) > std::tie(rhs.a, rhs.b, rhs.ext, rhs.c, rhs.ext2);
+  }
+  inline bool operator>=(const ExtendableParcelable& rhs) const {
+    return std::tie(a, b, ext, c, ext2) >= std::tie(rhs.a, rhs.b, rhs.ext, rhs.c, rhs.ext2);
+  }
+
+  static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "ExtendableParcelable{";
+    os << "a: " << ::android::internal::ToString(a);
+    os << ", b: " << ::android::internal::ToString(b);
+    os << ", ext: " << ::android::internal::ToString(ext);
+    os << ", c: " << ::android::internal::ToString(c);
+    os << ", ext2: " << ::android::internal::ToString(ext2);
+    os << "}";
+    return os.str();
+  }
+};
+}  // namespace extension
+}  // 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/extension/MyExt.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/MyExt.h
new file mode 100644
index 0000000..e0d39f9
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/MyExt.h
@@ -0,0 +1,64 @@
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+class MyExt {
+public:
+  typedef std::false_type fixed_size;
+  static const char* descriptor;
+
+  int32_t a = 0;
+  std::string b;
+
+  binder_status_t readFromParcel(const AParcel* parcel);
+  binder_status_t writeToParcel(AParcel* parcel) const;
+
+  inline bool operator!=(const MyExt& rhs) const {
+    return std::tie(a, b) != std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator<(const MyExt& rhs) const {
+    return std::tie(a, b) < std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator<=(const MyExt& rhs) const {
+    return std::tie(a, b) <= std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator==(const MyExt& rhs) const {
+    return std::tie(a, b) == std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator>(const MyExt& rhs) const {
+    return std::tie(a, b) > std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator>=(const MyExt& rhs) const {
+    return std::tie(a, b) >= std::tie(rhs.a, rhs.b);
+  }
+
+  static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "MyExt{";
+    os << "a: " << ::android::internal::ToString(a);
+    os << ", b: " << ::android::internal::ToString(b);
+    os << "}";
+    return os.str();
+  }
+};
+}  // namespace extension
+}  // 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/extension/MyExt2.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/MyExt2.h
new file mode 100644
index 0000000..ea21b55
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/MyExt2.h
@@ -0,0 +1,67 @@
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#include <aidl/android/aidl/tests/extension/MyExt.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+class MyExt2 {
+public:
+  typedef std::false_type fixed_size;
+  static const char* descriptor;
+
+  int32_t a = 0;
+  ::aidl::android::aidl::tests::extension::MyExt b;
+  std::string c;
+
+  binder_status_t readFromParcel(const AParcel* parcel);
+  binder_status_t writeToParcel(AParcel* parcel) const;
+
+  inline bool operator!=(const MyExt2& rhs) const {
+    return std::tie(a, b, c) != std::tie(rhs.a, rhs.b, rhs.c);
+  }
+  inline bool operator<(const MyExt2& rhs) const {
+    return std::tie(a, b, c) < std::tie(rhs.a, rhs.b, rhs.c);
+  }
+  inline bool operator<=(const MyExt2& rhs) const {
+    return std::tie(a, b, c) <= std::tie(rhs.a, rhs.b, rhs.c);
+  }
+  inline bool operator==(const MyExt2& rhs) const {
+    return std::tie(a, b, c) == std::tie(rhs.a, rhs.b, rhs.c);
+  }
+  inline bool operator>(const MyExt2& rhs) const {
+    return std::tie(a, b, c) > std::tie(rhs.a, rhs.b, rhs.c);
+  }
+  inline bool operator>=(const MyExt2& rhs) const {
+    return std::tie(a, b, c) >= std::tie(rhs.a, rhs.b, rhs.c);
+  }
+
+  static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "MyExt2{";
+    os << "a: " << ::android::internal::ToString(a);
+    os << ", b: " << ::android::internal::ToString(b);
+    os << ", c: " << ::android::internal::ToString(c);
+    os << "}";
+    return os.str();
+  }
+};
+}  // namespace extension
+}  // 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/extension/MyExtLike.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/MyExtLike.h
new file mode 100644
index 0000000..2687e19
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/extension/MyExtLike.h
@@ -0,0 +1,64 @@
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace extension {
+class MyExtLike {
+public:
+  typedef std::false_type fixed_size;
+  static const char* descriptor;
+
+  int32_t a = 0;
+  std::string b;
+
+  binder_status_t readFromParcel(const AParcel* parcel);
+  binder_status_t writeToParcel(AParcel* parcel) const;
+
+  inline bool operator!=(const MyExtLike& rhs) const {
+    return std::tie(a, b) != std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator<(const MyExtLike& rhs) const {
+    return std::tie(a, b) < std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator<=(const MyExtLike& rhs) const {
+    return std::tie(a, b) <= std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator==(const MyExtLike& rhs) const {
+    return std::tie(a, b) == std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator>(const MyExtLike& rhs) const {
+    return std::tie(a, b) > std::tie(rhs.a, rhs.b);
+  }
+  inline bool operator>=(const MyExtLike& rhs) const {
+    return std::tie(a, b) >= std::tie(rhs.a, rhs.b);
+  }
+
+  static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "MyExtLike{";
+    os << "a: " << ::android::internal::ToString(a);
+    os << ", b: " << ::android::internal::ToString(b);
+    os << "}";
+    return os.str();
+  }
+};
+}  // namespace extension
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnionWithFd.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BnDeeplyNested.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnionWithFd.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BnDeeplyNested.h
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BnNestedService.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BnNestedService.h
new file mode 100644
index 0000000..98ec330
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BnNestedService.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "aidl/android/aidl/tests/nested/INestedService.h"
+
+#include <android/binder_ibinder.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+class BnNestedService : public ::ndk::BnCInterface<INestedService> {
+public:
+  BnNestedService();
+  virtual ~BnNestedService();
+protected:
+  ::ndk::SpAIBinder createBinder() override;
+private:
+};
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnionWithFd.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BnParcelableWithNested.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BnUnionWithFd.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BnParcelableWithNested.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnionWithFd.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BpDeeplyNested.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnionWithFd.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BpDeeplyNested.h
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BpNestedService.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BpNestedService.h
new file mode 100644
index 0000000..f7ac476
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BpNestedService.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "aidl/android/aidl/tests/nested/INestedService.h"
+
+#include <android/binder_ibinder.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+class BpNestedService : public ::ndk::BpCInterface<INestedService> {
+public:
+  explicit BpNestedService(const ::ndk::SpAIBinder& binder);
+  virtual ~BpNestedService();
+
+  ::ndk::ScopedAStatus flipStatus(const ::aidl::android::aidl::tests::nested::ParcelableWithNested& in_p, ::aidl::android::aidl::tests::nested::INestedService::Result* _aidl_return) override;
+  ::ndk::ScopedAStatus flipStatusWithCallback(::aidl::android::aidl::tests::nested::ParcelableWithNested::Status in_status, const std::shared_ptr<::aidl::android::aidl::tests::nested::INestedService::ICallback>& in_cb) override;
+};
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnionWithFd.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BpParcelableWithNested.h
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/BpUnionWithFd.h
copy to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/BpParcelableWithNested.h
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/DeeplyNested.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/DeeplyNested.h
new file mode 100644
index 0000000..f516750
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/DeeplyNested.h
@@ -0,0 +1,242 @@
+#pragma once
+
+#include <array>
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+#include <android/binder_enums.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#include <aidl/android/aidl/tests/nested/DeeplyNested.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+class DeeplyNested {
+public:
+  typedef std::false_type fixed_size;
+  static const char* descriptor;
+
+  class B {
+  public:
+    typedef std::false_type fixed_size;
+    static const char* descriptor;
+
+    class C {
+    public:
+      typedef std::false_type fixed_size;
+      static const char* descriptor;
+
+      class D {
+      public:
+        typedef std::false_type fixed_size;
+        static const char* descriptor;
+
+        enum class E : int8_t {
+          OK = 0,
+        };
+
+
+        binder_status_t readFromParcel(const AParcel* parcel);
+        binder_status_t writeToParcel(AParcel* parcel) const;
+
+        inline bool operator!=(const D&) const {
+          return std::tie() != std::tie();
+        }
+        inline bool operator<(const D&) const {
+          return std::tie() < std::tie();
+        }
+        inline bool operator<=(const D&) const {
+          return std::tie() <= std::tie();
+        }
+        inline bool operator==(const D&) const {
+          return std::tie() == std::tie();
+        }
+        inline bool operator>(const D&) const {
+          return std::tie() > std::tie();
+        }
+        inline bool operator>=(const D&) 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 << "D{";
+          os << "}";
+          return os.str();
+        }
+      };
+
+      binder_status_t readFromParcel(const AParcel* parcel);
+      binder_status_t writeToParcel(AParcel* parcel) const;
+
+      inline bool operator!=(const C&) const {
+        return std::tie() != std::tie();
+      }
+      inline bool operator<(const C&) const {
+        return std::tie() < std::tie();
+      }
+      inline bool operator<=(const C&) const {
+        return std::tie() <= std::tie();
+      }
+      inline bool operator==(const C&) const {
+        return std::tie() == std::tie();
+      }
+      inline bool operator>(const C&) const {
+        return std::tie() > std::tie();
+      }
+      inline bool operator>=(const C&) 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 << "C{";
+        os << "}";
+        return os.str();
+      }
+    };
+
+    binder_status_t readFromParcel(const AParcel* parcel);
+    binder_status_t writeToParcel(AParcel* parcel) const;
+
+    inline bool operator!=(const B&) const {
+      return std::tie() != std::tie();
+    }
+    inline bool operator<(const B&) const {
+      return std::tie() < std::tie();
+    }
+    inline bool operator<=(const B&) const {
+      return std::tie() <= std::tie();
+    }
+    inline bool operator==(const B&) const {
+      return std::tie() == std::tie();
+    }
+    inline bool operator>(const B&) const {
+      return std::tie() > std::tie();
+    }
+    inline bool operator>=(const B&) 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 << "B{";
+      os << "}";
+      return os.str();
+    }
+  };
+  class A {
+  public:
+    typedef std::false_type fixed_size;
+    static const char* descriptor;
+
+    ::aidl::android::aidl::tests::nested::DeeplyNested::B::C::D::E e = ::aidl::android::aidl::tests::nested::DeeplyNested::B::C::D::E::OK;
+
+    binder_status_t readFromParcel(const AParcel* parcel);
+    binder_status_t writeToParcel(AParcel* parcel) const;
+
+    inline bool operator!=(const A& rhs) const {
+      return std::tie(e) != std::tie(rhs.e);
+    }
+    inline bool operator<(const A& rhs) const {
+      return std::tie(e) < std::tie(rhs.e);
+    }
+    inline bool operator<=(const A& rhs) const {
+      return std::tie(e) <= std::tie(rhs.e);
+    }
+    inline bool operator==(const A& rhs) const {
+      return std::tie(e) == std::tie(rhs.e);
+    }
+    inline bool operator>(const A& rhs) const {
+      return std::tie(e) > std::tie(rhs.e);
+    }
+    inline bool operator>=(const A& rhs) const {
+      return std::tie(e) >= std::tie(rhs.e);
+    }
+
+    static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "A{";
+      os << "e: " << ::android::internal::ToString(e);
+      os << "}";
+      return os.str();
+    }
+  };
+
+  binder_status_t readFromParcel(const AParcel* parcel);
+  binder_status_t writeToParcel(AParcel* parcel) const;
+
+  inline bool operator!=(const DeeplyNested&) const {
+    return std::tie() != std::tie();
+  }
+  inline bool operator<(const DeeplyNested&) const {
+    return std::tie() < std::tie();
+  }
+  inline bool operator<=(const DeeplyNested&) const {
+    return std::tie() <= std::tie();
+  }
+  inline bool operator==(const DeeplyNested&) const {
+    return std::tie() == std::tie();
+  }
+  inline bool operator>(const DeeplyNested&) const {
+    return std::tie() > std::tie();
+  }
+  inline bool operator>=(const DeeplyNested&) 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 << "DeeplyNested{";
+    os << "}";
+    return os.str();
+  }
+};
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+[[nodiscard]] static inline std::string toString(DeeplyNested::B::C::D::E val) {
+  switch(val) {
+  case DeeplyNested::B::C::D::E::OK:
+    return "OK";
+  default:
+    return std::to_string(static_cast<int8_t>(val));
+  }
+}
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace ndk {
+namespace internal {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++17-extensions"
+template <>
+constexpr inline std::array<aidl::android::aidl::tests::nested::DeeplyNested::B::C::D::E, 1> enum_values<aidl::android::aidl::tests::nested::DeeplyNested::B::C::D::E> = {
+  aidl::android::aidl::tests::nested::DeeplyNested::B::C::D::E::OK,
+};
+#pragma clang diagnostic pop
+}  // namespace internal
+}  // namespace ndk
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/INestedService.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/INestedService.h
new file mode 100644
index 0000000..ef526d1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/INestedService.h
@@ -0,0 +1,129 @@
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#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/nested/INestedService.h>
+#include <aidl/android/aidl/tests/nested/ParcelableWithNested.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+class INestedService : public ::ndk::ICInterface {
+public:
+  static const char* descriptor;
+  INestedService();
+  virtual ~INestedService();
+
+  class Result {
+  public:
+    typedef std::false_type fixed_size;
+    static const char* descriptor;
+
+    ::aidl::android::aidl::tests::nested::ParcelableWithNested::Status status = ::aidl::android::aidl::tests::nested::ParcelableWithNested::Status::OK;
+
+    binder_status_t readFromParcel(const AParcel* parcel);
+    binder_status_t writeToParcel(AParcel* parcel) const;
+
+    inline bool operator!=(const Result& rhs) const {
+      return std::tie(status) != std::tie(rhs.status);
+    }
+    inline bool operator<(const Result& rhs) const {
+      return std::tie(status) < std::tie(rhs.status);
+    }
+    inline bool operator<=(const Result& rhs) const {
+      return std::tie(status) <= std::tie(rhs.status);
+    }
+    inline bool operator==(const Result& rhs) const {
+      return std::tie(status) == std::tie(rhs.status);
+    }
+    inline bool operator>(const Result& rhs) const {
+      return std::tie(status) > std::tie(rhs.status);
+    }
+    inline bool operator>=(const Result& rhs) const {
+      return std::tie(status) >= std::tie(rhs.status);
+    }
+
+    static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+    inline std::string toString() const {
+      std::ostringstream os;
+      os << "Result{";
+      os << "status: " << ::android::internal::ToString(status);
+      os << "}";
+      return os.str();
+    }
+  };
+  class ICallback : public ::ndk::ICInterface {
+  public:
+    static const char* descriptor;
+    ICallback();
+    virtual ~ICallback();
+
+    static constexpr uint32_t TRANSACTION_done = FIRST_CALL_TRANSACTION + 0;
+
+    static std::shared_ptr<ICallback> fromBinder(const ::ndk::SpAIBinder& binder);
+    static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<ICallback>& instance);
+    static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<ICallback>* instance);
+    static bool setDefaultImpl(const std::shared_ptr<ICallback>& impl);
+    static const std::shared_ptr<ICallback>& getDefaultImpl();
+    virtual ::ndk::ScopedAStatus done(::aidl::android::aidl::tests::nested::ParcelableWithNested::Status in_status) = 0;
+  private:
+    static std::shared_ptr<ICallback> default_impl;
+  };
+  class ICallbackDefault : public ICallback {
+  public:
+    ::ndk::ScopedAStatus done(::aidl::android::aidl::tests::nested::ParcelableWithNested::Status in_status) override;
+    ::ndk::SpAIBinder asBinder() override;
+    bool isRemote() override;
+  };
+  class BpCallback : public ::ndk::BpCInterface<ICallback> {
+  public:
+    explicit BpCallback(const ::ndk::SpAIBinder& binder);
+    virtual ~BpCallback();
+
+    ::ndk::ScopedAStatus done(::aidl::android::aidl::tests::nested::ParcelableWithNested::Status in_status) override;
+  };
+  class BnCallback : public ::ndk::BnCInterface<ICallback> {
+  public:
+    BnCallback();
+    virtual ~BnCallback();
+  protected:
+    ::ndk::SpAIBinder createBinder() override;
+  private:
+  };
+  static constexpr uint32_t TRANSACTION_flipStatus = FIRST_CALL_TRANSACTION + 0;
+  static constexpr uint32_t TRANSACTION_flipStatusWithCallback = FIRST_CALL_TRANSACTION + 1;
+
+  static std::shared_ptr<INestedService> fromBinder(const ::ndk::SpAIBinder& binder);
+  static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<INestedService>& instance);
+  static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<INestedService>* instance);
+  static bool setDefaultImpl(const std::shared_ptr<INestedService>& impl);
+  static const std::shared_ptr<INestedService>& getDefaultImpl();
+  virtual ::ndk::ScopedAStatus flipStatus(const ::aidl::android::aidl::tests::nested::ParcelableWithNested& in_p, ::aidl::android::aidl::tests::nested::INestedService::Result* _aidl_return) = 0;
+  virtual ::ndk::ScopedAStatus flipStatusWithCallback(::aidl::android::aidl::tests::nested::ParcelableWithNested::Status in_status, const std::shared_ptr<::aidl::android::aidl::tests::nested::INestedService::ICallback>& in_cb) = 0;
+private:
+  static std::shared_ptr<INestedService> default_impl;
+};
+class INestedServiceDefault : public INestedService {
+public:
+  ::ndk::ScopedAStatus flipStatus(const ::aidl::android::aidl::tests::nested::ParcelableWithNested& in_p, ::aidl::android::aidl::tests::nested::INestedService::Result* _aidl_return) override;
+  ::ndk::ScopedAStatus flipStatusWithCallback(::aidl::android::aidl::tests::nested::ParcelableWithNested::Status in_status, const std::shared_ptr<::aidl::android::aidl::tests::nested::INestedService::ICallback>& in_cb) override;
+  ::ndk::SpAIBinder asBinder() override;
+  bool isRemote() override;
+};
+}  // namespace nested
+}  // 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/nested/ParcelableWithNested.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/ParcelableWithNested.h
new file mode 100644
index 0000000..60cee94
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/nested/ParcelableWithNested.h
@@ -0,0 +1,102 @@
+#pragma once
+
+#include <array>
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+#include <android/binder_enums.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#include <aidl/android/aidl/tests/nested/ParcelableWithNested.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+class ParcelableWithNested {
+public:
+  typedef std::false_type fixed_size;
+  static const char* descriptor;
+
+  enum class Status : int8_t {
+    OK = 0,
+    NOT_OK = 1,
+  };
+
+  ::aidl::android::aidl::tests::nested::ParcelableWithNested::Status status = ::aidl::android::aidl::tests::nested::ParcelableWithNested::Status::OK;
+
+  binder_status_t readFromParcel(const AParcel* parcel);
+  binder_status_t writeToParcel(AParcel* parcel) const;
+
+  inline bool operator!=(const ParcelableWithNested& rhs) const {
+    return std::tie(status) != std::tie(rhs.status);
+  }
+  inline bool operator<(const ParcelableWithNested& rhs) const {
+    return std::tie(status) < std::tie(rhs.status);
+  }
+  inline bool operator<=(const ParcelableWithNested& rhs) const {
+    return std::tie(status) <= std::tie(rhs.status);
+  }
+  inline bool operator==(const ParcelableWithNested& rhs) const {
+    return std::tie(status) == std::tie(rhs.status);
+  }
+  inline bool operator>(const ParcelableWithNested& rhs) const {
+    return std::tie(status) > std::tie(rhs.status);
+  }
+  inline bool operator>=(const ParcelableWithNested& rhs) const {
+    return std::tie(status) >= std::tie(rhs.status);
+  }
+
+  static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
+  inline std::string toString() const {
+    std::ostringstream os;
+    os << "ParcelableWithNested{";
+    os << "status: " << ::android::internal::ToString(status);
+    os << "}";
+    return os.str();
+  }
+};
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace nested {
+[[nodiscard]] static inline std::string toString(ParcelableWithNested::Status val) {
+  switch(val) {
+  case ParcelableWithNested::Status::OK:
+    return "OK";
+  case ParcelableWithNested::Status::NOT_OK:
+    return "NOT_OK";
+  default:
+    return std::to_string(static_cast<int8_t>(val));
+  }
+}
+}  // namespace nested
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace ndk {
+namespace internal {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wc++17-extensions"
+template <>
+constexpr inline std::array<aidl::android::aidl::tests::nested::ParcelableWithNested::Status, 2> enum_values<aidl::android::aidl::tests::nested::ParcelableWithNested::Status> = {
+  aidl::android::aidl::tests::nested::ParcelableWithNested::Status::OK,
+  aidl::android::aidl::tests::nested::ParcelableWithNested::Status::NOT_OK,
+};
+#pragma clang diagnostic pop
+}  // namespace internal
+}  // namespace ndk
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/permission/BnProtected.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/permission/BnProtected.h
new file mode 100644
index 0000000..150c5b8
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/permission/BnProtected.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "aidl/android/aidl/tests/permission/IProtected.h"
+
+#include <android/binder_ibinder.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+class BnProtected : public ::ndk::BnCInterface<IProtected> {
+public:
+  BnProtected();
+  virtual ~BnProtected();
+protected:
+  ::ndk::SpAIBinder createBinder() override;
+private:
+};
+}  // namespace permission
+}  // 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/permission/BnProtectedInterface.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/permission/BnProtectedInterface.h
new file mode 100644
index 0000000..ac2a46c
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/permission/BnProtectedInterface.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "aidl/android/aidl/tests/permission/IProtectedInterface.h"
+
+#include <android/binder_ibinder.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+class BnProtectedInterface : public ::ndk::BnCInterface<IProtectedInterface> {
+public:
+  BnProtectedInterface();
+  virtual ~BnProtectedInterface();
+protected:
+  ::ndk::SpAIBinder createBinder() override;
+private:
+};
+}  // namespace permission
+}  // 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/permission/BpProtected.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/permission/BpProtected.h
new file mode 100644
index 0000000..f3d8ee9
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/permission/BpProtected.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include "aidl/android/aidl/tests/permission/IProtected.h"
+
+#include <android/binder_ibinder.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+class BpProtected : public ::ndk::BpCInterface<IProtected> {
+public:
+  explicit BpProtected(const ::ndk::SpAIBinder& binder);
+  virtual ~BpProtected();
+
+  ::ndk::ScopedAStatus PermissionProtected() override;
+  ::ndk::ScopedAStatus MultiplePermissionsAll() override;
+  ::ndk::ScopedAStatus MultiplePermissionsAny() override;
+};
+}  // namespace permission
+}  // 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/permission/BpProtectedInterface.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/permission/BpProtectedInterface.h
new file mode 100644
index 0000000..7878862
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/permission/BpProtectedInterface.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include "aidl/android/aidl/tests/permission/IProtectedInterface.h"
+
+#include <android/binder_ibinder.h>
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+class BpProtectedInterface : public ::ndk::BpCInterface<IProtectedInterface> {
+public:
+  explicit BpProtectedInterface(const ::ndk::SpAIBinder& binder);
+  virtual ~BpProtectedInterface();
+
+  ::ndk::ScopedAStatus Method1() override;
+  ::ndk::ScopedAStatus Method2() override;
+};
+}  // namespace permission
+}  // 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/permission/IProtected.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/permission/IProtected.h
new file mode 100644
index 0000000..b3bc190
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/permission/IProtected.h
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+#include <android/binder_interface_utils.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+class IProtected : public ::ndk::ICInterface {
+public:
+  static const char* descriptor;
+  IProtected();
+  virtual ~IProtected();
+
+  static constexpr uint32_t TRANSACTION_PermissionProtected = FIRST_CALL_TRANSACTION + 0;
+  static constexpr uint32_t TRANSACTION_MultiplePermissionsAll = FIRST_CALL_TRANSACTION + 1;
+  static constexpr uint32_t TRANSACTION_MultiplePermissionsAny = FIRST_CALL_TRANSACTION + 2;
+
+  static std::shared_ptr<IProtected> fromBinder(const ::ndk::SpAIBinder& binder);
+  static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<IProtected>& instance);
+  static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<IProtected>* instance);
+  static bool setDefaultImpl(const std::shared_ptr<IProtected>& impl);
+  static const std::shared_ptr<IProtected>& getDefaultImpl();
+  virtual ::ndk::ScopedAStatus PermissionProtected() = 0;
+  virtual ::ndk::ScopedAStatus MultiplePermissionsAll() = 0;
+  virtual ::ndk::ScopedAStatus MultiplePermissionsAny() = 0;
+private:
+  static std::shared_ptr<IProtected> default_impl;
+};
+class IProtectedDefault : public IProtected {
+public:
+  ::ndk::ScopedAStatus PermissionProtected() override;
+  ::ndk::ScopedAStatus MultiplePermissionsAll() override;
+  ::ndk::ScopedAStatus MultiplePermissionsAny() override;
+  ::ndk::SpAIBinder asBinder() override;
+  bool isRemote() override;
+};
+}  // namespace permission
+}  // 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/permission/IProtectedInterface.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/permission/IProtectedInterface.h
new file mode 100644
index 0000000..2afb203
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/permission/IProtectedInterface.h
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <vector>
+#include <android/binder_interface_utils.h>
+#ifdef BINDER_STABILITY_SUPPORT
+#include <android/binder_stability.h>
+#endif  // BINDER_STABILITY_SUPPORT
+
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace tests {
+namespace permission {
+class IProtectedInterface : public ::ndk::ICInterface {
+public:
+  static const char* descriptor;
+  IProtectedInterface();
+  virtual ~IProtectedInterface();
+
+  static constexpr uint32_t TRANSACTION_Method1 = FIRST_CALL_TRANSACTION + 0;
+  static constexpr uint32_t TRANSACTION_Method2 = FIRST_CALL_TRANSACTION + 1;
+
+  static std::shared_ptr<IProtectedInterface> fromBinder(const ::ndk::SpAIBinder& binder);
+  static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<IProtectedInterface>& instance);
+  static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<IProtectedInterface>* instance);
+  static bool setDefaultImpl(const std::shared_ptr<IProtectedInterface>& impl);
+  static const std::shared_ptr<IProtectedInterface>& getDefaultImpl();
+  virtual ::ndk::ScopedAStatus Method1() = 0;
+  virtual ::ndk::ScopedAStatus Method2() = 0;
+private:
+  static std::shared_ptr<IProtectedInterface> default_impl;
+};
+class IProtectedInterfaceDefault : public IProtectedInterface {
+public:
+  ::ndk::ScopedAStatus Method1() override;
+  ::ndk::ScopedAStatus Method2() override;
+  ::ndk::SpAIBinder asBinder() override;
+  bool isRemote() override;
+};
+}  // namespace permission
+}  // namespace tests
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/BnEnumUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/BnEnumUnion.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/BnEnumUnion.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/BnEnumUnion.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/BnUnionInUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/BnUnionInUnion.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/BnUnionInUnion.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/BnUnionInUnion.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/BpEnumUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/BpEnumUnion.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/BpEnumUnion.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/BpEnumUnion.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/BpUnionInUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/BpUnionInUnion.h
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/BpUnionInUnion.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/BpUnionInUnion.h
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/EnumUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/EnumUnion.h
similarity index 95%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/EnumUnion.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/EnumUnion.h
index ef1345c..77c10d1 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/EnumUnion.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/EnumUnion.h
@@ -1,22 +1,22 @@
 #pragma once
-#include <android/binder_interface_utils.h>
-#include <android/binder_parcelable_utils.h>
-#include <android/binder_to_string.h>
 
 #include <cassert>
-#include <type_traits>
-#include <utility>
-#include <variant>
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
+#include <type_traits>
+#include <utility>
+#include <variant>
 #include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#include <aidl/android/aidl/tests/IntEnum.h>
+#include <aidl/android/aidl/tests/LongEnum.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
-#include <aidl/android/aidl/tests/IntEnum.h>
-#include <aidl/android/aidl/tests/LongEnum.h>
 
 #ifndef __BIONIC__
 #define __assert2(a,b,c,d) ((void)0)
@@ -41,10 +41,6 @@
   static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, EnumUnion>;
 
   EnumUnion() : _value(std::in_place_index<intEnum>, ::aidl::android::aidl::tests::IntEnum(::aidl::android::aidl::tests::IntEnum::FOO)) { }
-  EnumUnion(const EnumUnion&) = default;
-  EnumUnion(EnumUnion&&) = default;
-  EnumUnion& operator=(const EnumUnion&) = default;
-  EnumUnion& operator=(EnumUnion&&) = default;
 
   template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
   // NOLINTNEXTLINE(google-explicit-constructor)
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/UnionInUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/UnionInUnion.h
similarity index 94%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/UnionInUnion.h
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/UnionInUnion.h
index 9d57be4..8dc56f2 100644
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/unions/UnionInUnion.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/UnionInUnion.h
@@ -1,21 +1,21 @@
 #pragma once
-#include <android/binder_interface_utils.h>
-#include <android/binder_parcelable_utils.h>
-#include <android/binder_to_string.h>
 
 #include <cassert>
-#include <type_traits>
-#include <utility>
-#include <variant>
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
+#include <type_traits>
+#include <utility>
+#include <variant>
 #include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#include <aidl/android/aidl/tests/unions/EnumUnion.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
-#include <aidl/android/aidl/tests/unions/EnumUnion.h>
 
 #ifndef __BIONIC__
 #define __assert2(a,b,c,d) ((void)0)
@@ -40,10 +40,6 @@
   static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, UnionInUnion>;
 
   UnionInUnion() : _value(std::in_place_index<first>, ::aidl::android::aidl::tests::unions::EnumUnion()) { }
-  UnionInUnion(const UnionInUnion&) = default;
-  UnionInUnion(UnionInUnion&&) = default;
-  UnionInUnion& operator=(const UnionInUnion&) = default;
-  UnionInUnion& operator=(UnionInUnion&&) = default;
 
   template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
   // NOLINTNEXTLINE(google-explicit-constructor)
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp b/tests/golden_output/aidl-test-interface-ndk-source/gen/timestamp
similarity index 100%
rename from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp
rename to tests/golden_output/aidl-test-interface-ndk-source/gen/timestamp
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/DeprecatedParcelable.cpp b/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/DeprecatedParcelable.cpp
deleted file mode 100644
index 13fc6c2..0000000
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/DeprecatedParcelable.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "aidl/android/aidl/tests/DeprecatedParcelable.h"
-
-#include <android/binder_parcel_utils.h>
-
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace tests {
-const char* DeprecatedParcelable::descriptor = "android.aidl.tests.DeprecatedParcelable";
-
-binder_status_t DeprecatedParcelable::readFromParcel(const AParcel* parcel) {
-  int32_t _aidl_parcelable_size;
-  int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  binder_status_t _aidl_ret_status = AParcel_readInt32(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(parcel, _aidl_start_pos + _aidl_parcelable_size);
-  return _aidl_ret_status;
-}
-binder_status_t DeprecatedParcelable::writeToParcel(AParcel* parcel) const {
-  binder_status_t _aidl_ret_status;
-  size_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  _aidl_ret_status = AParcel_writeInt32(parcel, 0);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  size_t _aidl_end_pos = AParcel_getDataPosition(parcel);
-  AParcel_setDataPosition(parcel, _aidl_start_pos);
-  AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);
-  AParcel_setDataPosition(parcel, _aidl_end_pos);
-  return _aidl_ret_status;
-}
-
-}  // namespace tests
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/OtherParcelableForToString.cpp b/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/OtherParcelableForToString.cpp
deleted file mode 100644
index 17322d8..0000000
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/OtherParcelableForToString.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "aidl/android/aidl/tests/OtherParcelableForToString.h"
-
-#include <android/binder_parcel_utils.h>
-
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace tests {
-const char* OtherParcelableForToString::descriptor = "android.aidl.tests.OtherParcelableForToString";
-
-binder_status_t OtherParcelableForToString::readFromParcel(const AParcel* parcel) {
-  int32_t _aidl_parcelable_size;
-  int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  binder_status_t _aidl_ret_status = AParcel_readInt32(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(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readString(parcel, &field);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-  return _aidl_ret_status;
-}
-binder_status_t OtherParcelableForToString::writeToParcel(AParcel* parcel) const {
-  binder_status_t _aidl_ret_status;
-  size_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  _aidl_ret_status = AParcel_writeInt32(parcel, 0);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeString(parcel, field);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  size_t _aidl_end_pos = AParcel_getDataPosition(parcel);
-  AParcel_setDataPosition(parcel, _aidl_start_pos);
-  AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);
-  AParcel_setDataPosition(parcel, _aidl_end_pos);
-  return _aidl_ret_status;
-}
-
-}  // namespace tests
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ParcelableForToString.cpp b/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ParcelableForToString.cpp
deleted file mode 100644
index a5ad0a7..0000000
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ParcelableForToString.cpp
+++ /dev/null
@@ -1,268 +0,0 @@
-#include "aidl/android/aidl/tests/ParcelableForToString.h"
-
-#include <android/binder_parcel_utils.h>
-
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace tests {
-const char* ParcelableForToString::descriptor = "android.aidl.tests.ParcelableForToString";
-
-binder_status_t ParcelableForToString::readFromParcel(const AParcel* parcel) {
-  int32_t _aidl_parcelable_size;
-  int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  binder_status_t _aidl_ret_status = AParcel_readInt32(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(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, &intValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &intArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt64(parcel, &longValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &longArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readDouble(parcel, &doubleValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &doubleArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readFloat(parcel, &floatValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &floatArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readByte(parcel, &byteValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &byteArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readBool(parcel, &booleanValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &booleanArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readString(parcel, &stringValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &stringArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &stringList);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readParcelable(parcel, &parcelableValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &parcelableArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, reinterpret_cast<int32_t*>(&enumValue));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32Array(parcel, static_cast<void*>(&enumArray), ndk::AParcel_stdVectorAllocator<int32_t>);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &nullArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &nullList);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readParcelable(parcel, &parcelableGeneric);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readParcelable(parcel, &unionValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-  return _aidl_ret_status;
-}
-binder_status_t ParcelableForToString::writeToParcel(AParcel* parcel) const {
-  binder_status_t _aidl_ret_status;
-  size_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  _aidl_ret_status = AParcel_writeInt32(parcel, 0);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, intValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, intArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt64(parcel, longValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, longArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeDouble(parcel, doubleValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, doubleArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeFloat(parcel, floatValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, floatArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeByte(parcel, byteValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, byteArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeBool(parcel, booleanValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, booleanArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeString(parcel, stringValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, stringArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, stringList);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeParcelable(parcel, parcelableValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, parcelableArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, static_cast<int32_t>(enumValue));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32Array(parcel, reinterpret_cast<const int32_t*>(enumArray.data()), enumArray.size());
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, nullArray);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, nullList);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeParcelable(parcel, parcelableGeneric);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeParcelable(parcel, unionValue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  size_t _aidl_end_pos = AParcel_getDataPosition(parcel);
-  AParcel_setDataPosition(parcel, _aidl_start_pos);
-  AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);
-  AParcel_setDataPosition(parcel, _aidl_end_pos);
-  return _aidl_ret_status;
-}
-
-}  // namespace tests
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ParcelableForToString.cpp.d b/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ParcelableForToString.cpp.d
deleted file mode 100644
index 69fcacb..0000000
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ParcelableForToString.cpp.d
+++ /dev/null
@@ -1,7 +0,0 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/ParcelableForToString.cpp : \
-  system/tools/aidl/tests/android/aidl/tests/ParcelableForToString.aidl \
-  system/tools/aidl/tests/android/aidl/tests/GenericStructuredParcelable.aidl \
-  system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
-  system/tools/aidl/tests/android/aidl/tests/OtherParcelableForToString.aidl \
-  system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl \
-  system/tools/aidl/tests/android/aidl/tests/Union.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/StructuredParcelable.cpp b/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/StructuredParcelable.cpp
deleted file mode 100644
index 2d7588a..0000000
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/StructuredParcelable.cpp
+++ /dev/null
@@ -1,568 +0,0 @@
-#include "aidl/android/aidl/tests/StructuredParcelable.h"
-
-#include <android/binder_parcel_utils.h>
-
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace tests {
-const char* StructuredParcelable::descriptor = "android.aidl.tests.StructuredParcelable";
-
-binder_status_t StructuredParcelable::readFromParcel(const AParcel* parcel) {
-  int32_t _aidl_parcelable_size;
-  int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  binder_status_t _aidl_ret_status = AParcel_readInt32(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(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &shouldContainThreeFs);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, &f);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readString(parcel, &shouldBeJerry);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readByte(parcel, reinterpret_cast<int8_t*>(&shouldBeByteBar));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, reinterpret_cast<int32_t*>(&shouldBeIntBar));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt64(parcel, reinterpret_cast<int64_t*>(&shouldBeLongBar));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readByteArray(parcel, static_cast<void*>(&shouldContainTwoByteFoos), ndk::AParcel_stdVectorAllocator<int8_t>);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32Array(parcel, static_cast<void*>(&shouldContainTwoIntFoos), ndk::AParcel_stdVectorAllocator<int32_t>);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt64Array(parcel, static_cast<void*>(&shouldContainTwoLongFoos), ndk::AParcel_stdVectorAllocator<int64_t>);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readString(parcel, &stringDefaultsToFoo);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readByte(parcel, &byteDefaultsToFour);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, &intDefaultsToFive);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt64(parcel, &longDefaultsToNegativeSeven);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readBool(parcel, &booleanDefaultsToTrue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readChar(parcel, &charDefaultsToC);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readFloat(parcel, &floatDefaultsToPi);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readDouble(parcel, &doubleWithDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &arrayDefaultsTo123);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &arrayDefaultsToEmpty);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readBool(parcel, &boolDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readByte(parcel, &byteDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, &intDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt64(parcel, &longDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readFloat(parcel, &floatDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readDouble(parcel, &doubleDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readDouble(parcel, &checkDoubleFromFloat);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &checkStringArray1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &checkStringArray2);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, &int32_min);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, &int32_max);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt64(parcel, &int64_max);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, &hexInt32_neg_1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readNullableStrongBinder(parcel, &ibinder);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &int32_1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readVector(parcel, &int64_1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, &hexInt32_pos_1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, &hexInt64_pos_1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, reinterpret_cast<int32_t*>(&const_exprs_1));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, reinterpret_cast<int32_t*>(&const_exprs_2));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, reinterpret_cast<int32_t*>(&const_exprs_3));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, reinterpret_cast<int32_t*>(&const_exprs_4));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, reinterpret_cast<int32_t*>(&const_exprs_5));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, reinterpret_cast<int32_t*>(&const_exprs_6));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, reinterpret_cast<int32_t*>(&const_exprs_7));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, reinterpret_cast<int32_t*>(&const_exprs_8));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, reinterpret_cast<int32_t*>(&const_exprs_9));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, reinterpret_cast<int32_t*>(&const_exprs_10));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readString(parcel, &addString1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readString(parcel, &addString2);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, &shouldSetBit0AndBit2);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readNullableParcelable(parcel, &u);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readNullableParcelable(parcel, &shouldBeConstS1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, reinterpret_cast<int32_t*>(&defaultWithFoo));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-  return _aidl_ret_status;
-}
-binder_status_t StructuredParcelable::writeToParcel(AParcel* parcel) const {
-  binder_status_t _aidl_ret_status;
-  size_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  _aidl_ret_status = AParcel_writeInt32(parcel, 0);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, shouldContainThreeFs);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, f);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeString(parcel, shouldBeJerry);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeByte(parcel, static_cast<int8_t>(shouldBeByteBar));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, static_cast<int32_t>(shouldBeIntBar));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt64(parcel, static_cast<int64_t>(shouldBeLongBar));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeByteArray(parcel, reinterpret_cast<const int8_t*>(shouldContainTwoByteFoos.data()), shouldContainTwoByteFoos.size());
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32Array(parcel, reinterpret_cast<const int32_t*>(shouldContainTwoIntFoos.data()), shouldContainTwoIntFoos.size());
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt64Array(parcel, reinterpret_cast<const int64_t*>(shouldContainTwoLongFoos.data()), shouldContainTwoLongFoos.size());
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeString(parcel, stringDefaultsToFoo);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeByte(parcel, byteDefaultsToFour);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, intDefaultsToFive);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt64(parcel, longDefaultsToNegativeSeven);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeBool(parcel, booleanDefaultsToTrue);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeChar(parcel, charDefaultsToC);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeFloat(parcel, floatDefaultsToPi);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeDouble(parcel, doubleWithDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, arrayDefaultsTo123);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, arrayDefaultsToEmpty);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeBool(parcel, boolDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeByte(parcel, byteDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, intDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt64(parcel, longDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeFloat(parcel, floatDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeDouble(parcel, doubleDefault);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeDouble(parcel, checkDoubleFromFloat);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, checkStringArray1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, checkStringArray2);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, int32_min);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, int32_max);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt64(parcel, int64_max);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, hexInt32_neg_1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeNullableStrongBinder(parcel, ibinder);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, int32_1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(parcel, int64_1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, hexInt32_pos_1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, hexInt64_pos_1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, static_cast<int32_t>(const_exprs_1));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, static_cast<int32_t>(const_exprs_2));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, static_cast<int32_t>(const_exprs_3));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, static_cast<int32_t>(const_exprs_4));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, static_cast<int32_t>(const_exprs_5));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, static_cast<int32_t>(const_exprs_6));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, static_cast<int32_t>(const_exprs_7));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, static_cast<int32_t>(const_exprs_8));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, static_cast<int32_t>(const_exprs_9));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, static_cast<int32_t>(const_exprs_10));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeString(parcel, addString1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeString(parcel, addString2);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, shouldSetBit0AndBit2);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeNullableParcelable(parcel, u);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeNullableParcelable(parcel, shouldBeConstS1);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, static_cast<int32_t>(defaultWithFoo));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  size_t _aidl_end_pos = AParcel_getDataPosition(parcel);
-  AParcel_setDataPosition(parcel, _aidl_start_pos);
-  AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);
-  AParcel_setDataPosition(parcel, _aidl_end_pos);
-  return _aidl_ret_status;
-}
-
-}  // namespace tests
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/UnionInUnion.cpp.d b/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/UnionInUnion.cpp.d
deleted file mode 100644
index 5b41318..0000000
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/UnionInUnion.cpp.d
+++ /dev/null
@@ -1,3 +0,0 @@
-out/soong/.intermediates/system/tools/aidl/aidl-test-interface-ndk_platform-source/gen/android/aidl/tests/unions/UnionInUnion.cpp : \
-  system/tools/aidl/tests/android/aidl/tests/unions/UnionInUnion.aidl \
-  system/tools/aidl/tests/android/aidl/tests/unions/EnumUnion.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/ITestService.h b/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/ITestService.h
deleted file mode 100644
index 62f8132..0000000
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/ITestService.h
+++ /dev/null
@@ -1,278 +0,0 @@
-#pragma once
-
-#include <android/binder_interface_utils.h>
-
-#include <cstdint>
-#include <memory>
-#include <optional>
-#include <string>
-#include <vector>
-#ifdef BINDER_STABILITY_SUPPORT
-#include <android/binder_stability.h>
-#endif  // BINDER_STABILITY_SUPPORT
-#include <android/binder_parcel_platform.h>
-#include <android/binder_ibinder_platform.h>
-#include <aidl/android/aidl/tests/BackendType.h>
-#include <aidl/android/aidl/tests/ByteEnum.h>
-#include <aidl/android/aidl/tests/INamedCallback.h>
-#include <aidl/android/aidl/tests/INewName.h>
-#include <aidl/android/aidl/tests/IOldName.h>
-#include <aidl/android/aidl/tests/IntEnum.h>
-#include <aidl/android/aidl/tests/LongEnum.h>
-#include <aidl/android/aidl/tests/StructuredParcelable.h>
-
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace tests {
-class ITestService : public ::ndk::ICInterface {
-public:
-  static const char* descriptor;
-  ITestService();
-  virtual ~ITestService();
-
-  enum : int32_t { TEST_CONSTANT = 42 };
-  enum : int32_t { TEST_CONSTANT2 = -42 };
-  enum : int32_t { TEST_CONSTANT3 = 42 };
-  enum : int32_t { TEST_CONSTANT4 = 4 };
-  enum : int32_t { TEST_CONSTANT5 = -4 };
-  enum : int32_t { TEST_CONSTANT6 = 0 };
-  enum : int32_t { TEST_CONSTANT7 = 0 };
-  enum : int32_t { TEST_CONSTANT8 = 0 };
-  enum : int32_t { TEST_CONSTANT9 = 86 };
-  enum : int32_t { TEST_CONSTANT10 = 165 };
-  enum : int32_t { TEST_CONSTANT11 = 250 };
-  enum : int32_t { TEST_CONSTANT12 = -1 };
-  enum : int8_t { BYTE_TEST_CONSTANT = 17 };
-  enum : int64_t { LONG_TEST_CONSTANT = 1099511627776L };
-  static const char* STRING_TEST_CONSTANT;
-  static const char* STRING_TEST_CONSTANT2;
-  static const char* STRING_TEST_CONSTANT_UTF8;
-  enum : int32_t { A1 = 1 };
-  enum : int32_t { A2 = 1 };
-  enum : int32_t { A3 = 1 };
-  enum : int32_t { A4 = 1 };
-  enum : int32_t { A5 = 1 };
-  enum : int32_t { A6 = 1 };
-  enum : int32_t { A7 = 1 };
-  enum : int32_t { A8 = 1 };
-  enum : int32_t { A9 = 1 };
-  enum : int32_t { A10 = 1 };
-  enum : int32_t { A11 = 1 };
-  enum : int32_t { A12 = 1 };
-  enum : int32_t { A13 = 1 };
-  enum : int32_t { A14 = 1 };
-  enum : int32_t { A15 = 1 };
-  enum : int32_t { A16 = 1 };
-  enum : int32_t { A17 = 1 };
-  enum : int32_t { A18 = 1 };
-  enum : int32_t { A19 = 1 };
-  enum : int32_t { A20 = 1 };
-  enum : int32_t { A21 = 1 };
-  enum : int32_t { A22 = 1 };
-  enum : int32_t { A23 = 1 };
-  enum : int32_t { A24 = 1 };
-  enum : int32_t { A25 = 1 };
-  enum : int32_t { A26 = 1 };
-  enum : int32_t { A27 = 1 };
-  enum : int32_t { A28 = 1 };
-  enum : int32_t { A29 = 1 };
-  enum : int32_t { A30 = 1 };
-  enum : int32_t { A31 = 1 };
-  enum : int32_t { A32 = 1 };
-  enum : int32_t { A33 = 1 };
-  enum : int32_t { A34 = 1 };
-  enum : int32_t { A35 = 1 };
-  enum : int32_t { A36 = 1 };
-  enum : int32_t { A37 = 1 };
-  enum : int32_t { A38 = 1 };
-  enum : int32_t { A39 = 1 };
-  enum : int32_t { A40 = 1 };
-  enum : int32_t { A41 = 1 };
-  enum : int32_t { A42 = 1 };
-  enum : int32_t { A43 = 1 };
-  enum : int32_t { A44 = 1 };
-  enum : int32_t { A45 = 1 };
-  enum : int32_t { A46 = 1 };
-  enum : int32_t { A47 = 1 };
-  enum : int32_t { A48 = 1 };
-  enum : int32_t { A49 = 1 };
-  enum : int32_t { A50 = 1 };
-  enum : int32_t { A51 = 1 };
-  enum : int32_t { A52 = 1 };
-  enum : int32_t { A53 = 1 };
-  enum : int32_t { A54 = 1 };
-  enum : int32_t { A55 = 1 };
-  enum : int32_t { A56 = 1 };
-  enum : int32_t { A57 = 1 };
-  static constexpr uint32_t TRANSACTION_UnimplementedMethod = FIRST_CALL_TRANSACTION + 0;
-  static constexpr uint32_t TRANSACTION_Deprecated = FIRST_CALL_TRANSACTION + 1;
-  static constexpr uint32_t TRANSACTION_TestOneway = FIRST_CALL_TRANSACTION + 2;
-  static constexpr uint32_t TRANSACTION_RepeatBoolean = FIRST_CALL_TRANSACTION + 3;
-  static constexpr uint32_t TRANSACTION_RepeatByte = FIRST_CALL_TRANSACTION + 4;
-  static constexpr uint32_t TRANSACTION_RepeatChar = FIRST_CALL_TRANSACTION + 5;
-  static constexpr uint32_t TRANSACTION_RepeatInt = FIRST_CALL_TRANSACTION + 6;
-  static constexpr uint32_t TRANSACTION_RepeatLong = FIRST_CALL_TRANSACTION + 7;
-  static constexpr uint32_t TRANSACTION_RepeatFloat = FIRST_CALL_TRANSACTION + 8;
-  static constexpr uint32_t TRANSACTION_RepeatDouble = FIRST_CALL_TRANSACTION + 9;
-  static constexpr uint32_t TRANSACTION_RepeatString = FIRST_CALL_TRANSACTION + 10;
-  static constexpr uint32_t TRANSACTION_RepeatByteEnum = FIRST_CALL_TRANSACTION + 11;
-  static constexpr uint32_t TRANSACTION_RepeatIntEnum = FIRST_CALL_TRANSACTION + 12;
-  static constexpr uint32_t TRANSACTION_RepeatLongEnum = FIRST_CALL_TRANSACTION + 13;
-  static constexpr uint32_t TRANSACTION_ReverseBoolean = FIRST_CALL_TRANSACTION + 14;
-  static constexpr uint32_t TRANSACTION_ReverseByte = FIRST_CALL_TRANSACTION + 15;
-  static constexpr uint32_t TRANSACTION_ReverseChar = FIRST_CALL_TRANSACTION + 16;
-  static constexpr uint32_t TRANSACTION_ReverseInt = FIRST_CALL_TRANSACTION + 17;
-  static constexpr uint32_t TRANSACTION_ReverseLong = FIRST_CALL_TRANSACTION + 18;
-  static constexpr uint32_t TRANSACTION_ReverseFloat = FIRST_CALL_TRANSACTION + 19;
-  static constexpr uint32_t TRANSACTION_ReverseDouble = FIRST_CALL_TRANSACTION + 20;
-  static constexpr uint32_t TRANSACTION_ReverseString = FIRST_CALL_TRANSACTION + 21;
-  static constexpr uint32_t TRANSACTION_ReverseByteEnum = FIRST_CALL_TRANSACTION + 22;
-  static constexpr uint32_t TRANSACTION_ReverseIntEnum = FIRST_CALL_TRANSACTION + 23;
-  static constexpr uint32_t TRANSACTION_ReverseLongEnum = FIRST_CALL_TRANSACTION + 24;
-  static constexpr uint32_t TRANSACTION_GetOtherTestService = FIRST_CALL_TRANSACTION + 25;
-  static constexpr uint32_t TRANSACTION_VerifyName = FIRST_CALL_TRANSACTION + 26;
-  static constexpr uint32_t TRANSACTION_ReverseStringList = FIRST_CALL_TRANSACTION + 27;
-  static constexpr uint32_t TRANSACTION_RepeatParcelFileDescriptor = FIRST_CALL_TRANSACTION + 28;
-  static constexpr uint32_t TRANSACTION_ReverseParcelFileDescriptorArray = FIRST_CALL_TRANSACTION + 29;
-  static constexpr uint32_t TRANSACTION_ThrowServiceException = FIRST_CALL_TRANSACTION + 30;
-  static constexpr uint32_t TRANSACTION_RepeatNullableIntArray = FIRST_CALL_TRANSACTION + 31;
-  static constexpr uint32_t TRANSACTION_RepeatNullableByteEnumArray = FIRST_CALL_TRANSACTION + 32;
-  static constexpr uint32_t TRANSACTION_RepeatNullableIntEnumArray = FIRST_CALL_TRANSACTION + 33;
-  static constexpr uint32_t TRANSACTION_RepeatNullableLongEnumArray = FIRST_CALL_TRANSACTION + 34;
-  static constexpr uint32_t TRANSACTION_RepeatNullableString = FIRST_CALL_TRANSACTION + 35;
-  static constexpr uint32_t TRANSACTION_RepeatNullableStringList = FIRST_CALL_TRANSACTION + 36;
-  static constexpr uint32_t TRANSACTION_RepeatNullableParcelable = FIRST_CALL_TRANSACTION + 37;
-  static constexpr uint32_t TRANSACTION_TakesAnIBinder = FIRST_CALL_TRANSACTION + 38;
-  static constexpr uint32_t TRANSACTION_TakesANullableIBinder = FIRST_CALL_TRANSACTION + 39;
-  static constexpr uint32_t TRANSACTION_RepeatUtf8CppString = FIRST_CALL_TRANSACTION + 40;
-  static constexpr uint32_t TRANSACTION_RepeatNullableUtf8CppString = FIRST_CALL_TRANSACTION + 41;
-  static constexpr uint32_t TRANSACTION_ReverseUtf8CppString = FIRST_CALL_TRANSACTION + 42;
-  static constexpr uint32_t TRANSACTION_ReverseNullableUtf8CppString = FIRST_CALL_TRANSACTION + 43;
-  static constexpr uint32_t TRANSACTION_ReverseUtf8CppStringList = FIRST_CALL_TRANSACTION + 44;
-  static constexpr uint32_t TRANSACTION_GetCallback = FIRST_CALL_TRANSACTION + 45;
-  static constexpr uint32_t TRANSACTION_FillOutStructuredParcelable = FIRST_CALL_TRANSACTION + 46;
-  static constexpr uint32_t TRANSACTION_GetOldNameInterface = FIRST_CALL_TRANSACTION + 47;
-  static constexpr uint32_t TRANSACTION_GetNewNameInterface = FIRST_CALL_TRANSACTION + 48;
-  static constexpr uint32_t TRANSACTION_GetCppJavaTests = FIRST_CALL_TRANSACTION + 49;
-  static constexpr uint32_t TRANSACTION_getBackendType = FIRST_CALL_TRANSACTION + 50;
-
-  static std::shared_ptr<ITestService> fromBinder(const ::ndk::SpAIBinder& binder);
-  static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<ITestService>& instance);
-  static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<ITestService>* instance);
-  static bool setDefaultImpl(const std::shared_ptr<ITestService>& impl);
-  static const std::shared_ptr<ITestService>& getDefaultImpl();
-  virtual ::ndk::ScopedAStatus UnimplementedMethod(int32_t in_arg, int32_t* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus Deprecated() __attribute__((deprecated("to make sure we have something in system/tools/aidl which does a compile check of deprecated and make sure this is reflected in goldens"))) = 0;
-  virtual ::ndk::ScopedAStatus TestOneway() = 0;
-  virtual ::ndk::ScopedAStatus RepeatBoolean(bool in_token, bool* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatByte(int8_t in_token, int8_t* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatChar(char16_t in_token, char16_t* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatInt(int32_t in_token, int32_t* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatLong(int64_t in_token, int64_t* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatFloat(float in_token, float* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatDouble(double in_token, double* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatString(const std::string& in_token, std::string* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatByteEnum(::aidl::android::aidl::tests::ByteEnum in_token, ::aidl::android::aidl::tests::ByteEnum* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatIntEnum(::aidl::android::aidl::tests::IntEnum in_token, ::aidl::android::aidl::tests::IntEnum* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatLongEnum(::aidl::android::aidl::tests::LongEnum in_token, ::aidl::android::aidl::tests::LongEnum* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseBoolean(const std::vector<bool>& in_input, std::vector<bool>* out_repeated, std::vector<bool>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseByte(const std::vector<uint8_t>& in_input, std::vector<uint8_t>* out_repeated, std::vector<uint8_t>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseChar(const std::vector<char16_t>& in_input, std::vector<char16_t>* out_repeated, std::vector<char16_t>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseInt(const std::vector<int32_t>& in_input, std::vector<int32_t>* out_repeated, std::vector<int32_t>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseLong(const std::vector<int64_t>& in_input, std::vector<int64_t>* out_repeated, std::vector<int64_t>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseFloat(const std::vector<float>& in_input, std::vector<float>* out_repeated, std::vector<float>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseDouble(const std::vector<double>& in_input, std::vector<double>* out_repeated, std::vector<double>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseString(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseByteEnum(const std::vector<::aidl::android::aidl::tests::ByteEnum>& in_input, std::vector<::aidl::android::aidl::tests::ByteEnum>* out_repeated, std::vector<::aidl::android::aidl::tests::ByteEnum>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseIntEnum(const std::vector<::aidl::android::aidl::tests::IntEnum>& in_input, std::vector<::aidl::android::aidl::tests::IntEnum>* out_repeated, std::vector<::aidl::android::aidl::tests::IntEnum>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseLongEnum(const std::vector<::aidl::android::aidl::tests::LongEnum>& in_input, std::vector<::aidl::android::aidl::tests::LongEnum>* out_repeated, std::vector<::aidl::android::aidl::tests::LongEnum>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus GetOtherTestService(const std::string& in_name, std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus VerifyName(const std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>& in_service, const std::string& in_name, bool* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseStringList(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatParcelFileDescriptor(const ::ndk::ScopedFileDescriptor& in_read, ::ndk::ScopedFileDescriptor* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseParcelFileDescriptorArray(const std::vector<::ndk::ScopedFileDescriptor>& in_input, std::vector<::ndk::ScopedFileDescriptor>* out_repeated, std::vector<::ndk::ScopedFileDescriptor>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ThrowServiceException(int32_t in_code) = 0;
-  virtual ::ndk::ScopedAStatus RepeatNullableIntArray(const std::optional<std::vector<int32_t>>& in_input, std::optional<std::vector<int32_t>>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatNullableByteEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::ByteEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::ByteEnum>>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatNullableIntEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::IntEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::IntEnum>>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatNullableLongEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::LongEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::LongEnum>>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatNullableString(const std::optional<std::string>& in_input, std::optional<std::string>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatNullableStringList(const std::vector<std::string>& in_input, std::vector<std::string>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatNullableParcelable(const std::optional<::aidl::android::aidl::tests::StructuredParcelable>& in_input, std::optional<::aidl::android::aidl::tests::StructuredParcelable>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus TakesAnIBinder(const ::ndk::SpAIBinder& in_input) = 0;
-  virtual ::ndk::ScopedAStatus TakesANullableIBinder(const ::ndk::SpAIBinder& in_input) = 0;
-  virtual ::ndk::ScopedAStatus RepeatUtf8CppString(const std::string& in_token, std::string* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus RepeatNullableUtf8CppString(const std::optional<std::string>& in_token, std::optional<std::string>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseUtf8CppString(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseNullableUtf8CppString(const std::optional<std::vector<std::optional<std::string>>>& in_input, std::optional<std::vector<std::optional<std::string>>>* out_repeated, std::optional<std::vector<std::optional<std::string>>>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus ReverseUtf8CppStringList(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus GetCallback(bool in_return_null, std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus FillOutStructuredParcelable(::aidl::android::aidl::tests::StructuredParcelable* in_parcel) = 0;
-  virtual ::ndk::ScopedAStatus GetOldNameInterface(std::shared_ptr<::aidl::android::aidl::tests::IOldName>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus GetNewNameInterface(std::shared_ptr<::aidl::android::aidl::tests::INewName>* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus GetCppJavaTests(::ndk::SpAIBinder* _aidl_return) = 0;
-  virtual ::ndk::ScopedAStatus getBackendType(::aidl::android::aidl::tests::BackendType* _aidl_return) = 0;
-private:
-  static std::shared_ptr<ITestService> default_impl;
-};
-class ITestServiceDefault : public ITestService {
-public:
-  ::ndk::ScopedAStatus UnimplementedMethod(int32_t in_arg, int32_t* _aidl_return) override;
-  ::ndk::ScopedAStatus Deprecated() override __attribute__((deprecated("to make sure we have something in system/tools/aidl which does a compile check of deprecated and make sure this is reflected in goldens")));
-  ::ndk::ScopedAStatus TestOneway() override;
-  ::ndk::ScopedAStatus RepeatBoolean(bool in_token, bool* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatByte(int8_t in_token, int8_t* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatChar(char16_t in_token, char16_t* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatInt(int32_t in_token, int32_t* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatLong(int64_t in_token, int64_t* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatFloat(float in_token, float* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatDouble(double in_token, double* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatString(const std::string& in_token, std::string* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatByteEnum(::aidl::android::aidl::tests::ByteEnum in_token, ::aidl::android::aidl::tests::ByteEnum* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatIntEnum(::aidl::android::aidl::tests::IntEnum in_token, ::aidl::android::aidl::tests::IntEnum* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatLongEnum(::aidl::android::aidl::tests::LongEnum in_token, ::aidl::android::aidl::tests::LongEnum* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseBoolean(const std::vector<bool>& in_input, std::vector<bool>* out_repeated, std::vector<bool>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseByte(const std::vector<uint8_t>& in_input, std::vector<uint8_t>* out_repeated, std::vector<uint8_t>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseChar(const std::vector<char16_t>& in_input, std::vector<char16_t>* out_repeated, std::vector<char16_t>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseInt(const std::vector<int32_t>& in_input, std::vector<int32_t>* out_repeated, std::vector<int32_t>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseLong(const std::vector<int64_t>& in_input, std::vector<int64_t>* out_repeated, std::vector<int64_t>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseFloat(const std::vector<float>& in_input, std::vector<float>* out_repeated, std::vector<float>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseDouble(const std::vector<double>& in_input, std::vector<double>* out_repeated, std::vector<double>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseString(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseByteEnum(const std::vector<::aidl::android::aidl::tests::ByteEnum>& in_input, std::vector<::aidl::android::aidl::tests::ByteEnum>* out_repeated, std::vector<::aidl::android::aidl::tests::ByteEnum>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseIntEnum(const std::vector<::aidl::android::aidl::tests::IntEnum>& in_input, std::vector<::aidl::android::aidl::tests::IntEnum>* out_repeated, std::vector<::aidl::android::aidl::tests::IntEnum>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseLongEnum(const std::vector<::aidl::android::aidl::tests::LongEnum>& in_input, std::vector<::aidl::android::aidl::tests::LongEnum>* out_repeated, std::vector<::aidl::android::aidl::tests::LongEnum>* _aidl_return) override;
-  ::ndk::ScopedAStatus GetOtherTestService(const std::string& in_name, std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>* _aidl_return) override;
-  ::ndk::ScopedAStatus VerifyName(const std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>& in_service, const std::string& in_name, bool* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseStringList(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatParcelFileDescriptor(const ::ndk::ScopedFileDescriptor& in_read, ::ndk::ScopedFileDescriptor* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseParcelFileDescriptorArray(const std::vector<::ndk::ScopedFileDescriptor>& in_input, std::vector<::ndk::ScopedFileDescriptor>* out_repeated, std::vector<::ndk::ScopedFileDescriptor>* _aidl_return) override;
-  ::ndk::ScopedAStatus ThrowServiceException(int32_t in_code) override;
-  ::ndk::ScopedAStatus RepeatNullableIntArray(const std::optional<std::vector<int32_t>>& in_input, std::optional<std::vector<int32_t>>* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatNullableByteEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::ByteEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::ByteEnum>>* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatNullableIntEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::IntEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::IntEnum>>* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatNullableLongEnumArray(const std::optional<std::vector<::aidl::android::aidl::tests::LongEnum>>& in_input, std::optional<std::vector<::aidl::android::aidl::tests::LongEnum>>* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatNullableString(const std::optional<std::string>& in_input, std::optional<std::string>* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatNullableStringList(const std::vector<std::string>& in_input, std::vector<std::string>* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatNullableParcelable(const std::optional<::aidl::android::aidl::tests::StructuredParcelable>& in_input, std::optional<::aidl::android::aidl::tests::StructuredParcelable>* _aidl_return) override;
-  ::ndk::ScopedAStatus TakesAnIBinder(const ::ndk::SpAIBinder& in_input) override;
-  ::ndk::ScopedAStatus TakesANullableIBinder(const ::ndk::SpAIBinder& in_input) override;
-  ::ndk::ScopedAStatus RepeatUtf8CppString(const std::string& in_token, std::string* _aidl_return) override;
-  ::ndk::ScopedAStatus RepeatNullableUtf8CppString(const std::optional<std::string>& in_token, std::optional<std::string>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseUtf8CppString(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseNullableUtf8CppString(const std::optional<std::vector<std::optional<std::string>>>& in_input, std::optional<std::vector<std::optional<std::string>>>* out_repeated, std::optional<std::vector<std::optional<std::string>>>* _aidl_return) override;
-  ::ndk::ScopedAStatus ReverseUtf8CppStringList(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) override;
-  ::ndk::ScopedAStatus GetCallback(bool in_return_null, std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>* _aidl_return) override;
-  ::ndk::ScopedAStatus FillOutStructuredParcelable(::aidl::android::aidl::tests::StructuredParcelable* in_parcel) override;
-  ::ndk::ScopedAStatus GetOldNameInterface(std::shared_ptr<::aidl::android::aidl::tests::IOldName>* _aidl_return) override;
-  ::ndk::ScopedAStatus GetNewNameInterface(std::shared_ptr<::aidl::android::aidl::tests::INewName>* _aidl_return) override;
-  ::ndk::ScopedAStatus GetCppJavaTests(::ndk::SpAIBinder* _aidl_return) override;
-  ::ndk::ScopedAStatus getBackendType(::aidl::android::aidl::tests::BackendType* _aidl_return) override;
-  ::ndk::SpAIBinder asBinder() override;
-  bool isRemote() override;
-};
-}  // namespace tests
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/StructuredParcelable.h b/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/StructuredParcelable.h
deleted file mode 100644
index b665af5..0000000
--- a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/include/aidl/android/aidl/tests/StructuredParcelable.h
+++ /dev/null
@@ -1,170 +0,0 @@
-#pragma once
-#include <android/binder_interface_utils.h>
-#include <android/binder_parcelable_utils.h>
-#include <android/binder_to_string.h>
-#include <cstdint>
-#include <memory>
-#include <optional>
-#include <string>
-#include <vector>
-#ifdef BINDER_STABILITY_SUPPORT
-#include <android/binder_stability.h>
-#endif  // BINDER_STABILITY_SUPPORT
-#include <aidl/android/aidl/tests/ByteEnum.h>
-#include <aidl/android/aidl/tests/ConstantExpressionEnum.h>
-#include <aidl/android/aidl/tests/IntEnum.h>
-#include <aidl/android/aidl/tests/LongEnum.h>
-#include <aidl/android/aidl/tests/Union.h>
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace tests {
-class StructuredParcelable {
-public:
-  typedef std::false_type fixed_size;
-  static const char* descriptor;
-
-  std::vector<int32_t> shouldContainThreeFs;
-  int32_t f = 0;
-  std::string shouldBeJerry;
-  ::aidl::android::aidl::tests::ByteEnum shouldBeByteBar = ::aidl::android::aidl::tests::ByteEnum(0);
-  ::aidl::android::aidl::tests::IntEnum shouldBeIntBar = ::aidl::android::aidl::tests::IntEnum(0);
-  ::aidl::android::aidl::tests::LongEnum shouldBeLongBar = ::aidl::android::aidl::tests::LongEnum(0);
-  std::vector<::aidl::android::aidl::tests::ByteEnum> shouldContainTwoByteFoos;
-  std::vector<::aidl::android::aidl::tests::IntEnum> shouldContainTwoIntFoos;
-  std::vector<::aidl::android::aidl::tests::LongEnum> shouldContainTwoLongFoos;
-  std::string stringDefaultsToFoo = "foo";
-  int8_t byteDefaultsToFour = 4;
-  int32_t intDefaultsToFive = 5;
-  int64_t longDefaultsToNegativeSeven = -7L;
-  bool booleanDefaultsToTrue = true;
-  char16_t charDefaultsToC = 'C';
-  float floatDefaultsToPi = 3.140000f;
-  double doubleWithDefault = -314000000000000000.000000;
-  std::vector<int32_t> arrayDefaultsTo123 = {1, 2, 3};
-  std::vector<int32_t> arrayDefaultsToEmpty = {};
-  bool boolDefault = false;
-  int8_t byteDefault = 0;
-  int32_t intDefault = 0;
-  int64_t longDefault = 0L;
-  float floatDefault = 0.000000f;
-  double doubleDefault = 0.000000;
-  double checkDoubleFromFloat = 3.140000;
-  std::vector<std::string> checkStringArray1 = {"a", "b"};
-  std::vector<std::string> checkStringArray2 = {"a", "b"};
-  int32_t int32_min = -2147483648;
-  int32_t int32_max = 2147483647;
-  int64_t int64_max = 9223372036854775807L;
-  int32_t hexInt32_neg_1 = -1;
-  ::ndk::SpAIBinder ibinder;
-  std::vector<int32_t> int32_1 = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
-  std::vector<int64_t> int64_1 = {1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L};
-  int32_t hexInt32_pos_1 = 1;
-  int32_t hexInt64_pos_1 = 1;
-  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_1 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
-  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_2 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
-  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_3 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
-  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_4 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
-  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_5 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
-  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_6 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
-  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_7 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
-  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_8 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
-  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_9 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
-  ::aidl::android::aidl::tests::ConstantExpressionEnum const_exprs_10 = ::aidl::android::aidl::tests::ConstantExpressionEnum(0);
-  std::string addString1 = "hello world!";
-  std::string addString2 = "The quick brown fox jumps over the lazy dog.";
-  int32_t shouldSetBit0AndBit2 = 0;
-  std::optional<::aidl::android::aidl::tests::Union> u;
-  std::optional<::aidl::android::aidl::tests::Union> shouldBeConstS1;
-  ::aidl::android::aidl::tests::IntEnum defaultWithFoo = ::aidl::android::aidl::tests::IntEnum::FOO;
-
-  binder_status_t readFromParcel(const AParcel* parcel);
-  binder_status_t writeToParcel(AParcel* parcel) const;
-
-  inline bool operator!=(const StructuredParcelable& rhs) const {
-    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) != std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
-  }
-  inline bool operator<(const StructuredParcelable& rhs) const {
-    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) < std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
-  }
-  inline bool operator<=(const StructuredParcelable& rhs) const {
-    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) <= std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
-  }
-  inline bool operator==(const StructuredParcelable& rhs) const {
-    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) == std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
-  }
-  inline bool operator>(const StructuredParcelable& rhs) const {
-    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) > std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
-  }
-  inline bool operator>=(const StructuredParcelable& rhs) const {
-    return std::tie(shouldContainThreeFs, f, shouldBeJerry, shouldBeByteBar, shouldBeIntBar, shouldBeLongBar, shouldContainTwoByteFoos, shouldContainTwoIntFoos, shouldContainTwoLongFoos, stringDefaultsToFoo, byteDefaultsToFour, intDefaultsToFive, longDefaultsToNegativeSeven, booleanDefaultsToTrue, charDefaultsToC, floatDefaultsToPi, doubleWithDefault, arrayDefaultsTo123, arrayDefaultsToEmpty, boolDefault, byteDefault, intDefault, longDefault, floatDefault, doubleDefault, checkDoubleFromFloat, checkStringArray1, checkStringArray2, int32_min, int32_max, int64_max, hexInt32_neg_1, ibinder, int32_1, int64_1, hexInt32_pos_1, hexInt64_pos_1, const_exprs_1, const_exprs_2, const_exprs_3, const_exprs_4, const_exprs_5, const_exprs_6, const_exprs_7, const_exprs_8, const_exprs_9, const_exprs_10, addString1, addString2, shouldSetBit0AndBit2, u, shouldBeConstS1, defaultWithFoo) >= std::tie(rhs.shouldContainThreeFs, rhs.f, rhs.shouldBeJerry, rhs.shouldBeByteBar, rhs.shouldBeIntBar, rhs.shouldBeLongBar, rhs.shouldContainTwoByteFoos, rhs.shouldContainTwoIntFoos, rhs.shouldContainTwoLongFoos, rhs.stringDefaultsToFoo, rhs.byteDefaultsToFour, rhs.intDefaultsToFive, rhs.longDefaultsToNegativeSeven, rhs.booleanDefaultsToTrue, rhs.charDefaultsToC, rhs.floatDefaultsToPi, rhs.doubleWithDefault, rhs.arrayDefaultsTo123, rhs.arrayDefaultsToEmpty, rhs.boolDefault, rhs.byteDefault, rhs.intDefault, rhs.longDefault, rhs.floatDefault, rhs.doubleDefault, rhs.checkDoubleFromFloat, rhs.checkStringArray1, rhs.checkStringArray2, rhs.int32_min, rhs.int32_max, rhs.int64_max, rhs.hexInt32_neg_1, rhs.ibinder, rhs.int32_1, rhs.int64_1, rhs.hexInt32_pos_1, rhs.hexInt64_pos_1, rhs.const_exprs_1, rhs.const_exprs_2, rhs.const_exprs_3, rhs.const_exprs_4, rhs.const_exprs_5, rhs.const_exprs_6, rhs.const_exprs_7, rhs.const_exprs_8, rhs.const_exprs_9, rhs.const_exprs_10, rhs.addString1, rhs.addString2, rhs.shouldSetBit0AndBit2, rhs.u, rhs.shouldBeConstS1, rhs.defaultWithFoo);
-  }
-
-  static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
-  enum : int32_t { BIT0 = 1 };
-  enum : int32_t { BIT1 = 2 };
-  enum : int32_t { BIT2 = 4 };
-  inline std::string toString() const {
-    std::ostringstream os;
-    os << "StructuredParcelable{";
-    os << "shouldContainThreeFs: " << ::android::internal::ToString(shouldContainThreeFs);
-    os << ", f: " << ::android::internal::ToString(f);
-    os << ", shouldBeJerry: " << ::android::internal::ToString(shouldBeJerry);
-    os << ", shouldBeByteBar: " << ::android::internal::ToString(shouldBeByteBar);
-    os << ", shouldBeIntBar: " << ::android::internal::ToString(shouldBeIntBar);
-    os << ", shouldBeLongBar: " << ::android::internal::ToString(shouldBeLongBar);
-    os << ", shouldContainTwoByteFoos: " << ::android::internal::ToString(shouldContainTwoByteFoos);
-    os << ", shouldContainTwoIntFoos: " << ::android::internal::ToString(shouldContainTwoIntFoos);
-    os << ", shouldContainTwoLongFoos: " << ::android::internal::ToString(shouldContainTwoLongFoos);
-    os << ", stringDefaultsToFoo: " << ::android::internal::ToString(stringDefaultsToFoo);
-    os << ", byteDefaultsToFour: " << ::android::internal::ToString(byteDefaultsToFour);
-    os << ", intDefaultsToFive: " << ::android::internal::ToString(intDefaultsToFive);
-    os << ", longDefaultsToNegativeSeven: " << ::android::internal::ToString(longDefaultsToNegativeSeven);
-    os << ", booleanDefaultsToTrue: " << ::android::internal::ToString(booleanDefaultsToTrue);
-    os << ", charDefaultsToC: " << ::android::internal::ToString(charDefaultsToC);
-    os << ", floatDefaultsToPi: " << ::android::internal::ToString(floatDefaultsToPi);
-    os << ", doubleWithDefault: " << ::android::internal::ToString(doubleWithDefault);
-    os << ", arrayDefaultsTo123: " << ::android::internal::ToString(arrayDefaultsTo123);
-    os << ", arrayDefaultsToEmpty: " << ::android::internal::ToString(arrayDefaultsToEmpty);
-    os << ", boolDefault: " << ::android::internal::ToString(boolDefault);
-    os << ", byteDefault: " << ::android::internal::ToString(byteDefault);
-    os << ", intDefault: " << ::android::internal::ToString(intDefault);
-    os << ", longDefault: " << ::android::internal::ToString(longDefault);
-    os << ", floatDefault: " << ::android::internal::ToString(floatDefault);
-    os << ", doubleDefault: " << ::android::internal::ToString(doubleDefault);
-    os << ", checkDoubleFromFloat: " << ::android::internal::ToString(checkDoubleFromFloat);
-    os << ", checkStringArray1: " << ::android::internal::ToString(checkStringArray1);
-    os << ", checkStringArray2: " << ::android::internal::ToString(checkStringArray2);
-    os << ", int32_min: " << ::android::internal::ToString(int32_min);
-    os << ", int32_max: " << ::android::internal::ToString(int32_max);
-    os << ", int64_max: " << ::android::internal::ToString(int64_max);
-    os << ", hexInt32_neg_1: " << ::android::internal::ToString(hexInt32_neg_1);
-    os << ", ibinder: " << ::android::internal::ToString(ibinder);
-    os << ", int32_1: " << ::android::internal::ToString(int32_1);
-    os << ", int64_1: " << ::android::internal::ToString(int64_1);
-    os << ", hexInt32_pos_1: " << ::android::internal::ToString(hexInt32_pos_1);
-    os << ", hexInt64_pos_1: " << ::android::internal::ToString(hexInt64_pos_1);
-    os << ", const_exprs_1: " << ::android::internal::ToString(const_exprs_1);
-    os << ", const_exprs_2: " << ::android::internal::ToString(const_exprs_2);
-    os << ", const_exprs_3: " << ::android::internal::ToString(const_exprs_3);
-    os << ", const_exprs_4: " << ::android::internal::ToString(const_exprs_4);
-    os << ", const_exprs_5: " << ::android::internal::ToString(const_exprs_5);
-    os << ", const_exprs_6: " << ::android::internal::ToString(const_exprs_6);
-    os << ", const_exprs_7: " << ::android::internal::ToString(const_exprs_7);
-    os << ", const_exprs_8: " << ::android::internal::ToString(const_exprs_8);
-    os << ", const_exprs_9: " << ::android::internal::ToString(const_exprs_9);
-    os << ", const_exprs_10: " << ::android::internal::ToString(const_exprs_10);
-    os << ", addString1: " << ::android::internal::ToString(addString1);
-    os << ", addString2: " << ::android::internal::ToString(addString2);
-    os << ", shouldSetBit0AndBit2: " << ::android::internal::ToString(shouldSetBit0AndBit2);
-    os << ", u: " << ::android::internal::ToString(u);
-    os << ", shouldBeConstS1: " << ::android::internal::ToString(shouldBeConstS1);
-    os << ", defaultWithFoo: " << ::android::internal::ToString(defaultWithFoo);
-    os << "}";
-    return os.str();
-  }
-};
-}  // namespace tests
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl-test-interface-platform-java-source/gen/android/aidl/tests/permission/platform/IProtected.java b/tests/golden_output/aidl-test-interface-platform-java-source/gen/android/aidl/tests/permission/platform/IProtected.java
new file mode 100644
index 0000000..7b6d96f
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-platform-java-source/gen/android/aidl/tests/permission/platform/IProtected.java
@@ -0,0 +1,124 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.tests.permission.platform;
+public interface IProtected extends android.os.IInterface
+{
+  /** Default implementation for IProtected. */
+  public static class Default implements android.aidl.tests.permission.platform.IProtected
+  {
+    @Override public void ProtectedWithSourceAttribution(android.content.AttributionSource source) throws android.os.RemoteException
+    {
+    }
+    @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.permission.platform.IProtected
+  {
+    /** Construct the stub at attach it to the interface. */
+    public Stub()
+    {
+      this.attachInterface(this, DESCRIPTOR);
+    }
+    /**
+     * Cast an IBinder object into an android.aidl.tests.permission.platform.IProtected interface,
+     * generating a proxy if needed.
+     */
+    public static android.aidl.tests.permission.platform.IProtected 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.permission.platform.IProtected))) {
+        return ((android.aidl.tests.permission.platform.IProtected)iin);
+      }
+      return new android.aidl.tests.permission.platform.IProtected.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_ProtectedWithSourceAttribution:
+        {
+          android.content.AttributionSource _arg0;
+          _arg0 = data.readTypedObject(android.content.AttributionSource.CREATOR);
+          data.enforceNoDataAvail();
+          if (((this.permissionCheckerWrapper(android.Manifest.permission.INTERNET, this.getCallingPid(), _arg0)&&this.permissionCheckerWrapper(android.Manifest.permission.VIBRATE, this.getCallingPid(), _arg0))!=true)) {
+            throw new SecurityException("Access denied, requires: allOf = {android.Manifest.permission.INTERNET, android.Manifest.permission.VIBRATE}");
+          }
+          this.ProtectedWithSourceAttribution(_arg0);
+          reply.writeNoException();
+          break;
+        }
+        default:
+        {
+          return super.onTransact(code, data, reply, flags);
+        }
+      }
+      return true;
+    }
+    private static class Proxy implements android.aidl.tests.permission.platform.IProtected
+    {
+      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 void ProtectedWithSourceAttribution(android.content.AttributionSource source) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeTypedObject(source, 0);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_ProtectedWithSourceAttribution, _data, _reply, 0);
+          _reply.readException();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
+    }
+    private boolean permissionCheckerWrapper(
+        String permission, int pid, android.content.AttributionSource attributionSource) {
+      android.content.Context ctx =
+          android.app.ActivityThread.currentActivityThread().getSystemContext();
+      return (android.content.PermissionChecker.checkPermissionForDataDelivery(
+              ctx, permission, pid, attributionSource, "" /*message*/) ==
+          android.content.PermissionChecker.PERMISSION_GRANTED);
+    }
+    static final int TRANSACTION_ProtectedWithSourceAttribution = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+  }
+  public static final java.lang.String DESCRIPTOR = "android$aidl$tests$permission$platform$IProtected".replace('$', '.');
+  @android.annotation.EnforcePermission(allOf = {android.Manifest.permission.INTERNET, android.Manifest.permission.VIBRATE})
+  public void ProtectedWithSourceAttribution(android.content.AttributionSource source) throws android.os.RemoteException;
+}
diff --git a/tests/golden_output/aidl-test-interface-platform-java-source/gen/android/aidl/tests/permission/platform/IProtected.java.d b/tests/golden_output/aidl-test-interface-platform-java-source/gen/android/aidl/tests/permission/platform/IProtected.java.d
new file mode 100644
index 0000000..51e500e
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-platform-java-source/gen/android/aidl/tests/permission/platform/IProtected.java.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-platform-java-source/gen/android/aidl/tests/permission/platform/IProtected.java : \
+  system/tools/aidl/tests/android/aidl/tests/permission/platform/IProtected.aidl \
+  frameworks/base/core/java/android/content/AttributionSource.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp b/tests/golden_output/aidl-test-interface-platform-java-source/gen/timestamp
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp
copy to tests/golden_output/aidl-test-interface-platform-java-source/gen/timestamp
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..ee4b1f1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ArrayOfInterfaces.rs
@@ -0,0 +1,394 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#[derive(Debug)]
+pub struct ArrayOfInterfaces {
+}
+impl Default for ArrayOfInterfaces {
+  fn default() -> Self {
+    Self {
+    }
+  }
+}
+impl binder::Parcelable for ArrayOfInterfaces {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_write(|subparcel| {
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      Ok(())
+    })
+  }
+}
+binder::impl_serialize_for_parcelable!(ArrayOfInterfaces);
+binder::impl_deserialize_for_parcelable!(ArrayOfInterfaces);
+impl binder::binder_impl::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::binder_impl::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" }
+  }
+  #[::async_trait::async_trait]
+  pub trait IEmptyInterfaceAsyncServer: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.ArrayOfInterfaces.IEmptyInterface" }
+  }
+  impl BnEmptyInterface {
+    /// Create a new async binder service.
+    pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn IEmptyInterface>
+    where
+      T: IEmptyInterfaceAsyncServer + binder::Interface + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      struct Wrapper<T, R> {
+        _inner: T,
+        _rt: R,
+      }
+      impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+        fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+        fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+      }
+      impl<T, R> IEmptyInterface for Wrapper<T, R>
+      where
+        T: IEmptyInterfaceAsyncServer + Send + Sync + 'static,
+        R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+      {
+      }
+      let wrapped = Wrapper { _inner: inner, _rt: rt };
+      Self::new_binder(wrapped, features)
+    }
+  }
+  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_impl::Binder<BnEmptyInterface> {
+  }
+  fn on_transact(_aidl_service: &dyn IEmptyInterface, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
+    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::binder_impl::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::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::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>>>;
+  }
+  #[::async_trait::async_trait]
+  pub trait IMyInterfaceAsyncServer: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.ArrayOfInterfaces.IMyInterface" }
+    async 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::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>>;
+  }
+  impl BnMyInterface {
+    /// Create a new async binder service.
+    pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn IMyInterface>
+    where
+      T: IMyInterfaceAsyncServer + binder::Interface + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      struct Wrapper<T, R> {
+        _inner: T,
+        _rt: R,
+      }
+      impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+        fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+        fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+      }
+      impl<T, R> IMyInterface for Wrapper<T, R>
+      where
+        T: IMyInterfaceAsyncServer + Send + Sync + 'static,
+        R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+      {
+        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::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_17_ArrayOfInterfaces_15_IEmptyInterface>>>>> {
+          self._rt.block_on(self._inner.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 wrapped = Wrapper { _inner: inner, _rt: rt };
+      Self::new_binder(wrapped, features)
+    }
+  }
+  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::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::binder_impl::TransactionCode = binder::binder_impl::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::Result<binder::binder_impl::Parcel> {
+      let mut aidl_data = self.binder.prepare_transact()?;
+      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)
+    }
+    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: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::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?;
+      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::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::binder_impl::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::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::binder_impl::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_impl::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::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::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
+    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::Parcelable for MyParcelable {
+    fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      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::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      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::binder_impl::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::Parcelable for MyUnion {
+    fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      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::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      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::binder_impl::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
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/BackendType.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/BackendType.rs
index 5d8d059..7f4be56 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/BackendType.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/BackendType.rs
@@ -1,9 +1,15 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 use binder::declare_binder_enum;
-declare_binder_enum! { BackendType : i8 {
-  CPP = 0,
-  JAVA = 1,
-  NDK = 2,
-  RUST = 3,
-} }
-pub(crate) mod mangled { pub use super::BackendType as _7_android_4_aidl_5_tests_11_BackendType; }
+declare_binder_enum! {
+  BackendType : [i8; 4] {
+    CPP = 0,
+    JAVA = 1,
+    NDK = 2,
+    RUST = 3,
+  }
+}
+pub(crate) mod mangled {
+ pub use super::BackendType as _7_android_4_aidl_5_tests_11_BackendType;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ByteEnum.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ByteEnum.rs
index 7961532..57c61ee 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ByteEnum.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ByteEnum.rs
@@ -1,8 +1,14 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 use binder::declare_binder_enum;
-declare_binder_enum! { ByteEnum : i8 {
-  FOO = 1,
-  BAR = 2,
-  BAZ = 3,
-} }
-pub(crate) mod mangled { pub use super::ByteEnum as _7_android_4_aidl_5_tests_8_ByteEnum; }
+declare_binder_enum! {
+  ByteEnum : [i8; 3] {
+    FOO = 1,
+    BAR = 2,
+    BAZ = 3,
+  }
+}
+pub(crate) mod mangled {
+ pub use super::ByteEnum as _7_android_4_aidl_5_tests_8_ByteEnum;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ConstantExpressionEnum.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ConstantExpressionEnum.rs
index e1dae7d..32a1942 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ConstantExpressionEnum.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ConstantExpressionEnum.rs
@@ -1,15 +1,21 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 use binder::declare_binder_enum;
-declare_binder_enum! { ConstantExpressionEnum : i32 {
-  decInt32_1 = 1,
-  decInt32_2 = 1,
-  decInt64_1 = 1,
-  decInt64_2 = 1,
-  decInt64_3 = 1,
-  decInt64_4 = 1,
-  hexInt32_1 = 1,
-  hexInt32_2 = 1,
-  hexInt32_3 = 1,
-  hexInt64_1 = 1,
-} }
-pub(crate) mod mangled { pub use super::ConstantExpressionEnum as _7_android_4_aidl_5_tests_22_ConstantExpressionEnum; }
+declare_binder_enum! {
+  ConstantExpressionEnum : [i32; 10] {
+    decInt32_1 = 1,
+    decInt32_2 = 1,
+    decInt64_1 = 1,
+    decInt64_2 = 1,
+    decInt64_3 = 1,
+    decInt64_4 = 1,
+    hexInt32_1 = 1,
+    hexInt32_2 = 1,
+    hexInt32_3 = 1,
+    hexInt64_1 = 1,
+  }
+}
+pub(crate) mod mangled {
+ pub use super::ConstantExpressionEnum as _7_android_4_aidl_5_tests_22_ConstantExpressionEnum;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/DeprecatedEnum.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/DeprecatedEnum.rs
index 0d45d7d..5d3b054 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/DeprecatedEnum.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/DeprecatedEnum.rs
@@ -1,8 +1,15 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 use binder::declare_binder_enum;
-declare_binder_enum! { DeprecatedEnum : i32 {
-  A = 0,
-  B = 1,
-  C = 2,
-} }
-pub(crate) mod mangled { pub use super::DeprecatedEnum as _7_android_4_aidl_5_tests_14_DeprecatedEnum; }
+declare_binder_enum! {
+  #[deprecated = "test"]
+  DeprecatedEnum : [i32; 3] {
+    A = 0,
+    B = 1,
+    C = 2,
+  }
+}
+pub(crate) mod mangled {
+ pub use super::DeprecatedEnum as _7_android_4_aidl_5_tests_14_DeprecatedEnum;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/DeprecatedParcelable.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/DeprecatedParcelable.rs
index 18ba875..a13deb6 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/DeprecatedParcelable.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/DeprecatedParcelable.rs
@@ -1,55 +1,32 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #[derive(Debug)]
 #[deprecated = "test"]
 pub struct DeprecatedParcelable {
 }
-pub(crate) mod mangled { pub use super::DeprecatedParcelable as _7_android_4_aidl_5_tests_20_DeprecatedParcelable; }
 impl Default for DeprecatedParcelable {
   fn default() -> Self {
     Self {
     }
   }
 }
-impl binder::parcel::Serialize for DeprecatedParcelable {
-  fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-  }
-}
-impl binder::parcel::SerializeArray for DeprecatedParcelable {}
-impl binder::parcel::SerializeOption for DeprecatedParcelable {
-  fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    let this = if let Some(this) = this {
-      parcel.write(&1i32)?;
-      this
-    } else {
-      return parcel.write(&0i32);
-    };
+impl binder::Parcelable for DeprecatedParcelable {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
     parcel.sized_write(|subparcel| {
       Ok(())
     })
   }
-}
-impl binder::parcel::Deserialize for DeprecatedParcelable {
-  fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-    <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-       .transpose()
-       .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      Ok(())
+    })
   }
 }
-impl binder::parcel::DeserializeArray for DeprecatedParcelable {}
-impl binder::parcel::DeserializeOption for DeprecatedParcelable {
-  fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-    let status: i32 = parcel.read()?;
-    if status == 0 { return Ok(None); }
-    let start_pos = parcel.get_data_position();
-    let parcelable_size: i32 = parcel.read()?;
-    if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-    if start_pos.checked_add(parcelable_size).is_none() {
-      return Err(binder::StatusCode::BAD_VALUE);
-    }
-    let mut result = Self::default();
-    unsafe {
-      parcel.set_data_position(start_pos + parcelable_size)?;
-    }
-    Ok(Some(result))
-  }
+binder::impl_serialize_for_parcelable!(DeprecatedParcelable);
+binder::impl_deserialize_for_parcelable!(DeprecatedParcelable);
+impl binder::binder_impl::ParcelableMetadata for DeprecatedParcelable {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.DeprecatedParcelable" }
+}
+pub(crate) mod mangled {
+ pub use super::DeprecatedParcelable as _7_android_4_aidl_5_tests_20_DeprecatedParcelable;
 }
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs
new file mode 100644
index 0000000..ef73f72
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs
@@ -0,0 +1,224 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#[derive(Debug)]
+pub struct FixedSize {
+}
+impl Default for FixedSize {
+  fn default() -> Self {
+    Self {
+    }
+  }
+}
+impl binder::Parcelable for FixedSize {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_write(|subparcel| {
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      Ok(())
+    })
+  }
+}
+binder::impl_serialize_for_parcelable!(FixedSize);
+binder::impl_deserialize_for_parcelable!(FixedSize);
+impl binder::binder_impl::ParcelableMetadata for FixedSize {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.FixedSize" }
+}
+pub mod FixedParcelable {
+  #[derive(Debug)]
+  pub struct FixedParcelable {
+    pub booleanValue: bool,
+    pub byteValue: i8,
+    pub charValue: u16,
+    pub intValue: i32,
+    pub longValue: i64,
+    pub floatValue: f32,
+    pub doubleValue: f64,
+    pub enumValue: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum,
+    pub parcelableValue: crate::mangled::_7_android_4_aidl_5_tests_9_FixedSize_10_FixedUnion,
+  }
+  impl Default for FixedParcelable {
+    fn default() -> Self {
+      Self {
+        booleanValue: false,
+        byteValue: 0,
+        charValue: '\0' as u16,
+        intValue: 0,
+        longValue: 0,
+        floatValue: 0.000000f32,
+        doubleValue: 0.000000f64,
+        enumValue: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum::FOO,
+        parcelableValue: Default::default(),
+      }
+    }
+  }
+  impl binder::Parcelable for FixedParcelable {
+    fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_write(|subparcel| {
+        subparcel.write(&self.booleanValue)?;
+        subparcel.write(&self.byteValue)?;
+        subparcel.write(&self.charValue)?;
+        subparcel.write(&self.intValue)?;
+        subparcel.write(&self.longValue)?;
+        subparcel.write(&self.floatValue)?;
+        subparcel.write(&self.doubleValue)?;
+        subparcel.write(&self.enumValue)?;
+        subparcel.write(&self.parcelableValue)?;
+        Ok(())
+      })
+    }
+    fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_read(|subparcel| {
+        if subparcel.has_more_data() {
+          self.booleanValue = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.byteValue = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.charValue = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.intValue = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.longValue = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.floatValue = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.doubleValue = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.enumValue = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.parcelableValue = subparcel.read()?;
+        }
+        Ok(())
+      })
+    }
+  }
+  binder::impl_serialize_for_parcelable!(FixedParcelable);
+  binder::impl_deserialize_for_parcelable!(FixedParcelable);
+  impl binder::binder_impl::ParcelableMetadata for FixedParcelable {
+    fn get_descriptor() -> &'static str { "android.aidl.tests.FixedSize.FixedParcelable" }
+  }
+}
+pub mod FixedUnion {
+  #[derive(Debug)]
+  pub enum FixedUnion {
+    BooleanValue(bool),
+    ByteValue(i8),
+    CharValue(u16),
+    IntValue(i32),
+    LongValue(i64),
+    FloatValue(f32),
+    DoubleValue(f64),
+    EnumValue(crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum),
+  }
+  impl Default for FixedUnion {
+    fn default() -> Self {
+      Self::BooleanValue(false)
+    }
+  }
+  impl binder::Parcelable for FixedUnion {
+    fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      match self {
+        Self::BooleanValue(v) => {
+          parcel.write(&0i32)?;
+          parcel.write(v)
+        }
+        Self::ByteValue(v) => {
+          parcel.write(&1i32)?;
+          parcel.write(v)
+        }
+        Self::CharValue(v) => {
+          parcel.write(&2i32)?;
+          parcel.write(v)
+        }
+        Self::IntValue(v) => {
+          parcel.write(&3i32)?;
+          parcel.write(v)
+        }
+        Self::LongValue(v) => {
+          parcel.write(&4i32)?;
+          parcel.write(v)
+        }
+        Self::FloatValue(v) => {
+          parcel.write(&5i32)?;
+          parcel.write(v)
+        }
+        Self::DoubleValue(v) => {
+          parcel.write(&6i32)?;
+          parcel.write(v)
+        }
+        Self::EnumValue(v) => {
+          parcel.write(&7i32)?;
+          parcel.write(v)
+        }
+      }
+    }
+    fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      let tag: i32 = parcel.read()?;
+      match tag {
+        0 => {
+          let value: bool = parcel.read()?;
+          *self = Self::BooleanValue(value);
+          Ok(())
+        }
+        1 => {
+          let value: i8 = parcel.read()?;
+          *self = Self::ByteValue(value);
+          Ok(())
+        }
+        2 => {
+          let value: u16 = parcel.read()?;
+          *self = Self::CharValue(value);
+          Ok(())
+        }
+        3 => {
+          let value: i32 = parcel.read()?;
+          *self = Self::IntValue(value);
+          Ok(())
+        }
+        4 => {
+          let value: i64 = parcel.read()?;
+          *self = Self::LongValue(value);
+          Ok(())
+        }
+        5 => {
+          let value: f32 = parcel.read()?;
+          *self = Self::FloatValue(value);
+          Ok(())
+        }
+        6 => {
+          let value: f64 = parcel.read()?;
+          *self = Self::DoubleValue(value);
+          Ok(())
+        }
+        7 => {
+          let value: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum = parcel.read()?;
+          *self = Self::EnumValue(value);
+          Ok(())
+        }
+        _ => {
+          Err(binder::StatusCode::BAD_VALUE)
+        }
+      }
+    }
+  }
+  binder::impl_serialize_for_parcelable!(FixedUnion);
+  binder::impl_deserialize_for_parcelable!(FixedUnion);
+  impl binder::binder_impl::ParcelableMetadata for FixedUnion {
+    fn get_descriptor() -> &'static str { "android.aidl.tests.FixedSize.FixedUnion" }
+  }
+}
+pub(crate) mod mangled {
+ pub use super::FixedSize as _7_android_4_aidl_5_tests_9_FixedSize;
+ pub use super::FixedParcelable::FixedParcelable as _7_android_4_aidl_5_tests_9_FixedSize_15_FixedParcelable;
+ pub use super::FixedUnion::FixedUnion as _7_android_4_aidl_5_tests_9_FixedSize_10_FixedUnion;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs.d
new file mode 100644
index 0000000..0635f5e
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/FixedSize.rs : \
+  system/tools/aidl/tests/android/aidl/tests/FixedSize.aidl \
+  system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/GenericStructuredParcelable.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/GenericStructuredParcelable.rs
index 24fcd99..2729f51 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/GenericStructuredParcelable.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/GenericStructuredParcelable.rs
@@ -1,9 +1,10 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #[derive(Debug)]
 pub struct GenericStructuredParcelable {
   pub a: i32,
   pub b: i32,
 }
-pub(crate) mod mangled { pub use super::GenericStructuredParcelable as _7_android_4_aidl_5_tests_27_GenericStructuredParcelable; }
 impl Default for GenericStructuredParcelable {
   fn default() -> Self {
     Self {
@@ -12,57 +13,31 @@
     }
   }
 }
-impl binder::parcel::Serialize for GenericStructuredParcelable {
-  fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-  }
-}
-impl binder::parcel::SerializeArray for GenericStructuredParcelable {}
-impl binder::parcel::SerializeOption for GenericStructuredParcelable {
-  fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    let this = if let Some(this) = this {
-      parcel.write(&1i32)?;
-      this
-    } else {
-      return parcel.write(&0i32);
-    };
+impl binder::Parcelable for GenericStructuredParcelable {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
     parcel.sized_write(|subparcel| {
-      subparcel.write(&this.a)?;
-      subparcel.write(&this.b)?;
+      subparcel.write(&self.a)?;
+      subparcel.write(&self.b)?;
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      if subparcel.has_more_data() {
+        self.a = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.b = subparcel.read()?;
+      }
       Ok(())
     })
   }
 }
-impl binder::parcel::Deserialize for GenericStructuredParcelable {
-  fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-    <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-       .transpose()
-       .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-  }
+binder::impl_serialize_for_parcelable!(GenericStructuredParcelable);
+binder::impl_deserialize_for_parcelable!(GenericStructuredParcelable);
+impl binder::binder_impl::ParcelableMetadata for GenericStructuredParcelable {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.GenericStructuredParcelable" }
 }
-impl binder::parcel::DeserializeArray for GenericStructuredParcelable {}
-impl binder::parcel::DeserializeOption for GenericStructuredParcelable {
-  fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-    let status: i32 = parcel.read()?;
-    if status == 0 { return Ok(None); }
-    let start_pos = parcel.get_data_position();
-    let parcelable_size: i32 = parcel.read()?;
-    if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-    if start_pos.checked_add(parcelable_size).is_none() {
-      return Err(binder::StatusCode::BAD_VALUE);
-    }
-    let mut result = Self::default();
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.a = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.b = parcel.read()?;
-    unsafe {
-      parcel.set_data_position(start_pos + parcelable_size)?;
-    }
-    Ok(Some(result))
-  }
+pub(crate) mod mangled {
+ pub use super::GenericStructuredParcelable as _7_android_4_aidl_5_tests_27_GenericStructuredParcelable;
 }
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IDeprecated.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IDeprecated.rs
index 5920654..599a651 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IDeprecated.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IDeprecated.rs
@@ -1,12 +1,15 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 #![allow(non_snake_case)]
-#[allow(unused_imports)] use binder::IBinderInternal;
+#[allow(unused_imports)] use binder::binder_impl::IBinderInternal;
 use binder::declare_binder_interface;
 declare_binder_interface! {
   IDeprecated["android.aidl.tests.IDeprecated"] {
     native: BnDeprecated(on_transact),
     proxy: BpDeprecated {
     },
+    async: IDeprecatedAsync,
   }
 }
 #[deprecated = "test"]
@@ -19,6 +22,40 @@
     std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
   }
 }
+#[deprecated = "test"]
+pub trait IDeprecatedAsync<P>: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.IDeprecated" }
+}
+#[deprecated = "test"]
+#[::async_trait::async_trait]
+pub trait IDeprecatedAsyncServer: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.IDeprecated" }
+}
+impl BnDeprecated {
+  /// Create a new async binder service.
+  pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn IDeprecated>
+  where
+    T: IDeprecatedAsyncServer + binder::Interface + Send + Sync + 'static,
+    R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+  {
+    struct Wrapper<T, R> {
+      _inner: T,
+      _rt: R,
+    }
+    impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+      fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+      fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+    }
+    impl<T, R> IDeprecated for Wrapper<T, R>
+    where
+      T: IDeprecatedAsyncServer + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+    }
+    let wrapped = Wrapper { _inner: inner, _rt: rt };
+    Self::new_binder(wrapped, features)
+  }
+}
 pub trait IDeprecatedDefault: Send + Sync {
 }
 pub mod transactions {
@@ -28,13 +65,19 @@
 lazy_static! {
   static ref DEFAULT_IMPL: std::sync::Mutex<IDeprecatedDefaultRef> = std::sync::Mutex::new(None);
 }
-pub(crate) mod mangled { pub use super::IDeprecated as _7_android_4_aidl_5_tests_11_IDeprecated; }
+impl BpDeprecated {
+}
 impl IDeprecated for BpDeprecated {
 }
-impl IDeprecated for binder::Binder<BnDeprecated> {
+impl<P: binder::BinderAsyncPool> IDeprecatedAsync<P> for BpDeprecated {
 }
-fn on_transact(_aidl_service: &dyn IDeprecated, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+impl IDeprecated for binder::binder_impl::Binder<BnDeprecated> {
+}
+fn on_transact(_aidl_service: &dyn IDeprecated, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
   match _aidl_code {
     _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
   }
 }
+pub(crate) mod mangled {
+ pub use super::IDeprecated as _7_android_4_aidl_5_tests_11_IDeprecated;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/INamedCallback.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/INamedCallback.rs
index f8d1fba..49ae584 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/INamedCallback.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/INamedCallback.rs
@@ -1,17 +1,20 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 #![allow(non_snake_case)]
-#[allow(unused_imports)] use binder::IBinderInternal;
+#[allow(unused_imports)] use binder::binder_impl::IBinderInternal;
 use binder::declare_binder_interface;
 declare_binder_interface! {
   INamedCallback["android.aidl.tests.INamedCallback"] {
     native: BnNamedCallback(on_transact),
     proxy: BpNamedCallback {
     },
+    async: INamedCallbackAsync,
   }
 }
 pub trait INamedCallback: binder::Interface + Send {
   fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.INamedCallback" }
-  fn GetName(&self) -> binder::public_api::Result<String>;
+  fn GetName(&self) -> binder::Result<String>;
   fn getDefaultImpl() -> INamedCallbackDefaultRef where Self: Sized {
     DEFAULT_IMPL.lock().unwrap().clone()
   }
@@ -19,25 +22,62 @@
     std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
   }
 }
+pub trait INamedCallbackAsync<P>: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.INamedCallback" }
+  fn GetName<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<String>>;
+}
+#[::async_trait::async_trait]
+pub trait INamedCallbackAsyncServer: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.INamedCallback" }
+  async fn GetName(&self) -> binder::Result<String>;
+}
+impl BnNamedCallback {
+  /// Create a new async binder service.
+  pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn INamedCallback>
+  where
+    T: INamedCallbackAsyncServer + binder::Interface + Send + Sync + 'static,
+    R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+  {
+    struct Wrapper<T, R> {
+      _inner: T,
+      _rt: R,
+    }
+    impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+      fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+      fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+    }
+    impl<T, R> INamedCallback for Wrapper<T, R>
+    where
+      T: INamedCallbackAsyncServer + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      fn GetName(&self) -> binder::Result<String> {
+        self._rt.block_on(self._inner.GetName())
+      }
+    }
+    let wrapped = Wrapper { _inner: inner, _rt: rt };
+    Self::new_binder(wrapped, features)
+  }
+}
 pub trait INamedCallbackDefault: Send + Sync {
-  fn GetName(&self) -> binder::public_api::Result<String> {
+  fn GetName(&self) -> binder::Result<String> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
 }
 pub mod transactions {
-  pub const GetName: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 0;
+  pub const GetName: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 0;
 }
 pub type INamedCallbackDefaultRef = Option<std::sync::Arc<dyn INamedCallbackDefault>>;
 use lazy_static::lazy_static;
 lazy_static! {
   static ref DEFAULT_IMPL: std::sync::Mutex<INamedCallbackDefaultRef> = std::sync::Mutex::new(None);
 }
-pub(crate) mod mangled { pub use super::INamedCallback as _7_android_4_aidl_5_tests_14_INamedCallback; }
-impl INamedCallback for BpNamedCallback {
-  fn GetName(&self) -> binder::public_api::Result<String> {
-    let _aidl_reply = self.binder.transact(transactions::GetName, binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      Ok(())
-    });
+impl BpNamedCallback {
+  fn build_parcel_GetName(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    Ok(aidl_data)
+  }
+  fn read_response_GetName(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<String> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as INamedCallback>::getDefaultImpl() {
         return _aidl_default_impl.GetName();
@@ -50,10 +90,32 @@
     Ok(_aidl_return)
   }
 }
-impl INamedCallback for binder::Binder<BnNamedCallback> {
-  fn GetName(&self) -> binder::public_api::Result<String> { self.0.GetName() }
+impl INamedCallback for BpNamedCallback {
+  fn GetName(&self) -> binder::Result<String> {
+    let _aidl_data = self.build_parcel_GetName()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::GetName, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_GetName(_aidl_reply)
+  }
 }
-fn on_transact(_aidl_service: &dyn INamedCallback, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+impl<P: binder::BinderAsyncPool> INamedCallbackAsync<P> for BpNamedCallback {
+  fn GetName<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<String>> {
+    let _aidl_data = match self.build_parcel_GetName() {
+      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::GetName, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_GetName(_aidl_reply)
+      }
+    )
+  }
+}
+impl INamedCallback for binder::binder_impl::Binder<BnNamedCallback> {
+  fn GetName(&self) -> binder::Result<String> { self.0.GetName() }
+}
+fn on_transact(_aidl_service: &dyn INamedCallback, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
   match _aidl_code {
     transactions::GetName => {
       let _aidl_return = _aidl_service.GetName();
@@ -69,3 +131,6 @@
     _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
   }
 }
+pub(crate) mod mangled {
+ pub use super::INamedCallback as _7_android_4_aidl_5_tests_14_INamedCallback;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/INewName.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/INewName.rs
index 70b6bd1..f8003b5 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/INewName.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/INewName.rs
@@ -1,17 +1,20 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 #![allow(non_snake_case)]
-#[allow(unused_imports)] use binder::IBinderInternal;
+#[allow(unused_imports)] use binder::binder_impl::IBinderInternal;
 use binder::declare_binder_interface;
 declare_binder_interface! {
   INewName["android.aidl.tests.IOldName"] {
     native: BnNewName(on_transact),
     proxy: BpNewName {
     },
+    async: INewNameAsync,
   }
 }
 pub trait INewName: binder::Interface + Send {
   fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.IOldName" }
-  fn RealName(&self) -> binder::public_api::Result<String>;
+  fn RealName(&self) -> binder::Result<String>;
   fn getDefaultImpl() -> INewNameDefaultRef where Self: Sized {
     DEFAULT_IMPL.lock().unwrap().clone()
   }
@@ -19,25 +22,62 @@
     std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
   }
 }
+pub trait INewNameAsync<P>: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.IOldName" }
+  fn RealName<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<String>>;
+}
+#[::async_trait::async_trait]
+pub trait INewNameAsyncServer: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.IOldName" }
+  async fn RealName(&self) -> binder::Result<String>;
+}
+impl BnNewName {
+  /// Create a new async binder service.
+  pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn INewName>
+  where
+    T: INewNameAsyncServer + binder::Interface + Send + Sync + 'static,
+    R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+  {
+    struct Wrapper<T, R> {
+      _inner: T,
+      _rt: R,
+    }
+    impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+      fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+      fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+    }
+    impl<T, R> INewName for Wrapper<T, R>
+    where
+      T: INewNameAsyncServer + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      fn RealName(&self) -> binder::Result<String> {
+        self._rt.block_on(self._inner.RealName())
+      }
+    }
+    let wrapped = Wrapper { _inner: inner, _rt: rt };
+    Self::new_binder(wrapped, features)
+  }
+}
 pub trait INewNameDefault: Send + Sync {
-  fn RealName(&self) -> binder::public_api::Result<String> {
+  fn RealName(&self) -> binder::Result<String> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
 }
 pub mod transactions {
-  pub const RealName: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 0;
+  pub const RealName: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 0;
 }
 pub type INewNameDefaultRef = Option<std::sync::Arc<dyn INewNameDefault>>;
 use lazy_static::lazy_static;
 lazy_static! {
   static ref DEFAULT_IMPL: std::sync::Mutex<INewNameDefaultRef> = std::sync::Mutex::new(None);
 }
-pub(crate) mod mangled { pub use super::INewName as _7_android_4_aidl_5_tests_8_INewName; }
-impl INewName for BpNewName {
-  fn RealName(&self) -> binder::public_api::Result<String> {
-    let _aidl_reply = self.binder.transact(transactions::RealName, binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      Ok(())
-    });
+impl BpNewName {
+  fn build_parcel_RealName(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    Ok(aidl_data)
+  }
+  fn read_response_RealName(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<String> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as INewName>::getDefaultImpl() {
         return _aidl_default_impl.RealName();
@@ -50,10 +90,32 @@
     Ok(_aidl_return)
   }
 }
-impl INewName for binder::Binder<BnNewName> {
-  fn RealName(&self) -> binder::public_api::Result<String> { self.0.RealName() }
+impl INewName for BpNewName {
+  fn RealName(&self) -> binder::Result<String> {
+    let _aidl_data = self.build_parcel_RealName()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RealName, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RealName(_aidl_reply)
+  }
 }
-fn on_transact(_aidl_service: &dyn INewName, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+impl<P: binder::BinderAsyncPool> INewNameAsync<P> for BpNewName {
+  fn RealName<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<String>> {
+    let _aidl_data = match self.build_parcel_RealName() {
+      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::RealName, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RealName(_aidl_reply)
+      }
+    )
+  }
+}
+impl INewName for binder::binder_impl::Binder<BnNewName> {
+  fn RealName(&self) -> binder::Result<String> { self.0.RealName() }
+}
+fn on_transact(_aidl_service: &dyn INewName, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
   match _aidl_code {
     transactions::RealName => {
       let _aidl_return = _aidl_service.RealName();
@@ -69,3 +131,6 @@
     _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
   }
 }
+pub(crate) mod mangled {
+ pub use super::INewName as _7_android_4_aidl_5_tests_8_INewName;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IOldName.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IOldName.rs
index a61d664..e10bf92 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IOldName.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IOldName.rs
@@ -1,17 +1,20 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 #![allow(non_snake_case)]
-#[allow(unused_imports)] use binder::IBinderInternal;
+#[allow(unused_imports)] use binder::binder_impl::IBinderInternal;
 use binder::declare_binder_interface;
 declare_binder_interface! {
   IOldName["android.aidl.tests.IOldName"] {
     native: BnOldName(on_transact),
     proxy: BpOldName {
     },
+    async: IOldNameAsync,
   }
 }
 pub trait IOldName: binder::Interface + Send {
   fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.IOldName" }
-  fn RealName(&self) -> binder::public_api::Result<String>;
+  fn RealName(&self) -> binder::Result<String>;
   fn getDefaultImpl() -> IOldNameDefaultRef where Self: Sized {
     DEFAULT_IMPL.lock().unwrap().clone()
   }
@@ -19,25 +22,62 @@
     std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
   }
 }
+pub trait IOldNameAsync<P>: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.IOldName" }
+  fn RealName<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<String>>;
+}
+#[::async_trait::async_trait]
+pub trait IOldNameAsyncServer: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.IOldName" }
+  async fn RealName(&self) -> binder::Result<String>;
+}
+impl BnOldName {
+  /// Create a new async binder service.
+  pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn IOldName>
+  where
+    T: IOldNameAsyncServer + binder::Interface + Send + Sync + 'static,
+    R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+  {
+    struct Wrapper<T, R> {
+      _inner: T,
+      _rt: R,
+    }
+    impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+      fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+      fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+    }
+    impl<T, R> IOldName for Wrapper<T, R>
+    where
+      T: IOldNameAsyncServer + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      fn RealName(&self) -> binder::Result<String> {
+        self._rt.block_on(self._inner.RealName())
+      }
+    }
+    let wrapped = Wrapper { _inner: inner, _rt: rt };
+    Self::new_binder(wrapped, features)
+  }
+}
 pub trait IOldNameDefault: Send + Sync {
-  fn RealName(&self) -> binder::public_api::Result<String> {
+  fn RealName(&self) -> binder::Result<String> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
 }
 pub mod transactions {
-  pub const RealName: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 0;
+  pub const RealName: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 0;
 }
 pub type IOldNameDefaultRef = Option<std::sync::Arc<dyn IOldNameDefault>>;
 use lazy_static::lazy_static;
 lazy_static! {
   static ref DEFAULT_IMPL: std::sync::Mutex<IOldNameDefaultRef> = std::sync::Mutex::new(None);
 }
-pub(crate) mod mangled { pub use super::IOldName as _7_android_4_aidl_5_tests_8_IOldName; }
-impl IOldName for BpOldName {
-  fn RealName(&self) -> binder::public_api::Result<String> {
-    let _aidl_reply = self.binder.transact(transactions::RealName, binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      Ok(())
-    });
+impl BpOldName {
+  fn build_parcel_RealName(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    Ok(aidl_data)
+  }
+  fn read_response_RealName(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<String> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as IOldName>::getDefaultImpl() {
         return _aidl_default_impl.RealName();
@@ -50,10 +90,32 @@
     Ok(_aidl_return)
   }
 }
-impl IOldName for binder::Binder<BnOldName> {
-  fn RealName(&self) -> binder::public_api::Result<String> { self.0.RealName() }
+impl IOldName for BpOldName {
+  fn RealName(&self) -> binder::Result<String> {
+    let _aidl_data = self.build_parcel_RealName()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RealName, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RealName(_aidl_reply)
+  }
 }
-fn on_transact(_aidl_service: &dyn IOldName, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+impl<P: binder::BinderAsyncPool> IOldNameAsync<P> for BpOldName {
+  fn RealName<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<String>> {
+    let _aidl_data = match self.build_parcel_RealName() {
+      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::RealName, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RealName(_aidl_reply)
+      }
+    )
+  }
+}
+impl IOldName for binder::binder_impl::Binder<BnOldName> {
+  fn RealName(&self) -> binder::Result<String> { self.0.RealName() }
+}
+fn on_transact(_aidl_service: &dyn IOldName, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
   match _aidl_code {
     transactions::RealName => {
       let _aidl_return = _aidl_service.RealName();
@@ -69,3 +131,6 @@
     _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
   }
 }
+pub(crate) mod mangled {
+ pub use super::IOldName as _7_android_4_aidl_5_tests_8_IOldName;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ITestService.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ITestService.rs
index 2e34dba..9e8fd92 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ITestService.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ITestService.rs
@@ -1,68 +1,85 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 #![allow(non_snake_case)]
-#[allow(unused_imports)] use binder::IBinderInternal;
+#[allow(unused_imports)] use binder::binder_impl::IBinderInternal;
 use binder::declare_binder_interface;
 declare_binder_interface! {
   ITestService["android.aidl.tests.ITestService"] {
     native: BnTestService(on_transact),
     proxy: BpTestService {
     },
+    async: ITestServiceAsync,
   }
 }
 pub trait ITestService: binder::Interface + Send {
   fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.ITestService" }
-  fn UnimplementedMethod(&self, _arg_arg: i32) -> binder::public_api::Result<i32>;
+  fn UnimplementedMethod(&self, _arg_arg: i32) -> binder::Result<i32>;
   #[deprecated = "to make sure we have something in system/tools/aidl which does a compile check of deprecated and make sure this is reflected in goldens"]
-  fn Deprecated(&self) -> binder::public_api::Result<()>;
-  fn TestOneway(&self) -> binder::public_api::Result<()>;
-  fn RepeatBoolean(&self, _arg_token: bool) -> binder::public_api::Result<bool>;
-  fn RepeatByte(&self, _arg_token: i8) -> binder::public_api::Result<i8>;
-  fn RepeatChar(&self, _arg_token: u16) -> binder::public_api::Result<u16>;
-  fn RepeatInt(&self, _arg_token: i32) -> binder::public_api::Result<i32>;
-  fn RepeatLong(&self, _arg_token: i64) -> binder::public_api::Result<i64>;
-  fn RepeatFloat(&self, _arg_token: f32) -> binder::public_api::Result<f32>;
-  fn RepeatDouble(&self, _arg_token: f64) -> binder::public_api::Result<f64>;
-  fn RepeatString(&self, _arg_token: &str) -> binder::public_api::Result<String>;
-  fn RepeatByteEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>;
-  fn RepeatIntEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>;
-  fn RepeatLongEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>;
-  fn ReverseBoolean(&self, _arg_input: &[bool], _arg_repeated: &mut Vec<bool>) -> binder::public_api::Result<Vec<bool>>;
-  fn ReverseByte(&self, _arg_input: &[u8], _arg_repeated: &mut Vec<u8>) -> binder::public_api::Result<Vec<u8>>;
-  fn ReverseChar(&self, _arg_input: &[u16], _arg_repeated: &mut Vec<u16>) -> binder::public_api::Result<Vec<u16>>;
-  fn ReverseInt(&self, _arg_input: &[i32], _arg_repeated: &mut Vec<i32>) -> binder::public_api::Result<Vec<i32>>;
-  fn ReverseLong(&self, _arg_input: &[i64], _arg_repeated: &mut Vec<i64>) -> binder::public_api::Result<Vec<i64>>;
-  fn ReverseFloat(&self, _arg_input: &[f32], _arg_repeated: &mut Vec<f32>) -> binder::public_api::Result<Vec<f32>>;
-  fn ReverseDouble(&self, _arg_input: &[f64], _arg_repeated: &mut Vec<f64>) -> binder::public_api::Result<Vec<f64>>;
-  fn ReverseString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::public_api::Result<Vec<String>>;
-  fn ReverseByteEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>) -> binder::public_api::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>;
-  fn ReverseIntEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>) -> binder::public_api::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>;
-  fn ReverseLongEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>) -> binder::public_api::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>;
-  fn GetOtherTestService(&self, _arg_name: &str) -> binder::public_api::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>;
-  fn VerifyName(&self, _arg_service: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &str) -> binder::public_api::Result<bool>;
-  fn ReverseStringList(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::public_api::Result<Vec<String>>;
-  fn RepeatParcelFileDescriptor(&self, _arg_read: &binder::parcel::ParcelFileDescriptor) -> binder::public_api::Result<binder::parcel::ParcelFileDescriptor>;
-  fn ReverseParcelFileDescriptorArray(&self, _arg_input: &[binder::parcel::ParcelFileDescriptor], _arg_repeated: &mut Vec<Option<binder::parcel::ParcelFileDescriptor>>) -> binder::public_api::Result<Vec<binder::parcel::ParcelFileDescriptor>>;
-  fn ThrowServiceException(&self, _arg_code: i32) -> binder::public_api::Result<()>;
-  fn RepeatNullableIntArray(&self, _arg_input: Option<&[i32]>) -> binder::public_api::Result<Option<Vec<i32>>>;
-  fn RepeatNullableByteEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>) -> binder::public_api::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>>;
-  fn RepeatNullableIntEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>) -> binder::public_api::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>>;
-  fn RepeatNullableLongEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>) -> binder::public_api::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>>;
-  fn RepeatNullableString(&self, _arg_input: Option<&str>) -> binder::public_api::Result<Option<String>>;
-  fn RepeatNullableStringList(&self, _arg_input: Option<&[Option<String>]>) -> binder::public_api::Result<Option<Vec<Option<String>>>>;
-  fn RepeatNullableParcelable(&self, _arg_input: Option<&crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable>) -> binder::public_api::Result<Option<crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable>>;
-  fn TakesAnIBinder(&self, _arg_input: &binder::SpIBinder) -> binder::public_api::Result<()>;
-  fn TakesANullableIBinder(&self, _arg_input: Option<&binder::SpIBinder>) -> binder::public_api::Result<()>;
-  fn RepeatUtf8CppString(&self, _arg_token: &str) -> binder::public_api::Result<String>;
-  fn RepeatNullableUtf8CppString(&self, _arg_token: Option<&str>) -> binder::public_api::Result<Option<String>>;
-  fn ReverseUtf8CppString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::public_api::Result<Vec<String>>;
-  fn ReverseNullableUtf8CppString(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::public_api::Result<Option<Vec<Option<String>>>>;
-  fn ReverseUtf8CppStringList(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::public_api::Result<Option<Vec<Option<String>>>>;
-  fn GetCallback(&self, _arg_return_null: bool) -> binder::public_api::Result<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>;
-  fn FillOutStructuredParcelable(&self, _arg_parcel: &mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable) -> binder::public_api::Result<()>;
-  fn GetOldNameInterface(&self) -> binder::public_api::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName>>;
-  fn GetNewNameInterface(&self) -> binder::public_api::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName>>;
-  fn GetCppJavaTests(&self) -> binder::public_api::Result<Option<binder::SpIBinder>>;
-  fn getBackendType(&self) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_11_BackendType>;
+  fn Deprecated(&self) -> binder::Result<()>;
+  fn TestOneway(&self) -> binder::Result<()>;
+  fn RepeatBoolean(&self, _arg_token: bool) -> binder::Result<bool>;
+  fn RepeatByte(&self, _arg_token: i8) -> binder::Result<i8>;
+  fn RepeatChar(&self, _arg_token: u16) -> binder::Result<u16>;
+  fn RepeatInt(&self, _arg_token: i32) -> binder::Result<i32>;
+  fn RepeatLong(&self, _arg_token: i64) -> binder::Result<i64>;
+  fn RepeatFloat(&self, _arg_token: f32) -> binder::Result<f32>;
+  fn RepeatDouble(&self, _arg_token: f64) -> binder::Result<f64>;
+  fn RepeatString(&self, _arg_token: &str) -> binder::Result<String>;
+  fn RepeatByteEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>;
+  fn RepeatIntEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>;
+  fn RepeatLongEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>;
+  fn ReverseBoolean(&self, _arg_input: &[bool], _arg_repeated: &mut Vec<bool>) -> binder::Result<Vec<bool>>;
+  fn ReverseByte(&self, _arg_input: &[u8], _arg_repeated: &mut Vec<u8>) -> binder::Result<Vec<u8>>;
+  fn ReverseChar(&self, _arg_input: &[u16], _arg_repeated: &mut Vec<u16>) -> binder::Result<Vec<u16>>;
+  fn ReverseInt(&self, _arg_input: &[i32], _arg_repeated: &mut Vec<i32>) -> binder::Result<Vec<i32>>;
+  fn ReverseLong(&self, _arg_input: &[i64], _arg_repeated: &mut Vec<i64>) -> binder::Result<Vec<i64>>;
+  fn ReverseFloat(&self, _arg_input: &[f32], _arg_repeated: &mut Vec<f32>) -> binder::Result<Vec<f32>>;
+  fn ReverseDouble(&self, _arg_input: &[f64], _arg_repeated: &mut Vec<f64>) -> binder::Result<Vec<f64>>;
+  fn ReverseString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>>;
+  fn ReverseByteEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>;
+  fn ReverseIntEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>;
+  fn ReverseLongEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>;
+  fn GetOtherTestService(&self, _arg_name: &str) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>;
+  fn VerifyName(&self, _arg_service: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &str) -> binder::Result<bool>;
+  fn GetInterfaceArray(&self, _arg_names: &[String]) -> binder::Result<Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>;
+  fn VerifyNamesWithInterfaceArray(&self, _arg_services: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>], _arg_names: &[String]) -> binder::Result<bool>;
+  fn GetNullableInterfaceArray(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>>;
+  fn VerifyNamesWithNullableInterfaceArray(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<bool>;
+  fn GetInterfaceList(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>>;
+  fn VerifyNamesWithInterfaceList(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<bool>;
+  fn ReverseStringList(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>>;
+  fn RepeatParcelFileDescriptor(&self, _arg_read: &binder::ParcelFileDescriptor) -> binder::Result<binder::ParcelFileDescriptor>;
+  fn ReverseParcelFileDescriptorArray(&self, _arg_input: &[binder::ParcelFileDescriptor], _arg_repeated: &mut Vec<Option<binder::ParcelFileDescriptor>>) -> binder::Result<Vec<binder::ParcelFileDescriptor>>;
+  fn ThrowServiceException(&self, _arg_code: i32) -> binder::Result<()>;
+  fn RepeatNullableIntArray(&self, _arg_input: Option<&[i32]>) -> binder::Result<Option<Vec<i32>>>;
+  fn RepeatNullableByteEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>>;
+  fn RepeatNullableIntEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>>;
+  fn RepeatNullableLongEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>>;
+  fn RepeatNullableString(&self, _arg_input: Option<&str>) -> binder::Result<Option<String>>;
+  fn RepeatNullableStringList(&self, _arg_input: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<String>>>>;
+  fn RepeatNullableParcelable(&self, _arg_input: Option<&crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>) -> binder::Result<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>;
+  fn RepeatNullableParcelableArray(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>>;
+  fn RepeatNullableParcelableList(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>>;
+  fn TakesAnIBinder(&self, _arg_input: &binder::SpIBinder) -> binder::Result<()>;
+  fn TakesANullableIBinder(&self, _arg_input: Option<&binder::SpIBinder>) -> binder::Result<()>;
+  fn TakesAnIBinderList(&self, _arg_input: &[binder::SpIBinder]) -> binder::Result<()>;
+  fn TakesANullableIBinderList(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>) -> binder::Result<()>;
+  fn RepeatUtf8CppString(&self, _arg_token: &str) -> binder::Result<String>;
+  fn RepeatNullableUtf8CppString(&self, _arg_token: Option<&str>) -> binder::Result<Option<String>>;
+  fn ReverseUtf8CppString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>>;
+  fn ReverseNullableUtf8CppString(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<Option<Vec<Option<String>>>>;
+  fn ReverseUtf8CppStringList(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<Option<Vec<Option<String>>>>;
+  fn GetCallback(&self, _arg_return_null: bool) -> binder::Result<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>;
+  fn FillOutStructuredParcelable(&self, _arg_parcel: &mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable) -> binder::Result<()>;
+  fn RepeatExtendableParcelable(&self, _arg_ep: &crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable, _arg_ep2: &mut crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable) -> binder::Result<()>;
+  fn ReverseList(&self, _arg_list: &crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList>;
+  fn ReverseIBinderArray(&self, _arg_input: &[binder::SpIBinder], _arg_repeated: &mut Vec<Option<binder::SpIBinder>>) -> binder::Result<Vec<binder::SpIBinder>>;
+  fn ReverseNullableIBinderArray(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>, _arg_repeated: &mut Option<Vec<Option<binder::SpIBinder>>>) -> binder::Result<Option<Vec<Option<binder::SpIBinder>>>>;
+  fn GetOldNameInterface(&self) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName>>;
+  fn GetNewNameInterface(&self) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName>>;
+  fn GetCppJavaTests(&self) -> binder::Result<Option<binder::SpIBinder>>;
+  fn getBackendType(&self) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_11_BackendType>;
   fn getDefaultImpl() -> ITestServiceDefaultRef where Self: Sized {
     DEFAULT_IMPL.lock().unwrap().clone()
   }
@@ -70,213 +87,628 @@
     std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
   }
 }
+pub trait ITestServiceAsync<P>: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.ITestService" }
+  fn UnimplementedMethod<'a>(&'a self, _arg_arg: i32) -> binder::BoxFuture<'a, binder::Result<i32>>;
+  #[deprecated = "to make sure we have something in system/tools/aidl which does a compile check of deprecated and make sure this is reflected in goldens"]
+  fn Deprecated<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<()>>;
+  fn TestOneway(&self) -> std::future::Ready<binder::Result<()>>;
+  fn RepeatBoolean<'a>(&'a self, _arg_token: bool) -> binder::BoxFuture<'a, binder::Result<bool>>;
+  fn RepeatByte<'a>(&'a self, _arg_token: i8) -> binder::BoxFuture<'a, binder::Result<i8>>;
+  fn RepeatChar<'a>(&'a self, _arg_token: u16) -> binder::BoxFuture<'a, binder::Result<u16>>;
+  fn RepeatInt<'a>(&'a self, _arg_token: i32) -> binder::BoxFuture<'a, binder::Result<i32>>;
+  fn RepeatLong<'a>(&'a self, _arg_token: i64) -> binder::BoxFuture<'a, binder::Result<i64>>;
+  fn RepeatFloat<'a>(&'a self, _arg_token: f32) -> binder::BoxFuture<'a, binder::Result<f32>>;
+  fn RepeatDouble<'a>(&'a self, _arg_token: f64) -> binder::BoxFuture<'a, binder::Result<f64>>;
+  fn RepeatString<'a>(&'a self, _arg_token: &'a str) -> binder::BoxFuture<'a, binder::Result<String>>;
+  fn RepeatByteEnum<'a>(&'a self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum) -> binder::BoxFuture<'a, binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>;
+  fn RepeatIntEnum<'a>(&'a self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum) -> binder::BoxFuture<'a, binder::Result<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>;
+  fn RepeatLongEnum<'a>(&'a self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum) -> binder::BoxFuture<'a, binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>;
+  fn ReverseBoolean<'a>(&'a self, _arg_input: &'a [bool], _arg_repeated: &'a mut Vec<bool>) -> binder::BoxFuture<'a, binder::Result<Vec<bool>>>;
+  fn ReverseByte<'a>(&'a self, _arg_input: &'a [u8], _arg_repeated: &'a mut Vec<u8>) -> binder::BoxFuture<'a, binder::Result<Vec<u8>>>;
+  fn ReverseChar<'a>(&'a self, _arg_input: &'a [u16], _arg_repeated: &'a mut Vec<u16>) -> binder::BoxFuture<'a, binder::Result<Vec<u16>>>;
+  fn ReverseInt<'a>(&'a self, _arg_input: &'a [i32], _arg_repeated: &'a mut Vec<i32>) -> binder::BoxFuture<'a, binder::Result<Vec<i32>>>;
+  fn ReverseLong<'a>(&'a self, _arg_input: &'a [i64], _arg_repeated: &'a mut Vec<i64>) -> binder::BoxFuture<'a, binder::Result<Vec<i64>>>;
+  fn ReverseFloat<'a>(&'a self, _arg_input: &'a [f32], _arg_repeated: &'a mut Vec<f32>) -> binder::BoxFuture<'a, binder::Result<Vec<f32>>>;
+  fn ReverseDouble<'a>(&'a self, _arg_input: &'a [f64], _arg_repeated: &'a mut Vec<f64>) -> binder::BoxFuture<'a, binder::Result<Vec<f64>>>;
+  fn ReverseString<'a>(&'a self, _arg_input: &'a [String], _arg_repeated: &'a mut Vec<String>) -> binder::BoxFuture<'a, binder::Result<Vec<String>>>;
+  fn ReverseByteEnum<'a>(&'a self, _arg_input: &'a [crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &'a mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>) -> binder::BoxFuture<'a, binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>>;
+  fn ReverseIntEnum<'a>(&'a self, _arg_input: &'a [crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &'a mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>) -> binder::BoxFuture<'a, binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>>;
+  fn ReverseLongEnum<'a>(&'a self, _arg_input: &'a [crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &'a mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>) -> binder::BoxFuture<'a, binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>>;
+  fn GetOtherTestService<'a>(&'a self, _arg_name: &'a str) -> binder::BoxFuture<'a, binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>;
+  fn VerifyName<'a>(&'a self, _arg_service: &'a binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &'a str) -> binder::BoxFuture<'a, binder::Result<bool>>;
+  fn GetInterfaceArray<'a>(&'a self, _arg_names: &'a [String]) -> binder::BoxFuture<'a, binder::Result<Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>;
+  fn VerifyNamesWithInterfaceArray<'a>(&'a self, _arg_services: &'a [binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>], _arg_names: &'a [String]) -> binder::BoxFuture<'a, binder::Result<bool>>;
+  fn GetNullableInterfaceArray<'a>(&'a self, _arg_names: Option<&'a [Option<String>]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>>>;
+  fn VerifyNamesWithNullableInterfaceArray<'a>(&'a self, _arg_services: Option<&'a [Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&'a [Option<String>]>) -> binder::BoxFuture<'a, binder::Result<bool>>;
+  fn GetInterfaceList<'a>(&'a self, _arg_names: Option<&'a [Option<String>]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>>>;
+  fn VerifyNamesWithInterfaceList<'a>(&'a self, _arg_services: Option<&'a [Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&'a [Option<String>]>) -> binder::BoxFuture<'a, binder::Result<bool>>;
+  fn ReverseStringList<'a>(&'a self, _arg_input: &'a [String], _arg_repeated: &'a mut Vec<String>) -> binder::BoxFuture<'a, binder::Result<Vec<String>>>;
+  fn RepeatParcelFileDescriptor<'a>(&'a self, _arg_read: &'a binder::ParcelFileDescriptor) -> binder::BoxFuture<'a, binder::Result<binder::ParcelFileDescriptor>>;
+  fn ReverseParcelFileDescriptorArray<'a>(&'a self, _arg_input: &'a [binder::ParcelFileDescriptor], _arg_repeated: &'a mut Vec<Option<binder::ParcelFileDescriptor>>) -> binder::BoxFuture<'a, binder::Result<Vec<binder::ParcelFileDescriptor>>>;
+  fn ThrowServiceException<'a>(&'a self, _arg_code: i32) -> binder::BoxFuture<'a, binder::Result<()>>;
+  fn RepeatNullableIntArray<'a>(&'a self, _arg_input: Option<&'a [i32]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<i32>>>>;
+  fn RepeatNullableByteEnumArray<'a>(&'a self, _arg_input: Option<&'a [crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>>>;
+  fn RepeatNullableIntEnumArray<'a>(&'a self, _arg_input: Option<&'a [crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>>>;
+  fn RepeatNullableLongEnumArray<'a>(&'a self, _arg_input: Option<&'a [crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>>>;
+  fn RepeatNullableString<'a>(&'a self, _arg_input: Option<&'a str>) -> binder::BoxFuture<'a, binder::Result<Option<String>>>;
+  fn RepeatNullableStringList<'a>(&'a self, _arg_input: Option<&'a [Option<String>]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<String>>>>>;
+  fn RepeatNullableParcelable<'a>(&'a self, _arg_input: Option<&'a crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>) -> binder::BoxFuture<'a, binder::Result<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>;
+  fn RepeatNullableParcelableArray<'a>(&'a self, _arg_input: Option<&'a [Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>>>;
+  fn RepeatNullableParcelableList<'a>(&'a self, _arg_input: Option<&'a [Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>>>;
+  fn TakesAnIBinder<'a>(&'a self, _arg_input: &'a binder::SpIBinder) -> binder::BoxFuture<'a, binder::Result<()>>;
+  fn TakesANullableIBinder<'a>(&'a self, _arg_input: Option<&'a binder::SpIBinder>) -> binder::BoxFuture<'a, binder::Result<()>>;
+  fn TakesAnIBinderList<'a>(&'a self, _arg_input: &'a [binder::SpIBinder]) -> binder::BoxFuture<'a, binder::Result<()>>;
+  fn TakesANullableIBinderList<'a>(&'a self, _arg_input: Option<&'a [Option<binder::SpIBinder>]>) -> binder::BoxFuture<'a, binder::Result<()>>;
+  fn RepeatUtf8CppString<'a>(&'a self, _arg_token: &'a str) -> binder::BoxFuture<'a, binder::Result<String>>;
+  fn RepeatNullableUtf8CppString<'a>(&'a self, _arg_token: Option<&'a str>) -> binder::BoxFuture<'a, binder::Result<Option<String>>>;
+  fn ReverseUtf8CppString<'a>(&'a self, _arg_input: &'a [String], _arg_repeated: &'a mut Vec<String>) -> binder::BoxFuture<'a, binder::Result<Vec<String>>>;
+  fn ReverseNullableUtf8CppString<'a>(&'a self, _arg_input: Option<&'a [Option<String>]>, _arg_repeated: &'a mut Option<Vec<Option<String>>>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<String>>>>>;
+  fn ReverseUtf8CppStringList<'a>(&'a self, _arg_input: Option<&'a [Option<String>]>, _arg_repeated: &'a mut Option<Vec<Option<String>>>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<String>>>>>;
+  fn GetCallback<'a>(&'a self, _arg_return_null: bool) -> binder::BoxFuture<'a, binder::Result<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>;
+  fn FillOutStructuredParcelable<'a>(&'a self, _arg_parcel: &'a mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable) -> binder::BoxFuture<'a, binder::Result<()>>;
+  fn RepeatExtendableParcelable<'a>(&'a self, _arg_ep: &'a crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable, _arg_ep2: &'a mut crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable) -> binder::BoxFuture<'a, binder::Result<()>>;
+  fn ReverseList<'a>(&'a self, _arg_list: &'a crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList) -> binder::BoxFuture<'a, binder::Result<crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList>>;
+  fn ReverseIBinderArray<'a>(&'a self, _arg_input: &'a [binder::SpIBinder], _arg_repeated: &'a mut Vec<Option<binder::SpIBinder>>) -> binder::BoxFuture<'a, binder::Result<Vec<binder::SpIBinder>>>;
+  fn ReverseNullableIBinderArray<'a>(&'a self, _arg_input: Option<&'a [Option<binder::SpIBinder>]>, _arg_repeated: &'a mut Option<Vec<Option<binder::SpIBinder>>>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<binder::SpIBinder>>>>>;
+  fn GetOldNameInterface<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName>>>;
+  fn GetNewNameInterface<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName>>>;
+  fn GetCppJavaTests<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<Option<binder::SpIBinder>>>;
+  fn getBackendType<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<crate::mangled::_7_android_4_aidl_5_tests_11_BackendType>>;
+}
+#[::async_trait::async_trait]
+pub trait ITestServiceAsyncServer: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.ITestService" }
+  async fn UnimplementedMethod(&self, _arg_arg: i32) -> binder::Result<i32>;
+  #[deprecated = "to make sure we have something in system/tools/aidl which does a compile check of deprecated and make sure this is reflected in goldens"]
+  async fn Deprecated(&self) -> binder::Result<()>;
+  async fn TestOneway(&self) -> binder::Result<()>;
+  async fn RepeatBoolean(&self, _arg_token: bool) -> binder::Result<bool>;
+  async fn RepeatByte(&self, _arg_token: i8) -> binder::Result<i8>;
+  async fn RepeatChar(&self, _arg_token: u16) -> binder::Result<u16>;
+  async fn RepeatInt(&self, _arg_token: i32) -> binder::Result<i32>;
+  async fn RepeatLong(&self, _arg_token: i64) -> binder::Result<i64>;
+  async fn RepeatFloat(&self, _arg_token: f32) -> binder::Result<f32>;
+  async fn RepeatDouble(&self, _arg_token: f64) -> binder::Result<f64>;
+  async fn RepeatString(&self, _arg_token: &str) -> binder::Result<String>;
+  async fn RepeatByteEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>;
+  async fn RepeatIntEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>;
+  async fn RepeatLongEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>;
+  async fn ReverseBoolean(&self, _arg_input: &[bool], _arg_repeated: &mut Vec<bool>) -> binder::Result<Vec<bool>>;
+  async fn ReverseByte(&self, _arg_input: &[u8], _arg_repeated: &mut Vec<u8>) -> binder::Result<Vec<u8>>;
+  async fn ReverseChar(&self, _arg_input: &[u16], _arg_repeated: &mut Vec<u16>) -> binder::Result<Vec<u16>>;
+  async fn ReverseInt(&self, _arg_input: &[i32], _arg_repeated: &mut Vec<i32>) -> binder::Result<Vec<i32>>;
+  async fn ReverseLong(&self, _arg_input: &[i64], _arg_repeated: &mut Vec<i64>) -> binder::Result<Vec<i64>>;
+  async fn ReverseFloat(&self, _arg_input: &[f32], _arg_repeated: &mut Vec<f32>) -> binder::Result<Vec<f32>>;
+  async fn ReverseDouble(&self, _arg_input: &[f64], _arg_repeated: &mut Vec<f64>) -> binder::Result<Vec<f64>>;
+  async fn ReverseString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>>;
+  async fn ReverseByteEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>;
+  async fn ReverseIntEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>;
+  async fn ReverseLongEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>;
+  async fn GetOtherTestService(&self, _arg_name: &str) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>;
+  async fn VerifyName(&self, _arg_service: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &str) -> binder::Result<bool>;
+  async fn GetInterfaceArray(&self, _arg_names: &[String]) -> binder::Result<Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>;
+  async fn VerifyNamesWithInterfaceArray(&self, _arg_services: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>], _arg_names: &[String]) -> binder::Result<bool>;
+  async fn GetNullableInterfaceArray(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>>;
+  async fn VerifyNamesWithNullableInterfaceArray(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<bool>;
+  async fn GetInterfaceList(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>>;
+  async fn VerifyNamesWithInterfaceList(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<bool>;
+  async fn ReverseStringList(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>>;
+  async fn RepeatParcelFileDescriptor(&self, _arg_read: &binder::ParcelFileDescriptor) -> binder::Result<binder::ParcelFileDescriptor>;
+  async fn ReverseParcelFileDescriptorArray(&self, _arg_input: &[binder::ParcelFileDescriptor], _arg_repeated: &mut Vec<Option<binder::ParcelFileDescriptor>>) -> binder::Result<Vec<binder::ParcelFileDescriptor>>;
+  async fn ThrowServiceException(&self, _arg_code: i32) -> binder::Result<()>;
+  async fn RepeatNullableIntArray(&self, _arg_input: Option<&[i32]>) -> binder::Result<Option<Vec<i32>>>;
+  async fn RepeatNullableByteEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>>;
+  async fn RepeatNullableIntEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>>;
+  async fn RepeatNullableLongEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>>;
+  async fn RepeatNullableString(&self, _arg_input: Option<&str>) -> binder::Result<Option<String>>;
+  async fn RepeatNullableStringList(&self, _arg_input: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<String>>>>;
+  async fn RepeatNullableParcelable(&self, _arg_input: Option<&crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>) -> binder::Result<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>;
+  async fn RepeatNullableParcelableArray(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>>;
+  async fn RepeatNullableParcelableList(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>>;
+  async fn TakesAnIBinder(&self, _arg_input: &binder::SpIBinder) -> binder::Result<()>;
+  async fn TakesANullableIBinder(&self, _arg_input: Option<&binder::SpIBinder>) -> binder::Result<()>;
+  async fn TakesAnIBinderList(&self, _arg_input: &[binder::SpIBinder]) -> binder::Result<()>;
+  async fn TakesANullableIBinderList(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>) -> binder::Result<()>;
+  async fn RepeatUtf8CppString(&self, _arg_token: &str) -> binder::Result<String>;
+  async fn RepeatNullableUtf8CppString(&self, _arg_token: Option<&str>) -> binder::Result<Option<String>>;
+  async fn ReverseUtf8CppString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>>;
+  async fn ReverseNullableUtf8CppString(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<Option<Vec<Option<String>>>>;
+  async fn ReverseUtf8CppStringList(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<Option<Vec<Option<String>>>>;
+  async fn GetCallback(&self, _arg_return_null: bool) -> binder::Result<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>;
+  async fn FillOutStructuredParcelable(&self, _arg_parcel: &mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable) -> binder::Result<()>;
+  async fn RepeatExtendableParcelable(&self, _arg_ep: &crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable, _arg_ep2: &mut crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable) -> binder::Result<()>;
+  async fn ReverseList(&self, _arg_list: &crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList>;
+  async fn ReverseIBinderArray(&self, _arg_input: &[binder::SpIBinder], _arg_repeated: &mut Vec<Option<binder::SpIBinder>>) -> binder::Result<Vec<binder::SpIBinder>>;
+  async fn ReverseNullableIBinderArray(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>, _arg_repeated: &mut Option<Vec<Option<binder::SpIBinder>>>) -> binder::Result<Option<Vec<Option<binder::SpIBinder>>>>;
+  async fn GetOldNameInterface(&self) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName>>;
+  async fn GetNewNameInterface(&self) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName>>;
+  async fn GetCppJavaTests(&self) -> binder::Result<Option<binder::SpIBinder>>;
+  async fn getBackendType(&self) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_11_BackendType>;
+}
+impl BnTestService {
+  /// Create a new async binder service.
+  pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn ITestService>
+  where
+    T: ITestServiceAsyncServer + binder::Interface + Send + Sync + 'static,
+    R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+  {
+    struct Wrapper<T, R> {
+      _inner: T,
+      _rt: R,
+    }
+    impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+      fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+      fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+    }
+    impl<T, R> ITestService for Wrapper<T, R>
+    where
+      T: ITestServiceAsyncServer + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      fn UnimplementedMethod(&self, _arg_arg: i32) -> binder::Result<i32> {
+        self._rt.block_on(self._inner.UnimplementedMethod(_arg_arg))
+      }
+      fn Deprecated(&self) -> binder::Result<()> {
+        self._rt.block_on(self._inner.Deprecated())
+      }
+      fn TestOneway(&self) -> binder::Result<()> {
+        self._rt.block_on(self._inner.TestOneway())
+      }
+      fn RepeatBoolean(&self, _arg_token: bool) -> binder::Result<bool> {
+        self._rt.block_on(self._inner.RepeatBoolean(_arg_token))
+      }
+      fn RepeatByte(&self, _arg_token: i8) -> binder::Result<i8> {
+        self._rt.block_on(self._inner.RepeatByte(_arg_token))
+      }
+      fn RepeatChar(&self, _arg_token: u16) -> binder::Result<u16> {
+        self._rt.block_on(self._inner.RepeatChar(_arg_token))
+      }
+      fn RepeatInt(&self, _arg_token: i32) -> binder::Result<i32> {
+        self._rt.block_on(self._inner.RepeatInt(_arg_token))
+      }
+      fn RepeatLong(&self, _arg_token: i64) -> binder::Result<i64> {
+        self._rt.block_on(self._inner.RepeatLong(_arg_token))
+      }
+      fn RepeatFloat(&self, _arg_token: f32) -> binder::Result<f32> {
+        self._rt.block_on(self._inner.RepeatFloat(_arg_token))
+      }
+      fn RepeatDouble(&self, _arg_token: f64) -> binder::Result<f64> {
+        self._rt.block_on(self._inner.RepeatDouble(_arg_token))
+      }
+      fn RepeatString(&self, _arg_token: &str) -> binder::Result<String> {
+        self._rt.block_on(self._inner.RepeatString(_arg_token))
+      }
+      fn RepeatByteEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum> {
+        self._rt.block_on(self._inner.RepeatByteEnum(_arg_token))
+      }
+      fn RepeatIntEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum> {
+        self._rt.block_on(self._inner.RepeatIntEnum(_arg_token))
+      }
+      fn RepeatLongEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum> {
+        self._rt.block_on(self._inner.RepeatLongEnum(_arg_token))
+      }
+      fn ReverseBoolean(&self, _arg_input: &[bool], _arg_repeated: &mut Vec<bool>) -> binder::Result<Vec<bool>> {
+        self._rt.block_on(self._inner.ReverseBoolean(_arg_input, _arg_repeated))
+      }
+      fn ReverseByte(&self, _arg_input: &[u8], _arg_repeated: &mut Vec<u8>) -> binder::Result<Vec<u8>> {
+        self._rt.block_on(self._inner.ReverseByte(_arg_input, _arg_repeated))
+      }
+      fn ReverseChar(&self, _arg_input: &[u16], _arg_repeated: &mut Vec<u16>) -> binder::Result<Vec<u16>> {
+        self._rt.block_on(self._inner.ReverseChar(_arg_input, _arg_repeated))
+      }
+      fn ReverseInt(&self, _arg_input: &[i32], _arg_repeated: &mut Vec<i32>) -> binder::Result<Vec<i32>> {
+        self._rt.block_on(self._inner.ReverseInt(_arg_input, _arg_repeated))
+      }
+      fn ReverseLong(&self, _arg_input: &[i64], _arg_repeated: &mut Vec<i64>) -> binder::Result<Vec<i64>> {
+        self._rt.block_on(self._inner.ReverseLong(_arg_input, _arg_repeated))
+      }
+      fn ReverseFloat(&self, _arg_input: &[f32], _arg_repeated: &mut Vec<f32>) -> binder::Result<Vec<f32>> {
+        self._rt.block_on(self._inner.ReverseFloat(_arg_input, _arg_repeated))
+      }
+      fn ReverseDouble(&self, _arg_input: &[f64], _arg_repeated: &mut Vec<f64>) -> binder::Result<Vec<f64>> {
+        self._rt.block_on(self._inner.ReverseDouble(_arg_input, _arg_repeated))
+      }
+      fn ReverseString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>> {
+        self._rt.block_on(self._inner.ReverseString(_arg_input, _arg_repeated))
+      }
+      fn ReverseByteEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>> {
+        self._rt.block_on(self._inner.ReverseByteEnum(_arg_input, _arg_repeated))
+      }
+      fn ReverseIntEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>> {
+        self._rt.block_on(self._inner.ReverseIntEnum(_arg_input, _arg_repeated))
+      }
+      fn ReverseLongEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>> {
+        self._rt.block_on(self._inner.ReverseLongEnum(_arg_input, _arg_repeated))
+      }
+      fn GetOtherTestService(&self, _arg_name: &str) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>> {
+        self._rt.block_on(self._inner.GetOtherTestService(_arg_name))
+      }
+      fn VerifyName(&self, _arg_service: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &str) -> binder::Result<bool> {
+        self._rt.block_on(self._inner.VerifyName(_arg_service, _arg_name))
+      }
+      fn GetInterfaceArray(&self, _arg_names: &[String]) -> binder::Result<Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> {
+        self._rt.block_on(self._inner.GetInterfaceArray(_arg_names))
+      }
+      fn VerifyNamesWithInterfaceArray(&self, _arg_services: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>], _arg_names: &[String]) -> binder::Result<bool> {
+        self._rt.block_on(self._inner.VerifyNamesWithInterfaceArray(_arg_services, _arg_names))
+      }
+      fn GetNullableInterfaceArray(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>> {
+        self._rt.block_on(self._inner.GetNullableInterfaceArray(_arg_names))
+      }
+      fn VerifyNamesWithNullableInterfaceArray(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<bool> {
+        self._rt.block_on(self._inner.VerifyNamesWithNullableInterfaceArray(_arg_services, _arg_names))
+      }
+      fn GetInterfaceList(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>> {
+        self._rt.block_on(self._inner.GetInterfaceList(_arg_names))
+      }
+      fn VerifyNamesWithInterfaceList(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<bool> {
+        self._rt.block_on(self._inner.VerifyNamesWithInterfaceList(_arg_services, _arg_names))
+      }
+      fn ReverseStringList(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>> {
+        self._rt.block_on(self._inner.ReverseStringList(_arg_input, _arg_repeated))
+      }
+      fn RepeatParcelFileDescriptor(&self, _arg_read: &binder::ParcelFileDescriptor) -> binder::Result<binder::ParcelFileDescriptor> {
+        self._rt.block_on(self._inner.RepeatParcelFileDescriptor(_arg_read))
+      }
+      fn ReverseParcelFileDescriptorArray(&self, _arg_input: &[binder::ParcelFileDescriptor], _arg_repeated: &mut Vec<Option<binder::ParcelFileDescriptor>>) -> binder::Result<Vec<binder::ParcelFileDescriptor>> {
+        self._rt.block_on(self._inner.ReverseParcelFileDescriptorArray(_arg_input, _arg_repeated))
+      }
+      fn ThrowServiceException(&self, _arg_code: i32) -> binder::Result<()> {
+        self._rt.block_on(self._inner.ThrowServiceException(_arg_code))
+      }
+      fn RepeatNullableIntArray(&self, _arg_input: Option<&[i32]>) -> binder::Result<Option<Vec<i32>>> {
+        self._rt.block_on(self._inner.RepeatNullableIntArray(_arg_input))
+      }
+      fn RepeatNullableByteEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>> {
+        self._rt.block_on(self._inner.RepeatNullableByteEnumArray(_arg_input))
+      }
+      fn RepeatNullableIntEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>> {
+        self._rt.block_on(self._inner.RepeatNullableIntEnumArray(_arg_input))
+      }
+      fn RepeatNullableLongEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>> {
+        self._rt.block_on(self._inner.RepeatNullableLongEnumArray(_arg_input))
+      }
+      fn RepeatNullableString(&self, _arg_input: Option<&str>) -> binder::Result<Option<String>> {
+        self._rt.block_on(self._inner.RepeatNullableString(_arg_input))
+      }
+      fn RepeatNullableStringList(&self, _arg_input: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<String>>>> {
+        self._rt.block_on(self._inner.RepeatNullableStringList(_arg_input))
+      }
+      fn RepeatNullableParcelable(&self, _arg_input: Option<&crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>) -> binder::Result<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>> {
+        self._rt.block_on(self._inner.RepeatNullableParcelable(_arg_input))
+      }
+      fn RepeatNullableParcelableArray(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>> {
+        self._rt.block_on(self._inner.RepeatNullableParcelableArray(_arg_input))
+      }
+      fn RepeatNullableParcelableList(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>> {
+        self._rt.block_on(self._inner.RepeatNullableParcelableList(_arg_input))
+      }
+      fn TakesAnIBinder(&self, _arg_input: &binder::SpIBinder) -> binder::Result<()> {
+        self._rt.block_on(self._inner.TakesAnIBinder(_arg_input))
+      }
+      fn TakesANullableIBinder(&self, _arg_input: Option<&binder::SpIBinder>) -> binder::Result<()> {
+        self._rt.block_on(self._inner.TakesANullableIBinder(_arg_input))
+      }
+      fn TakesAnIBinderList(&self, _arg_input: &[binder::SpIBinder]) -> binder::Result<()> {
+        self._rt.block_on(self._inner.TakesAnIBinderList(_arg_input))
+      }
+      fn TakesANullableIBinderList(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>) -> binder::Result<()> {
+        self._rt.block_on(self._inner.TakesANullableIBinderList(_arg_input))
+      }
+      fn RepeatUtf8CppString(&self, _arg_token: &str) -> binder::Result<String> {
+        self._rt.block_on(self._inner.RepeatUtf8CppString(_arg_token))
+      }
+      fn RepeatNullableUtf8CppString(&self, _arg_token: Option<&str>) -> binder::Result<Option<String>> {
+        self._rt.block_on(self._inner.RepeatNullableUtf8CppString(_arg_token))
+      }
+      fn ReverseUtf8CppString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>> {
+        self._rt.block_on(self._inner.ReverseUtf8CppString(_arg_input, _arg_repeated))
+      }
+      fn ReverseNullableUtf8CppString(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<Option<Vec<Option<String>>>> {
+        self._rt.block_on(self._inner.ReverseNullableUtf8CppString(_arg_input, _arg_repeated))
+      }
+      fn ReverseUtf8CppStringList(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<Option<Vec<Option<String>>>> {
+        self._rt.block_on(self._inner.ReverseUtf8CppStringList(_arg_input, _arg_repeated))
+      }
+      fn GetCallback(&self, _arg_return_null: bool) -> binder::Result<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> {
+        self._rt.block_on(self._inner.GetCallback(_arg_return_null))
+      }
+      fn FillOutStructuredParcelable(&self, _arg_parcel: &mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable) -> binder::Result<()> {
+        self._rt.block_on(self._inner.FillOutStructuredParcelable(_arg_parcel))
+      }
+      fn RepeatExtendableParcelable(&self, _arg_ep: &crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable, _arg_ep2: &mut crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable) -> binder::Result<()> {
+        self._rt.block_on(self._inner.RepeatExtendableParcelable(_arg_ep, _arg_ep2))
+      }
+      fn ReverseList(&self, _arg_list: &crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList> {
+        self._rt.block_on(self._inner.ReverseList(_arg_list))
+      }
+      fn ReverseIBinderArray(&self, _arg_input: &[binder::SpIBinder], _arg_repeated: &mut Vec<Option<binder::SpIBinder>>) -> binder::Result<Vec<binder::SpIBinder>> {
+        self._rt.block_on(self._inner.ReverseIBinderArray(_arg_input, _arg_repeated))
+      }
+      fn ReverseNullableIBinderArray(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>, _arg_repeated: &mut Option<Vec<Option<binder::SpIBinder>>>) -> binder::Result<Option<Vec<Option<binder::SpIBinder>>>> {
+        self._rt.block_on(self._inner.ReverseNullableIBinderArray(_arg_input, _arg_repeated))
+      }
+      fn GetOldNameInterface(&self) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName>> {
+        self._rt.block_on(self._inner.GetOldNameInterface())
+      }
+      fn GetNewNameInterface(&self) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName>> {
+        self._rt.block_on(self._inner.GetNewNameInterface())
+      }
+      fn GetCppJavaTests(&self) -> binder::Result<Option<binder::SpIBinder>> {
+        self._rt.block_on(self._inner.GetCppJavaTests())
+      }
+      fn getBackendType(&self) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_11_BackendType> {
+        self._rt.block_on(self._inner.getBackendType())
+      }
+    }
+    let wrapped = Wrapper { _inner: inner, _rt: rt };
+    Self::new_binder(wrapped, features)
+  }
+}
 pub trait ITestServiceDefault: Send + Sync {
-  fn UnimplementedMethod(&self, _arg_arg: i32) -> binder::public_api::Result<i32> {
+  fn UnimplementedMethod(&self, _arg_arg: i32) -> binder::Result<i32> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn Deprecated(&self) -> binder::public_api::Result<()> {
+  fn Deprecated(&self) -> binder::Result<()> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn TestOneway(&self) -> binder::public_api::Result<()> {
+  fn TestOneway(&self) -> binder::Result<()> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatBoolean(&self, _arg_token: bool) -> binder::public_api::Result<bool> {
+  fn RepeatBoolean(&self, _arg_token: bool) -> binder::Result<bool> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatByte(&self, _arg_token: i8) -> binder::public_api::Result<i8> {
+  fn RepeatByte(&self, _arg_token: i8) -> binder::Result<i8> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatChar(&self, _arg_token: u16) -> binder::public_api::Result<u16> {
+  fn RepeatChar(&self, _arg_token: u16) -> binder::Result<u16> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatInt(&self, _arg_token: i32) -> binder::public_api::Result<i32> {
+  fn RepeatInt(&self, _arg_token: i32) -> binder::Result<i32> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatLong(&self, _arg_token: i64) -> binder::public_api::Result<i64> {
+  fn RepeatLong(&self, _arg_token: i64) -> binder::Result<i64> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatFloat(&self, _arg_token: f32) -> binder::public_api::Result<f32> {
+  fn RepeatFloat(&self, _arg_token: f32) -> binder::Result<f32> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatDouble(&self, _arg_token: f64) -> binder::public_api::Result<f64> {
+  fn RepeatDouble(&self, _arg_token: f64) -> binder::Result<f64> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatString(&self, _arg_token: &str) -> binder::public_api::Result<String> {
+  fn RepeatString(&self, _arg_token: &str) -> binder::Result<String> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatByteEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum> {
+  fn RepeatByteEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatIntEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum> {
+  fn RepeatIntEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatLongEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum> {
+  fn RepeatLongEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseBoolean(&self, _arg_input: &[bool], _arg_repeated: &mut Vec<bool>) -> binder::public_api::Result<Vec<bool>> {
+  fn ReverseBoolean(&self, _arg_input: &[bool], _arg_repeated: &mut Vec<bool>) -> binder::Result<Vec<bool>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseByte(&self, _arg_input: &[u8], _arg_repeated: &mut Vec<u8>) -> binder::public_api::Result<Vec<u8>> {
+  fn ReverseByte(&self, _arg_input: &[u8], _arg_repeated: &mut Vec<u8>) -> binder::Result<Vec<u8>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseChar(&self, _arg_input: &[u16], _arg_repeated: &mut Vec<u16>) -> binder::public_api::Result<Vec<u16>> {
+  fn ReverseChar(&self, _arg_input: &[u16], _arg_repeated: &mut Vec<u16>) -> binder::Result<Vec<u16>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseInt(&self, _arg_input: &[i32], _arg_repeated: &mut Vec<i32>) -> binder::public_api::Result<Vec<i32>> {
+  fn ReverseInt(&self, _arg_input: &[i32], _arg_repeated: &mut Vec<i32>) -> binder::Result<Vec<i32>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseLong(&self, _arg_input: &[i64], _arg_repeated: &mut Vec<i64>) -> binder::public_api::Result<Vec<i64>> {
+  fn ReverseLong(&self, _arg_input: &[i64], _arg_repeated: &mut Vec<i64>) -> binder::Result<Vec<i64>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseFloat(&self, _arg_input: &[f32], _arg_repeated: &mut Vec<f32>) -> binder::public_api::Result<Vec<f32>> {
+  fn ReverseFloat(&self, _arg_input: &[f32], _arg_repeated: &mut Vec<f32>) -> binder::Result<Vec<f32>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseDouble(&self, _arg_input: &[f64], _arg_repeated: &mut Vec<f64>) -> binder::public_api::Result<Vec<f64>> {
+  fn ReverseDouble(&self, _arg_input: &[f64], _arg_repeated: &mut Vec<f64>) -> binder::Result<Vec<f64>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::public_api::Result<Vec<String>> {
+  fn ReverseString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseByteEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>) -> binder::public_api::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>> {
+  fn ReverseByteEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseIntEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>) -> binder::public_api::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>> {
+  fn ReverseIntEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseLongEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>) -> binder::public_api::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>> {
+  fn ReverseLongEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn GetOtherTestService(&self, _arg_name: &str) -> binder::public_api::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>> {
+  fn GetOtherTestService(&self, _arg_name: &str) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn VerifyName(&self, _arg_service: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &str) -> binder::public_api::Result<bool> {
+  fn VerifyName(&self, _arg_service: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &str) -> binder::Result<bool> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseStringList(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::public_api::Result<Vec<String>> {
+  fn GetInterfaceArray(&self, _arg_names: &[String]) -> binder::Result<Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatParcelFileDescriptor(&self, _arg_read: &binder::parcel::ParcelFileDescriptor) -> binder::public_api::Result<binder::parcel::ParcelFileDescriptor> {
+  fn VerifyNamesWithInterfaceArray(&self, _arg_services: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>], _arg_names: &[String]) -> binder::Result<bool> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseParcelFileDescriptorArray(&self, _arg_input: &[binder::parcel::ParcelFileDescriptor], _arg_repeated: &mut Vec<Option<binder::parcel::ParcelFileDescriptor>>) -> binder::public_api::Result<Vec<binder::parcel::ParcelFileDescriptor>> {
+  fn GetNullableInterfaceArray(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ThrowServiceException(&self, _arg_code: i32) -> binder::public_api::Result<()> {
+  fn VerifyNamesWithNullableInterfaceArray(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<bool> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatNullableIntArray(&self, _arg_input: Option<&[i32]>) -> binder::public_api::Result<Option<Vec<i32>>> {
+  fn GetInterfaceList(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatNullableByteEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>) -> binder::public_api::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>> {
+  fn VerifyNamesWithInterfaceList(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<bool> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatNullableIntEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>) -> binder::public_api::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>> {
+  fn ReverseStringList(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatNullableLongEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>) -> binder::public_api::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>> {
+  fn RepeatParcelFileDescriptor(&self, _arg_read: &binder::ParcelFileDescriptor) -> binder::Result<binder::ParcelFileDescriptor> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatNullableString(&self, _arg_input: Option<&str>) -> binder::public_api::Result<Option<String>> {
+  fn ReverseParcelFileDescriptorArray(&self, _arg_input: &[binder::ParcelFileDescriptor], _arg_repeated: &mut Vec<Option<binder::ParcelFileDescriptor>>) -> binder::Result<Vec<binder::ParcelFileDescriptor>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatNullableStringList(&self, _arg_input: Option<&[Option<String>]>) -> binder::public_api::Result<Option<Vec<Option<String>>>> {
+  fn ThrowServiceException(&self, _arg_code: i32) -> binder::Result<()> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatNullableParcelable(&self, _arg_input: Option<&crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable>) -> binder::public_api::Result<Option<crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable>> {
+  fn RepeatNullableIntArray(&self, _arg_input: Option<&[i32]>) -> binder::Result<Option<Vec<i32>>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn TakesAnIBinder(&self, _arg_input: &binder::SpIBinder) -> binder::public_api::Result<()> {
+  fn RepeatNullableByteEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn TakesANullableIBinder(&self, _arg_input: Option<&binder::SpIBinder>) -> binder::public_api::Result<()> {
+  fn RepeatNullableIntEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatUtf8CppString(&self, _arg_token: &str) -> binder::public_api::Result<String> {
+  fn RepeatNullableLongEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn RepeatNullableUtf8CppString(&self, _arg_token: Option<&str>) -> binder::public_api::Result<Option<String>> {
+  fn RepeatNullableString(&self, _arg_input: Option<&str>) -> binder::Result<Option<String>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseUtf8CppString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::public_api::Result<Vec<String>> {
+  fn RepeatNullableStringList(&self, _arg_input: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<String>>>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseNullableUtf8CppString(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::public_api::Result<Option<Vec<Option<String>>>> {
+  fn RepeatNullableParcelable(&self, _arg_input: Option<&crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>) -> binder::Result<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn ReverseUtf8CppStringList(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::public_api::Result<Option<Vec<Option<String>>>> {
+  fn RepeatNullableParcelableArray(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn GetCallback(&self, _arg_return_null: bool) -> binder::public_api::Result<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> {
+  fn RepeatNullableParcelableList(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn FillOutStructuredParcelable(&self, _arg_parcel: &mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable) -> binder::public_api::Result<()> {
+  fn TakesAnIBinder(&self, _arg_input: &binder::SpIBinder) -> binder::Result<()> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn GetOldNameInterface(&self) -> binder::public_api::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName>> {
+  fn TakesANullableIBinder(&self, _arg_input: Option<&binder::SpIBinder>) -> binder::Result<()> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn GetNewNameInterface(&self) -> binder::public_api::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName>> {
+  fn TakesAnIBinderList(&self, _arg_input: &[binder::SpIBinder]) -> binder::Result<()> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn GetCppJavaTests(&self) -> binder::public_api::Result<Option<binder::SpIBinder>> {
+  fn TakesANullableIBinderList(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>) -> binder::Result<()> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
-  fn getBackendType(&self) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_11_BackendType> {
+  fn RepeatUtf8CppString(&self, _arg_token: &str) -> binder::Result<String> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn RepeatNullableUtf8CppString(&self, _arg_token: Option<&str>) -> binder::Result<Option<String>> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn ReverseUtf8CppString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn ReverseNullableUtf8CppString(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<Option<Vec<Option<String>>>> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn ReverseUtf8CppStringList(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<Option<Vec<Option<String>>>> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn GetCallback(&self, _arg_return_null: bool) -> binder::Result<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn FillOutStructuredParcelable(&self, _arg_parcel: &mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable) -> binder::Result<()> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn RepeatExtendableParcelable(&self, _arg_ep: &crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable, _arg_ep2: &mut crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable) -> binder::Result<()> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn ReverseList(&self, _arg_list: &crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn ReverseIBinderArray(&self, _arg_input: &[binder::SpIBinder], _arg_repeated: &mut Vec<Option<binder::SpIBinder>>) -> binder::Result<Vec<binder::SpIBinder>> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn ReverseNullableIBinderArray(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>, _arg_repeated: &mut Option<Vec<Option<binder::SpIBinder>>>) -> binder::Result<Option<Vec<Option<binder::SpIBinder>>>> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn GetOldNameInterface(&self) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName>> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn GetNewNameInterface(&self) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName>> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn GetCppJavaTests(&self) -> binder::Result<Option<binder::SpIBinder>> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn getBackendType(&self) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_11_BackendType> {
     Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
   }
 }
 pub mod transactions {
-  pub const UnimplementedMethod: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 0;
-  pub const Deprecated: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 1;
-  pub const TestOneway: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 2;
-  pub const RepeatBoolean: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 3;
-  pub const RepeatByte: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 4;
-  pub const RepeatChar: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 5;
-  pub const RepeatInt: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 6;
-  pub const RepeatLong: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 7;
-  pub const RepeatFloat: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 8;
-  pub const RepeatDouble: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 9;
-  pub const RepeatString: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 10;
-  pub const RepeatByteEnum: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 11;
-  pub const RepeatIntEnum: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 12;
-  pub const RepeatLongEnum: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 13;
-  pub const ReverseBoolean: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 14;
-  pub const ReverseByte: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 15;
-  pub const ReverseChar: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 16;
-  pub const ReverseInt: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 17;
-  pub const ReverseLong: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 18;
-  pub const ReverseFloat: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 19;
-  pub const ReverseDouble: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 20;
-  pub const ReverseString: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 21;
-  pub const ReverseByteEnum: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 22;
-  pub const ReverseIntEnum: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 23;
-  pub const ReverseLongEnum: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 24;
-  pub const GetOtherTestService: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 25;
-  pub const VerifyName: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 26;
-  pub const ReverseStringList: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 27;
-  pub const RepeatParcelFileDescriptor: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 28;
-  pub const ReverseParcelFileDescriptorArray: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 29;
-  pub const ThrowServiceException: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 30;
-  pub const RepeatNullableIntArray: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 31;
-  pub const RepeatNullableByteEnumArray: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 32;
-  pub const RepeatNullableIntEnumArray: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 33;
-  pub const RepeatNullableLongEnumArray: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 34;
-  pub const RepeatNullableString: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 35;
-  pub const RepeatNullableStringList: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 36;
-  pub const RepeatNullableParcelable: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 37;
-  pub const TakesAnIBinder: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 38;
-  pub const TakesANullableIBinder: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 39;
-  pub const RepeatUtf8CppString: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 40;
-  pub const RepeatNullableUtf8CppString: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 41;
-  pub const ReverseUtf8CppString: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 42;
-  pub const ReverseNullableUtf8CppString: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 43;
-  pub const ReverseUtf8CppStringList: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 44;
-  pub const GetCallback: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 45;
-  pub const FillOutStructuredParcelable: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 46;
-  pub const GetOldNameInterface: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 47;
-  pub const GetNewNameInterface: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 48;
-  pub const GetCppJavaTests: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 49;
-  pub const getBackendType: binder::TransactionCode = binder::FIRST_CALL_TRANSACTION + 50;
+  pub const UnimplementedMethod: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 0;
+  pub const Deprecated: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 1;
+  pub const TestOneway: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 2;
+  pub const RepeatBoolean: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 3;
+  pub const RepeatByte: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 4;
+  pub const RepeatChar: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 5;
+  pub const RepeatInt: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 6;
+  pub const RepeatLong: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 7;
+  pub const RepeatFloat: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 8;
+  pub const RepeatDouble: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 9;
+  pub const RepeatString: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 10;
+  pub const RepeatByteEnum: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 11;
+  pub const RepeatIntEnum: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 12;
+  pub const RepeatLongEnum: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 13;
+  pub const ReverseBoolean: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 14;
+  pub const ReverseByte: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 15;
+  pub const ReverseChar: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 16;
+  pub const ReverseInt: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 17;
+  pub const ReverseLong: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 18;
+  pub const ReverseFloat: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 19;
+  pub const ReverseDouble: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 20;
+  pub const ReverseString: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 21;
+  pub const ReverseByteEnum: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 22;
+  pub const ReverseIntEnum: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 23;
+  pub const ReverseLongEnum: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 24;
+  pub const GetOtherTestService: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 25;
+  pub const VerifyName: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 26;
+  pub const GetInterfaceArray: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 27;
+  pub const VerifyNamesWithInterfaceArray: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 28;
+  pub const GetNullableInterfaceArray: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 29;
+  pub const VerifyNamesWithNullableInterfaceArray: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 30;
+  pub const GetInterfaceList: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 31;
+  pub const VerifyNamesWithInterfaceList: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 32;
+  pub const ReverseStringList: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 33;
+  pub const RepeatParcelFileDescriptor: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 34;
+  pub const ReverseParcelFileDescriptorArray: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 35;
+  pub const ThrowServiceException: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 36;
+  pub const RepeatNullableIntArray: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 37;
+  pub const RepeatNullableByteEnumArray: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 38;
+  pub const RepeatNullableIntEnumArray: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 39;
+  pub const RepeatNullableLongEnumArray: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 40;
+  pub const RepeatNullableString: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 41;
+  pub const RepeatNullableStringList: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 42;
+  pub const RepeatNullableParcelable: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 43;
+  pub const RepeatNullableParcelableArray: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 44;
+  pub const RepeatNullableParcelableList: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 45;
+  pub const TakesAnIBinder: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 46;
+  pub const TakesANullableIBinder: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 47;
+  pub const TakesAnIBinderList: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 48;
+  pub const TakesANullableIBinderList: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 49;
+  pub const RepeatUtf8CppString: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 50;
+  pub const RepeatNullableUtf8CppString: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 51;
+  pub const ReverseUtf8CppString: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 52;
+  pub const ReverseNullableUtf8CppString: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 53;
+  pub const ReverseUtf8CppStringList: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 54;
+  pub const GetCallback: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 55;
+  pub const FillOutStructuredParcelable: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 56;
+  pub const RepeatExtendableParcelable: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 57;
+  pub const ReverseList: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 58;
+  pub const ReverseIBinderArray: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 59;
+  pub const ReverseNullableIBinderArray: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 60;
+  pub const GetOldNameInterface: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 61;
+  pub const GetNewNameInterface: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 62;
+  pub const GetCppJavaTests: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 63;
+  pub const getBackendType: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 64;
 }
 pub type ITestServiceDefaultRef = Option<std::sync::Arc<dyn ITestServiceDefault>>;
 use lazy_static::lazy_static;
@@ -357,14 +789,14 @@
 pub const A55: i32 = 1;
 pub const A56: i32 = 1;
 pub const A57: i32 = 1;
-pub(crate) mod mangled { pub use super::ITestService as _7_android_4_aidl_5_tests_12_ITestService; }
-impl ITestService for BpTestService {
-  fn UnimplementedMethod(&self, _arg_arg: i32) -> binder::public_api::Result<i32> {
-    let _aidl_reply = self.binder.transact(transactions::UnimplementedMethod, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_arg)?;
-      Ok(())
-    });
+impl BpTestService {
+  fn build_parcel_UnimplementedMethod(&self, _arg_arg: i32) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_arg)?;
+    Ok(aidl_data)
+  }
+  fn read_response_UnimplementedMethod(&self, _arg_arg: i32, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<i32> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.UnimplementedMethod(_arg_arg);
@@ -376,11 +808,12 @@
     let _aidl_return: i32 = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn Deprecated(&self) -> binder::public_api::Result<()> {
-    let _aidl_reply = self.binder.transact(transactions::Deprecated, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      Ok(())
-    });
+  fn build_parcel_Deprecated(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    Ok(aidl_data)
+  }
+  fn read_response_Deprecated(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.Deprecated();
@@ -391,11 +824,12 @@
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     Ok(())
   }
-  fn TestOneway(&self) -> binder::public_api::Result<()> {
-    let _aidl_reply = self.binder.transact(transactions::TestOneway, binder::FLAG_ONEWAY | binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      Ok(())
-    });
+  fn build_parcel_TestOneway(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    Ok(aidl_data)
+  }
+  fn read_response_TestOneway(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.TestOneway();
@@ -404,12 +838,13 @@
     let _aidl_reply = _aidl_reply?;
     Ok(())
   }
-  fn RepeatBoolean(&self, _arg_token: bool) -> binder::public_api::Result<bool> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatBoolean, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_token)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatBoolean(&self, _arg_token: bool) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_token)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatBoolean(&self, _arg_token: bool, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<bool> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatBoolean(_arg_token);
@@ -421,12 +856,13 @@
     let _aidl_return: bool = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatByte(&self, _arg_token: i8) -> binder::public_api::Result<i8> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatByte, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_token)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatByte(&self, _arg_token: i8) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_token)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatByte(&self, _arg_token: i8, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<i8> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatByte(_arg_token);
@@ -438,12 +874,13 @@
     let _aidl_return: i8 = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatChar(&self, _arg_token: u16) -> binder::public_api::Result<u16> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatChar, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_token)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatChar(&self, _arg_token: u16) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_token)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatChar(&self, _arg_token: u16, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<u16> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatChar(_arg_token);
@@ -455,12 +892,13 @@
     let _aidl_return: u16 = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatInt(&self, _arg_token: i32) -> binder::public_api::Result<i32> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatInt, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_token)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatInt(&self, _arg_token: i32) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_token)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatInt(&self, _arg_token: i32, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<i32> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatInt(_arg_token);
@@ -472,12 +910,13 @@
     let _aidl_return: i32 = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatLong(&self, _arg_token: i64) -> binder::public_api::Result<i64> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatLong, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_token)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatLong(&self, _arg_token: i64) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_token)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatLong(&self, _arg_token: i64, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<i64> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatLong(_arg_token);
@@ -489,12 +928,13 @@
     let _aidl_return: i64 = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatFloat(&self, _arg_token: f32) -> binder::public_api::Result<f32> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatFloat, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_token)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatFloat(&self, _arg_token: f32) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_token)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatFloat(&self, _arg_token: f32, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<f32> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatFloat(_arg_token);
@@ -506,12 +946,13 @@
     let _aidl_return: f32 = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatDouble(&self, _arg_token: f64) -> binder::public_api::Result<f64> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatDouble, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_token)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatDouble(&self, _arg_token: f64) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_token)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatDouble(&self, _arg_token: f64, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<f64> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatDouble(_arg_token);
@@ -523,12 +964,13 @@
     let _aidl_return: f64 = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatString(&self, _arg_token: &str) -> binder::public_api::Result<String> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatString, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_token)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatString(&self, _arg_token: &str) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_token)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatString(&self, _arg_token: &str, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<String> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatString(_arg_token);
@@ -540,12 +982,13 @@
     let _aidl_return: String = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatByteEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatByteEnum, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_token)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatByteEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_token)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatByteEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatByteEnum(_arg_token);
@@ -557,12 +1000,13 @@
     let _aidl_return: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatIntEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatIntEnum, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_token)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatIntEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_token)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatIntEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatIntEnum(_arg_token);
@@ -574,12 +1018,13 @@
     let _aidl_return: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatLongEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatLongEnum, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_token)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatLongEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_token)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatLongEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatLongEnum(_arg_token);
@@ -591,13 +1036,14 @@
     let _aidl_return: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn ReverseBoolean(&self, _arg_input: &[bool], _arg_repeated: &mut Vec<bool>) -> binder::public_api::Result<Vec<bool>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseBoolean, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      _aidl_data.write_slice_size(Some(_arg_repeated))?;
-      Ok(())
-    });
+  fn build_parcel_ReverseBoolean(&self, _arg_input: &[bool], _arg_repeated: &mut Vec<bool>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseBoolean(&self, _arg_input: &[bool], _arg_repeated: &mut Vec<bool>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<bool>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseBoolean(_arg_input, _arg_repeated);
@@ -607,16 +1053,17 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Vec<bool> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn ReverseByte(&self, _arg_input: &[u8], _arg_repeated: &mut Vec<u8>) -> binder::public_api::Result<Vec<u8>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseByte, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      _aidl_data.write_slice_size(Some(_arg_repeated))?;
-      Ok(())
-    });
+  fn build_parcel_ReverseByte(&self, _arg_input: &[u8], _arg_repeated: &mut Vec<u8>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseByte(&self, _arg_input: &[u8], _arg_repeated: &mut Vec<u8>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<u8>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseByte(_arg_input, _arg_repeated);
@@ -626,16 +1073,17 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Vec<u8> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn ReverseChar(&self, _arg_input: &[u16], _arg_repeated: &mut Vec<u16>) -> binder::public_api::Result<Vec<u16>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseChar, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      _aidl_data.write_slice_size(Some(_arg_repeated))?;
-      Ok(())
-    });
+  fn build_parcel_ReverseChar(&self, _arg_input: &[u16], _arg_repeated: &mut Vec<u16>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseChar(&self, _arg_input: &[u16], _arg_repeated: &mut Vec<u16>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<u16>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseChar(_arg_input, _arg_repeated);
@@ -645,16 +1093,17 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Vec<u16> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn ReverseInt(&self, _arg_input: &[i32], _arg_repeated: &mut Vec<i32>) -> binder::public_api::Result<Vec<i32>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseInt, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      _aidl_data.write_slice_size(Some(_arg_repeated))?;
-      Ok(())
-    });
+  fn build_parcel_ReverseInt(&self, _arg_input: &[i32], _arg_repeated: &mut Vec<i32>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseInt(&self, _arg_input: &[i32], _arg_repeated: &mut Vec<i32>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<i32>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseInt(_arg_input, _arg_repeated);
@@ -664,16 +1113,17 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Vec<i32> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn ReverseLong(&self, _arg_input: &[i64], _arg_repeated: &mut Vec<i64>) -> binder::public_api::Result<Vec<i64>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseLong, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      _aidl_data.write_slice_size(Some(_arg_repeated))?;
-      Ok(())
-    });
+  fn build_parcel_ReverseLong(&self, _arg_input: &[i64], _arg_repeated: &mut Vec<i64>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseLong(&self, _arg_input: &[i64], _arg_repeated: &mut Vec<i64>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<i64>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseLong(_arg_input, _arg_repeated);
@@ -683,16 +1133,17 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Vec<i64> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn ReverseFloat(&self, _arg_input: &[f32], _arg_repeated: &mut Vec<f32>) -> binder::public_api::Result<Vec<f32>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseFloat, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      _aidl_data.write_slice_size(Some(_arg_repeated))?;
-      Ok(())
-    });
+  fn build_parcel_ReverseFloat(&self, _arg_input: &[f32], _arg_repeated: &mut Vec<f32>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseFloat(&self, _arg_input: &[f32], _arg_repeated: &mut Vec<f32>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<f32>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseFloat(_arg_input, _arg_repeated);
@@ -702,16 +1153,17 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Vec<f32> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn ReverseDouble(&self, _arg_input: &[f64], _arg_repeated: &mut Vec<f64>) -> binder::public_api::Result<Vec<f64>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseDouble, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      _aidl_data.write_slice_size(Some(_arg_repeated))?;
-      Ok(())
-    });
+  fn build_parcel_ReverseDouble(&self, _arg_input: &[f64], _arg_repeated: &mut Vec<f64>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseDouble(&self, _arg_input: &[f64], _arg_repeated: &mut Vec<f64>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<f64>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseDouble(_arg_input, _arg_repeated);
@@ -721,16 +1173,17 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Vec<f64> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn ReverseString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::public_api::Result<Vec<String>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseString, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      _aidl_data.write_slice_size(Some(_arg_repeated))?;
-      Ok(())
-    });
+  fn build_parcel_ReverseString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<String>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseString(_arg_input, _arg_repeated);
@@ -740,16 +1193,17 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Vec<String> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn ReverseByteEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>) -> binder::public_api::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseByteEnum, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      _aidl_data.write_slice_size(Some(_arg_repeated))?;
-      Ok(())
-    });
+  fn build_parcel_ReverseByteEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseByteEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseByteEnum(_arg_input, _arg_repeated);
@@ -759,16 +1213,17 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn ReverseIntEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>) -> binder::public_api::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseIntEnum, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      _aidl_data.write_slice_size(Some(_arg_repeated))?;
-      Ok(())
-    });
+  fn build_parcel_ReverseIntEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseIntEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseIntEnum(_arg_input, _arg_repeated);
@@ -778,16 +1233,17 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn ReverseLongEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>) -> binder::public_api::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseLongEnum, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      _aidl_data.write_slice_size(Some(_arg_repeated))?;
-      Ok(())
-    });
+  fn build_parcel_ReverseLongEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseLongEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseLongEnum(_arg_input, _arg_repeated);
@@ -797,15 +1253,16 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn GetOtherTestService(&self, _arg_name: &str) -> binder::public_api::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>> {
-    let _aidl_reply = self.binder.transact(transactions::GetOtherTestService, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_name)?;
-      Ok(())
-    });
+  fn build_parcel_GetOtherTestService(&self, _arg_name: &str) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_name)?;
+    Ok(aidl_data)
+  }
+  fn read_response_GetOtherTestService(&self, _arg_name: &str, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.GetOtherTestService(_arg_name);
@@ -817,13 +1274,14 @@
     let _aidl_return: binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback> = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn VerifyName(&self, _arg_service: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &str) -> binder::public_api::Result<bool> {
-    let _aidl_reply = self.binder.transact(transactions::VerifyName, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_service)?;
-      _aidl_data.write(_arg_name)?;
-      Ok(())
-    });
+  fn build_parcel_VerifyName(&self, _arg_service: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &str) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_service)?;
+    aidl_data.write(_arg_name)?;
+    Ok(aidl_data)
+  }
+  fn read_response_VerifyName(&self, _arg_service: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &str, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<bool> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.VerifyName(_arg_service, _arg_name);
@@ -835,12 +1293,124 @@
     let _aidl_return: bool = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn ReverseStringList(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::public_api::Result<Vec<String>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseStringList, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      Ok(())
-    });
+  fn build_parcel_GetInterfaceArray(&self, _arg_names: &[String]) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_names)?;
+    Ok(aidl_data)
+  }
+  fn read_response_GetInterfaceArray(&self, _arg_names: &[String], _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.GetInterfaceArray(_arg_names);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    let _aidl_return: Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>> = _aidl_reply.read()?;
+    Ok(_aidl_return)
+  }
+  fn build_parcel_VerifyNamesWithInterfaceArray(&self, _arg_services: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>], _arg_names: &[String]) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_services)?;
+    aidl_data.write(_arg_names)?;
+    Ok(aidl_data)
+  }
+  fn read_response_VerifyNamesWithInterfaceArray(&self, _arg_services: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>], _arg_names: &[String], _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<bool> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.VerifyNamesWithInterfaceArray(_arg_services, _arg_names);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    let _aidl_return: bool = _aidl_reply.read()?;
+    Ok(_aidl_return)
+  }
+  fn build_parcel_GetNullableInterfaceArray(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_names)?;
+    Ok(aidl_data)
+  }
+  fn read_response_GetNullableInterfaceArray(&self, _arg_names: Option<&[Option<String>]>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.GetNullableInterfaceArray(_arg_names);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    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_14_INamedCallback>>>> = _aidl_reply.read()?;
+    Ok(_aidl_return)
+  }
+  fn build_parcel_VerifyNamesWithNullableInterfaceArray(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_services)?;
+    aidl_data.write(&_arg_names)?;
+    Ok(aidl_data)
+  }
+  fn read_response_VerifyNamesWithNullableInterfaceArray(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<bool> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.VerifyNamesWithNullableInterfaceArray(_arg_services, _arg_names);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    let _aidl_return: bool = _aidl_reply.read()?;
+    Ok(_aidl_return)
+  }
+  fn build_parcel_GetInterfaceList(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_names)?;
+    Ok(aidl_data)
+  }
+  fn read_response_GetInterfaceList(&self, _arg_names: Option<&[Option<String>]>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.GetInterfaceList(_arg_names);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    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_14_INamedCallback>>>> = _aidl_reply.read()?;
+    Ok(_aidl_return)
+  }
+  fn build_parcel_VerifyNamesWithInterfaceList(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_services)?;
+    aidl_data.write(&_arg_names)?;
+    Ok(aidl_data)
+  }
+  fn read_response_VerifyNamesWithInterfaceList(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<bool> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.VerifyNamesWithInterfaceList(_arg_services, _arg_names);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    let _aidl_return: bool = _aidl_reply.read()?;
+    Ok(_aidl_return)
+  }
+  fn build_parcel_ReverseStringList(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseStringList(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<String>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseStringList(_arg_input, _arg_repeated);
@@ -850,15 +1420,16 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Vec<String> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn RepeatParcelFileDescriptor(&self, _arg_read: &binder::parcel::ParcelFileDescriptor) -> binder::public_api::Result<binder::parcel::ParcelFileDescriptor> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatParcelFileDescriptor, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_read)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatParcelFileDescriptor(&self, _arg_read: &binder::ParcelFileDescriptor) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_read)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatParcelFileDescriptor(&self, _arg_read: &binder::ParcelFileDescriptor, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<binder::ParcelFileDescriptor> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatParcelFileDescriptor(_arg_read);
@@ -867,16 +1438,17 @@
     let _aidl_reply = _aidl_reply?;
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
-    let _aidl_return: binder::parcel::ParcelFileDescriptor = _aidl_reply.read()?;
+    let _aidl_return: binder::ParcelFileDescriptor = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn ReverseParcelFileDescriptorArray(&self, _arg_input: &[binder::parcel::ParcelFileDescriptor], _arg_repeated: &mut Vec<Option<binder::parcel::ParcelFileDescriptor>>) -> binder::public_api::Result<Vec<binder::parcel::ParcelFileDescriptor>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseParcelFileDescriptorArray, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      _aidl_data.write_slice_size(Some(_arg_repeated))?;
-      Ok(())
-    });
+  fn build_parcel_ReverseParcelFileDescriptorArray(&self, _arg_input: &[binder::ParcelFileDescriptor], _arg_repeated: &mut Vec<Option<binder::ParcelFileDescriptor>>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseParcelFileDescriptorArray(&self, _arg_input: &[binder::ParcelFileDescriptor], _arg_repeated: &mut Vec<Option<binder::ParcelFileDescriptor>>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<binder::ParcelFileDescriptor>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseParcelFileDescriptorArray(_arg_input, _arg_repeated);
@@ -885,16 +1457,17 @@
     let _aidl_reply = _aidl_reply?;
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
-    let _aidl_return: Vec<binder::parcel::ParcelFileDescriptor> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    let _aidl_return: Vec<binder::ParcelFileDescriptor> = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn ThrowServiceException(&self, _arg_code: i32) -> binder::public_api::Result<()> {
-    let _aidl_reply = self.binder.transact(transactions::ThrowServiceException, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_code)?;
-      Ok(())
-    });
+  fn build_parcel_ThrowServiceException(&self, _arg_code: i32) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_code)?;
+    Ok(aidl_data)
+  }
+  fn read_response_ThrowServiceException(&self, _arg_code: i32, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ThrowServiceException(_arg_code);
@@ -905,12 +1478,13 @@
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     Ok(())
   }
-  fn RepeatNullableIntArray(&self, _arg_input: Option<&[i32]>) -> binder::public_api::Result<Option<Vec<i32>>> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatNullableIntArray, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_input)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatNullableIntArray(&self, _arg_input: Option<&[i32]>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatNullableIntArray(&self, _arg_input: Option<&[i32]>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<Vec<i32>>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatNullableIntArray(_arg_input);
@@ -922,12 +1496,13 @@
     let _aidl_return: Option<Vec<i32>> = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatNullableByteEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>) -> binder::public_api::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatNullableByteEnumArray, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_input)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatNullableByteEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatNullableByteEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatNullableByteEnumArray(_arg_input);
@@ -939,12 +1514,13 @@
     let _aidl_return: Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>> = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatNullableIntEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>) -> binder::public_api::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatNullableIntEnumArray, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_input)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatNullableIntEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatNullableIntEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatNullableIntEnumArray(_arg_input);
@@ -956,12 +1532,13 @@
     let _aidl_return: Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>> = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatNullableLongEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>) -> binder::public_api::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatNullableLongEnumArray, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_input)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatNullableLongEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatNullableLongEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatNullableLongEnumArray(_arg_input);
@@ -973,12 +1550,13 @@
     let _aidl_return: Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>> = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatNullableString(&self, _arg_input: Option<&str>) -> binder::public_api::Result<Option<String>> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatNullableString, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_input)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatNullableString(&self, _arg_input: Option<&str>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatNullableString(&self, _arg_input: Option<&str>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<String>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatNullableString(_arg_input);
@@ -990,12 +1568,13 @@
     let _aidl_return: Option<String> = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatNullableStringList(&self, _arg_input: Option<&[Option<String>]>) -> binder::public_api::Result<Option<Vec<Option<String>>>> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatNullableStringList, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_input)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatNullableStringList(&self, _arg_input: Option<&[Option<String>]>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatNullableStringList(&self, _arg_input: Option<&[Option<String>]>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<Vec<Option<String>>>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatNullableStringList(_arg_input);
@@ -1007,12 +1586,13 @@
     let _aidl_return: Option<Vec<Option<String>>> = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatNullableParcelable(&self, _arg_input: Option<&crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable>) -> binder::public_api::Result<Option<crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable>> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatNullableParcelable, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_input)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatNullableParcelable(&self, _arg_input: Option<&crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatNullableParcelable(&self, _arg_input: Option<&crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatNullableParcelable(_arg_input);
@@ -1021,15 +1601,52 @@
     let _aidl_reply = _aidl_reply?;
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
-    let _aidl_return: Option<crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable> = _aidl_reply.read()?;
+    let _aidl_return: Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty> = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn TakesAnIBinder(&self, _arg_input: &binder::SpIBinder) -> binder::public_api::Result<()> {
-    let _aidl_reply = self.binder.transact(transactions::TakesAnIBinder, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatNullableParcelableArray(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatNullableParcelableArray(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.RepeatNullableParcelableArray(_arg_input);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    let _aidl_return: Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>> = _aidl_reply.read()?;
+    Ok(_aidl_return)
+  }
+  fn build_parcel_RepeatNullableParcelableList(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatNullableParcelableList(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.RepeatNullableParcelableList(_arg_input);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    let _aidl_return: Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>> = _aidl_reply.read()?;
+    Ok(_aidl_return)
+  }
+  fn build_parcel_TakesAnIBinder(&self, _arg_input: &binder::SpIBinder) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_TakesAnIBinder(&self, _arg_input: &binder::SpIBinder, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.TakesAnIBinder(_arg_input);
@@ -1040,12 +1657,13 @@
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     Ok(())
   }
-  fn TakesANullableIBinder(&self, _arg_input: Option<&binder::SpIBinder>) -> binder::public_api::Result<()> {
-    let _aidl_reply = self.binder.transact(transactions::TakesANullableIBinder, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_input)?;
-      Ok(())
-    });
+  fn build_parcel_TakesANullableIBinder(&self, _arg_input: Option<&binder::SpIBinder>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_TakesANullableIBinder(&self, _arg_input: Option<&binder::SpIBinder>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.TakesANullableIBinder(_arg_input);
@@ -1056,12 +1674,47 @@
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     Ok(())
   }
-  fn RepeatUtf8CppString(&self, _arg_token: &str) -> binder::public_api::Result<String> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatUtf8CppString, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_token)?;
-      Ok(())
-    });
+  fn build_parcel_TakesAnIBinderList(&self, _arg_input: &[binder::SpIBinder]) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_TakesAnIBinderList(&self, _arg_input: &[binder::SpIBinder], _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.TakesAnIBinderList(_arg_input);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    Ok(())
+  }
+  fn build_parcel_TakesANullableIBinderList(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_TakesANullableIBinderList(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.TakesANullableIBinderList(_arg_input);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    Ok(())
+  }
+  fn build_parcel_RepeatUtf8CppString(&self, _arg_token: &str) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_token)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatUtf8CppString(&self, _arg_token: &str, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<String> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatUtf8CppString(_arg_token);
@@ -1073,12 +1726,13 @@
     let _aidl_return: String = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn RepeatNullableUtf8CppString(&self, _arg_token: Option<&str>) -> binder::public_api::Result<Option<String>> {
-    let _aidl_reply = self.binder.transact(transactions::RepeatNullableUtf8CppString, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_token)?;
-      Ok(())
-    });
+  fn build_parcel_RepeatNullableUtf8CppString(&self, _arg_token: Option<&str>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_token)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatNullableUtf8CppString(&self, _arg_token: Option<&str>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<String>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.RepeatNullableUtf8CppString(_arg_token);
@@ -1090,13 +1744,14 @@
     let _aidl_return: Option<String> = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn ReverseUtf8CppString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::public_api::Result<Vec<String>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseUtf8CppString, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_input)?;
-      _aidl_data.write_slice_size(Some(_arg_repeated))?;
-      Ok(())
-    });
+  fn build_parcel_ReverseUtf8CppString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseUtf8CppString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<String>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseUtf8CppString(_arg_input, _arg_repeated);
@@ -1106,16 +1761,17 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Vec<String> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn ReverseNullableUtf8CppString(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::public_api::Result<Option<Vec<Option<String>>>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseNullableUtf8CppString, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_input)?;
-      _aidl_data.write_slice_size(_arg_repeated.as_deref())?;
-      Ok(())
-    });
+  fn build_parcel_ReverseNullableUtf8CppString(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    aidl_data.write_slice_size(_arg_repeated.as_deref())?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseNullableUtf8CppString(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<Vec<Option<String>>>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseNullableUtf8CppString(_arg_input, _arg_repeated);
@@ -1125,15 +1781,16 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Option<Vec<Option<String>>> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn ReverseUtf8CppStringList(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::public_api::Result<Option<Vec<Option<String>>>> {
-    let _aidl_reply = self.binder.transact(transactions::ReverseUtf8CppStringList, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_input)?;
-      Ok(())
-    });
+  fn build_parcel_ReverseUtf8CppStringList(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseUtf8CppStringList(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<Vec<Option<String>>>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.ReverseUtf8CppStringList(_arg_input, _arg_repeated);
@@ -1143,15 +1800,16 @@
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
     let _aidl_return: Option<Vec<Option<String>>> = _aidl_reply.read()?;
-    *_arg_repeated = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
     Ok(_aidl_return)
   }
-  fn GetCallback(&self, _arg_return_null: bool) -> binder::public_api::Result<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> {
-    let _aidl_reply = self.binder.transact(transactions::GetCallback, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(&_arg_return_null)?;
-      Ok(())
-    });
+  fn build_parcel_GetCallback(&self, _arg_return_null: bool) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_return_null)?;
+    Ok(aidl_data)
+  }
+  fn read_response_GetCallback(&self, _arg_return_null: bool, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.GetCallback(_arg_return_null);
@@ -1163,12 +1821,13 @@
     let _aidl_return: Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>> = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn FillOutStructuredParcelable(&self, _arg_parcel: &mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable) -> binder::public_api::Result<()> {
-    let _aidl_reply = self.binder.transact(transactions::FillOutStructuredParcelable, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      _aidl_data.write(_arg_parcel)?;
-      Ok(())
-    });
+  fn build_parcel_FillOutStructuredParcelable(&self, _arg_parcel: &mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_parcel)?;
+    Ok(aidl_data)
+  }
+  fn read_response_FillOutStructuredParcelable(&self, _arg_parcel: &mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.FillOutStructuredParcelable(_arg_parcel);
@@ -1177,14 +1836,91 @@
     let _aidl_reply = _aidl_reply?;
     let _aidl_status: binder::Status = _aidl_reply.read()?;
     if !_aidl_status.is_ok() { return Err(_aidl_status); }
-    *_arg_parcel = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_parcel)?;
     Ok(())
   }
-  fn GetOldNameInterface(&self) -> binder::public_api::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName>> {
-    let _aidl_reply = self.binder.transact(transactions::GetOldNameInterface, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      Ok(())
-    });
+  fn build_parcel_RepeatExtendableParcelable(&self, _arg_ep: &crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable, _arg_ep2: &mut crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_ep)?;
+    Ok(aidl_data)
+  }
+  fn read_response_RepeatExtendableParcelable(&self, _arg_ep: &crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable, _arg_ep2: &mut crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.RepeatExtendableParcelable(_arg_ep, _arg_ep2);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    _aidl_reply.read_onto(_arg_ep2)?;
+    Ok(())
+  }
+  fn build_parcel_ReverseList(&self, _arg_list: &crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_list)?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseList(&self, _arg_list: &crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.ReverseList(_arg_list);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    let _aidl_return: crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList = _aidl_reply.read()?;
+    Ok(_aidl_return)
+  }
+  fn build_parcel_ReverseIBinderArray(&self, _arg_input: &[binder::SpIBinder], _arg_repeated: &mut Vec<Option<binder::SpIBinder>>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(_arg_input)?;
+    aidl_data.write_slice_size(Some(_arg_repeated))?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseIBinderArray(&self, _arg_input: &[binder::SpIBinder], _arg_repeated: &mut Vec<Option<binder::SpIBinder>>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Vec<binder::SpIBinder>> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.ReverseIBinderArray(_arg_input, _arg_repeated);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    let _aidl_return: Vec<binder::SpIBinder> = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
+    Ok(_aidl_return)
+  }
+  fn build_parcel_ReverseNullableIBinderArray(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>, _arg_repeated: &mut Option<Vec<Option<binder::SpIBinder>>>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    aidl_data.write(&_arg_input)?;
+    aidl_data.write_slice_size(_arg_repeated.as_deref())?;
+    Ok(aidl_data)
+  }
+  fn read_response_ReverseNullableIBinderArray(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>, _arg_repeated: &mut Option<Vec<Option<binder::SpIBinder>>>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<Vec<Option<binder::SpIBinder>>>> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
+        return _aidl_default_impl.ReverseNullableIBinderArray(_arg_input, _arg_repeated);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    let _aidl_return: Option<Vec<Option<binder::SpIBinder>>> = _aidl_reply.read()?;
+    _aidl_reply.read_onto(_arg_repeated)?;
+    Ok(_aidl_return)
+  }
+  fn build_parcel_GetOldNameInterface(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    Ok(aidl_data)
+  }
+  fn read_response_GetOldNameInterface(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.GetOldNameInterface();
@@ -1196,11 +1932,12 @@
     let _aidl_return: binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName> = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn GetNewNameInterface(&self) -> binder::public_api::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName>> {
-    let _aidl_reply = self.binder.transact(transactions::GetNewNameInterface, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      Ok(())
-    });
+  fn build_parcel_GetNewNameInterface(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    Ok(aidl_data)
+  }
+  fn read_response_GetNewNameInterface(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.GetNewNameInterface();
@@ -1212,11 +1949,12 @@
     let _aidl_return: binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName> = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn GetCppJavaTests(&self) -> binder::public_api::Result<Option<binder::SpIBinder>> {
-    let _aidl_reply = self.binder.transact(transactions::GetCppJavaTests, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      Ok(())
-    });
+  fn build_parcel_GetCppJavaTests(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    Ok(aidl_data)
+  }
+  fn read_response_GetCppJavaTests(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<binder::SpIBinder>> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.GetCppJavaTests();
@@ -1228,11 +1966,12 @@
     let _aidl_return: Option<binder::SpIBinder> = _aidl_reply.read()?;
     Ok(_aidl_return)
   }
-  fn getBackendType(&self) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_11_BackendType> {
-    let _aidl_reply = self.binder.transact(transactions::getBackendType, binder::FLAG_CLEAR_BUF | binder::FLAG_PRIVATE_LOCAL, |_aidl_data| {
-      _aidl_data.mark_sensitive();
-      Ok(())
-    });
+  fn build_parcel_getBackendType(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.mark_sensitive();
+    Ok(aidl_data)
+  }
+  fn read_response_getBackendType(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_11_BackendType> {
     if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
       if let Some(_aidl_default_impl) = <Self as ITestService>::getDefaultImpl() {
         return _aidl_default_impl.getBackendType();
@@ -1245,60 +1984,1243 @@
     Ok(_aidl_return)
   }
 }
-impl ITestService for binder::Binder<BnTestService> {
-  fn UnimplementedMethod(&self, _arg_arg: i32) -> binder::public_api::Result<i32> { self.0.UnimplementedMethod(_arg_arg) }
-  fn Deprecated(&self) -> binder::public_api::Result<()> { self.0.Deprecated() }
-  fn TestOneway(&self) -> binder::public_api::Result<()> { self.0.TestOneway() }
-  fn RepeatBoolean(&self, _arg_token: bool) -> binder::public_api::Result<bool> { self.0.RepeatBoolean(_arg_token) }
-  fn RepeatByte(&self, _arg_token: i8) -> binder::public_api::Result<i8> { self.0.RepeatByte(_arg_token) }
-  fn RepeatChar(&self, _arg_token: u16) -> binder::public_api::Result<u16> { self.0.RepeatChar(_arg_token) }
-  fn RepeatInt(&self, _arg_token: i32) -> binder::public_api::Result<i32> { self.0.RepeatInt(_arg_token) }
-  fn RepeatLong(&self, _arg_token: i64) -> binder::public_api::Result<i64> { self.0.RepeatLong(_arg_token) }
-  fn RepeatFloat(&self, _arg_token: f32) -> binder::public_api::Result<f32> { self.0.RepeatFloat(_arg_token) }
-  fn RepeatDouble(&self, _arg_token: f64) -> binder::public_api::Result<f64> { self.0.RepeatDouble(_arg_token) }
-  fn RepeatString(&self, _arg_token: &str) -> binder::public_api::Result<String> { self.0.RepeatString(_arg_token) }
-  fn RepeatByteEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum> { self.0.RepeatByteEnum(_arg_token) }
-  fn RepeatIntEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum> { self.0.RepeatIntEnum(_arg_token) }
-  fn RepeatLongEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum> { self.0.RepeatLongEnum(_arg_token) }
-  fn ReverseBoolean(&self, _arg_input: &[bool], _arg_repeated: &mut Vec<bool>) -> binder::public_api::Result<Vec<bool>> { self.0.ReverseBoolean(_arg_input, _arg_repeated) }
-  fn ReverseByte(&self, _arg_input: &[u8], _arg_repeated: &mut Vec<u8>) -> binder::public_api::Result<Vec<u8>> { self.0.ReverseByte(_arg_input, _arg_repeated) }
-  fn ReverseChar(&self, _arg_input: &[u16], _arg_repeated: &mut Vec<u16>) -> binder::public_api::Result<Vec<u16>> { self.0.ReverseChar(_arg_input, _arg_repeated) }
-  fn ReverseInt(&self, _arg_input: &[i32], _arg_repeated: &mut Vec<i32>) -> binder::public_api::Result<Vec<i32>> { self.0.ReverseInt(_arg_input, _arg_repeated) }
-  fn ReverseLong(&self, _arg_input: &[i64], _arg_repeated: &mut Vec<i64>) -> binder::public_api::Result<Vec<i64>> { self.0.ReverseLong(_arg_input, _arg_repeated) }
-  fn ReverseFloat(&self, _arg_input: &[f32], _arg_repeated: &mut Vec<f32>) -> binder::public_api::Result<Vec<f32>> { self.0.ReverseFloat(_arg_input, _arg_repeated) }
-  fn ReverseDouble(&self, _arg_input: &[f64], _arg_repeated: &mut Vec<f64>) -> binder::public_api::Result<Vec<f64>> { self.0.ReverseDouble(_arg_input, _arg_repeated) }
-  fn ReverseString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::public_api::Result<Vec<String>> { self.0.ReverseString(_arg_input, _arg_repeated) }
-  fn ReverseByteEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>) -> binder::public_api::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>> { self.0.ReverseByteEnum(_arg_input, _arg_repeated) }
-  fn ReverseIntEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>) -> binder::public_api::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>> { self.0.ReverseIntEnum(_arg_input, _arg_repeated) }
-  fn ReverseLongEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>) -> binder::public_api::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>> { self.0.ReverseLongEnum(_arg_input, _arg_repeated) }
-  fn GetOtherTestService(&self, _arg_name: &str) -> binder::public_api::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>> { self.0.GetOtherTestService(_arg_name) }
-  fn VerifyName(&self, _arg_service: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &str) -> binder::public_api::Result<bool> { self.0.VerifyName(_arg_service, _arg_name) }
-  fn ReverseStringList(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::public_api::Result<Vec<String>> { self.0.ReverseStringList(_arg_input, _arg_repeated) }
-  fn RepeatParcelFileDescriptor(&self, _arg_read: &binder::parcel::ParcelFileDescriptor) -> binder::public_api::Result<binder::parcel::ParcelFileDescriptor> { self.0.RepeatParcelFileDescriptor(_arg_read) }
-  fn ReverseParcelFileDescriptorArray(&self, _arg_input: &[binder::parcel::ParcelFileDescriptor], _arg_repeated: &mut Vec<Option<binder::parcel::ParcelFileDescriptor>>) -> binder::public_api::Result<Vec<binder::parcel::ParcelFileDescriptor>> { self.0.ReverseParcelFileDescriptorArray(_arg_input, _arg_repeated) }
-  fn ThrowServiceException(&self, _arg_code: i32) -> binder::public_api::Result<()> { self.0.ThrowServiceException(_arg_code) }
-  fn RepeatNullableIntArray(&self, _arg_input: Option<&[i32]>) -> binder::public_api::Result<Option<Vec<i32>>> { self.0.RepeatNullableIntArray(_arg_input) }
-  fn RepeatNullableByteEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>) -> binder::public_api::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>> { self.0.RepeatNullableByteEnumArray(_arg_input) }
-  fn RepeatNullableIntEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>) -> binder::public_api::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>> { self.0.RepeatNullableIntEnumArray(_arg_input) }
-  fn RepeatNullableLongEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>) -> binder::public_api::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>> { self.0.RepeatNullableLongEnumArray(_arg_input) }
-  fn RepeatNullableString(&self, _arg_input: Option<&str>) -> binder::public_api::Result<Option<String>> { self.0.RepeatNullableString(_arg_input) }
-  fn RepeatNullableStringList(&self, _arg_input: Option<&[Option<String>]>) -> binder::public_api::Result<Option<Vec<Option<String>>>> { self.0.RepeatNullableStringList(_arg_input) }
-  fn RepeatNullableParcelable(&self, _arg_input: Option<&crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable>) -> binder::public_api::Result<Option<crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable>> { self.0.RepeatNullableParcelable(_arg_input) }
-  fn TakesAnIBinder(&self, _arg_input: &binder::SpIBinder) -> binder::public_api::Result<()> { self.0.TakesAnIBinder(_arg_input) }
-  fn TakesANullableIBinder(&self, _arg_input: Option<&binder::SpIBinder>) -> binder::public_api::Result<()> { self.0.TakesANullableIBinder(_arg_input) }
-  fn RepeatUtf8CppString(&self, _arg_token: &str) -> binder::public_api::Result<String> { self.0.RepeatUtf8CppString(_arg_token) }
-  fn RepeatNullableUtf8CppString(&self, _arg_token: Option<&str>) -> binder::public_api::Result<Option<String>> { self.0.RepeatNullableUtf8CppString(_arg_token) }
-  fn ReverseUtf8CppString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::public_api::Result<Vec<String>> { self.0.ReverseUtf8CppString(_arg_input, _arg_repeated) }
-  fn ReverseNullableUtf8CppString(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::public_api::Result<Option<Vec<Option<String>>>> { self.0.ReverseNullableUtf8CppString(_arg_input, _arg_repeated) }
-  fn ReverseUtf8CppStringList(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::public_api::Result<Option<Vec<Option<String>>>> { self.0.ReverseUtf8CppStringList(_arg_input, _arg_repeated) }
-  fn GetCallback(&self, _arg_return_null: bool) -> binder::public_api::Result<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> { self.0.GetCallback(_arg_return_null) }
-  fn FillOutStructuredParcelable(&self, _arg_parcel: &mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable) -> binder::public_api::Result<()> { self.0.FillOutStructuredParcelable(_arg_parcel) }
-  fn GetOldNameInterface(&self) -> binder::public_api::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName>> { self.0.GetOldNameInterface() }
-  fn GetNewNameInterface(&self) -> binder::public_api::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName>> { self.0.GetNewNameInterface() }
-  fn GetCppJavaTests(&self) -> binder::public_api::Result<Option<binder::SpIBinder>> { self.0.GetCppJavaTests() }
-  fn getBackendType(&self) -> binder::public_api::Result<crate::mangled::_7_android_4_aidl_5_tests_11_BackendType> { self.0.getBackendType() }
+impl ITestService for BpTestService {
+  fn UnimplementedMethod(&self, _arg_arg: i32) -> binder::Result<i32> {
+    let _aidl_data = self.build_parcel_UnimplementedMethod(_arg_arg)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::UnimplementedMethod, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_UnimplementedMethod(_arg_arg, _aidl_reply)
+  }
+  fn Deprecated(&self) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_Deprecated()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::Deprecated, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_Deprecated(_aidl_reply)
+  }
+  fn TestOneway(&self) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_TestOneway()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::TestOneway, _aidl_data, binder::binder_impl::FLAG_ONEWAY | binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_TestOneway(_aidl_reply)
+  }
+  fn RepeatBoolean(&self, _arg_token: bool) -> binder::Result<bool> {
+    let _aidl_data = self.build_parcel_RepeatBoolean(_arg_token)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatBoolean, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatBoolean(_arg_token, _aidl_reply)
+  }
+  fn RepeatByte(&self, _arg_token: i8) -> binder::Result<i8> {
+    let _aidl_data = self.build_parcel_RepeatByte(_arg_token)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatByte, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatByte(_arg_token, _aidl_reply)
+  }
+  fn RepeatChar(&self, _arg_token: u16) -> binder::Result<u16> {
+    let _aidl_data = self.build_parcel_RepeatChar(_arg_token)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatChar, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatChar(_arg_token, _aidl_reply)
+  }
+  fn RepeatInt(&self, _arg_token: i32) -> binder::Result<i32> {
+    let _aidl_data = self.build_parcel_RepeatInt(_arg_token)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatInt, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatInt(_arg_token, _aidl_reply)
+  }
+  fn RepeatLong(&self, _arg_token: i64) -> binder::Result<i64> {
+    let _aidl_data = self.build_parcel_RepeatLong(_arg_token)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatLong, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatLong(_arg_token, _aidl_reply)
+  }
+  fn RepeatFloat(&self, _arg_token: f32) -> binder::Result<f32> {
+    let _aidl_data = self.build_parcel_RepeatFloat(_arg_token)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatFloat, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatFloat(_arg_token, _aidl_reply)
+  }
+  fn RepeatDouble(&self, _arg_token: f64) -> binder::Result<f64> {
+    let _aidl_data = self.build_parcel_RepeatDouble(_arg_token)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatDouble, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatDouble(_arg_token, _aidl_reply)
+  }
+  fn RepeatString(&self, _arg_token: &str) -> binder::Result<String> {
+    let _aidl_data = self.build_parcel_RepeatString(_arg_token)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatString(_arg_token, _aidl_reply)
+  }
+  fn RepeatByteEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum> {
+    let _aidl_data = self.build_parcel_RepeatByteEnum(_arg_token)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatByteEnum, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatByteEnum(_arg_token, _aidl_reply)
+  }
+  fn RepeatIntEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum> {
+    let _aidl_data = self.build_parcel_RepeatIntEnum(_arg_token)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatIntEnum, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatIntEnum(_arg_token, _aidl_reply)
+  }
+  fn RepeatLongEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum> {
+    let _aidl_data = self.build_parcel_RepeatLongEnum(_arg_token)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatLongEnum, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatLongEnum(_arg_token, _aidl_reply)
+  }
+  fn ReverseBoolean(&self, _arg_input: &[bool], _arg_repeated: &mut Vec<bool>) -> binder::Result<Vec<bool>> {
+    let _aidl_data = self.build_parcel_ReverseBoolean(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseBoolean, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseBoolean(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ReverseByte(&self, _arg_input: &[u8], _arg_repeated: &mut Vec<u8>) -> binder::Result<Vec<u8>> {
+    let _aidl_data = self.build_parcel_ReverseByte(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseByte, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseByte(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ReverseChar(&self, _arg_input: &[u16], _arg_repeated: &mut Vec<u16>) -> binder::Result<Vec<u16>> {
+    let _aidl_data = self.build_parcel_ReverseChar(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseChar, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseChar(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ReverseInt(&self, _arg_input: &[i32], _arg_repeated: &mut Vec<i32>) -> binder::Result<Vec<i32>> {
+    let _aidl_data = self.build_parcel_ReverseInt(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseInt, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseInt(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ReverseLong(&self, _arg_input: &[i64], _arg_repeated: &mut Vec<i64>) -> binder::Result<Vec<i64>> {
+    let _aidl_data = self.build_parcel_ReverseLong(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseLong, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseLong(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ReverseFloat(&self, _arg_input: &[f32], _arg_repeated: &mut Vec<f32>) -> binder::Result<Vec<f32>> {
+    let _aidl_data = self.build_parcel_ReverseFloat(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseFloat, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseFloat(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ReverseDouble(&self, _arg_input: &[f64], _arg_repeated: &mut Vec<f64>) -> binder::Result<Vec<f64>> {
+    let _aidl_data = self.build_parcel_ReverseDouble(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseDouble, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseDouble(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ReverseString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>> {
+    let _aidl_data = self.build_parcel_ReverseString(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseString(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ReverseByteEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>> {
+    let _aidl_data = self.build_parcel_ReverseByteEnum(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseByteEnum, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseByteEnum(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ReverseIntEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>> {
+    let _aidl_data = self.build_parcel_ReverseIntEnum(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseIntEnum, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseIntEnum(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ReverseLongEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>> {
+    let _aidl_data = self.build_parcel_ReverseLongEnum(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseLongEnum, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseLongEnum(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn GetOtherTestService(&self, _arg_name: &str) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>> {
+    let _aidl_data = self.build_parcel_GetOtherTestService(_arg_name)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::GetOtherTestService, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_GetOtherTestService(_arg_name, _aidl_reply)
+  }
+  fn VerifyName(&self, _arg_service: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &str) -> binder::Result<bool> {
+    let _aidl_data = self.build_parcel_VerifyName(_arg_service, _arg_name)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::VerifyName, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_VerifyName(_arg_service, _arg_name, _aidl_reply)
+  }
+  fn GetInterfaceArray(&self, _arg_names: &[String]) -> binder::Result<Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> {
+    let _aidl_data = self.build_parcel_GetInterfaceArray(_arg_names)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::GetInterfaceArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_GetInterfaceArray(_arg_names, _aidl_reply)
+  }
+  fn VerifyNamesWithInterfaceArray(&self, _arg_services: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>], _arg_names: &[String]) -> binder::Result<bool> {
+    let _aidl_data = self.build_parcel_VerifyNamesWithInterfaceArray(_arg_services, _arg_names)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::VerifyNamesWithInterfaceArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_VerifyNamesWithInterfaceArray(_arg_services, _arg_names, _aidl_reply)
+  }
+  fn GetNullableInterfaceArray(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>> {
+    let _aidl_data = self.build_parcel_GetNullableInterfaceArray(_arg_names)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::GetNullableInterfaceArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_GetNullableInterfaceArray(_arg_names, _aidl_reply)
+  }
+  fn VerifyNamesWithNullableInterfaceArray(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<bool> {
+    let _aidl_data = self.build_parcel_VerifyNamesWithNullableInterfaceArray(_arg_services, _arg_names)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::VerifyNamesWithNullableInterfaceArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_VerifyNamesWithNullableInterfaceArray(_arg_services, _arg_names, _aidl_reply)
+  }
+  fn GetInterfaceList(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>> {
+    let _aidl_data = self.build_parcel_GetInterfaceList(_arg_names)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::GetInterfaceList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_GetInterfaceList(_arg_names, _aidl_reply)
+  }
+  fn VerifyNamesWithInterfaceList(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<bool> {
+    let _aidl_data = self.build_parcel_VerifyNamesWithInterfaceList(_arg_services, _arg_names)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::VerifyNamesWithInterfaceList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_VerifyNamesWithInterfaceList(_arg_services, _arg_names, _aidl_reply)
+  }
+  fn ReverseStringList(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>> {
+    let _aidl_data = self.build_parcel_ReverseStringList(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseStringList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseStringList(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn RepeatParcelFileDescriptor(&self, _arg_read: &binder::ParcelFileDescriptor) -> binder::Result<binder::ParcelFileDescriptor> {
+    let _aidl_data = self.build_parcel_RepeatParcelFileDescriptor(_arg_read)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatParcelFileDescriptor, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatParcelFileDescriptor(_arg_read, _aidl_reply)
+  }
+  fn ReverseParcelFileDescriptorArray(&self, _arg_input: &[binder::ParcelFileDescriptor], _arg_repeated: &mut Vec<Option<binder::ParcelFileDescriptor>>) -> binder::Result<Vec<binder::ParcelFileDescriptor>> {
+    let _aidl_data = self.build_parcel_ReverseParcelFileDescriptorArray(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseParcelFileDescriptorArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseParcelFileDescriptorArray(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ThrowServiceException(&self, _arg_code: i32) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_ThrowServiceException(_arg_code)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ThrowServiceException, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ThrowServiceException(_arg_code, _aidl_reply)
+  }
+  fn RepeatNullableIntArray(&self, _arg_input: Option<&[i32]>) -> binder::Result<Option<Vec<i32>>> {
+    let _aidl_data = self.build_parcel_RepeatNullableIntArray(_arg_input)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatNullableIntArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatNullableIntArray(_arg_input, _aidl_reply)
+  }
+  fn RepeatNullableByteEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>> {
+    let _aidl_data = self.build_parcel_RepeatNullableByteEnumArray(_arg_input)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatNullableByteEnumArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatNullableByteEnumArray(_arg_input, _aidl_reply)
+  }
+  fn RepeatNullableIntEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>> {
+    let _aidl_data = self.build_parcel_RepeatNullableIntEnumArray(_arg_input)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatNullableIntEnumArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatNullableIntEnumArray(_arg_input, _aidl_reply)
+  }
+  fn RepeatNullableLongEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>> {
+    let _aidl_data = self.build_parcel_RepeatNullableLongEnumArray(_arg_input)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatNullableLongEnumArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatNullableLongEnumArray(_arg_input, _aidl_reply)
+  }
+  fn RepeatNullableString(&self, _arg_input: Option<&str>) -> binder::Result<Option<String>> {
+    let _aidl_data = self.build_parcel_RepeatNullableString(_arg_input)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatNullableString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatNullableString(_arg_input, _aidl_reply)
+  }
+  fn RepeatNullableStringList(&self, _arg_input: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<String>>>> {
+    let _aidl_data = self.build_parcel_RepeatNullableStringList(_arg_input)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatNullableStringList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatNullableStringList(_arg_input, _aidl_reply)
+  }
+  fn RepeatNullableParcelable(&self, _arg_input: Option<&crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>) -> binder::Result<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>> {
+    let _aidl_data = self.build_parcel_RepeatNullableParcelable(_arg_input)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatNullableParcelable, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatNullableParcelable(_arg_input, _aidl_reply)
+  }
+  fn RepeatNullableParcelableArray(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>> {
+    let _aidl_data = self.build_parcel_RepeatNullableParcelableArray(_arg_input)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatNullableParcelableArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatNullableParcelableArray(_arg_input, _aidl_reply)
+  }
+  fn RepeatNullableParcelableList(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>> {
+    let _aidl_data = self.build_parcel_RepeatNullableParcelableList(_arg_input)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatNullableParcelableList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatNullableParcelableList(_arg_input, _aidl_reply)
+  }
+  fn TakesAnIBinder(&self, _arg_input: &binder::SpIBinder) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_TakesAnIBinder(_arg_input)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::TakesAnIBinder, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_TakesAnIBinder(_arg_input, _aidl_reply)
+  }
+  fn TakesANullableIBinder(&self, _arg_input: Option<&binder::SpIBinder>) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_TakesANullableIBinder(_arg_input)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::TakesANullableIBinder, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_TakesANullableIBinder(_arg_input, _aidl_reply)
+  }
+  fn TakesAnIBinderList(&self, _arg_input: &[binder::SpIBinder]) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_TakesAnIBinderList(_arg_input)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::TakesAnIBinderList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_TakesAnIBinderList(_arg_input, _aidl_reply)
+  }
+  fn TakesANullableIBinderList(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_TakesANullableIBinderList(_arg_input)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::TakesANullableIBinderList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_TakesANullableIBinderList(_arg_input, _aidl_reply)
+  }
+  fn RepeatUtf8CppString(&self, _arg_token: &str) -> binder::Result<String> {
+    let _aidl_data = self.build_parcel_RepeatUtf8CppString(_arg_token)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatUtf8CppString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatUtf8CppString(_arg_token, _aidl_reply)
+  }
+  fn RepeatNullableUtf8CppString(&self, _arg_token: Option<&str>) -> binder::Result<Option<String>> {
+    let _aidl_data = self.build_parcel_RepeatNullableUtf8CppString(_arg_token)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatNullableUtf8CppString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatNullableUtf8CppString(_arg_token, _aidl_reply)
+  }
+  fn ReverseUtf8CppString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>> {
+    let _aidl_data = self.build_parcel_ReverseUtf8CppString(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseUtf8CppString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseUtf8CppString(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ReverseNullableUtf8CppString(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<Option<Vec<Option<String>>>> {
+    let _aidl_data = self.build_parcel_ReverseNullableUtf8CppString(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseNullableUtf8CppString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseNullableUtf8CppString(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ReverseUtf8CppStringList(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<Option<Vec<Option<String>>>> {
+    let _aidl_data = self.build_parcel_ReverseUtf8CppStringList(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseUtf8CppStringList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseUtf8CppStringList(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn GetCallback(&self, _arg_return_null: bool) -> binder::Result<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> {
+    let _aidl_data = self.build_parcel_GetCallback(_arg_return_null)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::GetCallback, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_GetCallback(_arg_return_null, _aidl_reply)
+  }
+  fn FillOutStructuredParcelable(&self, _arg_parcel: &mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_FillOutStructuredParcelable(_arg_parcel)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::FillOutStructuredParcelable, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_FillOutStructuredParcelable(_arg_parcel, _aidl_reply)
+  }
+  fn RepeatExtendableParcelable(&self, _arg_ep: &crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable, _arg_ep2: &mut crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_RepeatExtendableParcelable(_arg_ep, _arg_ep2)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::RepeatExtendableParcelable, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_RepeatExtendableParcelable(_arg_ep, _arg_ep2, _aidl_reply)
+  }
+  fn ReverseList(&self, _arg_list: &crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList> {
+    let _aidl_data = self.build_parcel_ReverseList(_arg_list)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseList(_arg_list, _aidl_reply)
+  }
+  fn ReverseIBinderArray(&self, _arg_input: &[binder::SpIBinder], _arg_repeated: &mut Vec<Option<binder::SpIBinder>>) -> binder::Result<Vec<binder::SpIBinder>> {
+    let _aidl_data = self.build_parcel_ReverseIBinderArray(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseIBinderArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseIBinderArray(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn ReverseNullableIBinderArray(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>, _arg_repeated: &mut Option<Vec<Option<binder::SpIBinder>>>) -> binder::Result<Option<Vec<Option<binder::SpIBinder>>>> {
+    let _aidl_data = self.build_parcel_ReverseNullableIBinderArray(_arg_input, _arg_repeated)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::ReverseNullableIBinderArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_ReverseNullableIBinderArray(_arg_input, _arg_repeated, _aidl_reply)
+  }
+  fn GetOldNameInterface(&self) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName>> {
+    let _aidl_data = self.build_parcel_GetOldNameInterface()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::GetOldNameInterface, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_GetOldNameInterface(_aidl_reply)
+  }
+  fn GetNewNameInterface(&self) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName>> {
+    let _aidl_data = self.build_parcel_GetNewNameInterface()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::GetNewNameInterface, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_GetNewNameInterface(_aidl_reply)
+  }
+  fn GetCppJavaTests(&self) -> binder::Result<Option<binder::SpIBinder>> {
+    let _aidl_data = self.build_parcel_GetCppJavaTests()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::GetCppJavaTests, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_GetCppJavaTests(_aidl_reply)
+  }
+  fn getBackendType(&self) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_11_BackendType> {
+    let _aidl_data = self.build_parcel_getBackendType()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::getBackendType, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_getBackendType(_aidl_reply)
+  }
 }
-fn on_transact(_aidl_service: &dyn ITestService, _aidl_code: binder::TransactionCode, _aidl_data: &binder::parcel::Parcel, _aidl_reply: &mut binder::parcel::Parcel) -> binder::Result<()> {
+impl<P: binder::BinderAsyncPool> ITestServiceAsync<P> for BpTestService {
+  fn UnimplementedMethod<'a>(&'a self, _arg_arg: i32) -> binder::BoxFuture<'a, binder::Result<i32>> {
+    let _aidl_data = match self.build_parcel_UnimplementedMethod(_arg_arg) {
+      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::UnimplementedMethod, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_UnimplementedMethod(_arg_arg, _aidl_reply)
+      }
+    )
+  }
+  fn Deprecated<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_Deprecated() {
+      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::Deprecated, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_Deprecated(_aidl_reply)
+      }
+    )
+  }
+  fn TestOneway(&self) -> std::future::Ready<binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_TestOneway() {
+      Ok(_aidl_data) => _aidl_data,
+      Err(err) => return std::future::ready(Err(err)),
+    };
+    let _aidl_reply = self.binder.submit_transact(transactions::TestOneway, _aidl_data, binder::binder_impl::FLAG_ONEWAY | binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    std::future::ready(self.read_response_TestOneway(_aidl_reply))
+  }
+  fn RepeatBoolean<'a>(&'a self, _arg_token: bool) -> binder::BoxFuture<'a, binder::Result<bool>> {
+    let _aidl_data = match self.build_parcel_RepeatBoolean(_arg_token) {
+      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::RepeatBoolean, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatBoolean(_arg_token, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatByte<'a>(&'a self, _arg_token: i8) -> binder::BoxFuture<'a, binder::Result<i8>> {
+    let _aidl_data = match self.build_parcel_RepeatByte(_arg_token) {
+      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::RepeatByte, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatByte(_arg_token, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatChar<'a>(&'a self, _arg_token: u16) -> binder::BoxFuture<'a, binder::Result<u16>> {
+    let _aidl_data = match self.build_parcel_RepeatChar(_arg_token) {
+      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::RepeatChar, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatChar(_arg_token, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatInt<'a>(&'a self, _arg_token: i32) -> binder::BoxFuture<'a, binder::Result<i32>> {
+    let _aidl_data = match self.build_parcel_RepeatInt(_arg_token) {
+      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::RepeatInt, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatInt(_arg_token, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatLong<'a>(&'a self, _arg_token: i64) -> binder::BoxFuture<'a, binder::Result<i64>> {
+    let _aidl_data = match self.build_parcel_RepeatLong(_arg_token) {
+      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::RepeatLong, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatLong(_arg_token, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatFloat<'a>(&'a self, _arg_token: f32) -> binder::BoxFuture<'a, binder::Result<f32>> {
+    let _aidl_data = match self.build_parcel_RepeatFloat(_arg_token) {
+      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::RepeatFloat, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatFloat(_arg_token, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatDouble<'a>(&'a self, _arg_token: f64) -> binder::BoxFuture<'a, binder::Result<f64>> {
+    let _aidl_data = match self.build_parcel_RepeatDouble(_arg_token) {
+      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::RepeatDouble, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatDouble(_arg_token, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatString<'a>(&'a self, _arg_token: &'a str) -> binder::BoxFuture<'a, binder::Result<String>> {
+    let _aidl_data = match self.build_parcel_RepeatString(_arg_token) {
+      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::RepeatString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatString(_arg_token, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatByteEnum<'a>(&'a self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum) -> binder::BoxFuture<'a, binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>> {
+    let _aidl_data = match self.build_parcel_RepeatByteEnum(_arg_token) {
+      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::RepeatByteEnum, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatByteEnum(_arg_token, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatIntEnum<'a>(&'a self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum) -> binder::BoxFuture<'a, binder::Result<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>> {
+    let _aidl_data = match self.build_parcel_RepeatIntEnum(_arg_token) {
+      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::RepeatIntEnum, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatIntEnum(_arg_token, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatLongEnum<'a>(&'a self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum) -> binder::BoxFuture<'a, binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>> {
+    let _aidl_data = match self.build_parcel_RepeatLongEnum(_arg_token) {
+      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::RepeatLongEnum, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatLongEnum(_arg_token, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseBoolean<'a>(&'a self, _arg_input: &'a [bool], _arg_repeated: &'a mut Vec<bool>) -> binder::BoxFuture<'a, binder::Result<Vec<bool>>> {
+    let _aidl_data = match self.build_parcel_ReverseBoolean(_arg_input, _arg_repeated) {
+      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::ReverseBoolean, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseBoolean(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseByte<'a>(&'a self, _arg_input: &'a [u8], _arg_repeated: &'a mut Vec<u8>) -> binder::BoxFuture<'a, binder::Result<Vec<u8>>> {
+    let _aidl_data = match self.build_parcel_ReverseByte(_arg_input, _arg_repeated) {
+      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::ReverseByte, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseByte(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseChar<'a>(&'a self, _arg_input: &'a [u16], _arg_repeated: &'a mut Vec<u16>) -> binder::BoxFuture<'a, binder::Result<Vec<u16>>> {
+    let _aidl_data = match self.build_parcel_ReverseChar(_arg_input, _arg_repeated) {
+      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::ReverseChar, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseChar(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseInt<'a>(&'a self, _arg_input: &'a [i32], _arg_repeated: &'a mut Vec<i32>) -> binder::BoxFuture<'a, binder::Result<Vec<i32>>> {
+    let _aidl_data = match self.build_parcel_ReverseInt(_arg_input, _arg_repeated) {
+      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::ReverseInt, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseInt(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseLong<'a>(&'a self, _arg_input: &'a [i64], _arg_repeated: &'a mut Vec<i64>) -> binder::BoxFuture<'a, binder::Result<Vec<i64>>> {
+    let _aidl_data = match self.build_parcel_ReverseLong(_arg_input, _arg_repeated) {
+      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::ReverseLong, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseLong(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseFloat<'a>(&'a self, _arg_input: &'a [f32], _arg_repeated: &'a mut Vec<f32>) -> binder::BoxFuture<'a, binder::Result<Vec<f32>>> {
+    let _aidl_data = match self.build_parcel_ReverseFloat(_arg_input, _arg_repeated) {
+      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::ReverseFloat, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseFloat(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseDouble<'a>(&'a self, _arg_input: &'a [f64], _arg_repeated: &'a mut Vec<f64>) -> binder::BoxFuture<'a, binder::Result<Vec<f64>>> {
+    let _aidl_data = match self.build_parcel_ReverseDouble(_arg_input, _arg_repeated) {
+      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::ReverseDouble, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseDouble(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseString<'a>(&'a self, _arg_input: &'a [String], _arg_repeated: &'a mut Vec<String>) -> binder::BoxFuture<'a, binder::Result<Vec<String>>> {
+    let _aidl_data = match self.build_parcel_ReverseString(_arg_input, _arg_repeated) {
+      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::ReverseString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseString(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseByteEnum<'a>(&'a self, _arg_input: &'a [crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &'a mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>) -> binder::BoxFuture<'a, binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>> {
+    let _aidl_data = match self.build_parcel_ReverseByteEnum(_arg_input, _arg_repeated) {
+      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::ReverseByteEnum, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseByteEnum(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseIntEnum<'a>(&'a self, _arg_input: &'a [crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &'a mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>) -> binder::BoxFuture<'a, binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>> {
+    let _aidl_data = match self.build_parcel_ReverseIntEnum(_arg_input, _arg_repeated) {
+      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::ReverseIntEnum, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseIntEnum(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseLongEnum<'a>(&'a self, _arg_input: &'a [crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &'a mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>) -> binder::BoxFuture<'a, binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>> {
+    let _aidl_data = match self.build_parcel_ReverseLongEnum(_arg_input, _arg_repeated) {
+      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::ReverseLongEnum, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseLongEnum(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn GetOtherTestService<'a>(&'a self, _arg_name: &'a str) -> binder::BoxFuture<'a, binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> {
+    let _aidl_data = match self.build_parcel_GetOtherTestService(_arg_name) {
+      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::GetOtherTestService, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_GetOtherTestService(_arg_name, _aidl_reply)
+      }
+    )
+  }
+  fn VerifyName<'a>(&'a self, _arg_service: &'a binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &'a str) -> binder::BoxFuture<'a, binder::Result<bool>> {
+    let _aidl_data = match self.build_parcel_VerifyName(_arg_service, _arg_name) {
+      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::VerifyName, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_VerifyName(_arg_service, _arg_name, _aidl_reply)
+      }
+    )
+  }
+  fn GetInterfaceArray<'a>(&'a self, _arg_names: &'a [String]) -> binder::BoxFuture<'a, binder::Result<Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>> {
+    let _aidl_data = match self.build_parcel_GetInterfaceArray(_arg_names) {
+      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::GetInterfaceArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_GetInterfaceArray(_arg_names, _aidl_reply)
+      }
+    )
+  }
+  fn VerifyNamesWithInterfaceArray<'a>(&'a self, _arg_services: &'a [binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>], _arg_names: &'a [String]) -> binder::BoxFuture<'a, binder::Result<bool>> {
+    let _aidl_data = match self.build_parcel_VerifyNamesWithInterfaceArray(_arg_services, _arg_names) {
+      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::VerifyNamesWithInterfaceArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_VerifyNamesWithInterfaceArray(_arg_services, _arg_names, _aidl_reply)
+      }
+    )
+  }
+  fn GetNullableInterfaceArray<'a>(&'a self, _arg_names: Option<&'a [Option<String>]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>>> {
+    let _aidl_data = match self.build_parcel_GetNullableInterfaceArray(_arg_names) {
+      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::GetNullableInterfaceArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_GetNullableInterfaceArray(_arg_names, _aidl_reply)
+      }
+    )
+  }
+  fn VerifyNamesWithNullableInterfaceArray<'a>(&'a self, _arg_services: Option<&'a [Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&'a [Option<String>]>) -> binder::BoxFuture<'a, binder::Result<bool>> {
+    let _aidl_data = match self.build_parcel_VerifyNamesWithNullableInterfaceArray(_arg_services, _arg_names) {
+      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::VerifyNamesWithNullableInterfaceArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_VerifyNamesWithNullableInterfaceArray(_arg_services, _arg_names, _aidl_reply)
+      }
+    )
+  }
+  fn GetInterfaceList<'a>(&'a self, _arg_names: Option<&'a [Option<String>]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>>> {
+    let _aidl_data = match self.build_parcel_GetInterfaceList(_arg_names) {
+      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::GetInterfaceList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_GetInterfaceList(_arg_names, _aidl_reply)
+      }
+    )
+  }
+  fn VerifyNamesWithInterfaceList<'a>(&'a self, _arg_services: Option<&'a [Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&'a [Option<String>]>) -> binder::BoxFuture<'a, binder::Result<bool>> {
+    let _aidl_data = match self.build_parcel_VerifyNamesWithInterfaceList(_arg_services, _arg_names) {
+      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::VerifyNamesWithInterfaceList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_VerifyNamesWithInterfaceList(_arg_services, _arg_names, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseStringList<'a>(&'a self, _arg_input: &'a [String], _arg_repeated: &'a mut Vec<String>) -> binder::BoxFuture<'a, binder::Result<Vec<String>>> {
+    let _aidl_data = match self.build_parcel_ReverseStringList(_arg_input, _arg_repeated) {
+      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::ReverseStringList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseStringList(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatParcelFileDescriptor<'a>(&'a self, _arg_read: &'a binder::ParcelFileDescriptor) -> binder::BoxFuture<'a, binder::Result<binder::ParcelFileDescriptor>> {
+    let _aidl_data = match self.build_parcel_RepeatParcelFileDescriptor(_arg_read) {
+      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::RepeatParcelFileDescriptor, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatParcelFileDescriptor(_arg_read, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseParcelFileDescriptorArray<'a>(&'a self, _arg_input: &'a [binder::ParcelFileDescriptor], _arg_repeated: &'a mut Vec<Option<binder::ParcelFileDescriptor>>) -> binder::BoxFuture<'a, binder::Result<Vec<binder::ParcelFileDescriptor>>> {
+    let _aidl_data = match self.build_parcel_ReverseParcelFileDescriptorArray(_arg_input, _arg_repeated) {
+      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::ReverseParcelFileDescriptorArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseParcelFileDescriptorArray(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ThrowServiceException<'a>(&'a self, _arg_code: i32) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_ThrowServiceException(_arg_code) {
+      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::ThrowServiceException, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ThrowServiceException(_arg_code, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatNullableIntArray<'a>(&'a self, _arg_input: Option<&'a [i32]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<i32>>>> {
+    let _aidl_data = match self.build_parcel_RepeatNullableIntArray(_arg_input) {
+      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::RepeatNullableIntArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatNullableIntArray(_arg_input, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatNullableByteEnumArray<'a>(&'a self, _arg_input: Option<&'a [crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>>> {
+    let _aidl_data = match self.build_parcel_RepeatNullableByteEnumArray(_arg_input) {
+      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::RepeatNullableByteEnumArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatNullableByteEnumArray(_arg_input, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatNullableIntEnumArray<'a>(&'a self, _arg_input: Option<&'a [crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>>> {
+    let _aidl_data = match self.build_parcel_RepeatNullableIntEnumArray(_arg_input) {
+      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::RepeatNullableIntEnumArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatNullableIntEnumArray(_arg_input, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatNullableLongEnumArray<'a>(&'a self, _arg_input: Option<&'a [crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>>> {
+    let _aidl_data = match self.build_parcel_RepeatNullableLongEnumArray(_arg_input) {
+      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::RepeatNullableLongEnumArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatNullableLongEnumArray(_arg_input, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatNullableString<'a>(&'a self, _arg_input: Option<&'a str>) -> binder::BoxFuture<'a, binder::Result<Option<String>>> {
+    let _aidl_data = match self.build_parcel_RepeatNullableString(_arg_input) {
+      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::RepeatNullableString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatNullableString(_arg_input, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatNullableStringList<'a>(&'a self, _arg_input: Option<&'a [Option<String>]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<String>>>>> {
+    let _aidl_data = match self.build_parcel_RepeatNullableStringList(_arg_input) {
+      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::RepeatNullableStringList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatNullableStringList(_arg_input, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatNullableParcelable<'a>(&'a self, _arg_input: Option<&'a crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>) -> binder::BoxFuture<'a, binder::Result<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>> {
+    let _aidl_data = match self.build_parcel_RepeatNullableParcelable(_arg_input) {
+      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::RepeatNullableParcelable, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatNullableParcelable(_arg_input, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatNullableParcelableArray<'a>(&'a self, _arg_input: Option<&'a [Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>>> {
+    let _aidl_data = match self.build_parcel_RepeatNullableParcelableArray(_arg_input) {
+      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::RepeatNullableParcelableArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatNullableParcelableArray(_arg_input, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatNullableParcelableList<'a>(&'a self, _arg_input: Option<&'a [Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>>> {
+    let _aidl_data = match self.build_parcel_RepeatNullableParcelableList(_arg_input) {
+      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::RepeatNullableParcelableList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatNullableParcelableList(_arg_input, _aidl_reply)
+      }
+    )
+  }
+  fn TakesAnIBinder<'a>(&'a self, _arg_input: &'a binder::SpIBinder) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_TakesAnIBinder(_arg_input) {
+      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::TakesAnIBinder, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_TakesAnIBinder(_arg_input, _aidl_reply)
+      }
+    )
+  }
+  fn TakesANullableIBinder<'a>(&'a self, _arg_input: Option<&'a binder::SpIBinder>) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_TakesANullableIBinder(_arg_input) {
+      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::TakesANullableIBinder, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_TakesANullableIBinder(_arg_input, _aidl_reply)
+      }
+    )
+  }
+  fn TakesAnIBinderList<'a>(&'a self, _arg_input: &'a [binder::SpIBinder]) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_TakesAnIBinderList(_arg_input) {
+      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::TakesAnIBinderList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_TakesAnIBinderList(_arg_input, _aidl_reply)
+      }
+    )
+  }
+  fn TakesANullableIBinderList<'a>(&'a self, _arg_input: Option<&'a [Option<binder::SpIBinder>]>) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_TakesANullableIBinderList(_arg_input) {
+      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::TakesANullableIBinderList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_TakesANullableIBinderList(_arg_input, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatUtf8CppString<'a>(&'a self, _arg_token: &'a str) -> binder::BoxFuture<'a, binder::Result<String>> {
+    let _aidl_data = match self.build_parcel_RepeatUtf8CppString(_arg_token) {
+      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::RepeatUtf8CppString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatUtf8CppString(_arg_token, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatNullableUtf8CppString<'a>(&'a self, _arg_token: Option<&'a str>) -> binder::BoxFuture<'a, binder::Result<Option<String>>> {
+    let _aidl_data = match self.build_parcel_RepeatNullableUtf8CppString(_arg_token) {
+      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::RepeatNullableUtf8CppString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatNullableUtf8CppString(_arg_token, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseUtf8CppString<'a>(&'a self, _arg_input: &'a [String], _arg_repeated: &'a mut Vec<String>) -> binder::BoxFuture<'a, binder::Result<Vec<String>>> {
+    let _aidl_data = match self.build_parcel_ReverseUtf8CppString(_arg_input, _arg_repeated) {
+      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::ReverseUtf8CppString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseUtf8CppString(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseNullableUtf8CppString<'a>(&'a self, _arg_input: Option<&'a [Option<String>]>, _arg_repeated: &'a mut Option<Vec<Option<String>>>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<String>>>>> {
+    let _aidl_data = match self.build_parcel_ReverseNullableUtf8CppString(_arg_input, _arg_repeated) {
+      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::ReverseNullableUtf8CppString, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseNullableUtf8CppString(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseUtf8CppStringList<'a>(&'a self, _arg_input: Option<&'a [Option<String>]>, _arg_repeated: &'a mut Option<Vec<Option<String>>>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<String>>>>> {
+    let _aidl_data = match self.build_parcel_ReverseUtf8CppStringList(_arg_input, _arg_repeated) {
+      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::ReverseUtf8CppStringList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseUtf8CppStringList(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn GetCallback<'a>(&'a self, _arg_return_null: bool) -> binder::BoxFuture<'a, binder::Result<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>> {
+    let _aidl_data = match self.build_parcel_GetCallback(_arg_return_null) {
+      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::GetCallback, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_GetCallback(_arg_return_null, _aidl_reply)
+      }
+    )
+  }
+  fn FillOutStructuredParcelable<'a>(&'a self, _arg_parcel: &'a mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_FillOutStructuredParcelable(_arg_parcel) {
+      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::FillOutStructuredParcelable, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_FillOutStructuredParcelable(_arg_parcel, _aidl_reply)
+      }
+    )
+  }
+  fn RepeatExtendableParcelable<'a>(&'a self, _arg_ep: &'a crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable, _arg_ep2: &'a mut crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_RepeatExtendableParcelable(_arg_ep, _arg_ep2) {
+      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::RepeatExtendableParcelable, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_RepeatExtendableParcelable(_arg_ep, _arg_ep2, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseList<'a>(&'a self, _arg_list: &'a crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList) -> binder::BoxFuture<'a, binder::Result<crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList>> {
+    let _aidl_data = match self.build_parcel_ReverseList(_arg_list) {
+      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::ReverseList, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseList(_arg_list, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseIBinderArray<'a>(&'a self, _arg_input: &'a [binder::SpIBinder], _arg_repeated: &'a mut Vec<Option<binder::SpIBinder>>) -> binder::BoxFuture<'a, binder::Result<Vec<binder::SpIBinder>>> {
+    let _aidl_data = match self.build_parcel_ReverseIBinderArray(_arg_input, _arg_repeated) {
+      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::ReverseIBinderArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseIBinderArray(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn ReverseNullableIBinderArray<'a>(&'a self, _arg_input: Option<&'a [Option<binder::SpIBinder>]>, _arg_repeated: &'a mut Option<Vec<Option<binder::SpIBinder>>>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<binder::SpIBinder>>>>> {
+    let _aidl_data = match self.build_parcel_ReverseNullableIBinderArray(_arg_input, _arg_repeated) {
+      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::ReverseNullableIBinderArray, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_ReverseNullableIBinderArray(_arg_input, _arg_repeated, _aidl_reply)
+      }
+    )
+  }
+  fn GetOldNameInterface<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName>>> {
+    let _aidl_data = match self.build_parcel_GetOldNameInterface() {
+      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::GetOldNameInterface, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_GetOldNameInterface(_aidl_reply)
+      }
+    )
+  }
+  fn GetNewNameInterface<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName>>> {
+    let _aidl_data = match self.build_parcel_GetNewNameInterface() {
+      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::GetNewNameInterface, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_GetNewNameInterface(_aidl_reply)
+      }
+    )
+  }
+  fn GetCppJavaTests<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<Option<binder::SpIBinder>>> {
+    let _aidl_data = match self.build_parcel_GetCppJavaTests() {
+      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::GetCppJavaTests, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_GetCppJavaTests(_aidl_reply)
+      }
+    )
+  }
+  fn getBackendType<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<crate::mangled::_7_android_4_aidl_5_tests_11_BackendType>> {
+    let _aidl_data = match self.build_parcel_getBackendType() {
+      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::getBackendType, _aidl_data, binder::binder_impl::FLAG_CLEAR_BUF | binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_getBackendType(_aidl_reply)
+      }
+    )
+  }
+}
+impl ITestService for binder::binder_impl::Binder<BnTestService> {
+  fn UnimplementedMethod(&self, _arg_arg: i32) -> binder::Result<i32> { self.0.UnimplementedMethod(_arg_arg) }
+  fn Deprecated(&self) -> binder::Result<()> { self.0.Deprecated() }
+  fn TestOneway(&self) -> binder::Result<()> { self.0.TestOneway() }
+  fn RepeatBoolean(&self, _arg_token: bool) -> binder::Result<bool> { self.0.RepeatBoolean(_arg_token) }
+  fn RepeatByte(&self, _arg_token: i8) -> binder::Result<i8> { self.0.RepeatByte(_arg_token) }
+  fn RepeatChar(&self, _arg_token: u16) -> binder::Result<u16> { self.0.RepeatChar(_arg_token) }
+  fn RepeatInt(&self, _arg_token: i32) -> binder::Result<i32> { self.0.RepeatInt(_arg_token) }
+  fn RepeatLong(&self, _arg_token: i64) -> binder::Result<i64> { self.0.RepeatLong(_arg_token) }
+  fn RepeatFloat(&self, _arg_token: f32) -> binder::Result<f32> { self.0.RepeatFloat(_arg_token) }
+  fn RepeatDouble(&self, _arg_token: f64) -> binder::Result<f64> { self.0.RepeatDouble(_arg_token) }
+  fn RepeatString(&self, _arg_token: &str) -> binder::Result<String> { self.0.RepeatString(_arg_token) }
+  fn RepeatByteEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum> { self.0.RepeatByteEnum(_arg_token) }
+  fn RepeatIntEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum> { self.0.RepeatIntEnum(_arg_token) }
+  fn RepeatLongEnum(&self, _arg_token: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum> { self.0.RepeatLongEnum(_arg_token) }
+  fn ReverseBoolean(&self, _arg_input: &[bool], _arg_repeated: &mut Vec<bool>) -> binder::Result<Vec<bool>> { self.0.ReverseBoolean(_arg_input, _arg_repeated) }
+  fn ReverseByte(&self, _arg_input: &[u8], _arg_repeated: &mut Vec<u8>) -> binder::Result<Vec<u8>> { self.0.ReverseByte(_arg_input, _arg_repeated) }
+  fn ReverseChar(&self, _arg_input: &[u16], _arg_repeated: &mut Vec<u16>) -> binder::Result<Vec<u16>> { self.0.ReverseChar(_arg_input, _arg_repeated) }
+  fn ReverseInt(&self, _arg_input: &[i32], _arg_repeated: &mut Vec<i32>) -> binder::Result<Vec<i32>> { self.0.ReverseInt(_arg_input, _arg_repeated) }
+  fn ReverseLong(&self, _arg_input: &[i64], _arg_repeated: &mut Vec<i64>) -> binder::Result<Vec<i64>> { self.0.ReverseLong(_arg_input, _arg_repeated) }
+  fn ReverseFloat(&self, _arg_input: &[f32], _arg_repeated: &mut Vec<f32>) -> binder::Result<Vec<f32>> { self.0.ReverseFloat(_arg_input, _arg_repeated) }
+  fn ReverseDouble(&self, _arg_input: &[f64], _arg_repeated: &mut Vec<f64>) -> binder::Result<Vec<f64>> { self.0.ReverseDouble(_arg_input, _arg_repeated) }
+  fn ReverseString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>> { self.0.ReverseString(_arg_input, _arg_repeated) }
+  fn ReverseByteEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>> { self.0.ReverseByteEnum(_arg_input, _arg_repeated) }
+  fn ReverseIntEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>> { self.0.ReverseIntEnum(_arg_input, _arg_repeated) }
+  fn ReverseLongEnum(&self, _arg_input: &[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum], _arg_repeated: &mut Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>) -> binder::Result<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>> { self.0.ReverseLongEnum(_arg_input, _arg_repeated) }
+  fn GetOtherTestService(&self, _arg_name: &str) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>> { self.0.GetOtherTestService(_arg_name) }
+  fn VerifyName(&self, _arg_service: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>, _arg_name: &str) -> binder::Result<bool> { self.0.VerifyName(_arg_service, _arg_name) }
+  fn GetInterfaceArray(&self, _arg_names: &[String]) -> binder::Result<Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> { self.0.GetInterfaceArray(_arg_names) }
+  fn VerifyNamesWithInterfaceArray(&self, _arg_services: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>], _arg_names: &[String]) -> binder::Result<bool> { self.0.VerifyNamesWithInterfaceArray(_arg_services, _arg_names) }
+  fn GetNullableInterfaceArray(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>> { self.0.GetNullableInterfaceArray(_arg_names) }
+  fn VerifyNamesWithNullableInterfaceArray(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<bool> { self.0.VerifyNamesWithNullableInterfaceArray(_arg_services, _arg_names) }
+  fn GetInterfaceList(&self, _arg_names: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>>> { self.0.GetInterfaceList(_arg_names) }
+  fn VerifyNamesWithInterfaceList(&self, _arg_services: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>]>, _arg_names: Option<&[Option<String>]>) -> binder::Result<bool> { self.0.VerifyNamesWithInterfaceList(_arg_services, _arg_names) }
+  fn ReverseStringList(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>> { self.0.ReverseStringList(_arg_input, _arg_repeated) }
+  fn RepeatParcelFileDescriptor(&self, _arg_read: &binder::ParcelFileDescriptor) -> binder::Result<binder::ParcelFileDescriptor> { self.0.RepeatParcelFileDescriptor(_arg_read) }
+  fn ReverseParcelFileDescriptorArray(&self, _arg_input: &[binder::ParcelFileDescriptor], _arg_repeated: &mut Vec<Option<binder::ParcelFileDescriptor>>) -> binder::Result<Vec<binder::ParcelFileDescriptor>> { self.0.ReverseParcelFileDescriptorArray(_arg_input, _arg_repeated) }
+  fn ThrowServiceException(&self, _arg_code: i32) -> binder::Result<()> { self.0.ThrowServiceException(_arg_code) }
+  fn RepeatNullableIntArray(&self, _arg_input: Option<&[i32]>) -> binder::Result<Option<Vec<i32>>> { self.0.RepeatNullableIntArray(_arg_input) }
+  fn RepeatNullableByteEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum>>> { self.0.RepeatNullableByteEnumArray(_arg_input) }
+  fn RepeatNullableIntEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum>>> { self.0.RepeatNullableIntEnumArray(_arg_input) }
+  fn RepeatNullableLongEnumArray(&self, _arg_input: Option<&[crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum]>) -> binder::Result<Option<Vec<crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum>>> { self.0.RepeatNullableLongEnumArray(_arg_input) }
+  fn RepeatNullableString(&self, _arg_input: Option<&str>) -> binder::Result<Option<String>> { self.0.RepeatNullableString(_arg_input) }
+  fn RepeatNullableStringList(&self, _arg_input: Option<&[Option<String>]>) -> binder::Result<Option<Vec<Option<String>>>> { self.0.RepeatNullableStringList(_arg_input) }
+  fn RepeatNullableParcelable(&self, _arg_input: Option<&crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>) -> binder::Result<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>> { self.0.RepeatNullableParcelable(_arg_input) }
+  fn RepeatNullableParcelableArray(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>> { self.0.RepeatNullableParcelableArray(_arg_input) }
+  fn RepeatNullableParcelableList(&self, _arg_input: Option<&[Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>]>) -> binder::Result<Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>> { self.0.RepeatNullableParcelableList(_arg_input) }
+  fn TakesAnIBinder(&self, _arg_input: &binder::SpIBinder) -> binder::Result<()> { self.0.TakesAnIBinder(_arg_input) }
+  fn TakesANullableIBinder(&self, _arg_input: Option<&binder::SpIBinder>) -> binder::Result<()> { self.0.TakesANullableIBinder(_arg_input) }
+  fn TakesAnIBinderList(&self, _arg_input: &[binder::SpIBinder]) -> binder::Result<()> { self.0.TakesAnIBinderList(_arg_input) }
+  fn TakesANullableIBinderList(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>) -> binder::Result<()> { self.0.TakesANullableIBinderList(_arg_input) }
+  fn RepeatUtf8CppString(&self, _arg_token: &str) -> binder::Result<String> { self.0.RepeatUtf8CppString(_arg_token) }
+  fn RepeatNullableUtf8CppString(&self, _arg_token: Option<&str>) -> binder::Result<Option<String>> { self.0.RepeatNullableUtf8CppString(_arg_token) }
+  fn ReverseUtf8CppString(&self, _arg_input: &[String], _arg_repeated: &mut Vec<String>) -> binder::Result<Vec<String>> { self.0.ReverseUtf8CppString(_arg_input, _arg_repeated) }
+  fn ReverseNullableUtf8CppString(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<Option<Vec<Option<String>>>> { self.0.ReverseNullableUtf8CppString(_arg_input, _arg_repeated) }
+  fn ReverseUtf8CppStringList(&self, _arg_input: Option<&[Option<String>]>, _arg_repeated: &mut Option<Vec<Option<String>>>) -> binder::Result<Option<Vec<Option<String>>>> { self.0.ReverseUtf8CppStringList(_arg_input, _arg_repeated) }
+  fn GetCallback(&self, _arg_return_null: bool) -> binder::Result<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>> { self.0.GetCallback(_arg_return_null) }
+  fn FillOutStructuredParcelable(&self, _arg_parcel: &mut crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable) -> binder::Result<()> { self.0.FillOutStructuredParcelable(_arg_parcel) }
+  fn RepeatExtendableParcelable(&self, _arg_ep: &crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable, _arg_ep2: &mut crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable) -> binder::Result<()> { self.0.RepeatExtendableParcelable(_arg_ep, _arg_ep2) }
+  fn ReverseList(&self, _arg_list: &crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList> { self.0.ReverseList(_arg_list) }
+  fn ReverseIBinderArray(&self, _arg_input: &[binder::SpIBinder], _arg_repeated: &mut Vec<Option<binder::SpIBinder>>) -> binder::Result<Vec<binder::SpIBinder>> { self.0.ReverseIBinderArray(_arg_input, _arg_repeated) }
+  fn ReverseNullableIBinderArray(&self, _arg_input: Option<&[Option<binder::SpIBinder>]>, _arg_repeated: &mut Option<Vec<Option<binder::SpIBinder>>>) -> binder::Result<Option<Vec<Option<binder::SpIBinder>>>> { self.0.ReverseNullableIBinderArray(_arg_input, _arg_repeated) }
+  fn GetOldNameInterface(&self) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_IOldName>> { self.0.GetOldNameInterface() }
+  fn GetNewNameInterface(&self) -> binder::Result<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_8_INewName>> { self.0.GetNewNameInterface() }
+  fn GetCppJavaTests(&self) -> binder::Result<Option<binder::SpIBinder>> { self.0.GetCppJavaTests() }
+  fn getBackendType(&self) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_11_BackendType> { self.0.getBackendType() }
+}
+fn on_transact(_aidl_service: &dyn ITestService, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
   match _aidl_code {
     transactions::UnimplementedMethod => {
       let _arg_arg: i32 = _aidl_data.read()?;
@@ -1648,6 +3570,81 @@
       }
       Ok(())
     }
+    transactions::GetInterfaceArray => {
+      let _arg_names: Vec<String> = _aidl_data.read()?;
+      let _aidl_return = _aidl_service.GetInterfaceArray(&_arg_names);
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          _aidl_reply.write(_aidl_return)?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::VerifyNamesWithInterfaceArray => {
+      let _arg_services: Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>> = _aidl_data.read()?;
+      let _arg_names: Vec<String> = _aidl_data.read()?;
+      let _aidl_return = _aidl_service.VerifyNamesWithInterfaceArray(&_arg_services, &_arg_names);
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          _aidl_reply.write(_aidl_return)?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::GetNullableInterfaceArray => {
+      let _arg_names: Option<Vec<Option<String>>> = _aidl_data.read()?;
+      let _aidl_return = _aidl_service.GetNullableInterfaceArray(_arg_names.as_deref());
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          _aidl_reply.write(_aidl_return)?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::VerifyNamesWithNullableInterfaceArray => {
+      let _arg_services: Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>> = _aidl_data.read()?;
+      let _arg_names: Option<Vec<Option<String>>> = _aidl_data.read()?;
+      let _aidl_return = _aidl_service.VerifyNamesWithNullableInterfaceArray(_arg_services.as_deref(), _arg_names.as_deref());
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          _aidl_reply.write(_aidl_return)?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::GetInterfaceList => {
+      let _arg_names: Option<Vec<Option<String>>> = _aidl_data.read()?;
+      let _aidl_return = _aidl_service.GetInterfaceList(_arg_names.as_deref());
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          _aidl_reply.write(_aidl_return)?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::VerifyNamesWithInterfaceList => {
+      let _arg_services: Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_14_INamedCallback>>>> = _aidl_data.read()?;
+      let _arg_names: Option<Vec<Option<String>>> = _aidl_data.read()?;
+      let _aidl_return = _aidl_service.VerifyNamesWithInterfaceList(_arg_services.as_deref(), _arg_names.as_deref());
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          _aidl_reply.write(_aidl_return)?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
     transactions::ReverseStringList => {
       let _arg_input: Vec<String> = _aidl_data.read()?;
       let mut _arg_repeated: Vec<String> = Default::default();
@@ -1663,7 +3660,7 @@
       Ok(())
     }
     transactions::RepeatParcelFileDescriptor => {
-      let _arg_read: binder::parcel::ParcelFileDescriptor = _aidl_data.read()?;
+      let _arg_read: binder::ParcelFileDescriptor = _aidl_data.read()?;
       let _aidl_return = _aidl_service.RepeatParcelFileDescriptor(&_arg_read);
       match &_aidl_return {
         Ok(_aidl_return) => {
@@ -1675,8 +3672,8 @@
       Ok(())
     }
     transactions::ReverseParcelFileDescriptorArray => {
-      let _arg_input: Vec<binder::parcel::ParcelFileDescriptor> = _aidl_data.read()?;
-      let mut _arg_repeated: Vec<Option<binder::parcel::ParcelFileDescriptor>> = Default::default();
+      let _arg_input: Vec<binder::ParcelFileDescriptor> = _aidl_data.read()?;
+      let mut _arg_repeated: Vec<Option<binder::ParcelFileDescriptor>> = Default::default();
       _aidl_data.resize_out_vec(&mut _arg_repeated)?;
       let _aidl_return = _aidl_service.ReverseParcelFileDescriptorArray(&_arg_input, &mut _arg_repeated);
       match &_aidl_return {
@@ -1774,7 +3771,7 @@
       Ok(())
     }
     transactions::RepeatNullableParcelable => {
-      let _arg_input: Option<crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable> = _aidl_data.read()?;
+      let _arg_input: Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty> = _aidl_data.read()?;
       let _aidl_return = _aidl_service.RepeatNullableParcelable(_arg_input.as_ref());
       match &_aidl_return {
         Ok(_aidl_return) => {
@@ -1785,6 +3782,30 @@
       }
       Ok(())
     }
+    transactions::RepeatNullableParcelableArray => {
+      let _arg_input: Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>> = _aidl_data.read()?;
+      let _aidl_return = _aidl_service.RepeatNullableParcelableArray(_arg_input.as_deref());
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          _aidl_reply.write(_aidl_return)?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::RepeatNullableParcelableList => {
+      let _arg_input: Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>> = _aidl_data.read()?;
+      let _aidl_return = _aidl_service.RepeatNullableParcelableList(_arg_input.as_deref());
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          _aidl_reply.write(_aidl_return)?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
     transactions::TakesAnIBinder => {
       let _arg_input: binder::SpIBinder = _aidl_data.read()?;
       let _aidl_return = _aidl_service.TakesAnIBinder(&_arg_input);
@@ -1807,6 +3828,28 @@
       }
       Ok(())
     }
+    transactions::TakesAnIBinderList => {
+      let _arg_input: Vec<binder::SpIBinder> = _aidl_data.read()?;
+      let _aidl_return = _aidl_service.TakesAnIBinderList(&_arg_input);
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::TakesANullableIBinderList => {
+      let _arg_input: Option<Vec<Option<binder::SpIBinder>>> = _aidl_data.read()?;
+      let _aidl_return = _aidl_service.TakesANullableIBinderList(_arg_input.as_deref());
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
     transactions::RepeatUtf8CppString => {
       let _arg_token: String = _aidl_data.read()?;
       let _aidl_return = _aidl_service.RepeatUtf8CppString(&_arg_token);
@@ -1899,6 +3942,61 @@
       }
       Ok(())
     }
+    transactions::RepeatExtendableParcelable => {
+      let _arg_ep: crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable = _aidl_data.read()?;
+      let mut _arg_ep2: crate::mangled::_7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable = Default::default();
+      let _aidl_return = _aidl_service.RepeatExtendableParcelable(&_arg_ep, &mut _arg_ep2);
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          _aidl_reply.write(&_arg_ep2)?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::ReverseList => {
+      let _arg_list: crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList = _aidl_data.read()?;
+      let _aidl_return = _aidl_service.ReverseList(&_arg_list);
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          _aidl_reply.write(_aidl_return)?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::ReverseIBinderArray => {
+      let _arg_input: Vec<binder::SpIBinder> = _aidl_data.read()?;
+      let mut _arg_repeated: Vec<Option<binder::SpIBinder>> = Default::default();
+      _aidl_data.resize_out_vec(&mut _arg_repeated)?;
+      let _aidl_return = _aidl_service.ReverseIBinderArray(&_arg_input, &mut _arg_repeated);
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          _aidl_reply.write(_aidl_return)?;
+          _aidl_reply.write(&_arg_repeated)?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::ReverseNullableIBinderArray => {
+      let _arg_input: Option<Vec<Option<binder::SpIBinder>>> = _aidl_data.read()?;
+      let mut _arg_repeated: Option<Vec<Option<binder::SpIBinder>>> = Default::default();
+      _aidl_data.resize_nullable_out_vec(&mut _arg_repeated)?;
+      let _aidl_return = _aidl_service.ReverseNullableIBinderArray(_arg_input.as_deref(), &mut _arg_repeated);
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          _aidl_reply.write(_aidl_return)?;
+          _aidl_reply.write(&_arg_repeated)?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
     transactions::GetOldNameInterface => {
       let _aidl_return = _aidl_service.GetOldNameInterface();
       match &_aidl_return {
@@ -1946,3 +4044,174 @@
     _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
   }
 }
+pub mod Empty {
+  #[derive(Debug, Clone, PartialEq)]
+  pub struct Empty {
+  }
+  impl Default for Empty {
+    fn default() -> Self {
+      Self {
+      }
+    }
+  }
+  impl binder::Parcelable for Empty {
+    fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_write(|subparcel| {
+        Ok(())
+      })
+    }
+    fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_read(|subparcel| {
+        Ok(())
+      })
+    }
+  }
+  binder::impl_serialize_for_parcelable!(Empty);
+  binder::impl_deserialize_for_parcelable!(Empty);
+  impl binder::binder_impl::ParcelableMetadata for Empty {
+    fn get_descriptor() -> &'static str { "android.aidl.tests.ITestService.Empty" }
+  }
+}
+pub mod CompilerChecks {
+  #[derive(Debug)]
+  pub struct CompilerChecks {
+    pub binder: Option<binder::SpIBinder>,
+    pub nullable_binder: Option<binder::SpIBinder>,
+    pub binder_array: Vec<binder::SpIBinder>,
+    pub nullable_binder_array: Option<Vec<Option<binder::SpIBinder>>>,
+    pub binder_list: Vec<binder::SpIBinder>,
+    pub nullable_binder_list: Option<Vec<Option<binder::SpIBinder>>>,
+    pub pfd: Option<binder::ParcelFileDescriptor>,
+    pub nullable_pfd: Option<binder::ParcelFileDescriptor>,
+    pub pfd_array: Vec<binder::ParcelFileDescriptor>,
+    pub nullable_pfd_array: Option<Vec<Option<binder::ParcelFileDescriptor>>>,
+    pub pfd_list: Vec<binder::ParcelFileDescriptor>,
+    pub nullable_pfd_list: Option<Vec<Option<binder::ParcelFileDescriptor>>>,
+    pub parcel: crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty,
+    pub nullable_parcel: Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>,
+    pub parcel_array: Vec<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>,
+    pub nullable_parcel_array: Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>,
+    pub parcel_list: Vec<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>,
+    pub nullable_parcel_list: Option<Vec<Option<crate::mangled::_7_android_4_aidl_5_tests_12_ITestService_5_Empty>>>,
+  }
+  impl Default for CompilerChecks {
+    fn default() -> Self {
+      Self {
+        binder: Default::default(),
+        nullable_binder: Default::default(),
+        binder_array: Default::default(),
+        nullable_binder_array: Default::default(),
+        binder_list: Default::default(),
+        nullable_binder_list: Default::default(),
+        pfd: Default::default(),
+        nullable_pfd: Default::default(),
+        pfd_array: Default::default(),
+        nullable_pfd_array: Default::default(),
+        pfd_list: Default::default(),
+        nullable_pfd_list: Default::default(),
+        parcel: Default::default(),
+        nullable_parcel: Default::default(),
+        parcel_array: Default::default(),
+        nullable_parcel_array: Default::default(),
+        parcel_list: Default::default(),
+        nullable_parcel_list: Default::default(),
+      }
+    }
+  }
+  impl binder::Parcelable for CompilerChecks {
+    fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_write(|subparcel| {
+        let __field_ref = self.binder.as_ref().ok_or(binder::StatusCode::UNEXPECTED_NULL)?;
+        subparcel.write(__field_ref)?;
+        subparcel.write(&self.nullable_binder)?;
+        subparcel.write(&self.binder_array)?;
+        subparcel.write(&self.nullable_binder_array)?;
+        subparcel.write(&self.binder_list)?;
+        subparcel.write(&self.nullable_binder_list)?;
+        let __field_ref = self.pfd.as_ref().ok_or(binder::StatusCode::UNEXPECTED_NULL)?;
+        subparcel.write(__field_ref)?;
+        subparcel.write(&self.nullable_pfd)?;
+        subparcel.write(&self.pfd_array)?;
+        subparcel.write(&self.nullable_pfd_array)?;
+        subparcel.write(&self.pfd_list)?;
+        subparcel.write(&self.nullable_pfd_list)?;
+        subparcel.write(&self.parcel)?;
+        subparcel.write(&self.nullable_parcel)?;
+        subparcel.write(&self.parcel_array)?;
+        subparcel.write(&self.nullable_parcel_array)?;
+        subparcel.write(&self.parcel_list)?;
+        subparcel.write(&self.nullable_parcel_list)?;
+        Ok(())
+      })
+    }
+    fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_read(|subparcel| {
+        if subparcel.has_more_data() {
+          self.binder = Some(subparcel.read()?);
+        }
+        if subparcel.has_more_data() {
+          self.nullable_binder = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.binder_array = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.nullable_binder_array = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.binder_list = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.nullable_binder_list = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.pfd = Some(subparcel.read()?);
+        }
+        if subparcel.has_more_data() {
+          self.nullable_pfd = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.pfd_array = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.nullable_pfd_array = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.pfd_list = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.nullable_pfd_list = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.parcel = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.nullable_parcel = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.parcel_array = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.nullable_parcel_array = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.parcel_list = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.nullable_parcel_list = subparcel.read()?;
+        }
+        Ok(())
+      })
+    }
+  }
+  binder::impl_serialize_for_parcelable!(CompilerChecks);
+  binder::impl_deserialize_for_parcelable!(CompilerChecks);
+  impl binder::binder_impl::ParcelableMetadata for CompilerChecks {
+    fn get_descriptor() -> &'static str { "android.aidl.tests.ITestService.CompilerChecks" }
+  }
+}
+pub(crate) mod mangled {
+ pub use super::ITestService as _7_android_4_aidl_5_tests_12_ITestService;
+ pub use super::Empty::Empty as _7_android_4_aidl_5_tests_12_ITestService_5_Empty;
+ pub use super::CompilerChecks::CompilerChecks as _7_android_4_aidl_5_tests_12_ITestService_14_CompilerChecks;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ITestService.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ITestService.rs.d
index 573e399..3f2111f 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ITestService.rs.d
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ITestService.rs.d
@@ -7,4 +7,8 @@
   system/tools/aidl/tests/android/aidl/tests/IOldName.aidl \
   system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
   system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl \
-  system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl
+  system/tools/aidl/tests/android/aidl/tests/RecursiveList.aidl \
+  system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl \
+  system/tools/aidl/tests/android/aidl/tests/extension/ExtendableParcelable.aidl \
+  system/tools/aidl/tests/android/aidl/tests/ConstantExpressionEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/Union.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IntEnum.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IntEnum.rs
index ff9c6a9..5ff4d95 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IntEnum.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/IntEnum.rs
@@ -1,8 +1,14 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 use binder::declare_binder_enum;
-declare_binder_enum! { IntEnum : i32 {
-  FOO = 1000,
-  BAR = 2000,
-  BAZ = 2001,
-} }
-pub(crate) mod mangled { pub use super::IntEnum as _7_android_4_aidl_5_tests_7_IntEnum; }
+declare_binder_enum! {
+  IntEnum : [i32; 3] {
+    FOO = 1000,
+    BAR = 2000,
+    BAZ = 2001,
+  }
+}
+pub(crate) mod mangled {
+ pub use super::IntEnum as _7_android_4_aidl_5_tests_7_IntEnum;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ListOfInterfaces.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ListOfInterfaces.rs
new file mode 100644
index 0000000..274006e
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ListOfInterfaces.rs
@@ -0,0 +1,390 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#[derive(Debug)]
+pub struct ListOfInterfaces {
+}
+impl Default for ListOfInterfaces {
+  fn default() -> Self {
+    Self {
+    }
+  }
+}
+impl binder::Parcelable for ListOfInterfaces {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_write(|subparcel| {
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      Ok(())
+    })
+  }
+}
+binder::impl_serialize_for_parcelable!(ListOfInterfaces);
+binder::impl_deserialize_for_parcelable!(ListOfInterfaces);
+impl binder::binder_impl::ParcelableMetadata for ListOfInterfaces {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.ListOfInterfaces" }
+}
+pub mod IEmptyInterface {
+  #![allow(non_upper_case_globals)]
+  #![allow(non_snake_case)]
+  #[allow(unused_imports)] use binder::binder_impl::IBinderInternal;
+  use binder::declare_binder_interface;
+  declare_binder_interface! {
+    IEmptyInterface["android.aidl.tests.ListOfInterfaces.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.ListOfInterfaces.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.ListOfInterfaces.IEmptyInterface" }
+  }
+  #[::async_trait::async_trait]
+  pub trait IEmptyInterfaceAsyncServer: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.ListOfInterfaces.IEmptyInterface" }
+  }
+  impl BnEmptyInterface {
+    /// Create a new async binder service.
+    pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn IEmptyInterface>
+    where
+      T: IEmptyInterfaceAsyncServer + binder::Interface + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      struct Wrapper<T, R> {
+        _inner: T,
+        _rt: R,
+      }
+      impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+        fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+        fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+      }
+      impl<T, R> IEmptyInterface for Wrapper<T, R>
+      where
+        T: IEmptyInterfaceAsyncServer + Send + Sync + 'static,
+        R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+      {
+      }
+      let wrapped = Wrapper { _inner: inner, _rt: rt };
+      Self::new_binder(wrapped, features)
+    }
+  }
+  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_impl::Binder<BnEmptyInterface> {
+  }
+  fn on_transact(_aidl_service: &dyn IEmptyInterface, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
+    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::binder_impl::IBinderInternal;
+  use binder::declare_binder_interface;
+  declare_binder_interface! {
+    IMyInterface["android.aidl.tests.ListOfInterfaces.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.ListOfInterfaces.IMyInterface" }
+    fn methodWithInterfaces(&self, _arg_iface: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_iface_list_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>], _arg_iface_list_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>, _arg_iface_list_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_list_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_list_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_list_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_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.ListOfInterfaces.IMyInterface" }
+    fn methodWithInterfaces<'a>(&'a self, _arg_iface: &'a binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&'a binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_iface_list_in: &'a [binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>], _arg_iface_list_out: &'a mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>, _arg_iface_list_inout: &'a mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_list_in: Option<&'a [Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_list_out: &'a mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_list_inout: &'a mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>>>;
+  }
+  #[::async_trait::async_trait]
+  pub trait IMyInterfaceAsyncServer: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.ListOfInterfaces.IMyInterface" }
+    async fn methodWithInterfaces(&self, _arg_iface: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_iface_list_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>], _arg_iface_list_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>, _arg_iface_list_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_list_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_list_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_list_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>>;
+  }
+  impl BnMyInterface {
+    /// Create a new async binder service.
+    pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn IMyInterface>
+    where
+      T: IMyInterfaceAsyncServer + binder::Interface + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      struct Wrapper<T, R> {
+        _inner: T,
+        _rt: R,
+      }
+      impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+        fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+        fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+      }
+      impl<T, R> IMyInterface for Wrapper<T, R>
+      where
+        T: IMyInterfaceAsyncServer + Send + Sync + 'static,
+        R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+      {
+        fn methodWithInterfaces(&self, _arg_iface: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_iface_list_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>], _arg_iface_list_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>, _arg_iface_list_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_list_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_list_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_list_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>> {
+          self._rt.block_on(self._inner.methodWithInterfaces(_arg_iface, _arg_nullable_iface, _arg_iface_list_in, _arg_iface_list_out, _arg_iface_list_inout, _arg_nullable_iface_list_in, _arg_nullable_iface_list_out, _arg_nullable_iface_list_inout))
+        }
+      }
+      let wrapped = Wrapper { _inner: inner, _rt: rt };
+      Self::new_binder(wrapped, features)
+    }
+  }
+  pub trait IMyInterfaceDefault: Send + Sync {
+    fn methodWithInterfaces(&self, _arg_iface: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_iface_list_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>], _arg_iface_list_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>, _arg_iface_list_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_list_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_list_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_list_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>> {
+      Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+    }
+  }
+  pub mod transactions {
+    pub const methodWithInterfaces: binder::binder_impl::TransactionCode = binder::binder_impl::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_16_ListOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_iface_list_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>], _arg_iface_list_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>, _arg_iface_list_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_list_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_list_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_list_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>) -> binder::Result<binder::binder_impl::Parcel> {
+      let mut aidl_data = self.binder.prepare_transact()?;
+      aidl_data.write(_arg_iface)?;
+      aidl_data.write(&_arg_nullable_iface)?;
+      aidl_data.write(_arg_iface_list_in)?;
+      aidl_data.write(_arg_iface_list_inout)?;
+      aidl_data.write(&_arg_nullable_iface_list_in)?;
+      aidl_data.write(_arg_nullable_iface_list_inout)?;
+      Ok(aidl_data)
+    }
+    fn read_response_methodWithInterfaces(&self, _arg_iface: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_iface_list_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>], _arg_iface_list_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>, _arg_iface_list_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_list_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_list_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_list_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_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_list_in, _arg_iface_list_out, _arg_iface_list_inout, _arg_nullable_iface_list_in, _arg_nullable_iface_list_out, _arg_nullable_iface_list_inout);
+        }
+      }
+      let _aidl_reply = _aidl_reply?;
+      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_16_ListOfInterfaces_15_IEmptyInterface>>>> = _aidl_reply.read()?;
+      _aidl_reply.read_onto(_arg_iface_list_out)?;
+      _aidl_reply.read_onto(_arg_iface_list_inout)?;
+      _aidl_reply.read_onto(_arg_nullable_iface_list_out)?;
+      _aidl_reply.read_onto(_arg_nullable_iface_list_inout)?;
+      Ok(_aidl_return)
+    }
+  }
+  impl IMyInterface for BpMyInterface {
+    fn methodWithInterfaces(&self, _arg_iface: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_iface_list_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>], _arg_iface_list_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>, _arg_iface_list_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_list_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_list_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_list_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>> {
+      let _aidl_data = self.build_parcel_methodWithInterfaces(_arg_iface, _arg_nullable_iface, _arg_iface_list_in, _arg_iface_list_out, _arg_iface_list_inout, _arg_nullable_iface_list_in, _arg_nullable_iface_list_out, _arg_nullable_iface_list_inout)?;
+      let _aidl_reply = self.binder.submit_transact(transactions::methodWithInterfaces, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+      self.read_response_methodWithInterfaces(_arg_iface, _arg_nullable_iface, _arg_iface_list_in, _arg_iface_list_out, _arg_iface_list_inout, _arg_nullable_iface_list_in, _arg_nullable_iface_list_out, _arg_nullable_iface_list_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_16_ListOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&'a binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_iface_list_in: &'a [binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>], _arg_iface_list_out: &'a mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>, _arg_iface_list_inout: &'a mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_list_in: Option<&'a [Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_list_out: &'a mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_list_inout: &'a mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>) -> binder::BoxFuture<'a, binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>>> {
+      let _aidl_data = match self.build_parcel_methodWithInterfaces(_arg_iface, _arg_nullable_iface, _arg_iface_list_in, _arg_iface_list_out, _arg_iface_list_inout, _arg_nullable_iface_list_in, _arg_nullable_iface_list_out, _arg_nullable_iface_list_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::binder_impl::FLAG_PRIVATE_LOCAL),
+        move |_aidl_reply| async move {
+          self.read_response_methodWithInterfaces(_arg_iface, _arg_nullable_iface, _arg_iface_list_in, _arg_iface_list_out, _arg_iface_list_inout, _arg_nullable_iface_list_in, _arg_nullable_iface_list_out, _arg_nullable_iface_list_inout, _aidl_reply)
+        }
+      )
+    }
+  }
+  impl IMyInterface for binder::binder_impl::Binder<BnMyInterface> {
+    fn methodWithInterfaces(&self, _arg_iface: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>, _arg_nullable_iface: Option<&binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_iface_list_in: &[binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>], _arg_iface_list_out: &mut Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>, _arg_iface_list_inout: &mut Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>, _arg_nullable_iface_list_in: Option<&[Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>]>, _arg_nullable_iface_list_out: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>, _arg_nullable_iface_list_inout: &mut Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>) -> binder::Result<Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>> { self.0.methodWithInterfaces(_arg_iface, _arg_nullable_iface, _arg_iface_list_in, _arg_iface_list_out, _arg_iface_list_inout, _arg_nullable_iface_list_in, _arg_nullable_iface_list_out, _arg_nullable_iface_list_inout) }
+  }
+  fn on_transact(_aidl_service: &dyn IMyInterface, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
+    match _aidl_code {
+      transactions::methodWithInterfaces => {
+        let _arg_iface: binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface> = _aidl_data.read()?;
+        let _arg_nullable_iface: Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>> = _aidl_data.read()?;
+        let _arg_iface_list_in: Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>> = _aidl_data.read()?;
+        let mut _arg_iface_list_out: Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>> = Default::default();
+        let mut _arg_iface_list_inout: Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>> = _aidl_data.read()?;
+        let _arg_nullable_iface_list_in: Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>> = _aidl_data.read()?;
+        let mut _arg_nullable_iface_list_out: Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>> = Default::default();
+        let mut _arg_nullable_iface_list_inout: Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>> = _aidl_data.read()?;
+        let _aidl_return = _aidl_service.methodWithInterfaces(&_arg_iface, _arg_nullable_iface.as_ref(), &_arg_iface_list_in, &mut _arg_iface_list_out, &mut _arg_iface_list_inout, _arg_nullable_iface_list_in.as_deref(), &mut _arg_nullable_iface_list_out, &mut _arg_nullable_iface_list_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_list_out)?;
+            _aidl_reply.write(&_arg_iface_list_inout)?;
+            _aidl_reply.write(&_arg_nullable_iface_list_out)?;
+            _aidl_reply.write(&_arg_nullable_iface_list_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_16_ListOfInterfaces_15_IEmptyInterface>>,
+    pub nullable_iface: Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>,
+    pub iface_list: Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>,
+    pub nullable_iface_list: Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>,
+  }
+  impl Default for MyParcelable {
+    fn default() -> Self {
+      Self {
+        iface: Default::default(),
+        nullable_iface: Default::default(),
+        iface_list: Default::default(),
+        nullable_iface_list: Default::default(),
+      }
+    }
+  }
+  impl binder::Parcelable for MyParcelable {
+    fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      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_list)?;
+        subparcel.write(&self.nullable_iface_list)?;
+        Ok(())
+      })
+    }
+    fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      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_list = subparcel.read()?;
+        }
+        if subparcel.has_more_data() {
+          self.nullable_iface_list = subparcel.read()?;
+        }
+        Ok(())
+      })
+    }
+  }
+  binder::impl_serialize_for_parcelable!(MyParcelable);
+  binder::impl_deserialize_for_parcelable!(MyParcelable);
+  impl binder::binder_impl::ParcelableMetadata for MyParcelable {
+    fn get_descriptor() -> &'static str { "android.aidl.tests.ListOfInterfaces.MyParcelable" }
+  }
+}
+pub mod MyUnion {
+  #[derive(Debug)]
+  pub enum MyUnion {
+    Iface(Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>),
+    Nullable_iface(Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>),
+    Iface_list(Vec<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>),
+    Nullable_iface_list(Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>>),
+  }
+  impl Default for MyUnion {
+    fn default() -> Self {
+      Self::Iface(Default::default())
+    }
+  }
+  impl binder::Parcelable for MyUnion {
+    fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      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_list(v) => {
+          parcel.write(&2i32)?;
+          parcel.write(v)
+        }
+        Self::Nullable_iface_list(v) => {
+          parcel.write(&3i32)?;
+          parcel.write(v)
+        }
+      }
+    }
+    fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      let tag: i32 = parcel.read()?;
+      match tag {
+        0 => {
+          let value: Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_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_16_ListOfInterfaces_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_16_ListOfInterfaces_15_IEmptyInterface>> = parcel.read()?;
+          *self = Self::Iface_list(value);
+          Ok(())
+        }
+        3 => {
+          let value: Option<Vec<Option<binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface>>>> = parcel.read()?;
+          *self = Self::Nullable_iface_list(value);
+          Ok(())
+        }
+        _ => {
+          Err(binder::StatusCode::BAD_VALUE)
+        }
+      }
+    }
+  }
+  binder::impl_serialize_for_parcelable!(MyUnion);
+  binder::impl_deserialize_for_parcelable!(MyUnion);
+  impl binder::binder_impl::ParcelableMetadata for MyUnion {
+    fn get_descriptor() -> &'static str { "android.aidl.tests.ListOfInterfaces.MyUnion" }
+  }
+}
+pub(crate) mod mangled {
+ pub use super::ListOfInterfaces as _7_android_4_aidl_5_tests_16_ListOfInterfaces;
+ pub use super::IEmptyInterface::IEmptyInterface as _7_android_4_aidl_5_tests_16_ListOfInterfaces_15_IEmptyInterface;
+ pub use super::IMyInterface::IMyInterface as _7_android_4_aidl_5_tests_16_ListOfInterfaces_12_IMyInterface;
+ pub use super::MyParcelable::MyParcelable as _7_android_4_aidl_5_tests_16_ListOfInterfaces_12_MyParcelable;
+ pub use super::MyUnion::MyUnion as _7_android_4_aidl_5_tests_16_ListOfInterfaces_7_MyUnion;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ListOfInterfaces.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ListOfInterfaces.rs.d
new file mode 100644
index 0000000..b965c9a
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ListOfInterfaces.rs.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/ListOfInterfaces.rs : \
+  system/tools/aidl/tests/android/aidl/tests/ListOfInterfaces.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/LongEnum.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/LongEnum.rs
index 548b711..ae93821 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/LongEnum.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/LongEnum.rs
@@ -1,8 +1,14 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #![allow(non_upper_case_globals)]
 use binder::declare_binder_enum;
-declare_binder_enum! { LongEnum : i64 {
-  FOO = 100000000000,
-  BAR = 200000000000,
-  BAZ = 200000000001,
-} }
-pub(crate) mod mangled { pub use super::LongEnum as _7_android_4_aidl_5_tests_8_LongEnum; }
+declare_binder_enum! {
+  LongEnum : [i64; 3] {
+    FOO = 100000000000,
+    BAR = 200000000000,
+    BAZ = 200000000001,
+  }
+}
+pub(crate) mod mangled {
+ pub use super::LongEnum as _7_android_4_aidl_5_tests_8_LongEnum;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/OtherParcelableForToString.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/OtherParcelableForToString.rs
index d57775f..0facb4b 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/OtherParcelableForToString.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/OtherParcelableForToString.rs
@@ -1,8 +1,9 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #[derive(Debug)]
 pub struct OtherParcelableForToString {
   pub field: String,
 }
-pub(crate) mod mangled { pub use super::OtherParcelableForToString as _7_android_4_aidl_5_tests_26_OtherParcelableForToString; }
 impl Default for OtherParcelableForToString {
   fn default() -> Self {
     Self {
@@ -10,52 +11,27 @@
     }
   }
 }
-impl binder::parcel::Serialize for OtherParcelableForToString {
-  fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-  }
-}
-impl binder::parcel::SerializeArray for OtherParcelableForToString {}
-impl binder::parcel::SerializeOption for OtherParcelableForToString {
-  fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    let this = if let Some(this) = this {
-      parcel.write(&1i32)?;
-      this
-    } else {
-      return parcel.write(&0i32);
-    };
+impl binder::Parcelable for OtherParcelableForToString {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
     parcel.sized_write(|subparcel| {
-      subparcel.write(&this.field)?;
+      subparcel.write(&self.field)?;
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      if subparcel.has_more_data() {
+        self.field = subparcel.read()?;
+      }
       Ok(())
     })
   }
 }
-impl binder::parcel::Deserialize for OtherParcelableForToString {
-  fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-    <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-       .transpose()
-       .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-  }
+binder::impl_serialize_for_parcelable!(OtherParcelableForToString);
+binder::impl_deserialize_for_parcelable!(OtherParcelableForToString);
+impl binder::binder_impl::ParcelableMetadata for OtherParcelableForToString {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.OtherParcelableForToString" }
 }
-impl binder::parcel::DeserializeArray for OtherParcelableForToString {}
-impl binder::parcel::DeserializeOption for OtherParcelableForToString {
-  fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-    let status: i32 = parcel.read()?;
-    if status == 0 { return Ok(None); }
-    let start_pos = parcel.get_data_position();
-    let parcelable_size: i32 = parcel.read()?;
-    if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-    if start_pos.checked_add(parcelable_size).is_none() {
-      return Err(binder::StatusCode::BAD_VALUE);
-    }
-    let mut result = Self::default();
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.field = parcel.read()?;
-    unsafe {
-      parcel.set_data_position(start_pos + parcelable_size)?;
-    }
-    Ok(Some(result))
-  }
+pub(crate) mod mangled {
+ pub use super::OtherParcelableForToString as _7_android_4_aidl_5_tests_26_OtherParcelableForToString;
 }
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ParcelableForToString.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ParcelableForToString.rs
index 58b7d28..753ba36 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ParcelableForToString.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ParcelableForToString.rs
@@ -1,3 +1,5 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #[derive(Debug)]
 pub struct ParcelableForToString {
   pub intValue: i32,
@@ -24,7 +26,6 @@
   pub parcelableGeneric: i32,
   pub unionValue: crate::mangled::_7_android_4_aidl_5_tests_5_Union,
 }
-pub(crate) mod mangled { pub use super::ParcelableForToString as _7_android_4_aidl_5_tests_21_ParcelableForToString; }
 impl Default for ParcelableForToString {
   fn default() -> Self {
     Self {
@@ -54,162 +55,115 @@
     }
   }
 }
-impl binder::parcel::Serialize for ParcelableForToString {
-  fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-  }
-}
-impl binder::parcel::SerializeArray for ParcelableForToString {}
-impl binder::parcel::SerializeOption for ParcelableForToString {
-  fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    let this = if let Some(this) = this {
-      parcel.write(&1i32)?;
-      this
-    } else {
-      return parcel.write(&0i32);
-    };
+impl binder::Parcelable for ParcelableForToString {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
     parcel.sized_write(|subparcel| {
-      subparcel.write(&this.intValue)?;
-      subparcel.write(&this.intArray)?;
-      subparcel.write(&this.longValue)?;
-      subparcel.write(&this.longArray)?;
-      subparcel.write(&this.doubleValue)?;
-      subparcel.write(&this.doubleArray)?;
-      subparcel.write(&this.floatValue)?;
-      subparcel.write(&this.floatArray)?;
-      subparcel.write(&this.byteValue)?;
-      subparcel.write(&this.byteArray)?;
-      subparcel.write(&this.booleanValue)?;
-      subparcel.write(&this.booleanArray)?;
-      subparcel.write(&this.stringValue)?;
-      subparcel.write(&this.stringArray)?;
-      subparcel.write(&this.stringList)?;
-      subparcel.write(&this.parcelableValue)?;
-      subparcel.write(&this.parcelableArray)?;
-      subparcel.write(&this.enumValue)?;
-      subparcel.write(&this.enumArray)?;
-      subparcel.write(&this.nullArray)?;
-      subparcel.write(&this.nullList)?;
-      subparcel.write(&this.parcelableGeneric)?;
-      subparcel.write(&this.unionValue)?;
+      subparcel.write(&self.intValue)?;
+      subparcel.write(&self.intArray)?;
+      subparcel.write(&self.longValue)?;
+      subparcel.write(&self.longArray)?;
+      subparcel.write(&self.doubleValue)?;
+      subparcel.write(&self.doubleArray)?;
+      subparcel.write(&self.floatValue)?;
+      subparcel.write(&self.floatArray)?;
+      subparcel.write(&self.byteValue)?;
+      subparcel.write(&self.byteArray)?;
+      subparcel.write(&self.booleanValue)?;
+      subparcel.write(&self.booleanArray)?;
+      subparcel.write(&self.stringValue)?;
+      subparcel.write(&self.stringArray)?;
+      subparcel.write(&self.stringList)?;
+      subparcel.write(&self.parcelableValue)?;
+      subparcel.write(&self.parcelableArray)?;
+      subparcel.write(&self.enumValue)?;
+      subparcel.write(&self.enumArray)?;
+      subparcel.write(&self.nullArray)?;
+      subparcel.write(&self.nullList)?;
+      subparcel.write(&self.parcelableGeneric)?;
+      subparcel.write(&self.unionValue)?;
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      if subparcel.has_more_data() {
+        self.intValue = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.intArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.longValue = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.longArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.doubleValue = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.doubleArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.floatValue = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.floatArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.byteValue = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.byteArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.booleanValue = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.booleanArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.stringValue = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.stringArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.stringList = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.parcelableValue = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.parcelableArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.enumValue = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.enumArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.nullArray = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.nullList = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.parcelableGeneric = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.unionValue = subparcel.read()?;
+      }
       Ok(())
     })
   }
 }
-impl binder::parcel::Deserialize for ParcelableForToString {
-  fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-    <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-       .transpose()
-       .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-  }
+binder::impl_serialize_for_parcelable!(ParcelableForToString);
+binder::impl_deserialize_for_parcelable!(ParcelableForToString);
+impl binder::binder_impl::ParcelableMetadata for ParcelableForToString {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.ParcelableForToString" }
 }
-impl binder::parcel::DeserializeArray for ParcelableForToString {}
-impl binder::parcel::DeserializeOption for ParcelableForToString {
-  fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-    let status: i32 = parcel.read()?;
-    if status == 0 { return Ok(None); }
-    let start_pos = parcel.get_data_position();
-    let parcelable_size: i32 = parcel.read()?;
-    if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-    if start_pos.checked_add(parcelable_size).is_none() {
-      return Err(binder::StatusCode::BAD_VALUE);
-    }
-    let mut result = Self::default();
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.intValue = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.intArray = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.longValue = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.longArray = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.doubleValue = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.doubleArray = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.floatValue = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.floatArray = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.byteValue = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.byteArray = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.booleanValue = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.booleanArray = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.stringValue = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.stringArray = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.stringList = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.parcelableValue = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.parcelableArray = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.enumValue = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.enumArray = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.nullArray = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.nullList = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.parcelableGeneric = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.unionValue = parcel.read()?;
-    unsafe {
-      parcel.set_data_position(start_pos + parcelable_size)?;
-    }
-    Ok(Some(result))
-  }
+pub(crate) mod mangled {
+ pub use super::ParcelableForToString as _7_android_4_aidl_5_tests_21_ParcelableForToString;
 }
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ParcelableForToString.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ParcelableForToString.rs.d
index de46179..5471bd0 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ParcelableForToString.rs.d
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/ParcelableForToString.rs.d
@@ -4,4 +4,7 @@
   system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
   system/tools/aidl/tests/android/aidl/tests/OtherParcelableForToString.aidl \
   system/tools/aidl/tests/android/aidl/tests/StructuredParcelable.aidl \
-  system/tools/aidl/tests/android/aidl/tests/Union.aidl
+  system/tools/aidl/tests/android/aidl/tests/Union.aidl \
+  system/tools/aidl/tests/android/aidl/tests/ByteEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/ConstantExpressionEnum.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/RecursiveList.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/RecursiveList.rs
new file mode 100644
index 0000000..d03f48e
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/RecursiveList.rs
@@ -0,0 +1,43 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#[derive(Debug)]
+pub struct RecursiveList {
+  pub value: i32,
+  pub next: Option<Box<crate::mangled::_7_android_4_aidl_5_tests_13_RecursiveList>>,
+}
+impl Default for RecursiveList {
+  fn default() -> Self {
+    Self {
+      value: 0,
+      next: Default::default(),
+    }
+  }
+}
+impl binder::Parcelable for RecursiveList {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_write(|subparcel| {
+      subparcel.write(&self.value)?;
+      subparcel.write(&self.next)?;
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      if subparcel.has_more_data() {
+        self.value = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.next = subparcel.read()?;
+      }
+      Ok(())
+    })
+  }
+}
+binder::impl_serialize_for_parcelable!(RecursiveList);
+binder::impl_deserialize_for_parcelable!(RecursiveList);
+impl binder::binder_impl::ParcelableMetadata for RecursiveList {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.RecursiveList" }
+}
+pub(crate) mod mangled {
+ pub use super::RecursiveList as _7_android_4_aidl_5_tests_13_RecursiveList;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/RecursiveList.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/RecursiveList.rs.d
new file mode 100644
index 0000000..f0dd6cf
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/RecursiveList.rs.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/RecursiveList.rs : \
+  system/tools/aidl/tests/android/aidl/tests/RecursiveList.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/StructuredParcelable.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/StructuredParcelable.rs
index 72bc998..df666b3 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/StructuredParcelable.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/StructuredParcelable.rs
@@ -1,3 +1,5 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #[derive(Debug, Clone, PartialEq)]
 pub struct StructuredParcelable {
   pub shouldContainThreeFs: Vec<i32>,
@@ -33,6 +35,8 @@
   pub int64_max: i64,
   pub hexInt32_neg_1: i32,
   pub ibinder: Option<binder::SpIBinder>,
+  pub empty: crate::mangled::_7_android_4_aidl_5_tests_20_StructuredParcelable_5_Empty,
+  pub int8_1: Vec<u8>,
   pub int32_1: Vec<i32>,
   pub int64_1: Vec<i64>,
   pub hexInt32_pos_1: i32,
@@ -57,7 +61,6 @@
 pub const BIT0: i32 = 1;
 pub const BIT1: i32 = 2;
 pub const BIT2: i32 = 4;
-pub(crate) mod mangled { pub use super::StructuredParcelable as _7_android_4_aidl_5_tests_20_StructuredParcelable; }
 impl Default for StructuredParcelable {
   fn default() -> Self {
     Self {
@@ -78,8 +81,8 @@
       charDefaultsToC: 'C' as u16,
       floatDefaultsToPi: 3.140000f32,
       doubleWithDefault: -314000000000000000.000000f64,
-      arrayDefaultsTo123: vec!{1, 2, 3},
-      arrayDefaultsToEmpty: vec!{},
+      arrayDefaultsTo123: vec![1, 2, 3],
+      arrayDefaultsToEmpty: vec![],
       boolDefault: false,
       byteDefault: 0,
       intDefault: 0,
@@ -87,15 +90,17 @@
       floatDefault: 0.000000f32,
       doubleDefault: 0.000000f64,
       checkDoubleFromFloat: 3.140000f64,
-      checkStringArray1: vec!{"a".into(), "b".into()},
-      checkStringArray2: vec!{"a".into(), "b".into()},
+      checkStringArray1: vec!["a".into(), "b".into()],
+      checkStringArray2: vec!["a".into(), "b".into()],
       int32_min: -2147483648,
       int32_max: 2147483647,
       int64_max: 9223372036854775807,
       hexInt32_neg_1: -1,
       ibinder: Default::default(),
-      int32_1: vec!{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
-      int64_1: vec!{1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
+      empty: Default::default(),
+      int8_1: vec![1, 1, 1, 1, 1],
+      int32_1: vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
+      int64_1: vec![1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
       hexInt32_pos_1: 1,
       hexInt64_pos_1: 1,
       const_exprs_1: Default::default(),
@@ -117,312 +122,272 @@
     }
   }
 }
-impl binder::parcel::Serialize for StructuredParcelable {
-  fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-  }
-}
-impl binder::parcel::SerializeArray for StructuredParcelable {}
-impl binder::parcel::SerializeOption for StructuredParcelable {
-  fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    let this = if let Some(this) = this {
-      parcel.write(&1i32)?;
-      this
-    } else {
-      return parcel.write(&0i32);
-    };
+impl binder::Parcelable for StructuredParcelable {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
     parcel.sized_write(|subparcel| {
-      subparcel.write(&this.shouldContainThreeFs)?;
-      subparcel.write(&this.f)?;
-      subparcel.write(&this.shouldBeJerry)?;
-      subparcel.write(&this.shouldBeByteBar)?;
-      subparcel.write(&this.shouldBeIntBar)?;
-      subparcel.write(&this.shouldBeLongBar)?;
-      subparcel.write(&this.shouldContainTwoByteFoos)?;
-      subparcel.write(&this.shouldContainTwoIntFoos)?;
-      subparcel.write(&this.shouldContainTwoLongFoos)?;
-      subparcel.write(&this.stringDefaultsToFoo)?;
-      subparcel.write(&this.byteDefaultsToFour)?;
-      subparcel.write(&this.intDefaultsToFive)?;
-      subparcel.write(&this.longDefaultsToNegativeSeven)?;
-      subparcel.write(&this.booleanDefaultsToTrue)?;
-      subparcel.write(&this.charDefaultsToC)?;
-      subparcel.write(&this.floatDefaultsToPi)?;
-      subparcel.write(&this.doubleWithDefault)?;
-      subparcel.write(&this.arrayDefaultsTo123)?;
-      subparcel.write(&this.arrayDefaultsToEmpty)?;
-      subparcel.write(&this.boolDefault)?;
-      subparcel.write(&this.byteDefault)?;
-      subparcel.write(&this.intDefault)?;
-      subparcel.write(&this.longDefault)?;
-      subparcel.write(&this.floatDefault)?;
-      subparcel.write(&this.doubleDefault)?;
-      subparcel.write(&this.checkDoubleFromFloat)?;
-      subparcel.write(&this.checkStringArray1)?;
-      subparcel.write(&this.checkStringArray2)?;
-      subparcel.write(&this.int32_min)?;
-      subparcel.write(&this.int32_max)?;
-      subparcel.write(&this.int64_max)?;
-      subparcel.write(&this.hexInt32_neg_1)?;
-      subparcel.write(&this.ibinder)?;
-      subparcel.write(&this.int32_1)?;
-      subparcel.write(&this.int64_1)?;
-      subparcel.write(&this.hexInt32_pos_1)?;
-      subparcel.write(&this.hexInt64_pos_1)?;
-      subparcel.write(&this.const_exprs_1)?;
-      subparcel.write(&this.const_exprs_2)?;
-      subparcel.write(&this.const_exprs_3)?;
-      subparcel.write(&this.const_exprs_4)?;
-      subparcel.write(&this.const_exprs_5)?;
-      subparcel.write(&this.const_exprs_6)?;
-      subparcel.write(&this.const_exprs_7)?;
-      subparcel.write(&this.const_exprs_8)?;
-      subparcel.write(&this.const_exprs_9)?;
-      subparcel.write(&this.const_exprs_10)?;
-      subparcel.write(&this.addString1)?;
-      subparcel.write(&this.addString2)?;
-      subparcel.write(&this.shouldSetBit0AndBit2)?;
-      subparcel.write(&this.u)?;
-      subparcel.write(&this.shouldBeConstS1)?;
-      subparcel.write(&this.defaultWithFoo)?;
+      subparcel.write(&self.shouldContainThreeFs)?;
+      subparcel.write(&self.f)?;
+      subparcel.write(&self.shouldBeJerry)?;
+      subparcel.write(&self.shouldBeByteBar)?;
+      subparcel.write(&self.shouldBeIntBar)?;
+      subparcel.write(&self.shouldBeLongBar)?;
+      subparcel.write(&self.shouldContainTwoByteFoos)?;
+      subparcel.write(&self.shouldContainTwoIntFoos)?;
+      subparcel.write(&self.shouldContainTwoLongFoos)?;
+      subparcel.write(&self.stringDefaultsToFoo)?;
+      subparcel.write(&self.byteDefaultsToFour)?;
+      subparcel.write(&self.intDefaultsToFive)?;
+      subparcel.write(&self.longDefaultsToNegativeSeven)?;
+      subparcel.write(&self.booleanDefaultsToTrue)?;
+      subparcel.write(&self.charDefaultsToC)?;
+      subparcel.write(&self.floatDefaultsToPi)?;
+      subparcel.write(&self.doubleWithDefault)?;
+      subparcel.write(&self.arrayDefaultsTo123)?;
+      subparcel.write(&self.arrayDefaultsToEmpty)?;
+      subparcel.write(&self.boolDefault)?;
+      subparcel.write(&self.byteDefault)?;
+      subparcel.write(&self.intDefault)?;
+      subparcel.write(&self.longDefault)?;
+      subparcel.write(&self.floatDefault)?;
+      subparcel.write(&self.doubleDefault)?;
+      subparcel.write(&self.checkDoubleFromFloat)?;
+      subparcel.write(&self.checkStringArray1)?;
+      subparcel.write(&self.checkStringArray2)?;
+      subparcel.write(&self.int32_min)?;
+      subparcel.write(&self.int32_max)?;
+      subparcel.write(&self.int64_max)?;
+      subparcel.write(&self.hexInt32_neg_1)?;
+      subparcel.write(&self.ibinder)?;
+      subparcel.write(&self.empty)?;
+      subparcel.write(&self.int8_1)?;
+      subparcel.write(&self.int32_1)?;
+      subparcel.write(&self.int64_1)?;
+      subparcel.write(&self.hexInt32_pos_1)?;
+      subparcel.write(&self.hexInt64_pos_1)?;
+      subparcel.write(&self.const_exprs_1)?;
+      subparcel.write(&self.const_exprs_2)?;
+      subparcel.write(&self.const_exprs_3)?;
+      subparcel.write(&self.const_exprs_4)?;
+      subparcel.write(&self.const_exprs_5)?;
+      subparcel.write(&self.const_exprs_6)?;
+      subparcel.write(&self.const_exprs_7)?;
+      subparcel.write(&self.const_exprs_8)?;
+      subparcel.write(&self.const_exprs_9)?;
+      subparcel.write(&self.const_exprs_10)?;
+      subparcel.write(&self.addString1)?;
+      subparcel.write(&self.addString2)?;
+      subparcel.write(&self.shouldSetBit0AndBit2)?;
+      subparcel.write(&self.u)?;
+      subparcel.write(&self.shouldBeConstS1)?;
+      subparcel.write(&self.defaultWithFoo)?;
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      if subparcel.has_more_data() {
+        self.shouldContainThreeFs = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.f = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.shouldBeJerry = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.shouldBeByteBar = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.shouldBeIntBar = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.shouldBeLongBar = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.shouldContainTwoByteFoos = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.shouldContainTwoIntFoos = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.shouldContainTwoLongFoos = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.stringDefaultsToFoo = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.byteDefaultsToFour = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.intDefaultsToFive = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.longDefaultsToNegativeSeven = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.booleanDefaultsToTrue = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.charDefaultsToC = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.floatDefaultsToPi = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.doubleWithDefault = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.arrayDefaultsTo123 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.arrayDefaultsToEmpty = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.boolDefault = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.byteDefault = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.intDefault = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.longDefault = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.floatDefault = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.doubleDefault = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.checkDoubleFromFloat = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.checkStringArray1 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.checkStringArray2 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.int32_min = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.int32_max = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.int64_max = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.hexInt32_neg_1 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.ibinder = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.empty = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.int8_1 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.int32_1 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.int64_1 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.hexInt32_pos_1 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.hexInt64_pos_1 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.const_exprs_1 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.const_exprs_2 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.const_exprs_3 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.const_exprs_4 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.const_exprs_5 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.const_exprs_6 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.const_exprs_7 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.const_exprs_8 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.const_exprs_9 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.const_exprs_10 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.addString1 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.addString2 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.shouldSetBit0AndBit2 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.u = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.shouldBeConstS1 = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.defaultWithFoo = subparcel.read()?;
+      }
       Ok(())
     })
   }
 }
-impl binder::parcel::Deserialize for StructuredParcelable {
-  fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-    <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-       .transpose()
-       .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
+binder::impl_serialize_for_parcelable!(StructuredParcelable);
+binder::impl_deserialize_for_parcelable!(StructuredParcelable);
+impl binder::binder_impl::ParcelableMetadata for StructuredParcelable {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.StructuredParcelable" }
+}
+pub mod Empty {
+  #[derive(Debug, Clone, PartialEq)]
+  pub struct Empty {
+  }
+  impl Default for Empty {
+    fn default() -> Self {
+      Self {
+      }
+    }
+  }
+  impl binder::Parcelable for Empty {
+    fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_write(|subparcel| {
+        Ok(())
+      })
+    }
+    fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_read(|subparcel| {
+        Ok(())
+      })
+    }
+  }
+  binder::impl_serialize_for_parcelable!(Empty);
+  binder::impl_deserialize_for_parcelable!(Empty);
+  impl binder::binder_impl::ParcelableMetadata for Empty {
+    fn get_descriptor() -> &'static str { "android.aidl.tests.StructuredParcelable.Empty" }
   }
 }
-impl binder::parcel::DeserializeArray for StructuredParcelable {}
-impl binder::parcel::DeserializeOption for StructuredParcelable {
-  fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-    let status: i32 = parcel.read()?;
-    if status == 0 { return Ok(None); }
-    let start_pos = parcel.get_data_position();
-    let parcelable_size: i32 = parcel.read()?;
-    if parcelable_size < 0 { return Err(binder::StatusCode::BAD_VALUE); }
-    if start_pos.checked_add(parcelable_size).is_none() {
-      return Err(binder::StatusCode::BAD_VALUE);
-    }
-    let mut result = Self::default();
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.shouldContainThreeFs = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.f = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.shouldBeJerry = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.shouldBeByteBar = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.shouldBeIntBar = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.shouldBeLongBar = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.shouldContainTwoByteFoos = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.shouldContainTwoIntFoos = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.shouldContainTwoLongFoos = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.stringDefaultsToFoo = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.byteDefaultsToFour = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.intDefaultsToFive = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.longDefaultsToNegativeSeven = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.booleanDefaultsToTrue = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.charDefaultsToC = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.floatDefaultsToPi = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.doubleWithDefault = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.arrayDefaultsTo123 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.arrayDefaultsToEmpty = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.boolDefault = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.byteDefault = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.intDefault = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.longDefault = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.floatDefault = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.doubleDefault = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.checkDoubleFromFloat = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.checkStringArray1 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.checkStringArray2 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.int32_min = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.int32_max = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.int64_max = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.hexInt32_neg_1 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.ibinder = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.int32_1 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.int64_1 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.hexInt32_pos_1 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.hexInt64_pos_1 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.const_exprs_1 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.const_exprs_2 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.const_exprs_3 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.const_exprs_4 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.const_exprs_5 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.const_exprs_6 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.const_exprs_7 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.const_exprs_8 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.const_exprs_9 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.const_exprs_10 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.addString1 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.addString2 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.shouldSetBit0AndBit2 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.u = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.shouldBeConstS1 = parcel.read()?;
-    if (parcel.get_data_position() - start_pos) == parcelable_size {
-      return Ok(Some(result));
-    }
-    result.defaultWithFoo = parcel.read()?;
-    unsafe {
-      parcel.set_data_position(start_pos + parcelable_size)?;
-    }
-    Ok(Some(result))
-  }
+pub(crate) mod mangled {
+ pub use super::StructuredParcelable as _7_android_4_aidl_5_tests_20_StructuredParcelable;
+ pub use super::Empty::Empty as _7_android_4_aidl_5_tests_20_StructuredParcelable_5_Empty;
 }
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/Union.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/Union.rs
index fbb8a35..44f1f78 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/Union.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/Union.rs
@@ -1,3 +1,5 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #[derive(Debug, Clone, PartialEq)]
 pub enum Union {
   Ns(Vec<i32>),
@@ -9,27 +11,14 @@
   Be(crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum),
 }
 pub const S1: &str = "a string constant in union";
-pub(crate) mod mangled { pub use super::Union as _7_android_4_aidl_5_tests_5_Union; }
 impl Default for Union {
   fn default() -> Self {
-    Self::Ns(vec!{})
+    Self::Ns(vec![])
   }
 }
-impl binder::parcel::Serialize for Union {
-  fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-  }
-}
-impl binder::parcel::SerializeArray for Union {}
-impl binder::parcel::SerializeOption for Union {
-  fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    let this = if let Some(this) = this {
-      parcel.write(&1i32)?;
-      this
-    } else {
-      return parcel.write(&0i32);
-    };
-    match this {
+impl binder::Parcelable for Union {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    match self {
       Self::Ns(v) => {
         parcel.write(&0i32)?;
         parcel.write(v)
@@ -60,48 +49,43 @@
       }
     }
   }
-}
-impl binder::parcel::Deserialize for Union {
-  fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-    <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-       .transpose()
-       .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-  }
-}
-impl binder::parcel::DeserializeArray for Union {}
-impl binder::parcel::DeserializeOption for Union {
-  fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-    let status: i32 = parcel.read()?;
-    if status == 0 { return Ok(None); }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
     let tag: i32 = parcel.read()?;
     match tag {
       0 => {
         let value: Vec<i32> = parcel.read()?;
-        Ok(Some(Self::Ns(value)))
+        *self = Self::Ns(value);
+        Ok(())
       }
       1 => {
         let value: i32 = parcel.read()?;
-        Ok(Some(Self::N(value)))
+        *self = Self::N(value);
+        Ok(())
       }
       2 => {
         let value: i32 = parcel.read()?;
-        Ok(Some(Self::M(value)))
+        *self = Self::M(value);
+        Ok(())
       }
       3 => {
         let value: String = parcel.read()?;
-        Ok(Some(Self::S(value)))
+        *self = Self::S(value);
+        Ok(())
       }
       4 => {
         let value: Option<binder::SpIBinder> = parcel.read()?;
-        Ok(Some(Self::Ibinder(value)))
+        *self = Self::Ibinder(value);
+        Ok(())
       }
       5 => {
         let value: Vec<String> = parcel.read()?;
-        Ok(Some(Self::Ss(value)))
+        *self = Self::Ss(value);
+        Ok(())
       }
       6 => {
         let value: crate::mangled::_7_android_4_aidl_5_tests_8_ByteEnum = parcel.read()?;
-        Ok(Some(Self::Be(value)))
+        *self = Self::Be(value);
+        Ok(())
       }
       _ => {
         Err(binder::StatusCode::BAD_VALUE)
@@ -109,3 +93,11 @@
     }
   }
 }
+binder::impl_serialize_for_parcelable!(Union);
+binder::impl_deserialize_for_parcelable!(Union);
+impl binder::binder_impl::ParcelableMetadata for Union {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.Union" }
+}
+pub(crate) mod mangled {
+ pub use super::Union as _7_android_4_aidl_5_tests_5_Union;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/UnionWithFd.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/UnionWithFd.rs
index 501e00c..29af5a3 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/UnionWithFd.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/UnionWithFd.rs
@@ -1,29 +1,18 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #[derive(Debug)]
 pub enum UnionWithFd {
   Num(i32),
-  Pfd(Option<binder::parcel::ParcelFileDescriptor>),
+  Pfd(Option<binder::ParcelFileDescriptor>),
 }
-pub(crate) mod mangled { pub use super::UnionWithFd as _7_android_4_aidl_5_tests_11_UnionWithFd; }
 impl Default for UnionWithFd {
   fn default() -> Self {
     Self::Num(0)
   }
 }
-impl binder::parcel::Serialize for UnionWithFd {
-  fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-  }
-}
-impl binder::parcel::SerializeArray for UnionWithFd {}
-impl binder::parcel::SerializeOption for UnionWithFd {
-  fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    let this = if let Some(this) = this {
-      parcel.write(&1i32)?;
-      this
-    } else {
-      return parcel.write(&0i32);
-    };
-    match this {
+impl binder::Parcelable for UnionWithFd {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    match self {
       Self::Num(v) => {
         parcel.write(&0i32)?;
         parcel.write(v)
@@ -35,28 +24,18 @@
       }
     }
   }
-}
-impl binder::parcel::Deserialize for UnionWithFd {
-  fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-    <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-       .transpose()
-       .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-  }
-}
-impl binder::parcel::DeserializeArray for UnionWithFd {}
-impl binder::parcel::DeserializeOption for UnionWithFd {
-  fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-    let status: i32 = parcel.read()?;
-    if status == 0 { return Ok(None); }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
     let tag: i32 = parcel.read()?;
     match tag {
       0 => {
         let value: i32 = parcel.read()?;
-        Ok(Some(Self::Num(value)))
+        *self = Self::Num(value);
+        Ok(())
       }
       1 => {
-        let value: Option<binder::parcel::ParcelFileDescriptor> = Some(parcel.read()?);
-        Ok(Some(Self::Pfd(value)))
+        let value: Option<binder::ParcelFileDescriptor> = Some(parcel.read()?);
+        *self = Self::Pfd(value);
+        Ok(())
       }
       _ => {
         Err(binder::StatusCode::BAD_VALUE)
@@ -64,3 +43,11 @@
     }
   }
 }
+binder::impl_serialize_for_parcelable!(UnionWithFd);
+binder::impl_deserialize_for_parcelable!(UnionWithFd);
+impl binder::binder_impl::ParcelableMetadata for UnionWithFd {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.UnionWithFd" }
+}
+pub(crate) mod mangled {
+ pub use super::UnionWithFd as _7_android_4_aidl_5_tests_11_UnionWithFd;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/ExtendableParcelable.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/ExtendableParcelable.rs
new file mode 100644
index 0000000..d91ea32
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/ExtendableParcelable.rs
@@ -0,0 +1,61 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#[derive(Debug)]
+pub struct ExtendableParcelable {
+  pub a: i32,
+  pub b: String,
+  pub ext: binder::ParcelableHolder,
+  pub c: i64,
+  pub ext2: binder::ParcelableHolder,
+}
+impl Default for ExtendableParcelable {
+  fn default() -> Self {
+    Self {
+      a: 0,
+      b: Default::default(),
+      ext: binder::ParcelableHolder::new(binder::binder_impl::Stability::Local),
+      c: 0,
+      ext2: binder::ParcelableHolder::new(binder::binder_impl::Stability::Local),
+    }
+  }
+}
+impl binder::Parcelable for ExtendableParcelable {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_write(|subparcel| {
+      subparcel.write(&self.a)?;
+      subparcel.write(&self.b)?;
+      subparcel.write(&self.ext)?;
+      subparcel.write(&self.c)?;
+      subparcel.write(&self.ext2)?;
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      if subparcel.has_more_data() {
+        self.a = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.b = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.ext = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.c = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.ext2 = subparcel.read()?;
+      }
+      Ok(())
+    })
+  }
+}
+binder::impl_serialize_for_parcelable!(ExtendableParcelable);
+binder::impl_deserialize_for_parcelable!(ExtendableParcelable);
+impl binder::binder_impl::ParcelableMetadata for ExtendableParcelable {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.extension.ExtendableParcelable" }
+}
+pub(crate) mod mangled {
+ pub use super::ExtendableParcelable as _7_android_4_aidl_5_tests_9_extension_20_ExtendableParcelable;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/ExtendableParcelable.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/ExtendableParcelable.rs.d
new file mode 100644
index 0000000..8c891a1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/ExtendableParcelable.rs.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/ExtendableParcelable.rs : \
+  system/tools/aidl/tests/android/aidl/tests/extension/ExtendableParcelable.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt.rs
new file mode 100644
index 0000000..939c95d
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt.rs
@@ -0,0 +1,43 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#[derive(Debug)]
+pub struct MyExt {
+  pub a: i32,
+  pub b: String,
+}
+impl Default for MyExt {
+  fn default() -> Self {
+    Self {
+      a: 0,
+      b: Default::default(),
+    }
+  }
+}
+impl binder::Parcelable for MyExt {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_write(|subparcel| {
+      subparcel.write(&self.a)?;
+      subparcel.write(&self.b)?;
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      if subparcel.has_more_data() {
+        self.a = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.b = subparcel.read()?;
+      }
+      Ok(())
+    })
+  }
+}
+binder::impl_serialize_for_parcelable!(MyExt);
+binder::impl_deserialize_for_parcelable!(MyExt);
+impl binder::binder_impl::ParcelableMetadata for MyExt {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.extension.MyExt" }
+}
+pub(crate) mod mangled {
+ pub use super::MyExt as _7_android_4_aidl_5_tests_9_extension_5_MyExt;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt.rs.d
new file mode 100644
index 0000000..6f83175
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt.rs.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt.rs : \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExt.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt2.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt2.rs
new file mode 100644
index 0000000..27017b9
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt2.rs
@@ -0,0 +1,49 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#[derive(Debug)]
+pub struct MyExt2 {
+  pub a: i32,
+  pub b: crate::mangled::_7_android_4_aidl_5_tests_9_extension_5_MyExt,
+  pub c: String,
+}
+impl Default for MyExt2 {
+  fn default() -> Self {
+    Self {
+      a: 0,
+      b: Default::default(),
+      c: Default::default(),
+    }
+  }
+}
+impl binder::Parcelable for MyExt2 {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_write(|subparcel| {
+      subparcel.write(&self.a)?;
+      subparcel.write(&self.b)?;
+      subparcel.write(&self.c)?;
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      if subparcel.has_more_data() {
+        self.a = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.b = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.c = subparcel.read()?;
+      }
+      Ok(())
+    })
+  }
+}
+binder::impl_serialize_for_parcelable!(MyExt2);
+binder::impl_deserialize_for_parcelable!(MyExt2);
+impl binder::binder_impl::ParcelableMetadata for MyExt2 {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.extension.MyExt2" }
+}
+pub(crate) mod mangled {
+ pub use super::MyExt2 as _7_android_4_aidl_5_tests_9_extension_6_MyExt2;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt2.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt2.rs.d
new file mode 100644
index 0000000..7e58f61
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt2.rs.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExt2.rs : \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExt2.aidl \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExt.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExtLike.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExtLike.rs
new file mode 100644
index 0000000..c698aa3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExtLike.rs
@@ -0,0 +1,43 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#[derive(Debug)]
+pub struct MyExtLike {
+  pub a: i32,
+  pub b: String,
+}
+impl Default for MyExtLike {
+  fn default() -> Self {
+    Self {
+      a: 0,
+      b: Default::default(),
+    }
+  }
+}
+impl binder::Parcelable for MyExtLike {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_write(|subparcel| {
+      subparcel.write(&self.a)?;
+      subparcel.write(&self.b)?;
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      if subparcel.has_more_data() {
+        self.a = subparcel.read()?;
+      }
+      if subparcel.has_more_data() {
+        self.b = subparcel.read()?;
+      }
+      Ok(())
+    })
+  }
+}
+binder::impl_serialize_for_parcelable!(MyExtLike);
+binder::impl_deserialize_for_parcelable!(MyExtLike);
+impl binder::binder_impl::ParcelableMetadata for MyExtLike {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.extension.MyExtLike" }
+}
+pub(crate) mod mangled {
+ pub use super::MyExtLike as _7_android_4_aidl_5_tests_9_extension_9_MyExtLike;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExtLike.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExtLike.rs.d
new file mode 100644
index 0000000..4e904d6
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExtLike.rs.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/extension/MyExtLike.rs : \
+  system/tools/aidl/tests/android/aidl/tests/extension/MyExtLike.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/DeeplyNested.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/DeeplyNested.rs
new file mode 100644
index 0000000..547ac18
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/DeeplyNested.rs
@@ -0,0 +1,163 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#[derive(Debug)]
+pub struct DeeplyNested {
+}
+impl Default for DeeplyNested {
+  fn default() -> Self {
+    Self {
+    }
+  }
+}
+impl binder::Parcelable for DeeplyNested {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_write(|subparcel| {
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      Ok(())
+    })
+  }
+}
+binder::impl_serialize_for_parcelable!(DeeplyNested);
+binder::impl_deserialize_for_parcelable!(DeeplyNested);
+impl binder::binder_impl::ParcelableMetadata for DeeplyNested {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.nested.DeeplyNested" }
+}
+pub mod A {
+  #[derive(Debug)]
+  pub struct A {
+    pub e: crate::mangled::_7_android_4_aidl_5_tests_6_nested_12_DeeplyNested_1_B_1_C_1_D_1_E,
+  }
+  impl Default for A {
+    fn default() -> Self {
+      Self {
+        e: crate::mangled::_7_android_4_aidl_5_tests_6_nested_12_DeeplyNested_1_B_1_C_1_D_1_E::OK,
+      }
+    }
+  }
+  impl binder::Parcelable for A {
+    fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_write(|subparcel| {
+        subparcel.write(&self.e)?;
+        Ok(())
+      })
+    }
+    fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_read(|subparcel| {
+        if subparcel.has_more_data() {
+          self.e = subparcel.read()?;
+        }
+        Ok(())
+      })
+    }
+  }
+  binder::impl_serialize_for_parcelable!(A);
+  binder::impl_deserialize_for_parcelable!(A);
+  impl binder::binder_impl::ParcelableMetadata for A {
+    fn get_descriptor() -> &'static str { "android.aidl.tests.nested.DeeplyNested.A" }
+  }
+}
+pub mod B {
+  #[derive(Debug)]
+  pub struct B {
+  }
+  impl Default for B {
+    fn default() -> Self {
+      Self {
+      }
+    }
+  }
+  impl binder::Parcelable for B {
+    fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_write(|subparcel| {
+        Ok(())
+      })
+    }
+    fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_read(|subparcel| {
+        Ok(())
+      })
+    }
+  }
+  binder::impl_serialize_for_parcelable!(B);
+  binder::impl_deserialize_for_parcelable!(B);
+  impl binder::binder_impl::ParcelableMetadata for B {
+    fn get_descriptor() -> &'static str { "android.aidl.tests.nested.DeeplyNested.B" }
+  }
+  pub mod C {
+    #[derive(Debug)]
+    pub struct C {
+    }
+    impl Default for C {
+      fn default() -> Self {
+        Self {
+        }
+      }
+    }
+    impl binder::Parcelable for C {
+      fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+        parcel.sized_write(|subparcel| {
+          Ok(())
+        })
+      }
+      fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+        parcel.sized_read(|subparcel| {
+          Ok(())
+        })
+      }
+    }
+    binder::impl_serialize_for_parcelable!(C);
+    binder::impl_deserialize_for_parcelable!(C);
+    impl binder::binder_impl::ParcelableMetadata for C {
+      fn get_descriptor() -> &'static str { "android.aidl.tests.nested.DeeplyNested.B.C" }
+    }
+    pub mod D {
+      #[derive(Debug)]
+      pub struct D {
+      }
+      impl Default for D {
+        fn default() -> Self {
+          Self {
+          }
+        }
+      }
+      impl binder::Parcelable for D {
+        fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+          parcel.sized_write(|subparcel| {
+            Ok(())
+          })
+        }
+        fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+          parcel.sized_read(|subparcel| {
+            Ok(())
+          })
+        }
+      }
+      binder::impl_serialize_for_parcelable!(D);
+      binder::impl_deserialize_for_parcelable!(D);
+      impl binder::binder_impl::ParcelableMetadata for D {
+        fn get_descriptor() -> &'static str { "android.aidl.tests.nested.DeeplyNested.B.C.D" }
+      }
+      pub mod E {
+        #![allow(non_upper_case_globals)]
+        use binder::declare_binder_enum;
+        declare_binder_enum! {
+          E : [i8; 1] {
+            OK = 0,
+          }
+        }
+      }
+    }
+  }
+}
+pub(crate) mod mangled {
+ pub use super::DeeplyNested as _7_android_4_aidl_5_tests_6_nested_12_DeeplyNested;
+ pub use super::A::A as _7_android_4_aidl_5_tests_6_nested_12_DeeplyNested_1_A;
+ pub use super::B::B as _7_android_4_aidl_5_tests_6_nested_12_DeeplyNested_1_B;
+ pub use super::B::C::C as _7_android_4_aidl_5_tests_6_nested_12_DeeplyNested_1_B_1_C;
+ pub use super::B::C::D::D as _7_android_4_aidl_5_tests_6_nested_12_DeeplyNested_1_B_1_C_1_D;
+ pub use super::B::C::D::E::E as _7_android_4_aidl_5_tests_6_nested_12_DeeplyNested_1_B_1_C_1_D_1_E;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/DeeplyNested.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/DeeplyNested.rs.d
new file mode 100644
index 0000000..cfee6a4
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/DeeplyNested.rs.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/DeeplyNested.rs : \
+  system/tools/aidl/tests/android/aidl/tests/nested/DeeplyNested.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/INestedService.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/INestedService.rs
new file mode 100644
index 0000000..45b76b3
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/INestedService.rs
@@ -0,0 +1,365 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#![allow(non_upper_case_globals)]
+#![allow(non_snake_case)]
+#[allow(unused_imports)] use binder::binder_impl::IBinderInternal;
+use binder::declare_binder_interface;
+declare_binder_interface! {
+  INestedService["android.aidl.tests.nested.INestedService"] {
+    native: BnNestedService(on_transact),
+    proxy: BpNestedService {
+    },
+    async: INestedServiceAsync,
+  }
+}
+pub trait INestedService: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.nested.INestedService" }
+  fn flipStatus(&self, _arg_p: &crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_6_Result>;
+  fn flipStatusWithCallback(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status, _arg_cb: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_9_ICallback>) -> binder::Result<()>;
+  fn getDefaultImpl() -> INestedServiceDefaultRef where Self: Sized {
+    DEFAULT_IMPL.lock().unwrap().clone()
+  }
+  fn setDefaultImpl(d: INestedServiceDefaultRef) -> INestedServiceDefaultRef where Self: Sized {
+    std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+  }
+}
+pub trait INestedServiceAsync<P>: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.nested.INestedService" }
+  fn flipStatus<'a>(&'a self, _arg_p: &'a crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested) -> binder::BoxFuture<'a, binder::Result<crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_6_Result>>;
+  fn flipStatusWithCallback<'a>(&'a self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status, _arg_cb: &'a binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_9_ICallback>) -> binder::BoxFuture<'a, binder::Result<()>>;
+}
+#[::async_trait::async_trait]
+pub trait INestedServiceAsyncServer: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.nested.INestedService" }
+  async fn flipStatus(&self, _arg_p: &crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_6_Result>;
+  async fn flipStatusWithCallback(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status, _arg_cb: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_9_ICallback>) -> binder::Result<()>;
+}
+impl BnNestedService {
+  /// Create a new async binder service.
+  pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn INestedService>
+  where
+    T: INestedServiceAsyncServer + binder::Interface + Send + Sync + 'static,
+    R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+  {
+    struct Wrapper<T, R> {
+      _inner: T,
+      _rt: R,
+    }
+    impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+      fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+      fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+    }
+    impl<T, R> INestedService for Wrapper<T, R>
+    where
+      T: INestedServiceAsyncServer + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      fn flipStatus(&self, _arg_p: &crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_6_Result> {
+        self._rt.block_on(self._inner.flipStatus(_arg_p))
+      }
+      fn flipStatusWithCallback(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status, _arg_cb: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_9_ICallback>) -> binder::Result<()> {
+        self._rt.block_on(self._inner.flipStatusWithCallback(_arg_status, _arg_cb))
+      }
+    }
+    let wrapped = Wrapper { _inner: inner, _rt: rt };
+    Self::new_binder(wrapped, features)
+  }
+}
+pub trait INestedServiceDefault: Send + Sync {
+  fn flipStatus(&self, _arg_p: &crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_6_Result> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn flipStatusWithCallback(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status, _arg_cb: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_9_ICallback>) -> binder::Result<()> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+}
+pub mod transactions {
+  pub const flipStatus: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 0;
+  pub const flipStatusWithCallback: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 1;
+}
+pub type INestedServiceDefaultRef = Option<std::sync::Arc<dyn INestedServiceDefault>>;
+use lazy_static::lazy_static;
+lazy_static! {
+  static ref DEFAULT_IMPL: std::sync::Mutex<INestedServiceDefaultRef> = std::sync::Mutex::new(None);
+}
+impl BpNestedService {
+  fn build_parcel_flipStatus(&self, _arg_p: &crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.write(_arg_p)?;
+    Ok(aidl_data)
+  }
+  fn read_response_flipStatus(&self, _arg_p: &crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_6_Result> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as INestedService>::getDefaultImpl() {
+        return _aidl_default_impl.flipStatus(_arg_p);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    let _aidl_return: crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_6_Result = _aidl_reply.read()?;
+    Ok(_aidl_return)
+  }
+  fn build_parcel_flipStatusWithCallback(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status, _arg_cb: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_9_ICallback>) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    aidl_data.write(&_arg_status)?;
+    aidl_data.write(_arg_cb)?;
+    Ok(aidl_data)
+  }
+  fn read_response_flipStatusWithCallback(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status, _arg_cb: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_9_ICallback>, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as INestedService>::getDefaultImpl() {
+        return _aidl_default_impl.flipStatusWithCallback(_arg_status, _arg_cb);
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    Ok(())
+  }
+}
+impl INestedService for BpNestedService {
+  fn flipStatus(&self, _arg_p: &crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_6_Result> {
+    let _aidl_data = self.build_parcel_flipStatus(_arg_p)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::flipStatus, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_flipStatus(_arg_p, _aidl_reply)
+  }
+  fn flipStatusWithCallback(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status, _arg_cb: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_9_ICallback>) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_flipStatusWithCallback(_arg_status, _arg_cb)?;
+    let _aidl_reply = self.binder.submit_transact(transactions::flipStatusWithCallback, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_flipStatusWithCallback(_arg_status, _arg_cb, _aidl_reply)
+  }
+}
+impl<P: binder::BinderAsyncPool> INestedServiceAsync<P> for BpNestedService {
+  fn flipStatus<'a>(&'a self, _arg_p: &'a crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested) -> binder::BoxFuture<'a, binder::Result<crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_6_Result>> {
+    let _aidl_data = match self.build_parcel_flipStatus(_arg_p) {
+      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::flipStatus, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_flipStatus(_arg_p, _aidl_reply)
+      }
+    )
+  }
+  fn flipStatusWithCallback<'a>(&'a self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status, _arg_cb: &'a binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_9_ICallback>) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_flipStatusWithCallback(_arg_status, _arg_cb) {
+      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::flipStatusWithCallback, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_flipStatusWithCallback(_arg_status, _arg_cb, _aidl_reply)
+      }
+    )
+  }
+}
+impl INestedService for binder::binder_impl::Binder<BnNestedService> {
+  fn flipStatus(&self, _arg_p: &crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested) -> binder::Result<crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_6_Result> { self.0.flipStatus(_arg_p) }
+  fn flipStatusWithCallback(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status, _arg_cb: &binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_9_ICallback>) -> binder::Result<()> { self.0.flipStatusWithCallback(_arg_status, _arg_cb) }
+}
+fn on_transact(_aidl_service: &dyn INestedService, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
+  match _aidl_code {
+    transactions::flipStatus => {
+      let _arg_p: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested = _aidl_data.read()?;
+      let _aidl_return = _aidl_service.flipStatus(&_arg_p);
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          _aidl_reply.write(_aidl_return)?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::flipStatusWithCallback => {
+      let _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status = _aidl_data.read()?;
+      let _arg_cb: binder::Strong<dyn crate::mangled::_7_android_4_aidl_5_tests_6_nested_14_INestedService_9_ICallback> = _aidl_data.read()?;
+      let _aidl_return = _aidl_service.flipStatusWithCallback(_arg_status, &_arg_cb);
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+  }
+}
+pub mod Result {
+  #[derive(Debug, PartialEq)]
+  pub struct Result {
+    pub status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status,
+  }
+  impl Default for Result {
+    fn default() -> Self {
+      Self {
+        status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status::OK,
+      }
+    }
+  }
+  impl binder::Parcelable for Result {
+    fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_write(|subparcel| {
+        subparcel.write(&self.status)?;
+        Ok(())
+      })
+    }
+    fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+      parcel.sized_read(|subparcel| {
+        if subparcel.has_more_data() {
+          self.status = subparcel.read()?;
+        }
+        Ok(())
+      })
+    }
+  }
+  binder::impl_serialize_for_parcelable!(Result);
+  binder::impl_deserialize_for_parcelable!(Result);
+  impl binder::binder_impl::ParcelableMetadata for Result {
+    fn get_descriptor() -> &'static str { "android.aidl.tests.nested.INestedService.Result" }
+  }
+}
+pub mod ICallback {
+  #![allow(non_upper_case_globals)]
+  #![allow(non_snake_case)]
+  #[allow(unused_imports)] use binder::binder_impl::IBinderInternal;
+  use binder::declare_binder_interface;
+  declare_binder_interface! {
+    ICallback["android.aidl.tests.nested.INestedService.ICallback"] {
+      native: BnCallback(on_transact),
+      proxy: BpCallback {
+      },
+      async: ICallbackAsync,
+    }
+  }
+  pub trait ICallback: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.nested.INestedService.ICallback" }
+    fn done(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status) -> binder::Result<()>;
+    fn getDefaultImpl() -> ICallbackDefaultRef where Self: Sized {
+      DEFAULT_IMPL.lock().unwrap().clone()
+    }
+    fn setDefaultImpl(d: ICallbackDefaultRef) -> ICallbackDefaultRef where Self: Sized {
+      std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+    }
+  }
+  pub trait ICallbackAsync<P>: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.nested.INestedService.ICallback" }
+    fn done<'a>(&'a self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status) -> binder::BoxFuture<'a, binder::Result<()>>;
+  }
+  #[::async_trait::async_trait]
+  pub trait ICallbackAsyncServer: binder::Interface + Send {
+    fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.nested.INestedService.ICallback" }
+    async fn done(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status) -> binder::Result<()>;
+  }
+  impl BnCallback {
+    /// Create a new async binder service.
+    pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn ICallback>
+    where
+      T: ICallbackAsyncServer + binder::Interface + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      struct Wrapper<T, R> {
+        _inner: T,
+        _rt: R,
+      }
+      impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+        fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+        fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+      }
+      impl<T, R> ICallback for Wrapper<T, R>
+      where
+        T: ICallbackAsyncServer + Send + Sync + 'static,
+        R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+      {
+        fn done(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status) -> binder::Result<()> {
+          self._rt.block_on(self._inner.done(_arg_status))
+        }
+      }
+      let wrapped = Wrapper { _inner: inner, _rt: rt };
+      Self::new_binder(wrapped, features)
+    }
+  }
+  pub trait ICallbackDefault: Send + Sync {
+    fn done(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status) -> binder::Result<()> {
+      Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+    }
+  }
+  pub mod transactions {
+    pub const done: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 0;
+  }
+  pub type ICallbackDefaultRef = Option<std::sync::Arc<dyn ICallbackDefault>>;
+  use lazy_static::lazy_static;
+  lazy_static! {
+    static ref DEFAULT_IMPL: std::sync::Mutex<ICallbackDefaultRef> = std::sync::Mutex::new(None);
+  }
+  impl BpCallback {
+    fn build_parcel_done(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status) -> binder::Result<binder::binder_impl::Parcel> {
+      let mut aidl_data = self.binder.prepare_transact()?;
+      aidl_data.write(&_arg_status)?;
+      Ok(aidl_data)
+    }
+    fn read_response_done(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
+      if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+        if let Some(_aidl_default_impl) = <Self as ICallback>::getDefaultImpl() {
+          return _aidl_default_impl.done(_arg_status);
+        }
+      }
+      let _aidl_reply = _aidl_reply?;
+      let _aidl_status: binder::Status = _aidl_reply.read()?;
+      if !_aidl_status.is_ok() { return Err(_aidl_status); }
+      Ok(())
+    }
+  }
+  impl ICallback for BpCallback {
+    fn done(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status) -> binder::Result<()> {
+      let _aidl_data = self.build_parcel_done(_arg_status)?;
+      let _aidl_reply = self.binder.submit_transact(transactions::done, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+      self.read_response_done(_arg_status, _aidl_reply)
+    }
+  }
+  impl<P: binder::BinderAsyncPool> ICallbackAsync<P> for BpCallback {
+    fn done<'a>(&'a self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status) -> binder::BoxFuture<'a, binder::Result<()>> {
+      let _aidl_data = match self.build_parcel_done(_arg_status) {
+        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::done, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+        move |_aidl_reply| async move {
+          self.read_response_done(_arg_status, _aidl_reply)
+        }
+      )
+    }
+  }
+  impl ICallback for binder::binder_impl::Binder<BnCallback> {
+    fn done(&self, _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status) -> binder::Result<()> { self.0.done(_arg_status) }
+  }
+  fn on_transact(_aidl_service: &dyn ICallback, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
+    match _aidl_code {
+      transactions::done => {
+        let _arg_status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status = _aidl_data.read()?;
+        let _aidl_return = _aidl_service.done(_arg_status);
+        match &_aidl_return {
+          Ok(_aidl_return) => {
+            _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+          }
+          Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+        }
+        Ok(())
+      }
+      _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+    }
+  }
+}
+pub(crate) mod mangled {
+ pub use super::INestedService as _7_android_4_aidl_5_tests_6_nested_14_INestedService;
+ pub use super::Result::Result as _7_android_4_aidl_5_tests_6_nested_14_INestedService_6_Result;
+ pub use super::ICallback::ICallback as _7_android_4_aidl_5_tests_6_nested_14_INestedService_9_ICallback;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/INestedService.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/INestedService.rs.d
new file mode 100644
index 0000000..d2839d2
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/INestedService.rs.d
@@ -0,0 +1,3 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/INestedService.rs : \
+  system/tools/aidl/tests/android/aidl/tests/nested/INestedService.aidl \
+  system/tools/aidl/tests/android/aidl/tests/nested/ParcelableWithNested.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/ParcelableWithNested.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/ParcelableWithNested.rs
new file mode 100644
index 0000000..d160d8b
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/ParcelableWithNested.rs
@@ -0,0 +1,48 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#[derive(Debug)]
+pub struct ParcelableWithNested {
+  pub status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status,
+}
+impl Default for ParcelableWithNested {
+  fn default() -> Self {
+    Self {
+      status: crate::mangled::_7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status::OK,
+    }
+  }
+}
+impl binder::Parcelable for ParcelableWithNested {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_write(|subparcel| {
+      subparcel.write(&self.status)?;
+      Ok(())
+    })
+  }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    parcel.sized_read(|subparcel| {
+      if subparcel.has_more_data() {
+        self.status = subparcel.read()?;
+      }
+      Ok(())
+    })
+  }
+}
+binder::impl_serialize_for_parcelable!(ParcelableWithNested);
+binder::impl_deserialize_for_parcelable!(ParcelableWithNested);
+impl binder::binder_impl::ParcelableMetadata for ParcelableWithNested {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.nested.ParcelableWithNested" }
+}
+pub mod Status {
+  #![allow(non_upper_case_globals)]
+  use binder::declare_binder_enum;
+  declare_binder_enum! {
+    Status : [i8; 2] {
+      OK = 0,
+      NOT_OK = 1,
+    }
+  }
+}
+pub(crate) mod mangled {
+ pub use super::ParcelableWithNested as _7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested;
+ pub use super::Status::Status as _7_android_4_aidl_5_tests_6_nested_20_ParcelableWithNested_6_Status;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/ParcelableWithNested.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/ParcelableWithNested.rs.d
new file mode 100644
index 0000000..d91414e
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/ParcelableWithNested.rs.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/nested/ParcelableWithNested.rs : \
+  system/tools/aidl/tests/android/aidl/tests/nested/ParcelableWithNested.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtected.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtected.rs
new file mode 100644
index 0000000..0abf8c1
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtected.rs
@@ -0,0 +1,242 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#![allow(non_upper_case_globals)]
+#![allow(non_snake_case)]
+#[allow(unused_imports)] use binder::binder_impl::IBinderInternal;
+use binder::declare_binder_interface;
+declare_binder_interface! {
+  IProtected["android.aidl.tests.permission.IProtected"] {
+    native: BnProtected(on_transact),
+    proxy: BpProtected {
+    },
+    async: IProtectedAsync,
+  }
+}
+pub trait IProtected: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.permission.IProtected" }
+  fn PermissionProtected(&self) -> binder::Result<()>;
+  fn MultiplePermissionsAll(&self) -> binder::Result<()>;
+  fn MultiplePermissionsAny(&self) -> binder::Result<()>;
+  fn getDefaultImpl() -> IProtectedDefaultRef where Self: Sized {
+    DEFAULT_IMPL.lock().unwrap().clone()
+  }
+  fn setDefaultImpl(d: IProtectedDefaultRef) -> IProtectedDefaultRef where Self: Sized {
+    std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+  }
+}
+pub trait IProtectedAsync<P>: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.permission.IProtected" }
+  fn PermissionProtected<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<()>>;
+  fn MultiplePermissionsAll<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<()>>;
+  fn MultiplePermissionsAny<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<()>>;
+}
+#[::async_trait::async_trait]
+pub trait IProtectedAsyncServer: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.permission.IProtected" }
+  async fn PermissionProtected(&self) -> binder::Result<()>;
+  async fn MultiplePermissionsAll(&self) -> binder::Result<()>;
+  async fn MultiplePermissionsAny(&self) -> binder::Result<()>;
+}
+impl BnProtected {
+  /// Create a new async binder service.
+  pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn IProtected>
+  where
+    T: IProtectedAsyncServer + binder::Interface + Send + Sync + 'static,
+    R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+  {
+    struct Wrapper<T, R> {
+      _inner: T,
+      _rt: R,
+    }
+    impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+      fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+      fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+    }
+    impl<T, R> IProtected for Wrapper<T, R>
+    where
+      T: IProtectedAsyncServer + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      fn PermissionProtected(&self) -> binder::Result<()> {
+        self._rt.block_on(self._inner.PermissionProtected())
+      }
+      fn MultiplePermissionsAll(&self) -> binder::Result<()> {
+        self._rt.block_on(self._inner.MultiplePermissionsAll())
+      }
+      fn MultiplePermissionsAny(&self) -> binder::Result<()> {
+        self._rt.block_on(self._inner.MultiplePermissionsAny())
+      }
+    }
+    let wrapped = Wrapper { _inner: inner, _rt: rt };
+    Self::new_binder(wrapped, features)
+  }
+}
+pub trait IProtectedDefault: Send + Sync {
+  fn PermissionProtected(&self) -> binder::Result<()> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn MultiplePermissionsAll(&self) -> binder::Result<()> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn MultiplePermissionsAny(&self) -> binder::Result<()> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+}
+pub mod transactions {
+  pub const PermissionProtected: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 0;
+  pub const MultiplePermissionsAll: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 1;
+  pub const MultiplePermissionsAny: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 2;
+}
+pub type IProtectedDefaultRef = Option<std::sync::Arc<dyn IProtectedDefault>>;
+use lazy_static::lazy_static;
+lazy_static! {
+  static ref DEFAULT_IMPL: std::sync::Mutex<IProtectedDefaultRef> = std::sync::Mutex::new(None);
+}
+impl BpProtected {
+  fn build_parcel_PermissionProtected(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    Ok(aidl_data)
+  }
+  fn read_response_PermissionProtected(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as IProtected>::getDefaultImpl() {
+        return _aidl_default_impl.PermissionProtected();
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    Ok(())
+  }
+  fn build_parcel_MultiplePermissionsAll(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    Ok(aidl_data)
+  }
+  fn read_response_MultiplePermissionsAll(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as IProtected>::getDefaultImpl() {
+        return _aidl_default_impl.MultiplePermissionsAll();
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    Ok(())
+  }
+  fn build_parcel_MultiplePermissionsAny(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    Ok(aidl_data)
+  }
+  fn read_response_MultiplePermissionsAny(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as IProtected>::getDefaultImpl() {
+        return _aidl_default_impl.MultiplePermissionsAny();
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    Ok(())
+  }
+}
+impl IProtected for BpProtected {
+  fn PermissionProtected(&self) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_PermissionProtected()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::PermissionProtected, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_PermissionProtected(_aidl_reply)
+  }
+  fn MultiplePermissionsAll(&self) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_MultiplePermissionsAll()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::MultiplePermissionsAll, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_MultiplePermissionsAll(_aidl_reply)
+  }
+  fn MultiplePermissionsAny(&self) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_MultiplePermissionsAny()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::MultiplePermissionsAny, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_MultiplePermissionsAny(_aidl_reply)
+  }
+}
+impl<P: binder::BinderAsyncPool> IProtectedAsync<P> for BpProtected {
+  fn PermissionProtected<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_PermissionProtected() {
+      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::PermissionProtected, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_PermissionProtected(_aidl_reply)
+      }
+    )
+  }
+  fn MultiplePermissionsAll<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_MultiplePermissionsAll() {
+      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::MultiplePermissionsAll, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_MultiplePermissionsAll(_aidl_reply)
+      }
+    )
+  }
+  fn MultiplePermissionsAny<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_MultiplePermissionsAny() {
+      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::MultiplePermissionsAny, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_MultiplePermissionsAny(_aidl_reply)
+      }
+    )
+  }
+}
+impl IProtected for binder::binder_impl::Binder<BnProtected> {
+  fn PermissionProtected(&self) -> binder::Result<()> { self.0.PermissionProtected() }
+  fn MultiplePermissionsAll(&self) -> binder::Result<()> { self.0.MultiplePermissionsAll() }
+  fn MultiplePermissionsAny(&self) -> binder::Result<()> { self.0.MultiplePermissionsAny() }
+}
+fn on_transact(_aidl_service: &dyn IProtected, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
+  match _aidl_code {
+    transactions::PermissionProtected => {
+      let _aidl_return = _aidl_service.PermissionProtected();
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::MultiplePermissionsAll => {
+      let _aidl_return = _aidl_service.MultiplePermissionsAll();
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::MultiplePermissionsAny => {
+      let _aidl_return = _aidl_service.MultiplePermissionsAny();
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+  }
+}
+pub(crate) mod mangled {
+ pub use super::IProtected as _7_android_4_aidl_5_tests_10_permission_10_IProtected;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtected.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtected.rs.d
new file mode 100644
index 0000000..72476b7
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtected.rs.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtected.rs : \
+  system/tools/aidl/tests/android/aidl/tests/permission/IProtected.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtectedInterface.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtectedInterface.rs
new file mode 100644
index 0000000..cdbf3b5
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtectedInterface.rs
@@ -0,0 +1,188 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
+#![allow(non_upper_case_globals)]
+#![allow(non_snake_case)]
+#[allow(unused_imports)] use binder::binder_impl::IBinderInternal;
+use binder::declare_binder_interface;
+declare_binder_interface! {
+  IProtectedInterface["android.aidl.tests.permission.IProtectedInterface"] {
+    native: BnProtectedInterface(on_transact),
+    proxy: BpProtectedInterface {
+    },
+    async: IProtectedInterfaceAsync,
+  }
+}
+pub trait IProtectedInterface: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.permission.IProtectedInterface" }
+  fn Method1(&self) -> binder::Result<()>;
+  fn Method2(&self) -> binder::Result<()>;
+  fn getDefaultImpl() -> IProtectedInterfaceDefaultRef where Self: Sized {
+    DEFAULT_IMPL.lock().unwrap().clone()
+  }
+  fn setDefaultImpl(d: IProtectedInterfaceDefaultRef) -> IProtectedInterfaceDefaultRef where Self: Sized {
+    std::mem::replace(&mut *DEFAULT_IMPL.lock().unwrap(), d)
+  }
+}
+pub trait IProtectedInterfaceAsync<P>: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.permission.IProtectedInterface" }
+  fn Method1<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<()>>;
+  fn Method2<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<()>>;
+}
+#[::async_trait::async_trait]
+pub trait IProtectedInterfaceAsyncServer: binder::Interface + Send {
+  fn get_descriptor() -> &'static str where Self: Sized { "android.aidl.tests.permission.IProtectedInterface" }
+  async fn Method1(&self) -> binder::Result<()>;
+  async fn Method2(&self) -> binder::Result<()>;
+}
+impl BnProtectedInterface {
+  /// Create a new async binder service.
+  pub fn new_async_binder<T, R>(inner: T, rt: R, features: binder::BinderFeatures) -> binder::Strong<dyn IProtectedInterface>
+  where
+    T: IProtectedInterfaceAsyncServer + binder::Interface + Send + Sync + 'static,
+    R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+  {
+    struct Wrapper<T, R> {
+      _inner: T,
+      _rt: R,
+    }
+    impl<T, R> binder::Interface for Wrapper<T, R> where T: binder::Interface, R: Send + Sync {
+      fn as_binder(&self) -> binder::SpIBinder { self._inner.as_binder() }
+      fn dump(&self, _file: &std::fs::File, _args: &[&std::ffi::CStr]) -> std::result::Result<(), binder::StatusCode> { self._inner.dump(_file, _args) }
+    }
+    impl<T, R> IProtectedInterface for Wrapper<T, R>
+    where
+      T: IProtectedInterfaceAsyncServer + Send + Sync + 'static,
+      R: binder::binder_impl::BinderAsyncRuntime + Send + Sync + 'static,
+    {
+      fn Method1(&self) -> binder::Result<()> {
+        self._rt.block_on(self._inner.Method1())
+      }
+      fn Method2(&self) -> binder::Result<()> {
+        self._rt.block_on(self._inner.Method2())
+      }
+    }
+    let wrapped = Wrapper { _inner: inner, _rt: rt };
+    Self::new_binder(wrapped, features)
+  }
+}
+pub trait IProtectedInterfaceDefault: Send + Sync {
+  fn Method1(&self) -> binder::Result<()> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+  fn Method2(&self) -> binder::Result<()> {
+    Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+  }
+}
+pub mod transactions {
+  pub const Method1: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 0;
+  pub const Method2: binder::binder_impl::TransactionCode = binder::binder_impl::FIRST_CALL_TRANSACTION + 1;
+}
+pub type IProtectedInterfaceDefaultRef = Option<std::sync::Arc<dyn IProtectedInterfaceDefault>>;
+use lazy_static::lazy_static;
+lazy_static! {
+  static ref DEFAULT_IMPL: std::sync::Mutex<IProtectedInterfaceDefaultRef> = std::sync::Mutex::new(None);
+}
+impl BpProtectedInterface {
+  fn build_parcel_Method1(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    Ok(aidl_data)
+  }
+  fn read_response_Method1(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as IProtectedInterface>::getDefaultImpl() {
+        return _aidl_default_impl.Method1();
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    Ok(())
+  }
+  fn build_parcel_Method2(&self) -> binder::Result<binder::binder_impl::Parcel> {
+    let mut aidl_data = self.binder.prepare_transact()?;
+    Ok(aidl_data)
+  }
+  fn read_response_Method2(&self, _aidl_reply: std::result::Result<binder::binder_impl::Parcel, binder::StatusCode>) -> binder::Result<()> {
+    if let Err(binder::StatusCode::UNKNOWN_TRANSACTION) = _aidl_reply {
+      if let Some(_aidl_default_impl) = <Self as IProtectedInterface>::getDefaultImpl() {
+        return _aidl_default_impl.Method2();
+      }
+    }
+    let _aidl_reply = _aidl_reply?;
+    let _aidl_status: binder::Status = _aidl_reply.read()?;
+    if !_aidl_status.is_ok() { return Err(_aidl_status); }
+    Ok(())
+  }
+}
+impl IProtectedInterface for BpProtectedInterface {
+  fn Method1(&self) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_Method1()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::Method1, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_Method1(_aidl_reply)
+  }
+  fn Method2(&self) -> binder::Result<()> {
+    let _aidl_data = self.build_parcel_Method2()?;
+    let _aidl_reply = self.binder.submit_transact(transactions::Method2, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL);
+    self.read_response_Method2(_aidl_reply)
+  }
+}
+impl<P: binder::BinderAsyncPool> IProtectedInterfaceAsync<P> for BpProtectedInterface {
+  fn Method1<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_Method1() {
+      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::Method1, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_Method1(_aidl_reply)
+      }
+    )
+  }
+  fn Method2<'a>(&'a self) -> binder::BoxFuture<'a, binder::Result<()>> {
+    let _aidl_data = match self.build_parcel_Method2() {
+      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::Method2, _aidl_data, binder::binder_impl::FLAG_PRIVATE_LOCAL),
+      move |_aidl_reply| async move {
+        self.read_response_Method2(_aidl_reply)
+      }
+    )
+  }
+}
+impl IProtectedInterface for binder::binder_impl::Binder<BnProtectedInterface> {
+  fn Method1(&self) -> binder::Result<()> { self.0.Method1() }
+  fn Method2(&self) -> binder::Result<()> { self.0.Method2() }
+}
+fn on_transact(_aidl_service: &dyn IProtectedInterface, _aidl_code: binder::binder_impl::TransactionCode, _aidl_data: &binder::binder_impl::BorrowedParcel<'_>, _aidl_reply: &mut binder::binder_impl::BorrowedParcel<'_>) -> std::result::Result<(), binder::StatusCode> {
+  match _aidl_code {
+    transactions::Method1 => {
+      let _aidl_return = _aidl_service.Method1();
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    transactions::Method2 => {
+      let _aidl_return = _aidl_service.Method2();
+      match &_aidl_return {
+        Ok(_aidl_return) => {
+          _aidl_reply.write(&binder::Status::from(binder::StatusCode::OK))?;
+        }
+        Err(_aidl_status) => _aidl_reply.write(_aidl_status)?
+      }
+      Ok(())
+    }
+    _ => Err(binder::StatusCode::UNKNOWN_TRANSACTION)
+  }
+}
+pub(crate) mod mangled {
+ pub use super::IProtectedInterface as _7_android_4_aidl_5_tests_10_permission_19_IProtectedInterface;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtectedInterface.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtectedInterface.rs.d
new file mode 100644
index 0000000..318359f
--- /dev/null
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtectedInterface.rs.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/permission/IProtectedInterface.rs : \
+  system/tools/aidl/tests/android/aidl/tests/permission/IProtectedInterface.aidl
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/EnumUnion.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/EnumUnion.rs
index 426b9d2..bf142f7 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/EnumUnion.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/EnumUnion.rs
@@ -1,29 +1,18 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #[derive(Debug, Clone, PartialEq)]
 pub enum EnumUnion {
   IntEnum(crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum),
   LongEnum(crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum),
 }
-pub(crate) mod mangled { pub use super::EnumUnion as _7_android_4_aidl_5_tests_6_unions_9_EnumUnion; }
 impl Default for EnumUnion {
   fn default() -> Self {
     Self::IntEnum(crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum::FOO)
   }
 }
-impl binder::parcel::Serialize for EnumUnion {
-  fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-  }
-}
-impl binder::parcel::SerializeArray for EnumUnion {}
-impl binder::parcel::SerializeOption for EnumUnion {
-  fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    let this = if let Some(this) = this {
-      parcel.write(&1i32)?;
-      this
-    } else {
-      return parcel.write(&0i32);
-    };
-    match this {
+impl binder::Parcelable for EnumUnion {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    match self {
       Self::IntEnum(v) => {
         parcel.write(&0i32)?;
         parcel.write(v)
@@ -34,28 +23,18 @@
       }
     }
   }
-}
-impl binder::parcel::Deserialize for EnumUnion {
-  fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-    <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-       .transpose()
-       .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-  }
-}
-impl binder::parcel::DeserializeArray for EnumUnion {}
-impl binder::parcel::DeserializeOption for EnumUnion {
-  fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-    let status: i32 = parcel.read()?;
-    if status == 0 { return Ok(None); }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
     let tag: i32 = parcel.read()?;
     match tag {
       0 => {
         let value: crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum = parcel.read()?;
-        Ok(Some(Self::IntEnum(value)))
+        *self = Self::IntEnum(value);
+        Ok(())
       }
       1 => {
         let value: crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum = parcel.read()?;
-        Ok(Some(Self::LongEnum(value)))
+        *self = Self::LongEnum(value);
+        Ok(())
       }
       _ => {
         Err(binder::StatusCode::BAD_VALUE)
@@ -63,3 +42,11 @@
     }
   }
 }
+binder::impl_serialize_for_parcelable!(EnumUnion);
+binder::impl_deserialize_for_parcelable!(EnumUnion);
+impl binder::binder_impl::ParcelableMetadata for EnumUnion {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.unions.EnumUnion" }
+}
+pub(crate) mod mangled {
+ pub use super::EnumUnion as _7_android_4_aidl_5_tests_6_unions_9_EnumUnion;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/UnionInUnion.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/UnionInUnion.rs
index 7adee52..fd2d68d 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/UnionInUnion.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/UnionInUnion.rs
@@ -1,29 +1,18 @@
+#![forbid(unsafe_code)]
+#![rustfmt::skip]
 #[derive(Debug, Clone, PartialEq)]
 pub enum UnionInUnion {
   First(crate::mangled::_7_android_4_aidl_5_tests_6_unions_9_EnumUnion),
   Second(i32),
 }
-pub(crate) mod mangled { pub use super::UnionInUnion as _7_android_4_aidl_5_tests_6_unions_12_UnionInUnion; }
 impl Default for UnionInUnion {
   fn default() -> Self {
     Self::First(Default::default())
   }
 }
-impl binder::parcel::Serialize for UnionInUnion {
-  fn serialize(&self, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    <Self as binder::parcel::SerializeOption>::serialize_option(Some(self), parcel)
-  }
-}
-impl binder::parcel::SerializeArray for UnionInUnion {}
-impl binder::parcel::SerializeOption for UnionInUnion {
-  fn serialize_option(this: Option<&Self>, parcel: &mut binder::parcel::Parcel) -> binder::Result<()> {
-    let this = if let Some(this) = this {
-      parcel.write(&1i32)?;
-      this
-    } else {
-      return parcel.write(&0i32);
-    };
-    match this {
+impl binder::Parcelable for UnionInUnion {
+  fn write_to_parcel(&self, parcel: &mut binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
+    match self {
       Self::First(v) => {
         parcel.write(&0i32)?;
         parcel.write(v)
@@ -34,28 +23,18 @@
       }
     }
   }
-}
-impl binder::parcel::Deserialize for UnionInUnion {
-  fn deserialize(parcel: &binder::parcel::Parcel) -> binder::Result<Self> {
-    <Self as binder::parcel::DeserializeOption>::deserialize_option(parcel)
-       .transpose()
-       .unwrap_or(Err(binder::StatusCode::UNEXPECTED_NULL))
-  }
-}
-impl binder::parcel::DeserializeArray for UnionInUnion {}
-impl binder::parcel::DeserializeOption for UnionInUnion {
-  fn deserialize_option(parcel: &binder::parcel::Parcel) -> binder::Result<Option<Self>> {
-    let status: i32 = parcel.read()?;
-    if status == 0 { return Ok(None); }
+  fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
     let tag: i32 = parcel.read()?;
     match tag {
       0 => {
         let value: crate::mangled::_7_android_4_aidl_5_tests_6_unions_9_EnumUnion = parcel.read()?;
-        Ok(Some(Self::First(value)))
+        *self = Self::First(value);
+        Ok(())
       }
       1 => {
         let value: i32 = parcel.read()?;
-        Ok(Some(Self::Second(value)))
+        *self = Self::Second(value);
+        Ok(())
       }
       _ => {
         Err(binder::StatusCode::BAD_VALUE)
@@ -63,3 +42,11 @@
     }
   }
 }
+binder::impl_serialize_for_parcelable!(UnionInUnion);
+binder::impl_deserialize_for_parcelable!(UnionInUnion);
+impl binder::binder_impl::ParcelableMetadata for UnionInUnion {
+  fn get_descriptor() -> &'static str { "android.aidl.tests.unions.UnionInUnion" }
+}
+pub(crate) mod mangled {
+ pub use super::UnionInUnion as _7_android_4_aidl_5_tests_6_unions_12_UnionInUnion;
+}
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/UnionInUnion.rs.d b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/UnionInUnion.rs.d
index f5b5366..2376cf5 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/UnionInUnion.rs.d
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/UnionInUnion.rs.d
@@ -1,3 +1,5 @@
 out/soong/.intermediates/system/tools/aidl/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/UnionInUnion.rs : \
   system/tools/aidl/tests/android/aidl/tests/unions/UnionInUnion.aidl \
-  system/tools/aidl/tests/android/aidl/tests/unions/EnumUnion.aidl
+  system/tools/aidl/tests/android/aidl/tests/unions/EnumUnion.aidl \
+  system/tools/aidl/tests/android/aidl/tests/IntEnum.aidl \
+  system/tools/aidl/tests/android/aidl/tests/LongEnum.aidl
diff --git a/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java
new file mode 100644
index 0000000..7a85c41
--- /dev/null
+++ b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java
@@ -0,0 +1,130 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.versioned.tests;
+public final class BazUnion implements android.os.Parcelable {
+  // tags for union fields
+  public final static int intNum = 0;  // int intNum;
+  public final static int longNum = 1;  // long longNum;
+
+  private int _tag;
+  private Object _value;
+
+  public BazUnion() {
+    int _value = 0;
+    this._tag = intNum;
+    this._value = _value;
+  }
+
+  private BazUnion(android.os.Parcel _aidl_parcel) {
+    readFromParcel(_aidl_parcel);
+  }
+
+  private BazUnion(int _tag, Object _value) {
+    this._tag = _tag;
+    this._value = _value;
+  }
+
+  public int getTag() {
+    return _tag;
+  }
+
+  // int intNum;
+
+  public static BazUnion intNum(int _value) {
+    return new BazUnion(intNum, _value);
+  }
+
+  public int getIntNum() {
+    _assertTag(intNum);
+    return (int) _value;
+  }
+
+  public void setIntNum(int _value) {
+    _set(intNum, _value);
+  }
+
+  // long longNum;
+
+  public static BazUnion longNum(long _value) {
+    return new BazUnion(longNum, _value);
+  }
+
+  public long getLongNum() {
+    _assertTag(longNum);
+    return (long) _value;
+  }
+
+  public void setLongNum(long _value) {
+    _set(longNum, _value);
+  }
+
+  public static final android.os.Parcelable.Creator<BazUnion> CREATOR = new android.os.Parcelable.Creator<BazUnion>() {
+    @Override
+    public BazUnion createFromParcel(android.os.Parcel _aidl_source) {
+      return new BazUnion(_aidl_source);
+    }
+    @Override
+    public BazUnion[] newArray(int _aidl_size) {
+      return new BazUnion[_aidl_size];
+    }
+  };
+
+  @Override
+  public final void writeToParcel(android.os.Parcel _aidl_parcel, int _aidl_flag) {
+    _aidl_parcel.writeInt(_tag);
+    switch (_tag) {
+    case intNum:
+      _aidl_parcel.writeInt(getIntNum());
+      break;
+    case longNum:
+      _aidl_parcel.writeLong(getLongNum());
+      break;
+    }
+  }
+
+  public void readFromParcel(android.os.Parcel _aidl_parcel) {
+    int _aidl_tag;
+    _aidl_tag = _aidl_parcel.readInt();
+    switch (_aidl_tag) {
+    case intNum: {
+      int _aidl_value;
+      _aidl_value = _aidl_parcel.readInt();
+      _set(_aidl_tag, _aidl_value);
+      return; }
+    case longNum: {
+      long _aidl_value;
+      _aidl_value = _aidl_parcel.readLong();
+      _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;
+  }
+
+  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 intNum: return "intNum";
+    case longNum: return "longNum";
+    }
+    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-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java.d b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java.d
new file mode 100644
index 0000000..68d7b75
--- /dev/null
+++ b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/BazUnion.java : \
+  system/tools/aidl/aidl_api/aidl-test-versioned-interface/2/android/aidl/versioned/tests/BazUnion.aidl
diff --git a/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java
new file mode 100644
index 0000000..e58c2fb
--- /dev/null
+++ b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java
@@ -0,0 +1,50 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.versioned.tests;
+public class Foo implements android.os.Parcelable
+{
+  public int intDefault42 = 42;
+  public static final android.os.Parcelable.Creator<Foo> CREATOR = new android.os.Parcelable.Creator<Foo>() {
+    @Override
+    public Foo createFromParcel(android.os.Parcel _aidl_source) {
+      Foo _aidl_out = new Foo();
+      _aidl_out.readFromParcel(_aidl_source);
+      return _aidl_out;
+    }
+    @Override
+    public Foo[] newArray(int _aidl_size) {
+      return new Foo[_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.writeInt(intDefault42);
+    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 < 4) throw new android.os.BadParcelableException("Parcelable too small");;
+      if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
+      intDefault42 = _aidl_parcel.readInt();
+    } 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;
+  }
+}
diff --git a/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java.d b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java.d
new file mode 100644
index 0000000..b7db41a
--- /dev/null
+++ b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java.d
@@ -0,0 +1,2 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/Foo.java : \
+  system/tools/aidl/aidl_api/aidl-test-versioned-interface/2/android/aidl/versioned/tests/Foo.aidl
diff --git a/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java
new file mode 100644
index 0000000..f0f5777
--- /dev/null
+++ b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java
@@ -0,0 +1,334 @@
+/*
+ * This file is auto-generated.  DO NOT MODIFY.
+ */
+package android.aidl.versioned.tests;
+public interface IFooInterface extends android.os.IInterface
+{
+  /**
+   * The version of this interface that the caller is built against.
+   * This might be different from what {@link #getInterfaceVersion()
+   * getInterfaceVersion} returns as that is the version of the interface
+   * that the remote object is implementing.
+   */
+  public static final int VERSION = 2;
+  public static final String HASH = "da8c4bc94ca7feff0e0a65563a466787698b5891";
+  /** Default implementation for IFooInterface. */
+  public static class Default implements android.aidl.versioned.tests.IFooInterface
+  {
+    @Override public void originalApi() throws android.os.RemoteException
+    {
+    }
+    @Override public java.lang.String acceptUnionAndReturnString(android.aidl.versioned.tests.BazUnion u) throws android.os.RemoteException
+    {
+      return null;
+    }
+    @Override public int ignoreParcelablesAndRepeatInt(android.aidl.versioned.tests.Foo inFoo, android.aidl.versioned.tests.Foo inoutFoo, android.aidl.versioned.tests.Foo outFoo, int value) throws android.os.RemoteException
+    {
+      return 0;
+    }
+    @Override public int returnsLengthOfFooArray(android.aidl.versioned.tests.Foo[] foos) throws android.os.RemoteException
+    {
+      return 0;
+    }
+    @Override public void newApi() throws android.os.RemoteException
+    {
+    }
+    @Override
+    public int getInterfaceVersion() {
+      return 0;
+    }
+    @Override
+    public String getInterfaceHash() {
+      return "";
+    }
+    @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.versioned.tests.IFooInterface
+  {
+    /** Construct the stub at attach it to the interface. */
+    public Stub()
+    {
+      this.attachInterface(this, DESCRIPTOR);
+    }
+    /**
+     * Cast an IBinder object into an android.aidl.versioned.tests.IFooInterface interface,
+     * generating a proxy if needed.
+     */
+    public static android.aidl.versioned.tests.IFooInterface asInterface(android.os.IBinder obj)
+    {
+      if ((obj==null)) {
+        return null;
+      }
+      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+      if (((iin!=null)&&(iin instanceof android.aidl.versioned.tests.IFooInterface))) {
+        return ((android.aidl.versioned.tests.IFooInterface)iin);
+      }
+      return new android.aidl.versioned.tests.IFooInterface.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;
+        }
+        case TRANSACTION_getInterfaceVersion:
+        {
+          reply.writeNoException();
+          reply.writeInt(getInterfaceVersion());
+          return true;
+        }
+        case TRANSACTION_getInterfaceHash:
+        {
+          reply.writeNoException();
+          reply.writeString(getInterfaceHash());
+          return true;
+        }
+      }
+      switch (code)
+      {
+        case TRANSACTION_originalApi:
+        {
+          this.originalApi();
+          reply.writeNoException();
+          break;
+        }
+        case TRANSACTION_acceptUnionAndReturnString:
+        {
+          android.aidl.versioned.tests.BazUnion _arg0;
+          _arg0 = data.readTypedObject(android.aidl.versioned.tests.BazUnion.CREATOR);
+          data.enforceNoDataAvail();
+          java.lang.String _result = this.acceptUnionAndReturnString(_arg0);
+          reply.writeNoException();
+          reply.writeString(_result);
+          break;
+        }
+        case TRANSACTION_ignoreParcelablesAndRepeatInt:
+        {
+          android.aidl.versioned.tests.Foo _arg0;
+          _arg0 = data.readTypedObject(android.aidl.versioned.tests.Foo.CREATOR);
+          android.aidl.versioned.tests.Foo _arg1;
+          _arg1 = data.readTypedObject(android.aidl.versioned.tests.Foo.CREATOR);
+          android.aidl.versioned.tests.Foo _arg2;
+          _arg2 = new android.aidl.versioned.tests.Foo();
+          int _arg3;
+          _arg3 = data.readInt();
+          data.enforceNoDataAvail();
+          int _result = this.ignoreParcelablesAndRepeatInt(_arg0, _arg1, _arg2, _arg3);
+          reply.writeNoException();
+          reply.writeInt(_result);
+          reply.writeTypedObject(_arg1, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+          reply.writeTypedObject(_arg2, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+          break;
+        }
+        case TRANSACTION_returnsLengthOfFooArray:
+        {
+          android.aidl.versioned.tests.Foo[] _arg0;
+          _arg0 = data.createTypedArray(android.aidl.versioned.tests.Foo.CREATOR);
+          data.enforceNoDataAvail();
+          int _result = this.returnsLengthOfFooArray(_arg0);
+          reply.writeNoException();
+          reply.writeInt(_result);
+          break;
+        }
+        case TRANSACTION_newApi:
+        {
+          this.newApi();
+          reply.writeNoException();
+          break;
+        }
+        default:
+        {
+          return super.onTransact(code, data, reply, flags);
+        }
+      }
+      return true;
+    }
+    private static class Proxy implements android.aidl.versioned.tests.IFooInterface
+    {
+      private android.os.IBinder mRemote;
+      Proxy(android.os.IBinder remote)
+      {
+        mRemote = remote;
+      }
+      private int mCachedVersion = -1;
+      private String mCachedHash = "-1";
+      @Override public android.os.IBinder asBinder()
+      {
+        return mRemote;
+      }
+      public java.lang.String getInterfaceDescriptor()
+      {
+        return DESCRIPTOR;
+      }
+      @Override public void originalApi() throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_originalApi, _data, _reply, 0);
+          if (!_status) {
+            throw new android.os.RemoteException("Method originalApi is unimplemented.");
+          }
+          _reply.readException();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
+      @Override public java.lang.String acceptUnionAndReturnString(android.aidl.versioned.tests.BazUnion u) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        java.lang.String _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeTypedObject(u, 0);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_acceptUnionAndReturnString, _data, _reply, 0);
+          if (!_status) {
+            throw new android.os.RemoteException("Method acceptUnionAndReturnString is unimplemented.");
+          }
+          _reply.readException();
+          _result = _reply.readString();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public int ignoreParcelablesAndRepeatInt(android.aidl.versioned.tests.Foo inFoo, android.aidl.versioned.tests.Foo inoutFoo, android.aidl.versioned.tests.Foo outFoo, int value) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        int _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeTypedObject(inFoo, 0);
+          _data.writeTypedObject(inoutFoo, 0);
+          _data.writeInt(value);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_ignoreParcelablesAndRepeatInt, _data, _reply, 0);
+          if (!_status) {
+            throw new android.os.RemoteException("Method ignoreParcelablesAndRepeatInt is unimplemented.");
+          }
+          _reply.readException();
+          _result = _reply.readInt();
+          if ((0!=_reply.readInt())) {
+            inoutFoo.readFromParcel(_reply);
+          }
+          if ((0!=_reply.readInt())) {
+            outFoo.readFromParcel(_reply);
+          }
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public int returnsLengthOfFooArray(android.aidl.versioned.tests.Foo[] foos) throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        int _result;
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          _data.writeTypedArray(foos, 0);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_returnsLengthOfFooArray, _data, _reply, 0);
+          if (!_status) {
+            throw new android.os.RemoteException("Method returnsLengthOfFooArray is unimplemented.");
+          }
+          _reply.readException();
+          _result = _reply.readInt();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+        return _result;
+      }
+      @Override public void newApi() throws android.os.RemoteException
+      {
+        android.os.Parcel _data = android.os.Parcel.obtain();
+        android.os.Parcel _reply = android.os.Parcel.obtain();
+        try {
+          _data.writeInterfaceToken(DESCRIPTOR);
+          boolean _status = mRemote.transact(Stub.TRANSACTION_newApi, _data, _reply, 0);
+          if (!_status) {
+            throw new android.os.RemoteException("Method newApi is unimplemented.");
+          }
+          _reply.readException();
+        }
+        finally {
+          _reply.recycle();
+          _data.recycle();
+        }
+      }
+      @Override
+      public int getInterfaceVersion() throws android.os.RemoteException {
+        if (mCachedVersion == -1) {
+          android.os.Parcel data = android.os.Parcel.obtain();
+          android.os.Parcel reply = android.os.Parcel.obtain();
+          try {
+            data.writeInterfaceToken(DESCRIPTOR);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_getInterfaceVersion, data, reply, 0);
+            reply.readException();
+            mCachedVersion = reply.readInt();
+          } finally {
+            reply.recycle();
+            data.recycle();
+          }
+        }
+        return mCachedVersion;
+      }
+      @Override
+      public synchronized String getInterfaceHash() throws android.os.RemoteException {
+        if ("-1".equals(mCachedHash)) {
+          android.os.Parcel data = android.os.Parcel.obtain();
+          android.os.Parcel reply = android.os.Parcel.obtain();
+          try {
+            data.writeInterfaceToken(DESCRIPTOR);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_getInterfaceHash, data, reply, 0);
+            reply.readException();
+            mCachedHash = reply.readString();
+          } finally {
+            reply.recycle();
+            data.recycle();
+          }
+        }
+        return mCachedHash;
+      }
+    }
+    static final int TRANSACTION_originalApi = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+    static final int TRANSACTION_acceptUnionAndReturnString = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
+    static final int TRANSACTION_ignoreParcelablesAndRepeatInt = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
+    static final int TRANSACTION_returnsLengthOfFooArray = (android.os.IBinder.FIRST_CALL_TRANSACTION + 3);
+    static final int TRANSACTION_newApi = (android.os.IBinder.FIRST_CALL_TRANSACTION + 4);
+    static final int TRANSACTION_getInterfaceVersion = (android.os.IBinder.FIRST_CALL_TRANSACTION + 16777214);
+    static final int TRANSACTION_getInterfaceHash = (android.os.IBinder.FIRST_CALL_TRANSACTION + 16777213);
+  }
+  public static final java.lang.String DESCRIPTOR = "android$aidl$versioned$tests$IFooInterface".replace('$', '.');
+  public void originalApi() throws android.os.RemoteException;
+  public java.lang.String acceptUnionAndReturnString(android.aidl.versioned.tests.BazUnion u) throws android.os.RemoteException;
+  public int ignoreParcelablesAndRepeatInt(android.aidl.versioned.tests.Foo inFoo, android.aidl.versioned.tests.Foo inoutFoo, android.aidl.versioned.tests.Foo outFoo, int value) throws android.os.RemoteException;
+  public int returnsLengthOfFooArray(android.aidl.versioned.tests.Foo[] foos) throws android.os.RemoteException;
+  public void newApi() throws android.os.RemoteException;
+  public int getInterfaceVersion() throws android.os.RemoteException;
+  public String getInterfaceHash() throws android.os.RemoteException;
+}
diff --git a/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java.d b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java.d
new file mode 100644
index 0000000..b6dd541
--- /dev/null
+++ b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java.d
@@ -0,0 +1,4 @@
+out/soong/.intermediates/system/tools/aidl/aidl-test-versioned-interface-V2-java-source/gen/android/aidl/versioned/tests/IFooInterface.java : \
+  system/tools/aidl/aidl_api/aidl-test-versioned-interface/2/android/aidl/versioned/tests/IFooInterface.aidl \
+  system/tools/aidl/aidl_api/aidl-test-versioned-interface/2/android/aidl/versioned/tests/BazUnion.aidl \
+  system/tools/aidl/aidl_api/aidl-test-versioned-interface/2/android/aidl/versioned/tests/Foo.aidl
diff --git a/tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp b/tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/timestamp
similarity index 100%
copy from tests/golden_output/aidl-test-interface-ndk_platform-source/gen/timestamp
copy to tests/golden_output/aidl-test-versioned-interface-V2-java-source/gen/timestamp
diff --git a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/Data.cpp b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/Data.cpp
index b38dae4..5910ede 100644
--- a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/Data.cpp
+++ b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/Data.cpp
@@ -1,17 +1,18 @@
 #include <android/aidl/loggable/Data.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace loggable {
-
 ::android::status_t Data::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);
+  size_t _aidl_start_pos = _aidl_parcel->dataPosition();
+  int32_t _aidl_parcelable_raw_size = 0;
+  _aidl_ret_status = _aidl_parcel->readInt32(&_aidl_parcelable_raw_size);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    return _aidl_ret_status;
+  }
+  if (_aidl_parcelable_raw_size < 4) return ::android::BAD_VALUE;
+  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);
@@ -48,7 +49,6 @@
   _aidl_parcel->setDataPosition(_aidl_start_pos + _aidl_parcelable_size);
   return _aidl_ret_status;
 }
-
 ::android::status_t Data::writeToParcel(::android::Parcel* _aidl_parcel) const {
   ::android::status_t _aidl_ret_status = ::android::OK;
   auto _aidl_start_pos = _aidl_parcel->dataPosition();
@@ -75,9 +75,6 @@
   _aidl_parcel->setDataPosition(_aidl_end_pos);
   return _aidl_ret_status;
 }
-
 }  // namespace loggable
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/ILoggableInterface.cpp b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/ILoggableInterface.cpp
index 931d9b1..676d78a 100644
--- a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/ILoggableInterface.cpp
+++ b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/ILoggableInterface.cpp
@@ -1,18 +1,11 @@
 #include <android/aidl/loggable/ILoggableInterface.h>
 #include <android/aidl/loggable/BpLoggableInterface.h>
-
 namespace android {
-
 namespace aidl {
-
 namespace loggable {
-
 DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(LoggableInterface, "android.aidl.loggable.ILoggableInterface")
-
 }  // namespace loggable
-
 }  // namespace aidl
-
 }  // namespace android
 #include <android/aidl/loggable/BpLoggableInterface.h>
 #include <android/aidl/loggable/BnLoggableInterface.h>
@@ -22,9 +15,7 @@
 #include <functional>
 
 namespace android {
-
 namespace aidl {
-
 namespace loggable {
 
 BpLoggableInterface::BpLoggableInterface(const ::android::sp<::android::IBinder>& _aidl_impl)
@@ -246,9 +237,7 @@
 }
 
 }  // namespace loggable
-
 }  // namespace aidl
-
 }  // namespace android
 #include <android/aidl/loggable/BnLoggableInterface.h>
 #include <binder/Parcel.h>
@@ -257,9 +246,7 @@
 #include <functional>
 
 namespace android {
-
 namespace aidl {
-
 namespace loggable {
 
 BnLoggableInterface::BnLoggableInterface()
@@ -408,6 +395,10 @@
       _transaction_log.input_args.emplace_back("in_pfdArray", ::android::internal::ToString(in_pfdArray));
     }
     auto _log_start = std::chrono::steady_clock::now();
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
     ::android::binder::Status _aidl_status(LogThis(in_boolValue, &in_boolArray, in_byteValue, &in_byteArray, in_charValue, &in_charArray, in_intValue, &in_intArray, in_longValue, &in_longArray, in_floatValue, &in_floatArray, in_doubleValue, &in_doubleArray, in_stringValue, &in_stringArray, &in_listValue, in_dataValue, in_binderValue, &in_pfdValue, &in_pfdArray, &_aidl_return));
     if (BnLoggableInterface::logFunc != nullptr) {
       auto _log_end = std::chrono::steady_clock::now();
@@ -498,15 +489,171 @@
   break;
   }
   if (_aidl_ret_status == ::android::UNEXPECTED_NULL) {
-    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeToParcel(_aidl_reply);
+    _aidl_ret_status = ::android::binder::Status::fromExceptionCode(::android::binder::Status::EX_NULL_POINTER).writeOverParcel(_aidl_reply);
   }
   return _aidl_ret_status;
 }
 
 std::function<void(const BnLoggableInterface::TransactionLog&)> BnLoggableInterface::logFunc;
+}  // namespace loggable
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/loggable/ILoggableInterface.h>
+#include <android/aidl/loggable/ILoggableInterface.h>
+namespace android {
+namespace aidl {
+namespace loggable {
+DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE(ILoggableInterface, Sub, "android.aidl.loggable.ILoggableInterface.ISub")
+}  // namespace loggable
+}  // namespace aidl
+}  // namespace android
+#include <android/aidl/loggable/ILoggableInterface.h>
+#include <android/aidl/loggable/ILoggableInterface.h>
+#include <binder/Parcel.h>
+#include <android-base/macros.h>
+#include <chrono>
+#include <functional>
+
+namespace android {
+namespace aidl {
+namespace loggable {
+
+ILoggableInterface::BpSub::BpSub(const ::android::sp<::android::IBinder>& _aidl_impl)
+    : BpInterface<ISub>(_aidl_impl){
+}
+
+std::function<void(const ILoggableInterface::BpSub::TransactionLog&)> ILoggableInterface::BpSub::logFunc;
+
+::android::binder::Status ILoggableInterface::BpSub::Log(int32_t value) {
+  ::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;
+  ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::ISub::Log::cppClient");
+  ILoggableInterface::BpSub::TransactionLog _transaction_log;
+  if (ILoggableInterface::BpSub::logFunc != nullptr) {
+    _transaction_log.input_args.emplace_back("value", ::android::internal::ToString(value));
+  }
+  auto _log_start = std::chrono::steady_clock::now();
+  _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = _aidl_data.writeInt32(value);
+  if (((_aidl_ret_status) != (::android::OK))) {
+    goto _aidl_error;
+  }
+  _aidl_ret_status = remote()->transact(ILoggableInterface::BnSub::TRANSACTION_Log, _aidl_data, &_aidl_reply, 0);
+  if (UNLIKELY(_aidl_ret_status == ::android::UNKNOWN_TRANSACTION && ISub::getDefaultImpl())) {
+     return ISub::getDefaultImpl()->Log(value);
+  }
+  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_error:
+  _aidl_status.setFromStatusT(_aidl_ret_status);
+  if (ILoggableInterface::BpSub::logFunc != nullptr) {
+    auto _log_end = std::chrono::steady_clock::now();
+    _transaction_log.duration_ms = std::chrono::duration<double, std::milli>(_log_end - _log_start).count();
+    _transaction_log.interface_name = "android.aidl.loggable.ILoggableInterface.ISub";
+    _transaction_log.method_name = "Log";
+    _transaction_log.stub_address = nullptr;
+    _transaction_log.proxy_address = static_cast<const void*>(this);
+    _transaction_log.exception_code = _aidl_status.exceptionCode();
+    _transaction_log.exception_message = _aidl_status.exceptionMessage();
+    _transaction_log.transaction_error = _aidl_status.transactionError();
+    _transaction_log.service_specific_error_code = _aidl_status.serviceSpecificErrorCode();
+    ILoggableInterface::BpSub::logFunc(_transaction_log);
+  }
+  return _aidl_status;
+}
 
 }  // namespace loggable
-
 }  // namespace aidl
+}  // namespace android
+#include <android/aidl/loggable/ILoggableInterface.h>
+#include <binder/Parcel.h>
+#include <binder/Stability.h>
+#include <chrono>
+#include <functional>
 
+namespace android {
+namespace aidl {
+namespace loggable {
+
+ILoggableInterface::BnSub::BnSub()
+{
+  ::android::internal::Stability::markCompilationUnit(this);
+}
+
+::android::status_t ILoggableInterface::BnSub::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 BnSub::TRANSACTION_Log:
+  {
+    int32_t in_value;
+    if (!(_aidl_data.checkInterface(this))) {
+      _aidl_ret_status = ::android::BAD_TYPE;
+      break;
+    }
+    ::android::ScopedTrace _aidl_trace(ATRACE_TAG_AIDL, "AIDL::cpp::ISub::Log::cppServer");
+    _aidl_ret_status = _aidl_data.readInt32(&in_value);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    ILoggableInterface::BnSub::TransactionLog _transaction_log;
+    if (ILoggableInterface::BnSub::logFunc != nullptr) {
+      _transaction_log.input_args.emplace_back("in_value", ::android::internal::ToString(in_value));
+    }
+    auto _log_start = std::chrono::steady_clock::now();
+    if (auto st = _aidl_data.enforceNoDataAvail(); !st.isOk()) {
+      _aidl_ret_status = st.writeToParcel(_aidl_reply);
+      break;
+    }
+    ::android::binder::Status _aidl_status(Log(in_value));
+    if (ILoggableInterface::BnSub::logFunc != nullptr) {
+      auto _log_end = std::chrono::steady_clock::now();
+      _transaction_log.duration_ms = std::chrono::duration<double, std::milli>(_log_end - _log_start).count();
+      _transaction_log.interface_name = "android.aidl.loggable.ILoggableInterface.ISub";
+      _transaction_log.method_name = "Log";
+      _transaction_log.stub_address = static_cast<const void*>(this);
+      _transaction_log.proxy_address = nullptr;
+      _transaction_log.exception_code = _aidl_status.exceptionCode();
+      _transaction_log.exception_message = _aidl_status.exceptionMessage();
+      _transaction_log.transaction_error = _aidl_status.transactionError();
+      _transaction_log.service_specific_error_code = _aidl_status.serviceSpecificErrorCode();
+      ILoggableInterface::BnSub::logFunc(_transaction_log);
+    }
+    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
+    if (((_aidl_ret_status) != (::android::OK))) {
+      break;
+    }
+    if (!_aidl_status.isOk()) {
+      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).writeOverParcel(_aidl_reply);
+  }
+  return _aidl_ret_status;
+}
+
+std::function<void(const ILoggableInterface::BnSub::TransactionLog&)> ILoggableInterface::BnSub::logFunc;
+}  // namespace loggable
+}  // namespace aidl
 }  // namespace android
diff --git a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/ILoggableInterface.cpp.d b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/ILoggableInterface.cpp.d
index 4f7a25f..ac79ae8 100644
--- a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/ILoggableInterface.cpp.d
+++ b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/ILoggableInterface.cpp.d
@@ -1,3 +1,5 @@
 out/soong/.intermediates/system/tools/aidl/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/ILoggableInterface.cpp : \
   system/tools/aidl/tests/android/aidl/loggable/ILoggableInterface.aidl \
-  system/tools/aidl/tests/android/aidl/loggable/Data.aidl
+  system/tools/aidl/tests/android/aidl/loggable/Data.aidl \
+  system/tools/aidl/tests/android/aidl/loggable/Union.aidl \
+  system/tools/aidl/tests/android/aidl/loggable/Enum.aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/Union.cpp b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/Union.cpp
index 4ec0683..092692e 100644
--- a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/Union.cpp
+++ b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/android/aidl/loggable/Union.cpp
@@ -1,11 +1,8 @@
 #include <android/aidl/loggable/Union.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace loggable {
-
 ::android::status_t Union::readFromParcel(const ::android::Parcel* _aidl_parcel) {
   ::android::status_t _aidl_ret_status;
   int32_t _aidl_tag;
@@ -34,7 +31,6 @@
   }
   return ::android::BAD_VALUE;
 }
-
 ::android::status_t Union::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;
@@ -44,9 +40,6 @@
   }
   __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
 }
-
 }  // namespace loggable
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/BnLoggableInterface.h b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/BnLoggableInterface.h
index 4e6ca8c..475068e 100644
--- a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/BnLoggableInterface.h
+++ b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/BnLoggableInterface.h
@@ -6,11 +6,8 @@
 #include <android/binder_to_string.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace loggable {
-
 class BnLoggableInterface : public ::android::BnInterface<ILoggableInterface> {
 public:
   static constexpr uint32_t TRANSACTION_LogThis = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
@@ -33,8 +30,16 @@
   static std::function<void(const TransactionLog&)> logFunc;
 };  // class BnLoggableInterface
 
+class ILoggableInterfaceDelegator : public BnLoggableInterface {
+public:
+  explicit ILoggableInterfaceDelegator(::android::sp<ILoggableInterface> &impl) : _aidl_delegate(impl) {}
+
+  ::android::binder::Status LogThis(bool boolValue, ::std::vector<bool>* boolArray, int8_t byteValue, ::std::vector<uint8_t>* byteArray, char16_t charValue, ::std::vector<char16_t>* charArray, int32_t intValue, ::std::vector<int32_t>* intArray, int64_t longValue, ::std::vector<int64_t>* longArray, float floatValue, ::std::vector<float>* floatArray, double doubleValue, ::std::vector<double>* doubleArray, const ::android::String16& stringValue, ::std::vector<::android::String16>* stringArray, ::std::vector<::android::String16>* listValue, const ::android::aidl::loggable::Data& dataValue, const ::android::sp<::android::IBinder>& binderValue, ::std::optional<::android::os::ParcelFileDescriptor>* pfdValue, ::std::vector<::android::os::ParcelFileDescriptor>* pfdArray, ::std::vector<::android::String16>* _aidl_return) override {
+    return _aidl_delegate->LogThis(boolValue, boolArray, byteValue, byteArray, charValue, charArray, intValue, intArray, longValue, longArray, floatValue, floatArray, doubleValue, doubleArray, stringValue, stringArray, listValue, dataValue, binderValue, pfdValue, pfdArray, _aidl_return);
+  }
+private:
+  ::android::sp<ILoggableInterface> _aidl_delegate;
+};  // class ILoggableInterfaceDelegator
 }  // namespace loggable
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/BpLoggableInterface.h b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/BpLoggableInterface.h
index 73219b8..c391dd4 100644
--- a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/BpLoggableInterface.h
+++ b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/BpLoggableInterface.h
@@ -8,11 +8,8 @@
 #include <android/binder_to_string.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace loggable {
-
 class BpLoggableInterface : public ::android::BpInterface<ILoggableInterface> {
 public:
   explicit BpLoggableInterface(const ::android::sp<::android::IBinder>& _aidl_impl);
@@ -34,9 +31,6 @@
   };
   static std::function<void(const TransactionLog&)> logFunc;
 };  // class BpLoggableInterface
-
 }  // namespace loggable
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/Data.h b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/Data.h
index 505a565..61b590e 100644
--- a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/Data.h
+++ b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/Data.h
@@ -11,13 +11,14 @@
 #include <utils/String16.h>
 
 namespace android {
-
 namespace aidl {
-
 namespace loggable {
-
 class Data : public ::android::Parcelable {
 public:
+  int32_t num = 0;
+  ::std::string str;
+  ::android::aidl::loggable::Union nestedUnion;
+  ::android::aidl::loggable::Enum nestedEnum = ::android::aidl::loggable::Enum::FOO;
   inline bool operator!=(const Data& rhs) const {
     return std::tie(num, str, nestedUnion, nestedEnum) != std::tie(rhs.num, rhs.str, rhs.nestedUnion, rhs.nestedEnum);
   }
@@ -37,10 +38,6 @@
     return std::tie(num, str, nestedUnion, nestedEnum) >= std::tie(rhs.num, rhs.str, rhs.nestedUnion, rhs.nestedEnum);
   }
 
-  int32_t num = int32_t(0);
-  ::std::string str;
-  ::android::aidl::loggable::Union nestedUnion;
-  ::android::aidl::loggable::Enum nestedEnum = ::android::aidl::loggable::Enum(::android::aidl::loggable::Enum::FOO);
   ::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() {
@@ -58,9 +55,6 @@
     return os.str();
   }
 };  // class Data
-
 }  // namespace loggable
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/Enum.h b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/Enum.h
index 7b5982b..c169661 100644
--- a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/Enum.h
+++ b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/Enum.h
@@ -6,15 +6,17 @@
 #include <string>
 
 namespace android {
-
 namespace aidl {
-
 namespace loggable {
-
 enum class Enum : int8_t {
   FOO = 42,
 };
-
+}  // namespace loggable
+}  // namespace aidl
+}  // namespace android
+namespace android {
+namespace aidl {
+namespace loggable {
 [[nodiscard]] static inline std::string toString(Enum val) {
   switch(val) {
   case Enum::FOO:
@@ -23,16 +25,11 @@
     return std::to_string(static_cast<int8_t>(val));
   }
 }
-
 }  // namespace loggable
-
 }  // namespace aidl
-
 }  // namespace android
 namespace android {
-
 namespace internal {
-
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wc++17-extensions"
 template <>
@@ -40,7 +37,5 @@
   ::android::aidl::loggable::Enum::FOO,
 };
 #pragma clang diagnostic pop
-
 }  // namespace internal
-
 }  // namespace android
diff --git a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/ILoggableInterface.h b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/ILoggableInterface.h
index c532e3d..2c2cfb9 100644
--- a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/ILoggableInterface.h
+++ b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/ILoggableInterface.h
@@ -1,11 +1,13 @@
 #pragma once
 
 #include <android/aidl/loggable/Data.h>
+#include <android/binder_to_string.h>
 #include <binder/IBinder.h>
 #include <binder/IInterface.h>
 #include <binder/ParcelFileDescriptor.h>
 #include <binder/Status.h>
 #include <cstdint>
+#include <functional>
 #include <optional>
 #include <utils/String16.h>
 #include <utils/StrongPointer.h>
@@ -13,14 +15,79 @@
 #include <vector>
 
 namespace android {
-
 namespace aidl {
-
 namespace loggable {
-
 class ILoggableInterface : public ::android::IInterface {
 public:
   DECLARE_META_INTERFACE(LoggableInterface)
+  class ISub : public ::android::IInterface {
+  public:
+    DECLARE_META_INTERFACE(Sub)
+    virtual ::android::binder::Status Log(int32_t value) = 0;
+  };  // class ISub
+
+  class ISubDefault : public ISub {
+  public:
+    ::android::IBinder* onAsBinder() override {
+      return nullptr;
+    }
+    ::android::binder::Status Log(int32_t /*value*/) override {
+      return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+  };  // class ISubDefault
+  class BpSub : public ::android::BpInterface<ISub> {
+  public:
+    explicit BpSub(const ::android::sp<::android::IBinder>& _aidl_impl);
+    virtual ~BpSub() = default;
+    ::android::binder::Status Log(int32_t value) override;
+    struct TransactionLog {
+      double duration_ms;
+      std::string interface_name;
+      std::string method_name;
+      const void* proxy_address;
+      const void* stub_address;
+      std::vector<std::pair<std::string, std::string>> input_args;
+      std::vector<std::pair<std::string, std::string>> output_args;
+      std::string result;
+      std::string exception_message;
+      int32_t exception_code;
+      int32_t transaction_error;
+      int32_t service_specific_error_code;
+    };
+    static std::function<void(const TransactionLog&)> logFunc;
+  };  // class BpSub
+  class BnSub : public ::android::BnInterface<ISub> {
+  public:
+    static constexpr uint32_t TRANSACTION_Log = ::android::IBinder::FIRST_CALL_TRANSACTION + 0;
+    explicit BnSub();
+    ::android::status_t onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) override;
+    struct TransactionLog {
+      double duration_ms;
+      std::string interface_name;
+      std::string method_name;
+      const void* proxy_address;
+      const void* stub_address;
+      std::vector<std::pair<std::string, std::string>> input_args;
+      std::vector<std::pair<std::string, std::string>> output_args;
+      std::string result;
+      std::string exception_message;
+      int32_t exception_code;
+      int32_t transaction_error;
+      int32_t service_specific_error_code;
+    };
+    static std::function<void(const TransactionLog&)> logFunc;
+  };  // class BnSub
+
+  class ISubDelegator : public BnSub {
+  public:
+    explicit ISubDelegator(::android::sp<ISub> &impl) : _aidl_delegate(impl) {}
+
+    ::android::binder::Status Log(int32_t value) override {
+      return _aidl_delegate->Log(value);
+    }
+  private:
+    ::android::sp<ISub> _aidl_delegate;
+  };  // class ISubDelegator
   virtual ::android::binder::Status LogThis(bool boolValue, ::std::vector<bool>* boolArray, int8_t byteValue, ::std::vector<uint8_t>* byteArray, char16_t charValue, ::std::vector<char16_t>* charArray, int32_t intValue, ::std::vector<int32_t>* intArray, int64_t longValue, ::std::vector<int64_t>* longArray, float floatValue, ::std::vector<float>* floatArray, double doubleValue, ::std::vector<double>* doubleArray, const ::android::String16& stringValue, ::std::vector<::android::String16>* stringArray, ::std::vector<::android::String16>* listValue, const ::android::aidl::loggable::Data& dataValue, const ::android::sp<::android::IBinder>& binderValue, ::std::optional<::android::os::ParcelFileDescriptor>* pfdValue, ::std::vector<::android::os::ParcelFileDescriptor>* pfdArray, ::std::vector<::android::String16>* _aidl_return) = 0;
 };  // class ILoggableInterface
 
@@ -29,13 +96,10 @@
   ::android::IBinder* onAsBinder() override {
     return nullptr;
   }
-  ::android::binder::Status LogThis(bool, ::std::vector<bool>*, int8_t, ::std::vector<uint8_t>*, char16_t, ::std::vector<char16_t>*, int32_t, ::std::vector<int32_t>*, int64_t, ::std::vector<int64_t>*, float, ::std::vector<float>*, double, ::std::vector<double>*, const ::android::String16&, ::std::vector<::android::String16>*, ::std::vector<::android::String16>*, const ::android::aidl::loggable::Data&, const ::android::sp<::android::IBinder>&, ::std::optional<::android::os::ParcelFileDescriptor>*, ::std::vector<::android::os::ParcelFileDescriptor>*, ::std::vector<::android::String16>*) override {
+  ::android::binder::Status LogThis(bool /*boolValue*/, ::std::vector<bool>* /*boolArray*/, int8_t /*byteValue*/, ::std::vector<uint8_t>* /*byteArray*/, char16_t /*charValue*/, ::std::vector<char16_t>* /*charArray*/, int32_t /*intValue*/, ::std::vector<int32_t>* /*intArray*/, int64_t /*longValue*/, ::std::vector<int64_t>* /*longArray*/, float /*floatValue*/, ::std::vector<float>* /*floatArray*/, double /*doubleValue*/, ::std::vector<double>* /*doubleArray*/, const ::android::String16& /*stringValue*/, ::std::vector<::android::String16>* /*stringArray*/, ::std::vector<::android::String16>* /*listValue*/, const ::android::aidl::loggable::Data& /*dataValue*/, const ::android::sp<::android::IBinder>& /*binderValue*/, ::std::optional<::android::os::ParcelFileDescriptor>* /*pfdValue*/, ::std::vector<::android::os::ParcelFileDescriptor>* /*pfdArray*/, ::std::vector<::android::String16>* /*_aidl_return*/) override {
     return ::android::binder::Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
   }
 };  // class ILoggableInterfaceDefault
-
 }  // namespace loggable
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/Union.h b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/Union.h
index 5891ba3..918f117 100644
--- a/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/Union.h
+++ b/tests/golden_output/aidl_test_loggable_interface-cpp-source/gen/include/android/aidl/loggable/Union.h
@@ -16,32 +16,10 @@
 #endif
 
 namespace android {
-
 namespace aidl {
-
 namespace loggable {
-
 class Union : public ::android::Parcelable {
 public:
-  inline bool operator!=(const Union& rhs) const {
-    return _value != rhs._value;
-  }
-  inline bool operator<(const Union& rhs) const {
-    return _value < rhs._value;
-  }
-  inline bool operator<=(const Union& rhs) const {
-    return _value <= rhs._value;
-  }
-  inline bool operator==(const Union& rhs) const {
-    return _value == rhs._value;
-  }
-  inline bool operator>(const Union& rhs) const {
-    return _value > rhs._value;
-  }
-  inline bool operator>=(const Union& rhs) const {
-    return _value >= rhs._value;
-  }
-
   enum Tag : int32_t {
     num = 0,  // int num;
     str,  // String str;
@@ -51,10 +29,6 @@
   static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, Union>;
 
   Union() : _value(std::in_place_index<num>, int32_t(43)) { }
-  Union(const Union&) = default;
-  Union(Union&&) = default;
-  Union& operator=(const Union&) = default;
-  Union& operator=(Union&&) = default;
 
   template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
   // NOLINTNEXTLINE(google-explicit-constructor)
@@ -96,6 +70,25 @@
     _value.emplace<_tag>(std::forward<_Tp>(_args)...);
   }
 
+  inline bool operator!=(const Union& rhs) const {
+    return _value != rhs._value;
+  }
+  inline bool operator<(const Union& rhs) const {
+    return _value < rhs._value;
+  }
+  inline bool operator<=(const Union& rhs) const {
+    return _value <= rhs._value;
+  }
+  inline bool operator==(const Union& rhs) const {
+    return _value == rhs._value;
+  }
+  inline bool operator>(const Union& rhs) const {
+    return _value > rhs._value;
+  }
+  inline bool operator>=(const Union& rhs) const {
+    return _value >= rhs._value;
+  }
+
   ::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() {
@@ -115,9 +108,6 @@
 private:
   std::variant<int32_t, ::std::string> _value;
 };  // class Union
-
 }  // namespace loggable
-
 }  // namespace aidl
-
 }  // namespace android
diff --git a/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/Data.java b/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/Data.java
index 4e1ebfd..5e54a99 100644
--- a/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/Data.java
+++ b/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/Data.java
@@ -26,13 +26,7 @@
     _aidl_parcel.writeInt(0);
     _aidl_parcel.writeInt(num);
     _aidl_parcel.writeString(str);
-    if ((nestedUnion!=null)) {
-      _aidl_parcel.writeInt(1);
-      nestedUnion.writeToParcel(_aidl_parcel, 0);
-    }
-    else {
-      _aidl_parcel.writeInt(0);
-    }
+    _aidl_parcel.writeTypedObject(nestedUnion, 0);
     _aidl_parcel.writeByte(nestedEnum);
     int _aidl_end_pos = _aidl_parcel.dataPosition();
     _aidl_parcel.setDataPosition(_aidl_start_pos);
@@ -44,18 +38,13 @@
     int _aidl_start_pos = _aidl_parcel.dataPosition();
     int _aidl_parcelable_size = _aidl_parcel.readInt();
     try {
-      if (_aidl_parcelable_size < 0) return;
+      if (_aidl_parcelable_size < 4) throw new android.os.BadParcelableException("Parcelable too small");;
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       num = _aidl_parcel.readInt();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       str = _aidl_parcel.readString();
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
-      if ((0!=_aidl_parcel.readInt())) {
-        nestedUnion = android.aidl.loggable.Union.CREATOR.createFromParcel(_aidl_parcel);
-      }
-      else {
-        nestedUnion = null;
-      }
+      nestedUnion = _aidl_parcel.readTypedObject(android.aidl.loggable.Union.CREATOR);
       if (_aidl_parcel.dataPosition() - _aidl_start_pos >= _aidl_parcelable_size) return;
       nestedEnum = _aidl_parcel.readByte();
     } finally {
diff --git a/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/ILoggableInterface.java b/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/ILoggableInterface.java
index bcb8001..ee02a61 100644
--- a/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/ILoggableInterface.java
+++ b/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/ILoggableInterface.java
@@ -46,6 +46,9 @@
     @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:
@@ -60,9 +63,8 @@
         {
           try {
             android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::ILoggableInterface::LogThis::server");
-            data.enforceInterface(descriptor);
             boolean _arg0;
-            _arg0 = (0!=data.readInt());
+            _arg0 = data.readBoolean();
             boolean[] _arg1;
             _arg1 = data.createBooleanArray();
             byte _arg2;
@@ -96,23 +98,14 @@
             java.util.List<java.lang.String> _arg16;
             _arg16 = data.createStringArrayList();
             android.aidl.loggable.Data _arg17;
-            if ((0!=data.readInt())) {
-              _arg17 = android.aidl.loggable.Data.CREATOR.createFromParcel(data);
-            }
-            else {
-              _arg17 = null;
-            }
+            _arg17 = data.readTypedObject(android.aidl.loggable.Data.CREATOR);
             android.os.IBinder _arg18;
             _arg18 = data.readStrongBinder();
             android.os.ParcelFileDescriptor _arg19;
-            if ((0!=data.readInt())) {
-              _arg19 = android.os.ParcelFileDescriptor.CREATOR.createFromParcel(data);
-            }
-            else {
-              _arg19 = null;
-            }
+            _arg19 = data.readTypedObject(android.os.ParcelFileDescriptor.CREATOR);
             android.os.ParcelFileDescriptor[] _arg20;
             _arg20 = data.createTypedArray(android.os.ParcelFileDescriptor.CREATOR);
+            data.enforceNoDataAvail();
             java.lang.String[] _result = this.LogThis(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8, _arg9, _arg10, _arg11, _arg12, _arg13, _arg14, _arg15, _arg16, _arg17, _arg18, _arg19, _arg20);
             reply.writeNoException();
             reply.writeStringArray(_result);
@@ -125,25 +118,20 @@
             reply.writeDoubleArray(_arg13);
             reply.writeStringArray(_arg15);
             reply.writeStringList(_arg16);
-            if ((_arg19!=null)) {
-              reply.writeInt(1);
-              _arg19.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-            }
-            else {
-              reply.writeInt(0);
-            }
+            reply.writeTypedObject(_arg19, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
             reply.writeTypedArray(_arg20, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
-            return true;
           }
           finally {
             android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
           }
+          break;
         }
         default:
         {
           return super.onTransact(code, data, reply, flags);
         }
       }
+      return true;
     }
     private static class Proxy implements android.aidl.loggable.ILoggableInterface
     {
@@ -168,7 +156,7 @@
         try {
           android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::ILoggableInterface::LogThis::client");
           _data.writeInterfaceToken(DESCRIPTOR);
-          _data.writeInt(((boolValue)?(1):(0)));
+          _data.writeBoolean(boolValue);
           _data.writeBooleanArray(boolArray);
           _data.writeByte(byteValue);
           _data.writeByteArray(byteArray);
@@ -185,28 +173,11 @@
           _data.writeString(stringValue);
           _data.writeStringArray(stringArray);
           _data.writeStringList(listValue);
-          if ((dataValue!=null)) {
-            _data.writeInt(1);
-            dataValue.writeToParcel(_data, 0);
-          }
-          else {
-            _data.writeInt(0);
-          }
+          _data.writeTypedObject(dataValue, 0);
           _data.writeStrongBinder(binderValue);
-          if ((pfdValue!=null)) {
-            _data.writeInt(1);
-            pfdValue.writeToParcel(_data, 0);
-          }
-          else {
-            _data.writeInt(0);
-          }
+          _data.writeTypedObject(pfdValue, 0);
           _data.writeTypedArray(pfdArray, 0);
           boolean _status = mRemote.transact(Stub.TRANSACTION_LogThis, _data, _reply, 0);
-          if (!_status) {
-            if (getDefaultImpl() != null) {
-              return getDefaultImpl().LogThis(boolValue, boolArray, byteValue, byteArray, charValue, charArray, intValue, intArray, longValue, longArray, floatValue, floatArray, doubleValue, doubleArray, stringValue, stringArray, listValue, dataValue, binderValue, pfdValue, pfdArray);
-            }
-          }
           _reply.readException();
           _result = _reply.createStringArray();
           _reply.readBooleanArray(boolArray);
@@ -230,26 +201,125 @@
         }
         return _result;
       }
-      public static android.aidl.loggable.ILoggableInterface sDefaultImpl;
     }
     static final int TRANSACTION_LogThis = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
-    public static boolean setDefaultImpl(android.aidl.loggable.ILoggableInterface 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.loggable.ILoggableInterface getDefaultImpl() {
-      return Stub.Proxy.sDefaultImpl;
-    }
   }
   public static final java.lang.String DESCRIPTOR = "android$aidl$loggable$ILoggableInterface".replace('$', '.');
   public java.lang.String[] LogThis(boolean boolValue, boolean[] boolArray, byte byteValue, byte[] byteArray, char charValue, char[] charArray, int intValue, int[] intArray, long longValue, long[] longArray, float floatValue, float[] floatArray, double doubleValue, double[] doubleArray, java.lang.String stringValue, java.lang.String[] stringArray, java.util.List<java.lang.String> listValue, android.aidl.loggable.Data dataValue, android.os.IBinder binderValue, android.os.ParcelFileDescriptor pfdValue, android.os.ParcelFileDescriptor[] pfdArray) throws android.os.RemoteException;
+  public interface ISub extends android.os.IInterface
+  {
+    /** Default implementation for ISub. */
+    public static class Default implements android.aidl.loggable.ILoggableInterface.ISub
+    {
+      @Override public void Log(int value) throws android.os.RemoteException
+      {
+      }
+      @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.loggable.ILoggableInterface.ISub
+    {
+      /** Construct the stub at attach it to the interface. */
+      public Stub()
+      {
+        this.attachInterface(this, DESCRIPTOR);
+      }
+      /**
+       * Cast an IBinder object into an android.aidl.loggable.ILoggableInterface.ISub interface,
+       * generating a proxy if needed.
+       */
+      public static android.aidl.loggable.ILoggableInterface.ISub asInterface(android.os.IBinder obj)
+      {
+        if ((obj==null)) {
+          return null;
+        }
+        android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
+        if (((iin!=null)&&(iin instanceof android.aidl.loggable.ILoggableInterface.ISub))) {
+          return ((android.aidl.loggable.ILoggableInterface.ISub)iin);
+        }
+        return new android.aidl.loggable.ILoggableInterface.ISub.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_Log:
+          {
+            try {
+              android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::ISub::Log::server");
+              int _arg0;
+              _arg0 = data.readInt();
+              data.enforceNoDataAvail();
+              this.Log(_arg0);
+              reply.writeNoException();
+            }
+            finally {
+              android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+            }
+            break;
+          }
+          default:
+          {
+            return super.onTransact(code, data, reply, flags);
+          }
+        }
+        return true;
+      }
+      private static class Proxy implements android.aidl.loggable.ILoggableInterface.ISub
+      {
+        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 void Log(int value) throws android.os.RemoteException
+        {
+          android.os.Parcel _data = android.os.Parcel.obtain();
+          android.os.Parcel _reply = android.os.Parcel.obtain();
+          try {
+            android.os.Trace.traceBegin(android.os.Trace.TRACE_TAG_AIDL, "AIDL::java::ISub::Log::client");
+            _data.writeInterfaceToken(DESCRIPTOR);
+            _data.writeInt(value);
+            boolean _status = mRemote.transact(Stub.TRANSACTION_Log, _data, _reply, 0);
+            _reply.readException();
+          }
+          finally {
+            _reply.recycle();
+            _data.recycle();
+            android.os.Trace.traceEnd(android.os.Trace.TRACE_TAG_AIDL);
+          }
+        }
+      }
+      static final int TRANSACTION_Log = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
+    }
+    public static final java.lang.String DESCRIPTOR = "android$aidl$loggable$ILoggableInterface$ISub".replace('$', '.');
+    public void Log(int value) throws android.os.RemoteException;
+  }
 }
diff --git a/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/ILoggableInterface.java.d b/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/ILoggableInterface.java.d
index 3563433..670f2c1 100644
--- a/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/ILoggableInterface.java.d
+++ b/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/ILoggableInterface.java.d
@@ -1,3 +1,5 @@
 out/soong/.intermediates/system/tools/aidl/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/ILoggableInterface.java : \
   system/tools/aidl/tests/android/aidl/loggable/ILoggableInterface.aidl \
-  system/tools/aidl/tests/android/aidl/loggable/Data.aidl
+  system/tools/aidl/tests/android/aidl/loggable/Data.aidl \
+  system/tools/aidl/tests/android/aidl/loggable/Union.aidl \
+  system/tools/aidl/tests/android/aidl/loggable/Enum.aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/Union.java b/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/Union.java
index 2126c93..1751db3 100644
--- a/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/Union.java
+++ b/tests/golden_output/aidl_test_loggable_interface-java-source/gen/android/aidl/loggable/Union.java
@@ -2,7 +2,6 @@
  * This file is auto-generated.  DO NOT MODIFY.
  */
 package android.aidl.loggable;
-
 public final class Union implements android.os.Parcelable {
   // tags for union fields
   public final static int num = 0;  // int num;
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/Data.cpp b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/Data.cpp
index 29ba3c3..2593fbf 100644
--- a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/Data.cpp
+++ b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/Data.cpp
@@ -8,67 +8,68 @@
 namespace loggable {
 const char* Data::descriptor = "android.aidl.loggable.Data";
 
-binder_status_t Data::readFromParcel(const AParcel* parcel) {
-  int32_t _aidl_parcelable_size;
-  int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  binder_status_t _aidl_ret_status = AParcel_readInt32(parcel, &_aidl_parcelable_size);
+binder_status_t Data::readFromParcel(const AParcel* _aidl_parcel) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  int32_t _aidl_start_pos = AParcel_getDataPosition(_aidl_parcel);
+  int32_t _aidl_parcelable_size = 0;
+  _aidl_ret_status = AParcel_readInt32(_aidl_parcel, &_aidl_parcelable_size);
+  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
+
+  if (_aidl_parcelable_size < 4) return STATUS_BAD_VALUE;
   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(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
+  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 = AParcel_readInt32(parcel, &num);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_parcel, &num);
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
 
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
+  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_readString(parcel, &str);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_parcel, &str);
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
 
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
+  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_readParcelable(parcel, &nestedUnion);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_parcel, &nestedUnion);
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
 
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
+  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 = AParcel_readByte(parcel, reinterpret_cast<int8_t*>(&nestedEnum));
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_parcel, &nestedEnum);
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
 
-  AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
+  AParcel_setDataPosition(_aidl_parcel, _aidl_start_pos + _aidl_parcelable_size);
   return _aidl_ret_status;
 }
-binder_status_t Data::writeToParcel(AParcel* parcel) const {
+binder_status_t Data::writeToParcel(AParcel* _aidl_parcel) const {
   binder_status_t _aidl_ret_status;
-  size_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  _aidl_ret_status = AParcel_writeInt32(parcel, 0);
+  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 = AParcel_writeInt32(parcel, num);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, num);
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
 
-  _aidl_ret_status = ::ndk::AParcel_writeString(parcel, str);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, str);
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
 
-  _aidl_ret_status = ::ndk::AParcel_writeParcelable(parcel, nestedUnion);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, nestedUnion);
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
 
-  _aidl_ret_status = AParcel_writeByte(parcel, static_cast<int8_t>(nestedEnum));
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_parcel, nestedEnum);
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
 
-  size_t _aidl_end_pos = AParcel_getDataPosition(parcel);
-  AParcel_setDataPosition(parcel, _aidl_start_pos);
-  AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);
-  AParcel_setDataPosition(parcel, _aidl_end_pos);
+  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;
 }
 
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/ILoggableInterface.cpp b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/ILoggableInterface.cpp
index 4835f3b..66d1e72 100644
--- a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/ILoggableInterface.cpp
+++ b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/ILoggableInterface.cpp
@@ -1,23 +1,22 @@
+#include "aidl/android/aidl/loggable/ILoggableInterface.h"
+
 #include <android/binder_parcel_utils.h>
-#include <aidl/android/aidl/loggable/BpLoggableInterface.h>
-#include <aidl/android/aidl/loggable/BnLoggableInterface.h>
-#include <aidl/android/aidl/loggable/ILoggableInterface.h>
 #include <android/binder_to_string.h>
+#include <aidl/android/aidl/loggable/BnLoggableInterface.h>
+#include <aidl/android/aidl/loggable/BpLoggableInterface.h>
+
+namespace {
+struct ScopedTrace {
+  inline explicit ScopedTrace(const char* name) { ATrace_beginSection(name); }
+  inline ~ScopedTrace() { ATrace_endSection(); }
+};
+}  // namespace
 
 namespace aidl {
 namespace android {
 namespace aidl {
 namespace loggable {
-class ScopedTrace {
-  public:
-  inline explicit ScopedTrace(const char* name) {
-  ATrace_beginSection(name);
-  }
-  inline ~ScopedTrace() {
-  ATrace_endSection();
-  }
-};
-static binder_status_t _aidl_onTransact(AIBinder* _aidl_binder, transaction_code_t _aidl_code, const AParcel* _aidl_in, AParcel* _aidl_out) {
+static binder_status_t _aidl_android_aidl_loggable_ILoggableInterface_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;
@@ -48,67 +47,67 @@
       std::vector<std::string> _aidl_return;
 
       ScopedTrace _aidl_trace("AIDL::ndk::ILoggableInterface::LogThis::server");
-      _aidl_ret_status = AParcel_readBool(_aidl_in, &in_boolValue);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_boolValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_boolArray);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_boolArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = AParcel_readByte(_aidl_in, &in_byteValue);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_byteValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_byteArray);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_byteArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = AParcel_readChar(_aidl_in, &in_charValue);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_charValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_charArray);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_charArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = AParcel_readInt32(_aidl_in, &in_intValue);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_intValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_intArray);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_intArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = AParcel_readInt64(_aidl_in, &in_longValue);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_longValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_longArray);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_longArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = AParcel_readFloat(_aidl_in, &in_floatValue);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_floatValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_floatArray);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_floatArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = AParcel_readDouble(_aidl_in, &in_doubleValue);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_doubleValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_doubleArray);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_doubleArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readString(_aidl_in, &in_stringValue);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_stringValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_stringArray);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_stringArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_listValue);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_listValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readParcelable(_aidl_in, &in_dataValue);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_dataValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readNullableStrongBinder(_aidl_in, &in_binderValue);
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_binderValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readNullableParcelFileDescriptor(_aidl_in, &in_pfdValue);
+      _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_in, &in_pfdValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_pfdArray);
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_pfdArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
       BnLoggableInterface::TransactionLog _transaction_log;
@@ -167,40 +166,40 @@
 
       if (!AStatus_isOk(_aidl_status.get())) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, _aidl_return);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, _aidl_return);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_boolArray);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, in_boolArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_byteArray);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, in_byteArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_charArray);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, in_charArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_intArray);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, in_intArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_longArray);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, in_longArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_floatArray);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, in_floatArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_doubleArray);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, in_doubleArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_stringArray);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, in_stringArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_listValue);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, in_listValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeNullableParcelFileDescriptor(_aidl_out, in_pfdValue);
+      _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_out, in_pfdValue);
       if (_aidl_ret_status != STATUS_OK) break;
 
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_pfdArray);
+      _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_out, in_pfdArray);
       if (_aidl_ret_status != STATUS_OK) break;
 
       break;
@@ -209,7 +208,7 @@
   return _aidl_ret_status;
 }
 
-static AIBinder_Class* _g_aidl_clazz = ::ndk::ICInterface::defineClass(ILoggableInterface::descriptor, _aidl_onTransact);
+static AIBinder_Class* _g_aidl_android_aidl_loggable_ILoggableInterface_clazz = ::ndk::ICInterface::defineClass(ILoggableInterface::descriptor, _aidl_android_aidl_loggable_ILoggableInterface_onTransact);
 
 BpLoggableInterface::BpLoggableInterface(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
 BpLoggableInterface::~BpLoggableInterface() {}
@@ -250,67 +249,67 @@
   _aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeBool(_aidl_in.get(), in_boolValue);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_boolValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_boolArray);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), *in_boolArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeByte(_aidl_in.get(), in_byteValue);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_byteValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_byteArray);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), *in_byteArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeChar(_aidl_in.get(), in_charValue);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_charValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_charArray);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), *in_charArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeInt32(_aidl_in.get(), in_intValue);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_intValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_intArray);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), *in_intArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeInt64(_aidl_in.get(), in_longValue);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_longValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_longArray);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), *in_longArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeFloat(_aidl_in.get(), in_floatValue);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_floatValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_floatArray);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), *in_floatArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = AParcel_writeDouble(_aidl_in.get(), in_doubleValue);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_doubleValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_doubleArray);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), *in_doubleArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_in.get(), in_stringValue);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_stringValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_stringArray);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), *in_stringArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_listValue);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), *in_listValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeParcelable(_aidl_in.get(), in_dataValue);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_dataValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeNullableStrongBinder(_aidl_in.get(), in_binderValue);
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), in_binderValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeNullableParcelFileDescriptor(_aidl_in.get(), *in_pfdValue);
+  _aidl_ret_status = ::ndk::AParcel_writeNullableData(_aidl_in.get(), *in_pfdValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_pfdArray);
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), *in_pfdArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_ret_status = AIBinder_transact(
@@ -333,40 +332,40 @@
   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);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), _aidl_return);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_boolArray);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), in_boolArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_byteArray);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), in_byteArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_charArray);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), in_charArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_intArray);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), in_intArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_longArray);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), in_longArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_floatArray);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), in_floatArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_doubleArray);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), in_doubleArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_stringArray);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), in_stringArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_listValue);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), in_listValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readNullableParcelFileDescriptor(_aidl_out.get(), in_pfdValue);
+  _aidl_ret_status = ::ndk::AParcel_readNullableData(_aidl_out.get(), in_pfdValue);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_pfdArray);
+  _aidl_ret_status = ::ndk::AParcel_readData(_aidl_out.get(), in_pfdArray);
   if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
 
   _aidl_error:
@@ -404,7 +403,7 @@
 BnLoggableInterface::~BnLoggableInterface() {}
 std::function<void(const BnLoggableInterface::TransactionLog&)> BnLoggableInterface::logFunc;
 ::ndk::SpAIBinder BnLoggableInterface::createBinder() {
-  AIBinder* binder = AIBinder_new(_g_aidl_clazz, static_cast<void*>(this));
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_loggable_ILoggableInterface_clazz, static_cast<void*>(this));
   #ifdef BINDER_STABILITY_SUPPORT
   AIBinder_markCompilationUnitStability(binder);
   #endif  // BINDER_STABILITY_SUPPORT
@@ -417,7 +416,7 @@
 
 
 std::shared_ptr<ILoggableInterface> ILoggableInterface::fromBinder(const ::ndk::SpAIBinder& binder) {
-  if (!AIBinder_associateClass(binder.get(), _g_aidl_clazz)) { return nullptr; }
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_loggable_ILoggableInterface_clazz)) { return nullptr; }
   std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
   if (interface) {
     return std::static_pointer_cast<ILoggableInterface>(interface);
@@ -465,3 +464,178 @@
 }  // namespace aidl
 }  // namespace android
 }  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace loggable {
+static binder_status_t _aidl_android_aidl_loggable_ILoggableInterface_ISub_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<ILoggableInterface::BnSub> _aidl_impl = std::static_pointer_cast<ILoggableInterface::BnSub>(::ndk::ICInterface::asInterface(_aidl_binder));
+  switch (_aidl_code) {
+    case (FIRST_CALL_TRANSACTION + 0 /*Log*/): {
+      int32_t in_value;
+
+      ScopedTrace _aidl_trace("AIDL::ndk::ISub::Log::server");
+      _aidl_ret_status = ::ndk::AParcel_readData(_aidl_in, &in_value);
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      ILoggableInterface::BnSub::TransactionLog _transaction_log;
+      if (ILoggableInterface::BnSub::logFunc != nullptr) {
+        _transaction_log.input_args.emplace_back("in_value", ::android::internal::ToString(in_value));
+      }
+      auto _log_start = std::chrono::steady_clock::now();
+      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->Log(in_value);
+      if (ILoggableInterface::BnSub::logFunc != nullptr) {
+        auto _log_end = std::chrono::steady_clock::now();
+        _transaction_log.duration_ms = std::chrono::duration<double, std::milli>(_log_end - _log_start).count();
+        _transaction_log.interface_name = "android.aidl.loggable.ILoggableInterface.ISub";
+        _transaction_log.method_name = "Log";
+        _transaction_log.stub_address = _aidl_impl.get();
+        _transaction_log.proxy_address = nullptr;
+        _transaction_log.exception_code = AStatus_getExceptionCode(_aidl_status.get());
+        _transaction_log.exception_message = AStatus_getMessage(_aidl_status.get());
+        _transaction_log.transaction_error = AStatus_getStatus(_aidl_status.get());
+        _transaction_log.service_specific_error_code = AStatus_getServiceSpecificError(_aidl_status.get());
+        ILoggableInterface::BnSub::logFunc(_transaction_log);
+      }
+      _aidl_ret_status = AParcel_writeStatusHeader(_aidl_out, _aidl_status.get());
+      if (_aidl_ret_status != STATUS_OK) break;
+
+      if (!AStatus_isOk(_aidl_status.get())) break;
+
+      break;
+    }
+  }
+  return _aidl_ret_status;
+}
+
+static AIBinder_Class* _g_aidl_android_aidl_loggable_ILoggableInterface_ISub_clazz = ::ndk::ICInterface::defineClass(ILoggableInterface::ISub::descriptor, _aidl_android_aidl_loggable_ILoggableInterface_ISub_onTransact);
+
+ILoggableInterface::BpSub::BpSub(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
+ILoggableInterface::BpSub::~BpSub() {}
+std::function<void(const ILoggableInterface::BpSub::TransactionLog&)> ILoggableInterface::BpSub::logFunc;
+
+::ndk::ScopedAStatus ILoggableInterface::BpSub::Log(int32_t in_value) {
+  binder_status_t _aidl_ret_status = STATUS_OK;
+  ::ndk::ScopedAStatus _aidl_status;
+  ::ndk::ScopedAParcel _aidl_in;
+  ::ndk::ScopedAParcel _aidl_out;
+
+  ILoggableInterface::BpSub::TransactionLog _transaction_log;
+  if (ILoggableInterface::BpSub::logFunc != nullptr) {
+    _transaction_log.input_args.emplace_back("in_value", ::android::internal::ToString(in_value));
+  }
+  auto _log_start = std::chrono::steady_clock::now();
+  ScopedTrace _aidl_trace("AIDL::ndk::ISub::Log::client");
+  _aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = ::ndk::AParcel_writeData(_aidl_in.get(), in_value);
+  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
+
+  _aidl_ret_status = AIBinder_transact(
+    asBinder().get(),
+    (FIRST_CALL_TRANSACTION + 0 /*Log*/),
+    _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 && ISub::getDefaultImpl()) {
+    _aidl_status = ISub::getDefaultImpl()->Log(in_value);
+    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_error:
+  _aidl_status.set(AStatus_fromStatus(_aidl_ret_status));
+  _aidl_status_return:
+  if (ILoggableInterface::BpSub::logFunc != nullptr) {
+    auto _log_end = std::chrono::steady_clock::now();
+    _transaction_log.duration_ms = std::chrono::duration<double, std::milli>(_log_end - _log_start).count();
+    _transaction_log.interface_name = "android.aidl.loggable.ILoggableInterface.ISub";
+    _transaction_log.method_name = "Log";
+    _transaction_log.stub_address = nullptr;
+    _transaction_log.proxy_address = static_cast<const void*>(this);
+    _transaction_log.exception_code = AStatus_getExceptionCode(_aidl_status.get());
+    _transaction_log.exception_message = AStatus_getMessage(_aidl_status.get());
+    _transaction_log.transaction_error = AStatus_getStatus(_aidl_status.get());
+    _transaction_log.service_specific_error_code = AStatus_getServiceSpecificError(_aidl_status.get());
+    ILoggableInterface::BpSub::logFunc(_transaction_log);
+  }
+  return _aidl_status;
+}
+// Source for BnSub
+ILoggableInterface::BnSub::BnSub() {}
+ILoggableInterface::BnSub::~BnSub() {}
+std::function<void(const ILoggableInterface::BnSub::TransactionLog&)> ILoggableInterface::BnSub::logFunc;
+::ndk::SpAIBinder ILoggableInterface::BnSub::createBinder() {
+  AIBinder* binder = AIBinder_new(_g_aidl_android_aidl_loggable_ILoggableInterface_ISub_clazz, static_cast<void*>(this));
+  #ifdef BINDER_STABILITY_SUPPORT
+  AIBinder_markCompilationUnitStability(binder);
+  #endif  // BINDER_STABILITY_SUPPORT
+  return ::ndk::SpAIBinder(binder);
+}
+// Source for ISub
+const char* ILoggableInterface::ISub::descriptor = "android.aidl.loggable.ILoggableInterface.ISub";
+ILoggableInterface::ISub::ISub() {}
+ILoggableInterface::ISub::~ISub() {}
+
+
+std::shared_ptr<ILoggableInterface::ISub> ILoggableInterface::ISub::fromBinder(const ::ndk::SpAIBinder& binder) {
+  if (!AIBinder_associateClass(binder.get(), _g_aidl_android_aidl_loggable_ILoggableInterface_ISub_clazz)) { return nullptr; }
+  std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
+  if (interface) {
+    return std::static_pointer_cast<ISub>(interface);
+  }
+  return ::ndk::SharedRefBase::make<ILoggableInterface::BpSub>(binder);
+}
+
+binder_status_t ILoggableInterface::ISub::writeToParcel(AParcel* parcel, const std::shared_ptr<ISub>& instance) {
+  return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : nullptr);
+}
+binder_status_t ILoggableInterface::ISub::readFromParcel(const AParcel* parcel, std::shared_ptr<ISub>* instance) {
+  ::ndk::SpAIBinder binder;
+  binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());
+  if (status != STATUS_OK) return status;
+  *instance = ISub::fromBinder(binder);
+  return STATUS_OK;
+}
+bool ILoggableInterface::ISub::setDefaultImpl(const std::shared_ptr<ISub>& 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(!ISub::default_impl);
+  if (impl) {
+    ISub::default_impl = impl;
+    return true;
+  }
+  return false;
+}
+const std::shared_ptr<ILoggableInterface::ISub>& ILoggableInterface::ISub::getDefaultImpl() {
+  return ISub::default_impl;
+}
+std::shared_ptr<ILoggableInterface::ISub> ILoggableInterface::ISub::default_impl = nullptr;
+::ndk::ScopedAStatus ILoggableInterface::ISubDefault::Log(int32_t /*in_value*/) {
+  ::ndk::ScopedAStatus _aidl_status;
+  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
+  return _aidl_status;
+}
+::ndk::SpAIBinder ILoggableInterface::ISubDefault::asBinder() {
+  return ::ndk::SpAIBinder();
+}
+bool ILoggableInterface::ISubDefault::isRemote() {
+  return false;
+}
+}  // namespace loggable
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/ILoggableInterface.cpp.d b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/ILoggableInterface.cpp.d
index f5c556d..3bcdcd4 100644
--- a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/ILoggableInterface.cpp.d
+++ b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/ILoggableInterface.cpp.d
@@ -1,3 +1,5 @@
 out/soong/.intermediates/system/tools/aidl/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/ILoggableInterface.cpp : \
   system/tools/aidl/tests/android/aidl/loggable/ILoggableInterface.aidl \
-  system/tools/aidl/tests/android/aidl/loggable/Data.aidl
+  system/tools/aidl/tests/android/aidl/loggable/Data.aidl \
+  system/tools/aidl/tests/android/aidl/loggable/Union.aidl \
+  system/tools/aidl/tests/android/aidl/loggable/Enum.aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/Union.cpp b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/Union.cpp
index 7d02d4d..aec5ed6 100644
--- a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/Union.cpp
+++ b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/android/aidl/loggable/Union.cpp
@@ -11,11 +11,11 @@
 binder_status_t Union::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;
+  if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_tag)) != STATUS_OK) return _aidl_ret_status;
   switch (_aidl_tag) {
   case num: {
     int32_t _aidl_value;
-    if ((_aidl_ret_status = AParcel_readInt32(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<int32_t>) {
       set<num>(_aidl_value);
     } else {
@@ -25,7 +25,7 @@
     return STATUS_OK; }
   case str: {
     std::string _aidl_value;
-    if ((_aidl_ret_status = ::ndk::AParcel_readString(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
     if constexpr (std::is_trivially_copyable_v<std::string>) {
       set<str>(_aidl_value);
     } else {
@@ -37,11 +37,11 @@
   return STATUS_BAD_VALUE;
 }
 binder_status_t Union::writeToParcel(AParcel* _parcel) const {
-  binder_status_t _aidl_ret_status = AParcel_writeInt32(_parcel, getTag());
+  binder_status_t _aidl_ret_status = ::ndk::AParcel_writeData(_parcel, getTag());
   if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
   switch (getTag()) {
-  case num: return AParcel_writeInt32(_parcel, get<num>());
-  case str: return ::ndk::AParcel_writeString(_parcel, get<str>());
+  case num: return ::ndk::AParcel_writeData(_parcel, get<num>());
+  case str: return ::ndk::AParcel_writeData(_parcel, get<str>());
   }
   __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
 }
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/Data.h b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/Data.h
index ecc788e..edd38e2 100644
--- a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/Data.h
+++ b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/Data.h
@@ -1,17 +1,19 @@
 #pragma once
-#include <android/binder_interface_utils.h>
-#include <android/binder_parcelable_utils.h>
-#include <android/binder_to_string.h>
+
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
+#include <aidl/android/aidl/loggable/Enum.h>
+#include <aidl/android/aidl/loggable/Union.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
-#include <aidl/android/aidl/loggable/Enum.h>
-#include <aidl/android/aidl/loggable/Union.h>
+
 namespace aidl {
 namespace android {
 namespace aidl {
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/Enum.h b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/Enum.h
index 1f02080..99542ab 100644
--- a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/Enum.h
+++ b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/Enum.h
@@ -1,15 +1,16 @@
 #pragma once
 
+#include <array>
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
 #include <vector>
+#include <android/binder_enums.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
-#include <array>
-#include <android/binder_enums.h>
+
 namespace aidl {
 namespace android {
 namespace aidl {
@@ -18,6 +19,14 @@
   FOO = 42,
 };
 
+}  // namespace loggable
+}  // namespace aidl
+}  // namespace android
+}  // namespace aidl
+namespace aidl {
+namespace android {
+namespace aidl {
+namespace loggable {
 [[nodiscard]] static inline std::string toString(Enum val) {
   switch(val) {
   case Enum::FOO:
@@ -40,4 +49,4 @@
 };
 #pragma clang diagnostic pop
 }  // namespace internal
-}  // namespace android
+}  // namespace ndk
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/ILoggableInterface.h b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/ILoggableInterface.h
index 33c79e1..9ab0248 100644
--- a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/ILoggableInterface.h
+++ b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/ILoggableInterface.h
@@ -1,19 +1,20 @@
 #pragma once
 
-#include <android/binder_interface_utils.h>
-#include <functional>
 #include <chrono>
-#include <sstream>
-
 #include <cstdint>
+#include <functional>
 #include <memory>
 #include <optional>
+#include <sstream>
 #include <string>
 #include <vector>
+#include <android/binder_ibinder.h>
+#include <android/binder_interface_utils.h>
+#include <android/trace.h>
+#include <aidl/android/aidl/loggable/Data.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
-#include <aidl/android/aidl/loggable/Data.h>
 
 namespace aidl {
 namespace android {
@@ -25,6 +26,74 @@
   ILoggableInterface();
   virtual ~ILoggableInterface();
 
+  class ISub : public ::ndk::ICInterface {
+  public:
+    static const char* descriptor;
+    ISub();
+    virtual ~ISub();
+
+    static constexpr uint32_t TRANSACTION_Log = FIRST_CALL_TRANSACTION + 0;
+
+    static std::shared_ptr<ISub> fromBinder(const ::ndk::SpAIBinder& binder);
+    static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<ISub>& instance);
+    static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<ISub>* instance);
+    static bool setDefaultImpl(const std::shared_ptr<ISub>& impl);
+    static const std::shared_ptr<ISub>& getDefaultImpl();
+    virtual ::ndk::ScopedAStatus Log(int32_t in_value) = 0;
+  private:
+    static std::shared_ptr<ISub> default_impl;
+  };
+  class ISubDefault : public ISub {
+  public:
+    ::ndk::ScopedAStatus Log(int32_t in_value) override;
+    ::ndk::SpAIBinder asBinder() override;
+    bool isRemote() override;
+  };
+  class BpSub : public ::ndk::BpCInterface<ISub> {
+  public:
+    explicit BpSub(const ::ndk::SpAIBinder& binder);
+    virtual ~BpSub();
+
+    ::ndk::ScopedAStatus Log(int32_t in_value) override;
+    struct TransactionLog {
+      double duration_ms;
+      std::string interface_name;
+      std::string method_name;
+      const void* proxy_address;
+      const void* stub_address;
+      std::vector<std::pair<std::string, std::string>> input_args;
+      std::vector<std::pair<std::string, std::string>> output_args;
+      std::string result;
+      std::string exception_message;
+      int32_t exception_code;
+      int32_t transaction_error;
+      int32_t service_specific_error_code;
+    };
+    static std::function<void(const TransactionLog&)> logFunc;
+  };
+  class BnSub : public ::ndk::BnCInterface<ISub> {
+  public:
+    BnSub();
+    virtual ~BnSub();
+    struct TransactionLog {
+      double duration_ms;
+      std::string interface_name;
+      std::string method_name;
+      const void* proxy_address;
+      const void* stub_address;
+      std::vector<std::pair<std::string, std::string>> input_args;
+      std::vector<std::pair<std::string, std::string>> output_args;
+      std::string result;
+      std::string exception_message;
+      int32_t exception_code;
+      int32_t transaction_error;
+      int32_t service_specific_error_code;
+    };
+    static std::function<void(const TransactionLog&)> logFunc;
+  protected:
+    ::ndk::SpAIBinder createBinder() override;
+  private:
+  };
   static constexpr uint32_t TRANSACTION_LogThis = FIRST_CALL_TRANSACTION + 0;
 
   static std::shared_ptr<ILoggableInterface> fromBinder(const ::ndk::SpAIBinder& binder);
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/Union.h b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/Union.h
index f53752a..ceb63ac 100644
--- a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/Union.h
+++ b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/Union.h
@@ -1,17 +1,17 @@
 #pragma once
-#include <android/binder_interface_utils.h>
-#include <android/binder_parcelable_utils.h>
-#include <android/binder_to_string.h>
 
 #include <cassert>
-#include <type_traits>
-#include <utility>
-#include <variant>
 #include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
+#include <type_traits>
+#include <utility>
+#include <variant>
 #include <vector>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#include <android/binder_to_string.h>
 #ifdef BINDER_STABILITY_SUPPORT
 #include <android/binder_stability.h>
 #endif  // BINDER_STABILITY_SUPPORT
@@ -38,10 +38,6 @@
   static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, Union>;
 
   Union() : _value(std::in_place_index<num>, int32_t(43)) { }
-  Union(const Union&) = default;
-  Union(Union&&) = default;
-  Union& operator=(const Union&) = default;
-  Union& operator=(Union&&) = default;
 
   template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
   // NOLINTNEXTLINE(google-explicit-constructor)
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Data.cpp b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Data.cpp
deleted file mode 100644
index 29ba3c3..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Data.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-#include "aidl/android/aidl/loggable/Data.h"
-
-#include <android/binder_parcel_utils.h>
-
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace loggable {
-const char* Data::descriptor = "android.aidl.loggable.Data";
-
-binder_status_t Data::readFromParcel(const AParcel* parcel) {
-  int32_t _aidl_parcelable_size;
-  int32_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  binder_status_t _aidl_ret_status = AParcel_readInt32(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(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readInt32(parcel, &num);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readString(parcel, &str);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = ::ndk::AParcel_readParcelable(parcel, &nestedUnion);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  if (AParcel_getDataPosition(parcel) - _aidl_start_pos >= _aidl_parcelable_size) {
-    AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-    return _aidl_ret_status;
-  }
-  _aidl_ret_status = AParcel_readByte(parcel, reinterpret_cast<int8_t*>(&nestedEnum));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  AParcel_setDataPosition(parcel, _aidl_start_pos + _aidl_parcelable_size);
-  return _aidl_ret_status;
-}
-binder_status_t Data::writeToParcel(AParcel* parcel) const {
-  binder_status_t _aidl_ret_status;
-  size_t _aidl_start_pos = AParcel_getDataPosition(parcel);
-  _aidl_ret_status = AParcel_writeInt32(parcel, 0);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeInt32(parcel, num);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeString(parcel, str);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = ::ndk::AParcel_writeParcelable(parcel, nestedUnion);
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  _aidl_ret_status = AParcel_writeByte(parcel, static_cast<int8_t>(nestedEnum));
-  if (_aidl_ret_status != STATUS_OK) return _aidl_ret_status;
-
-  size_t _aidl_end_pos = AParcel_getDataPosition(parcel);
-  AParcel_setDataPosition(parcel, _aidl_start_pos);
-  AParcel_writeInt32(parcel, _aidl_end_pos - _aidl_start_pos);
-  AParcel_setDataPosition(parcel, _aidl_end_pos);
-  return _aidl_ret_status;
-}
-
-}  // namespace loggable
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Data.cpp.d b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Data.cpp.d
deleted file mode 100644
index 490370d..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Data.cpp.d
+++ /dev/null
@@ -1,4 +0,0 @@
-out/soong/.intermediates/system/tools/aidl/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Data.cpp : \
-  system/tools/aidl/tests/android/aidl/loggable/Data.aidl \
-  system/tools/aidl/tests/android/aidl/loggable/Enum.aidl \
-  system/tools/aidl/tests/android/aidl/loggable/Union.aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Enum.cpp b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Enum.cpp
deleted file mode 100644
index eb1d7cb..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Enum.cpp
+++ /dev/null
@@ -1 +0,0 @@
-// This file is intentionally left blank as placeholder for enum declaration.
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Enum.cpp.d b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Enum.cpp.d
deleted file mode 100644
index ea5065b..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Enum.cpp.d
+++ /dev/null
@@ -1,2 +0,0 @@
-out/soong/.intermediates/system/tools/aidl/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Enum.cpp : \
-  system/tools/aidl/tests/android/aidl/loggable/Enum.aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/ILoggableInterface.cpp b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/ILoggableInterface.cpp
deleted file mode 100644
index 4835f3b..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/ILoggableInterface.cpp
+++ /dev/null
@@ -1,467 +0,0 @@
-#include <android/binder_parcel_utils.h>
-#include <aidl/android/aidl/loggable/BpLoggableInterface.h>
-#include <aidl/android/aidl/loggable/BnLoggableInterface.h>
-#include <aidl/android/aidl/loggable/ILoggableInterface.h>
-#include <android/binder_to_string.h>
-
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace loggable {
-class ScopedTrace {
-  public:
-  inline explicit ScopedTrace(const char* name) {
-  ATrace_beginSection(name);
-  }
-  inline ~ScopedTrace() {
-  ATrace_endSection();
-  }
-};
-static binder_status_t _aidl_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<BnLoggableInterface> _aidl_impl = std::static_pointer_cast<BnLoggableInterface>(::ndk::ICInterface::asInterface(_aidl_binder));
-  switch (_aidl_code) {
-    case (FIRST_CALL_TRANSACTION + 0 /*LogThis*/): {
-      bool in_boolValue;
-      std::vector<bool> in_boolArray;
-      int8_t in_byteValue;
-      std::vector<uint8_t> in_byteArray;
-      char16_t in_charValue;
-      std::vector<char16_t> in_charArray;
-      int32_t in_intValue;
-      std::vector<int32_t> in_intArray;
-      int64_t in_longValue;
-      std::vector<int64_t> in_longArray;
-      float in_floatValue;
-      std::vector<float> in_floatArray;
-      double in_doubleValue;
-      std::vector<double> in_doubleArray;
-      std::string in_stringValue;
-      std::vector<std::string> in_stringArray;
-      std::vector<std::string> in_listValue;
-      ::aidl::android::aidl::loggable::Data in_dataValue;
-      ::ndk::SpAIBinder in_binderValue;
-      ::ndk::ScopedFileDescriptor in_pfdValue;
-      std::vector<::ndk::ScopedFileDescriptor> in_pfdArray;
-      std::vector<std::string> _aidl_return;
-
-      ScopedTrace _aidl_trace("AIDL::ndk::ILoggableInterface::LogThis::server");
-      _aidl_ret_status = AParcel_readBool(_aidl_in, &in_boolValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_boolArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = AParcel_readByte(_aidl_in, &in_byteValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_byteArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = AParcel_readChar(_aidl_in, &in_charValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_charArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = AParcel_readInt32(_aidl_in, &in_intValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_intArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = AParcel_readInt64(_aidl_in, &in_longValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_longArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = AParcel_readFloat(_aidl_in, &in_floatValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_floatArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = AParcel_readDouble(_aidl_in, &in_doubleValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_doubleArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readString(_aidl_in, &in_stringValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_stringArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_listValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readParcelable(_aidl_in, &in_dataValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readNullableStrongBinder(_aidl_in, &in_binderValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readNullableParcelFileDescriptor(_aidl_in, &in_pfdValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_in, &in_pfdArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      BnLoggableInterface::TransactionLog _transaction_log;
-      if (BnLoggableInterface::logFunc != nullptr) {
-        _transaction_log.input_args.emplace_back("in_boolValue", ::android::internal::ToString(in_boolValue));
-        _transaction_log.input_args.emplace_back("in_boolArray", ::android::internal::ToString(in_boolArray));
-        _transaction_log.input_args.emplace_back("in_byteValue", ::android::internal::ToString(in_byteValue));
-        _transaction_log.input_args.emplace_back("in_byteArray", ::android::internal::ToString(in_byteArray));
-        _transaction_log.input_args.emplace_back("in_charValue", ::android::internal::ToString(in_charValue));
-        _transaction_log.input_args.emplace_back("in_charArray", ::android::internal::ToString(in_charArray));
-        _transaction_log.input_args.emplace_back("in_intValue", ::android::internal::ToString(in_intValue));
-        _transaction_log.input_args.emplace_back("in_intArray", ::android::internal::ToString(in_intArray));
-        _transaction_log.input_args.emplace_back("in_longValue", ::android::internal::ToString(in_longValue));
-        _transaction_log.input_args.emplace_back("in_longArray", ::android::internal::ToString(in_longArray));
-        _transaction_log.input_args.emplace_back("in_floatValue", ::android::internal::ToString(in_floatValue));
-        _transaction_log.input_args.emplace_back("in_floatArray", ::android::internal::ToString(in_floatArray));
-        _transaction_log.input_args.emplace_back("in_doubleValue", ::android::internal::ToString(in_doubleValue));
-        _transaction_log.input_args.emplace_back("in_doubleArray", ::android::internal::ToString(in_doubleArray));
-        _transaction_log.input_args.emplace_back("in_stringValue", ::android::internal::ToString(in_stringValue));
-        _transaction_log.input_args.emplace_back("in_stringArray", ::android::internal::ToString(in_stringArray));
-        _transaction_log.input_args.emplace_back("in_listValue", ::android::internal::ToString(in_listValue));
-        _transaction_log.input_args.emplace_back("in_dataValue", ::android::internal::ToString(in_dataValue));
-        _transaction_log.input_args.emplace_back("in_binderValue", ::android::internal::ToString(in_binderValue));
-        _transaction_log.input_args.emplace_back("in_pfdValue", ::android::internal::ToString(in_pfdValue));
-        _transaction_log.input_args.emplace_back("in_pfdArray", ::android::internal::ToString(in_pfdArray));
-      }
-      auto _log_start = std::chrono::steady_clock::now();
-      ::ndk::ScopedAStatus _aidl_status = _aidl_impl->LogThis(in_boolValue, &in_boolArray, in_byteValue, &in_byteArray, in_charValue, &in_charArray, in_intValue, &in_intArray, in_longValue, &in_longArray, in_floatValue, &in_floatArray, in_doubleValue, &in_doubleArray, in_stringValue, &in_stringArray, &in_listValue, in_dataValue, in_binderValue, &in_pfdValue, &in_pfdArray, &_aidl_return);
-      if (BnLoggableInterface::logFunc != nullptr) {
-        auto _log_end = std::chrono::steady_clock::now();
-        _transaction_log.duration_ms = std::chrono::duration<double, std::milli>(_log_end - _log_start).count();
-        _transaction_log.interface_name = "android.aidl.loggable.ILoggableInterface";
-        _transaction_log.method_name = "LogThis";
-        _transaction_log.stub_address = _aidl_impl.get();
-        _transaction_log.proxy_address = nullptr;
-        _transaction_log.exception_code = AStatus_getExceptionCode(_aidl_status.get());
-        _transaction_log.exception_message = AStatus_getMessage(_aidl_status.get());
-        _transaction_log.transaction_error = AStatus_getStatus(_aidl_status.get());
-        _transaction_log.service_specific_error_code = AStatus_getServiceSpecificError(_aidl_status.get());
-        _transaction_log.output_args.emplace_back("in_boolArray", ::android::internal::ToString(in_boolArray));
-        _transaction_log.output_args.emplace_back("in_byteArray", ::android::internal::ToString(in_byteArray));
-        _transaction_log.output_args.emplace_back("in_charArray", ::android::internal::ToString(in_charArray));
-        _transaction_log.output_args.emplace_back("in_intArray", ::android::internal::ToString(in_intArray));
-        _transaction_log.output_args.emplace_back("in_longArray", ::android::internal::ToString(in_longArray));
-        _transaction_log.output_args.emplace_back("in_floatArray", ::android::internal::ToString(in_floatArray));
-        _transaction_log.output_args.emplace_back("in_doubleArray", ::android::internal::ToString(in_doubleArray));
-        _transaction_log.output_args.emplace_back("in_stringArray", ::android::internal::ToString(in_stringArray));
-        _transaction_log.output_args.emplace_back("in_listValue", ::android::internal::ToString(in_listValue));
-        _transaction_log.output_args.emplace_back("in_pfdValue", ::android::internal::ToString(in_pfdValue));
-        _transaction_log.output_args.emplace_back("in_pfdArray", ::android::internal::ToString(in_pfdArray));
-        _transaction_log.result = ::android::internal::ToString(_aidl_return);
-        BnLoggableInterface::logFunc(_transaction_log);
-      }
-      _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, in_boolArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_byteArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_charArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_intArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_longArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_floatArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_doubleArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_stringArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_listValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_writeNullableParcelFileDescriptor(_aidl_out, in_pfdValue);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_out, in_pfdArray);
-      if (_aidl_ret_status != STATUS_OK) break;
-
-      break;
-    }
-  }
-  return _aidl_ret_status;
-}
-
-static AIBinder_Class* _g_aidl_clazz = ::ndk::ICInterface::defineClass(ILoggableInterface::descriptor, _aidl_onTransact);
-
-BpLoggableInterface::BpLoggableInterface(const ::ndk::SpAIBinder& binder) : BpCInterface(binder) {}
-BpLoggableInterface::~BpLoggableInterface() {}
-std::function<void(const BpLoggableInterface::TransactionLog&)> BpLoggableInterface::logFunc;
-
-::ndk::ScopedAStatus BpLoggableInterface::LogThis(bool in_boolValue, std::vector<bool>* in_boolArray, int8_t in_byteValue, std::vector<uint8_t>* in_byteArray, char16_t in_charValue, std::vector<char16_t>* in_charArray, int32_t in_intValue, std::vector<int32_t>* in_intArray, int64_t in_longValue, std::vector<int64_t>* in_longArray, float in_floatValue, std::vector<float>* in_floatArray, double in_doubleValue, std::vector<double>* in_doubleArray, const std::string& in_stringValue, std::vector<std::string>* in_stringArray, std::vector<std::string>* in_listValue, const ::aidl::android::aidl::loggable::Data& in_dataValue, const ::ndk::SpAIBinder& in_binderValue, ::ndk::ScopedFileDescriptor* in_pfdValue, std::vector<::ndk::ScopedFileDescriptor>* in_pfdArray, std::vector<std::string>* _aidl_return) {
-  binder_status_t _aidl_ret_status = STATUS_OK;
-  ::ndk::ScopedAStatus _aidl_status;
-  ::ndk::ScopedAParcel _aidl_in;
-  ::ndk::ScopedAParcel _aidl_out;
-
-  BpLoggableInterface::TransactionLog _transaction_log;
-  if (BpLoggableInterface::logFunc != nullptr) {
-    _transaction_log.input_args.emplace_back("in_boolValue", ::android::internal::ToString(in_boolValue));
-    _transaction_log.input_args.emplace_back("in_boolArray", ::android::internal::ToString(*in_boolArray));
-    _transaction_log.input_args.emplace_back("in_byteValue", ::android::internal::ToString(in_byteValue));
-    _transaction_log.input_args.emplace_back("in_byteArray", ::android::internal::ToString(*in_byteArray));
-    _transaction_log.input_args.emplace_back("in_charValue", ::android::internal::ToString(in_charValue));
-    _transaction_log.input_args.emplace_back("in_charArray", ::android::internal::ToString(*in_charArray));
-    _transaction_log.input_args.emplace_back("in_intValue", ::android::internal::ToString(in_intValue));
-    _transaction_log.input_args.emplace_back("in_intArray", ::android::internal::ToString(*in_intArray));
-    _transaction_log.input_args.emplace_back("in_longValue", ::android::internal::ToString(in_longValue));
-    _transaction_log.input_args.emplace_back("in_longArray", ::android::internal::ToString(*in_longArray));
-    _transaction_log.input_args.emplace_back("in_floatValue", ::android::internal::ToString(in_floatValue));
-    _transaction_log.input_args.emplace_back("in_floatArray", ::android::internal::ToString(*in_floatArray));
-    _transaction_log.input_args.emplace_back("in_doubleValue", ::android::internal::ToString(in_doubleValue));
-    _transaction_log.input_args.emplace_back("in_doubleArray", ::android::internal::ToString(*in_doubleArray));
-    _transaction_log.input_args.emplace_back("in_stringValue", ::android::internal::ToString(in_stringValue));
-    _transaction_log.input_args.emplace_back("in_stringArray", ::android::internal::ToString(*in_stringArray));
-    _transaction_log.input_args.emplace_back("in_listValue", ::android::internal::ToString(*in_listValue));
-    _transaction_log.input_args.emplace_back("in_dataValue", ::android::internal::ToString(in_dataValue));
-    _transaction_log.input_args.emplace_back("in_binderValue", ::android::internal::ToString(in_binderValue));
-    _transaction_log.input_args.emplace_back("in_pfdValue", ::android::internal::ToString(*in_pfdValue));
-    _transaction_log.input_args.emplace_back("in_pfdArray", ::android::internal::ToString(*in_pfdArray));
-  }
-  auto _log_start = std::chrono::steady_clock::now();
-  ScopedTrace _aidl_trace("AIDL::ndk::ILoggableInterface::LogThis::client");
-  _aidl_ret_status = AIBinder_prepareTransaction(asBinder().get(), _aidl_in.getR());
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = AParcel_writeBool(_aidl_in.get(), in_boolValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_boolArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = AParcel_writeByte(_aidl_in.get(), in_byteValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_byteArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = AParcel_writeChar(_aidl_in.get(), in_charValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_charArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = AParcel_writeInt32(_aidl_in.get(), in_intValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_intArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = AParcel_writeInt64(_aidl_in.get(), in_longValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_longArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = AParcel_writeFloat(_aidl_in.get(), in_floatValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_floatArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = AParcel_writeDouble(_aidl_in.get(), in_doubleValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_doubleArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeString(_aidl_in.get(), in_stringValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_stringArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_listValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeParcelable(_aidl_in.get(), in_dataValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeNullableStrongBinder(_aidl_in.get(), in_binderValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeNullableParcelFileDescriptor(_aidl_in.get(), *in_pfdValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_writeVector(_aidl_in.get(), *in_pfdArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = AIBinder_transact(
-    asBinder().get(),
-    (FIRST_CALL_TRANSACTION + 0 /*LogThis*/),
-    _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 && ILoggableInterface::getDefaultImpl()) {
-    _aidl_status = ILoggableInterface::getDefaultImpl()->LogThis(in_boolValue, in_boolArray, in_byteValue, in_byteArray, in_charValue, in_charArray, in_intValue, in_intArray, in_longValue, in_longArray, in_floatValue, in_floatArray, in_doubleValue, in_doubleArray, in_stringValue, in_stringArray, in_listValue, in_dataValue, in_binderValue, in_pfdValue, in_pfdArray, _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(), in_boolArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_byteArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_charArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_intArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_longArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_floatArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_doubleArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_stringArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_listValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_readNullableParcelFileDescriptor(_aidl_out.get(), in_pfdValue);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_ret_status = ::ndk::AParcel_readVector(_aidl_out.get(), in_pfdArray);
-  if (_aidl_ret_status != STATUS_OK) goto _aidl_error;
-
-  _aidl_error:
-  _aidl_status.set(AStatus_fromStatus(_aidl_ret_status));
-  _aidl_status_return:
-  if (BpLoggableInterface::logFunc != nullptr) {
-    auto _log_end = std::chrono::steady_clock::now();
-    _transaction_log.duration_ms = std::chrono::duration<double, std::milli>(_log_end - _log_start).count();
-    _transaction_log.interface_name = "android.aidl.loggable.ILoggableInterface";
-    _transaction_log.method_name = "LogThis";
-    _transaction_log.stub_address = nullptr;
-    _transaction_log.proxy_address = static_cast<const void*>(this);
-    _transaction_log.exception_code = AStatus_getExceptionCode(_aidl_status.get());
-    _transaction_log.exception_message = AStatus_getMessage(_aidl_status.get());
-    _transaction_log.transaction_error = AStatus_getStatus(_aidl_status.get());
-    _transaction_log.service_specific_error_code = AStatus_getServiceSpecificError(_aidl_status.get());
-    _transaction_log.output_args.emplace_back("in_boolArray", ::android::internal::ToString(*in_boolArray));
-    _transaction_log.output_args.emplace_back("in_byteArray", ::android::internal::ToString(*in_byteArray));
-    _transaction_log.output_args.emplace_back("in_charArray", ::android::internal::ToString(*in_charArray));
-    _transaction_log.output_args.emplace_back("in_intArray", ::android::internal::ToString(*in_intArray));
-    _transaction_log.output_args.emplace_back("in_longArray", ::android::internal::ToString(*in_longArray));
-    _transaction_log.output_args.emplace_back("in_floatArray", ::android::internal::ToString(*in_floatArray));
-    _transaction_log.output_args.emplace_back("in_doubleArray", ::android::internal::ToString(*in_doubleArray));
-    _transaction_log.output_args.emplace_back("in_stringArray", ::android::internal::ToString(*in_stringArray));
-    _transaction_log.output_args.emplace_back("in_listValue", ::android::internal::ToString(*in_listValue));
-    _transaction_log.output_args.emplace_back("in_pfdValue", ::android::internal::ToString(*in_pfdValue));
-    _transaction_log.output_args.emplace_back("in_pfdArray", ::android::internal::ToString(*in_pfdArray));
-    _transaction_log.result = ::android::internal::ToString(*_aidl_return);
-    BpLoggableInterface::logFunc(_transaction_log);
-  }
-  return _aidl_status;
-}
-// Source for BnLoggableInterface
-BnLoggableInterface::BnLoggableInterface() {}
-BnLoggableInterface::~BnLoggableInterface() {}
-std::function<void(const BnLoggableInterface::TransactionLog&)> BnLoggableInterface::logFunc;
-::ndk::SpAIBinder BnLoggableInterface::createBinder() {
-  AIBinder* binder = AIBinder_new(_g_aidl_clazz, static_cast<void*>(this));
-  #ifdef BINDER_STABILITY_SUPPORT
-  AIBinder_markCompilationUnitStability(binder);
-  #endif  // BINDER_STABILITY_SUPPORT
-  return ::ndk::SpAIBinder(binder);
-}
-// Source for ILoggableInterface
-const char* ILoggableInterface::descriptor = "android.aidl.loggable.ILoggableInterface";
-ILoggableInterface::ILoggableInterface() {}
-ILoggableInterface::~ILoggableInterface() {}
-
-
-std::shared_ptr<ILoggableInterface> ILoggableInterface::fromBinder(const ::ndk::SpAIBinder& binder) {
-  if (!AIBinder_associateClass(binder.get(), _g_aidl_clazz)) { return nullptr; }
-  std::shared_ptr<::ndk::ICInterface> interface = ::ndk::ICInterface::asInterface(binder.get());
-  if (interface) {
-    return std::static_pointer_cast<ILoggableInterface>(interface);
-  }
-  return ::ndk::SharedRefBase::make<BpLoggableInterface>(binder);
-}
-
-binder_status_t ILoggableInterface::writeToParcel(AParcel* parcel, const std::shared_ptr<ILoggableInterface>& instance) {
-  return AParcel_writeStrongBinder(parcel, instance ? instance->asBinder().get() : nullptr);
-}
-binder_status_t ILoggableInterface::readFromParcel(const AParcel* parcel, std::shared_ptr<ILoggableInterface>* instance) {
-  ::ndk::SpAIBinder binder;
-  binder_status_t status = AParcel_readStrongBinder(parcel, binder.getR());
-  if (status != STATUS_OK) return status;
-  *instance = ILoggableInterface::fromBinder(binder);
-  return STATUS_OK;
-}
-bool ILoggableInterface::setDefaultImpl(const std::shared_ptr<ILoggableInterface>& 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(!ILoggableInterface::default_impl);
-  if (impl) {
-    ILoggableInterface::default_impl = impl;
-    return true;
-  }
-  return false;
-}
-const std::shared_ptr<ILoggableInterface>& ILoggableInterface::getDefaultImpl() {
-  return ILoggableInterface::default_impl;
-}
-std::shared_ptr<ILoggableInterface> ILoggableInterface::default_impl = nullptr;
-::ndk::ScopedAStatus ILoggableInterfaceDefault::LogThis(bool /*in_boolValue*/, std::vector<bool>* /*in_boolArray*/, int8_t /*in_byteValue*/, std::vector<uint8_t>* /*in_byteArray*/, char16_t /*in_charValue*/, std::vector<char16_t>* /*in_charArray*/, int32_t /*in_intValue*/, std::vector<int32_t>* /*in_intArray*/, int64_t /*in_longValue*/, std::vector<int64_t>* /*in_longArray*/, float /*in_floatValue*/, std::vector<float>* /*in_floatArray*/, double /*in_doubleValue*/, std::vector<double>* /*in_doubleArray*/, const std::string& /*in_stringValue*/, std::vector<std::string>* /*in_stringArray*/, std::vector<std::string>* /*in_listValue*/, const ::aidl::android::aidl::loggable::Data& /*in_dataValue*/, const ::ndk::SpAIBinder& /*in_binderValue*/, ::ndk::ScopedFileDescriptor* /*in_pfdValue*/, std::vector<::ndk::ScopedFileDescriptor>* /*in_pfdArray*/, std::vector<std::string>* /*_aidl_return*/) {
-  ::ndk::ScopedAStatus _aidl_status;
-  _aidl_status.set(AStatus_fromStatus(STATUS_UNKNOWN_TRANSACTION));
-  return _aidl_status;
-}
-::ndk::SpAIBinder ILoggableInterfaceDefault::asBinder() {
-  return ::ndk::SpAIBinder();
-}
-bool ILoggableInterfaceDefault::isRemote() {
-  return false;
-}
-}  // namespace loggable
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/ILoggableInterface.cpp.d b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/ILoggableInterface.cpp.d
deleted file mode 100644
index 2816dc0..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/ILoggableInterface.cpp.d
+++ /dev/null
@@ -1,3 +0,0 @@
-out/soong/.intermediates/system/tools/aidl/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/ILoggableInterface.cpp : \
-  system/tools/aidl/tests/android/aidl/loggable/ILoggableInterface.aidl \
-  system/tools/aidl/tests/android/aidl/loggable/Data.aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Union.cpp b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Union.cpp
deleted file mode 100644
index 7d02d4d..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Union.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-#include "aidl/android/aidl/loggable/Union.h"
-
-#include <android/binder_parcel_utils.h>
-
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace loggable {
-const char* Union::descriptor = "android.aidl.loggable.Union";
-
-binder_status_t Union::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 num: {
-    int32_t _aidl_value;
-    if ((_aidl_ret_status = AParcel_readInt32(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
-    if constexpr (std::is_trivially_copyable_v<int32_t>) {
-      set<num>(_aidl_value);
-    } else {
-      // NOLINTNEXTLINE(performance-move-const-arg)
-      set<num>(std::move(_aidl_value));
-    }
-    return STATUS_OK; }
-  case str: {
-    std::string _aidl_value;
-    if ((_aidl_ret_status = ::ndk::AParcel_readString(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
-    if constexpr (std::is_trivially_copyable_v<std::string>) {
-      set<str>(_aidl_value);
-    } else {
-      // NOLINTNEXTLINE(performance-move-const-arg)
-      set<str>(std::move(_aidl_value));
-    }
-    return STATUS_OK; }
-  }
-  return STATUS_BAD_VALUE;
-}
-binder_status_t Union::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 num: return AParcel_writeInt32(_parcel, get<num>());
-  case str: return ::ndk::AParcel_writeString(_parcel, get<str>());
-  }
-  __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
-}
-
-}  // namespace loggable
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Union.cpp.d b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Union.cpp.d
deleted file mode 100644
index 0968751..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Union.cpp.d
+++ /dev/null
@@ -1,2 +0,0 @@
-out/soong/.intermediates/system/tools/aidl/aidl_test_loggable_interface-ndk_platform-source/gen/android/aidl/loggable/Union.cpp : \
-  system/tools/aidl/tests/android/aidl/loggable/Union.aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BnData.h b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BnData.h
deleted file mode 100644
index 4291108..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BnData.h
+++ /dev/null
@@ -1 +0,0 @@
-#error TODO(b/111362593) defined_types do not have bn classes
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BnEnum.h b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BnEnum.h
deleted file mode 100644
index e85bbc8..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BnEnum.h
+++ /dev/null
@@ -1 +0,0 @@
-#error TODO(b/111362593) enums do not have bn classes
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BnLoggableInterface.h b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BnLoggableInterface.h
deleted file mode 100644
index 650ca86..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BnLoggableInterface.h
+++ /dev/null
@@ -1,37 +0,0 @@
-#pragma once
-
-#include "aidl/android/aidl/loggable/ILoggableInterface.h"
-
-#include <android/binder_ibinder.h>
-
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace loggable {
-class BnLoggableInterface : public ::ndk::BnCInterface<ILoggableInterface> {
-public:
-  BnLoggableInterface();
-  virtual ~BnLoggableInterface();
-  struct TransactionLog {
-    double duration_ms;
-    std::string interface_name;
-    std::string method_name;
-    const void* proxy_address;
-    const void* stub_address;
-    std::vector<std::pair<std::string, std::string>> input_args;
-    std::vector<std::pair<std::string, std::string>> output_args;
-    std::string result;
-    std::string exception_message;
-    int32_t exception_code;
-    int32_t transaction_error;
-    int32_t service_specific_error_code;
-  };
-  static std::function<void(const TransactionLog&)> logFunc;
-protected:
-  ::ndk::SpAIBinder createBinder() override;
-private:
-};
-}  // namespace loggable
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BnUnion.h b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BnUnion.h
deleted file mode 100644
index 4291108..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BnUnion.h
+++ /dev/null
@@ -1 +0,0 @@
-#error TODO(b/111362593) defined_types do not have bn classes
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BpData.h b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BpData.h
deleted file mode 100644
index e8a0db3..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BpData.h
+++ /dev/null
@@ -1 +0,0 @@
-#error TODO(b/111362593) defined_types do not have bp classes
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BpEnum.h b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BpEnum.h
deleted file mode 100644
index 74a2c6d..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BpEnum.h
+++ /dev/null
@@ -1 +0,0 @@
-#error TODO(b/111362593) enums do not have bp classes
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BpLoggableInterface.h b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BpLoggableInterface.h
deleted file mode 100644
index f7fc576..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BpLoggableInterface.h
+++ /dev/null
@@ -1,40 +0,0 @@
-#pragma once
-
-#include "aidl/android/aidl/loggable/ILoggableInterface.h"
-
-#include <android/binder_ibinder.h>
-#include <functional>
-#include <chrono>
-#include <sstream>
-#include <android/trace.h>
-
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace loggable {
-class BpLoggableInterface : public ::ndk::BpCInterface<ILoggableInterface> {
-public:
-  explicit BpLoggableInterface(const ::ndk::SpAIBinder& binder);
-  virtual ~BpLoggableInterface();
-
-  ::ndk::ScopedAStatus LogThis(bool in_boolValue, std::vector<bool>* in_boolArray, int8_t in_byteValue, std::vector<uint8_t>* in_byteArray, char16_t in_charValue, std::vector<char16_t>* in_charArray, int32_t in_intValue, std::vector<int32_t>* in_intArray, int64_t in_longValue, std::vector<int64_t>* in_longArray, float in_floatValue, std::vector<float>* in_floatArray, double in_doubleValue, std::vector<double>* in_doubleArray, const std::string& in_stringValue, std::vector<std::string>* in_stringArray, std::vector<std::string>* in_listValue, const ::aidl::android::aidl::loggable::Data& in_dataValue, const ::ndk::SpAIBinder& in_binderValue, ::ndk::ScopedFileDescriptor* in_pfdValue, std::vector<::ndk::ScopedFileDescriptor>* in_pfdArray, std::vector<std::string>* _aidl_return) override;
-  struct TransactionLog {
-    double duration_ms;
-    std::string interface_name;
-    std::string method_name;
-    const void* proxy_address;
-    const void* stub_address;
-    std::vector<std::pair<std::string, std::string>> input_args;
-    std::vector<std::pair<std::string, std::string>> output_args;
-    std::string result;
-    std::string exception_message;
-    int32_t exception_code;
-    int32_t transaction_error;
-    int32_t service_specific_error_code;
-  };
-  static std::function<void(const TransactionLog&)> logFunc;
-};
-}  // namespace loggable
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BpUnion.h b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BpUnion.h
deleted file mode 100644
index e8a0db3..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/BpUnion.h
+++ /dev/null
@@ -1 +0,0 @@
-#error TODO(b/111362593) defined_types do not have bp classes
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/Data.h b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/Data.h
deleted file mode 100644
index ecc788e..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/Data.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#pragma once
-#include <android/binder_interface_utils.h>
-#include <android/binder_parcelable_utils.h>
-#include <android/binder_to_string.h>
-#include <cstdint>
-#include <memory>
-#include <optional>
-#include <string>
-#include <vector>
-#ifdef BINDER_STABILITY_SUPPORT
-#include <android/binder_stability.h>
-#endif  // BINDER_STABILITY_SUPPORT
-#include <aidl/android/aidl/loggable/Enum.h>
-#include <aidl/android/aidl/loggable/Union.h>
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace loggable {
-class Data {
-public:
-  typedef std::false_type fixed_size;
-  static const char* descriptor;
-
-  int32_t num = 0;
-  std::string str;
-  ::aidl::android::aidl::loggable::Union nestedUnion;
-  ::aidl::android::aidl::loggable::Enum nestedEnum = ::aidl::android::aidl::loggable::Enum::FOO;
-
-  binder_status_t readFromParcel(const AParcel* parcel);
-  binder_status_t writeToParcel(AParcel* parcel) const;
-
-  inline bool operator!=(const Data& rhs) const {
-    return std::tie(num, str, nestedUnion, nestedEnum) != std::tie(rhs.num, rhs.str, rhs.nestedUnion, rhs.nestedEnum);
-  }
-  inline bool operator<(const Data& rhs) const {
-    return std::tie(num, str, nestedUnion, nestedEnum) < std::tie(rhs.num, rhs.str, rhs.nestedUnion, rhs.nestedEnum);
-  }
-  inline bool operator<=(const Data& rhs) const {
-    return std::tie(num, str, nestedUnion, nestedEnum) <= std::tie(rhs.num, rhs.str, rhs.nestedUnion, rhs.nestedEnum);
-  }
-  inline bool operator==(const Data& rhs) const {
-    return std::tie(num, str, nestedUnion, nestedEnum) == std::tie(rhs.num, rhs.str, rhs.nestedUnion, rhs.nestedEnum);
-  }
-  inline bool operator>(const Data& rhs) const {
-    return std::tie(num, str, nestedUnion, nestedEnum) > std::tie(rhs.num, rhs.str, rhs.nestedUnion, rhs.nestedEnum);
-  }
-  inline bool operator>=(const Data& rhs) const {
-    return std::tie(num, str, nestedUnion, nestedEnum) >= std::tie(rhs.num, rhs.str, rhs.nestedUnion, rhs.nestedEnum);
-  }
-
-  static const ::ndk::parcelable_stability_t _aidl_stability = ::ndk::STABILITY_LOCAL;
-  inline std::string toString() const {
-    std::ostringstream os;
-    os << "Data{";
-    os << "num: " << ::android::internal::ToString(num);
-    os << ", str: " << ::android::internal::ToString(str);
-    os << ", nestedUnion: " << ::android::internal::ToString(nestedUnion);
-    os << ", nestedEnum: " << ::android::internal::ToString(nestedEnum);
-    os << "}";
-    return os.str();
-  }
-};
-}  // namespace loggable
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/Enum.h b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/Enum.h
deleted file mode 100644
index 1f02080..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/Enum.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#pragma once
-
-#include <cstdint>
-#include <memory>
-#include <optional>
-#include <string>
-#include <vector>
-#ifdef BINDER_STABILITY_SUPPORT
-#include <android/binder_stability.h>
-#endif  // BINDER_STABILITY_SUPPORT
-#include <array>
-#include <android/binder_enums.h>
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace loggable {
-enum class Enum : int8_t {
-  FOO = 42,
-};
-
-[[nodiscard]] static inline std::string toString(Enum val) {
-  switch(val) {
-  case Enum::FOO:
-    return "FOO";
-  default:
-    return std::to_string(static_cast<int8_t>(val));
-  }
-}
-}  // namespace loggable
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
-namespace ndk {
-namespace internal {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wc++17-extensions"
-template <>
-constexpr inline std::array<aidl::android::aidl::loggable::Enum, 1> enum_values<aidl::android::aidl::loggable::Enum> = {
-  aidl::android::aidl::loggable::Enum::FOO,
-};
-#pragma clang diagnostic pop
-}  // namespace internal
-}  // namespace android
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/ILoggableInterface.h b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/ILoggableInterface.h
deleted file mode 100644
index 33c79e1..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/ILoggableInterface.h
+++ /dev/null
@@ -1,48 +0,0 @@
-#pragma once
-
-#include <android/binder_interface_utils.h>
-#include <functional>
-#include <chrono>
-#include <sstream>
-
-#include <cstdint>
-#include <memory>
-#include <optional>
-#include <string>
-#include <vector>
-#ifdef BINDER_STABILITY_SUPPORT
-#include <android/binder_stability.h>
-#endif  // BINDER_STABILITY_SUPPORT
-#include <aidl/android/aidl/loggable/Data.h>
-
-namespace aidl {
-namespace android {
-namespace aidl {
-namespace loggable {
-class ILoggableInterface : public ::ndk::ICInterface {
-public:
-  static const char* descriptor;
-  ILoggableInterface();
-  virtual ~ILoggableInterface();
-
-  static constexpr uint32_t TRANSACTION_LogThis = FIRST_CALL_TRANSACTION + 0;
-
-  static std::shared_ptr<ILoggableInterface> fromBinder(const ::ndk::SpAIBinder& binder);
-  static binder_status_t writeToParcel(AParcel* parcel, const std::shared_ptr<ILoggableInterface>& instance);
-  static binder_status_t readFromParcel(const AParcel* parcel, std::shared_ptr<ILoggableInterface>* instance);
-  static bool setDefaultImpl(const std::shared_ptr<ILoggableInterface>& impl);
-  static const std::shared_ptr<ILoggableInterface>& getDefaultImpl();
-  virtual ::ndk::ScopedAStatus LogThis(bool in_boolValue, std::vector<bool>* in_boolArray, int8_t in_byteValue, std::vector<uint8_t>* in_byteArray, char16_t in_charValue, std::vector<char16_t>* in_charArray, int32_t in_intValue, std::vector<int32_t>* in_intArray, int64_t in_longValue, std::vector<int64_t>* in_longArray, float in_floatValue, std::vector<float>* in_floatArray, double in_doubleValue, std::vector<double>* in_doubleArray, const std::string& in_stringValue, std::vector<std::string>* in_stringArray, std::vector<std::string>* in_listValue, const ::aidl::android::aidl::loggable::Data& in_dataValue, const ::ndk::SpAIBinder& in_binderValue, ::ndk::ScopedFileDescriptor* in_pfdValue, std::vector<::ndk::ScopedFileDescriptor>* in_pfdArray, std::vector<std::string>* _aidl_return) = 0;
-private:
-  static std::shared_ptr<ILoggableInterface> default_impl;
-};
-class ILoggableInterfaceDefault : public ILoggableInterface {
-public:
-  ::ndk::ScopedAStatus LogThis(bool in_boolValue, std::vector<bool>* in_boolArray, int8_t in_byteValue, std::vector<uint8_t>* in_byteArray, char16_t in_charValue, std::vector<char16_t>* in_charArray, int32_t in_intValue, std::vector<int32_t>* in_intArray, int64_t in_longValue, std::vector<int64_t>* in_longArray, float in_floatValue, std::vector<float>* in_floatArray, double in_doubleValue, std::vector<double>* in_doubleArray, const std::string& in_stringValue, std::vector<std::string>* in_stringArray, std::vector<std::string>* in_listValue, const ::aidl::android::aidl::loggable::Data& in_dataValue, const ::ndk::SpAIBinder& in_binderValue, ::ndk::ScopedFileDescriptor* in_pfdValue, std::vector<::ndk::ScopedFileDescriptor>* in_pfdArray, std::vector<std::string>* _aidl_return) override;
-  ::ndk::SpAIBinder asBinder() override;
-  bool isRemote() override;
-};
-}  // namespace loggable
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/Union.h b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/Union.h
deleted file mode 100644
index f53752a..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/include/aidl/android/aidl/loggable/Union.h
+++ /dev/null
@@ -1,125 +0,0 @@
-#pragma once
-#include <android/binder_interface_utils.h>
-#include <android/binder_parcelable_utils.h>
-#include <android/binder_to_string.h>
-
-#include <cassert>
-#include <type_traits>
-#include <utility>
-#include <variant>
-#include <cstdint>
-#include <memory>
-#include <optional>
-#include <string>
-#include <vector>
-#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 loggable {
-class Union {
-public:
-  typedef std::false_type fixed_size;
-  static const char* descriptor;
-
-  enum Tag : int32_t {
-    num = 0,  // int num;
-    str,  // String str;
-  };
-
-  template<typename _Tp>
-  static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, Union>;
-
-  Union() : _value(std::in_place_index<num>, int32_t(43)) { }
-  Union(const Union&) = default;
-  Union(Union&&) = default;
-  Union& operator=(const Union&) = default;
-  Union& operator=(Union&&) = default;
-
-  template <typename _Tp, typename = std::enable_if_t<_not_self<_Tp>>>
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  constexpr Union(_Tp&& _arg)
-      : _value(std::forward<_Tp>(_arg)) {}
-
-  template <size_t _Np, typename... _Tp>
-  constexpr explicit Union(std::in_place_index_t<_Np>, _Tp&&... _args)
-      : _value(std::in_place_index<_Np>, std::forward<_Tp>(_args)...) {}
-
-  template <Tag _tag, typename... _Tp>
-  static Union make(_Tp&&... _args) {
-    return Union(std::in_place_index<_tag>, std::forward<_Tp>(_args)...);
-  }
-
-  template <Tag _tag, typename _Tp, typename... _Up>
-  static Union make(std::initializer_list<_Tp> _il, _Up&&... _args) {
-    return Union(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 Union& rhs) const {
-    return _value != rhs._value;
-  }
-  inline bool operator<(const Union& rhs) const {
-    return _value < rhs._value;
-  }
-  inline bool operator<=(const Union& rhs) const {
-    return _value <= rhs._value;
-  }
-  inline bool operator==(const Union& rhs) const {
-    return _value == rhs._value;
-  }
-  inline bool operator>(const Union& rhs) const {
-    return _value > rhs._value;
-  }
-  inline bool operator>=(const Union& 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 << "Union{";
-    switch (getTag()) {
-    case num: os << "num: " << ::android::internal::ToString(get<num>()); break;
-    case str: os << "str: " << ::android::internal::ToString(get<str>()); break;
-    }
-    os << "}";
-    return os.str();
-  }
-private:
-  std::variant<int32_t, std::string> _value;
-};
-}  // namespace loggable
-}  // namespace aidl
-}  // namespace android
-}  // namespace aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/timestamp b/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/timestamp
deleted file mode 100644
index e69de29..0000000
--- a/tests/golden_output/aidl_test_loggable_interface-ndk_platform-source/gen/timestamp
+++ /dev/null
diff --git a/tests/golden_test.sh b/tests/golden_test.sh
index 9729bd5..547999e 100755
--- a/tests/golden_test.sh
+++ b/tests/golden_test.sh
@@ -39,12 +39,17 @@
   modules=(
     "aidl-test-interface-cpp-source"
     "aidl-test-interface-java-source"
-    "aidl-test-interface-ndk_platform-source"
+    "aidl-test-versioned-interface-V2-java-source"
+    "aidl-test-interface-ndk-source"
     "aidl-test-interface-rust-source"
     "aidl_test_loggable_interface-cpp-source"
     "aidl_test_loggable_interface-java-source"
-    "aidl_test_loggable_interface-ndk_platform-source"
     "aidl_test_loggable_interface-ndk-source"
+    "aidl-test-interface-platform-java-source"
+    "aidl-test-fixedsizearray-cpp-source"
+    "aidl-test-fixedsizearray-java-source"
+    "aidl-test-fixedsizearray-ndk-source"
+    "aidl-test-fixedsizearray-rust-source"
   )
 
   local root="."
@@ -69,7 +74,7 @@
       mkdir -p "$golden"
       cp -r "$built/gen" "$golden"
     else
-      diff -r "$built" "$golden" || e=1
+      diff -r "$built/gen" "$golden/gen" || e=1
     fi
   done
 
diff --git a/tests/java/src/android/aidl/sdkversion/ITestService.aidl b/tests/java/src/android/aidl/sdkversion/ITestService.aidl
new file mode 100644
index 0000000..afefdde
--- /dev/null
+++ b/tests/java/src/android/aidl/sdkversion/ITestService.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.sdkversion;
+
+interface ITestService {
+    // Since sdk = 29, we have write/readBoolean
+    boolean RepeatBoolean(boolean token);
+
+    // Since sdk = 23, we have write/readTypedObject
+    @JavaDerive(toString=true, equals=true)
+    parcelable TypedObject {
+        boolean b;
+    }
+    @nullable TypedObject RepeatTypedObject(in @nullable TypedObject token);
+}
diff --git a/tests/java/src/android/aidl/sdkversion/service/AidlJavaVersionTestService.java b/tests/java/src/android/aidl/sdkversion/service/AidlJavaVersionTestService.java
new file mode 100644
index 0000000..ca108c8
--- /dev/null
+++ b/tests/java/src/android/aidl/sdkversion/service/AidlJavaVersionTestService.java
@@ -0,0 +1,42 @@
+/*
+ * 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.sdkversion.service;
+
+import android.aidl.sdkversion.ITestService;
+import android.aidl.sdkversion.ITestService.TypedObject;
+import android.os.Binder;
+import android.os.ServiceManager;
+
+public class AidlJavaVersionTestService {
+  static class TestServiceServer extends ITestService.Stub {
+    @Override
+    public boolean RepeatBoolean(boolean token) {
+      return token;
+    }
+
+    @Override
+    public TypedObject RepeatTypedObject(TypedObject token) {
+      return token;
+    }
+  }
+
+  public static void main(String[] args) {
+    TestServiceServer myServer = new TestServiceServer();
+    ServiceManager.addService(ITestService.class.getName(), myServer);
+    Binder.joinThreadPool();
+  }
+}
diff --git a/tests/java/src/android/aidl/sdkversion/tests/AidlJavaVersionTests.java b/tests/java/src/android/aidl/sdkversion/tests/AidlJavaVersionTests.java
new file mode 100644
index 0000000..7239ad7
--- /dev/null
+++ b/tests/java/src/android/aidl/sdkversion/tests/AidlJavaVersionTests.java
@@ -0,0 +1,69 @@
+/*
+ * 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.sdkversion.tests;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.aidl.sdkversion.ITestService;
+import android.aidl.sdkversion.ITestService.TypedObject;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.internal.TextListener;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class AidlJavaVersionTests {
+  public static void main(String[] args) {
+    JUnitCore junit = new JUnitCore();
+    junit.addListener(new TextListener(System.out));
+    Result result = junit.run(AidlJavaVersionTests.class);
+    System.out.println(result.wasSuccessful() ? "TEST SUCCESS" : "TEST FAILURE");
+  }
+
+  private ITestService mService;
+
+  @Before
+  public void setUp() {
+    IBinder binder = ServiceManager.waitForService(ITestService.class.getName());
+    assertNotNull(binder);
+    mService = ITestService.Stub.asInterface(binder);
+    assertNotNull(mService);
+  }
+
+  @Test
+  public void testBoolean() throws RemoteException {
+    assertTrue(mService.RepeatBoolean(true));
+    assertFalse(mService.RepeatBoolean(false));
+  }
+
+  @Test
+  public void testTypedObject() throws RemoteException {
+    TypedObject token = new TypedObject();
+    assertEquals(mService.RepeatTypedObject(token), token);
+    assertNull(mService.RepeatTypedObject(null));
+  }
+}
diff --git a/tests/java/src/android/aidl/service/TestServiceServer.java b/tests/java/src/android/aidl/service/TestServiceServer.java
index 06ef6cc..ad98416 100644
--- a/tests/java/src/android/aidl/service/TestServiceServer.java
+++ b/tests/java/src/android/aidl/service/TestServiceServer.java
@@ -16,7 +16,10 @@
 
 package android.aidl.service;
 
+import android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray;
+import android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable;
 import android.aidl.tests.BackendType;
+import android.aidl.tests.BadParcelable;
 import android.aidl.tests.ByteEnum;
 import android.aidl.tests.ConstantExpressionEnum;
 import android.aidl.tests.GenericStructuredParcelable;
@@ -27,11 +30,14 @@
 import android.aidl.tests.ITestService;
 import android.aidl.tests.IntEnum;
 import android.aidl.tests.LongEnum;
+import android.aidl.tests.RecursiveList;
 import android.aidl.tests.SimpleParcelable;
 import android.aidl.tests.StructuredParcelable;
 import android.aidl.tests.Union;
 import android.aidl.tests.extension.ExtendableParcelable;
 import android.aidl.tests.extension.MyExt;
+import android.aidl.tests.nested.INestedService;
+import android.aidl.tests.nested.ParcelableWithNested;
 import android.aidl.versioned.tests.BazUnion;
 import android.aidl.versioned.tests.Foo;
 import android.aidl.versioned.tests.IFooInterface;
@@ -47,6 +53,7 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 
@@ -58,6 +65,12 @@
     FooInterface foo = new FooInterface();
     ServiceManager.addService(IFooInterface.class.getName(), foo);
 
+    NestedService nested = new NestedService();
+    ServiceManager.addService(INestedService.class.getName(), nested);
+
+    FixedSizeArrayService fixedSize = new FixedSizeArrayService();
+    ServiceManager.addService(IRepeatFixedSizeArray.DESCRIPTOR, fixedSize);
+
     Binder.joinThreadPool();
   }
 
@@ -89,6 +102,27 @@
     }
   }
 
+  private static class NestedService extends INestedService.Stub {
+    @Override
+    public final Result flipStatus(ParcelableWithNested p) {
+      Result result = new Result();
+      if (p.status == ParcelableWithNested.Status.OK) {
+        result.status = ParcelableWithNested.Status.NOT_OK;
+      } else {
+        result.status = ParcelableWithNested.Status.OK;
+      }
+      return result;
+    }
+    @Override
+    public final void flipStatusWithCallback(byte st, ICallback cb) throws RemoteException {
+      if (st == ParcelableWithNested.Status.OK) {
+        cb.done(ParcelableWithNested.Status.NOT_OK);
+      } else {
+        cb.done(ParcelableWithNested.Status.OK);
+      }
+    }
+  }
+
   @Override
   public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
     // UnimplementedMethod
@@ -274,6 +308,60 @@
     return name.equals(service.GetName());
   }
   @Override
+  public INamedCallback[] GetInterfaceArray(String[] names) throws RemoteException {
+    return GetNullableInterfaceArray(names);
+  }
+  @Override
+  public boolean VerifyNamesWithInterfaceArray(INamedCallback[] services, String[] names)
+      throws RemoteException {
+    return VerifyNamesWithNullableInterfaceArray(services, names);
+  }
+  @Override
+  public INamedCallback[] GetNullableInterfaceArray(String[] names) throws RemoteException {
+    if (names == null)
+      return null;
+    INamedCallback[] services = new INamedCallback[names.length];
+    for (int i = 0; i < names.length; i++) {
+      if (names[i] == null) {
+        services[i] = null;
+      } else {
+        services[i] = GetOtherTestService(names[i]);
+      }
+    }
+    return services;
+  }
+  @Override
+  public boolean VerifyNamesWithNullableInterfaceArray(INamedCallback[] services, String[] names)
+      throws RemoteException {
+    if (services != null && names != null) {
+      for (int i = 0; i < names.length; i++) {
+        if (services[i] != null && names[i] != null) {
+          if (!VerifyName(services[i], names[i])) {
+            return false;
+          }
+        } else if (services[i] != null || names[i] != null) {
+          return false;
+        }
+      }
+      return true;
+    } else if (services != null || names != null) {
+      return false;
+    } else {
+      return true;
+    }
+  }
+  @Override
+  public List<INamedCallback> GetInterfaceList(String[] names) throws RemoteException {
+    INamedCallback[] services = GetNullableInterfaceArray(names);
+    return services == null ? null : Arrays.asList(services);
+  }
+  @Override
+  public boolean VerifyNamesWithInterfaceList(List<INamedCallback> services, String[] names)
+      throws RemoteException {
+    return VerifyNamesWithNullableInterfaceArray(
+        services == null ? null : services.toArray(new INamedCallback[0]), names);
+  }
+  @Override
   public List<String> ReverseStringList(List<String> input, List<String> repeated)
       throws RemoteException {
     ArrayList<String> reversed = new ArrayList<String>();
@@ -333,7 +421,17 @@
     return input;
   }
   @Override
-  public StructuredParcelable RepeatNullableParcelable(StructuredParcelable input)
+  public ITestService.Empty RepeatNullableParcelable(ITestService.Empty input)
+      throws RemoteException {
+    return input;
+  }
+  @Override
+  public List<ITestService.Empty> RepeatNullableParcelableList(List<ITestService.Empty> input)
+      throws RemoteException {
+    return input;
+  }
+  @Override
+  public ITestService.Empty[] RepeatNullableParcelableArray(ITestService.Empty[] input)
       throws RemoteException {
     return input;
   }
@@ -346,6 +444,15 @@
     // do nothing
   }
   @Override
+  public void TakesAnIBinderList(List<IBinder> input) throws RemoteException {
+    // do nothing
+  }
+  @Override
+  public void TakesANullableIBinderList(List<IBinder> input) throws RemoteException {
+    // do nothing
+  }
+
+  @Override
   public String RepeatUtf8CppString(String token) throws RemoteException {
     return token;
   }
@@ -422,7 +529,45 @@
     parcelable.u = Union.ns(new int[] {1, 2, 3});
     parcelable.shouldBeConstS1 = Union.s(Union.S1);
   }
-
+  @Override
+  public void RepeatExtendableParcelable(ExtendableParcelable ep, ExtendableParcelable ep2)
+      throws RemoteException {
+    ep2.a = ep.a;
+    ep2.b = ep.b;
+    // no way to copy currently w/o unparceling
+    ep2.ext.setParcelable(ep.ext.getParcelable(MyExt.class));
+    ep2.c = ep.c;
+    ep2.ext2.setParcelable(null);
+  }
+  @Override
+  public RecursiveList ReverseList(RecursiveList list) throws RemoteException {
+    RecursiveList reversed = null;
+    while (list != null) {
+      RecursiveList next = list.next;
+      list.next = reversed;
+      reversed = list;
+      list = next;
+    }
+    return reversed;
+  }
+  @Override
+  public IBinder[] ReverseIBinderArray(IBinder[] input, IBinder[] repeated) {
+    IBinder[] reversed = new IBinder[input.length];
+    for (int i = 0; i < input.length; i++) {
+      repeated[i] = input[i];
+      reversed[i] = input[input.length - i - 1];
+    }
+    return reversed;
+  }
+  @Override
+  public IBinder[] ReverseNullableIBinderArray(IBinder[] input, IBinder[] repeated) {
+    IBinder[] reversed = new IBinder[input.length];
+    for (int i = 0; i < input.length; i++) {
+      repeated[i] = input[i];
+      reversed[i] = input[input.length - i - 1];
+    }
+    return reversed;
+  }
   private static class MyOldName extends IOldName.Stub {
     @Override
     public String RealName() {
@@ -449,6 +594,10 @@
 
   class MyCppJavaTests extends ICppJavaTests.Stub {
     @Override
+    public BadParcelable RepeatBadParcelable(BadParcelable input) throws RemoteException {
+      return input;
+    }
+    @Override
     public SimpleParcelable RepeatSimpleParcelable(SimpleParcelable input, SimpleParcelable repeat)
         throws RemoteException {
       repeat.set(input.getName(), input.getNumber());
@@ -520,19 +669,75 @@
       }
       return reversed;
     }
+  }
+
+  public static class FixedSizeArrayService extends IRepeatFixedSizeArray.Stub {
     @Override
-    public void TakesAnIBinderList(List<IBinder> input) throws RemoteException {}
+    public byte[] RepeatBytes(byte[] input, byte[] repeated) throws RemoteException {
+      for (int i = 0; i < input.length; i++) {
+        repeated[i] = input[i];
+      }
+      return input;
+    }
     @Override
-    public void TakesANullableIBinderList(List<IBinder> input) throws RemoteException {}
+    public int[] RepeatInts(int[] input, int[] repeated) throws RemoteException {
+      for (int i = 0; i < input.length; i++) {
+        repeated[i] = input[i];
+      }
+      return input;
+    }
     @Override
-    public void RepeatExtendableParcelable(ExtendableParcelable ep, ExtendableParcelable ep2)
+    public IBinder[] RepeatBinders(IBinder[] input, IBinder[] repeated) throws RemoteException {
+      for (int i = 0; i < input.length; i++) {
+        repeated[i] = input[i];
+      }
+      return input;
+    }
+    @Override
+    public IntParcelable[] RepeatParcelables(IntParcelable[] input, IntParcelable[] repeated)
         throws RemoteException {
-      ep2.a = ep.a;
-      ep2.b = ep.b;
-      // no way to copy currently w/o unparceling
-      ep2.ext.setParcelable(ep.ext.getParcelable(MyExt.class));
-      ep2.c = ep.c;
-      ep2.ext2.setParcelable(null);
+      for (int i = 0; i < input.length; i++) {
+        repeated[i] = input[i];
+      }
+      return input;
+    }
+    @Override
+    public byte[][] Repeat2dBytes(byte[][] input, byte[][] repeated) throws RemoteException {
+      for (int i = 0; i < input.length; i++) {
+        for (int j = 0; j < input[i].length; j++) {
+          repeated[i][j] = input[i][j];
+        }
+      }
+      return input;
+    }
+    @Override
+    public int[][] Repeat2dInts(int[][] input, int[][] repeated) throws RemoteException {
+      for (int i = 0; i < input.length; i++) {
+        for (int j = 0; j < input[i].length; j++) {
+          repeated[i][j] = input[i][j];
+        }
+      }
+      return input;
+    }
+    @Override
+    public IBinder[][] Repeat2dBinders(IBinder[][] input, IBinder[][] repeated)
+        throws RemoteException {
+      for (int i = 0; i < input.length; i++) {
+        for (int j = 0; j < input[i].length; j++) {
+          repeated[i][j] = input[i][j];
+        }
+      }
+      return input;
+    }
+    @Override
+    public IntParcelable[][] Repeat2dParcelables(
+        IntParcelable[][] input, IntParcelable[][] repeated) throws RemoteException {
+      for (int i = 0; i < input.length; i++) {
+        for (int j = 0; j < input[i].length; j++) {
+          repeated[i][j] = input[i][j];
+        }
+      }
+      return input;
     }
   }
 
diff --git a/tests/java/src/android/aidl/tests/AidlJavaTests.java b/tests/java/src/android/aidl/tests/AidlJavaTests.java
index 43d9263..dd93ca0 100644
--- a/tests/java/src/android/aidl/tests/AidlJavaTests.java
+++ b/tests/java/src/android/aidl/tests/AidlJavaTests.java
@@ -12,7 +12,7 @@
         Result result = junit.run(ExtensionTests.class, GenericTests.class,
             JavaOnlyImmutableAnnotationTests.class, MapTests.class, NullableTests.class,
             TestServiceClient.class, TestVersionedInterface.class, UnionTests.class,
-            VintfTests.class);
+            VintfTests.class, BuiltInTests.class, DelegatorTests.class);
 
         System.out.println(result.wasSuccessful() ? "TEST SUCCESS" : "TEST FAILURE");
     }
diff --git a/tests/java/src/android/aidl/tests/BadParcelable.java b/tests/java/src/android/aidl/tests/BadParcelable.java
new file mode 100644
index 0000000..077fbf5
--- /dev/null
+++ b/tests/java/src/android/aidl/tests/BadParcelable.java
@@ -0,0 +1,83 @@
+/*
+ * 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;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class BadParcelable implements Parcelable {
+  private boolean mBad;
+  private String mName;
+  private int mNumber;
+
+  BadParcelable() {}
+  BadParcelable(boolean bad, String name, int number) {
+    this.mBad = bad;
+    this.mName = name;
+    this.mNumber = number;
+  }
+
+  public int describeContents() { return 0; }
+
+  public void writeToParcel(Parcel dest, int flags) {
+    dest.writeBoolean(mBad);
+    dest.writeString(mName);
+    dest.writeInt(mNumber);
+    // BAD! write superfluous data
+    if (mBad) {
+      dest.writeInt(42);
+    }
+  }
+
+  public void readFromParcel(Parcel source) {
+    mBad = source.readBoolean();
+    mName = source.readString();
+    mNumber = source.readInt();
+  }
+
+  public boolean equals(Object o) {
+    if (o == null) {
+      return false;
+    }
+    if (!(o instanceof BadParcelable)) {
+      return false;
+    }
+    BadParcelable p = (BadParcelable) o;
+    if (mBad != p.mBad) {
+      return false;
+    }
+    if ((mName == null && p.mName != null) || (mName != null && !mName.equals(p.mName))) {
+      return false;
+    }
+    return mNumber == p.mNumber;
+  }
+
+  public String toString() {
+    return "BadParcelable(bad=" + mBad + ",name=" + mName + ",number=" + mNumber + "}";
+  }
+
+  public static final Parcelable.Creator<BadParcelable> CREATOR =
+      new Parcelable.Creator<BadParcelable>() {
+        public BadParcelable createFromParcel(Parcel source) {
+          BadParcelable p = new BadParcelable();
+          p.readFromParcel(source);
+          return p;
+        }
+
+        public BadParcelable[] newArray(int size) { return new BadParcelable[size]; }
+      };
+}
diff --git a/tests/java/src/android/aidl/tests/BuiltInTests.java b/tests/java/src/android/aidl/tests/BuiltInTests.java
new file mode 100644
index 0000000..4babc37
--- /dev/null
+++ b/tests/java/src/android/aidl/tests/BuiltInTests.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class BuiltInTests {
+  private IBinder mBinder;
+
+  @Before
+  public void setUp() throws RemoteException {
+    mBinder = ServiceManager.waitForService(ITestService.class.getName());
+    assertNotNull(mBinder);
+  }
+
+  @Test
+  public void testPing() {
+    assertTrue(mBinder.pingBinder());
+  }
+
+  @Test
+  public void testInterfaceDescriptor() throws RemoteException {
+    assertThat(mBinder.getInterfaceDescriptor(), is("android.aidl.tests.ITestService"));
+  }
+}
diff --git a/tests/java/src/android/aidl/tests/DelegatorTests.java b/tests/java/src/android/aidl/tests/DelegatorTests.java
new file mode 100644
index 0000000..a01356e
--- /dev/null
+++ b/tests/java/src/android/aidl/tests/DelegatorTests.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022, 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;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class DelegatorTests {
+  static byte kFakeByte = 16;
+  static byte kExpectedByte = 12;
+
+  private class Custom extends ITestService.Delegator {
+    public Custom(ITestService impl) { super(impl); }
+    @Override
+    public byte RepeatByte(byte token) throws RemoteException {
+      return kFakeByte;
+    }
+  }
+
+  @Test
+  public void testDelegator() throws RemoteException {
+    IBinder binder = ServiceManager.waitForService(ITestService.class.getName());
+    assertNotNull(binder);
+    ITestService service = ITestService.Stub.asInterface(binder);
+    ITestService.Delegator delegator = new ITestService.Delegator(service);
+    assertThat(delegator.RepeatByte(kExpectedByte), is(kExpectedByte));
+  }
+
+  @Test
+  public void testCustomDelegator() throws RemoteException {
+    IBinder binder = ServiceManager.waitForService(ITestService.class.getName());
+    assertNotNull(binder);
+    ITestService service = ITestService.Stub.asInterface(binder);
+    ITestService.Delegator custom = new Custom(service);
+    assertThat(custom.RepeatByte(kExpectedByte), is(kFakeByte));
+  }
+
+  @Test
+  public void testAsBinderAsInterface() throws RemoteException {
+    IBinder binder = ServiceManager.waitForService(ITestService.class.getName());
+    assertNotNull(binder);
+    ITestService service = ITestService.Stub.asInterface(binder);
+    ITestService.Delegator delegator = new ITestService.Delegator(service);
+    assertThat(ITestService.Delegator.asInterface(delegator.asBinder()).RepeatByte(kExpectedByte),
+        is(kExpectedByte));
+  }
+}
diff --git a/tests/java/src/android/aidl/tests/ExtensionTests.java b/tests/java/src/android/aidl/tests/ExtensionTests.java
index e923ad2..d573156 100644
--- a/tests/java/src/android/aidl/tests/ExtensionTests.java
+++ b/tests/java/src/android/aidl/tests/ExtensionTests.java
@@ -58,20 +58,14 @@
     private UnstableParcelable up;
 
     private ITestService mService;
-    private ICppJavaTests mCppJavaTests;
 
     @Before
-    public void setUp() throws RemoteException {
+    public void setUp() {
       IBinder binder = ServiceManager.waitForService(ITestService.class.getName());
       assertNotNull(binder);
       mService = ITestService.Stub.asInterface(binder);
       assertNotNull(mService);
 
-      IBinder binder2 = mService.GetCppJavaTests();
-      if (binder2 != null) {
-        mCppJavaTests = ICppJavaTests.Stub.asInterface(binder2);
-      }
-
       vep = new VintfExtendableParcelable();
       vp = new VintfParcelable();
 
@@ -84,8 +78,6 @@
 
     @Test
     public void testRepeatExtendableParcelable() throws RemoteException {
-      assumeTrue(mCppJavaTests != null);
-
       MyExt ext = new MyExt();
       ext.a = 42;
       ext.b = "EXT";
@@ -98,7 +90,7 @@
       ep.ext.setParcelable(ext);
 
       ExtendableParcelable ep2 = new ExtendableParcelable();
-      mCppJavaTests.RepeatExtendableParcelable(ep, ep2);
+      mService.RepeatExtendableParcelable(ep, ep2);
       assertThat(ep2.a, is(ep.a));
       assertThat(ep2.b, is(ep.b));
 
diff --git a/tests/java/src/android/aidl/tests/NestedTypesTests.java b/tests/java/src/android/aidl/tests/NestedTypesTests.java
new file mode 100644
index 0000000..c5851d5
--- /dev/null
+++ b/tests/java/src/android/aidl/tests/NestedTypesTests.java
@@ -0,0 +1,60 @@
+/*
+ * 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;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assume.assumeTrue;
+
+import android.aidl.tests.nested.INestedService;
+import android.aidl.tests.nested.ParcelableWithNested;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class NestedTypesTests {
+  @Test
+  public void testUseNestedTypes() throws RemoteException {
+    IBinder binder = ServiceManager.waitForService(INestedService.class.getName());
+    assertNotNull(binder);
+    INestedService nestedService = INestedService.Stub.asInterface(binder);
+    assertNotNull(nestedService);
+
+    // OK -> NOT_OK
+    ParcelableWithNested p = new ParcelableWithNested();
+    p.status = ParcelableWithNested.Status.OK;
+    INestedService.Result result = nestedService.flipStatus(p);
+    assertThat(result, is(ParcelableWithNested.Status.NOT_OK));
+
+    // NOT_OK -> OK with nested callback interface
+    class Callback extends INestedService.ICallback.Stub {
+      byte received = ParcelableWithNested.Status.NOT_OK;
+      @Override
+      public void done(byte st) {
+        received = st;
+      }
+    }
+    Callback cb = new Callback();
+    nestedService.flipStatusWithCallback(p.status, cb);
+    assertThat(cb.received, is(ParcelableWithNested.Status.OK));
+  }
+}
diff --git a/tests/java/src/android/aidl/tests/NullableTests.java b/tests/java/src/android/aidl/tests/NullableTests.java
index 392d784..2cab3a2 100644
--- a/tests/java/src/android/aidl/tests/NullableTests.java
+++ b/tests/java/src/android/aidl/tests/NullableTests.java
@@ -16,24 +16,25 @@
 
 package android.aidl.tests;
 
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNull.notNullValue;
+import static org.hamcrest.core.IsNull.nullValue;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertThat;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
-import static org.hamcrest.core.Is.is;
-import static org.hamcrest.core.IsNull.nullValue;
-import static org.hamcrest.core.IsNull.notNullValue;
 
+import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
-
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.runners.JUnit4;
 import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 
 @RunWith(JUnit4.class)
 public class NullableTests {
@@ -66,6 +67,20 @@
     }
 
     @Test
+    public void testRepeatNullableParcelableArray() throws RemoteException {
+      ITestService.Empty[] input = {new ITestService.Empty(), null};
+      assertThat(mService.RepeatNullableParcelableArray(input), is(input));
+      assertThat(mService.RepeatNullableParcelableArray(null), is(nullValue()));
+    }
+
+    @Test
+    public void testRepeatNullableParcelableList() throws RemoteException {
+      List<ITestService.Empty> input = Arrays.asList(new ITestService.Empty(), null);
+      assertThat(mService.RepeatNullableParcelableList(input), is(input));
+      assertThat(mService.RepeatNullableParcelableList(null), is(nullValue()));
+    }
+
+    @Test
     public void testExpectNpeWithNullBinder() throws RemoteException {
         try {
             mService.TakesAnIBinder(null);
@@ -80,12 +95,10 @@
 
     @Test
     public void testExpectNpeWithNullBinderList() throws RemoteException {
-        assumeTrue(mCppJavaTests != null);
-
         List<IBinder> listWithNulls = new ArrayList<IBinder>();
         listWithNulls.add(null);
         try {
-            mCppJavaTests.TakesAnIBinderList(listWithNulls);
+          mService.TakesAnIBinderList(listWithNulls);
         } catch (NullPointerException ex) {
             return;
         }
@@ -95,6 +108,34 @@
     }
 
     @Test
+    public void testReverseIBinderArray() throws RemoteException {
+      IBinder[] input = {new Binder(), new Binder()};
+      IBinder[] repeated = new IBinder[input.length];
+      IBinder[] reversed = mService.ReverseIBinderArray(input, repeated);
+
+      assertThat(repeated, is(input));
+      assertThat(reversed.length, is(input.length));
+      for (int i = 0; i < input.length; ++i) {
+        int j = reversed.length - (1 + i);
+        assertThat(reversed[j], is(input[i]));
+      }
+    }
+
+    @Test
+    public void testReverseNullableIBinderArray() throws RemoteException {
+      IBinder[] input = {new Binder(), null};
+      IBinder[] repeated = new IBinder[input.length];
+      IBinder[] reversed = mService.ReverseNullableIBinderArray(input, repeated);
+
+      assertThat(repeated, is(input));
+      assertThat(reversed.length, is(input.length));
+      for (int i = 0; i < input.length; ++i) {
+        int j = reversed.length - (1 + i);
+        assertThat(reversed[j], is(input[i]));
+      }
+    }
+
+    @Test
     public void testNullableIInterface() throws RemoteException {
         INamedCallback callback  = mService.GetCallback(false);
         assertThat(callback, is(notNullValue()));
diff --git a/tests/java/src/android/aidl/tests/TestServiceClient.java b/tests/java/src/android/aidl/tests/TestServiceClient.java
index e1e8e8b..e9140cc 100644
--- a/tests/java/src/android/aidl/tests/TestServiceClient.java
+++ b/tests/java/src/android/aidl/tests/TestServiceClient.java
@@ -18,16 +18,23 @@
 
 import static org.hamcrest.core.Is.is;
 import static org.hamcrest.core.IsNull.notNullValue;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
 
+import android.aidl.fixedsizearray.FixedSizeArrayExample.IRepeatFixedSizeArray;
+import android.aidl.fixedsizearray.FixedSizeArrayExample.IntParcelable;
+import android.aidl.tests.BadParcelable;
 import android.aidl.tests.ByteEnum;
 import android.aidl.tests.GenericStructuredParcelable;
 import android.aidl.tests.INamedCallback;
 import android.aidl.tests.ITestService;
+import android.aidl.tests.ITestService.CompilerChecks;
 import android.aidl.tests.IntEnum;
 import android.aidl.tests.LongEnum;
 import android.aidl.tests.SimpleParcelable;
@@ -37,9 +44,11 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
+import android.os.BadParcelableException;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -50,6 +59,7 @@
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.lang.reflect.Array;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -283,6 +293,38 @@
     }
 
     @Test
+    public void testBinderArrayExchange() throws RemoteException {
+      String[] names = {"Fizz", "Buzz"};
+      INamedCallback[] got = service.GetInterfaceArray(names);
+      assertThat(got[0].GetName(), is(names[0]));
+      assertThat(got[1].GetName(), is(names[1]));
+
+      assertThat(service.VerifyNamesWithInterfaceArray(got, names), is(true));
+    }
+
+    @Test
+    public void testNullableBinderArrayExchange() throws RemoteException {
+      String[] names = {"Fizz", null, "Buzz"};
+      INamedCallback[] got = service.GetNullableInterfaceArray(names);
+      assertThat(got[0].GetName(), is(names[0]));
+      assertNull(got[1]);
+      assertThat(got[2].GetName(), is(names[2]));
+
+      assertThat(service.VerifyNamesWithNullableInterfaceArray(got, names), is(true));
+    }
+
+    @Test
+    public void testInterfaceListExchange() throws RemoteException {
+      String[] names = {"Fizz", null, "Buzz"};
+      List<INamedCallback> got = service.GetInterfaceList(names);
+      assertThat(got.get(0).GetName(), is(names[0]));
+      assertNull(got.get(1));
+      assertThat(got.get(2).GetName(), is(names[2]));
+
+      assertThat(service.VerifyNamesWithInterfaceList(got, names), is(true));
+    }
+
+    @Test
     public void testListReversal() throws RemoteException {
         List<String> input = Arrays.asList("Walk", "into", "Córdoba");
         List<String> echoed = new ArrayList<String>();
@@ -314,6 +356,19 @@
     }
 
     @Test
+    public void testBadParcelable() throws RemoteException {
+      assumeTrue(cpp_java_tests != null);
+      BadParcelable bad = new BadParcelable(/*bad=*/true, "foo", 42);
+      Throwable error =
+          assertThrows(BadParcelableException.class, () -> cpp_java_tests.RepeatBadParcelable(bad));
+      assertTrue(error.getMessage().contains("Parcel data not fully consumed"));
+
+      BadParcelable notBad = new BadParcelable(/*bad=*/false, "foo", 42);
+      BadParcelable output = cpp_java_tests.RepeatBadParcelable(notBad);
+      assertThat(notBad, is(output));
+    }
+
+    @Test
     public void testRepeatParcelable() throws RemoteException {
         assumeTrue(cpp_java_tests != null);
 
@@ -437,6 +492,21 @@
         assertThat(reversed[2].getDouble(testDoubleKey), is(input[0].getDouble(testDoubleKey)));
     }
 
+    private void writeToFd(FileDescriptor fd, byte[] testData) throws IOException {
+      FileOutputStream fdStream = new FileOutputStream(fd);
+      fdStream.write(testData);
+      fdStream.close();
+    }
+
+    private void verifyFileContents(String file, byte[] testData) throws IOException {
+      FileInputStream fis = new FileInputStream(file);
+      byte[] readData = new byte[testData.length];
+
+      assertThat(fis.read(readData), is(readData.length));
+      assertThat(readData, is(testData));
+      assertThat(fis.read(), is(-1));
+    }
+
     @Test
     public void testFileDescriptorPassing() throws RemoteException, IOException {
         assumeTrue(cpp_java_tests != null);
@@ -448,18 +518,43 @@
         FileDescriptor journeyed = cpp_java_tests.RepeatFileDescriptor(descriptor);
         fos.close();
 
-        FileOutputStream journeyedStream = new FileOutputStream(journeyed);
-
         String testData = "FrazzleSnazzleFlimFlamFlibbityGumboChops";
-        byte[] output = testData.getBytes();
-        journeyedStream.write(output);
-        journeyedStream.close();
+        writeToFd(journeyed, testData.getBytes());
+        verifyFileContents(file, testData.getBytes());
+    }
 
-        FileInputStream fis = new FileInputStream(file);
-        byte[] input = new byte[output.length];
+    @Test
+    public void testFileDescriptorArrayPassing() throws RemoteException, IOException {
+      assumeTrue(cpp_java_tests != null);
 
-        assertThat(fis.read(input), is(input.length));
-        assertThat(input, is(output));
+      final int kTestSize = 2;
+
+      String fileBase = "/data/local/tmp/aidl-test-file_";
+      String[] files = new String[kTestSize]; // any size to test
+      FileOutputStream[] fos = new FileOutputStream[kTestSize];
+      FileDescriptor[] descriptors = new FileDescriptor[kTestSize];
+      for (int i = 0; i < kTestSize; i++) {
+        files[i] = fileBase + i;
+        fos[i] = new FileOutputStream(files[i], false /*append*/);
+        descriptors[i] = fos[i].getFD();
+      }
+
+      FileDescriptor[] repeated = new FileDescriptor[kTestSize];
+      FileDescriptor[] reversed = cpp_java_tests.ReverseFileDescriptorArray(descriptors, repeated);
+
+      for (int i = 0; i < kTestSize; i++) {
+        fos[i].close();
+      }
+
+      for (int i = 0; i < kTestSize; i++) {
+        String testData = "Something " + i;
+
+        writeToFd(reversed[kTestSize - 1 - i], testData.getBytes());
+        verifyFileContents(files[i], testData.getBytes());
+
+        writeToFd(repeated[i], testData.getBytes());
+        verifyFileContents(files[i], (testData + testData).getBytes());
+      }
     }
 
     @Test
@@ -512,7 +607,7 @@
 
     @Test
     public void testReverseUtf8StringArray() throws RemoteException {
-        String[] input = (String[])utf8_queries.toArray();
+        String[] input = utf8_queries.toArray(new String[0]);
         String echoed[] = new String[input.length];
 
         String[] reversed = service.ReverseUtf8CppString(input, echoed);
@@ -535,7 +630,7 @@
                 null,
                 // Java doesn't handle unicode code points above U+FFFF well.
                 new String(Character.toChars(0x1F701)) + "\u03A9");
-        String[] input = (String[])utf8_queries_and_nulls.toArray();
+        String[] input = utf8_queries_and_nulls.toArray(new String[0]);
         String echoed[] = new String[input.length];
 
         String[] reversed = service.ReverseNullableUtf8CppString(input, echoed);
@@ -566,7 +661,7 @@
     }
 
     @Test
-    public void testStructurecParcelableEquality() {
+    public void testStructuredParcelableEquality() {
         StructuredParcelable p = new StructuredParcelable();
         p.shouldContainThreeFs = new int[] {1, 2, 3};
         p.shouldBeJerry = "Jerry";
@@ -588,7 +683,7 @@
     }
 
     @Test
-    public void testStrucuturedParcelable() throws RemoteException {
+    public void testStructuredParcelable() throws RemoteException {
         final int kDesiredFValue = 17;
 
         StructuredParcelable p = new StructuredParcelable();
@@ -598,6 +693,7 @@
         p.shouldContainTwoByteFoos = new byte[2];
         p.shouldContainTwoIntFoos = new int[2];
         p.shouldContainTwoLongFoos = new long[2];
+        p.empty = new StructuredParcelable.Empty();
 
         // Check the default values
         assertThat(p.stringDefaultsToFoo, is("foo"));
@@ -628,6 +724,9 @@
         assertThat(p.int32_max, is(Integer.MAX_VALUE));
         assertThat(p.int64_max, is(Long.MAX_VALUE));
         assertThat(p.hexInt32_neg_1, is(-1));
+        for (int ndx = 0; ndx < p.int8_1.length; ndx++) {
+          assertThat(p.int8_1[ndx], is((byte) 1));
+        }
         for (int ndx = 0; ndx < p.int32_1.length; ndx++) {
             assertThat(p.int32_1[ndx], is(1));
         }
@@ -687,6 +786,8 @@
             + "int64_max: 9223372036854775807, "
             + "hexInt32_neg_1: -1, "
             + "ibinder: null, "
+            + "empty: android.aidl.tests.StructuredParcelable.Empty{}, "
+            + "int8_1: [1, 1, 1, 1, 1], "
             + "int32_1: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, "
             + "1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, "
             + "1, 1, 1, 1], "
@@ -834,4 +935,71 @@
       assertThat(repeated.getNs(), is(new int[] {1, 2, 3}));
       assertThat(reversed.getNs(), is(new int[] {3, 2, 1}));
     }
+
+    @Test
+    public void testReverseRecursiveList() throws RemoteException {
+      RecursiveList head = null;
+      for (int i = 0; i < 10; i++) {
+        RecursiveList node = new RecursiveList();
+        node.value = i;
+        node.next = head;
+        head = node;
+      }
+      // head: [9, 8, .. , 0]
+      RecursiveList reversed = service.ReverseList(head);
+      // reversed should be [0, 1, .. 9]
+      for (int i = 0; i < 10; i++) {
+        assertThat(reversed.value, is(i));
+        reversed = reversed.next;
+      }
+      assertNull(reversed);
+    }
+
+    @Test
+    public void testDescribeContents() throws Exception {
+      CompilerChecks cc = new CompilerChecks();
+      cc.pfd_array = new ParcelFileDescriptor[] {null, null, null};
+      assertThat(cc.describeContents(), is(0));
+
+      String file = "/data/local/tmp/aidl-test-file";
+      cc.pfd_array[1] = ParcelFileDescriptor.open(
+          new File(file), ParcelFileDescriptor.MODE_CREATE | ParcelFileDescriptor.MODE_WRITE_ONLY);
+      assertThat(cc.describeContents(), is(Parcelable.CONTENTS_FILE_DESCRIPTOR));
+    }
+
+    @Test
+    public void testFixedSizeArrayOverBinder() throws Exception {
+      IBinder binder = ServiceManager.waitForService(IRepeatFixedSizeArray.DESCRIPTOR);
+      assertNotNull(binder);
+      IRepeatFixedSizeArray service = IRepeatFixedSizeArray.Stub.asInterface(binder);
+      assertNotNull(service);
+
+      {
+        byte[] input = new byte[] {1, 2, 3};
+        byte[] repeated = new byte[3];
+        byte[] output = service.RepeatBytes(input, repeated);
+        assertArrayEquals(input, repeated);
+        assertArrayEquals(input, output);
+      }
+      {
+        int[] input = new int[] {1, 2, 3};
+        int[] repeated = new int[3];
+        int[] output = service.RepeatInts(input, repeated);
+        assertArrayEquals(input, repeated);
+        assertArrayEquals(input, output);
+      }
+      {
+        IntParcelable p1 = new IntParcelable();
+        p1.value = 1;
+        IntParcelable p2 = new IntParcelable();
+        p2.value = 1;
+        IntParcelable p3 = new IntParcelable();
+        p3.value = 1;
+        IntParcelable[][] input = new IntParcelable[][] {{p1, p2, p3}, {p1, p2, p3}};
+        IntParcelable[][] repeated = new IntParcelable[2][3];
+        IntParcelable[][] output = service.Repeat2dParcelables(input, repeated);
+        assertArrayEquals(input, repeated);
+        assertArrayEquals(input, output);
+      }
+    }
 }
diff --git a/tests/java/src/android/aidl/tests/TestVersionedInterface.java b/tests/java/src/android/aidl/tests/TestVersionedInterface.java
index bb96331..dd25ccd 100644
--- a/tests/java/src/android/aidl/tests/TestVersionedInterface.java
+++ b/tests/java/src/android/aidl/tests/TestVersionedInterface.java
@@ -92,8 +92,24 @@
     public void testReadDataCorrectlyAfterParcelableWithNewField() throws RemoteException {
       Foo inFoo = new Foo();
       Foo inoutFoo = new Foo();
+      inoutFoo.intDefault42 = 0;
       Foo outFoo = new Foo();
+      outFoo.intDefault42 = 0;
       int ret = service.ignoreParcelablesAndRepeatInt(inFoo, inoutFoo, outFoo, 43);
       assertThat(ret, is(43));
+      assertThat(inoutFoo.intDefault42, is(0));
+      assertThat(outFoo.intDefault42, is(0));
+    }
+
+    @Test
+    public void testDelegatorGetInterfaceVersion() throws RemoteException {
+      IFooInterface.Delegator delegator = new IFooInterface.Delegator(service);
+      assertThat(delegator.getInterfaceVersion(), is(1));
+    }
+
+    @Test
+    public void testDelegatorGetInterfaceHash() throws RemoteException {
+      IFooInterface.Delegator delegator = new IFooInterface.Delegator(service);
+      assertThat(delegator.getInterfaceHash(), is("9e7be1859820c59d9d55dd133e71a3687b5d2e5b"));
     }
 }
diff --git a/tests/lazy_test/Android.bp b/tests/lazy_test/Android.bp
index fea1263..9eb814c 100644
--- a/tests/lazy_test/Android.bp
+++ b/tests/lazy_test/Android.bp
@@ -22,6 +22,7 @@
 
     static_libs: [
         "lazy_test_service_aidl-cpp",
+        "lazy_cb_test_service_aidl-cpp",
     ],
 }
 
@@ -53,3 +54,32 @@
         "ILazyTestService.aidl",
     ],
 }
+
+cc_binary {
+    name: "aidl_lazy_cb_test_server",
+    srcs: [
+        "ServerCb.cpp",
+        "LazyTestServiceCb.cpp",
+    ],
+    init_rc: ["aidl_lazy_cb_test_server.rc"],
+    system_ext_specific: true,
+
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+
+    static_libs: [
+        "lazy_cb_test_service_aidl-cpp",
+    ],
+}
+
+aidl_interface {
+    name: "lazy_cb_test_service_aidl",
+    unstable: true,
+    flags: ["-Werror"],
+    srcs: [
+        "ILazyTestServiceCb.aidl",
+    ],
+}
diff --git a/tests/lazy_test/ILazyTestService.aidl b/tests/lazy_test/ILazyTestService.aidl
index 46939d9..9cafdd1 100644
--- a/tests/lazy_test/ILazyTestService.aidl
+++ b/tests/lazy_test/ILazyTestService.aidl
@@ -16,11 +16,4 @@
 
 interface ILazyTestService {
     void forcePersist(boolean persist);
-    /**
-     * Ask the process hosting the service to install a callback that notifies if there are
-	 * services with clients.
-     * For testing purposes, this callback exercises the code to unregister/re-register
-     * the services and eventually shuts down the process.
-     */
-    void setCustomActiveServicesCallback();
 }
diff --git a/tests/lazy_test/ILazyTestServiceCb.aidl b/tests/lazy_test/ILazyTestServiceCb.aidl
new file mode 100644
index 0000000..a304761
--- /dev/null
+++ b/tests/lazy_test/ILazyTestServiceCb.aidl
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+interface ILazyTestServiceCb {
+    /**
+     * Set the eventfd used to notify that the active services
+     * callback is being executed and is about to terminate the process.
+     */
+    void setEventFd(in ParcelFileDescriptor parcelFd);
+}
diff --git a/tests/lazy_test/LazyTestService.cpp b/tests/lazy_test/LazyTestService.cpp
index ce8b406..d6a5cd3 100644
--- a/tests/lazy_test/LazyTestService.cpp
+++ b/tests/lazy_test/LazyTestService.cpp
@@ -27,34 +27,5 @@
   return Status::ok();
 }
 
-Status LazyTestService::setCustomActiveServicesCallback() {
-  auto lazyRegistrar = LazyServiceRegistrar::getInstance();
-  lazyRegistrar.setActiveServicesCallback([lazyRegistrar](bool hasClients) mutable -> bool {
-    if (hasClients) {
-      return false;
-    }
-
-    // Unregister all services
-    if (!lazyRegistrar.tryUnregister()) {
-      // Prevent shutdown (test will fail)
-      return true;
-    }
-
-    // Re-register all services
-    lazyRegistrar.reRegister();
-
-    // Unregister again before shutdown
-    if (!lazyRegistrar.tryUnregister()) {
-      // Prevent shutdown (test will fail)
-      return true;
-    }
-
-    exit(EXIT_SUCCESS);
-    // Unreachable
-  });
-
-  return Status::ok();
-}
-
 }  // namespace binder
 }  // namespace android
diff --git a/tests/lazy_test/LazyTestService.h b/tests/lazy_test/LazyTestService.h
index fbab1f5..31d1155 100644
--- a/tests/lazy_test/LazyTestService.h
+++ b/tests/lazy_test/LazyTestService.h
@@ -28,7 +28,6 @@
   virtual ~LazyTestService() {}
 
   ::android::binder::Status forcePersist(bool persist);
-  ::android::binder::Status setCustomActiveServicesCallback();
 };
 
 }  // namespace binder
diff --git a/tests/lazy_test/LazyTestServiceCb.cpp b/tests/lazy_test/LazyTestServiceCb.cpp
new file mode 100644
index 0000000..f6e1d84
--- /dev/null
+++ b/tests/lazy_test/LazyTestServiceCb.cpp
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#include <sys/eventfd.h>
+
+#include <binder/LazyServiceRegistrar.h>
+#include "LazyTestServiceCb.h"
+
+namespace android {
+namespace binder {
+
+void LazyTestServiceCb::setCustomActiveServicesCallback() {
+  auto lazyRegistrar = LazyServiceRegistrar::getInstance();
+  lazyRegistrar.setActiveServicesCallback([lazyRegistrar, this](bool hasClients) mutable -> bool {
+    if (hasClients) {
+      return false;
+    }
+
+    if (mFd < 0) {
+      // Prevent shutdown (test will fail)
+      return true;
+    }
+
+    // Unregister all services
+    if (!lazyRegistrar.tryUnregister()) {
+      // Prevent shutdown (test will fail)
+      return true;
+    }
+
+    // Re-register all services
+    lazyRegistrar.reRegister();
+
+    // Unregister again before shutdown
+    if (!lazyRegistrar.tryUnregister()) {
+      // Prevent shutdown (test will fail)
+      return true;
+    }
+
+    // Tell the test we're shutting down
+    if (TEMP_FAILURE_RETRY(eventfd_write(mFd, /* value */ 1)) < 0) {
+      // Prevent shutdown (test will fail)
+      return true;
+    }
+
+    exit(EXIT_SUCCESS);
+    // Unreachable
+  });
+}
+
+Status LazyTestServiceCb::setEventFd(const ::android::os::ParcelFileDescriptor& parcelFd) {
+  mFd = dup(parcelFd.get());
+
+  return mFd < 0 ? Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT) : Status::ok();
+}
+
+}  // namespace binder
+}  // namespace android
diff --git a/tests/lazy_test/LazyTestServiceCb.h b/tests/lazy_test/LazyTestServiceCb.h
new file mode 100644
index 0000000..68fc808
--- /dev/null
+++ b/tests/lazy_test/LazyTestServiceCb.h
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <BnLazyTestServiceCb.h>
+#include <binder/Status.h>
+
+namespace android {
+namespace binder {
+
+class LazyTestServiceCb : public BnLazyTestServiceCb {
+ public:
+  LazyTestServiceCb() : mFd(-1) {}
+  virtual ~LazyTestServiceCb() {}
+
+  ::android::binder::Status setEventFd(const ::android::os::ParcelFileDescriptor& parcelFd);
+  void setCustomActiveServicesCallback();
+
+ private:
+  int mFd;
+};
+
+}  // namespace binder
+}  // namespace android
diff --git a/tests/lazy_test/ServerCb.cpp b/tests/lazy_test/ServerCb.cpp
new file mode 100644
index 0000000..bed9ec0
--- /dev/null
+++ b/tests/lazy_test/ServerCb.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#include <binder/IBinder.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/LazyServiceRegistrar.h>
+#include <utils/Log.h>
+#include "LazyTestServiceCb.h"
+
+using android::BBinder;
+using android::IBinder;
+using android::IPCThreadState;
+using android::OK;
+using android::sp;
+using android::binder::LazyServiceRegistrar;
+using android::binder::LazyTestServiceCb;
+
+int main() {
+  sp<LazyTestServiceCb> service = new LazyTestServiceCb();
+
+  // Set the callback before registering the service
+  service->setCustomActiveServicesCallback();
+
+  auto lazyRegistrar = LazyServiceRegistrar::getInstance();
+  LOG_ALWAYS_FATAL_IF(OK != lazyRegistrar.registerService(service, "aidl_lazy_cb_test"), "");
+
+  IPCThreadState::self()->joinThreadPool();
+
+  return 1;
+}
diff --git a/tests/lazy_test/aidl_lazy_cb_test_server.rc b/tests/lazy_test/aidl_lazy_cb_test_server.rc
new file mode 100644
index 0000000..d3b505b
--- /dev/null
+++ b/tests/lazy_test/aidl_lazy_cb_test_server.rc
@@ -0,0 +1,6 @@
+service aidl_lazy_cb_test /system_ext/bin/aidl_lazy_cb_test_server
+    interface aidl aidl_lazy_cb_test
+    user system
+    group system
+    oneshot
+    disabled
diff --git a/tests/lazy_test/main.cpp b/tests/lazy_test/main.cpp
index e1fa5f1..0a8393f 100644
--- a/tests/lazy_test/main.cpp
+++ b/tests/lazy_test/main.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <sys/eventfd.h>
 #include <cstdlib>
 #include <ctime>
 #include <iostream>
@@ -21,9 +22,11 @@
 #include <string>
 #include <thread>
 
+#include <sys/epoll.h>
 #include <unistd.h>
 
 #include <ILazyTestService.h>
+#include <ILazyTestServiceCb.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <gtest/gtest.h>
@@ -35,9 +38,12 @@
 using ::android::IServiceManager;
 using ::android::sp;
 using ::android::String16;
+using ::android::base::unique_fd;
+using ::android::os::ParcelFileDescriptor;
 
 std::vector<String16> gServiceNames;
 static constexpr size_t SHUTDOWN_WAIT_TIME = 10;
+static constexpr size_t CALLBACK_SHUTDOWN_WAIT_TIME = 5;
 
 sp<IBinder> waitForService(const String16& name) {
   sp<IServiceManager> manager;
@@ -166,8 +172,9 @@
   }
 };
 
-sp<ILazyTestService> waitForLazyTestService(String16 name) {
-  sp<ILazyTestService> service = android::waitForService<ILazyTestService>(name);
+template <typename T>
+sp<T> waitForLazyTestService(String16 name) {
+  sp<T> service = android::waitForService<T>(name);
   EXPECT_NE(service, nullptr);
   return service;
 }
@@ -175,7 +182,7 @@
 TEST_F(AidlLazyRegistrarTest, ForcedPersistenceTest) {
   sp<ILazyTestService> service;
   for (int i = 0; i < 2; i++) {
-    service = waitForLazyTestService(serviceName);
+    service = waitForLazyTestService<ILazyTestService>(serviceName);
     EXPECT_TRUE(service->forcePersist(i == 0).isOk());
     service = nullptr;
 
@@ -193,15 +200,49 @@
 }
 
 TEST_F(AidlLazyRegistrarTest, ActiveServicesCountCallbackTest) {
-  sp<ILazyTestService> service;
-  service = waitForLazyTestService(serviceName);
-  ASSERT_TRUE(service->setCustomActiveServicesCallback().isOk());
+  const String16 cbServiceName = String16("aidl_lazy_cb_test");
+
+  int efd = eventfd(0, 0);
+  ASSERT_GE(efd, 0) << "Failed to create eventfd";
+
+  unique_fd uniqueEventFd(efd);
+  ParcelFileDescriptor parcelEventFd(std::move(uniqueEventFd));
+
+  sp<ILazyTestServiceCb> service;
+  service = waitForLazyTestService<ILazyTestServiceCb>(cbServiceName);
+  ASSERT_TRUE(service->setEventFd(parcelEventFd).isOk());
   service = nullptr;
 
-  std::cout << "Waiting " << SHUTDOWN_WAIT_TIME << " seconds before checking whether the "
-            << "service is still running." << std::endl;
   IPCThreadState::self()->flushCommands();
-  sleep(SHUTDOWN_WAIT_TIME);
+
+  std::cout << "Waiting " << SHUTDOWN_WAIT_TIME << " seconds for callback completion "
+            << "notification." << std::endl;
+
+  int epollFd = epoll_create1(EPOLL_CLOEXEC);
+  ASSERT_GE(epollFd, 0) << "Failed to create epoll";
+  unique_fd epollUniqueFd(epollFd);
+
+  const int EPOLL_MAX_EVENTS = 1;
+  struct epoll_event event, events[EPOLL_MAX_EVENTS];
+
+  event.events = EPOLLIN;
+  event.data.fd = efd;
+  int rc = epoll_ctl(epollFd, EPOLL_CTL_ADD, efd, &event);
+  ASSERT_GE(rc, 0) << "Failed to add fd to epoll";
+
+  rc = TEMP_FAILURE_RETRY(epoll_wait(epollFd, events, EPOLL_MAX_EVENTS, SHUTDOWN_WAIT_TIME * 1000));
+  ASSERT_NE(rc, 0) << "Service shutdown timeout";
+  ASSERT_GT(rc, 0) << "Error waiting for service shutdown notification";
+
+  eventfd_t counter;
+  rc = TEMP_FAILURE_RETRY(eventfd_read(parcelEventFd.get(), &counter));
+  ASSERT_GE(rc, 0) << "Failed to get callback completion notification from service";
+  ASSERT_EQ(counter, 1);
+
+  std::cout << "Waiting " << CALLBACK_SHUTDOWN_WAIT_TIME << " seconds before checking whether the "
+            << "service is still running." << std::endl;
+
+  sleep(CALLBACK_SHUTDOWN_WAIT_TIME);
 
   ASSERT_FALSE(isServiceRunning(serviceName)) << "Service failed to shut down.";
 }
diff --git a/tests/rust/test_client.rs b/tests/rust/test_client.rs
index 0725161..1d75234 100644
--- a/tests/rust/test_client.rs
+++ b/tests/rust/test_client.rs
@@ -16,25 +16,46 @@
 
 //! Test Rust client for the AIDL compiler.
 
+use ::binder::{binder_impl::Parcel, Parcelable};
+use aidl_test_fixedsizearray::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::{
+    FixedSizeArrayExample,
+    IRepeatFixedSizeArray::{BpRepeatFixedSizeArray, IRepeatFixedSizeArray},
+    IntParcelable::IntParcelable,
+};
+use aidl_test_interface::aidl::android::aidl::tests::nested::{
+    INestedService, ParcelableWithNested,
+};
+use aidl_test_interface::aidl::android::aidl::tests::unions::EnumUnion::EnumUnion;
 use aidl_test_interface::aidl::android::aidl::tests::INewName::{self, BpNewName};
 use aidl_test_interface::aidl::android::aidl::tests::IOldName::{self, BpOldName};
 use aidl_test_interface::aidl::android::aidl::tests::ITestService::{
-    self, BpTestService, ITestServiceDefault, ITestServiceDefaultRef,
+    self, BpTestService, Empty::Empty, ITestServiceDefault, ITestServiceDefaultRef,
 };
 use aidl_test_interface::aidl::android::aidl::tests::{
-    BackendType::BackendType, ByteEnum::ByteEnum, IntEnum::IntEnum, LongEnum::LongEnum, StructuredParcelable, Union,
+    extension::ExtendableParcelable::ExtendableParcelable, extension::MyExt::MyExt,
+    extension::MyExt2::MyExt2, extension::MyExtLike::MyExtLike, BackendType::BackendType,
+    ByteEnum::ByteEnum, IntEnum::IntEnum, LongEnum::LongEnum, RecursiveList::RecursiveList,
+    StructuredParcelable, Union,
 };
-use aidl_test_interface::aidl::android::aidl::tests::unions::{
-    EnumUnion::EnumUnion,
+use aidl_test_interface::binder::{self, BinderFeatures, IBinder, Interface};
+use aidl_test_nonvintf_parcelable::aidl::android::aidl::tests::nonvintf::{
+    NonVintfExtendableParcelable::NonVintfExtendableParcelable,
+    NonVintfParcelable::NonVintfParcelable,
 };
-use aidl_test_interface::binder;
+use aidl_test_unstable_parcelable::aidl::android::aidl::tests::unstable::{
+    UnstableExtendableParcelable::UnstableExtendableParcelable,
+    UnstableParcelable::UnstableParcelable,
+};
 use aidl_test_versioned_interface::aidl::android::aidl::versioned::tests::{
-    IFooInterface, IFooInterface::BpFooInterface, BazUnion::BazUnion,
+    BazUnion::BazUnion, Foo::Foo, IFooInterface, IFooInterface::BpFooInterface,
+};
+use aidl_test_vintf_parcelable::aidl::android::aidl::tests::vintf::{
+    VintfExtendableParcelable::VintfExtendableParcelable, VintfParcelable::VintfParcelable,
 };
 use std::fs::File;
 use std::io::{Read, Write};
 use std::os::unix::io::FromRawFd;
-use std::sync::Arc;
+use std::sync::{Arc, Mutex};
 
 fn get_test_service() -> binder::Strong<dyn ITestService::ITestService> {
     binder::get_interface(<BpTestService as ITestService::ITestService>::get_descriptor())
@@ -160,7 +181,7 @@
         ITestService::STRING_TEST_CONSTANT2.into(),
     ];
     for input in &inputs {
-        let result = service.RepeatString(&input);
+        let result = service.RepeatString(input);
         assert_eq!(result.as_ref(), Ok(input));
     }
 }
@@ -169,7 +190,7 @@
     ($test:ident, $func:ident, $array:expr) => {
         #[test]
         fn $test() {
-            let mut array = $array;
+            let mut array = $array.to_vec();
 
             // Java needs initial values here (can't resize arrays)
             let mut repeated = vec![Default::default(); array.len()];
@@ -208,6 +229,11 @@
     vec![ByteEnum::FOO, ByteEnum::BAR, ByteEnum::BAR]
 }
 test_reverse_array! {
+    test_array_byte_enum_values,
+    ReverseByteEnum,
+    ByteEnum::enum_values()
+}
+test_reverse_array! {
     test_array_byte_enum_v2,
     ReverseByteEnum,
     vec![ByteEnum::FOO, ByteEnum::BAR, ByteEnum::BAZ]
@@ -243,13 +269,58 @@
 fn test_binder_exchange() {
     const NAME: &str = "Smythe";
     let service = get_test_service();
-    let got = service
-        .GetOtherTestService(NAME)
-        .expect("error calling GetOtherTestService");
+    let got = service.GetOtherTestService(NAME).expect("error calling GetOtherTestService");
     assert_eq!(got.GetName().as_ref().map(String::as_ref), Ok(NAME));
     assert_eq!(service.VerifyName(&got, NAME), Ok(true));
 }
 
+#[test]
+fn test_binder_array_exchange() {
+    let names = vec!["Fizz".into(), "Buzz".into()];
+    let service = get_test_service();
+    let got = service.GetInterfaceArray(&names).expect("error calling GetInterfaceArray");
+    assert_eq!(got.iter().map(|s| s.GetName()).collect::<Result<Vec<_>, _>>(), Ok(names.clone()));
+    assert_eq!(service.VerifyNamesWithInterfaceArray(&got, &names), Ok(true));
+}
+
+#[test]
+fn test_binder_nullable_array_exchange() {
+    let names = vec![Some("Fizz".into()), None, Some("Buzz".into())];
+    let service = get_test_service();
+    let got = service
+        .GetNullableInterfaceArray(Some(&names))
+        .expect("error calling GetNullableInterfaceArray");
+    assert_eq!(
+        got.as_ref().map(|arr| arr
+            .iter()
+            .map(|opt_s| opt_s.as_ref().map(|s| s.GetName().expect("error calling GetName")))
+            .collect::<Vec<_>>()),
+        Some(names.clone())
+    );
+    assert_eq!(
+        service.VerifyNamesWithNullableInterfaceArray(got.as_ref().map(|v| &v[..]), Some(&names)),
+        Ok(true)
+    );
+}
+
+#[test]
+fn test_interface_list_exchange() {
+    let names = vec![Some("Fizz".into()), None, Some("Buzz".into())];
+    let service = get_test_service();
+    let got = service.GetInterfaceList(Some(&names)).expect("error calling GetInterfaceList");
+    assert_eq!(
+        got.as_ref().map(|arr| arr
+            .iter()
+            .map(|opt_s| opt_s.as_ref().map(|s| s.GetName().expect("error calling GetName")))
+            .collect::<Vec<_>>()),
+        Some(names.clone())
+    );
+    assert_eq!(
+        service.VerifyNamesWithInterfaceList(got.as_ref().map(|v| &v[..]), Some(&names)),
+        Ok(true)
+    );
+}
+
 fn build_pipe() -> (File, File) {
     // Safety: we get two file descriptors from pipe()
     // and pass them after checking if the function returned
@@ -275,15 +346,10 @@
         .expect("error calling RepeatParcelFileDescriptor");
 
     const TEST_DATA: &[u8] = b"FrazzleSnazzleFlimFlamFlibbityGumboChops";
-    result_pfd
-        .as_ref()
-        .write_all(TEST_DATA)
-        .expect("error writing to pipe");
+    result_pfd.as_ref().write_all(TEST_DATA).expect("error writing to pipe");
 
     let mut buf = [0u8; TEST_DATA.len()];
-    read_file
-        .read_exact(&mut buf)
-        .expect("error reading from pipe");
+    read_file.read_exact(&mut buf).expect("error reading from pipe");
     assert_eq!(&buf[..], TEST_DATA);
 }
 
@@ -311,27 +377,18 @@
         .ReverseParcelFileDescriptorArray(&input[..], &mut repeated)
         .expect("error calling ReverseParcelFileDescriptorArray");
 
-    input[1]
-        .as_ref()
-        .write_all(b"First")
-        .expect("error writing to pipe");
+    input[1].as_ref().write_all(b"First").expect("error writing to pipe");
     repeated[1]
         .as_mut()
         .expect("received None for ParcelFileDescriptor")
         .as_ref()
         .write_all(b"Second")
         .expect("error writing to pipe");
-    result[0]
-        .as_ref()
-        .write_all(b"Third")
-        .expect("error writing to pipe");
+    result[0].as_ref().write_all(b"Third").expect("error writing to pipe");
 
     const TEST_DATA: &[u8] = b"FirstSecondThird";
     let mut buf = [0u8; TEST_DATA.len()];
-    input[0]
-        .as_ref()
-        .read_exact(&mut buf)
-        .expect("error reading from pipe");
+    input[0].as_ref().read_exact(&mut buf).expect("error reading from pipe");
     assert_eq!(&buf[..], TEST_DATA);
 }
 
@@ -339,21 +396,12 @@
 fn test_service_specific_exception() {
     let service = get_test_service();
 
-    let backend = service.getBackendType().expect("error getting backend type");
-    if backend == BackendType::JAVA {
-        // TODO(b/178861468): not correctly thrown from Java
-        return;
-    }
-
     for i in -1..2 {
         let result = service.ThrowServiceException(i);
         assert!(result.is_err());
 
         let status = result.unwrap_err();
-        assert_eq!(
-            status.exception_code(),
-            binder::ExceptionCode::SERVICE_SPECIFIC
-        );
+        assert_eq!(status.exception_code(), binder::ExceptionCode::SERVICE_SPECIFIC);
         assert_eq!(status.service_specific_error(), i);
     }
 }
@@ -405,10 +453,7 @@
 
 #[test]
 fn test_nullable_parcelable() {
-    let value = StructuredParcelable::StructuredParcelable{
-        f: 42,
-        ..Default::default()
-    };
+    let value = Empty {};
 
     let service = get_test_service();
     let value = Some(value);
@@ -419,13 +464,28 @@
     assert_eq!(result, Ok(None));
 }
 
+test_nullable! {
+    test_nullable_parcelable_array,
+    RepeatNullableParcelableArray,
+    vec![
+        Some(Empty {}),
+        None,
+    ]
+}
+
+test_nullable! {
+    test_nullable_parcelable_list,
+    RepeatNullableParcelableList,
+    vec![
+        Some(Empty {}),
+        None,
+    ]
+}
+
 #[test]
 fn test_binder() {
     let service = get_test_service();
-    assert!(service
-        .GetCallback(true)
-        .expect("error calling GetCallback")
-        .is_none());
+    assert!(service.GetCallback(true).expect("error calling GetCallback").is_none());
     let callback = service
         .GetCallback(false)
         .expect("error calling GetCallback")
@@ -519,11 +579,11 @@
     assert_eq!(parcelable.byteDefaultsToFour, 4);
     assert_eq!(parcelable.intDefaultsToFive, 5);
     assert_eq!(parcelable.longDefaultsToNegativeSeven, -7);
-    assert_eq!(parcelable.booleanDefaultsToTrue, true);
+    assert!(parcelable.booleanDefaultsToTrue);
     assert_eq!(parcelable.charDefaultsToC, 'C' as u16);
     assert_eq!(parcelable.floatDefaultsToPi, 3.14f32);
     assert_eq!(parcelable.doubleWithDefault, -3.14e17f64);
-    assert_eq!(parcelable.boolDefault, false);
+    assert!(!parcelable.boolDefault);
     assert_eq!(parcelable.byteDefault, 0);
     assert_eq!(parcelable.intDefault, 0);
     assert_eq!(parcelable.longDefault, 0);
@@ -535,15 +595,15 @@
     let result = service.FillOutStructuredParcelable(&mut parcelable);
     assert_eq!(result, Ok(()));
 
-    assert_eq!(
-        parcelable.shouldContainThreeFs,
-        [DESIRED_VALUE, DESIRED_VALUE, DESIRED_VALUE]
-    );
+    assert_eq!(parcelable.shouldContainThreeFs, [DESIRED_VALUE, DESIRED_VALUE, DESIRED_VALUE]);
     assert_eq!(parcelable.shouldBeJerry, "Jerry");
     assert_eq!(parcelable.int32_min, i32::MIN);
     assert_eq!(parcelable.int32_max, i32::MAX);
     assert_eq!(parcelable.int64_max, i64::MAX);
     assert_eq!(parcelable.hexInt32_neg_1, -1);
+    for i in parcelable.int8_1 {
+        assert_eq!(i, 1);
+    }
     for i in parcelable.int32_1 {
         assert_eq!(i, 1);
     }
@@ -563,18 +623,205 @@
     assert_eq!(parcelable.const_exprs_9.0, 1);
     assert_eq!(parcelable.const_exprs_10.0, 1);
     assert_eq!(parcelable.addString1, "hello world!");
-    assert_eq!(
-        parcelable.addString2,
-        "The quick brown fox jumps over the lazy dog."
-    );
+    assert_eq!(parcelable.addString2, "The quick brown fox jumps over the lazy dog.");
 
-    assert_eq!(parcelable.shouldSetBit0AndBit2, StructuredParcelable::BIT0 | StructuredParcelable::BIT2);
+    assert_eq!(
+        parcelable.shouldSetBit0AndBit2,
+        StructuredParcelable::BIT0 | StructuredParcelable::BIT2
+    );
 
     assert_eq!(parcelable.u, Some(Union::Union::Ns(vec![1, 2, 3])));
     assert_eq!(parcelable.shouldBeConstS1, Some(Union::Union::S(Union::S1.to_string())))
 }
 
 #[test]
+fn test_repeat_extendable_parcelable() {
+    let service = get_test_service();
+
+    let ext = Arc::new(MyExt { a: 42, b: "EXT".into() });
+    let mut ep = ExtendableParcelable { a: 1, b: "a".into(), c: 42, ..Default::default() };
+    ep.ext.set_parcelable(Arc::clone(&ext)).expect("error setting parcelable");
+
+    let mut ep2 = ExtendableParcelable::default();
+    let result = service.RepeatExtendableParcelable(&ep, &mut ep2);
+    assert_eq!(result, Ok(()));
+    assert_eq!(ep2.a, ep.a);
+    assert_eq!(ep2.b, ep.b);
+
+    let ret_ext = ep2.ext.get_parcelable::<MyExt>().expect("error getting parcelable");
+    assert!(ret_ext.is_some());
+
+    let ret_ext = ret_ext.unwrap();
+    assert_eq!(ret_ext.a, ext.a);
+    assert_eq!(ret_ext.b, ext.b);
+}
+
+macro_rules! test_parcelable_holder_stability {
+    ($test:ident, $holder:path, $parcelable:path) => {
+        #[test]
+        fn $test() {
+            let mut holder = <$holder>::default();
+            let parcelable = Arc::new(<$parcelable>::default());
+            let result = holder.ext.set_parcelable(Arc::clone(&parcelable));
+            assert_eq!(result, Ok(()));
+
+            let parcelable2 = holder.ext.get_parcelable::<$parcelable>().unwrap().unwrap();
+            assert!(Arc::ptr_eq(&parcelable, &parcelable2));
+        }
+    };
+}
+
+test_parcelable_holder_stability! {
+    test_vintf_parcelable_holder_can_contain_vintf_parcelable,
+    VintfExtendableParcelable,
+    VintfParcelable
+}
+test_parcelable_holder_stability! {
+    test_stable_parcelable_holder_can_contain_vintf_parcelable,
+    NonVintfExtendableParcelable,
+    VintfParcelable
+}
+test_parcelable_holder_stability! {
+    test_stable_parcelable_holder_can_contain_non_vintf_parcelable,
+    NonVintfExtendableParcelable,
+    NonVintfParcelable
+}
+test_parcelable_holder_stability! {
+    test_stable_parcelable_holder_can_contain_unstable_parcelable,
+    NonVintfExtendableParcelable,
+    UnstableParcelable
+}
+test_parcelable_holder_stability! {
+    test_unstable_parcelable_holder_can_contain_vintf_parcelable,
+    UnstableExtendableParcelable,
+    VintfParcelable
+}
+test_parcelable_holder_stability! {
+    test_unstable_parcelable_holder_can_contain_non_vintf_parcelable,
+    UnstableExtendableParcelable,
+    NonVintfParcelable
+}
+test_parcelable_holder_stability! {
+    test_unstable_parcelable_holder_can_contain_unstable_parcelable,
+    UnstableExtendableParcelable,
+    UnstableParcelable
+}
+
+#[test]
+fn test_vintf_parcelable_holder_cannot_contain_not_vintf_parcelable() {
+    let mut holder = VintfExtendableParcelable::default();
+    let parcelable = Arc::new(NonVintfParcelable::default());
+    let result = holder.ext.set_parcelable(Arc::clone(&parcelable));
+    assert_eq!(result, Err(binder::StatusCode::BAD_VALUE));
+
+    let parcelable2 = holder.ext.get_parcelable::<NonVintfParcelable>();
+    assert!(parcelable2.unwrap().is_none());
+}
+
+#[test]
+fn test_vintf_parcelable_holder_cannot_contain_unstable_parcelable() {
+    let mut holder = VintfExtendableParcelable::default();
+    let parcelable = Arc::new(UnstableParcelable::default());
+    let result = holder.ext.set_parcelable(Arc::clone(&parcelable));
+    assert_eq!(result, Err(binder::StatusCode::BAD_VALUE));
+
+    let parcelable2 = holder.ext.get_parcelable::<UnstableParcelable>();
+    assert!(parcelable2.unwrap().is_none());
+}
+
+#[test]
+fn test_read_write_extension() {
+    let ext = Arc::new(MyExt { a: 42, b: "EXT".into() });
+    let ext2 = Arc::new(MyExt2 { a: 42, b: MyExt { a: 24, b: "INEXT".into() }, c: "EXT2".into() });
+
+    let mut ep = ExtendableParcelable { a: 1, b: "a".into(), c: 42, ..Default::default() };
+
+    ep.ext.set_parcelable(Arc::clone(&ext)).unwrap();
+    ep.ext2.set_parcelable(Arc::clone(&ext2)).unwrap();
+
+    let ext_like = ep.ext.get_parcelable::<MyExtLike>();
+    assert_eq!(ext_like.unwrap_err(), binder::StatusCode::BAD_VALUE);
+
+    let actual_ext = ep.ext.get_parcelable::<MyExt>();
+    assert!(actual_ext.unwrap().is_some());
+    let actual_ext2 = ep.ext2.get_parcelable::<MyExt2>();
+    assert!(actual_ext2.unwrap().is_some());
+
+    check_extension_content(&ep, &ext, &ext2);
+
+    let mut parcel = Parcel::new();
+    ep.write_to_parcel(&mut parcel.borrowed()).unwrap();
+
+    unsafe {
+        parcel.set_data_position(0).unwrap();
+    }
+    let mut ep1 = ExtendableParcelable::default();
+    ep1.read_from_parcel(parcel.borrowed_ref()).unwrap();
+
+    unsafe {
+        parcel.set_data_position(0).unwrap();
+    }
+    ep1.write_to_parcel(&mut parcel.borrowed()).unwrap();
+
+    unsafe {
+        parcel.set_data_position(0).unwrap();
+    }
+    let mut ep2 = ExtendableParcelable::default();
+    ep2.read_from_parcel(parcel.borrowed_ref()).unwrap();
+
+    let ext_like = ep2.ext.get_parcelable::<MyExtLike>();
+    assert!(ext_like.unwrap().is_none());
+
+    let actual_ext = ep2.ext.get_parcelable::<MyExt>();
+    assert!(actual_ext.unwrap().is_some());
+
+    let new_ext2 =
+        Arc::new(MyExt2 { a: 79, b: MyExt { a: 42, b: "INNEWEXT".into() }, c: "NEWEXT2".into() });
+    ep2.ext2.set_parcelable(Arc::clone(&new_ext2)).unwrap();
+
+    check_extension_content(&ep1, &ext, &ext2);
+    check_extension_content(&ep2, &ext, &new_ext2);
+}
+
+fn check_extension_content(ep: &ExtendableParcelable, ext: &MyExt, ext2: &MyExt2) {
+    assert_eq!(ep.a, 1);
+    assert_eq!(ep.b, "a");
+    assert_eq!(ep.c, 42);
+
+    let actual_ext = ep.ext.get_parcelable::<MyExt>().unwrap().unwrap();
+    assert_eq!(ext.a, actual_ext.a);
+    assert_eq!(ext.b, actual_ext.b);
+
+    let actual_ext2 = ep.ext2.get_parcelable::<MyExt2>().unwrap().unwrap();
+    assert_eq!(ext2.a, actual_ext2.a);
+    assert_eq!(ext2.b.a, actual_ext2.b.a);
+    assert_eq!(ext2.b.b, actual_ext2.b.b);
+    assert_eq!(ext2.c, actual_ext2.c);
+}
+
+#[test]
+fn test_reverse_recursive_list() {
+    let service = get_test_service();
+
+    let mut head = None;
+    for n in 0..10 {
+        let node = RecursiveList { value: n, next: head };
+        head = Some(Box::new(node));
+    }
+    // head = [9, 8, .., 0]
+    let result = service.ReverseList(head.as_ref().unwrap());
+    assert!(result.is_ok());
+
+    // reversed should be [0, 1, ... 9]
+    let mut reversed: Option<&RecursiveList> = result.as_ref().ok();
+    for n in 0..10 {
+        assert_eq!(reversed.map(|inner| inner.value), Some(n));
+        reversed = reversed.unwrap().next.as_ref().map(|n| n.as_ref());
+    }
+    assert!(reversed.is_none())
+}
+
+#[test]
 fn test_unions() {
     assert_eq!(Union::Union::default(), Union::Union::Ns(vec![]));
     assert_eq!(EnumUnion::default(), EnumUnion::IntEnum(IntEnum::FOO));
@@ -621,10 +868,7 @@
             .expect("did not get binder service");
 
     let hash = service.getInterfaceHash();
-    assert_eq!(
-        hash.as_ref().map(String::as_str),
-        Ok("9e7be1859820c59d9d55dd133e71a3687b5d2e5b")
-    );
+    assert_eq!(hash.as_ref().map(String::as_str), Ok("9e7be1859820c59d9d55dd133e71a3687b5d2e5b"));
 }
 
 #[test]
@@ -674,10 +918,12 @@
             .expect("did not get binder service");
 
     let in_foo = Default::default();
-    let mut inout_foo = Default::default();
-    let mut out_foo = Default::default();
+    let mut inout_foo = Foo { intDefault42: 0 };
+    let mut out_foo = Foo { intDefault42: 0 };
     let ret = service.ignoreParcelablesAndRepeatInt(&in_foo, &mut inout_foo, &mut out_foo, 43);
     assert_eq!(ret, Ok(43));
+    assert_eq!(inout_foo.intDefault42, 0);
+    assert_eq!(out_foo.intDefault42, 0);
 }
 
 fn test_renamed_interface<F>(f: F)
@@ -723,9 +969,7 @@
 #[test]
 fn test_renamed_interface_old_as_new() {
     test_renamed_interface(|old_name, _| {
-        let new_name = old_name
-            .as_binder()
-            .into_interface::<dyn INewName::INewName>();
+        let new_name = old_name.as_binder().into_interface::<dyn INewName::INewName>();
         assert!(new_name.is_ok());
 
         let real_name = new_name.unwrap().RealName();
@@ -736,12 +980,232 @@
 #[test]
 fn test_renamed_interface_new_as_old() {
     test_renamed_interface(|_, new_name| {
-        let old_name = new_name
-            .as_binder()
-            .into_interface::<dyn IOldName::IOldName>();
+        let old_name = new_name.as_binder().into_interface::<dyn IOldName::IOldName>();
         assert!(old_name.is_ok());
 
         let real_name = old_name.unwrap().RealName();
         assert_eq!(real_name.as_ref().map(String::as_str), Ok("NewName"));
     });
 }
+
+#[derive(Debug, Default)]
+struct Callback {
+    received: Arc<Mutex<Option<ParcelableWithNested::Status::Status>>>,
+}
+
+impl Interface for Callback {}
+
+impl INestedService::ICallback::ICallback for Callback {
+    fn done(&self, st: ParcelableWithNested::Status::Status) -> binder::Result<()> {
+        *self.received.lock().unwrap() = Some(st);
+        Ok(())
+    }
+}
+
+#[test]
+fn test_nested_type() {
+    let service: binder::Strong<dyn INestedService::INestedService> = binder::get_interface(
+        <INestedService::BpNestedService as INestedService::INestedService>::get_descriptor(),
+    )
+    .expect("did not get binder service");
+
+    let p = ParcelableWithNested::ParcelableWithNested {
+        status: ParcelableWithNested::Status::Status::OK,
+    };
+    // OK -> NOT_OK
+    let ret = service.flipStatus(&p);
+    assert_eq!(
+        ret,
+        Ok(INestedService::Result::Result { status: ParcelableWithNested::Status::Status::NOT_OK })
+    );
+    let received = Arc::new(Mutex::new(None));
+    // NOT_OK -> OK with nested callback interface
+    let cb = INestedService::ICallback::BnCallback::new_binder(
+        Callback { received: Arc::clone(&received) },
+        BinderFeatures::default(),
+    );
+    let ret = service.flipStatusWithCallback(ParcelableWithNested::Status::Status::NOT_OK, &cb);
+    assert_eq!(ret, Ok(()));
+    let received = received.lock().unwrap();
+    assert_eq!(*received, Some(ParcelableWithNested::Status::Status::OK))
+}
+
+#[test]
+fn test_nonnull_binder() {
+    let service = get_test_service();
+    let result = service.TakesAnIBinder(&service.as_binder());
+    assert!(result.is_ok());
+}
+
+#[test]
+fn test_binder_list_without_null() {
+    let service = get_test_service();
+    let result = service.TakesAnIBinderList(&[service.as_binder()]);
+    assert!(result.is_ok());
+}
+
+#[test]
+fn test_null_binder_to_annotated_method() {
+    let service = get_test_service();
+    let result = service.TakesANullableIBinder(None);
+    assert!(result.is_ok());
+}
+
+#[test]
+fn test_binder_list_with_null_to_annotated_method() {
+    let service = get_test_service();
+    let result = service.TakesANullableIBinderList(Some(&[Some(service.as_binder()), None]));
+    assert!(result.is_ok());
+}
+
+#[test]
+fn test_binder_array() {
+    let service = get_test_service();
+    let callback = service
+        .GetCallback(false)
+        .expect("error calling GetCallback")
+        .expect("expected Some from GetCallback");
+
+    let mut array = vec![service.as_binder(), callback.as_binder()];
+
+    // Java needs initial values here (can't resize arrays)
+    let mut repeated = vec![Default::default(); array.len()];
+
+    let result = service.ReverseIBinderArray(&array, &mut repeated);
+    assert_eq!(repeated.into_iter().collect::<Option<Vec<_>>>().as_ref(), Some(&array));
+    array.reverse();
+    assert_eq!(result, Ok(array));
+}
+
+#[test]
+fn test_nullable_binder_array() {
+    let service = get_test_service();
+    let mut array = vec![Some(service.as_binder()), None];
+
+    // Java needs initial values here (can't resize arrays)
+    let mut repeated = Some(vec![Default::default(); array.len()]);
+
+    let result = service.ReverseNullableIBinderArray(Some(&array[..]), &mut repeated);
+    assert_eq!(repeated.as_ref(), Some(&array));
+    array.reverse();
+    assert_eq!(result, Ok(Some(array)));
+}
+
+#[test]
+fn test_read_write_fixed_size_array() {
+    let mut parcel = Parcel::new();
+    let mut p: FixedSizeArrayExample = Default::default();
+    p.byteMatrix[0][0] = 0;
+    p.byteMatrix[0][1] = 1;
+    p.byteMatrix[1][0] = 2;
+    p.byteMatrix[1][1] = 3;
+
+    p.floatMatrix[0][0] = 0.0;
+    p.floatMatrix[0][1] = 1.0;
+    p.floatMatrix[1][0] = 2.0;
+    p.floatMatrix[1][1] = 3.0;
+
+    p.boolNullableArray = Some([true, false]);
+    p.byteNullableArray = Some([42, 0]);
+    p.stringNullableArray = Some([Some("hello".into()), Some("world".into())]);
+
+    p.boolNullableMatrix = Some([[true, false], Default::default()]);
+    p.byteNullableMatrix = Some([[42, 0], Default::default()]);
+    p.stringNullableMatrix =
+        Some([[Some("hello".into()), Some("world".into())], Default::default()]);
+
+    assert_eq!(parcel.write(&p), Ok(()));
+    unsafe {
+        parcel.set_data_position(0).unwrap();
+    }
+    assert_eq!(p, parcel.read::<FixedSizeArrayExample>().unwrap());
+}
+
+#[test]
+fn test_fixed_size_array_uses_array_optimization() {
+    let mut parcel = Parcel::new();
+    let byte_array = [[1u8, 2u8, 3u8], [4u8, 5u8, 6u8]];
+    assert_eq!(parcel.write(&byte_array), Ok(()));
+    unsafe {
+        parcel.set_data_position(0).unwrap();
+    }
+    assert_eq!(parcel.read::<i32>(), Ok(2i32));
+    assert_eq!(parcel.read::<Vec<u8>>(), Ok(vec![1u8, 2u8, 3u8]));
+    assert_eq!(parcel.read::<Vec<u8>>(), Ok(vec![4u8, 5u8, 6u8]));
+}
+
+macro_rules! test_repeat_fixed_size_array {
+    ($service:ident, $func:ident, $value:expr) => {
+        let array = $value;
+        let mut repeated = Default::default();
+        let result = $service.$func(&array, &mut repeated).unwrap();
+        assert_eq!(repeated, array);
+        assert_eq!(result, array);
+    };
+}
+
+macro_rules! test_repeat_fixed_size_array_1d_binder {
+    ($service:ident, $func:ident, $value:expr) => {
+        let array = $value;
+        let mut repeated = Default::default();
+        let result = $service.$func(&array, &mut repeated).unwrap();
+        assert_eq!(result, array.clone());
+        assert_eq!(repeated, array.map(Some));
+    };
+}
+
+macro_rules! test_repeat_fixed_size_array_2d_binder {
+    ($service:ident, $func:ident, $value:expr) => {
+        let array = $value;
+        let mut repeated = Default::default();
+        let result = $service.$func(&array, &mut repeated).unwrap();
+        assert_eq!(result, array.clone());
+        assert_eq!(repeated, array.map(|row| row.map(Some)));
+    };
+}
+
+#[test]
+fn test_fixed_size_array_over_binder() {
+    let test_service = get_test_service();
+    let service: binder::Strong<dyn IRepeatFixedSizeArray> =
+        binder::get_interface(<BpRepeatFixedSizeArray as IRepeatFixedSizeArray>::get_descriptor())
+            .expect("did not get binder service");
+
+    test_repeat_fixed_size_array!(service, RepeatBytes, [1u8, 2u8, 3u8]);
+    test_repeat_fixed_size_array!(service, RepeatInts, [1i32, 2i32, 3i32]);
+
+    let binder1 = test_service.as_binder();
+    let binder2 = test_service
+        .GetCallback(false)
+        .expect("error calling GetCallback")
+        .expect("expected Some from GetCallback")
+        .as_binder();
+    let binder3 = service.as_binder();
+    test_repeat_fixed_size_array_1d_binder!(
+        service,
+        RepeatBinders,
+        [binder1.clone(), binder2.clone(), binder3.clone()]
+    );
+
+    let p1 = IntParcelable { value: 1 };
+    let p2 = IntParcelable { value: 2 };
+    let p3 = IntParcelable { value: 3 };
+    test_repeat_fixed_size_array!(service, RepeatParcelables, [p1, p2, p3]);
+
+    test_repeat_fixed_size_array!(service, Repeat2dBytes, [[1u8, 2u8, 3u8], [1u8, 2u8, 3u8]]);
+    test_repeat_fixed_size_array!(service, Repeat2dInts, [[1i32, 2i32, 3i32], [1i32, 2i32, 3i32]]);
+
+    test_repeat_fixed_size_array_2d_binder!(
+        service,
+        Repeat2dBinders,
+        [[binder1.clone(), binder2.clone(), binder3.clone()], [binder1, binder2, binder3]]
+    );
+
+    test_repeat_fixed_size_array!(service, Repeat2dParcelables, [[p1, p2, p3], [p1, p2, p3]]);
+}
+
+#[test]
+fn test_ping() {
+    let test_service = get_test_service();
+    assert_eq!(test_service.as_binder().ping_binder(), Ok(()));
+}
diff --git a/tests/rust/test_service.rs b/tests/rust/test_service.rs
index 9019775..1d3c092 100644
--- a/tests/rust/test_service.rs
+++ b/tests/rust/test_service.rs
@@ -16,13 +16,20 @@
 
 //! Test Rust service for the AIDL compiler.
 
+use aidl_test_fixedsizearray::aidl::android::aidl::fixedsizearray::FixedSizeArrayExample::{
+    IRepeatFixedSizeArray, IntParcelable::IntParcelable,
+};
+use aidl_test_interface::aidl::android::aidl::tests::nested::{
+    INestedService, ParcelableWithNested,
+};
 use aidl_test_interface::aidl::android::aidl::tests::ITestService::{
-    self, BnTestService, BpTestService,
+    self, BnTestService, BpTestService, Empty::Empty,
 };
 use aidl_test_interface::aidl::android::aidl::tests::{
+    extension::ExtendableParcelable::ExtendableParcelable, extension::MyExt::MyExt,
     BackendType::BackendType, ByteEnum::ByteEnum, ConstantExpressionEnum::ConstantExpressionEnum,
-    INamedCallback, INewName, IOldName, IntEnum::IntEnum, LongEnum::LongEnum, StructuredParcelable,
-    Union,
+    INamedCallback, INewName, IOldName, IntEnum::IntEnum, LongEnum::LongEnum,
+    RecursiveList::RecursiveList, StructuredParcelable, Union,
 };
 use aidl_test_interface::binder::{
     self, BinderFeatures, Interface, ParcelFileDescriptor, SpIBinder,
@@ -174,6 +181,87 @@
         service.GetName().map(|found_name| found_name == name)
     }
 
+    fn GetInterfaceArray(
+        &self,
+        names: &[String],
+    ) -> binder::Result<Vec<binder::Strong<dyn INamedCallback::INamedCallback>>> {
+        names.iter().map(|name| self.GetOtherTestService(name)).collect()
+    }
+
+    fn VerifyNamesWithInterfaceArray(
+        &self,
+        services: &[binder::Strong<dyn INamedCallback::INamedCallback>],
+        names: &[String],
+    ) -> binder::Result<bool> {
+        if services.len() == names.len() {
+            for (s, n) in services.iter().zip(names) {
+                if !self.VerifyName(s, n)? {
+                    return Ok(false);
+                }
+            }
+            Ok(true)
+        } else {
+            Ok(false)
+        }
+    }
+
+    fn GetNullableInterfaceArray(
+        &self,
+        names: Option<&[Option<String>]>,
+    ) -> binder::Result<Option<Vec<Option<binder::Strong<dyn INamedCallback::INamedCallback>>>>>
+    {
+        if let Some(names) = names {
+            let mut services = vec![];
+            for name in names {
+                if let Some(name) = name {
+                    services.push(Some(self.GetOtherTestService(name)?));
+                } else {
+                    services.push(None);
+                }
+            }
+            Ok(Some(services))
+        } else {
+            Ok(None)
+        }
+    }
+
+    fn VerifyNamesWithNullableInterfaceArray(
+        &self,
+        services: Option<&[Option<binder::Strong<dyn INamedCallback::INamedCallback>>]>,
+        names: Option<&[Option<String>]>,
+    ) -> binder::Result<bool> {
+        if let (Some(services), Some(names)) = (services, names) {
+            for (s, n) in services.iter().zip(names) {
+                if let (Some(s), Some(n)) = (s, n) {
+                    if !self.VerifyName(s, n)? {
+                        return Ok(false);
+                    }
+                } else if s.is_some() || n.is_some() {
+                    return Ok(false);
+                }
+            }
+            Ok(true)
+        } else {
+            Ok(services.is_none() && names.is_none())
+        }
+    }
+
+    fn GetInterfaceList(
+        &self,
+        names: Option<&[Option<String>]>,
+    ) -> binder::Result<Option<Vec<Option<binder::Strong<dyn INamedCallback::INamedCallback>>>>>
+    {
+        self.GetNullableInterfaceArray(names)
+    }
+
+    fn VerifyNamesWithInterfaceList(
+        &self,
+        services: Option<&[Option<binder::Strong<dyn INamedCallback::INamedCallback>>]>,
+        names: Option<&[Option<String>]>,
+    ) -> binder::Result<bool> {
+        self.VerifyNamesWithNullableInterfaceArray(services, names)
+    }
+
     fn RepeatParcelFileDescriptor(
         &self,
         read: &ParcelFileDescriptor,
@@ -209,13 +297,13 @@
         Ok(input.map(String::from))
     }
 
-    fn RepeatNullableParcelable(
-        &self,
-        input: Option<&StructuredParcelable::StructuredParcelable>,
-    ) -> binder::Result<Option<StructuredParcelable::StructuredParcelable>> {
+    fn RepeatNullableParcelable(&self, input: Option<&Empty>) -> binder::Result<Option<Empty>> {
         Ok(input.cloned())
     }
 
+    impl_repeat_nullable! {RepeatNullableParcelableArray, Option<Empty>}
+    impl_repeat_nullable! {RepeatNullableParcelableList, Option<Empty>}
+
     fn TakesAnIBinder(&self, _: &SpIBinder) -> binder::Result<()> {
         Ok(())
     }
@@ -224,6 +312,14 @@
         Ok(())
     }
 
+    fn TakesAnIBinderList(&self, _: &[SpIBinder]) -> binder::Result<()> {
+        Ok(())
+    }
+
+    fn TakesANullableIBinderList(&self, _: Option<&[Option<SpIBinder>]>) -> binder::Result<()> {
+        Ok(())
+    }
+
     fn ReverseNullableUtf8CppString(
         &self,
         input: Option<&[Option<String>]>,
@@ -289,18 +385,60 @@
         Ok(())
     }
 
+    fn RepeatExtendableParcelable(
+        &self,
+        ep: &ExtendableParcelable,
+        ep2: &mut ExtendableParcelable,
+    ) -> binder::Result<()> {
+        ep2.a = ep.a;
+        ep2.b = ep.b.clone();
+
+        let my_ext = ep.ext.get_parcelable::<MyExt>()?;
+        if let Some(my_ext) = my_ext {
+            ep2.ext.set_parcelable(my_ext)?;
+        } else {
+            ep2.ext.reset();
+        }
+
+        Ok(())
+    }
+
+    fn ReverseList(&self, list: &RecursiveList) -> binder::Result<RecursiveList> {
+        let mut reversed: Option<RecursiveList> = None;
+        let mut cur: Option<&RecursiveList> = Some(list);
+        while let Some(node) = cur {
+            reversed = Some(RecursiveList { value: node.value, next: reversed.map(Box::new) });
+            cur = node.next.as_ref().map(|n| n.as_ref());
+        }
+        // `list` is always not empty, so is `reversed`.
+        Ok(reversed.unwrap())
+    }
+
+    fn ReverseIBinderArray(
+        &self,
+        input: &[SpIBinder],
+        repeated: &mut Vec<Option<SpIBinder>>,
+    ) -> binder::Result<Vec<SpIBinder>> {
+        *repeated = input.iter().cloned().map(Some).collect();
+        Ok(input.iter().rev().cloned().collect())
+    }
+
+    fn ReverseNullableIBinderArray(
+        &self,
+        input: Option<&[Option<SpIBinder>]>,
+        repeated: &mut Option<Vec<Option<SpIBinder>>>,
+    ) -> binder::Result<Option<Vec<Option<SpIBinder>>>> {
+        let input = input.expect("input is null");
+        *repeated = Some(input.to_vec());
+        Ok(Some(input.iter().rev().cloned().collect()))
+    }
+
     fn GetOldNameInterface(&self) -> binder::Result<binder::Strong<dyn IOldName::IOldName>> {
-        Ok(IOldName::BnOldName::new_binder(
-            OldName,
-            BinderFeatures::default(),
-        ))
+        Ok(IOldName::BnOldName::new_binder(OldName, BinderFeatures::default()))
     }
 
     fn GetNewNameInterface(&self) -> binder::Result<binder::Strong<dyn INewName::INewName>> {
-        Ok(INewName::BnNewName::new_binder(
-            NewName,
-            BinderFeatures::default(),
-        ))
+        Ok(INewName::BnNewName::new_binder(NewName, BinderFeatures::default()))
     }
 
     fn GetCppJavaTests(&self) -> binder::Result<Option<SpIBinder>> {
@@ -328,11 +466,110 @@
     fn returnsLengthOfFooArray(&self, foos: &[Foo]) -> binder::Result<i32> {
         Ok(foos.len() as i32)
     }
-    fn ignoreParcelablesAndRepeatInt(&self, _in_foo: &Foo, _inout_foo: &mut Foo, _out_foo: &mut Foo, value: i32) -> binder::Result<i32> {
+    fn ignoreParcelablesAndRepeatInt(
+        &self,
+        _in_foo: &Foo,
+        _inout_foo: &mut Foo,
+        _out_foo: &mut Foo,
+        value: i32,
+    ) -> binder::Result<i32> {
         Ok(value)
     }
 }
 
+struct NestedService;
+
+impl Interface for NestedService {}
+
+impl INestedService::INestedService for NestedService {
+    fn flipStatus(
+        &self,
+        p: &ParcelableWithNested::ParcelableWithNested,
+    ) -> binder::Result<INestedService::Result::Result> {
+        if p.status == ParcelableWithNested::Status::Status::OK {
+            Ok(INestedService::Result::Result {
+                status: ParcelableWithNested::Status::Status::NOT_OK,
+            })
+        } else {
+            Ok(INestedService::Result::Result { status: ParcelableWithNested::Status::Status::OK })
+        }
+    }
+    fn flipStatusWithCallback(
+        &self,
+        st: ParcelableWithNested::Status::Status,
+        cb: &binder::Strong<dyn INestedService::ICallback::ICallback>,
+    ) -> binder::Result<()> {
+        if st == ParcelableWithNested::Status::Status::OK {
+            cb.done(ParcelableWithNested::Status::Status::NOT_OK)
+        } else {
+            cb.done(ParcelableWithNested::Status::Status::OK)
+        }
+    }
+}
+
+struct FixedSizeArrayService;
+
+impl Interface for FixedSizeArrayService {}
+
+impl IRepeatFixedSizeArray::IRepeatFixedSizeArray for FixedSizeArrayService {
+    fn RepeatBytes(&self, input: &[u8; 3], repeated: &mut [u8; 3]) -> binder::Result<[u8; 3]> {
+        *repeated = *input;
+        Ok(*input)
+    }
+    fn RepeatInts(&self, input: &[i32; 3], repeated: &mut [i32; 3]) -> binder::Result<[i32; 3]> {
+        *repeated = *input;
+        Ok(*input)
+    }
+    fn RepeatBinders(
+        &self,
+        input: &[SpIBinder; 3],
+        repeated: &mut [Option<SpIBinder>; 3],
+    ) -> binder::Result<[SpIBinder; 3]> {
+        *repeated = input.clone().map(Some);
+        Ok(input.clone())
+    }
+    fn RepeatParcelables(
+        &self,
+        input: &[IntParcelable; 3],
+        repeated: &mut [IntParcelable; 3],
+    ) -> binder::Result<[IntParcelable; 3]> {
+        *repeated = *input;
+        Ok(*input)
+    }
+    fn Repeat2dBytes(
+        &self,
+        input: &[[u8; 3]; 2],
+        repeated: &mut [[u8; 3]; 2],
+    ) -> binder::Result<[[u8; 3]; 2]> {
+        *repeated = *input;
+        Ok(*input)
+    }
+    fn Repeat2dInts(
+        &self,
+        input: &[[i32; 3]; 2],
+        repeated: &mut [[i32; 3]; 2],
+    ) -> binder::Result<[[i32; 3]; 2]> {
+        *repeated = *input;
+        Ok(*input)
+    }
+    fn Repeat2dBinders(
+        &self,
+        input: &[[SpIBinder; 3]; 2],
+        repeated: &mut [[Option<SpIBinder>; 3]; 2],
+    ) -> binder::Result<[[SpIBinder; 3]; 2]> {
+        *repeated = input.clone().map(|nested| nested.map(Some));
+        Ok(input.clone())
+    }
+    fn Repeat2dParcelables(
+        &self,
+        input: &[[IntParcelable; 3]; 2],
+        repeated: &mut [[IntParcelable; 3]; 2],
+    ) -> binder::Result<[[IntParcelable; 3]; 2]> {
+        *repeated = *input;
+        Ok(*input)
+    }
+}
+
 fn main() {
     binder::ProcessState::set_thread_pool_max_thread_count(0);
     binder::ProcessState::start_thread_pool();
@@ -346,5 +583,21 @@
     binder::add_service(versioned_service_name, versioned_service.as_binder())
         .expect("Could not register service");
 
+    let nested_service_name =
+        <INestedService::BpNestedService as INestedService::INestedService>::get_descriptor();
+    let nested_service =
+        INestedService::BnNestedService::new_binder(NestedService, BinderFeatures::default());
+    binder::add_service(nested_service_name, nested_service.as_binder())
+        .expect("Could not register service");
+
+    let fixed_size_array_service_name =
+        <IRepeatFixedSizeArray::BpRepeatFixedSizeArray as IRepeatFixedSizeArray::IRepeatFixedSizeArray>::get_descriptor();
+    let fixed_size_array_service = IRepeatFixedSizeArray::BnRepeatFixedSizeArray::new_binder(
+        FixedSizeArrayService,
+        BinderFeatures::default(),
+    );
+    binder::add_service(fixed_size_array_service_name, fixed_size_array_service.as_binder())
+        .expect("Could not register service");
+
     binder::ProcessState::join_thread_pool();
 }
diff --git a/tests/rust/test_service_async.rs b/tests/rust/test_service_async.rs
new file mode 100644
index 0000000..f6cd039
--- /dev/null
+++ b/tests/rust/test_service_async.rs
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 2022, 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.
+ */
+
+//! Test Rust service for the AIDL compiler.
+
+use aidl_test_interface::aidl::android::aidl::tests::nested::{
+    INestedService, ParcelableWithNested,
+};
+use aidl_test_interface::aidl::android::aidl::tests::ITestService::{
+    self, BnTestService, BpTestService, Empty::Empty,
+};
+use aidl_test_interface::aidl::android::aidl::tests::{
+    extension::ExtendableParcelable::ExtendableParcelable, extension::MyExt::MyExt,
+    BackendType::BackendType, ByteEnum::ByteEnum, ConstantExpressionEnum::ConstantExpressionEnum,
+    INamedCallback, INewName, IOldName, IntEnum::IntEnum, LongEnum::LongEnum,
+    RecursiveList::RecursiveList, StructuredParcelable, Union,
+};
+use aidl_test_interface::binder::{
+    self, BinderFeatures, Interface, ParcelFileDescriptor, SpIBinder,
+};
+use aidl_test_versioned_interface::aidl::android::aidl::versioned::tests::{
+    BazUnion::BazUnion, Foo::Foo, IFooInterface, IFooInterface::BnFooInterface,
+    IFooInterface::BpFooInterface,
+};
+use std::collections::HashMap;
+use std::sync::Mutex;
+
+use async_trait::async_trait;
+
+fn dup_fd(fd: &ParcelFileDescriptor) -> ParcelFileDescriptor {
+    ParcelFileDescriptor::new(fd.as_ref().try_clone().unwrap())
+}
+
+struct NamedCallback(String);
+
+impl Interface for NamedCallback {}
+
+#[async_trait]
+impl INamedCallback::INamedCallbackAsyncServer for NamedCallback {
+    async fn GetName(&self) -> binder::Result<String> {
+        Ok(self.0.clone())
+    }
+}
+
+struct OldName;
+
+impl Interface for OldName {}
+
+#[async_trait]
+impl IOldName::IOldNameAsyncServer for OldName {
+    async fn RealName(&self) -> binder::Result<String> {
+        Ok("OldName".into())
+    }
+}
+
+#[derive(Debug, Default)]
+struct NewName;
+
+impl Interface for NewName {}
+
+#[async_trait]
+impl INewName::INewNameAsyncServer for NewName {
+    async fn RealName(&self) -> binder::Result<String> {
+        Ok("NewName".into())
+    }
+}
+
+#[derive(Default)]
+struct TestService {
+    service_map: Mutex<HashMap<String, binder::Strong<dyn INamedCallback::INamedCallback>>>,
+}
+
+impl Interface for TestService {}
+
+// Macros are expanded in the wrong order, so async_trait does not apply to
+// functions defined by declarative macros.
+
+type BoxFuture<'a, T> = std::pin::Pin<Box<dyn std::future::Future<Output = T> + Send + 'a>>;
+
+macro_rules! impl_repeat {
+    ($repeat_name:ident, $type:ty) => {
+        fn $repeat_name<'a, 'b>(&'a self, token: $type) -> BoxFuture<'b, binder::Result<$type>>
+        where
+            'a: 'b,
+            Self: 'b,
+        {
+            Box::pin(async move { Ok(token) })
+        }
+    };
+}
+
+macro_rules! impl_reverse {
+    ($reverse_name:ident, $type:ty) => {
+        fn $reverse_name<'a, 'b, 'c, 'd>(
+            &'a self,
+            input: &'b [$type],
+            repeated: &'c mut Vec<$type>,
+        ) -> BoxFuture<'d, binder::Result<Vec<$type>>>
+        where
+            'a: 'd,
+            'b: 'd,
+            'c: 'd,
+            Self: 'd,
+        {
+            Box::pin(async move {
+                repeated.clear();
+                repeated.extend_from_slice(input);
+                Ok(input.iter().rev().cloned().collect())
+            })
+        }
+    };
+}
+
+macro_rules! impl_repeat_reverse {
+    ($repeat_name:ident, $reverse_name:ident, $type:ty) => {
+        impl_repeat! {$repeat_name, $type}
+        impl_reverse! {$reverse_name, $type}
+    };
+}
+
+macro_rules! impl_repeat_nullable {
+    ($repeat_nullable_name:ident, $type:ty) => {
+        fn $repeat_nullable_name<'a, 'b, 'c>(
+            &'a self,
+            input: Option<&'b [$type]>,
+        ) -> BoxFuture<'c, binder::Result<Option<Vec<$type>>>>
+        where
+            'a: 'c,
+            'b: 'c,
+            Self: 'c,
+        {
+            Box::pin(async move { Ok(input.map(<[$type]>::to_vec)) })
+        }
+    };
+}
+
+#[async_trait]
+impl ITestService::ITestServiceAsyncServer for TestService {
+    impl_repeat! {RepeatByte, i8}
+    impl_reverse! {ReverseByte, u8}
+
+    async fn UnimplementedMethod(&self, _: i32) -> binder::Result<i32> {
+        // Pretend this method hasn't been implemented
+        Err(binder::StatusCode::UNKNOWN_TRANSACTION.into())
+    }
+
+    async fn TestOneway(&self) -> binder::Result<()> {
+        Err(binder::StatusCode::UNKNOWN_ERROR.into())
+    }
+
+    async fn Deprecated(&self) -> binder::Result<()> {
+        Ok(())
+    }
+
+    impl_repeat_reverse! {RepeatBoolean, ReverseBoolean, bool}
+    impl_repeat_reverse! {RepeatChar, ReverseChar, u16}
+    impl_repeat_reverse! {RepeatInt, ReverseInt, i32}
+    impl_repeat_reverse! {RepeatLong, ReverseLong, i64}
+    impl_repeat_reverse! {RepeatFloat, ReverseFloat, f32}
+    impl_repeat_reverse! {RepeatDouble, ReverseDouble, f64}
+    impl_repeat_reverse! {RepeatByteEnum, ReverseByteEnum, ByteEnum}
+    impl_repeat_reverse! {RepeatIntEnum, ReverseIntEnum, IntEnum}
+    impl_repeat_reverse! {RepeatLongEnum, ReverseLongEnum, LongEnum}
+    impl_reverse! {ReverseString, String}
+    impl_reverse! {ReverseStringList, String}
+    impl_reverse! {ReverseUtf8CppString, String}
+
+    async fn RepeatString(&self, input: &str) -> binder::Result<String> {
+        Ok(input.into())
+    }
+
+    async fn RepeatUtf8CppString(&self, input: &str) -> binder::Result<String> {
+        Ok(input.into())
+    }
+
+    async fn GetOtherTestService(
+        &self,
+        name: &str,
+    ) -> binder::Result<binder::Strong<dyn INamedCallback::INamedCallback>> {
+        let mut service_map = self.service_map.lock().unwrap();
+        let other_service = service_map.entry(name.into()).or_insert_with(|| {
+            let named_callback = NamedCallback(name.into());
+            INamedCallback::BnNamedCallback::new_async_binder(
+                named_callback,
+                rt(),
+                BinderFeatures::default(),
+            )
+        });
+        Ok(other_service.to_owned())
+    }
+
+    async fn VerifyName(
+        &self,
+        service: &binder::Strong<dyn INamedCallback::INamedCallback>,
+        name: &str,
+    ) -> binder::Result<bool> {
+        service.GetName().map(|found_name| found_name == name)
+    }
+
+    async fn GetInterfaceArray(
+        &self,
+        names: &[String],
+    ) -> binder::Result<Vec<binder::Strong<dyn INamedCallback::INamedCallback>>> {
+        let mut res = Vec::new();
+        for name in names {
+            res.push(self.GetOtherTestService(name).await?);
+        }
+        Ok(res)
+    }
+
+    async fn VerifyNamesWithInterfaceArray(
+        &self,
+        services: &[binder::Strong<dyn INamedCallback::INamedCallback>],
+        names: &[String],
+    ) -> binder::Result<bool> {
+        if services.len() == names.len() {
+            for (s, n) in services.iter().zip(names) {
+                if !self.VerifyName(s, n).await? {
+                    return Ok(false);
+                }
+            }
+            Ok(true)
+        } else {
+            Ok(false)
+        }
+    }
+
+    async fn GetNullableInterfaceArray(
+        &self,
+        names: Option<&[Option<String>]>,
+    ) -> binder::Result<Option<Vec<Option<binder::Strong<dyn INamedCallback::INamedCallback>>>>>
+    {
+        if let Some(names) = names {
+            let mut services = vec![];
+            for name in names {
+                if let Some(name) = name {
+                    services.push(Some(self.GetOtherTestService(name).await?));
+                } else {
+                    services.push(None);
+                }
+            }
+            Ok(Some(services))
+        } else {
+            Ok(None)
+        }
+    }
+
+    async fn VerifyNamesWithNullableInterfaceArray(
+        &self,
+        services: Option<&[Option<binder::Strong<dyn INamedCallback::INamedCallback>>]>,
+        names: Option<&[Option<String>]>,
+    ) -> binder::Result<bool> {
+        if let (Some(services), Some(names)) = (services, names) {
+            for (s, n) in services.iter().zip(names) {
+                if let (Some(s), Some(n)) = (s, n) {
+                    if !self.VerifyName(s, n).await? {
+                        return Ok(false);
+                    }
+                } else if s.is_some() || n.is_some() {
+                    return Ok(false);
+                }
+            }
+            Ok(true)
+        } else {
+            Ok(services.is_none() && names.is_none())
+        }
+    }
+
+    async fn GetInterfaceList(
+        &self,
+        names: Option<&[Option<String>]>,
+    ) -> binder::Result<Option<Vec<Option<binder::Strong<dyn INamedCallback::INamedCallback>>>>>
+    {
+        self.GetNullableInterfaceArray(names).await
+    }
+
+    async fn VerifyNamesWithInterfaceList(
+        &self,
+        services: Option<&[Option<binder::Strong<dyn INamedCallback::INamedCallback>>]>,
+        names: Option<&[Option<String>]>,
+    ) -> binder::Result<bool> {
+        self.VerifyNamesWithNullableInterfaceArray(services, names).await
+    }
+
+    async fn RepeatParcelFileDescriptor(
+        &self,
+        read: &ParcelFileDescriptor,
+    ) -> binder::Result<ParcelFileDescriptor> {
+        Ok(dup_fd(read))
+    }
+
+    async fn ReverseParcelFileDescriptorArray(
+        &self,
+        input: &[ParcelFileDescriptor],
+        repeated: &mut Vec<Option<ParcelFileDescriptor>>,
+    ) -> binder::Result<Vec<ParcelFileDescriptor>> {
+        repeated.clear();
+        repeated.extend(input.iter().map(dup_fd).map(Some));
+        Ok(input.iter().rev().map(dup_fd).collect())
+    }
+
+    async fn ThrowServiceException(&self, code: i32) -> binder::Result<()> {
+        Err(binder::Status::new_service_specific_error(code, None))
+    }
+
+    impl_repeat_nullable! {RepeatNullableIntArray, i32}
+    impl_repeat_nullable! {RepeatNullableByteEnumArray, ByteEnum}
+    impl_repeat_nullable! {RepeatNullableIntEnumArray, IntEnum}
+    impl_repeat_nullable! {RepeatNullableLongEnumArray, LongEnum}
+    impl_repeat_nullable! {RepeatNullableStringList, Option<String>}
+
+    async fn RepeatNullableString(&self, input: Option<&str>) -> binder::Result<Option<String>> {
+        Ok(input.map(String::from))
+    }
+
+    async fn RepeatNullableUtf8CppString(
+        &self,
+        input: Option<&str>,
+    ) -> binder::Result<Option<String>> {
+        Ok(input.map(String::from))
+    }
+
+    async fn RepeatNullableParcelable(
+        &self,
+        input: Option<&Empty>,
+    ) -> binder::Result<Option<Empty>> {
+        Ok(input.cloned())
+    }
+
+    impl_repeat_nullable! {RepeatNullableParcelableArray, Option<Empty>}
+    impl_repeat_nullable! {RepeatNullableParcelableList, Option<Empty>}
+
+    async fn TakesAnIBinder(&self, _: &SpIBinder) -> binder::Result<()> {
+        Ok(())
+    }
+
+    async fn TakesANullableIBinder(&self, _: Option<&SpIBinder>) -> binder::Result<()> {
+        Ok(())
+    }
+
+    async fn TakesAnIBinderList(&self, _: &[SpIBinder]) -> binder::Result<()> {
+        Ok(())
+    }
+
+    async fn TakesANullableIBinderList(
+        &self,
+        _: Option<&[Option<SpIBinder>]>,
+    ) -> binder::Result<()> {
+        Ok(())
+    }
+
+    async fn ReverseNullableUtf8CppString(
+        &self,
+        input: Option<&[Option<String>]>,
+        repeated: &mut Option<Vec<Option<String>>>,
+    ) -> binder::Result<Option<Vec<Option<String>>>> {
+        if let Some(input) = input {
+            *repeated = Some(input.to_vec());
+            Ok(Some(input.iter().rev().cloned().collect()))
+        } else {
+            // We don't touch `repeated` here, since
+            // the C++ test service doesn't either
+            Ok(None)
+        }
+    }
+
+    async fn ReverseUtf8CppStringList(
+        &self,
+        input: Option<&[Option<String>]>,
+        repeated: &mut Option<Vec<Option<String>>>,
+    ) -> binder::Result<Option<Vec<Option<String>>>> {
+        self.ReverseNullableUtf8CppString(input, repeated).await
+    }
+
+    async fn GetCallback(
+        &self,
+        return_null: bool,
+    ) -> binder::Result<Option<binder::Strong<dyn INamedCallback::INamedCallback>>> {
+        if return_null {
+            Ok(None)
+        } else {
+            self.GetOtherTestService("ABT: always be testing").await.map(Some)
+        }
+    }
+
+    async fn FillOutStructuredParcelable(
+        &self,
+        parcelable: &mut StructuredParcelable::StructuredParcelable,
+    ) -> binder::Result<()> {
+        parcelable.shouldBeJerry = "Jerry".into();
+        parcelable.shouldContainThreeFs = vec![parcelable.f, parcelable.f, parcelable.f];
+        parcelable.shouldBeByteBar = ByteEnum::BAR;
+        parcelable.shouldBeIntBar = IntEnum::BAR;
+        parcelable.shouldBeLongBar = LongEnum::BAR;
+        parcelable.shouldContainTwoByteFoos = vec![ByteEnum::FOO, ByteEnum::FOO];
+        parcelable.shouldContainTwoIntFoos = vec![IntEnum::FOO, IntEnum::FOO];
+        parcelable.shouldContainTwoLongFoos = vec![LongEnum::FOO, LongEnum::FOO];
+
+        parcelable.const_exprs_1 = ConstantExpressionEnum::decInt32_1;
+        parcelable.const_exprs_2 = ConstantExpressionEnum::decInt32_2;
+        parcelable.const_exprs_3 = ConstantExpressionEnum::decInt64_1;
+        parcelable.const_exprs_4 = ConstantExpressionEnum::decInt64_2;
+        parcelable.const_exprs_5 = ConstantExpressionEnum::decInt64_3;
+        parcelable.const_exprs_6 = ConstantExpressionEnum::decInt64_4;
+        parcelable.const_exprs_7 = ConstantExpressionEnum::hexInt32_1;
+        parcelable.const_exprs_8 = ConstantExpressionEnum::hexInt32_2;
+        parcelable.const_exprs_9 = ConstantExpressionEnum::hexInt32_3;
+        parcelable.const_exprs_10 = ConstantExpressionEnum::hexInt64_1;
+
+        parcelable.shouldSetBit0AndBit2 = StructuredParcelable::BIT0 | StructuredParcelable::BIT2;
+
+        parcelable.u = Some(Union::Union::Ns(vec![1, 2, 3]));
+        parcelable.shouldBeConstS1 = Some(Union::Union::S(Union::S1.to_string()));
+        Ok(())
+    }
+
+    async fn RepeatExtendableParcelable(
+        &self,
+        ep: &ExtendableParcelable,
+        ep2: &mut ExtendableParcelable,
+    ) -> binder::Result<()> {
+        ep2.a = ep.a;
+        ep2.b = ep.b.clone();
+
+        let my_ext = ep.ext.get_parcelable::<MyExt>()?;
+        if let Some(my_ext) = my_ext {
+            ep2.ext.set_parcelable(my_ext)?;
+        } else {
+            ep2.ext.reset();
+        }
+
+        Ok(())
+    }
+
+    async fn ReverseList(&self, list: &RecursiveList) -> binder::Result<RecursiveList> {
+        let mut reversed: Option<RecursiveList> = None;
+        let mut cur: Option<&RecursiveList> = Some(list);
+        while let Some(node) = cur {
+            reversed = Some(RecursiveList { value: node.value, next: reversed.map(Box::new) });
+            cur = node.next.as_ref().map(|n| n.as_ref());
+        }
+        // `list` is always not empty, so is `reversed`.
+        Ok(reversed.unwrap())
+    }
+
+    async fn ReverseIBinderArray(
+        &self,
+        input: &[SpIBinder],
+        repeated: &mut Vec<Option<SpIBinder>>,
+    ) -> binder::Result<Vec<SpIBinder>> {
+        *repeated = input.iter().cloned().map(Some).collect();
+        Ok(input.iter().rev().cloned().collect())
+    }
+
+    async fn ReverseNullableIBinderArray(
+        &self,
+        input: Option<&[Option<SpIBinder>]>,
+        repeated: &mut Option<Vec<Option<SpIBinder>>>,
+    ) -> binder::Result<Option<Vec<Option<SpIBinder>>>> {
+        let input = input.expect("input is null");
+        *repeated = Some(input.to_vec());
+        Ok(Some(input.iter().rev().cloned().collect()))
+    }
+
+    async fn GetOldNameInterface(&self) -> binder::Result<binder::Strong<dyn IOldName::IOldName>> {
+        Ok(IOldName::BnOldName::new_async_binder(OldName, rt(), BinderFeatures::default()))
+    }
+
+    async fn GetNewNameInterface(&self) -> binder::Result<binder::Strong<dyn INewName::INewName>> {
+        Ok(INewName::BnNewName::new_async_binder(NewName, rt(), BinderFeatures::default()))
+    }
+
+    async fn GetCppJavaTests(&self) -> binder::Result<Option<SpIBinder>> {
+        Ok(None)
+    }
+
+    async fn getBackendType(&self) -> binder::Result<BackendType> {
+        Ok(BackendType::RUST)
+    }
+}
+
+struct FooInterface;
+
+impl Interface for FooInterface {}
+
+#[async_trait]
+impl IFooInterface::IFooInterfaceAsyncServer for FooInterface {
+    async fn originalApi(&self) -> binder::Result<()> {
+        Ok(())
+    }
+    async fn acceptUnionAndReturnString(&self, u: &BazUnion) -> binder::Result<String> {
+        match u {
+            BazUnion::IntNum(n) => Ok(n.to_string()),
+        }
+    }
+    async fn returnsLengthOfFooArray(&self, foos: &[Foo]) -> binder::Result<i32> {
+        Ok(foos.len() as i32)
+    }
+    async fn ignoreParcelablesAndRepeatInt(
+        &self,
+        _in_foo: &Foo,
+        _inout_foo: &mut Foo,
+        _out_foo: &mut Foo,
+        value: i32,
+    ) -> binder::Result<i32> {
+        Ok(value)
+    }
+}
+
+struct NestedService;
+
+impl Interface for NestedService {}
+
+#[async_trait]
+impl INestedService::INestedServiceAsyncServer for NestedService {
+    async fn flipStatus(
+        &self,
+        p: &ParcelableWithNested::ParcelableWithNested,
+    ) -> binder::Result<INestedService::Result::Result> {
+        if p.status == ParcelableWithNested::Status::Status::OK {
+            Ok(INestedService::Result::Result {
+                status: ParcelableWithNested::Status::Status::NOT_OK,
+            })
+        } else {
+            Ok(INestedService::Result::Result { status: ParcelableWithNested::Status::Status::OK })
+        }
+    }
+    async fn flipStatusWithCallback(
+        &self,
+        st: ParcelableWithNested::Status::Status,
+        cb: &binder::Strong<dyn INestedService::ICallback::ICallback>,
+    ) -> binder::Result<()> {
+        if st == ParcelableWithNested::Status::Status::OK {
+            cb.done(ParcelableWithNested::Status::Status::NOT_OK)
+        } else {
+            cb.done(ParcelableWithNested::Status::Status::OK)
+        }
+    }
+}
+
+fn rt() -> binder_tokio::TokioRuntime<tokio::runtime::Runtime> {
+    let rt = tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap();
+    binder_tokio::TokioRuntime(rt)
+}
+
+fn main() {
+    binder::ProcessState::set_thread_pool_max_thread_count(0);
+    binder::ProcessState::start_thread_pool();
+
+    let service_name = <BpTestService as ITestService::ITestService>::get_descriptor();
+    let service =
+        BnTestService::new_async_binder(TestService::default(), rt(), BinderFeatures::default());
+    binder::add_service(service_name, service.as_binder()).expect("Could not register service");
+
+    let versioned_service_name = <BpFooInterface as IFooInterface::IFooInterface>::get_descriptor();
+    let versioned_service =
+        BnFooInterface::new_async_binder(FooInterface, rt(), BinderFeatures::default());
+    binder::add_service(versioned_service_name, versioned_service.as_binder())
+        .expect("Could not register service");
+
+    let nested_service_name =
+        <INestedService::BpNestedService as INestedService::INestedService>::get_descriptor();
+    let nested_service = INestedService::BnNestedService::new_async_binder(
+        NestedService,
+        rt(),
+        BinderFeatures::default(),
+    );
+    binder::add_service(nested_service_name, nested_service.as_binder())
+        .expect("Could not register service");
+
+    binder::ProcessState::join_thread_pool();
+}
diff --git a/tests/stability_test/Android.bp b/tests/stability_test/Android.bp
index a885bcb..993f122 100644
--- a/tests/stability_test/Android.bp
+++ b/tests/stability_test/Android.bp
@@ -40,7 +40,7 @@
             enabled: false,
         },
         rust: {
-            enabled: false,
+            enabled: true,
         },
     },
     versions: ["1"],
@@ -64,7 +64,7 @@
             enabled: false,
         },
         rust: {
-            enabled: false,
+            enabled: true,
         },
     },
 }
@@ -87,7 +87,7 @@
             enabled: false,
         },
         rust: {
-            enabled: false,
+            enabled: true,
         },
     },
     versions: ["1"],
diff --git a/tests/versioned/android/aidl/versioned/tests/Foo.aidl b/tests/versioned/android/aidl/versioned/tests/Foo.aidl
index acf7620..4b8c3e9 100644
--- a/tests/versioned/android/aidl/versioned/tests/Foo.aidl
+++ b/tests/versioned/android/aidl/versioned/tests/Foo.aidl
@@ -1,5 +1,6 @@
 package android.aidl.versioned.tests;
 
+@JavaSuppressLint({"NewApi"})
 parcelable Foo {
     // V1 is empty
     // V2
diff --git a/tests/versioned/android/aidl/versioned/tests/IFooInterface.aidl b/tests/versioned/android/aidl/versioned/tests/IFooInterface.aidl
index bb383b8..0ce9101 100644
--- a/tests/versioned/android/aidl/versioned/tests/IFooInterface.aidl
+++ b/tests/versioned/android/aidl/versioned/tests/IFooInterface.aidl
@@ -1,6 +1,8 @@
 package android.aidl.versioned.tests;
 import android.aidl.versioned.tests.BazUnion;
 import android.aidl.versioned.tests.Foo;
+
+@JavaDelegator
 interface IFooInterface {
     // V1
     void originalApi();