Snap for 8140651 from f08c15f417c49e4ffb170d6275613aec65a74c1e to sdk-release

Change-Id: Icf30ba6772fc4a6c623bc347b6c29b1e0d19b0cb
diff --git a/Android.bp b/Android.bp
index 5ca8f73..cc37829 100644
--- a/Android.bp
+++ b/Android.bp
@@ -426,6 +426,7 @@
         "libbinder_ndk",
     ],
     srcs: [
+        "tests/aidl_test_client_ndk_delegate.cpp",
         "tests/aidl_test_client_ndk_loggable_interface.cpp",
         "tests/aidl_test_client_ndk_nested.cpp",
         "tests/aidl_test_client_ndk_nullables.cpp",
@@ -446,7 +447,7 @@
             enabled: true,
         },
         java: {
-            enabled: false,
+            enabled: true,
         },
         ndk: {
             enabled: true,
@@ -473,6 +474,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",
@@ -630,6 +632,7 @@
         ":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/**/*",
diff --git a/aidl_const_expressions.cpp b/aidl_const_expressions.cpp
index 244ec4b..aefd8a0 100644
--- a/aidl_const_expressions.cpp
+++ b/aidl_const_expressions.cpp
@@ -477,10 +477,13 @@
 }
 
 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 at index " << i << " in string constant '"
-                           << value << "'";
+      AIDL_ERROR(location) << "Found invalid character '" << value[i] << "' at index " << i - 1
+                           << " in string constant '" << value << "'";
       return new AidlConstantValue(location, Type::ERROR, value);
     }
   }
diff --git a/aidl_language.cpp b/aidl_language.cpp
index 82995dc..2d8886b 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -410,6 +410,19 @@
   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) {}
 
@@ -434,7 +447,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 {
@@ -1723,7 +1738,7 @@
 }
 
 AidlDocument::AidlDocument(const AidlLocation& location, const Comments& comments,
-                           std::set<string> imports,
+                           std::vector<string> imports,
                            std::vector<std::unique_ptr<AidlDefinedType>> defined_types,
                            bool is_preprocessed)
     : AidlCommentable(location, comments),
diff --git a/aidl_language.h b/aidl_language.h
index d19e425..0f4e2d1 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -1202,7 +1202,7 @@
 class AidlDocument : public AidlCommentable, public AidlScope {
  public:
   AidlDocument(const AidlLocation& location, const Comments& comments,
-               std::set<std::string> imports,
+               std::vector<std::string> imports,
                std::vector<std::unique_ptr<AidlDefinedType>> defined_types, bool is_preprocessed);
   ~AidlDocument() = default;
 
@@ -1213,7 +1213,7 @@
   AidlDocument& operator=(AidlDocument&&) = delete;
 
   std::string ResolveName(const std::string& name) const override;
-  const std::set<std::string>& Imports() const { return imports_; }
+  const std::vector<std::string>& Imports() const { return imports_; }
   const std::vector<std::unique_ptr<AidlDefinedType>>& DefinedTypes() const {
     return defined_types_;
   }
@@ -1227,7 +1227,7 @@
   void DispatchVisit(AidlVisitor& v) const override { v.Visit(*this); }
 
  private:
-  const std::set<std::string> imports_;
+  const std::vector<std::string> imports_;
   const std::vector<std::unique_ptr<AidlDefinedType>> defined_types_;
   bool is_preprocessed_;
 };
diff --git a/aidl_language_l.ll b/aidl_language_l.ll
index 04a8ff0..a286a7f 100644
--- a/aidl_language_l.ll
+++ b/aidl_language_l.ll
@@ -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 1665709..7f0b5bf 100644
--- a/aidl_language_y.yy
+++ b/aidl_language_y.yy
@@ -188,10 +188,9 @@
     } else if (!$2->empty()) {
       comments = $2->front()->GetComments();
     }
-    // dedup imports
-    std::set<std::string> imports;
+    std::vector<std::string> imports;
     for (const auto& import : *$2) {
-      imports.insert(import->GetText());
+      imports.push_back(import->GetText());
     }
     ps->MakeDocument(loc(@1), comments, std::move(imports), std::move(*$3));
     delete $1;
diff --git a/aidl_to_java.cpp b/aidl_to_java.cpp
index d8a05d5..d60362b 100644
--- a/aidl_to_java.cpp
+++ b/aidl_to_java.cpp
@@ -147,13 +147,18 @@
     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) {
@@ -166,7 +171,13 @@
     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;
 }
@@ -466,6 +477,12 @@
   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();
@@ -687,6 +704,17 @@
   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();
@@ -833,6 +861,14 @@
   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();
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 888ab94..26b4067 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -462,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");
@@ -1249,6 +1271,23 @@
   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 =
@@ -5282,7 +5321,7 @@
     {"ndk_primitiveArray", {"", ""}},
     {"rust_primitiveArray", {"", ""}},
     {"cpp_primitiveFixedArray", {"", ""}},
-    {"java_primitiveFixedArray", {"not supported yet", "not supported yet"}},
+    {"java_primitiveFixedArray", {"", ""}},
     {"ndk_primitiveFixedArray", {"", ""}},
     {"rust_primitiveFixedArray", {"", ""}},
     {"cpp_String", {"", ""}},
diff --git a/build/aidl_interface.go b/build/aidl_interface.go
index cc338d8..8d27826 100644
--- a/build/aidl_interface.go
+++ b/build/aidl_interface.go
@@ -252,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 {
@@ -828,29 +823,6 @@
 	}
 }
 
-// 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.BoolDefault(a.commonBackendProperties(lang).Srcs_available, true) {
-			// 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
 }
diff --git a/build/aidl_interface_backends.go b/build/aidl_interface_backends.go
index 9d9d5c3..ac4fce4 100644
--- a/build/aidl_interface_backends.go
+++ b/build/aidl_interface_backends.go
@@ -85,7 +85,6 @@
 		GenTrace:        genTrace,
 		Unstable:        i.properties.Unstable,
 		NotFrozen:       notFrozen,
-		Visibility:      srcsVisibility(mctx, lang),
 		Flags:           i.flagsForAidlGenRule(version),
 	})
 
@@ -231,7 +230,6 @@
 		GenTrace:        proptools.Bool(i.properties.Gen_trace),
 		Unstable:        i.properties.Unstable,
 		NotFrozen:       notFrozen,
-		Visibility:      srcsVisibility(mctx, langJava),
 		Flags:           i.flagsForAidlGenRule(version),
 	})
 
@@ -281,7 +279,6 @@
 		Version:         i.versionForAidlGenRule(version),
 		Unstable:        i.properties.Unstable,
 		NotFrozen:       notFrozen,
-		Visibility:      srcsVisibility(mctx, langRust),
 		Flags:           i.flagsForAidlGenRule(version),
 	})
 
diff --git a/build/aidl_test.go b/build/aidl_test.go
index 6cb89a7..2d5dc17 100644
--- a/build/aidl_test.go
+++ b/build/aidl_test.go
@@ -1069,45 +1069,6 @@
 	ctx.ModuleForTests("myiface-V1-cpp", "android_recovery_arm64_armv8-a_shared")
 }
 
-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)
-}
-
 func TestRustDuplicateNames(t *testing.T) {
 	testAidl(t, `
 		aidl_interface {
diff --git a/check_valid.cpp b/check_valid.cpp
index 7216c89..e7bcb8d 100644
--- a/check_valid.cpp
+++ b/check_valid.cpp
@@ -80,19 +80,6 @@
     return true;
   });
 
-  if (options.GetTask() == Options::Task::COMPILE) {
-    v.Check([&](const AidlTypeSpecifier& type) {
-      if (type.IsFixedSizeArray()) {
-        if (lang == Options::Language::JAVA) {
-          AIDL_ERROR(type) << "Fixed-size arrays are not supported yet in " << to_string(lang)
-                           << " backend.";
-          return false;
-        }
-      }
-      return true;
-    });
-  }
-
   VisitTopDown(v, doc);
   return v.success;
 }
diff --git a/diagnostics_unittest.cpp b/diagnostics_unittest.cpp
index 8c13df4..0066b9f 100644
--- a/diagnostics_unittest.cpp
+++ b/diagnostics_unittest.cpp
@@ -218,12 +218,12 @@
                "interface IFoo{}"}});
 }
 
-TEST_F(DiagnosticsTest, AllowRedundantImports) {
-  expect_diagnostics = {};
+TEST_F(DiagnosticsTest, RedundantImports) {
+  expect_diagnostics = {DiagnosticID::unique_import};
   ParseFiles({{"p/IFoo.aidl",
                "package p;\n"
                "import q.IBar;\n"
-               "import q.IBar;\n"  // ugly, but okay
+               "import q.IBar;\n"
                "interface IFoo{}"},
               {"q/IBar.aidl", "package q; interface IBar{}"}});
 }
diff --git a/generate_java_binder.cpp b/generate_java_binder.cpp
index 1fcef9d..508cd9e 100644
--- a/generate_java_binder.cpp
+++ b/generate_java_binder.cpp
@@ -574,8 +574,8 @@
         // "out" parameter should be instantiated before calling the real impl.
         string java_type = InstantiableJavaSignatureOf(arg->GetType());
 
-        if (arg->GetType().IsArray()) {
-          // array should be created with a passed length
+        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";
@@ -583,6 +583,13 @@
           (*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 {
           // otherwise, create a new instance with a default constructor
           (*writer) << v->name << " = new " << java_type << "();\n";
@@ -759,7 +766,7 @@
   for (const std::unique_ptr<AidlArgument>& arg : method.GetArguments()) {
     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>(
diff --git a/generate_ndk.cpp b/generate_ndk.cpp
index d7b6663..8a44854 100644
--- a/generate_ndk.cpp
+++ b/generate_ndk.cpp
@@ -980,6 +980,62 @@
   LeaveNdkNamespace(out, defined_type);
 }
 
+void GenerateDelegatorClassDecl(CodeWriter& out, const AidlTypenames& types,
+                                const AidlInterface& defined_type, const Options& options) {
+  const std::string clazz = ClassName(defined_type, ClassNames::DELEGATOR_IMPL);
+  const std::string iface = ClassName(defined_type, ClassNames::INTERFACE);
+  const std::string bn_name = ClassName(defined_type, ClassNames::SERVER);
+  const std::string kDelegateImplVarName = "_impl";
+  const std::string kStatusType = "::ndk::ScopedAStatus";
+
+  out << "class";
+  cpp::GenerateDeprecated(out, defined_type);
+  out << " " << clazz << " : public " << bn_name << " {\n";
+  out << "public:\n";
+  out.Indent();
+  out << "explicit " << clazz << "(const std::shared_ptr<" << iface << "> &impl)"
+      << " : " << kDelegateImplVarName << "(impl) {}\n\n";
+  for (const auto& method : defined_type.GetMethods()) {
+    if (method->IsUserDefined()) {
+      out << kStatusType << " " << method->GetName() << "("
+          << NdkArgList(types, *method, FormatArgForDecl) << ") override";
+      cpp::GenerateDeprecated(out, *method);
+      out << " {\n"
+          << "  return " << kDelegateImplVarName << "->" << method->GetName() << "("
+          << NdkArgList(types, *method, FormatArgNameOnly) << ");\n";
+      out << "}\n";
+    } else {
+      if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
+        out << kStatusType << " " << kGetInterfaceVersion << "(int32_t *aidl_return) override {\n"
+            << "  int32_t _delegator_ver  = " << iface << "::" << kVersion << ";\n"
+            << "  int32_t _impl_ver = 0;\n"
+            << "  " << kStatusType << " _ret = " << kDelegateImplVarName << "->"
+            << kGetInterfaceVersion << "(&_impl_ver);\n"
+            << "  if (!_ret.isOk()) return _ret;\n"
+            << "  *aidl_return = _delegator_ver < _impl_ver ? _delegator_ver : _impl_ver;\n"
+            << "  return _ret;\n"
+            << "}\n";
+      } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
+        out << kStatusType << " " << kGetInterfaceHash << "(std::string *aidl_return) override {\n"
+            << "  return " << kDelegateImplVarName << "->" << kGetInterfaceHash
+            << "(aidl_return);\n"
+            << "}\n";
+      } else {
+        AIDL_FATAL(defined_type) << "Meta method '" << method->GetName() << "' is unimplemented.";
+      }
+    }
+  }
+  out.Dedent();
+  out << "protected:\n";
+  out.Indent();
+  out.Dedent();
+  out << "private:\n";
+  out.Indent();
+  out << "std::shared_ptr<" << iface << "> " << kDelegateImplVarName << ";\n";
+  out.Dedent();
+  out << "};\n\n";
+}
+
 void GenerateServerClassDecl(CodeWriter& out, const AidlTypenames& types,
                              const AidlInterface& defined_type, const Options& options) {
   const std::string clazz = ClassName(defined_type, ClassNames::SERVER);
@@ -999,9 +1055,9 @@
       continue;
     }
     if (method->GetName() == kGetInterfaceVersion && options.Version() > 0) {
-      out << NdkMethodDecl(types, *method) << " final;\n";
+      out << NdkMethodDecl(types, *method) << ";\n";
     } else if (method->GetName() == kGetInterfaceHash && !options.Hash().empty()) {
-      out << NdkMethodDecl(types, *method) << " final;\n";
+      out << NdkMethodDecl(types, *method) << ";\n";
     } else {
       AIDL_FATAL(defined_type) << "Meta method '" << method->GetName() << "' is unimplemented.";
     }
@@ -1031,6 +1087,7 @@
   out << "\n";
   EnterNdkNamespace(out, defined_type);
   GenerateServerClassDecl(out, types, defined_type, options);
+  GenerateDelegatorClassDecl(out, types, defined_type, options);
   LeaveNdkNamespace(out, defined_type);
 }
 
diff --git a/parser.cpp b/parser.cpp
index 0c2677a..9988f56 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -310,7 +310,7 @@
 }
 
 void Parser::MakeDocument(const AidlLocation& location, const Comments& comments,
-                          std::set<std::string> imports,
+                          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),
diff --git a/parser.h b/parser.h
index e497912..074d6d5 100644
--- a/parser.h
+++ b/parser.h
@@ -92,7 +92,7 @@
   const std::string& Package() const { return package_; }
 
   void MakeDocument(const AidlLocation& location, const Comments& comments,
-                    std::set<std::string> imports,
+                    std::vector<std::string> imports,
                     std::vector<std::unique_ptr<AidlDefinedType>> defined_types);
 
  private:
diff --git a/tests/aidl_test_client_ndk_delegate.cpp b/tests/aidl_test_client_ndk_delegate.cpp
new file mode 100644
index 0000000..6bec01a
--- /dev/null
+++ b/tests/aidl_test_client_ndk_delegate.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+#include <android/binder_auto_utils.h>
+#include <android/binder_manager.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <aidl/android/aidl/tests/BnTestService.h>
+#include <android-base/logging.h>
+
+using aidl::android::aidl::tests::BackendType;
+using aidl::android::aidl::tests::ITestService;
+using aidl::android::aidl::tests::ITestServiceDelegator;
+
+static constexpr int8_t kCustomByte = 8;
+
+struct CustomDelegator : public ITestServiceDelegator {
+ public:
+  CustomDelegator(std::shared_ptr<ITestService>& impl) : ITestServiceDelegator(impl) {}
+
+  // Change RepeatByte to always return the same byte.
+  ndk::ScopedAStatus RepeatByte(int8_t /* token */, int8_t* _aidl_return) override {
+    *_aidl_return = kCustomByte;
+    return ndk::ScopedAStatus::ok();
+  }
+};
+
+struct AidlDelegatorTest : 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>(); }
+  std::shared_ptr<ITestService> service;
+};
+
+TEST_F(AidlDelegatorTest, SimpleDelegator) {
+  auto delegator = ndk::SharedRefBase::make<ITestServiceDelegator>(service);
+  int8_t returned_value;
+  auto status = delegator->RepeatByte(12, &returned_value);
+  ASSERT_TRUE(status.isOk()) << status.getMessage();
+  EXPECT_EQ(12, returned_value);
+}
+
+TEST_F(AidlDelegatorTest, CustomDelegator) {
+  auto delegator = ndk::SharedRefBase::make<CustomDelegator>(service);
+  int8_t returned_value;
+  auto status = delegator->RepeatByte(12, &returned_value);
+  ASSERT_TRUE(status.isOk()) << status.getMessage();
+  EXPECT_EQ(kCustomByte, returned_value);
+}
+
+TEST_F(AidlDelegatorTest, SendDelegator) {
+  auto delegator = ndk::SharedRefBase::make<ITestServiceDelegator>(service);
+  auto fromAsBinder = ITestServiceDelegator::fromBinder(delegator->asBinder());
+  // Make sure the delegator works after asBinder -> fromBinder conversions
+  int8_t returned_value = 0;
+  auto status = fromAsBinder->RepeatByte(12, &returned_value);
+  ASSERT_TRUE(status.isOk()) << status.getDescription();
+  EXPECT_EQ(12, returned_value);
+}
diff --git a/tests/aidl_test_client_ndk_parcelables.cpp b/tests/aidl_test_client_ndk_parcelables.cpp
index 55af497..72d309d 100644
--- a/tests/aidl_test_client_ndk_parcelables.cpp
+++ b/tests/aidl_test_client_ndk_parcelables.cpp
@@ -172,12 +172,6 @@
 }
 
 TEST_F(AidlTest, FixedSizeArrayOverBinder) {
-  auto test_service = getService<ITestService>();
-  BackendType backend;
-  auto status = test_service->getBackendType(&backend);
-  EXPECT_TRUE(status.isOk());
-  if (backend == BackendType::JAVA) GTEST_SKIP();
-
   auto service = getService<IRepeatFixedSizeArray>();
 
   CheckRepeat(service, &IRepeatFixedSizeArray::RepeatBytes, (std::array<uint8_t, 3>{1, 2, 3}));
diff --git a/tests/aidl_test_client_ndk_versioned_interface.cpp b/tests/aidl_test_client_ndk_versioned_interface.cpp
index 97da834..e21c8a0 100644
--- a/tests/aidl_test_client_ndk_versioned_interface.cpp
+++ b/tests/aidl_test_client_ndk_versioned_interface.cpp
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
+#include <aidl/android/aidl/versioned/tests/BnFooInterface.h>
 #include <aidl/android/aidl/versioned/tests/IFooInterface.h>
-
 #include <android/binder_auto_utils.h>
 #include <android/binder_manager.h>
 #include <gmock/gmock.h>
@@ -24,6 +24,7 @@
 using aidl::android::aidl::versioned::tests::BazUnion;
 using aidl::android::aidl::versioned::tests::Foo;
 using aidl::android::aidl::versioned::tests::IFooInterface;
+using aidl::android::aidl::versioned::tests::IFooInterfaceDelegator;
 using std::optional;
 using std::pair;
 using std::shared_ptr;
@@ -72,4 +73,18 @@
   EXPECT_EQ(43, ret);
   EXPECT_EQ(0, inoutFoo.intDefault42);
   EXPECT_EQ(0, outFoo.intDefault42);
-}
\ No newline at end of file
+}
+
+TEST_F(VersionedInterfaceTest, newerDelegatorReturnsImplVersion) {
+  auto delegator = ndk::SharedRefBase::make<IFooInterfaceDelegator>(versioned);
+  int32_t version = 0;
+  EXPECT_TRUE(delegator->getInterfaceVersion(&version).isOk());
+  EXPECT_EQ(1, version);
+}
+
+TEST_F(VersionedInterfaceTest, newerDelegatorReturnsImplHash) {
+  auto delegator = ndk::SharedRefBase::make<IFooInterfaceDelegator>(versioned);
+  std::string hash;
+  EXPECT_TRUE(delegator->getInterfaceHash(&hash).isOk());
+  EXPECT_EQ("9e7be1859820c59d9d55dd133e71a3687b5d2e5b", hash);
+}
diff --git a/tests/aidl_test_client_parcelables.cpp b/tests/aidl_test_client_parcelables.cpp
index 8cd5f06..99052bc 100644
--- a/tests/aidl_test_client_parcelables.cpp
+++ b/tests/aidl_test_client_parcelables.cpp
@@ -661,11 +661,6 @@
 }
 
 TEST_F(AidlTest, FixedSizeArrayOverBinder) {
-  BackendType backend;
-  auto status = service->getBackendType(&backend);
-  EXPECT_TRUE(status.isOk());
-  if (backend == BackendType::JAVA) GTEST_SKIP();
-
   sp<IRepeatFixedSizeArray> service;
   ASSERT_EQ(OK, getService(IRepeatFixedSizeArray::descriptor, &service));
 
diff --git a/tests/android/aidl/fixedsizearray/FixedSizeArrayExample.aidl b/tests/android/aidl/fixedsizearray/FixedSizeArrayExample.aidl
index dafb583..e226c3d 100644
--- a/tests/android/aidl/fixedsizearray/FixedSizeArrayExample.aidl
+++ b/tests/android/aidl/fixedsizearray/FixedSizeArrayExample.aidl
@@ -109,6 +109,7 @@
 
     @Backing(type="long") enum LongEnum { A }
 
+    @JavaDerive(equals=true)
     @RustDerive(Clone=true, Copy=true, PartialEq=true)
     parcelable IntParcelable {
         int value;
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-fixedsizearray-java-source/gen/timestamp b/tests/golden_output/aidl-test-fixedsizearray-java-source/gen/timestamp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/golden_output/aidl-test-fixedsizearray-java-source/gen/timestamp
diff --git a/tests/golden_output/aidl-test-interface-ndk-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
index 0b6f042..48da333 100644
--- a/tests/golden_output/aidl-test-interface-ndk-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
@@ -16,6 +16,15 @@
   ::ndk::SpAIBinder createBinder() override;
 private:
 };
+class __attribute__((deprecated("test"))) IDeprecatedDelegator : public BnDeprecated {
+public:
+  explicit IDeprecatedDelegator(const std::shared_ptr<IDeprecated> &impl) : _impl(impl) {}
+
+protected:
+private:
+  std::shared_ptr<IDeprecated> _impl;
+};
+
 }  // namespace tests
 }  // namespace aidl
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-ndk-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
index 6f38a28..310a837 100644
--- a/tests/golden_output/aidl-test-interface-ndk-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
@@ -16,6 +16,18 @@
   ::ndk::SpAIBinder createBinder() override;
 private:
 };
+class INamedCallbackDelegator : public BnNamedCallback {
+public:
+  explicit INamedCallbackDelegator(const std::shared_ptr<INamedCallback> &impl) : _impl(impl) {}
+
+  ::ndk::ScopedAStatus GetName(std::string* _aidl_return) override {
+    return _impl->GetName(_aidl_return);
+  }
+protected:
+private:
+  std::shared_ptr<INamedCallback> _impl;
+};
+
 }  // namespace tests
 }  // namespace aidl
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-ndk-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
index 32d8a7b..b7118c8 100644
--- a/tests/golden_output/aidl-test-interface-ndk-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
@@ -16,6 +16,18 @@
   ::ndk::SpAIBinder createBinder() override;
 private:
 };
+class INewNameDelegator : public BnNewName {
+public:
+  explicit INewNameDelegator(const std::shared_ptr<INewName> &impl) : _impl(impl) {}
+
+  ::ndk::ScopedAStatus RealName(std::string* _aidl_return) override {
+    return _impl->RealName(_aidl_return);
+  }
+protected:
+private:
+  std::shared_ptr<INewName> _impl;
+};
+
 }  // namespace tests
 }  // namespace aidl
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-ndk-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
index e1782d1..4e2ad8e 100644
--- a/tests/golden_output/aidl-test-interface-ndk-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
@@ -16,6 +16,18 @@
   ::ndk::SpAIBinder createBinder() override;
 private:
 };
+class IOldNameDelegator : public BnOldName {
+public:
+  explicit IOldNameDelegator(const std::shared_ptr<IOldName> &impl) : _impl(impl) {}
+
+  ::ndk::ScopedAStatus RealName(std::string* _aidl_return) override {
+    return _impl->RealName(_aidl_return);
+  }
+protected:
+private:
+  std::shared_ptr<IOldName> _impl;
+};
+
 }  // namespace tests
 }  // namespace aidl
 }  // namespace android
diff --git a/tests/golden_output/aidl-test-interface-ndk-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
index a33592b..dfd86b3 100644
--- a/tests/golden_output/aidl-test-interface-ndk-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
@@ -16,6 +16,210 @@
   ::ndk::SpAIBinder createBinder() override;
 private:
 };
+class ITestServiceDelegator : public BnTestService {
+public:
+  explicit ITestServiceDelegator(const std::shared_ptr<ITestService> &impl) : _impl(impl) {}
+
+  ::ndk::ScopedAStatus UnimplementedMethod(int32_t in_arg, int32_t* _aidl_return) override {
+    return _impl->UnimplementedMethod(in_arg, _aidl_return);
+  }
+  ::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"))) {
+    return _impl->Deprecated();
+  }
+  ::ndk::ScopedAStatus TestOneway() override {
+    return _impl->TestOneway();
+  }
+  ::ndk::ScopedAStatus RepeatBoolean(bool in_token, bool* _aidl_return) override {
+    return _impl->RepeatBoolean(in_token, _aidl_return);
+  }
+  ::ndk::ScopedAStatus RepeatByte(int8_t in_token, int8_t* _aidl_return) override {
+    return _impl->RepeatByte(in_token, _aidl_return);
+  }
+  ::ndk::ScopedAStatus RepeatChar(char16_t in_token, char16_t* _aidl_return) override {
+    return _impl->RepeatChar(in_token, _aidl_return);
+  }
+  ::ndk::ScopedAStatus RepeatInt(int32_t in_token, int32_t* _aidl_return) override {
+    return _impl->RepeatInt(in_token, _aidl_return);
+  }
+  ::ndk::ScopedAStatus RepeatLong(int64_t in_token, int64_t* _aidl_return) override {
+    return _impl->RepeatLong(in_token, _aidl_return);
+  }
+  ::ndk::ScopedAStatus RepeatFloat(float in_token, float* _aidl_return) override {
+    return _impl->RepeatFloat(in_token, _aidl_return);
+  }
+  ::ndk::ScopedAStatus RepeatDouble(double in_token, double* _aidl_return) override {
+    return _impl->RepeatDouble(in_token, _aidl_return);
+  }
+  ::ndk::ScopedAStatus RepeatString(const std::string& in_token, std::string* _aidl_return) override {
+    return _impl->RepeatString(in_token, _aidl_return);
+  }
+  ::ndk::ScopedAStatus RepeatByteEnum(::aidl::android::aidl::tests::ByteEnum in_token, ::aidl::android::aidl::tests::ByteEnum* _aidl_return) override {
+    return _impl->RepeatByteEnum(in_token, _aidl_return);
+  }
+  ::ndk::ScopedAStatus RepeatIntEnum(::aidl::android::aidl::tests::IntEnum in_token, ::aidl::android::aidl::tests::IntEnum* _aidl_return) override {
+    return _impl->RepeatIntEnum(in_token, _aidl_return);
+  }
+  ::ndk::ScopedAStatus RepeatLongEnum(::aidl::android::aidl::tests::LongEnum in_token, ::aidl::android::aidl::tests::LongEnum* _aidl_return) override {
+    return _impl->RepeatLongEnum(in_token, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ReverseBoolean(const std::vector<bool>& in_input, std::vector<bool>* out_repeated, std::vector<bool>* _aidl_return) override {
+    return _impl->ReverseBoolean(in_input, out_repeated, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ReverseByte(const std::vector<uint8_t>& in_input, std::vector<uint8_t>* out_repeated, std::vector<uint8_t>* _aidl_return) override {
+    return _impl->ReverseByte(in_input, out_repeated, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ReverseChar(const std::vector<char16_t>& in_input, std::vector<char16_t>* out_repeated, std::vector<char16_t>* _aidl_return) override {
+    return _impl->ReverseChar(in_input, out_repeated, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ReverseInt(const std::vector<int32_t>& in_input, std::vector<int32_t>* out_repeated, std::vector<int32_t>* _aidl_return) override {
+    return _impl->ReverseInt(in_input, out_repeated, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ReverseLong(const std::vector<int64_t>& in_input, std::vector<int64_t>* out_repeated, std::vector<int64_t>* _aidl_return) override {
+    return _impl->ReverseLong(in_input, out_repeated, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ReverseFloat(const std::vector<float>& in_input, std::vector<float>* out_repeated, std::vector<float>* _aidl_return) override {
+    return _impl->ReverseFloat(in_input, out_repeated, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ReverseDouble(const std::vector<double>& in_input, std::vector<double>* out_repeated, std::vector<double>* _aidl_return) override {
+    return _impl->ReverseDouble(in_input, out_repeated, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ReverseString(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) override {
+    return _impl->ReverseString(in_input, out_repeated, _aidl_return);
+  }
+  ::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 {
+    return _impl->ReverseByteEnum(in_input, out_repeated, _aidl_return);
+  }
+  ::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 {
+    return _impl->ReverseIntEnum(in_input, out_repeated, _aidl_return);
+  }
+  ::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 {
+    return _impl->ReverseLongEnum(in_input, out_repeated, _aidl_return);
+  }
+  ::ndk::ScopedAStatus GetOtherTestService(const std::string& in_name, std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>* _aidl_return) override {
+    return _impl->GetOtherTestService(in_name, _aidl_return);
+  }
+  ::ndk::ScopedAStatus VerifyName(const std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>& in_service, const std::string& in_name, bool* _aidl_return) override {
+    return _impl->VerifyName(in_service, in_name, _aidl_return);
+  }
+  ::ndk::ScopedAStatus GetInterfaceArray(const std::vector<std::string>& in_names, std::vector<std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>>* _aidl_return) override {
+    return _impl->GetInterfaceArray(in_names, _aidl_return);
+  }
+  ::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 {
+    return _impl->VerifyNamesWithInterfaceArray(in_services, in_names, _aidl_return);
+  }
+  ::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 {
+    return _impl->GetNullableInterfaceArray(in_names, _aidl_return);
+  }
+  ::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 {
+    return _impl->VerifyNamesWithNullableInterfaceArray(in_services, in_names, _aidl_return);
+  }
+  ::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 {
+    return _impl->GetInterfaceList(in_names, _aidl_return);
+  }
+  ::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 {
+    return _impl->VerifyNamesWithInterfaceList(in_services, in_names, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ReverseStringList(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) override {
+    return _impl->ReverseStringList(in_input, out_repeated, _aidl_return);
+  }
+  ::ndk::ScopedAStatus RepeatParcelFileDescriptor(const ::ndk::ScopedFileDescriptor& in_read, ::ndk::ScopedFileDescriptor* _aidl_return) override {
+    return _impl->RepeatParcelFileDescriptor(in_read, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ReverseParcelFileDescriptorArray(const std::vector<::ndk::ScopedFileDescriptor>& in_input, std::vector<::ndk::ScopedFileDescriptor>* out_repeated, std::vector<::ndk::ScopedFileDescriptor>* _aidl_return) override {
+    return _impl->ReverseParcelFileDescriptorArray(in_input, out_repeated, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ThrowServiceException(int32_t in_code) override {
+    return _impl->ThrowServiceException(in_code);
+  }
+  ::ndk::ScopedAStatus RepeatNullableIntArray(const std::optional<std::vector<int32_t>>& in_input, std::optional<std::vector<int32_t>>* _aidl_return) override {
+    return _impl->RepeatNullableIntArray(in_input, _aidl_return);
+  }
+  ::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 {
+    return _impl->RepeatNullableByteEnumArray(in_input, _aidl_return);
+  }
+  ::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 {
+    return _impl->RepeatNullableIntEnumArray(in_input, _aidl_return);
+  }
+  ::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 {
+    return _impl->RepeatNullableLongEnumArray(in_input, _aidl_return);
+  }
+  ::ndk::ScopedAStatus RepeatNullableString(const std::optional<std::string>& in_input, std::optional<std::string>* _aidl_return) override {
+    return _impl->RepeatNullableString(in_input, _aidl_return);
+  }
+  ::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 {
+    return _impl->RepeatNullableStringList(in_input, _aidl_return);
+  }
+  ::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 {
+    return _impl->RepeatNullableParcelable(in_input, _aidl_return);
+  }
+  ::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 {
+    return _impl->RepeatNullableParcelableArray(in_input, _aidl_return);
+  }
+  ::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 {
+    return _impl->RepeatNullableParcelableList(in_input, _aidl_return);
+  }
+  ::ndk::ScopedAStatus TakesAnIBinder(const ::ndk::SpAIBinder& in_input) override {
+    return _impl->TakesAnIBinder(in_input);
+  }
+  ::ndk::ScopedAStatus TakesANullableIBinder(const ::ndk::SpAIBinder& in_input) override {
+    return _impl->TakesANullableIBinder(in_input);
+  }
+  ::ndk::ScopedAStatus TakesAnIBinderList(const std::vector<::ndk::SpAIBinder>& in_input) override {
+    return _impl->TakesAnIBinderList(in_input);
+  }
+  ::ndk::ScopedAStatus TakesANullableIBinderList(const std::optional<std::vector<::ndk::SpAIBinder>>& in_input) override {
+    return _impl->TakesANullableIBinderList(in_input);
+  }
+  ::ndk::ScopedAStatus RepeatUtf8CppString(const std::string& in_token, std::string* _aidl_return) override {
+    return _impl->RepeatUtf8CppString(in_token, _aidl_return);
+  }
+  ::ndk::ScopedAStatus RepeatNullableUtf8CppString(const std::optional<std::string>& in_token, std::optional<std::string>* _aidl_return) override {
+    return _impl->RepeatNullableUtf8CppString(in_token, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ReverseUtf8CppString(const std::vector<std::string>& in_input, std::vector<std::string>* out_repeated, std::vector<std::string>* _aidl_return) override {
+    return _impl->ReverseUtf8CppString(in_input, out_repeated, _aidl_return);
+  }
+  ::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 {
+    return _impl->ReverseNullableUtf8CppString(in_input, out_repeated, _aidl_return);
+  }
+  ::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 {
+    return _impl->ReverseUtf8CppStringList(in_input, out_repeated, _aidl_return);
+  }
+  ::ndk::ScopedAStatus GetCallback(bool in_return_null, std::shared_ptr<::aidl::android::aidl::tests::INamedCallback>* _aidl_return) override {
+    return _impl->GetCallback(in_return_null, _aidl_return);
+  }
+  ::ndk::ScopedAStatus FillOutStructuredParcelable(::aidl::android::aidl::tests::StructuredParcelable* in_parcel) override {
+    return _impl->FillOutStructuredParcelable(in_parcel);
+  }
+  ::ndk::ScopedAStatus RepeatExtendableParcelable(const ::aidl::android::aidl::tests::extension::ExtendableParcelable& in_ep, ::aidl::android::aidl::tests::extension::ExtendableParcelable* out_ep2) override {
+    return _impl->RepeatExtendableParcelable(in_ep, out_ep2);
+  }
+  ::ndk::ScopedAStatus ReverseList(const ::aidl::android::aidl::tests::RecursiveList& in_list, ::aidl::android::aidl::tests::RecursiveList* _aidl_return) override {
+    return _impl->ReverseList(in_list, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ReverseIBinderArray(const std::vector<::ndk::SpAIBinder>& in_input, std::vector<::ndk::SpAIBinder>* out_repeated, std::vector<::ndk::SpAIBinder>* _aidl_return) override {
+    return _impl->ReverseIBinderArray(in_input, out_repeated, _aidl_return);
+  }
+  ::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 {
+    return _impl->ReverseNullableIBinderArray(in_input, out_repeated, _aidl_return);
+  }
+  ::ndk::ScopedAStatus GetOldNameInterface(std::shared_ptr<::aidl::android::aidl::tests::IOldName>* _aidl_return) override {
+    return _impl->GetOldNameInterface(_aidl_return);
+  }
+  ::ndk::ScopedAStatus GetNewNameInterface(std::shared_ptr<::aidl::android::aidl::tests::INewName>* _aidl_return) override {
+    return _impl->GetNewNameInterface(_aidl_return);
+  }
+  ::ndk::ScopedAStatus GetCppJavaTests(::ndk::SpAIBinder* _aidl_return) override {
+    return _impl->GetCppJavaTests(_aidl_return);
+  }
+  ::ndk::ScopedAStatus getBackendType(::aidl::android::aidl::tests::BackendType* _aidl_return) override {
+    return _impl->getBackendType(_aidl_return);
+  }
+protected:
+private:
+  std::shared_ptr<ITestService> _impl;
+};
+
 }  // namespace tests
 }  // namespace aidl
 }  // namespace android
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
index 98ec330..b6ea332 100644
--- 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
@@ -17,6 +17,21 @@
   ::ndk::SpAIBinder createBinder() override;
 private:
 };
+class INestedServiceDelegator : public BnNestedService {
+public:
+  explicit INestedServiceDelegator(const std::shared_ptr<INestedService> &impl) : _impl(impl) {}
+
+  ::ndk::ScopedAStatus flipStatus(const ::aidl::android::aidl::tests::nested::ParcelableWithNested& in_p, ::aidl::android::aidl::tests::nested::INestedService::Result* _aidl_return) override {
+    return _impl->flipStatus(in_p, _aidl_return);
+  }
+  ::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 {
+    return _impl->flipStatusWithCallback(in_status, in_cb);
+  }
+protected:
+private:
+  std::shared_ptr<INestedService> _impl;
+};
+
 }  // namespace nested
 }  // namespace tests
 }  // namespace aidl
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
index 150c5b8..3a8674f 100644
--- 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
@@ -17,6 +17,24 @@
   ::ndk::SpAIBinder createBinder() override;
 private:
 };
+class IProtectedDelegator : public BnProtected {
+public:
+  explicit IProtectedDelegator(const std::shared_ptr<IProtected> &impl) : _impl(impl) {}
+
+  ::ndk::ScopedAStatus PermissionProtected() override {
+    return _impl->PermissionProtected();
+  }
+  ::ndk::ScopedAStatus MultiplePermissionsAll() override {
+    return _impl->MultiplePermissionsAll();
+  }
+  ::ndk::ScopedAStatus MultiplePermissionsAny() override {
+    return _impl->MultiplePermissionsAny();
+  }
+protected:
+private:
+  std::shared_ptr<IProtected> _impl;
+};
+
 }  // namespace permission
 }  // namespace tests
 }  // 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
index ac2a46c..16cc53e 100644
--- 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
@@ -17,6 +17,21 @@
   ::ndk::SpAIBinder createBinder() override;
 private:
 };
+class IProtectedInterfaceDelegator : public BnProtectedInterface {
+public:
+  explicit IProtectedInterfaceDelegator(const std::shared_ptr<IProtectedInterface> &impl) : _impl(impl) {}
+
+  ::ndk::ScopedAStatus Method1() override {
+    return _impl->Method1();
+  }
+  ::ndk::ScopedAStatus Method2() override {
+    return _impl->Method2();
+  }
+protected:
+private:
+  std::shared_ptr<IProtectedInterface> _impl;
+};
+
 }  // namespace permission
 }  // namespace tests
 }  // namespace aidl
diff --git a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/BnLoggableInterface.h b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/BnLoggableInterface.h
index 650ca86..2ae567f 100644
--- a/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/BnLoggableInterface.h
+++ b/tests/golden_output/aidl_test_loggable_interface-ndk-source/gen/include/aidl/android/aidl/loggable/BnLoggableInterface.h
@@ -31,6 +31,18 @@
   ::ndk::SpAIBinder createBinder() override;
 private:
 };
+class ILoggableInterfaceDelegator : public BnLoggableInterface {
+public:
+  explicit ILoggableInterfaceDelegator(const std::shared_ptr<ILoggableInterface> &impl) : _impl(impl) {}
+
+  ::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 {
+    return _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);
+  }
+protected:
+private:
+  std::shared_ptr<ILoggableInterface> _impl;
+};
+
 }  // namespace loggable
 }  // namespace aidl
 }  // namespace android
diff --git a/tests/golden_test.sh b/tests/golden_test.sh
index 2ffc35c..547999e 100755
--- a/tests/golden_test.sh
+++ b/tests/golden_test.sh
@@ -47,6 +47,7 @@
     "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"
   )
diff --git a/tests/java/src/android/aidl/service/TestServiceServer.java b/tests/java/src/android/aidl/service/TestServiceServer.java
index 0b012d3..ad98416 100644
--- a/tests/java/src/android/aidl/service/TestServiceServer.java
+++ b/tests/java/src/android/aidl/service/TestServiceServer.java
@@ -16,6 +16,8 @@
 
 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;
@@ -66,6 +68,9 @@
     NestedService nested = new NestedService();
     ServiceManager.addService(INestedService.class.getName(), nested);
 
+    FixedSizeArrayService fixedSize = new FixedSizeArrayService();
+    ServiceManager.addService(IRepeatFixedSizeArray.DESCRIPTOR, fixedSize);
+
     Binder.joinThreadPool();
   }
 
@@ -666,6 +671,76 @@
     }
   }
 
+  public static class FixedSizeArrayService extends IRepeatFixedSizeArray.Stub {
+    @Override
+    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 int[] RepeatInts(int[] input, int[] repeated) throws RemoteException {
+      for (int i = 0; i < input.length; i++) {
+        repeated[i] = input[i];
+      }
+      return input;
+    }
+    @Override
+    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 {
+      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;
+    }
+  }
+
   @Override
   public IBinder GetCppJavaTests() throws RemoteException {
     return new MyCppJavaTests();
diff --git a/tests/java/src/android/aidl/tests/TestServiceClient.java b/tests/java/src/android/aidl/tests/TestServiceClient.java
index d209240..e9140cc 100644
--- a/tests/java/src/android/aidl/tests/TestServiceClient.java
+++ b/tests/java/src/android/aidl/tests/TestServiceClient.java
@@ -18,6 +18,7 @@
 
 import static org.hamcrest.core.Is.is;
 import static org.hamcrest.core.IsNull.notNullValue;
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -26,6 +27,8 @@
 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;
@@ -56,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;
@@ -962,4 +966,40 @@
           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/rust/test_client.rs b/tests/rust/test_client.rs
index d2ec94b..1d75234 100644
--- a/tests/rust/test_client.rs
+++ b/tests/rust/test_client.rs
@@ -1167,12 +1167,6 @@
 #[test]
 fn test_fixed_size_array_over_binder() {
     let test_service = get_test_service();
-    let backend = test_service.getBackendType().expect("error getting backend type");
-    if backend == BackendType::JAVA {
-        // Java doesn't support fixed-size arrays yet
-        return;
-    }
-
     let service: binder::Strong<dyn IRepeatFixedSizeArray> =
         binder::get_interface(<BpRepeatFixedSizeArray as IRepeatFixedSizeArray>::get_descriptor())
             .expect("did not get binder service");