Support ParcelableHolder in NDK

Bug: 146611855
Test: atest CtsNdkBinderTest aidl_unittests aidl_integration_test
Change-Id: Ic3beb6f650b484d0a67f613ca77c03f4aac6b4bf
diff --git a/aidl_language.cpp b/aidl_language.cpp
index 63a7d4f..fc4929c 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -922,10 +922,9 @@
                      << " backend does not support array of IBinder";
     return false;
   }
-  if ((lang == Options::Language::NDK || lang == Options::Language::RUST) &&
-      GetName() == "ParcelableHolder") {
-    // TODO(b/146611855): Remove it when both NDK and Rust backend support ParcelableHolder
-    AIDL_ERROR(this) << "The NDK and Rust backend does not support ParcelableHolder yet.";
+  if (lang == Options::Language::RUST && GetName() == "ParcelableHolder") {
+    // TODO(b/146611855): Remove it when Rust backend supports ParcelableHolder
+    AIDL_ERROR(this) << "The Rust backend does not support ParcelableHolder yet.";
     return false;
   }
   if ((lang == Options::Language::NDK || lang == Options::Language::RUST) && IsArray() &&
diff --git a/aidl_to_ndk.cpp b/aidl_to_ndk.cpp
index c4b1aeb..6884e89 100644
--- a/aidl_to_ndk.cpp
+++ b/aidl_to_ndk.cpp
@@ -322,6 +322,19 @@
          }),
          .nullable_array = nullptr,
      }},
+    {"ParcelableHolder",
+     TypeInfo{
+         .raw =
+             TypeInfo::Aspect{
+                 .cpp_name = "::ndk::AParcelableHolder",
+                 .value_is_cheap = false,
+                 .read_func = StandardRead("::ndk::AParcel_readParcelable"),
+                 .write_func = StandardWrite("::ndk::AParcel_writeParcelable"),
+             },
+         .array = nullptr,
+         .nullable = nullptr,
+         .nullable_array = nullptr,
+     }},
 };
 
 static TypeInfo::Aspect GetTypeAspect(const AidlTypenames& types, const AidlTypeSpecifier& aidl) {
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 60f99ef..f479f08 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -1231,10 +1231,10 @@
       "  ParcelableHolder extension;\n"
       "  ParcelableHolder extension2;\n"
       "}";
-  if (GetLanguage() == Options::Language::NDK || GetLanguage() == Options::Language::RUST) {
+  if (GetLanguage() == Options::Language::RUST) {
     EXPECT_EQ(nullptr, Parse("a/Data.aidl", extendable_parcelable, typenames_, GetLanguage()));
     EXPECT_EQ(
-        "ERROR: a/Data.aidl:2.1-19: The NDK and Rust backend does not support ParcelableHolder "
+        "ERROR: a/Data.aidl:2.1-19: The Rust backend does not support ParcelableHolder "
         "yet.\n",
         GetCapturedStderr());
   } else {
@@ -1251,10 +1251,10 @@
   EXPECT_EQ(nullptr,
             Parse("a/IFoo.aidl", parcelableholder_return_interface, typenames_, GetLanguage()));
 
-  if (GetLanguage() == Options::Language::NDK || GetLanguage() == Options::Language::RUST) {
+  if (GetLanguage() == Options::Language::RUST) {
     EXPECT_EQ(
         "ERROR: a/IFoo.aidl:2.19-23: ParcelableHolder cannot be a return type\n"
-        "ERROR: a/IFoo.aidl:2.1-19: The NDK and Rust backend does not support ParcelableHolder "
+        "ERROR: a/IFoo.aidl:2.1-19: The Rust backend does not support ParcelableHolder "
         "yet.\n",
         GetCapturedStderr());
     return;
@@ -1272,10 +1272,10 @@
   EXPECT_EQ(nullptr,
             Parse("a/IFoo.aidl", extendable_parcelable_arg_interface, typenames_, GetLanguage()));
 
-  if (GetLanguage() == Options::Language::NDK || GetLanguage() == Options::Language::RUST) {
+  if (GetLanguage() == Options::Language::RUST) {
     EXPECT_EQ(
         "ERROR: a/IFoo.aidl:2.31-34: ParcelableHolder cannot be an argument type\n"
-        "ERROR: a/IFoo.aidl:2.14-31: The NDK and Rust backend does not support ParcelableHolder "
+        "ERROR: a/IFoo.aidl:2.14-31: The Rust backend does not support ParcelableHolder "
         "yet.\n",
         GetCapturedStderr());
     return;
diff --git a/generate_ndk.cpp b/generate_ndk.cpp
index 6f4d52b..8718561 100644
--- a/generate_ndk.cpp
+++ b/generate_ndk.cpp
@@ -1000,6 +1000,10 @@
   out << "\n";
   for (const auto& variable : defined_type.GetFields()) {
     out << NdkNameOf(types, variable->GetType(), StorageMode::STACK) << " " << variable->GetName();
+    if (variable->GetType().GetName() == "ParcelableHolder") {
+      out << "{::ndk::" << (defined_type.IsVintfStability() ? "STABILITY_VINTF" : "STABILITY_LOCAL")
+          << "}";
+    }
     if (defined_type.IsFixedSize()) {
       int alignment = NdkAlignmentOf(types, variable->GetType());
       if (alignment > 0) {