Merge "finalize Tiramisu SDK version (33)" into tm-dev
diff --git a/Android.bp b/Android.bp
index c795969..08df261 100644
--- a/Android.bp
+++ b/Android.bp
@@ -442,6 +442,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",
diff --git a/aidl_to_cpp_common.cpp b/aidl_to_cpp_common.cpp
index 589bb55..682b6c8 100644
--- a/aidl_to_cpp_common.cpp
+++ b/aidl_to_cpp_common.cpp
@@ -425,9 +425,16 @@
   out << "os << \"" + parcelable.GetName() + "{\";\n";
   out << "switch (getTag()) {\n";
   for (const auto& f : parcelable.GetFields()) {
+    if (f->IsDeprecated()) {
+      out << "#pragma clang diagnostic push\n";
+      out << "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n";
+    }
     const string tag = f->GetName();
     out << "case " << tag << ": os << \"" << tag << ": \" << "
         << "::android::internal::ToString(get<" + tag + ">()); break;\n";
+    if (f->IsDeprecated()) {
+      out << "#pragma clang diagnostic pop\n";
+    }
   }
   out << "}\n";
   out << "os << \"}\";\n";
@@ -651,6 +658,10 @@
   read_var(tag, *tag_type);
   out << fmt::format("switch (static_cast<Tag>({})) {{\n", tag);
   for (const auto& variable : decl.GetFields()) {
+    if (variable->IsDeprecated()) {
+      out << "#pragma clang diagnostic push\n";
+      out << "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n";
+    }
     out << fmt::format("case {}: {{\n", variable->GetName());
     out.Indent();
     const auto& type = variable->GetType();
@@ -670,6 +681,9 @@
     out << "}\n";
     out << fmt::format("return {}; }}\n", ctx.status_ok);
     out.Dedent();
+    if (variable->IsDeprecated()) {
+      out << "#pragma clang diagnostic pop\n";
+    }
   }
   out << "}\n";
   out << fmt::format("return {};\n", ctx.status_bad);
@@ -690,9 +704,16 @@
   out << fmt::format("if ({} != {}) return {};\n", status, ctx.status_ok, status);
   out << "switch (getTag()) {\n";
   for (const auto& variable : decl.GetFields()) {
+    if (variable->IsDeprecated()) {
+      out << "#pragma clang diagnostic push\n";
+      out << "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n";
+    }
     out << fmt::format("case {}: return ", variable->GetName());
     ctx.write_func(out, "get<" + variable->GetName() + ">()", variable->GetType());
     out << ";\n";
+    if (variable->IsDeprecated()) {
+      out << "#pragma clang diagnostic pop\n";
+    }
   }
   out << "}\n";
   out << "__assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, \"can't reach here\");\n";
diff --git a/build/aidl_interface_backends.go b/build/aidl_interface_backends.go
index 128eee2..62a167c 100644
--- a/build/aidl_interface_backends.go
+++ b/build/aidl_interface_backends.go
@@ -81,7 +81,7 @@
 		Lang:            lang,
 		BaseName:        i.ModuleBase.Name(),
 		GenLog:          genLog,
-		Version:         i.versionForAidlGenRule(version),
+		Version:         i.versionForInitVersionCompat(version),
 		GenTrace:        genTrace,
 		Unstable:        i.properties.Unstable,
 		NotFrozen:       notFrozen,
@@ -229,7 +229,7 @@
 		Platform_apis:   proptools.Bool(i.properties.Backend.Java.Platform_apis),
 		Lang:            langJava,
 		BaseName:        i.ModuleBase.Name(),
-		Version:         i.versionForAidlGenRule(version),
+		Version:         version,
 		GenRpc:          proptools.Bool(i.properties.Backend.Java.Gen_rpc),
 		GenTrace:        proptools.Bool(i.properties.Gen_trace),
 		Unstable:        i.properties.Unstable,
@@ -280,7 +280,7 @@
 		Min_sdk_version: i.minSdkVersion(langRust),
 		Lang:            langRust,
 		BaseName:        i.ModuleBase.Name(),
-		Version:         i.versionForAidlGenRule(version),
+		Version:         i.versionForInitVersionCompat(version),
 		Unstable:        i.properties.Unstable,
 		NotFrozen:       notFrozen,
 		Flags:           i.flagsForAidlGenRule(version),
@@ -343,7 +343,10 @@
 	}
 }
 
-func (i *aidlInterface) versionForAidlGenRule(version string) string {
+// For certain backend, avoid a difference between the initial version of a versioned
+// interface and an unversioned interface. This ensures that prebuilts can't prevent
+// an interface from switching from unversioned to versioned.
+func (i *aidlInterface) versionForInitVersionCompat(version string) string {
 	if !i.hasVersion() {
 		return ""
 	}
diff --git a/generate_ndk.cpp b/generate_ndk.cpp
index e3db352..4345a74 100644
--- a/generate_ndk.cpp
+++ b/generate_ndk.cpp
@@ -288,7 +288,7 @@
         includes.insert("chrono");
         includes.insert("sstream");
       }
-      // For nested interfacees client/server classes are defined in the same header.
+      // For nested interfaces client/server classes are defined in the same header.
       // So we need includes for client/server class as well.
       if (interface.GetParentType()) {
         includes.insert("android/binder_ibinder.h");
@@ -985,6 +985,59 @@
   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";
+  if (options.Version() > 0) {
+    // TODO(b/222347502) If we need to support mismatched versions of delegator and
+    // impl, this check will be removed. The NDK backend can't override the
+    // getInterface* meta methods because they are marked "final". Removing
+    // "final" changes the ABI and breaks prebuilts.
+    out << "   int32_t _impl_ver = 0;\n";
+    out << "   if (!impl->" << kGetInterfaceVersion << "(&_impl_ver).isOk()) {;\n";
+    out << "      __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, \"Delegator failed to get "
+           "version of the implementation.\");\n";
+    out << "   }\n";
+    out << "   if (_impl_ver != " << iface << "::" << kVersion << ") {\n";
+    out << "      __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, \"Mismatched versions of "
+           "delegator and implementation is not allowed.\");\n";
+    out << "   }\n";
+  }
+  out << "}\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";
+    }
+  }
+  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);
@@ -1033,9 +1086,18 @@
       << "\"\n";
   out << "\n";
   out << "#include <android/binder_ibinder.h>\n";
+  // Needed for *Delegator classes while delegator version is required to be
+  // the same as the implementation version
+  // TODO(b/222347502) If we ever need to support mismatched versions of delegator and
+  // impl, this include can be removed.
+  out << "#include <cassert>\n\n";
+  // TODO(b/31559095) bionic on host should define __assert2
+  out << "#ifndef __BIONIC__\n#ifndef __assert2\n#define __assert2(a,b,c,d) "
+         "((void)0)\n#endif\n#endif\n";
   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/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_versioned_interface.cpp b/tests/aidl_test_client_ndk_versioned_interface.cpp
index 97da834..f1d0207 100644
--- a/tests/aidl_test_client_ndk_versioned_interface.cpp
+++ b/tests/aidl_test_client_ndk_versioned_interface.cpp
@@ -72,4 +72,4 @@
   EXPECT_EQ(43, ret);
   EXPECT_EQ(0, inoutFoo.intDefault42);
   EXPECT_EQ(0, outFoo.intDefault42);
-}
\ No newline at end of file
+}
diff --git a/tests/android/aidl/tests/unions/EnumUnion.aidl b/tests/android/aidl/tests/unions/EnumUnion.aidl
index 5f9bb05..817ea1c 100644
--- a/tests/android/aidl/tests/unions/EnumUnion.aidl
+++ b/tests/android/aidl/tests/unions/EnumUnion.aidl
@@ -23,4 +23,6 @@
 union EnumUnion {
     IntEnum intEnum = IntEnum.FOO;
     LongEnum longEnum;
+    /** @deprecated do not use this */
+    int deprecatedField;
 }
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/EnumUnion.cpp b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/EnumUnion.cpp
index b51ef52..0261f25 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/EnumUnion.cpp
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/android/aidl/tests/unions/EnumUnion.cpp
@@ -29,6 +29,19 @@
       set<longEnum>(std::move(_aidl_value));
     }
     return ::android::OK; }
+  #pragma clang diagnostic push
+  #pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  case deprecatedField: {
+    int32_t _aidl_value;
+    if ((_aidl_ret_status = _aidl_parcel->readInt32(&_aidl_value)) != ::android::OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<int32_t>) {
+      set<deprecatedField>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<deprecatedField>(std::move(_aidl_value));
+    }
+    return ::android::OK; }
+  #pragma clang diagnostic pop
   }
   return ::android::BAD_VALUE;
 }
@@ -38,6 +51,10 @@
   switch (getTag()) {
   case intEnum: return _aidl_parcel->writeInt32(static_cast<int32_t>(get<intEnum>()));
   case longEnum: return _aidl_parcel->writeInt64(static_cast<int64_t>(get<longEnum>()));
+  #pragma clang diagnostic push
+  #pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  case deprecatedField: return _aidl_parcel->writeInt32(get<deprecatedField>());
+  #pragma clang diagnostic pop
   }
   __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
 }
diff --git a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/unions/EnumUnion.h b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/unions/EnumUnion.h
index a65f9f0..7a41b20 100644
--- a/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/unions/EnumUnion.h
+++ b/tests/golden_output/aidl-test-interface-cpp-source/gen/include/android/aidl/tests/unions/EnumUnion.h
@@ -28,10 +28,12 @@
   enum class Tag : int32_t {
     intEnum = 0,
     longEnum = 1,
+    deprecatedField __attribute__((deprecated("do not use this"))) = 2,
   };
   // Expose tag symbols for legacy code
   static const inline Tag intEnum = Tag::intEnum;
   static const inline Tag longEnum = Tag::longEnum;
+  static const inline Tag __attribute__((deprecated("do not use this"))) deprecatedField = Tag::deprecatedField;
 
   template<typename _Tp>
   static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, EnumUnion>;
@@ -109,12 +111,16 @@
     switch (getTag()) {
     case intEnum: os << "intEnum: " << ::android::internal::ToString(get<intEnum>()); break;
     case longEnum: os << "longEnum: " << ::android::internal::ToString(get<longEnum>()); break;
+    #pragma clang diagnostic push
+    #pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    case deprecatedField: os << "deprecatedField: " << ::android::internal::ToString(get<deprecatedField>()); break;
+    #pragma clang diagnostic pop
     }
     os << "}";
     return os.str();
   }
 private:
-  std::variant<::android::aidl::tests::IntEnum, ::android::aidl::tests::LongEnum> _value;
+  std::variant<::android::aidl::tests::IntEnum, ::android::aidl::tests::LongEnum, int32_t> _value;
 };  // class EnumUnion
 }  // namespace unions
 }  // namespace tests
@@ -124,16 +130,21 @@
 namespace aidl {
 namespace tests {
 namespace unions {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
 [[nodiscard]] static inline std::string toString(EnumUnion::Tag val) {
   switch(val) {
   case EnumUnion::Tag::intEnum:
     return "intEnum";
   case EnumUnion::Tag::longEnum:
     return "longEnum";
+  case EnumUnion::Tag::deprecatedField:
+    return "deprecatedField";
   default:
     return std::to_string(static_cast<int32_t>(val));
   }
 }
+#pragma clang diagnostic pop
 }  // namespace unions
 }  // namespace tests
 }  // namespace aidl
@@ -142,10 +153,12 @@
 namespace internal {
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wc++17-extensions"
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
 template <>
-constexpr inline std::array<::android::aidl::tests::unions::EnumUnion::Tag, 2> enum_values<::android::aidl::tests::unions::EnumUnion::Tag> = {
+constexpr inline std::array<::android::aidl::tests::unions::EnumUnion::Tag, 3> enum_values<::android::aidl::tests::unions::EnumUnion::Tag> = {
   ::android::aidl::tests::unions::EnumUnion::Tag::intEnum,
   ::android::aidl::tests::unions::EnumUnion::Tag::longEnum,
+  ::android::aidl::tests::unions::EnumUnion::Tag::deprecatedField,
 };
 #pragma clang diagnostic pop
 }  // namespace internal
diff --git a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/EnumUnion.java b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/EnumUnion.java
index 937d9d5..7519fd4 100644
--- a/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/EnumUnion.java
+++ b/tests/golden_output/aidl-test-interface-java-source/gen/android/aidl/tests/unions/EnumUnion.java
@@ -6,6 +6,7 @@
   // tags for union fields
   public final static int intEnum = 0;  // android.aidl.tests.IntEnum intEnum;
   public final static int longEnum = 1;  // android.aidl.tests.LongEnum longEnum;
+  public final static int deprecatedField = 2;  // int deprecatedField;
 
   private int _tag;
   private Object _value;
@@ -59,6 +60,23 @@
     _set(longEnum, _value);
   }
 
+  // int deprecatedField;
+
+  /** @deprecated do not use this */
+  @Deprecated
+  public static EnumUnion deprecatedField(int _value) {
+    return new EnumUnion(deprecatedField, _value);
+  }
+
+  public int getDeprecatedField() {
+    _assertTag(deprecatedField);
+    return (int) _value;
+  }
+
+  public void setDeprecatedField(int _value) {
+    _set(deprecatedField, _value);
+  }
+
   public static final android.os.Parcelable.Creator<EnumUnion> CREATOR = new android.os.Parcelable.Creator<EnumUnion>() {
     @Override
     public EnumUnion createFromParcel(android.os.Parcel _aidl_source) {
@@ -80,6 +98,9 @@
     case longEnum:
       _aidl_parcel.writeLong(getLongEnum());
       break;
+    case deprecatedField:
+      _aidl_parcel.writeInt(getDeprecatedField());
+      break;
     }
   }
 
@@ -97,6 +118,11 @@
       _aidl_value = _aidl_parcel.readLong();
       _set(_aidl_tag, _aidl_value);
       return; }
+    case deprecatedField: {
+      int _aidl_value;
+      _aidl_value = _aidl_parcel.readInt();
+      _set(_aidl_tag, _aidl_value);
+      return; }
     }
     throw new IllegalArgumentException("union: unknown tag: " + _aidl_tag);
   }
@@ -114,6 +140,7 @@
     switch (_tag) {
     case intEnum: return "android.aidl.tests.unions.EnumUnion.intEnum(" + (android.aidl.tests.IntEnum.$.toString(getIntEnum())) + ")";
     case longEnum: return "android.aidl.tests.unions.EnumUnion.longEnum(" + (getLongEnum()) + ")";
+    case deprecatedField: return "android.aidl.tests.unions.EnumUnion.deprecatedField(" + (getDeprecatedField()) + ")";
     }
     throw new IllegalStateException("unknown field: " + _tag);
   }
@@ -143,6 +170,7 @@
     switch (_tag) {
     case intEnum: return "intEnum";
     case longEnum: return "longEnum";
+    case deprecatedField: return "deprecatedField";
     }
     throw new IllegalStateException("unknown field: " + _tag);
   }
@@ -154,5 +182,8 @@
   public static @interface Tag {
     public static final int intEnum = 0;
     public static final int longEnum = 1;
+    /** @deprecated do not use this */
+    @Deprecated
+    public static final int deprecatedField = 2;
   }
 }
diff --git a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/EnumUnion.cpp b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/EnumUnion.cpp
index bb47430..c3f473f 100644
--- a/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/EnumUnion.cpp
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/android/aidl/tests/unions/EnumUnion.cpp
@@ -34,6 +34,19 @@
       set<longEnum>(std::move(_aidl_value));
     }
     return STATUS_OK; }
+  #pragma clang diagnostic push
+  #pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  case deprecatedField: {
+    int32_t _aidl_value;
+    if ((_aidl_ret_status = ::ndk::AParcel_readData(_parcel, &_aidl_value)) != STATUS_OK) return _aidl_ret_status;
+    if constexpr (std::is_trivially_copyable_v<int32_t>) {
+      set<deprecatedField>(_aidl_value);
+    } else {
+      // NOLINTNEXTLINE(performance-move-const-arg)
+      set<deprecatedField>(std::move(_aidl_value));
+    }
+    return STATUS_OK; }
+  #pragma clang diagnostic pop
   }
   return STATUS_BAD_VALUE;
 }
@@ -43,6 +56,10 @@
   switch (getTag()) {
   case intEnum: return ::ndk::AParcel_writeData(_parcel, get<intEnum>());
   case longEnum: return ::ndk::AParcel_writeData(_parcel, get<longEnum>());
+  #pragma clang diagnostic push
+  #pragma clang diagnostic ignored "-Wdeprecated-declarations"
+  case deprecatedField: return ::ndk::AParcel_writeData(_parcel, get<deprecatedField>());
+  #pragma clang diagnostic pop
   }
   __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "can't reach here");
 }
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..356e9a4 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
@@ -3,6 +3,13 @@
 #include "aidl/android/aidl/tests/IDeprecated.h"
 
 #include <android/binder_ibinder.h>
+#include <cassert>
+
+#ifndef __BIONIC__
+#ifndef __assert2
+#define __assert2(a,b,c,d) ((void)0)
+#endif
+#endif
 
 namespace aidl {
 namespace android {
@@ -16,6 +23,16 @@
   ::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..fa465fa 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
@@ -3,6 +3,13 @@
 #include "aidl/android/aidl/tests/INamedCallback.h"
 
 #include <android/binder_ibinder.h>
+#include <cassert>
+
+#ifndef __BIONIC__
+#ifndef __assert2
+#define __assert2(a,b,c,d) ((void)0)
+#endif
+#endif
 
 namespace aidl {
 namespace android {
@@ -16,6 +23,19 @@
   ::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..78fcbaa 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
@@ -3,6 +3,13 @@
 #include "aidl/android/aidl/tests/INewName.h"
 
 #include <android/binder_ibinder.h>
+#include <cassert>
+
+#ifndef __BIONIC__
+#ifndef __assert2
+#define __assert2(a,b,c,d) ((void)0)
+#endif
+#endif
 
 namespace aidl {
 namespace android {
@@ -16,6 +23,19 @@
   ::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..e08fcc1 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
@@ -3,6 +3,13 @@
 #include "aidl/android/aidl/tests/IOldName.h"
 
 #include <android/binder_ibinder.h>
+#include <cassert>
+
+#ifndef __BIONIC__
+#ifndef __assert2
+#define __assert2(a,b,c,d) ((void)0)
+#endif
+#endif
 
 namespace aidl {
 namespace android {
@@ -16,6 +23,19 @@
   ::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..3b5a37d 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
@@ -3,6 +3,13 @@
 #include "aidl/android/aidl/tests/ITestService.h"
 
 #include <android/binder_ibinder.h>
+#include <cassert>
+
+#ifndef __BIONIC__
+#ifndef __assert2
+#define __assert2(a,b,c,d) ((void)0)
+#endif
+#endif
 
 namespace aidl {
 namespace android {
@@ -16,6 +23,214 @@
   ::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 GetUnionTags(const std::vector<::aidl::android::aidl::tests::Union>& in_input, std::vector<::aidl::android::aidl::tests::Union::Tag>* _aidl_return) override {
+    return _impl->GetUnionTags(in_input, _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..4fc97ab 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
@@ -3,6 +3,13 @@
 #include "aidl/android/aidl/tests/nested/INestedService.h"
 
 #include <android/binder_ibinder.h>
+#include <cassert>
+
+#ifndef __BIONIC__
+#ifndef __assert2
+#define __assert2(a,b,c,d) ((void)0)
+#endif
+#endif
 
 namespace aidl {
 namespace android {
@@ -17,6 +24,22 @@
   ::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/unions/EnumUnion.h b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/EnumUnion.h
index f52a45e..2190f50 100644
--- a/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/EnumUnion.h
+++ b/tests/golden_output/aidl-test-interface-ndk-source/gen/include/aidl/android/aidl/tests/unions/EnumUnion.h
@@ -37,11 +37,13 @@
   enum class Tag : int32_t {
     intEnum = 0,
     longEnum = 1,
+    deprecatedField __attribute__((deprecated("do not use this"))) = 2,
   };
 
   // Expose tag symbols for legacy code
   static const inline Tag intEnum = Tag::intEnum;
   static const inline Tag longEnum = Tag::longEnum;
+  static const inline Tag __attribute__((deprecated("do not use this"))) deprecatedField = Tag::deprecatedField;
 
   template<typename _Tp>
   static constexpr bool _not_self = !std::is_same_v<std::remove_cv_t<std::remove_reference_t<_Tp>>, EnumUnion>;
@@ -117,12 +119,16 @@
     switch (getTag()) {
     case intEnum: os << "intEnum: " << ::android::internal::ToString(get<intEnum>()); break;
     case longEnum: os << "longEnum: " << ::android::internal::ToString(get<longEnum>()); break;
+    #pragma clang diagnostic push
+    #pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    case deprecatedField: os << "deprecatedField: " << ::android::internal::ToString(get<deprecatedField>()); break;
+    #pragma clang diagnostic pop
     }
     os << "}";
     return os.str();
   }
 private:
-  std::variant<::aidl::android::aidl::tests::IntEnum, ::aidl::android::aidl::tests::LongEnum> _value;
+  std::variant<::aidl::android::aidl::tests::IntEnum, ::aidl::android::aidl::tests::LongEnum, int32_t> _value;
 };
 }  // namespace unions
 }  // namespace tests
@@ -134,16 +140,21 @@
 namespace aidl {
 namespace tests {
 namespace unions {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
 [[nodiscard]] static inline std::string toString(EnumUnion::Tag val) {
   switch(val) {
   case EnumUnion::Tag::intEnum:
     return "intEnum";
   case EnumUnion::Tag::longEnum:
     return "longEnum";
+  case EnumUnion::Tag::deprecatedField:
+    return "deprecatedField";
   default:
     return std::to_string(static_cast<int32_t>(val));
   }
 }
+#pragma clang diagnostic pop
 }  // namespace unions
 }  // namespace tests
 }  // namespace aidl
@@ -153,10 +164,12 @@
 namespace internal {
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wc++17-extensions"
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
 template <>
-constexpr inline std::array<aidl::android::aidl::tests::unions::EnumUnion::Tag, 2> enum_values<aidl::android::aidl::tests::unions::EnumUnion::Tag> = {
+constexpr inline std::array<aidl::android::aidl::tests::unions::EnumUnion::Tag, 3> enum_values<aidl::android::aidl::tests::unions::EnumUnion::Tag> = {
   aidl::android::aidl::tests::unions::EnumUnion::Tag::intEnum,
   aidl::android::aidl::tests::unions::EnumUnion::Tag::longEnum,
+  aidl::android::aidl::tests::unions::EnumUnion::Tag::deprecatedField,
 };
 #pragma clang diagnostic pop
 }  // namespace internal
diff --git a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/EnumUnion.rs b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/EnumUnion.rs
index 4d5fe95..6f26dcc 100644
--- a/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/EnumUnion.rs
+++ b/tests/golden_output/aidl-test-interface-rust-source/gen/android/aidl/tests/unions/EnumUnion.rs
@@ -4,6 +4,8 @@
 pub enum EnumUnion {
   IntEnum(crate::mangled::_7_android_4_aidl_5_tests_7_IntEnum),
   LongEnum(crate::mangled::_7_android_4_aidl_5_tests_8_LongEnum),
+  #[deprecated = "do not use this"]
+  DeprecatedField(i32),
 }
 impl Default for EnumUnion {
   fn default() -> Self {
@@ -21,6 +23,10 @@
         parcel.write(&1i32)?;
         parcel.write(v)
       }
+      Self::DeprecatedField(v) => {
+        parcel.write(&2i32)?;
+        parcel.write(v)
+      }
     }
   }
   fn read_from_parcel(&mut self, parcel: &binder::binder_impl::BorrowedParcel) -> std::result::Result<(), binder::StatusCode> {
@@ -36,6 +42,11 @@
         *self = Self::LongEnum(value);
         Ok(())
       }
+      2 => {
+        let value: i32 = parcel.read()?;
+        *self = Self::DeprecatedField(value);
+        Ok(())
+      }
       _ => {
         Err(binder::StatusCode::BAD_VALUE)
       }
@@ -51,9 +62,11 @@
   #![allow(non_upper_case_globals)]
   use binder::declare_binder_enum;
   declare_binder_enum! {
-    Tag : [i32; 2] {
+    Tag : [i32; 3] {
       intEnum = 0,
       longEnum = 1,
+      #[deprecated = "do not use this"]
+      deprecatedField = 2,
     }
   }
 }
diff --git a/tests/golden_output/aidl-test-versioned-interface-V1-ndk-source/gen/include/aidl/android/aidl/versioned/tests/BnFooInterface.h b/tests/golden_output/aidl-test-versioned-interface-V1-ndk-source/gen/include/aidl/android/aidl/versioned/tests/BnFooInterface.h
index f464a1e..cdb26d7 100644
--- a/tests/golden_output/aidl-test-versioned-interface-V1-ndk-source/gen/include/aidl/android/aidl/versioned/tests/BnFooInterface.h
+++ b/tests/golden_output/aidl-test-versioned-interface-V1-ndk-source/gen/include/aidl/android/aidl/versioned/tests/BnFooInterface.h
@@ -3,6 +3,13 @@
 #include "aidl/android/aidl/versioned/tests/IFooInterface.h"
 
 #include <android/binder_ibinder.h>
+#include <cassert>
+
+#ifndef __BIONIC__
+#ifndef __assert2
+#define __assert2(a,b,c,d) ((void)0)
+#endif
+#endif
 
 namespace aidl {
 namespace android {
@@ -19,6 +26,35 @@
   ::ndk::SpAIBinder createBinder() override;
 private:
 };
+class IFooInterfaceDelegator : public BnFooInterface {
+public:
+  explicit IFooInterfaceDelegator(const std::shared_ptr<IFooInterface> &impl) : _impl(impl) {
+     int32_t _impl_ver = 0;
+     if (!impl->getInterfaceVersion(&_impl_ver).isOk()) {;
+        __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Delegator failed to get version of the implementation.");
+     }
+     if (_impl_ver != IFooInterface::version) {
+        __assert2(__FILE__, __LINE__, __PRETTY_FUNCTION__, "Mismatched versions of delegator and implementation is not allowed.");
+     }
+  }
+
+  ::ndk::ScopedAStatus originalApi() override {
+    return _impl->originalApi();
+  }
+  ::ndk::ScopedAStatus acceptUnionAndReturnString(const ::aidl::android::aidl::versioned::tests::BazUnion& in_u, std::string* _aidl_return) override {
+    return _impl->acceptUnionAndReturnString(in_u, _aidl_return);
+  }
+  ::ndk::ScopedAStatus ignoreParcelablesAndRepeatInt(const ::aidl::android::aidl::versioned::tests::Foo& in_inFoo, ::aidl::android::aidl::versioned::tests::Foo* in_inoutFoo, ::aidl::android::aidl::versioned::tests::Foo* out_outFoo, int32_t in_value, int32_t* _aidl_return) override {
+    return _impl->ignoreParcelablesAndRepeatInt(in_inFoo, in_inoutFoo, out_outFoo, in_value, _aidl_return);
+  }
+  ::ndk::ScopedAStatus returnsLengthOfFooArray(const std::vector<::aidl::android::aidl::versioned::tests::Foo>& in_foos, int32_t* _aidl_return) override {
+    return _impl->returnsLengthOfFooArray(in_foos, _aidl_return);
+  }
+protected:
+private:
+  std::shared_ptr<IFooInterface> _impl;
+};
+
 }  // namespace tests
 }  // namespace versioned
 }  // 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..d6f61e1 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
@@ -3,6 +3,13 @@
 #include "aidl/android/aidl/loggable/ILoggableInterface.h"
 
 #include <android/binder_ibinder.h>
+#include <cassert>
+
+#ifndef __BIONIC__
+#ifndef __assert2
+#define __assert2(a,b,c,d) ((void)0)
+#endif
+#endif
 
 namespace aidl {
 namespace android {
@@ -31,6 +38,19 @@
   ::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