1 /*
2 * Copyright (C) 2015, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "type_cpp.h"
18
19 #include <algorithm>
20 #include <iostream>
21 #include <memory>
22 #include <vector>
23
24 #include <android-base/stringprintf.h>
25 #include <android-base/strings.h>
26
27 #include "logging.h"
28
29 using std::string;
30 using std::vector;
31
32 using android::base::Join;
33 using android::base::StringPrintf;
34
35 namespace android {
36 namespace aidl {
37 namespace cpp {
38 namespace {
39
40 const char kNoPackage[] = "";
41 const char kNoHeader[] = "";
42 const char kNoValidMethod[] = "";
43 Type* const kNoArrayType = nullptr;
44 Type* const kNoNullableType = nullptr;
45
46 class VoidType : public Type {
47 public:
VoidType()48 VoidType() : Type(ValidatableType::KIND_BUILT_IN, kNoPackage, "void",
49 {}, "void", kNoValidMethod, kNoValidMethod) {}
50 ~VoidType() override = default;
CanWriteToParcel() const51 bool CanWriteToParcel() const override { return false; }
52 }; // class VoidType
53
54 class CppArrayType : public Type {
55 public:
CppArrayType(int kind,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="")56 CppArrayType(int kind, // from ValidatableType
57 const std::string& package,
58 const string& underlying_aidl_type,
59 const string& cpp_header,
60 const string& underlying_cpp_type,
61 const string& underlying_cpp_type_nulllable,
62 const string& read_method,
63 const string& write_method,
64 bool is_nullable,
65 const string& src_file_name = "")
66 : Type(kind, package,
67 underlying_aidl_type + "[]",
68 GetHeaders(is_nullable, cpp_header),
69 GetCppType(is_nullable, underlying_cpp_type),
70 read_method, write_method, kNoArrayType,
71 (is_nullable)
72 ? kNoNullableType
73 // All arrays are nullable.
74 : new CppArrayType(kind, package, underlying_aidl_type,
75 cpp_header, underlying_cpp_type_nulllable,
76 underlying_cpp_type_nulllable,
77 read_method, write_method, true),
78 src_file_name) {}
79
80 private:
GetHeaders(bool is_nullable,const string & cpp_header)81 static vector<string> GetHeaders(bool is_nullable, const string& cpp_header) {
82 vector<string> result = {"vector"};
83 if (is_nullable) {
84 result.push_back("memory");
85 }
86 if (!cpp_header.empty()) {
87 result.push_back(cpp_header);
88 }
89 return result;
90 }
91
GetCppType(bool is_nullable,const string & underlying_cpp_type)92 static string GetCppType(bool is_nullable,
93 const string& underlying_cpp_type) {
94 if (is_nullable)
95 return StringPrintf("::std::unique_ptr<::std::vector<%s>>",
96 underlying_cpp_type.c_str());
97 return StringPrintf("::std::vector<%s>",
98 underlying_cpp_type.c_str());
99 }
100
101 DISALLOW_COPY_AND_ASSIGN(CppArrayType);
102 }; // class CppArrayType
103
104 class PrimitiveType : public Type {
105 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)106 PrimitiveType(const std::string& aidl_type,
107 const std::string& header,
108 const std::string& cpp_type,
109 const std::string& read_method,
110 const std::string& write_method,
111 const std::string& read_array_method,
112 const std::string& write_array_method)
113 : Type(ValidatableType::KIND_BUILT_IN, kNoPackage, aidl_type, {header},
114 cpp_type, read_method, write_method,
115 new CppArrayType(ValidatableType::KIND_BUILT_IN, kNoPackage,
116 aidl_type, header, cpp_type, cpp_type,
117 read_array_method, write_array_method,
118 false)) {}
119
120 ~PrimitiveType() override = default;
IsCppPrimitive() const121 bool IsCppPrimitive() const override { return true; }
122
123 private:
124 DISALLOW_COPY_AND_ASSIGN(PrimitiveType);
125 }; // class PrimitiveType
126
127 // Unfortunately, bytes in Java are signed. However, most C authors would
128 // say that a byte is not in fact signed. Compromise: customize this otherwise
129 // normal primitive to use signed single bytes, but unsigned byte arrays.
130 class ByteType : public Type {
131 public:
ByteType()132 ByteType()
133 : Type(ValidatableType::KIND_BUILT_IN, kNoPackage, "byte",
134 {"cstdint"}, "int8_t", "readByte", "writeByte",
135 new CppArrayType(ValidatableType::KIND_BUILT_IN, kNoPackage,
136 "byte", "cstdint", "uint8_t", "uint8_t",
137 "readByteVector", "writeByteVector",
138 false)) {}
139
140 ~ByteType() override = default;
IsCppPrimitive() const141 bool IsCppPrimitive() const override { return true; }
142
143 private:
144 DISALLOW_COPY_AND_ASSIGN(ByteType);
145 }; // class PrimitiveType
146
GetCppHeader(const AidlDefinedType & defined_type)147 static string GetCppHeader(const AidlDefinedType& defined_type) {
148 vector<string> name = defined_type.GetSplitPackage();
149 name.push_back(defined_type.GetName());
150 return Join(name, '/') + ".h";
151 }
152
153 class BinderType : public Type {
154 public:
BinderType(const AidlInterface & interface,const std::string & src_file_name)155 BinderType(const AidlInterface& interface, const std::string& src_file_name)
156 : BinderType(interface, src_file_name,
157 new BinderType(interface, src_file_name, kNoNullableType,
158 "readNullableStrongBinder"),
159 "readStrongBinder") {}
160 ~BinderType() override = default;
161
WriteCast(const string & val) const162 string WriteCast(const string& val) const override {
163 return write_cast_ + "(" + val + ")";
164 }
165
166 private:
BinderType(const AidlInterface & interface,const std::string & src_file_name,Type * nullable_type,const std::string & read)167 BinderType(const AidlInterface& interface, const std::string& src_file_name, Type* nullable_type,
168 const std::string& read)
169 : Type(ValidatableType::KIND_GENERATED, interface.GetPackage(), interface.GetName(),
170 {GetCppHeader(interface)}, GetCppName(interface), read, "writeStrongBinder",
171 kNoArrayType, nullable_type, src_file_name),
172 write_cast_(GetRawCppName(interface) + "::asBinder") {}
173
GetCppName(const AidlInterface & interface)174 static string GetCppName(const AidlInterface& interface) {
175 return "::android::sp<" + GetRawCppName(interface) + ">";
176 }
177
GetRawCppName(const AidlInterface & interface)178 static string GetRawCppName(const AidlInterface& interface) {
179 vector<string> name = interface.GetSplitPackage();
180 string ret;
181
182 name.push_back(interface.GetName());
183
184 for (const auto& term : name) {
185 ret += "::" + term;
186 }
187
188 return ret;
189 }
190
191 std::string write_cast_;
192 };
193
194 class NullableParcelableType : public Type {
195 public:
NullableParcelableType(const AidlParcelable & parcelable,const std::string & cpp_header,const std::string & src_file_name)196 NullableParcelableType(const AidlParcelable& parcelable, const std::string& cpp_header,
197 const std::string& src_file_name)
198 : Type(ValidatableType::KIND_PARCELABLE, parcelable.GetPackage(), parcelable.GetName(),
199 {cpp_header}, GetCppName(parcelable), "readParcelable", "writeNullableParcelable",
200 kNoArrayType, kNoNullableType, src_file_name) {}
201 ~NullableParcelableType() override = default;
202
203 private:
GetCppName(const AidlParcelable & parcelable)204 static string GetCppName(const AidlParcelable& parcelable) {
205 return "::std::unique_ptr<::" + Join(parcelable.GetSplitPackage(), "::") +
206 "::" + parcelable.GetCppName() + ">";
207 }
208 };
209
210 class ParcelableType : public Type {
211 public:
ParcelableType(const AidlParcelable & parcelable,const std::string & cpp_header,const std::string & src_file_name)212 ParcelableType(const AidlParcelable& parcelable, const std::string& cpp_header,
213 const std::string& src_file_name)
214 : Type(ValidatableType::KIND_PARCELABLE, parcelable.GetPackage(), parcelable.GetName(),
215 {cpp_header}, GetCppName(parcelable), "readParcelable", "writeParcelable",
216 new CppArrayType(ValidatableType::KIND_PARCELABLE, parcelable.GetPackage(),
217 parcelable.GetName(), cpp_header, GetCppName(parcelable),
218 GetCppName(parcelable), "readParcelableVector",
219 "writeParcelableVector", false, src_file_name),
220 new NullableParcelableType(parcelable, cpp_header, src_file_name), src_file_name) {}
221 ~ParcelableType() override = default;
222
223 private:
GetCppName(const AidlParcelable & parcelable)224 static string GetCppName(const AidlParcelable& parcelable) {
225 return "::" + Join(parcelable.GetSplitPackage(), "::") +
226 "::" + parcelable.GetCppName();
227 }
228 };
229
230 class NullableMap : public Type {
231 public:
NullableMap()232 NullableMap()
233 : Type(ValidatableType::KIND_BUILT_IN,
234 "java.util", "Map",
235 {"binder/Map.h", "binder/Value.h"},
236 "::std::unique_ptr<::android::binder::Map>",
237 "readNullableMap", "writeNullableMap") {}
238 ~NullableMap() override = default;
239 };
240
241
242 class MapType : public Type {
243 public:
MapType()244 MapType()
245 : Type(ValidatableType::KIND_BUILT_IN,
246 "java.util", "Map",
247 {"binder/Map.h","binder/Value.h"},
248 "::android::binder::Map",
249 "readMap", "writeMap",
250 kNoArrayType,
251 new NullableMap() ) {}
252 ~MapType() override = default;
253
254 private:
255 DISALLOW_COPY_AND_ASSIGN(MapType);
256 }; // class MapType
257
258 class NullableStringListType : public Type {
259 public:
NullableStringListType()260 NullableStringListType()
261 : Type(ValidatableType::KIND_BUILT_IN,
262 "java.util", "List<" + string(kStringCanonicalName) + ">",
263 {"utils/String16.h", "memory", "vector"},
264 "::std::unique_ptr<::std::vector<std::unique_ptr<::android::String16>>>",
265 "readString16Vector", "writeString16Vector") {}
266 ~NullableStringListType() override = default;
267
268 private:
269 DISALLOW_COPY_AND_ASSIGN(NullableStringListType);
270 }; // class NullableStringListType
271
272 class StringListType : public Type {
273 public:
StringListType()274 StringListType()
275 : Type(ValidatableType::KIND_BUILT_IN,
276 "java.util", "List<" + string(kStringCanonicalName) + ">",
277 {"utils/String16.h", "vector"},
278 "::std::vector<::android::String16>",
279 "readString16Vector", "writeString16Vector",
280 kNoArrayType, new NullableStringListType()) {}
281 ~StringListType() override = default;
282
283 private:
284 DISALLOW_COPY_AND_ASSIGN(StringListType);
285 }; // class StringListType
286
287 class NullableUtf8InCppStringListType : public Type {
288 public:
NullableUtf8InCppStringListType()289 NullableUtf8InCppStringListType()
290 : Type(ValidatableType::KIND_BUILT_IN,
291 "java.util", "List<" + string(kUtf8InCppStringCanonicalName) + ">",
292 {"memory", "string", "vector"},
293 "::std::unique_ptr<::std::vector<std::unique_ptr<::std::string>>>",
294 "readUtf8VectorFromUtf16Vector", "writeUtf8VectorAsUtf16Vector") {}
295 ~NullableUtf8InCppStringListType() override = default;
296
297 private:
298 DISALLOW_COPY_AND_ASSIGN(NullableUtf8InCppStringListType);
299 }; // class NullableUtf8InCppStringListType
300
301 class Utf8InCppStringListType : public Type {
302 public:
Utf8InCppStringListType()303 Utf8InCppStringListType()
304 : Type(ValidatableType::KIND_BUILT_IN,
305 "java.util", "List<" + string(kUtf8InCppStringCanonicalName) + ">",
306 {"string", "vector"},
307 "::std::vector<::std::string>",
308 "readUtf8VectorFromUtf16Vector", "writeUtf8VectorAsUtf16Vector",
309 kNoArrayType, new NullableUtf8InCppStringListType()) {}
310 ~Utf8InCppStringListType() override = default;
311
312 private:
313 DISALLOW_COPY_AND_ASSIGN(Utf8InCppStringListType);
314 }; // class Utf8InCppStringListType
315
316 class NullableBinderListType : public Type {
317 public:
NullableBinderListType()318 NullableBinderListType()
319 : Type(ValidatableType::KIND_BUILT_IN, "java.util",
320 "List<android.os.IBinder>", {"binder/IBinder.h", "vector"},
321 "::std::unique_ptr<::std::vector<::android::sp<::android::IBinder>>>",
322 "readStrongBinderVector", "writeStrongBinderVector") {}
323 ~NullableBinderListType() override = default;
324
325 private:
326 DISALLOW_COPY_AND_ASSIGN(NullableBinderListType);
327 }; // class NullableBinderListType
328
329 class BinderListType : public Type {
330 public:
BinderListType()331 BinderListType()
332 : Type(ValidatableType::KIND_BUILT_IN, "java.util",
333 "List<android.os.IBinder>", {"binder/IBinder.h", "vector"},
334 "::std::vector<::android::sp<::android::IBinder>>",
335 "readStrongBinderVector", "writeStrongBinderVector",
336 kNoArrayType, new NullableBinderListType()) {}
337 ~BinderListType() override = default;
338
339 private:
340 DISALLOW_COPY_AND_ASSIGN(BinderListType);
341 }; // class BinderListType
342
343 } // namespace
344
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)345 Type::Type(int kind,
346 const std::string& package,
347 const std::string& aidl_type,
348 const vector<string>& headers,
349 const string& cpp_type,
350 const string& read_method,
351 const string& write_method,
352 Type* array_type,
353 Type* nullable_type,
354 const string& src_file_name,
355 int line)
356 : ValidatableType(kind, package, aidl_type, src_file_name, line),
357 headers_(headers),
358 aidl_type_(aidl_type),
359 cpp_type_(cpp_type),
360 parcel_read_method_(read_method),
361 parcel_write_method_(write_method),
362 array_type_(array_type),
363 nullable_type_(nullable_type) {}
364
CanWriteToParcel() const365 bool Type::CanWriteToParcel() const { return true; }
366
Init()367 void TypeNamespace::Init() {
368 Add(std::make_unique<ByteType>());
369 Add(std::make_unique<PrimitiveType>("int", "cstdint", "int32_t", "readInt32", "writeInt32",
370 "readInt32Vector", "writeInt32Vector"));
371 Add(std::make_unique<PrimitiveType>("long", "cstdint", "int64_t", "readInt64", "writeInt64",
372 "readInt64Vector", "writeInt64Vector"));
373 Add(std::make_unique<PrimitiveType>("float", kNoHeader, "float", "readFloat", "writeFloat",
374 "readFloatVector", "writeFloatVector"));
375 Add(std::make_unique<PrimitiveType>("double", kNoHeader, "double", "readDouble", "writeDouble",
376 "readDoubleVector", "writeDoubleVector"));
377 Add(std::make_unique<PrimitiveType>("boolean", kNoHeader, "bool", "readBool", "writeBool",
378 "readBoolVector", "writeBoolVector"));
379 // C++11 defines the char16_t type as a built in for Unicode characters.
380 Add(std::make_unique<PrimitiveType>("char", kNoHeader, "char16_t", "readChar", "writeChar",
381 "readCharVector", "writeCharVector"));
382
383 Type* string_array_type = new CppArrayType(
384 ValidatableType::KIND_BUILT_IN, "java.lang", "String",
385 "utils/String16.h", "::android::String16",
386 "::std::unique_ptr<::android::String16>", "readString16Vector",
387 "writeString16Vector", false);
388
389 Type* nullable_string_type =
390 new Type(ValidatableType::KIND_BUILT_IN, "java.lang", "String",
391 {"memory", "utils/String16.h"}, "::std::unique_ptr<::android::String16>",
392 "readString16", "writeString16");
393
394 AddAndSetMember(&string_type_,
395 std::make_unique<Type>(ValidatableType::KIND_BUILT_IN, "java.lang", "String",
396 std::vector<std::string>{"utils/String16.h"},
397 "::android::String16", "readString16", "writeString16",
398 string_array_type, nullable_string_type));
399
400 using ::android::aidl::kAidlReservedTypePackage;
401 using ::android::aidl::kUtf8InCppStringClass;
402
403 // This type is a Utf16 string in the parcel, but deserializes to
404 // a std::string in Utf8 format when we use it in C++.
405 Type* cpp_utf8_string_array = new CppArrayType(
406 ValidatableType::KIND_BUILT_IN,
407 kAidlReservedTypePackage, kUtf8InCppStringClass,
408 "string", "::std::string", "::std::unique_ptr<::std::string>",
409 "readUtf8VectorFromUtf16Vector", "writeUtf8VectorAsUtf16Vector",
410 false);
411 Type* nullable_cpp_utf8_string_type =
412 new Type(ValidatableType::KIND_BUILT_IN, kAidlReservedTypePackage, kUtf8InCppStringClass,
413 std::vector<std::string>{"string", "memory"}, "::std::unique_ptr<::std::string>",
414 "readUtf8FromUtf16", "writeUtf8AsUtf16");
415 Add(std::make_unique<Type>(ValidatableType::KIND_BUILT_IN, kAidlReservedTypePackage,
416 kUtf8InCppStringClass, std::vector<std::string>{"string"},
417 "::std::string", "readUtf8FromUtf16", "writeUtf8AsUtf16",
418 cpp_utf8_string_array, nullable_cpp_utf8_string_type));
419
420 Type* nullable_ibinder = new Type(
421 ValidatableType::KIND_BUILT_IN, "android.os", "IBinder",
422 {"binder/IBinder.h"}, "::android::sp<::android::IBinder>",
423 "readNullableStrongBinder", "writeStrongBinder");
424
425 AddAndSetMember(&ibinder_type_,
426 std::make_unique<Type>(ValidatableType::KIND_BUILT_IN, "android.os", "IBinder",
427 std::vector<std::string>{"binder/IBinder.h"},
428 "::android::sp<::android::IBinder>", "readStrongBinder",
429 "writeStrongBinder", kNoArrayType, nullable_ibinder));
430
431 Add(std::make_unique<MapType>());
432
433 Add(std::make_unique<BinderListType>());
434 Add(std::make_unique<StringListType>());
435 Add(std::make_unique<Utf8InCppStringListType>());
436
437 Type* fd_vector_type = new CppArrayType(
438 ValidatableType::KIND_BUILT_IN, kNoPackage, "FileDescriptor",
439 "android-base/unique_fd.h",
440 "::android::base::unique_fd", "::android::base::unique_fd",
441 "readUniqueFileDescriptorVector", "writeUniqueFileDescriptorVector",
442 false);
443
444 Add(std::make_unique<Type>(ValidatableType::KIND_BUILT_IN, kNoPackage, "FileDescriptor",
445 std::vector<std::string>{"android-base/unique_fd.h"},
446 "::android::base::unique_fd", "readUniqueFileDescriptor",
447 "writeUniqueFileDescriptor", fd_vector_type));
448
449 Type* pfd_vector_type =
450 new CppArrayType(ValidatableType::KIND_BUILT_IN, "android.os", "ParcelFileDescriptor",
451 "binder/ParcelFileDescriptor.h", "::android::os::ParcelFileDescriptor",
452 "::android::os::ParcelFileDescriptor", "readParcelableVector",
453 "writeParcelableVector", false);
454
455 Type* nullable_pfd_type =
456 new Type(ValidatableType::KIND_BUILT_IN, "android.os", "ParcelFileDescriptor",
457 std::vector<std::string>{"memory", "binder/ParcelFileDescriptor.h"},
458 "::std::unique_ptr<::android::os::ParcelFileDescriptor>", "readParcelable",
459 "writeNullableParcelable");
460
461 Add(std::make_unique<Type>(ValidatableType::KIND_BUILT_IN, "android.os", "ParcelFileDescriptor",
462 std::vector<std::string>{"binder/ParcelFileDescriptor.h"},
463 "::android::os::ParcelFileDescriptor", "readParcelable",
464 "writeParcelable", pfd_vector_type, nullable_pfd_type));
465
466 // Qualify VoidType so we don't get collisions with the VoidType method
467 AddAndSetMember(&void_type_, std::make_unique<class VoidType>());
468 }
469
AddParcelableType(const AidlParcelable & p,const std::string & filename)470 bool TypeNamespace::AddParcelableType(const AidlParcelable& p, const std::string& filename) {
471 const std::string cpp_header = p.AsStructuredParcelable() ? GetCppHeader(p) : p.GetCppHeader();
472
473 if (cpp_header.empty()) {
474 AIDL_ERROR(p) << "Parcelable " << p.GetCanonicalName() << " has no C++ header defined.";
475 return false;
476 }
477
478 Add(std::make_unique<ParcelableType>(p, cpp_header, filename));
479 return true;
480 }
481
AddBinderType(const AidlInterface & b,const std::string & filename)482 bool TypeNamespace::AddBinderType(const AidlInterface& b, const std::string& filename) {
483 Add(std::make_unique<BinderType>(b, filename));
484 return true;
485 }
486
AddListType(const std::string & type_name)487 bool TypeNamespace::AddListType(const std::string& type_name) {
488 const Type* contained_type = FindTypeByCanonicalName(type_name);
489 if (!contained_type) {
490 LOG(ERROR) << "Cannot create List<" << type_name << "> because contained "
491 "type cannot be found or is invalid.";
492 return false;
493 }
494 if (contained_type->IsCppPrimitive()) {
495 LOG(ERROR) << "Cannot create List<" << type_name << "> because contained "
496 "type is a primitive in Java and Java List cannot hold "
497 "primitives.";
498 return false;
499 }
500
501 if (contained_type->CanonicalName() == kStringCanonicalName ||
502 contained_type->CanonicalName() == kUtf8InCppStringCanonicalName ||
503 contained_type == IBinderType()) {
504 return true;
505 }
506
507 // TODO Support lists of parcelables b/23600712
508
509 LOG(ERROR) << "aidl-cpp does not yet support List<" << type_name << ">";
510 return false;
511 }
512
AddMapType(const std::string &,const std::string &)513 bool TypeNamespace::AddMapType(const std::string& /* key_type_name */,
514 const std::string& /* value_type_name */) {
515 // TODO Support list types b/25242025
516 LOG(ERROR) << "aidl does not implement support for typed maps!";
517 return false;
518 }
519
GetArgType(const AidlArgument & a,int arg_index,const AidlDefinedType & context) const520 const ValidatableType* TypeNamespace::GetArgType(const AidlArgument& a, int arg_index,
521 const AidlDefinedType& context) const {
522 return ::android::aidl::TypeNamespace::GetArgType(a, arg_index, context);
523 }
524
525 } // namespace cpp
526 } // namespace aidl
527 } // namespace android
528