| /* |
| * 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 <algorithm> |
| #include <iostream> |
| #include <vector> |
| |
| #include <android-base/stringprintf.h> |
| #include <android-base/strings.h> |
| |
| #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) {} |
| virtual ~VoidType() = 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<string> GetHeaders(bool is_nullable, const string& cpp_header) { |
| vector<string> 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)) {} |
| |
| virtual ~PrimitiveType() = 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)) {} |
| |
| virtual ~ByteType() = default; |
| bool IsCppPrimitive() const override { return true; } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(ByteType); |
| }; // class PrimitiveType |
| |
| static string GetCppHeader(const AidlDefinedType& defined_type) { |
| vector<string> 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") {} |
| virtual ~BinderType() = 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<string> 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) {} |
| virtual ~NullableParcelableType() = 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) {} |
| virtual ~ParcelableType() = 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") {} |
| virtual ~NullableMap() = 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() ) {} |
| virtual ~MapType() = 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<std::unique_ptr<::android::String16>>>", |
| "readString16Vector", "writeString16Vector") {} |
| virtual ~NullableStringListType() = 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()) {} |
| virtual ~StringListType() = 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<std::unique_ptr<::std::string>>>", |
| "readUtf8VectorFromUtf16Vector", "writeUtf8VectorAsUtf16Vector") {} |
| virtual ~NullableUtf8InCppStringListType() = 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()) {} |
| virtual ~Utf8InCppStringListType() = default; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(Utf8InCppStringListType); |
| }; // class Utf8InCppStringListType |
| |
| class NullableBinderListType : public Type { |
| public: |
| NullableBinderListType() |
| : Type(ValidatableType::KIND_BUILT_IN, "java.util", |
| "List<android.os.IBinder>", {"binder/IBinder.h", "vector"}, |
| "::std::unique_ptr<::std::vector<::android::sp<::android::IBinder>>>", |
| "readStrongBinderVector", "writeStrongBinderVector") {} |
| virtual ~NullableBinderListType() = default; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(NullableBinderListType); |
| }; // class NullableBinderListType |
| |
| class BinderListType : public Type { |
| public: |
| BinderListType() |
| : Type(ValidatableType::KIND_BUILT_IN, "java.util", |
| "List<android.os.IBinder>", {"binder/IBinder.h", "vector"}, |
| "::std::vector<::android::sp<::android::IBinder>>", |
| "readStrongBinderVector", "writeStrongBinderVector", |
| kNoArrayType, new NullableBinderListType()) {} |
| virtual ~BinderListType() = 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<string>& 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(new ByteType()); |
| Add(new PrimitiveType( |
| "int", |
| "cstdint", "int32_t", "readInt32", "writeInt32", |
| "readInt32Vector", "writeInt32Vector")); |
| Add(new PrimitiveType( |
| "long", |
| "cstdint", "int64_t", "readInt64", "writeInt64", |
| "readInt64Vector", "writeInt64Vector")); |
| Add(new PrimitiveType( |
| "float", |
| kNoHeader, "float", "readFloat", "writeFloat", |
| "readFloatVector", "writeFloatVector")); |
| Add(new PrimitiveType( |
| "double", |
| kNoHeader, "double", "readDouble", "writeDouble", |
| "readDoubleVector", "writeDoubleVector")); |
| Add(new PrimitiveType( |
| "boolean", |
| kNoHeader, "bool", "readBool", "writeBool", |
| "readBoolVector", "writeBoolVector")); |
| // C++11 defines the char16_t type as a built in for Unicode characters. |
| Add(new PrimitiveType( |
| "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"); |
| |
| string_type_ = new Type(ValidatableType::KIND_BUILT_IN, "java.lang", "String", |
| {"utils/String16.h"}, "::android::String16", |
| "readString16", "writeString16", |
| string_array_type, nullable_string_type); |
| Add(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, |
| {"string", "memory"}, "::std::unique_ptr<::std::string>", |
| "readUtf8FromUtf16", "writeUtf8AsUtf16"); |
| Add(new Type( |
| ValidatableType::KIND_BUILT_IN, |
| kAidlReservedTypePackage, kUtf8InCppStringClass, |
| {"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"); |
| ibinder_type_ = new Type( |
| ValidatableType::KIND_BUILT_IN, "android.os", "IBinder", |
| {"binder/IBinder.h"}, "::android::sp<::android::IBinder>", |
| "readStrongBinder", "writeStrongBinder", |
| kNoArrayType, nullable_ibinder); |
| Add(ibinder_type_); |
| |
| Add(new MapType()); |
| |
| Add(new BinderListType()); |
| Add(new StringListType()); |
| Add(new Utf8InCppStringListType()); |
| |
| 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(new Type( |
| ValidatableType::KIND_BUILT_IN, kNoPackage, "FileDescriptor", |
| {"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", |
| {"memory", "binder/ParcelFileDescriptor.h"}, |
| "::std::unique_ptr<::android::os::ParcelFileDescriptor>", "readParcelable", |
| "writeNullableParcelable"); |
| |
| Add(new Type(ValidatableType::KIND_BUILT_IN, "android.os", "ParcelFileDescriptor", |
| {"binder/ParcelFileDescriptor.h"}, "::android::os::ParcelFileDescriptor", |
| "readParcelable", "writeParcelable", pfd_vector_type, nullable_pfd_type)); |
| |
| void_type_ = new class VoidType(); |
| Add(void_type_); |
| } |
| |
| 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(new ParcelableType(p, cpp_header, filename)); |
| return true; |
| } |
| |
| bool TypeNamespace::AddBinderType(const AidlInterface& b, const std::string& filename) { |
| Add(new BinderType(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 |