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 <vector> 22 23 #include <android-base/stringprintf.h> 24 #include <android-base/strings.h> 25 26 #include "logging.h" 27 28 using std::cerr; 29 using std::endl; 30 using std::set; 31 using std::string; 32 using std::unique_ptr; 33 using std::vector; 34 35 using android::base::Split; 36 using android::base::Join; 37 using android::base::StringPrintf; 38 39 namespace android { 40 namespace aidl { 41 namespace cpp { 42 namespace { 43 44 const char kNoPackage[] = ""; 45 const char kNoHeader[] = ""; 46 const char kNoValidMethod[] = ""; 47 Type* const kNoArrayType = nullptr; 48 Type* const kNoNullableType = nullptr; 49 50 bool is_cpp_keyword(const std::string& str) { 51 static const std::vector<std::string> kCppKeywords{ 52 "alignas", "alignof", "and", "and_eq", "asm", "auto", "bitand", "bitor", 53 "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class", 54 "compl", "concept", "const", "constexpr", "const_cast", "continue", 55 "decltype", "default", "delete", "do", "double", "dynamic_cast", "else", 56 "enum", "explicit", "export", "extern", "false", "float", "for", "friend", 57 "goto", "if", "inline", "int", "long", "mutable", "namespace", "new", 58 "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq", 59 "private", "protected", "public", "register", "reinterpret_cast", 60 "requires", "return", "short", "signed", "sizeof", "static", 61 "static_assert", "static_cast", "struct", "switch", "template", "this", 62 "thread_local", "throw", "true", "try", "typedef", "typeid", "typename", 63 "union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t", 64 "while", "xor", "xor_eq", 65 }; 66 return std::find(kCppKeywords.begin(), kCppKeywords.end(), str) != 67 kCppKeywords.end(); 68 } 69 70 class VoidType : public Type { 71 public: 72 VoidType() : Type(ValidatableType::KIND_BUILT_IN, kNoPackage, "void", 73 {}, "void", kNoValidMethod, kNoValidMethod) {} 74 virtual ~VoidType() = default; 75 bool CanBeOutParameter() const override { return false; } 76 bool CanWriteToParcel() const override { return false; } 77 }; // class VoidType 78 79 class PrimitiveType : public Type { 80 public: 81 PrimitiveType(int kind, // from ValidatableType 82 const std::string& package, 83 const std::string& aidl_type, 84 const std::string& header, 85 const std::string& cpp_type, 86 const std::string& read_method, 87 const std::string& write_method, 88 const std::string& read_array_method, 89 const std::string& write_array_method) 90 : Type(kind, package, aidl_type, {header}, cpp_type, read_method, 91 write_method, PrimitiveArrayType(kind, package, aidl_type, 92 header, cpp_type, 93 read_array_method, 94 write_array_method)) {} 95 96 virtual ~PrimitiveType() = default; 97 bool IsCppPrimitive() const override { return true; } 98 bool CanBeOutParameter() const override { return is_array_; } 99 100 protected: 101 static PrimitiveType* PrimitiveArrayType(int kind, // from ValidatableType 102 const std::string& package, 103 const std::string& aidl_type, 104 const std::string& header, 105 const std::string& cpp_type, 106 const std::string& read_method, 107 const std::string& write_method) { 108 PrimitiveType* nullable = 109 new PrimitiveType(kind, package, aidl_type + "[]", header, 110 "::std::unique_ptr<::std::vector<" + cpp_type + ">>", 111 read_method, write_method); 112 113 return new PrimitiveType(kind, package, aidl_type + "[]", header, 114 "::std::vector<" + cpp_type + ">", 115 read_method, write_method, nullable); 116 } 117 118 PrimitiveType(int kind, // from ValidatableType 119 const std::string& package, 120 const std::string& aidl_type, 121 const std::string& header, 122 const std::string& cpp_type, 123 const std::string& read_method, 124 const std::string& write_method, 125 Type* nullable_type = nullptr) 126 : Type(kind, package, aidl_type, {header, "vector"}, cpp_type, read_method, 127 write_method, kNoArrayType, nullable_type) { 128 is_array_ = true; 129 } 130 131 private: 132 bool is_array_ = false; 133 134 DISALLOW_COPY_AND_ASSIGN(PrimitiveType); 135 }; // class PrimitiveType 136 137 class ByteType : public Type { 138 public: 139 ByteType() : ByteType(false, "byte", "int8_t", "readByte", "writeByte", 140 new ByteType(true, "byte[]", "::std::vector<uint8_t>", "readByteVector", 141 "writeByteVector", kNoArrayType, 142 new ByteType(true, "byte[]", 143 "::std::unique_ptr<::std::vector<uint8_t>>", 144 "readByteVector", "writeByteVector", kNoArrayType, 145 kNoNullableType)), kNoNullableType) {} 146 147 virtual ~ByteType() = default; 148 bool IsCppPrimitive() const override { return true; } 149 bool CanBeOutParameter() const override { return is_array_; } 150 151 protected: 152 ByteType(bool is_array, 153 const std::string& name, 154 const std::string& cpp_type, 155 const std::string& read_method, 156 const std::string& write_method, 157 Type* array_type, 158 Type* nullable_type) 159 : Type(ValidatableType::KIND_BUILT_IN, kNoPackage, name, {"cstdint"}, 160 cpp_type, read_method, write_method, array_type, nullable_type), 161 is_array_(is_array) {} 162 163 private: 164 bool is_array_ = false; 165 166 DISALLOW_COPY_AND_ASSIGN(ByteType); 167 }; // class PrimitiveType 168 169 class BinderType : public Type { 170 public: 171 BinderType(const AidlInterface& interface, const std::string& src_file_name) 172 : Type(ValidatableType::KIND_GENERATED, 173 interface.GetPackage(), interface.GetName(), 174 {GetCppHeader(interface)}, GetCppName(interface), 175 "readStrongBinder", "writeStrongBinder", 176 kNoArrayType, kNoNullableType, src_file_name, 177 interface.GetLine()), 178 write_cast_(GetRawCppName(interface) + "::asBinder") {} 179 virtual ~BinderType() = default; 180 181 string WriteCast(const string& val) const override { 182 return write_cast_ + "(" + val + ")"; 183 } 184 185 private: 186 static string GetCppName(const AidlInterface& interface) { 187 return "::android::sp<" + GetRawCppName(interface) + ">"; 188 } 189 190 static string GetRawCppName(const AidlInterface& interface) { 191 vector<string> name = interface.GetSplitPackage(); 192 string ret; 193 194 name.push_back(interface.GetName()); 195 196 for (const auto& term : name) { 197 ret += "::" + term; 198 } 199 200 return ret; 201 } 202 203 static string GetCppHeader(const AidlInterface& interface) { 204 vector<string> name = interface.GetSplitPackage(); 205 name.push_back(interface.GetName()); 206 return Join(name, '/') + ".h"; 207 } 208 209 std::string write_cast_; 210 }; 211 212 class NullableParcelableArrayType : public ArrayType { 213 public: 214 NullableParcelableArrayType(const AidlParcelable& parcelable, 215 const std::string& src_file_name) 216 : ArrayType(ValidatableType::KIND_PARCELABLE, 217 parcelable.GetPackage(), parcelable.GetName(), 218 {parcelable.GetCppHeader(), "vector"}, 219 GetCppName(parcelable), "readParcelableVector", 220 "writeParcelableVector", kNoArrayType, kNoNullableType, 221 src_file_name, parcelable.GetLine()) {} 222 virtual ~NullableParcelableArrayType() = default; 223 224 private: 225 static string GetCppName(const AidlParcelable& parcelable) { 226 return "::std::unique_ptr<::std::vector<std::unique_ptr<" + 227 Join(parcelable.GetSplitPackage(), "::") + "::" + 228 parcelable.GetName() + ">>>"; 229 } 230 }; 231 232 class ParcelableArrayType : public ArrayType { 233 public: 234 ParcelableArrayType(const AidlParcelable& parcelable, 235 const std::string& src_file_name) 236 : ArrayType(ValidatableType::KIND_PARCELABLE, 237 parcelable.GetPackage(), parcelable.GetName(), 238 {parcelable.GetCppHeader(), "vector"}, 239 GetCppName(parcelable), "readParcelableVector", 240 "writeParcelableVector", kNoArrayType, 241 new NullableParcelableArrayType(parcelable, src_file_name), 242 src_file_name, parcelable.GetLine()) {} 243 virtual ~ParcelableArrayType() = default; 244 245 private: 246 static string GetCppName(const AidlParcelable& parcelable) { 247 return "::std::vector<" + Join(parcelable.GetSplitPackage(), "::") + 248 "::" + parcelable.GetName() + ">"; 249 } 250 }; 251 252 class NullableParcelableType : public Type { 253 public: 254 NullableParcelableType(const AidlParcelable& parcelable, 255 const std::string& src_file_name) 256 : Type(ValidatableType::KIND_PARCELABLE, 257 parcelable.GetPackage(), parcelable.GetName(), 258 {parcelable.GetCppHeader()}, GetCppName(parcelable), 259 "readParcelable", "writeNullableParcelable", 260 kNoArrayType, kNoNullableType, 261 src_file_name, parcelable.GetLine()) {} 262 virtual ~NullableParcelableType() = default; 263 bool CanBeOutParameter() const override { return true; } 264 265 private: 266 static string GetCppName(const AidlParcelable& parcelable) { 267 return "::std::unique_ptr<::" + Join(parcelable.GetSplitPackage(), "::") + 268 "::" + parcelable.GetName() + ">"; 269 } 270 }; 271 272 class ParcelableType : public Type { 273 public: 274 ParcelableType(const AidlParcelable& parcelable, 275 const std::string& src_file_name) 276 : Type(ValidatableType::KIND_PARCELABLE, 277 parcelable.GetPackage(), parcelable.GetName(), 278 {parcelable.GetCppHeader()}, GetCppName(parcelable), 279 "readParcelable", "writeParcelable", 280 new ParcelableArrayType(parcelable, src_file_name), 281 new NullableParcelableType(parcelable, src_file_name), 282 src_file_name, parcelable.GetLine()) {} 283 virtual ~ParcelableType() = default; 284 bool CanBeOutParameter() const override { return true; } 285 286 private: 287 static string GetCppName(const AidlParcelable& parcelable) { 288 return "::" + Join(parcelable.GetSplitPackage(), "::") + 289 "::" + parcelable.GetName(); 290 } 291 }; 292 293 class NullableStringListType : public Type { 294 public: 295 NullableStringListType() 296 : Type(ValidatableType::KIND_BUILT_IN, 297 "java.util", "List<" + string(kStringCanonicalName) + ">", 298 {"utils/String16.h", "memory", "vector"}, 299 "::std::unique_ptr<::std::vector<std::unique_ptr<::android::String16>>>", 300 "readString16Vector", "writeString16Vector") {} 301 virtual ~NullableStringListType() = default; 302 bool CanBeOutParameter() const override { return true; } 303 304 private: 305 DISALLOW_COPY_AND_ASSIGN(NullableStringListType); 306 }; // class NullableStringListType 307 308 class StringListType : public Type { 309 public: 310 StringListType() 311 : Type(ValidatableType::KIND_BUILT_IN, 312 "java.util", "List<" + string(kStringCanonicalName) + ">", 313 {"utils/String16.h", "vector"}, 314 "::std::vector<::android::String16>", 315 "readString16Vector", "writeString16Vector", 316 kNoArrayType, new NullableStringListType()) {} 317 virtual ~StringListType() = default; 318 bool CanBeOutParameter() const override { return true; } 319 320 private: 321 DISALLOW_COPY_AND_ASSIGN(StringListType); 322 }; // class StringListType 323 324 class NullableUtf8InCppStringListType : public Type { 325 public: 326 NullableUtf8InCppStringListType() 327 : Type(ValidatableType::KIND_BUILT_IN, 328 "java.util", "List<" + string(kUtf8InCppStringCanonicalName) + ">", 329 {"memory", "string", "vector"}, 330 "::std::unique_ptr<::std::vector<std::unique_ptr<::std::string>>>", 331 "readUtf8VectorFromUtf16Vector", "writeUtf8VectorAsUtf16Vector") {} 332 virtual ~NullableUtf8InCppStringListType() = default; 333 bool CanBeOutParameter() const override { return true; } 334 335 private: 336 DISALLOW_COPY_AND_ASSIGN(NullableUtf8InCppStringListType); 337 }; // class NullableUtf8InCppStringListType 338 339 class Utf8InCppStringListType : public Type { 340 public: 341 Utf8InCppStringListType() 342 : Type(ValidatableType::KIND_BUILT_IN, 343 "java.util", "List<" + string(kUtf8InCppStringCanonicalName) + ">", 344 {"string", "vector"}, 345 "::std::vector<::std::string>", 346 "readUtf8VectorFromUtf16Vector", "writeUtf8VectorAsUtf16Vector", 347 kNoArrayType, new NullableUtf8InCppStringListType()) {} 348 virtual ~Utf8InCppStringListType() = default; 349 bool CanBeOutParameter() const override { return true; } 350 351 private: 352 DISALLOW_COPY_AND_ASSIGN(Utf8InCppStringListType); 353 }; // class Utf8InCppStringListType 354 355 class NullableBinderListType : public Type { 356 public: 357 NullableBinderListType() 358 : Type(ValidatableType::KIND_BUILT_IN, "java.util", 359 "List<android.os.IBinder>", {"binder/IBinder.h", "vector"}, 360 "::std::unique_ptr<::std::vector<::android::sp<::android::IBinder>>>", 361 "readStrongBinderVector", "writeStrongBinderVector") {} 362 virtual ~NullableBinderListType() = default; 363 bool CanBeOutParameter() const override { return true; } 364 365 private: 366 DISALLOW_COPY_AND_ASSIGN(NullableBinderListType); 367 }; // class NullableBinderListType 368 369 class BinderListType : public Type { 370 public: 371 BinderListType() 372 : Type(ValidatableType::KIND_BUILT_IN, "java.util", 373 "List<android.os.IBinder>", {"binder/IBinder.h", "vector"}, 374 "::std::vector<::android::sp<::android::IBinder>>", 375 "readStrongBinderVector", "writeStrongBinderVector", 376 kNoArrayType, new NullableBinderListType()) {} 377 virtual ~BinderListType() = default; 378 bool CanBeOutParameter() const override { return true; } 379 380 private: 381 DISALLOW_COPY_AND_ASSIGN(BinderListType); 382 }; // class BinderListType 383 384 } // namespace 385 386 Type::Type(int kind, 387 const std::string& package, 388 const std::string& aidl_type, 389 const vector<string>& headers, 390 const string& cpp_type, 391 const string& read_method, 392 const string& write_method, 393 Type* array_type, 394 Type* nullable_type, 395 const string& src_file_name, 396 int line) 397 : ValidatableType(kind, package, aidl_type, src_file_name, line), 398 headers_(headers), 399 aidl_type_(aidl_type), 400 cpp_type_(cpp_type), 401 parcel_read_method_(read_method), 402 parcel_write_method_(write_method), 403 array_type_(array_type), 404 nullable_type_(nullable_type) {} 405 406 bool Type::CanWriteToParcel() const { return true; } 407 408 void TypeNamespace::Init() { 409 Add(new ByteType()); 410 Add(new PrimitiveType( 411 ValidatableType::KIND_BUILT_IN, kNoPackage, "int", 412 "cstdint", "int32_t", "readInt32", "writeInt32", 413 "readInt32Vector", "writeInt32Vector")); 414 Add(new PrimitiveType( 415 ValidatableType::KIND_BUILT_IN, kNoPackage, "long", 416 "cstdint", "int64_t", "readInt64", "writeInt64", 417 "readInt64Vector", "writeInt64Vector")); 418 Add(new PrimitiveType( 419 ValidatableType::KIND_BUILT_IN, kNoPackage, "float", 420 kNoHeader, "float", "readFloat", "writeFloat", 421 "readFloatVector", "writeFloatVector")); 422 Add(new PrimitiveType( 423 ValidatableType::KIND_BUILT_IN, kNoPackage, "double", 424 kNoHeader, "double", "readDouble", "writeDouble", 425 "readDoubleVector", "writeDoubleVector")); 426 Add(new PrimitiveType( 427 ValidatableType::KIND_BUILT_IN, kNoPackage, "boolean", 428 kNoHeader, "bool", "readBool", "writeBool", 429 "readBoolVector", "writeBoolVector")); 430 // C++11 defines the char16_t type as a built in for Unicode characters. 431 Add(new PrimitiveType( 432 ValidatableType::KIND_BUILT_IN, kNoPackage, "char", 433 kNoHeader, "char16_t", "readChar", "writeChar", 434 "readCharVector", "writeCharVector")); 435 436 Type* nullable_string_array_type = 437 new ArrayType(ValidatableType::KIND_BUILT_IN, "java.lang", "String[]", 438 {"utils/String16.h", "memory", "vector"}, 439 "::std::unique_ptr<::std::vector<::std::unique_ptr<::android::String16>>>", 440 "readString16Vector", "writeString16Vector"); 441 442 Type* string_array_type = new ArrayType(ValidatableType::KIND_BUILT_IN, 443 "java.lang", "String[]", 444 {"utils/String16.h", "vector"}, 445 "::std::vector<::android::String16>", 446 "readString16Vector", 447 "writeString16Vector", kNoArrayType, 448 nullable_string_array_type); 449 450 Type* nullable_string_type = 451 new Type(ValidatableType::KIND_BUILT_IN, "java.lang", "String", 452 {"memory", "utils/String16.h"}, "::std::unique_ptr<::android::String16>", 453 "readString16", "writeString16"); 454 455 string_type_ = new Type(ValidatableType::KIND_BUILT_IN, "java.lang", "String", 456 {"utils/String16.h"}, "::android::String16", 457 "readString16", "writeString16", 458 string_array_type, nullable_string_type); 459 Add(string_type_); 460 461 using ::android::aidl::kAidlReservedTypePackage; 462 using ::android::aidl::kUtf8InCppStringClass; 463 464 // This type is a Utf16 string in the parcel, but deserializes to 465 // a std::string in Utf8 format when we use it in C++. 466 Type* nullable_cpp_utf8_string_array = new ArrayType( 467 ValidatableType::KIND_BUILT_IN, 468 kAidlReservedTypePackage, StringPrintf("%s[]", kUtf8InCppStringClass), 469 {"memory", "string", "vector"}, 470 "::std::unique_ptr<::std::vector<::std::unique_ptr<::std::string>>>", 471 "readUtf8VectorFromUtf16Vector", "writeUtf8VectorAsUtf16Vector"); 472 Type* cpp_utf8_string_array = new ArrayType( 473 ValidatableType::KIND_BUILT_IN, 474 kAidlReservedTypePackage, StringPrintf("%s[]", kUtf8InCppStringClass), 475 {"string", "vector"}, 476 "::std::vector<::std::string>", 477 "readUtf8VectorFromUtf16Vector", "writeUtf8VectorAsUtf16Vector", 478 kNoArrayType, nullable_cpp_utf8_string_array); 479 Type* nullable_cpp_utf8_string_type = new Type( 480 ValidatableType::KIND_BUILT_IN, 481 kAidlReservedTypePackage, kUtf8InCppStringClass, 482 {"string", "memory"}, "::std::unique_ptr<::std::string>", 483 "readUtf8FromUtf16", "writeUtf8AsUtf16"); 484 Add(new Type( 485 ValidatableType::KIND_BUILT_IN, 486 kAidlReservedTypePackage, kUtf8InCppStringClass, 487 {"string"}, "::std::string", "readUtf8FromUtf16", "writeUtf8AsUtf16", 488 cpp_utf8_string_array, nullable_cpp_utf8_string_type)); 489 490 ibinder_type_ = new Type(ValidatableType::KIND_BUILT_IN, "android.os", 491 "IBinder", {"binder/IBinder.h"}, 492 "::android::sp<::android::IBinder>", "readStrongBinder", 493 "writeStrongBinder"); 494 Add(ibinder_type_); 495 496 Add(new BinderListType()); 497 Add(new StringListType()); 498 Add(new Utf8InCppStringListType()); 499 500 Type* fd_vector_type = new ArrayType( 501 ValidatableType::KIND_BUILT_IN, kNoPackage, "FileDescriptor[]", 502 {"nativehelper/ScopedFd.h", "vector"}, "::std::vector<::ScopedFd>", 503 "readUniqueFileDescriptorVector", "writeUniqueFileDescriptorVector"); 504 505 Add(new Type( 506 ValidatableType::KIND_BUILT_IN, kNoPackage, "FileDescriptor", 507 {"nativehelper/ScopedFd.h"}, "::ScopedFd", 508 "readUniqueFileDescriptor", "writeUniqueFileDescriptor", 509 fd_vector_type)); 510 511 void_type_ = new class VoidType(); 512 Add(void_type_); 513 } 514 515 bool TypeNamespace::AddParcelableType(const AidlParcelable& p, 516 const string& filename) { 517 if (p.GetCppHeader().empty()) { 518 LOG(ERROR) << "Parcelable " << p.GetCanonicalName() 519 << " has no C++ header defined."; 520 return false; 521 } 522 Add(new ParcelableType(p, filename)); 523 return true; 524 } 525 526 bool TypeNamespace::AddBinderType(const AidlInterface& b, 527 const string& file_name) { 528 Add(new BinderType(b, file_name)); 529 return true; 530 } 531 532 bool TypeNamespace::AddListType(const std::string& type_name) { 533 const Type* contained_type = FindTypeByCanonicalName(type_name); 534 if (!contained_type) { 535 LOG(ERROR) << "Cannot create List<" << type_name << "> because contained " 536 "type cannot be found or is invalid."; 537 return false; 538 } 539 if (contained_type->IsCppPrimitive()) { 540 LOG(ERROR) << "Cannot create List<" << type_name << "> because contained " 541 "type is a primitive in Java and Java List cannot hold " 542 "primitives."; 543 return false; 544 } 545 546 if (contained_type->CanonicalName() == kStringCanonicalName || 547 contained_type->CanonicalName() == kUtf8InCppStringCanonicalName || 548 contained_type == IBinderType()) { 549 return true; 550 } 551 552 // TODO Support lists of parcelables b/23600712 553 554 LOG(ERROR) << "aidl-cpp does not yet support List<" << type_name << ">"; 555 return false; 556 } 557 558 bool TypeNamespace::AddMapType(const std::string& /* key_type_name */, 559 const std::string& /* value_type_name */) { 560 // TODO Support list types b/25242025 561 LOG(ERROR) << "aidl does not implement support for typed maps!"; 562 return false; 563 } 564 565 bool TypeNamespace::IsValidPackage(const string& package) const { 566 if (package.empty()) { 567 return false; 568 } 569 570 auto pieces = Split(package, "."); 571 for (const string& piece : pieces) { 572 if (is_cpp_keyword(piece)) { 573 return false; 574 } 575 } 576 577 return true; 578 } 579 580 const ValidatableType* TypeNamespace::GetArgType(const AidlArgument& a, 581 int arg_index, 582 const std::string& filename) const { 583 const string error_prefix = StringPrintf( 584 "In file %s line %d parameter %s (%d):\n ", 585 filename.c_str(), a.GetLine(), a.GetName().c_str(), arg_index); 586 587 // check that the name doesn't match a keyword 588 if (is_cpp_keyword(a.GetName().c_str())) { 589 cerr << error_prefix << "Argument name is a C++ keyword" 590 << endl; 591 return nullptr; 592 } 593 594 return ::android::aidl::TypeNamespace::GetArgType(a, arg_index, filename); 595 } 596 597 } // namespace cpp 598 } // namespace aidl 599 } // namespace android 600