/* * Copyright (C) 2015, 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 "type_cpp.h" #include #include #include #include #include #include #include "logging.h" using std::string; using std::vector; using android::base::Join; using android::base::StringPrintf; namespace android { namespace aidl { namespace cpp { namespace { const char kNoPackage[] = ""; const char kNoHeader[] = ""; const char kNoValidMethod[] = ""; Type* const kNoArrayType = nullptr; Type* const kNoNullableType = nullptr; class VoidType : public Type { public: VoidType() : Type(ValidatableType::KIND_BUILT_IN, kNoPackage, "void", {}, "void", kNoValidMethod, kNoValidMethod) {} ~VoidType() override = default; bool CanWriteToParcel() const override { return false; } }; // class VoidType class CppArrayType : public Type { public: CppArrayType(int kind, // from ValidatableType const std::string& package, const string& underlying_aidl_type, const string& cpp_header, const string& underlying_cpp_type, const string& underlying_cpp_type_nulllable, const string& read_method, const string& write_method, bool is_nullable, const string& src_file_name = "") : Type(kind, package, underlying_aidl_type + "[]", GetHeaders(is_nullable, cpp_header), GetCppType(is_nullable, underlying_cpp_type), read_method, write_method, kNoArrayType, (is_nullable) ? kNoNullableType // All arrays are nullable. : new CppArrayType(kind, package, underlying_aidl_type, cpp_header, underlying_cpp_type_nulllable, underlying_cpp_type_nulllable, read_method, write_method, true), src_file_name) {} private: static vector GetHeaders(bool is_nullable, const string& cpp_header) { vector result = {"vector"}; if (is_nullable) { result.push_back("memory"); } if (!cpp_header.empty()) { result.push_back(cpp_header); } return result; } static string GetCppType(bool is_nullable, const string& underlying_cpp_type) { if (is_nullable) return StringPrintf("::std::unique_ptr<::std::vector<%s>>", underlying_cpp_type.c_str()); return StringPrintf("::std::vector<%s>", underlying_cpp_type.c_str()); } DISALLOW_COPY_AND_ASSIGN(CppArrayType); }; // class CppArrayType class PrimitiveType : public Type { public: PrimitiveType(const std::string& aidl_type, const std::string& header, const std::string& cpp_type, const std::string& read_method, const std::string& write_method, const std::string& read_array_method, const std::string& write_array_method) : Type(ValidatableType::KIND_BUILT_IN, kNoPackage, aidl_type, {header}, cpp_type, read_method, write_method, new CppArrayType(ValidatableType::KIND_BUILT_IN, kNoPackage, aidl_type, header, cpp_type, cpp_type, read_array_method, write_array_method, false)) {} ~PrimitiveType() override = default; bool IsCppPrimitive() const override { return true; } private: DISALLOW_COPY_AND_ASSIGN(PrimitiveType); }; // class PrimitiveType // Unfortunately, bytes in Java are signed. However, most C authors would // say that a byte is not in fact signed. Compromise: customize this otherwise // normal primitive to use signed single bytes, but unsigned byte arrays. class ByteType : public Type { public: ByteType() : Type(ValidatableType::KIND_BUILT_IN, kNoPackage, "byte", {"cstdint"}, "int8_t", "readByte", "writeByte", new CppArrayType(ValidatableType::KIND_BUILT_IN, kNoPackage, "byte", "cstdint", "uint8_t", "uint8_t", "readByteVector", "writeByteVector", false)) {} ~ByteType() override = default; bool IsCppPrimitive() const override { return true; } private: DISALLOW_COPY_AND_ASSIGN(ByteType); }; // class PrimitiveType static string GetCppHeader(const AidlDefinedType& defined_type) { vector name = defined_type.GetSplitPackage(); name.push_back(defined_type.GetName()); return Join(name, '/') + ".h"; } class BinderType : public Type { public: BinderType(const AidlInterface& interface, const std::string& src_file_name) : BinderType(interface, src_file_name, new BinderType(interface, src_file_name, kNoNullableType, "readNullableStrongBinder"), "readStrongBinder") {} ~BinderType() override = default; string WriteCast(const string& val) const override { return write_cast_ + "(" + val + ")"; } private: BinderType(const AidlInterface& interface, const std::string& src_file_name, Type* nullable_type, const std::string& read) : Type(ValidatableType::KIND_GENERATED, interface.GetPackage(), interface.GetName(), {GetCppHeader(interface)}, GetCppName(interface), read, "writeStrongBinder", kNoArrayType, nullable_type, src_file_name), write_cast_(GetRawCppName(interface) + "::asBinder") {} static string GetCppName(const AidlInterface& interface) { return "::android::sp<" + GetRawCppName(interface) + ">"; } static string GetRawCppName(const AidlInterface& interface) { vector name = interface.GetSplitPackage(); string ret; name.push_back(interface.GetName()); for (const auto& term : name) { ret += "::" + term; } return ret; } std::string write_cast_; }; class NullableParcelableType : public Type { public: NullableParcelableType(const AidlParcelable& parcelable, const std::string& cpp_header, const std::string& src_file_name) : Type(ValidatableType::KIND_PARCELABLE, parcelable.GetPackage(), parcelable.GetName(), {cpp_header}, GetCppName(parcelable), "readParcelable", "writeNullableParcelable", kNoArrayType, kNoNullableType, src_file_name) {} ~NullableParcelableType() override = default; private: static string GetCppName(const AidlParcelable& parcelable) { return "::std::unique_ptr<::" + Join(parcelable.GetSplitPackage(), "::") + "::" + parcelable.GetCppName() + ">"; } }; class ParcelableType : public Type { public: ParcelableType(const AidlParcelable& parcelable, const std::string& cpp_header, const std::string& src_file_name) : Type(ValidatableType::KIND_PARCELABLE, parcelable.GetPackage(), parcelable.GetName(), {cpp_header}, GetCppName(parcelable), "readParcelable", "writeParcelable", new CppArrayType(ValidatableType::KIND_PARCELABLE, parcelable.GetPackage(), parcelable.GetName(), cpp_header, GetCppName(parcelable), GetCppName(parcelable), "readParcelableVector", "writeParcelableVector", false, src_file_name), new NullableParcelableType(parcelable, cpp_header, src_file_name), src_file_name) {} ~ParcelableType() override = default; private: static string GetCppName(const AidlParcelable& parcelable) { return "::" + Join(parcelable.GetSplitPackage(), "::") + "::" + parcelable.GetCppName(); } }; class NullableMap : public Type { public: NullableMap() : Type(ValidatableType::KIND_BUILT_IN, "java.util", "Map", {"binder/Map.h", "binder/Value.h"}, "::std::unique_ptr<::android::binder::Map>", "readNullableMap", "writeNullableMap") {} ~NullableMap() override = default; }; class MapType : public Type { public: MapType() : Type(ValidatableType::KIND_BUILT_IN, "java.util", "Map", {"binder/Map.h","binder/Value.h"}, "::android::binder::Map", "readMap", "writeMap", kNoArrayType, new NullableMap() ) {} ~MapType() override = default; private: DISALLOW_COPY_AND_ASSIGN(MapType); }; // class MapType class NullableStringListType : public Type { public: NullableStringListType() : Type(ValidatableType::KIND_BUILT_IN, "java.util", "List<" + string(kStringCanonicalName) + ">", {"utils/String16.h", "memory", "vector"}, "::std::unique_ptr<::std::vector>>", "readString16Vector", "writeString16Vector") {} ~NullableStringListType() override = default; private: DISALLOW_COPY_AND_ASSIGN(NullableStringListType); }; // class NullableStringListType class StringListType : public Type { public: StringListType() : Type(ValidatableType::KIND_BUILT_IN, "java.util", "List<" + string(kStringCanonicalName) + ">", {"utils/String16.h", "vector"}, "::std::vector<::android::String16>", "readString16Vector", "writeString16Vector", kNoArrayType, new NullableStringListType()) {} ~StringListType() override = default; private: DISALLOW_COPY_AND_ASSIGN(StringListType); }; // class StringListType class NullableUtf8InCppStringListType : public Type { public: NullableUtf8InCppStringListType() : Type(ValidatableType::KIND_BUILT_IN, "java.util", "List<" + string(kUtf8InCppStringCanonicalName) + ">", {"memory", "string", "vector"}, "::std::unique_ptr<::std::vector>>", "readUtf8VectorFromUtf16Vector", "writeUtf8VectorAsUtf16Vector") {} ~NullableUtf8InCppStringListType() override = default; private: DISALLOW_COPY_AND_ASSIGN(NullableUtf8InCppStringListType); }; // class NullableUtf8InCppStringListType class Utf8InCppStringListType : public Type { public: Utf8InCppStringListType() : Type(ValidatableType::KIND_BUILT_IN, "java.util", "List<" + string(kUtf8InCppStringCanonicalName) + ">", {"string", "vector"}, "::std::vector<::std::string>", "readUtf8VectorFromUtf16Vector", "writeUtf8VectorAsUtf16Vector", kNoArrayType, new NullableUtf8InCppStringListType()) {} ~Utf8InCppStringListType() override = default; private: DISALLOW_COPY_AND_ASSIGN(Utf8InCppStringListType); }; // class Utf8InCppStringListType class NullableBinderListType : public Type { public: NullableBinderListType() : Type(ValidatableType::KIND_BUILT_IN, "java.util", "List", {"binder/IBinder.h", "vector"}, "::std::unique_ptr<::std::vector<::android::sp<::android::IBinder>>>", "readStrongBinderVector", "writeStrongBinderVector") {} ~NullableBinderListType() override = default; private: DISALLOW_COPY_AND_ASSIGN(NullableBinderListType); }; // class NullableBinderListType class BinderListType : public Type { public: BinderListType() : Type(ValidatableType::KIND_BUILT_IN, "java.util", "List", {"binder/IBinder.h", "vector"}, "::std::vector<::android::sp<::android::IBinder>>", "readStrongBinderVector", "writeStrongBinderVector", kNoArrayType, new NullableBinderListType()) {} ~BinderListType() override = default; private: DISALLOW_COPY_AND_ASSIGN(BinderListType); }; // class BinderListType } // namespace Type::Type(int kind, const std::string& package, const std::string& aidl_type, const vector& headers, const string& cpp_type, const string& read_method, const string& write_method, Type* array_type, Type* nullable_type, const string& src_file_name, int line) : ValidatableType(kind, package, aidl_type, src_file_name, line), headers_(headers), aidl_type_(aidl_type), cpp_type_(cpp_type), parcel_read_method_(read_method), parcel_write_method_(write_method), array_type_(array_type), nullable_type_(nullable_type) {} bool Type::CanWriteToParcel() const { return true; } void TypeNamespace::Init() { Add(std::make_unique()); Add(std::make_unique("int", "cstdint", "int32_t", "readInt32", "writeInt32", "readInt32Vector", "writeInt32Vector")); Add(std::make_unique("long", "cstdint", "int64_t", "readInt64", "writeInt64", "readInt64Vector", "writeInt64Vector")); Add(std::make_unique("float", kNoHeader, "float", "readFloat", "writeFloat", "readFloatVector", "writeFloatVector")); Add(std::make_unique("double", kNoHeader, "double", "readDouble", "writeDouble", "readDoubleVector", "writeDoubleVector")); Add(std::make_unique("boolean", kNoHeader, "bool", "readBool", "writeBool", "readBoolVector", "writeBoolVector")); // C++11 defines the char16_t type as a built in for Unicode characters. Add(std::make_unique("char", kNoHeader, "char16_t", "readChar", "writeChar", "readCharVector", "writeCharVector")); Type* string_array_type = new CppArrayType( ValidatableType::KIND_BUILT_IN, "java.lang", "String", "utils/String16.h", "::android::String16", "::std::unique_ptr<::android::String16>", "readString16Vector", "writeString16Vector", false); Type* nullable_string_type = new Type(ValidatableType::KIND_BUILT_IN, "java.lang", "String", {"memory", "utils/String16.h"}, "::std::unique_ptr<::android::String16>", "readString16", "writeString16"); AddAndSetMember(&string_type_, std::make_unique(ValidatableType::KIND_BUILT_IN, "java.lang", "String", std::vector{"utils/String16.h"}, "::android::String16", "readString16", "writeString16", string_array_type, nullable_string_type)); using ::android::aidl::kAidlReservedTypePackage; using ::android::aidl::kUtf8InCppStringClass; // This type is a Utf16 string in the parcel, but deserializes to // a std::string in Utf8 format when we use it in C++. Type* cpp_utf8_string_array = new CppArrayType( ValidatableType::KIND_BUILT_IN, kAidlReservedTypePackage, kUtf8InCppStringClass, "string", "::std::string", "::std::unique_ptr<::std::string>", "readUtf8VectorFromUtf16Vector", "writeUtf8VectorAsUtf16Vector", false); Type* nullable_cpp_utf8_string_type = new Type(ValidatableType::KIND_BUILT_IN, kAidlReservedTypePackage, kUtf8InCppStringClass, std::vector{"string", "memory"}, "::std::unique_ptr<::std::string>", "readUtf8FromUtf16", "writeUtf8AsUtf16"); Add(std::make_unique(ValidatableType::KIND_BUILT_IN, kAidlReservedTypePackage, kUtf8InCppStringClass, std::vector{"string"}, "::std::string", "readUtf8FromUtf16", "writeUtf8AsUtf16", cpp_utf8_string_array, nullable_cpp_utf8_string_type)); Type* nullable_ibinder = new Type( ValidatableType::KIND_BUILT_IN, "android.os", "IBinder", {"binder/IBinder.h"}, "::android::sp<::android::IBinder>", "readNullableStrongBinder", "writeStrongBinder"); AddAndSetMember(&ibinder_type_, std::make_unique(ValidatableType::KIND_BUILT_IN, "android.os", "IBinder", std::vector{"binder/IBinder.h"}, "::android::sp<::android::IBinder>", "readStrongBinder", "writeStrongBinder", kNoArrayType, nullable_ibinder)); Add(std::make_unique()); Add(std::make_unique()); Add(std::make_unique()); Add(std::make_unique()); Type* fd_vector_type = new CppArrayType( ValidatableType::KIND_BUILT_IN, kNoPackage, "FileDescriptor", "android-base/unique_fd.h", "::android::base::unique_fd", "::android::base::unique_fd", "readUniqueFileDescriptorVector", "writeUniqueFileDescriptorVector", false); Add(std::make_unique(ValidatableType::KIND_BUILT_IN, kNoPackage, "FileDescriptor", std::vector{"android-base/unique_fd.h"}, "::android::base::unique_fd", "readUniqueFileDescriptor", "writeUniqueFileDescriptor", fd_vector_type)); Type* pfd_vector_type = new CppArrayType(ValidatableType::KIND_BUILT_IN, "android.os", "ParcelFileDescriptor", "binder/ParcelFileDescriptor.h", "::android::os::ParcelFileDescriptor", "::android::os::ParcelFileDescriptor", "readParcelableVector", "writeParcelableVector", false); Type* nullable_pfd_type = new Type(ValidatableType::KIND_BUILT_IN, "android.os", "ParcelFileDescriptor", std::vector{"memory", "binder/ParcelFileDescriptor.h"}, "::std::unique_ptr<::android::os::ParcelFileDescriptor>", "readParcelable", "writeNullableParcelable"); Add(std::make_unique(ValidatableType::KIND_BUILT_IN, "android.os", "ParcelFileDescriptor", std::vector{"binder/ParcelFileDescriptor.h"}, "::android::os::ParcelFileDescriptor", "readParcelable", "writeParcelable", pfd_vector_type, nullable_pfd_type)); // Qualify VoidType so we don't get collisions with the VoidType method AddAndSetMember(&void_type_, std::make_unique()); } bool TypeNamespace::AddParcelableType(const AidlParcelable& p, const std::string& filename) { const std::string cpp_header = p.AsStructuredParcelable() ? GetCppHeader(p) : p.GetCppHeader(); if (cpp_header.empty()) { AIDL_ERROR(p) << "Parcelable " << p.GetCanonicalName() << " has no C++ header defined."; return false; } Add(std::make_unique(p, cpp_header, filename)); return true; } bool TypeNamespace::AddBinderType(const AidlInterface& b, const std::string& filename) { Add(std::make_unique(b, filename)); return true; } bool TypeNamespace::AddListType(const std::string& type_name) { const Type* contained_type = FindTypeByCanonicalName(type_name); if (!contained_type) { LOG(ERROR) << "Cannot create List<" << type_name << "> because contained " "type cannot be found or is invalid."; return false; } if (contained_type->IsCppPrimitive()) { LOG(ERROR) << "Cannot create List<" << type_name << "> because contained " "type is a primitive in Java and Java List cannot hold " "primitives."; return false; } if (contained_type->CanonicalName() == kStringCanonicalName || contained_type->CanonicalName() == kUtf8InCppStringCanonicalName || contained_type == IBinderType()) { return true; } // TODO Support lists of parcelables b/23600712 LOG(ERROR) << "aidl-cpp does not yet support List<" << type_name << ">"; return false; } bool TypeNamespace::AddMapType(const std::string& /* key_type_name */, const std::string& /* value_type_name */) { // TODO Support list types b/25242025 LOG(ERROR) << "aidl does not implement support for typed maps!"; return false; } const ValidatableType* TypeNamespace::GetArgType(const AidlArgument& a, int arg_index, const AidlDefinedType& context) const { return ::android::aidl::TypeNamespace::GetArgType(a, arg_index, context); } } // namespace cpp } // namespace aidl } // namespace android