blob: c3cab98e69adab0ec9d318e7f5f4497ef32a1c56 [file] [log] [blame]
/*
* 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 <memory>
#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) {}
~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<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)) {}
~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<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") {}
~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<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) {}
~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<std::unique_ptr<::android::String16>>>",
"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<std::unique_ptr<::std::string>>>",
"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<android.os.IBinder>", {"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<android.os.IBinder>", {"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<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(std::make_unique<ByteType>());
Add(std::make_unique<PrimitiveType>("int", "cstdint", "int32_t", "readInt32", "writeInt32",
"readInt32Vector", "writeInt32Vector"));
Add(std::make_unique<PrimitiveType>("long", "cstdint", "int64_t", "readInt64", "writeInt64",
"readInt64Vector", "writeInt64Vector"));
Add(std::make_unique<PrimitiveType>("float", kNoHeader, "float", "readFloat", "writeFloat",
"readFloatVector", "writeFloatVector"));
Add(std::make_unique<PrimitiveType>("double", kNoHeader, "double", "readDouble", "writeDouble",
"readDoubleVector", "writeDoubleVector"));
Add(std::make_unique<PrimitiveType>("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<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");
AddAndSetMember(&string_type_,
std::make_unique<Type>(ValidatableType::KIND_BUILT_IN, "java.lang", "String",
std::vector<std::string>{"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<std::string>{"string", "memory"}, "::std::unique_ptr<::std::string>",
"readUtf8FromUtf16", "writeUtf8AsUtf16");
Add(std::make_unique<Type>(ValidatableType::KIND_BUILT_IN, kAidlReservedTypePackage,
kUtf8InCppStringClass, std::vector<std::string>{"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<Type>(ValidatableType::KIND_BUILT_IN, "android.os", "IBinder",
std::vector<std::string>{"binder/IBinder.h"},
"::android::sp<::android::IBinder>", "readStrongBinder",
"writeStrongBinder", kNoArrayType, nullable_ibinder));
Add(std::make_unique<MapType>());
Add(std::make_unique<BinderListType>());
Add(std::make_unique<StringListType>());
Add(std::make_unique<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(std::make_unique<Type>(ValidatableType::KIND_BUILT_IN, kNoPackage, "FileDescriptor",
std::vector<std::string>{"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<std::string>{"memory", "binder/ParcelFileDescriptor.h"},
"::std::unique_ptr<::android::os::ParcelFileDescriptor>", "readParcelable",
"writeNullableParcelable");
Add(std::make_unique<Type>(ValidatableType::KIND_BUILT_IN, "android.os", "ParcelFileDescriptor",
std::vector<std::string>{"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<class VoidType>());
}
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<ParcelableType>(p, cpp_header, filename));
return true;
}
bool TypeNamespace::AddBinderType(const AidlInterface& b, const std::string& filename) {
Add(std::make_unique<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