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(