Use readData/writeData APIs for NDK backend.

These new APIS dispatch the actual APIs based on types. Now the AIDL
compiler's NDK backend doens't have to handle each backend type.

This is a preparation step to add fixed-size array in AIDL. The AIDL
compiler will delegate read/write to these new APIs.

Bug: 207087196
Test: atest CtsNdkBinderTestCases aidl_integration_test
Change-Id: Ib82b86b2324ac629cca7f1c07ba2764cfa04e643
diff --git a/aidl_to_ndk.cpp b/aidl_to_ndk.cpp
index b9b632c..844ef4d 100644
--- a/aidl_to_ndk.cpp
+++ b/aidl_to_ndk.cpp
@@ -38,36 +38,10 @@
 
 // This represents a type in AIDL (e.g. 'String' which can be referenced in multiple ways)
 struct TypeInfo {
-  struct Aspect {
-    // name of the type in C++ output
-    std::string cpp_name;
-    // whether to prefer 'value type' over 'const&'
-    bool value_is_cheap;
-
-    std::function<void(const CodeGeneratorContext& c)> read_func;
-    std::function<void(const CodeGeneratorContext& c)> write_func;
-  };
-
-  // e.g. 'String'
-  Aspect raw;
-
-  // e.g. 'String[]'
-  std::shared_ptr<Aspect> array;
-
-  // note: Nullable types do not exist in Java. For most Java types, the type is split into a
-  // nullable and non-nullable variant. This is because C++ types are more usually non-nullable, but
-  // everything in Java is non-nullable. This does mean that some Java interfaces may have to have
-  // '@nullable' added to them in order to function as expected w/ the NDK. It also means that some
-  // transactions will be allowed in Java which are not allowed in C++. However, in Java, if a null
-  // is ignored, it will just result in a NullPointerException and be delivered to the other side.
-  // C++ does not have this same capacity (in Android), and so instead, we distinguish nullability
-  // in the type system.
-
-  // e.g. '@nullable String'
-  std::shared_ptr<Aspect> nullable;
-
-  // e.g. '@nullable String[]'
-  std::shared_ptr<Aspect> nullable_array;
+  // name of the type in C++ output
+  std::string cpp_name;
+  // whether to prefer 'value type' over 'const&'
+  bool value_is_cheap = false;
 };
 
 std::string ConstantValueDecorator(
@@ -76,298 +50,24 @@
   return cpp::CppConstantValueDecorator(type, raw_value, /*is_ndk=*/true);
 };
 
-static std::function<void(const CodeGeneratorContext& c)> StandardRead(const std::string& name) {
-  return [name](const CodeGeneratorContext& c) {
-    c.writer << name << "(" << c.parcel << ", " << c.var << ")";
-  };
-}
-static std::function<void(const CodeGeneratorContext& c)> StandardWrite(const std::string& name) {
-  return [name](const CodeGeneratorContext& c) {
-    c.writer << name << "(" << c.parcel << ", " << c.var << ")";
-  };
-}
-
-TypeInfo PrimitiveType(const std::string& cpp_name, const std::string& pretty_name,
-                       const std::optional<std::string>& cpp_name_for_array_opt = std::nullopt) {
-  std::string cpp_name_for_array = cpp_name_for_array_opt.value_or(cpp_name);
-  return TypeInfo{
-      .raw =
-          TypeInfo::Aspect{
-              .cpp_name = cpp_name,
-              .value_is_cheap = true,
-              .read_func = StandardRead("AParcel_read" + pretty_name),
-              .write_func = StandardWrite("AParcel_write" + pretty_name),
-          },
-      .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::vector<" + cpp_name_for_array + ">",
-          .value_is_cheap = false,
-          .read_func = StandardRead("::ndk::AParcel_readVector"),
-          .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-      }),
-      .nullable = nullptr,
-      .nullable_array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::optional<std::vector<" + cpp_name_for_array + ">>",
-          .value_is_cheap = false,
-          .read_func = StandardRead("::ndk::AParcel_readVector"),
-          .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-      }),
-  };
-}
-
-TypeInfo InterfaceTypeInfo(const AidlInterface& type) {
-  const std::string clazz = NdkFullClassName(type, cpp::ClassNames::INTERFACE);
-
-  return TypeInfo{
-      .raw =
-          TypeInfo::Aspect{
-              .cpp_name = "std::shared_ptr<" + clazz + ">",
-              .value_is_cheap = false,
-              .read_func = StandardRead(clazz + "::readFromParcel"),
-              .write_func = StandardWrite(clazz + "::writeToParcel"),
-          },
-      .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::vector<std::shared_ptr<" + clazz + ">>",
-          .value_is_cheap = false,
-          .read_func = StandardRead("::ndk::AParcel_readVector"),
-          .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-      }),
-      .nullable = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::shared_ptr<" + clazz + ">",
-          .value_is_cheap = false,
-          .read_func = StandardRead(clazz + "::readFromParcel"),
-          .write_func = StandardWrite(clazz + "::writeToParcel"),
-      }),
-      .nullable_array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::optional<std::vector<std::shared_ptr<" + clazz + ">>>",
-          .value_is_cheap = false,
-          .read_func = StandardRead("::ndk::AParcel_readVector"),
-          .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-      }),
-  };
-}
-
-TypeInfo ParcelableTypeInfo(const AidlParcelable& type, const AidlTypeSpecifier& typeSpec,
-                            const AidlTypenames& types) {
-  std::string clazz = NdkFullClassName(type, cpp::ClassNames::RAW);
-  std::string template_params = "";
-  if (typeSpec.IsGeneric()) {
-    std::vector<std::string> type_params;
-    for (const auto& parameter : typeSpec.GetTypeParameters()) {
-      type_params.push_back(NdkNameOf(types, *parameter, StorageMode::STACK));
-    }
-    clazz += base::StringPrintf("<%s>", base::Join(type_params, ", ").c_str());
-  }
-  const std::string nullable = typeSpec.IsHeapNullable() ? "std::unique_ptr" : "std::optional";
-  return TypeInfo{
-      .raw =
-          TypeInfo::Aspect{
-              .cpp_name = clazz,
-              .value_is_cheap = false,
-              .read_func = StandardRead("::ndk::AParcel_readParcelable"),
-              .write_func = StandardWrite("::ndk::AParcel_writeParcelable"),
-          },
-      .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::vector<" + clazz + ">",
-          .value_is_cheap = false,
-          .read_func = StandardRead("::ndk::AParcel_readVector"),
-          .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-      }),
-      .nullable = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = nullable + "<" + clazz + ">",
-          .value_is_cheap = false,
-          .read_func = StandardRead("::ndk::AParcel_readNullableParcelable"),
-          .write_func = StandardWrite("::ndk::AParcel_writeNullableParcelable"),
-      }),
-      .nullable_array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::optional<std::vector<std::optional<" + clazz + ">>>",
-          .value_is_cheap = false,
-          .read_func = StandardRead("::ndk::AParcel_readVector"),
-          .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-      }),
-  };
-}
-
-TypeInfo EnumDeclarationTypeInfo(const AidlEnumDeclaration& enum_decl) {
-  const std::string clazz = NdkFullClassName(enum_decl, cpp::ClassNames::RAW);
-
-  static map<std::string, std::string> kAParcelTypeNameMap = {
-      {"byte", "Byte"},
-      {"int", "Int32"},
-      {"long", "Int64"},
-  };
-  auto aparcel_name_it = kAParcelTypeNameMap.find(enum_decl.GetBackingType().GetName());
-  AIDL_FATAL_IF(aparcel_name_it == kAParcelTypeNameMap.end(), enum_decl);
-  const std::string aparcel_name = aparcel_name_it->second;
-
-  const std::string backing_type_name =
-      NdkNameOf(AidlTypenames(), enum_decl.GetBackingType(), StorageMode::STACK);
-
-  return TypeInfo{
-      .raw = TypeInfo::Aspect{
-          .cpp_name = clazz,
-          .value_is_cheap = true,
-          .read_func =
-              [aparcel_name, backing_type_name](const CodeGeneratorContext& c) {
-                c.writer << "AParcel_read" << aparcel_name << "(" << c.parcel
-                         << ", reinterpret_cast<" << backing_type_name << "*>(" << c.var << "))";
-              },
-          .write_func =
-              [aparcel_name, backing_type_name](const CodeGeneratorContext& c) {
-                c.writer << "AParcel_write" << aparcel_name << "(" << c.parcel << ", static_cast<"
-                         << backing_type_name << ">(" << c.var << "))";
-              },
-      },
-      .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::vector<" + clazz + ">",
-          .value_is_cheap = false,
-          .read_func =
-              [aparcel_name, backing_type_name](const CodeGeneratorContext& c) {
-                c.writer << "AParcel_read" << aparcel_name << "Array(" << c.parcel
-                         << ", static_cast<void*>(" << c.var
-                         << "), ndk::AParcel_stdVectorAllocator<" << backing_type_name << ">)";
-              },
-          .write_func =
-              [aparcel_name, backing_type_name](const CodeGeneratorContext& c) {
-                c.writer << "AParcel_write" << aparcel_name << "Array(" << c.parcel
-                         << ", reinterpret_cast<const " << backing_type_name << "*>(" << c.var
-                         << ".data()), " << c.var << ".size())";
-              },
-      }),
-      .nullable = nullptr,
-      .nullable_array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-          .cpp_name = "std::optional<std::vector<" + clazz + ">>",
-          .value_is_cheap = false,
-          .read_func =
-              [aparcel_name, backing_type_name](const CodeGeneratorContext& c) {
-                c.writer << "AParcel_read" << aparcel_name << "Array(" << c.parcel
-                         << ", static_cast<void*>(" << c.var
-                         << "), ndk::AParcel_nullableStdVectorAllocator<" << backing_type_name
-                         << ">)";
-              },
-          .write_func =
-              [aparcel_name, backing_type_name](const CodeGeneratorContext& c) {
-                // If the var exists, use writeArray with data() and size().
-                // Otherwise, use nullptr and -1.
-                c.writer << "AParcel_write" << aparcel_name << "Array(" << c.parcel << ", ("
-                         << c.var << " ? reinterpret_cast<const " << backing_type_name << "*>("
-                         << c.var << "->data()) : nullptr)"
-                         << ", (" << c.var << " ? " << c.var << "->size() : -1))";
-              },
-      }),
-  };
-}
-
 // map from AIDL built-in type name to the corresponding Ndk type info
 static map<std::string, TypeInfo> kNdkTypeInfoMap = {
-    {"void", TypeInfo{{"void", true, nullptr, nullptr}, nullptr, nullptr, nullptr}},
-    {"boolean", PrimitiveType("bool", "Bool")},
-    {"byte", PrimitiveType("int8_t", "Byte", "uint8_t")},
-    {"char", PrimitiveType("char16_t", "Char")},
-    {"int", PrimitiveType("int32_t", "Int32")},
-    {"long", PrimitiveType("int64_t", "Int64")},
-    {"float", PrimitiveType("float", "Float")},
-    {"double", PrimitiveType("double", "Double")},
-    {"String",
-     TypeInfo{
-         .raw =
-             TypeInfo::Aspect{
-                 .cpp_name = "std::string",
-                 .value_is_cheap = false,
-                 .read_func = StandardRead("::ndk::AParcel_readString"),
-                 .write_func = StandardWrite("::ndk::AParcel_writeString"),
-             },
-         .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-             .cpp_name = "std::vector<std::string>",
-             .value_is_cheap = false,
-             .read_func = StandardRead("::ndk::AParcel_readVector"),
-             .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-         }),
-         .nullable = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-             .cpp_name = "std::optional<std::string>",
-             .value_is_cheap = false,
-             .read_func = StandardRead("::ndk::AParcel_readString"),
-             .write_func = StandardWrite("::ndk::AParcel_writeString"),
-         }),
-         .nullable_array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-             .cpp_name = "std::optional<std::vector<std::optional<std::string>>>",
-             .value_is_cheap = false,
-             .read_func = StandardRead("::ndk::AParcel_readVector"),
-             .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-         }),
-     }},
+    {"void", {"void", true}},
+    {"boolean", {"bool", true}},
+    {"byte", {"int8_t", true}},
+    {"char", {"char16_t", true}},
+    {"int", {"int32_t", true}},
+    {"long", {"int64_t", true}},
+    {"float", {"float", true}},
+    {"double", {"double", true}},
+    {"String", {"std::string"}},
     // TODO(b/136048684) {"Map", ""},
-    {"IBinder",
-     TypeInfo{
-         .raw =
-             TypeInfo::Aspect{
-                 .cpp_name = "::ndk::SpAIBinder",
-                 .value_is_cheap = false,
-                 .read_func = StandardRead("::ndk::AParcel_readRequiredStrongBinder"),
-                 .write_func = StandardRead("::ndk::AParcel_writeRequiredStrongBinder"),
-             },
-         .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-             .cpp_name = "std::vector<::ndk::SpAIBinder>",
-             .value_is_cheap = false,
-             .read_func = StandardRead("::ndk::AParcel_readVector"),
-             .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-         }),
-         .nullable = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-             .cpp_name = "::ndk::SpAIBinder",
-             .value_is_cheap = false,
-             .read_func = StandardRead("::ndk::AParcel_readNullableStrongBinder"),
-             .write_func = StandardRead("::ndk::AParcel_writeNullableStrongBinder"),
-         }),
-         .nullable_array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-             .cpp_name = "std::optional<std::vector<::ndk::SpAIBinder>>",
-             .value_is_cheap = false,
-             .read_func = StandardRead("::ndk::AParcel_readVector"),
-             .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-         }),
-     }},
-    {"ParcelFileDescriptor",
-     TypeInfo{
-         .raw =
-             TypeInfo::Aspect{
-                 .cpp_name = "::ndk::ScopedFileDescriptor",
-                 .value_is_cheap = false,
-                 .read_func = StandardRead("::ndk::AParcel_readRequiredParcelFileDescriptor"),
-                 .write_func = StandardRead("::ndk::AParcel_writeRequiredParcelFileDescriptor"),
-             },
-         .array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-             .cpp_name = "std::vector<::ndk::ScopedFileDescriptor>",
-             .value_is_cheap = false,
-             .read_func = StandardRead("::ndk::AParcel_readVector"),
-             .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-         }),
-         .nullable = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-             .cpp_name = "::ndk::ScopedFileDescriptor",
-             .value_is_cheap = false,
-             .read_func = StandardRead("::ndk::AParcel_readNullableParcelFileDescriptor"),
-             .write_func = StandardRead("::ndk::AParcel_writeNullableParcelFileDescriptor"),
-         }),
-         .nullable_array = std::shared_ptr<TypeInfo::Aspect>(new TypeInfo::Aspect{
-             .cpp_name = "std::optional<std::vector<::ndk::ScopedFileDescriptor>>",
-             .value_is_cheap = false,
-             .read_func = StandardRead("::ndk::AParcel_readVector"),
-             .write_func = StandardWrite("::ndk::AParcel_writeVector"),
-         }),
-     }},
-    {"ParcelableHolder",
-     TypeInfo{
-         .raw =
-             TypeInfo::Aspect{
-                 .cpp_name = "::ndk::AParcelableHolder",
-                 .value_is_cheap = false,
-                 .read_func = StandardRead("::ndk::AParcel_readParcelable"),
-                 .write_func = StandardWrite("::ndk::AParcel_writeParcelable"),
-             },
-         .array = nullptr,
-         .nullable = nullptr,
-         .nullable_array = nullptr,
-     }},
+    {"IBinder", {"::ndk::SpAIBinder"}},
+    {"ParcelFileDescriptor", {"::ndk::ScopedFileDescriptor"}},
+    {"ParcelableHolder", {"::ndk::AParcelableHolder"}},
 };
 
-static TypeInfo GetTypeInfo(const AidlTypenames& types, const AidlTypeSpecifier& aidl) {
+static TypeInfo GetBaseTypeInfo(const AidlTypenames& types, const AidlTypeSpecifier& aidl) {
   auto& aidl_name = aidl.GetName();
 
   if (AidlTypenames::IsBuiltinTypename(aidl_name)) {
@@ -379,55 +79,96 @@
   AIDL_FATAL_IF(type == nullptr, aidl_name) << "Unrecognized type.";
 
   if (const AidlInterface* intf = type->AsInterface(); intf != nullptr) {
-    return InterfaceTypeInfo(*intf);
+    const std::string clazz = NdkFullClassName(*intf, cpp::ClassNames::INTERFACE);
+    return TypeInfo{"std::shared_ptr<" + clazz + ">"};
   } else if (const AidlParcelable* parcelable = type->AsParcelable(); parcelable != nullptr) {
-    return ParcelableTypeInfo(*parcelable, aidl, types);
+    std::string clazz = NdkFullClassName(*parcelable, cpp::ClassNames::RAW);
+    std::string template_params = "";
+    if (aidl.IsGeneric()) {
+      std::vector<std::string> type_params;
+      for (const auto& parameter : aidl.GetTypeParameters()) {
+        type_params.push_back(NdkNameOf(types, *parameter, StorageMode::STACK));
+      }
+      clazz += base::StringPrintf("<%s>", base::Join(type_params, ", ").c_str());
+    }
+    return TypeInfo{clazz};
   } else if (const AidlEnumDeclaration* enum_decl = type->AsEnumDeclaration();
              enum_decl != nullptr) {
-    return EnumDeclarationTypeInfo(*enum_decl);
+    const std::string clazz = NdkFullClassName(*enum_decl, cpp::ClassNames::RAW);
+    return TypeInfo{clazz, true};
   } else {
     AIDL_FATAL(aidl_name) << "Unrecognized type";
   }
 }
 
-static TypeInfo::Aspect GetTypeAspect(const AidlTypenames& types, const AidlTypeSpecifier& aidl) {
+static TypeInfo WrapNullableType(TypeInfo info, bool is_heap) {
+  if (is_heap) {
+    info.cpp_name = "std::unique_ptr<" + info.cpp_name + ">";
+  } else {
+    info.cpp_name = "std::optional<" + info.cpp_name + ">";
+  }
+  info.value_is_cheap = false;
+  return info;
+}
+
+static TypeInfo WrapArrayType(TypeInfo info) {
+  if (info.cpp_name == "int8_t") {
+    info.cpp_name = "std::vector<uint8_t>";
+  } else {
+    info.cpp_name = "std::vector<" + info.cpp_name + ">";
+  }
+  info.value_is_cheap = false;
+  return info;
+}
+
+static bool ShouldWrapNullable(const AidlTypenames& types, const std::string& aidl_name) {
+  if (AidlTypenames::IsPrimitiveTypename(aidl_name) || aidl_name == "ParcelableHolder" ||
+      aidl_name == "IBinder" || aidl_name == "ParcelFileDescriptor") {
+    return false;
+  }
+  if (auto defined_type = types.TryGetDefinedType(aidl_name); defined_type) {
+    if (defined_type->AsEnumDeclaration() || defined_type->AsInterface()) {
+      return false;
+    }
+  }
+  return true;
+}
+
+static TypeInfo GetTypeInfo(const AidlTypenames& types, const AidlTypeSpecifier& aidl) {
   AIDL_FATAL_IF(!aidl.IsResolved(), aidl) << aidl.ToString();
-  auto& aidl_name = aidl.GetName();
+  // Keep original @nullable to handle the case of List<T>. "@nullable" is attached to "List" not
+  // "T"
+  bool is_nullable = aidl.IsNullable();
+  bool is_array = aidl.IsArray();
+  const AidlTypeSpecifier* element_type = &aidl;
 
-  TypeInfo info;
-
-  // TODO(b/136048684): For now, List<T> is converted to T[].(Both are using vector<T>)
-  if (aidl_name == "List") {
+  // List<T> is converted to T[].
+  if (aidl.GetName() == "List") {
     AIDL_FATAL_IF(!aidl.IsGeneric(), aidl) << "List must be generic type.";
     AIDL_FATAL_IF(aidl.GetTypeParameters().size() != 1, aidl)
         << "List can accept only one type parameter.";
     const auto& type_param = *aidl.GetTypeParameters()[0];
     // TODO(b/136048684) AIDL doesn't support nested type parameter yet.
     AIDL_FATAL_IF(type_param.IsGeneric(), aidl) << "AIDL doesn't support nested type parameter";
-
-    info = GetTypeInfo(types, type_param);
-  } else {
-    info = GetTypeInfo(types, aidl);
+    // Treat "List<T>" as an array of T.
+    is_array = true;
+    element_type = &type_param;
   }
 
-  if (aidl.IsArray() || aidl_name == "List") {
-    if (aidl.IsNullable()) {
-      AIDL_FATAL_IF(info.nullable_array == nullptr, aidl)
-          << "Unsupported type in NDK Backend: " << aidl.ToString();
-      return *info.nullable_array;
+  TypeInfo info = GetBaseTypeInfo(types, *element_type);
+
+  if (is_nullable && ShouldWrapNullable(types, element_type->GetName())) {
+    info = WrapNullableType(info, aidl.IsHeapNullable());
+  }
+  if (is_array) {
+    info = WrapArrayType(info);
+    // @nullable is applied to both the element type and the vector type.
+    if (is_nullable) {
+      AIDL_FATAL_IF(aidl.IsHeapNullable(), aidl) << "Array/List can't be @nullable(heap=true)";
+      info = WrapNullableType(info, /*is_heap=*/false);
     }
-    AIDL_FATAL_IF(info.array == nullptr, aidl)
-        << "Unsupported type in NDK Backend: " << aidl.ToString();
-    return *info.array;
   }
-
-  if (aidl.IsNullable()) {
-    AIDL_FATAL_IF(info.nullable == nullptr, aidl)
-        << "Unsupported type in NDK Backend: " << aidl.ToString();
-    return *info.nullable;
-  }
-
-  return info.raw;
+  return info;
 }
 
 std::string NdkFullClassName(const AidlDefinedType& type, cpp::ClassNames name) {
@@ -440,7 +181,7 @@
 }
 
 std::string NdkNameOf(const AidlTypenames& types, const AidlTypeSpecifier& aidl, StorageMode mode) {
-  TypeInfo::Aspect aspect = GetTypeAspect(types, aidl);
+  TypeInfo aspect = GetTypeInfo(types, aidl);
 
   switch (mode) {
     case StorageMode::STACK:
@@ -459,13 +200,19 @@
 }
 
 void WriteToParcelFor(const CodeGeneratorContext& c) {
-  TypeInfo::Aspect aspect = GetTypeAspect(c.types, c.type);
-  aspect.write_func(c);
+  if (c.type.IsNullable()) {
+    c.writer << "::ndk::AParcel_writeNullableData(" << c.parcel << ", " << c.var << ")";
+  } else {
+    c.writer << "::ndk::AParcel_writeData(" << c.parcel << ", " << c.var << ")";
+  }
 }
 
 void ReadFromParcelFor(const CodeGeneratorContext& c) {
-  TypeInfo::Aspect aspect = GetTypeAspect(c.types, c.type);
-  aspect.read_func(c);
+  if (c.type.IsNullable()) {
+    c.writer << "::ndk::AParcel_readNullableData(" << c.parcel << ", " << c.var << ")";
+  } else {
+    c.writer << "::ndk::AParcel_readData(" << c.parcel << ", " << c.var << ")";
+  }
 }
 
 std::string NdkArgList(