1 /* 2 * Copyright (C) 2016 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 "Interface.h" 18 19 #include "Annotation.h" 20 #include "ArrayType.h" 21 #include "ConstantExpression.h" 22 #include "DeathRecipientType.h" 23 #include "Method.h" 24 #include "ScalarType.h" 25 #include "StringType.h" 26 #include "VectorType.h" 27 28 #include <unistd.h> 29 30 #include <iostream> 31 #include <sstream> 32 33 #include <android-base/logging.h> 34 #include <hidl-hash/Hash.h> 35 #include <hidl-util/Formatter.h> 36 #include <hidl-util/StringHelper.h> 37 38 namespace android { 39 40 #define B_PACK_CHARS(c1, c2, c3, c4) \ 41 ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4)) 42 43 /* It is very important that these values NEVER change. These values 44 * must remain unchanged over the lifetime of android. This is 45 * because the framework on a device will be updated independently of 46 * the hals on a device. If the hals are compiled with one set of 47 * transaction values, and the framework with another, then the 48 * interface between them will be destroyed, and the device will not 49 * work. 50 */ 51 enum { 52 /////////////////// User defined transactions 53 FIRST_CALL_TRANSACTION = 0x00000001, 54 LAST_CALL_TRANSACTION = 0x0effffff, 55 /////////////////// HIDL reserved 56 FIRST_HIDL_TRANSACTION = 0x0f000000, 57 HIDL_PING_TRANSACTION = B_PACK_CHARS(0x0f, 'P', 'N', 'G'), 58 HIDL_DESCRIPTOR_CHAIN_TRANSACTION = B_PACK_CHARS(0x0f, 'C', 'H', 'N'), 59 HIDL_GET_DESCRIPTOR_TRANSACTION = B_PACK_CHARS(0x0f, 'D', 'S', 'C'), 60 HIDL_SYSPROPS_CHANGED_TRANSACTION = B_PACK_CHARS(0x0f, 'S', 'Y', 'S'), 61 HIDL_LINK_TO_DEATH_TRANSACTION = B_PACK_CHARS(0x0f, 'L', 'T', 'D'), 62 HIDL_UNLINK_TO_DEATH_TRANSACTION = B_PACK_CHARS(0x0f, 'U', 'T', 'D'), 63 HIDL_SET_HAL_INSTRUMENTATION_TRANSACTION = B_PACK_CHARS(0x0f, 'I', 'N', 'T'), 64 HIDL_GET_REF_INFO_TRANSACTION = B_PACK_CHARS(0x0f, 'R', 'E', 'F'), 65 HIDL_DEBUG_TRANSACTION = B_PACK_CHARS(0x0f, 'D', 'B', 'G'), 66 HIDL_HASH_CHAIN_TRANSACTION = B_PACK_CHARS(0x0f, 'H', 'S', 'H'), 67 LAST_HIDL_TRANSACTION = 0x0fffffff, 68 }; 69 70 Interface::Interface(const char* localName, const Location& location, Scope* parent, 71 Interface* super) 72 : Scope(localName, location, parent), mSuperType(super), mIsJavaCompatibleInProgress(false) {} 73 74 std::string Interface::typeName() const { 75 return "interface " + localName(); 76 } 77 78 bool Interface::fillPingMethod(Method *method) const { 79 if (method->name() != "ping") { 80 return false; 81 } 82 83 method->fillImplementation( 84 HIDL_PING_TRANSACTION, 85 { 86 {IMPL_INTERFACE, 87 [](auto &out) { 88 out << "return ::android::hardware::Void();\n"; 89 } 90 }, 91 {IMPL_STUB_IMPL, 92 [](auto &out) { 93 out << "return ::android::hardware::Void();\n"; 94 } 95 } 96 }, /*cppImpl*/ 97 { 98 {IMPL_INTERFACE, 99 [](auto &out) { 100 out << "return;\n"; 101 } 102 }, 103 {IMPL_STUB, nullptr /* don't generate code */} 104 } /*javaImpl*/ 105 ); 106 107 return true; 108 } 109 110 bool Interface::fillLinkToDeathMethod(Method *method) const { 111 if (method->name() != "linkToDeath") { 112 return false; 113 } 114 115 method->fillImplementation( 116 HIDL_LINK_TO_DEATH_TRANSACTION, 117 { 118 {IMPL_INTERFACE, 119 [](auto &out) { 120 out << "(void)cookie;\n" 121 << "return (recipient != nullptr);\n"; 122 } 123 }, 124 {IMPL_PROXY, 125 [](auto &out) { 126 out << "::android::hardware::ProcessState::self()->startThreadPool();\n"; 127 out << "::android::hardware::hidl_binder_death_recipient *binder_recipient" 128 << " = new ::android::hardware::hidl_binder_death_recipient(recipient, cookie, this);\n" 129 << "std::unique_lock<std::mutex> lock(_hidl_mMutex);\n" 130 << "_hidl_mDeathRecipients.push_back(binder_recipient);\n" 131 << "return (remote()->linkToDeath(binder_recipient)" 132 << " == ::android::OK);\n"; 133 } 134 }, 135 {IMPL_STUB, nullptr} 136 }, /*cppImpl*/ 137 { 138 {IMPL_INTERFACE, 139 [](auto &out) { 140 out << "return true;"; 141 } 142 }, 143 {IMPL_PROXY, 144 [](auto &out) { 145 out << "return mRemote.linkToDeath(recipient, cookie);\n"; 146 } 147 }, 148 {IMPL_STUB, nullptr} 149 } /*javaImpl*/ 150 ); 151 return true; 152 } 153 154 bool Interface::fillUnlinkToDeathMethod(Method *method) const { 155 if (method->name() != "unlinkToDeath") { 156 return false; 157 } 158 159 method->fillImplementation( 160 HIDL_UNLINK_TO_DEATH_TRANSACTION, 161 { 162 {IMPL_INTERFACE, 163 [](auto &out) { 164 out << "return (recipient != nullptr);\n"; 165 } 166 }, 167 {IMPL_PROXY, 168 [](auto &out) { 169 out << "std::unique_lock<std::mutex> lock(_hidl_mMutex);\n" 170 << "for (auto it = _hidl_mDeathRecipients.begin();" 171 << "it != _hidl_mDeathRecipients.end();" 172 << "++it) {\n"; 173 out.indent([&] { 174 out.sIf("(*it)->getRecipient() == recipient", [&] { 175 out << "::android::status_t status = remote()->unlinkToDeath(*it);\n" 176 << "_hidl_mDeathRecipients.erase(it);\n" 177 << "return status == ::android::OK;\n"; 178 }); 179 }); 180 out << "}\n"; 181 out << "return false;\n"; 182 } 183 }, 184 {IMPL_STUB, nullptr /* don't generate code */} 185 }, /*cppImpl*/ 186 { 187 {IMPL_INTERFACE, 188 [](auto &out) { 189 out << "return true;\n"; 190 } 191 }, 192 {IMPL_PROXY, 193 [](auto &out) { 194 out << "return mRemote.unlinkToDeath(recipient);\n"; 195 } 196 }, 197 {IMPL_STUB, nullptr /* don't generate code */} 198 } /*javaImpl*/ 199 ); 200 return true; 201 } 202 bool Interface::fillSyspropsChangedMethod(Method *method) const { 203 if (method->name() != "notifySyspropsChanged") { 204 return false; 205 } 206 207 method->fillImplementation( 208 HIDL_SYSPROPS_CHANGED_TRANSACTION, 209 { { IMPL_INTERFACE, [](auto &out) { 210 out << "::android::report_sysprop_change();\n"; 211 out << "return ::android::hardware::Void();"; 212 } } }, /*cppImpl */ 213 { { IMPL_INTERFACE, [](auto &out) { /* javaImpl */ 214 out << "android.os.SystemProperties.reportSyspropChanged();"; 215 } } } /*javaImpl */ 216 ); 217 return true; 218 } 219 220 bool Interface::fillSetHALInstrumentationMethod(Method *method) const { 221 if (method->name() != "setHALInstrumentation") { 222 return false; 223 } 224 225 method->fillImplementation( 226 HIDL_SET_HAL_INSTRUMENTATION_TRANSACTION, 227 { 228 {IMPL_INTERFACE, 229 [](auto &out) { 230 // do nothing for base class. 231 out << "return ::android::hardware::Void();\n"; 232 } 233 }, 234 {IMPL_STUB, 235 [](auto &out) { 236 out << "configureInstrumentation();\n"; 237 } 238 }, 239 {IMPL_PASSTHROUGH, 240 [](auto &out) { 241 out << "configureInstrumentation();\n"; 242 out << "return ::android::hardware::Void();\n"; 243 } 244 }, 245 }, /*cppImpl */ 246 { { IMPL_INTERFACE, [](auto & /*out*/) { /* javaImpl */ 247 // Not support for Java Impl for now. 248 } } } /*javaImpl */ 249 ); 250 return true; 251 } 252 253 bool Interface::fillDescriptorChainMethod(Method *method) const { 254 if (method->name() != "interfaceChain") { 255 return false; 256 } 257 258 method->fillImplementation( 259 HIDL_DESCRIPTOR_CHAIN_TRANSACTION, 260 { { IMPL_INTERFACE, [this](auto &out) { 261 std::vector<const Interface *> chain = typeChain(); 262 out << "_hidl_cb("; 263 out.block([&] { 264 for (const Interface *iface : chain) { 265 out << iface->fullName() << "::descriptor,\n"; 266 } 267 }); 268 out << ");\n"; 269 out << "return ::android::hardware::Void();"; 270 } } }, /* cppImpl */ 271 { { IMPL_INTERFACE, [this](auto &out) { 272 std::vector<const Interface *> chain = typeChain(); 273 out << "return new java.util.ArrayList<String>(java.util.Arrays.asList(\n"; 274 out.indent(); out.indent(); 275 for (size_t i = 0; i < chain.size(); ++i) { 276 if (i != 0) 277 out << ",\n"; 278 out << chain[i]->fullJavaName() << ".kInterfaceName"; 279 } 280 out << "));"; 281 out.unindent(); out.unindent(); 282 } } } /* javaImpl */ 283 ); 284 return true; 285 } 286 287 static void emitDigestChain( 288 Formatter &out, 289 const std::string &prefix, 290 const std::vector<const Interface *> &chain, 291 std::function<std::string(const ConstantExpression &)> byteToString) { 292 out.join(chain.begin(), chain.end(), ",\n", [&] (const auto &iface) { 293 const Hash &hash = Hash::getHash(iface->location().begin().filename()); 294 out << prefix; 295 out << "{"; 296 out.join(hash.raw().begin(), hash.raw().end(), ",", [&](const auto &e) { 297 // Use ConstantExpression::cppValue / javaValue 298 // because Java used signed byte for uint8_t. 299 out << byteToString(ConstantExpression::ValueOf(ScalarType::Kind::KIND_UINT8, e)); 300 }); 301 out << "} /* "; 302 out << hash.hexString(); 303 out << " */"; 304 }); 305 } 306 307 bool Interface::fillHashChainMethod(Method *method) const { 308 if (method->name() != "getHashChain") { 309 return false; 310 } 311 const VectorType *chainType = static_cast<const VectorType *>(&method->results()[0]->type()); 312 const ArrayType *digestType = static_cast<const ArrayType *>(chainType->getElementType()); 313 314 method->fillImplementation( 315 HIDL_HASH_CHAIN_TRANSACTION, 316 { { IMPL_INTERFACE, [this, digestType](auto &out) { 317 std::vector<const Interface *> chain = typeChain(); 318 out << "_hidl_cb("; 319 out.block([&] { 320 emitDigestChain(out, "(" + digestType->getInternalDataCppType() + ")", 321 chain, [](const auto &e){return e.cppValue();}); 322 }); 323 out << ");\n"; 324 out << "return ::android::hardware::Void();\n"; 325 } } }, /* cppImpl */ 326 { { IMPL_INTERFACE, [this, digestType, chainType](auto &out) { 327 std::vector<const Interface *> chain = typeChain(); 328 out << "return new " 329 << chainType->getJavaType(false /* forInitializer */) 330 << "(java.util.Arrays.asList(\n"; 331 out.indent(2, [&] { 332 // No need for dimensions when elements are explicitly provided. 333 emitDigestChain(out, "new " + digestType->getJavaType(false /* forInitializer */), 334 chain, [](const auto &e){return e.javaValue();}); 335 }); 336 out << "));\n"; 337 } } } /* javaImpl */ 338 ); 339 return true; 340 } 341 342 bool Interface::fillGetDescriptorMethod(Method *method) const { 343 if (method->name() != "interfaceDescriptor") { 344 return false; 345 } 346 347 method->fillImplementation( 348 HIDL_GET_DESCRIPTOR_TRANSACTION, 349 { { IMPL_INTERFACE, [this](auto &out) { 350 out << "_hidl_cb(" 351 << fullName() 352 << "::descriptor);\n" 353 << "return ::android::hardware::Void();"; 354 } } }, /* cppImpl */ 355 { { IMPL_INTERFACE, [this](auto &out) { 356 out << "return " 357 << fullJavaName() 358 << ".kInterfaceName;\n"; 359 } } } /* javaImpl */ 360 ); 361 return true; 362 } 363 364 bool Interface::fillGetDebugInfoMethod(Method *method) const { 365 if (method->name() != "getDebugInfo") { 366 return false; 367 } 368 369 static const std::string sArch = 370 "#if defined(__LP64__)\n" 371 "::android::hidl::base::V1_0::DebugInfo::Architecture::IS_64BIT\n" 372 "#else\n" 373 "::android::hidl::base::V1_0::DebugInfo::Architecture::IS_32BIT\n" 374 "#endif\n"; 375 376 method->fillImplementation( 377 HIDL_GET_REF_INFO_TRANSACTION, 378 { 379 {IMPL_INTERFACE, 380 [](auto &out) { 381 // getDebugInfo returns N/A for local objects. 382 out << "_hidl_cb({ -1 /* pid */, 0 /* ptr */, \n" 383 << sArch 384 << "});\n" 385 << "return ::android::hardware::Void();"; 386 } 387 }, 388 {IMPL_STUB_IMPL, 389 [](auto &out) { 390 out << "_hidl_cb("; 391 out.block([&] { 392 out << "::android::hardware::details::debuggable()" 393 << "? getpid() : -1 /* pid */,\n" 394 << "::android::hardware::details::debuggable()" 395 << "? reinterpret_cast<uint64_t>(this) : 0 /* ptr */,\n" 396 << sArch << "\n"; 397 }); 398 out << ");\n" 399 << "return ::android::hardware::Void();"; 400 } 401 } 402 }, /* cppImpl */ 403 { { IMPL_INTERFACE, [method](auto &out) { 404 const Type &refInfo = method->results().front()->type(); 405 out << refInfo.getJavaType(false /* forInitializer */) << " info = new " 406 << refInfo.getJavaType(true /* forInitializer */) << "();\n" 407 // TODO(b/34777099): PID for java. 408 << "info.pid = -1;\n" 409 << "info.ptr = 0;\n" 410 << "info.arch = android.hidl.base.V1_0.DebugInfo.Architecture.UNKNOWN;" 411 << "return info;"; 412 } } } /* javaImpl */ 413 ); 414 415 return true; 416 } 417 418 bool Interface::fillDebugMethod(Method *method) const { 419 if (method->name() != "debug") { 420 return false; 421 } 422 423 method->fillImplementation( 424 HIDL_DEBUG_TRANSACTION, 425 { 426 {IMPL_INTERFACE, 427 [](auto &out) { 428 out << "(void)fd;\n" 429 << "(void)options;\n" 430 << "return ::android::hardware::Void();"; 431 } 432 }, 433 }, /* cppImpl */ 434 { 435 /* unused, as the debug method is hidden from Java */ 436 } /* javaImpl */ 437 ); 438 439 return true; 440 } 441 442 static std::map<std::string, Method *> gAllReservedMethods; 443 444 bool Interface::addMethod(Method *method) { 445 if (isIBase()) { 446 if (!gAllReservedMethods.emplace(method->name(), method).second) { 447 LOG(ERROR) << "ERROR: hidl-gen encountered duplicated reserved method " 448 << method->name(); 449 return false; 450 } 451 // will add it in addAllReservedMethods 452 return true; 453 } 454 455 CHECK(!method->isHidlReserved()); 456 if (lookupMethod(method->name()) != nullptr) { 457 LOG(ERROR) << "Redefinition of method " << method->name(); 458 return false; 459 } 460 size_t serial = FIRST_CALL_TRANSACTION; 461 462 serial += userDefinedMethods().size(); 463 464 const Interface *ancestor = mSuperType; 465 while (ancestor != nullptr) { 466 serial += ancestor->userDefinedMethods().size(); 467 ancestor = ancestor->superType(); 468 } 469 470 CHECK(serial <= LAST_CALL_TRANSACTION) << "More than " 471 << LAST_CALL_TRANSACTION << " methods are not allowed."; 472 method->setSerialId(serial); 473 mUserMethods.push_back(method); 474 475 return true; 476 } 477 478 bool Interface::addAllReservedMethods() { 479 // use a sorted map to insert them in serial ID order. 480 std::map<int32_t, Method *> reservedMethodsById; 481 for (const auto &pair : gAllReservedMethods) { 482 Method *method = pair.second->copySignature(); 483 bool fillSuccess = fillPingMethod(method) 484 || fillDescriptorChainMethod(method) 485 || fillGetDescriptorMethod(method) 486 || fillHashChainMethod(method) 487 || fillSyspropsChangedMethod(method) 488 || fillLinkToDeathMethod(method) 489 || fillUnlinkToDeathMethod(method) 490 || fillSetHALInstrumentationMethod(method) 491 || fillGetDebugInfoMethod(method) 492 || fillDebugMethod(method); 493 494 if (!fillSuccess) { 495 LOG(ERROR) << "ERROR: hidl-gen does not recognize a reserved method " 496 << method->name(); 497 return false; 498 } 499 if (!reservedMethodsById.emplace(method->getSerialId(), method).second) { 500 LOG(ERROR) << "ERROR: hidl-gen uses duplicated serial id for " 501 << method->name() << " and " 502 << reservedMethodsById[method->getSerialId()]->name() 503 << ", serialId = " << method->getSerialId(); 504 return false; 505 } 506 } 507 for (const auto &pair : reservedMethodsById) { 508 this->mReservedMethods.push_back(pair.second); 509 } 510 return true; 511 } 512 513 const Interface *Interface::superType() const { 514 return mSuperType; 515 } 516 517 std::vector<const Interface *> Interface::typeChain() const { 518 std::vector<const Interface *> v; 519 const Interface *iface = this; 520 while (iface != nullptr) { 521 v.push_back(iface); 522 iface = iface->mSuperType; 523 } 524 return v; 525 } 526 527 std::vector<const Interface *> Interface::superTypeChain() const { 528 return superType()->typeChain(); // should work even if superType is nullptr 529 } 530 531 bool Interface::isElidableType() const { 532 return true; 533 } 534 535 bool Interface::isInterface() const { 536 return true; 537 } 538 539 bool Interface::isBinder() const { 540 return true; 541 } 542 543 const std::vector<Method *> &Interface::userDefinedMethods() const { 544 return mUserMethods; 545 } 546 547 const std::vector<Method *> &Interface::hidlReservedMethods() const { 548 return mReservedMethods; 549 } 550 551 std::vector<Method *> Interface::methods() const { 552 std::vector<Method *> v(mUserMethods); 553 v.insert(v.end(), mReservedMethods.begin(), mReservedMethods.end()); 554 return v; 555 } 556 557 std::vector<InterfaceAndMethod> Interface::allMethodsFromRoot() const { 558 std::vector<InterfaceAndMethod> v; 559 std::vector<const Interface *> chain = typeChain(); 560 for (auto it = chain.rbegin(); it != chain.rend(); ++it) { 561 const Interface *iface = *it; 562 for (Method *userMethod : iface->userDefinedMethods()) { 563 v.push_back(InterfaceAndMethod(iface, userMethod)); 564 } 565 } 566 for (Method *reservedMethod : hidlReservedMethods()) { 567 v.push_back(InterfaceAndMethod( 568 *chain.rbegin(), // IBase 569 reservedMethod)); 570 } 571 return v; 572 } 573 574 Method *Interface::lookupMethod(std::string name) const { 575 for (const auto &tuple : allMethodsFromRoot()) { 576 Method *method = tuple.method(); 577 if (method->name() == name) { 578 return method; 579 } 580 } 581 582 return nullptr; 583 } 584 585 std::string Interface::getBaseName() const { 586 return fqName().getInterfaceBaseName(); 587 } 588 589 std::string Interface::getProxyName() const { 590 return fqName().getInterfaceProxyName(); 591 } 592 593 std::string Interface::getStubName() const { 594 return fqName().getInterfaceStubName(); 595 } 596 597 std::string Interface::getHwName() const { 598 return fqName().getInterfaceHwName(); 599 } 600 601 std::string Interface::getPassthroughName() const { 602 return fqName().getInterfacePassthroughName(); 603 } 604 605 FQName Interface::getProxyFqName() const { 606 return fqName().getInterfaceProxyFqName(); 607 } 608 609 FQName Interface::getStubFqName() const { 610 return fqName().getInterfaceStubFqName(); 611 } 612 613 FQName Interface::getPassthroughFqName() const { 614 return fqName().getInterfacePassthroughFqName(); 615 } 616 617 std::string Interface::getCppType(StorageMode mode, 618 bool specifyNamespaces) const { 619 const std::string base = 620 std::string(specifyNamespaces ? "::android::" : "") 621 + "sp<" 622 + fullName() 623 + ">"; 624 625 switch (mode) { 626 case StorageMode_Stack: 627 case StorageMode_Result: 628 return base; 629 630 case StorageMode_Argument: 631 return "const " + base + "&"; 632 } 633 } 634 635 std::string Interface::getJavaType(bool /* forInitializer */) const { 636 return fullJavaName(); 637 } 638 639 std::string Interface::getVtsType() const { 640 if (StringHelper::EndsWith(localName(), "Callback")) { 641 return "TYPE_HIDL_CALLBACK"; 642 } else { 643 return "TYPE_HIDL_INTERFACE"; 644 } 645 } 646 647 void Interface::emitReaderWriter( 648 Formatter &out, 649 const std::string &name, 650 const std::string &parcelObj, 651 bool parcelObjIsPointer, 652 bool isReader, 653 ErrorMode mode) const { 654 const std::string parcelObjDeref = 655 parcelObj + (parcelObjIsPointer ? "->" : "."); 656 657 if (isReader) { 658 out << "{\n"; 659 out.indent(); 660 661 const std::string binderName = "_hidl_" + name + "_binder"; 662 663 out << "::android::sp<::android::hardware::IBinder> " 664 << binderName << ";\n"; 665 666 out << "_hidl_err = "; 667 out << parcelObjDeref 668 << "readNullableStrongBinder(&" 669 << binderName 670 << ");\n"; 671 672 handleError(out, mode); 673 674 out << name 675 << " = " 676 << "::android::hardware::fromBinder<" 677 << fqName().cppName() 678 << "," 679 << getProxyFqName().cppName() 680 << "," 681 << getStubFqName().cppName() 682 << ">(" 683 << binderName 684 << ");\n"; 685 686 out.unindent(); 687 out << "}\n\n"; 688 } else { 689 out << "if (" << name << " == nullptr) {\n"; 690 out.indent(); 691 out << "_hidl_err = "; 692 out << parcelObjDeref 693 << "writeStrongBinder(nullptr);\n"; 694 out.unindent(); 695 out << "} else {\n"; 696 out.indent(); 697 out << "::android::sp<::android::hardware::IBinder> _hidl_binder = " 698 << "::android::hardware::toBinder<\n"; 699 out.indent(2, [&] { 700 out << fqName().cppName() 701 << ">(" 702 << name 703 << ");\n"; 704 }); 705 out << "if (_hidl_binder.get() != nullptr) {\n"; 706 out.indent([&] { 707 out << "_hidl_err = " 708 << parcelObjDeref 709 << "writeStrongBinder(_hidl_binder);\n"; 710 }); 711 out << "} else {\n"; 712 out.indent([&] { 713 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n"; 714 }); 715 out << "}\n"; 716 out.unindent(); 717 out << "}\n"; 718 719 handleError(out, mode); 720 } 721 } 722 723 status_t Interface::emitGlobalTypeDeclarations(Formatter &out) const { 724 status_t status = Scope::emitGlobalTypeDeclarations(out); 725 if (status != OK) { 726 return status; 727 } 728 out << "std::string toString(" 729 << getCppArgumentType() 730 << ");\n"; 731 return OK; 732 } 733 734 735 status_t Interface::emitTypeDefinitions( 736 Formatter &out, const std::string prefix) const { 737 std::string space = prefix.empty() ? "" : (prefix + "::"); 738 status_t err = Scope::emitTypeDefinitions(out, space + localName()); 739 if (err != OK) { 740 return err; 741 } 742 743 out << "std::string toString(" 744 << getCppArgumentType() 745 << " o) "; 746 747 out.block([&] { 748 out << "std::string os = \"[class or subclass of \";\n" 749 << "os += " << fullName() << "::descriptor;\n" 750 << "os += \"]\";\n" 751 << "os += o->isRemote() ? \"@remote\" : \"@local\";\n" 752 << "return os;\n"; 753 }).endl().endl(); 754 755 return OK; 756 } 757 758 void Interface::emitJavaReaderWriter( 759 Formatter &out, 760 const std::string &parcelObj, 761 const std::string &argName, 762 bool isReader) const { 763 if (isReader) { 764 out << fullJavaName() 765 << ".asInterface(" 766 << parcelObj 767 << ".readStrongBinder());\n"; 768 } else { 769 out << parcelObj 770 << ".writeStrongBinder(" 771 << argName 772 << " == null ? null : " 773 << argName 774 << ".asBinder());\n"; 775 } 776 } 777 778 status_t Interface::emitVtsAttributeDeclaration(Formatter &out) const { 779 for (const auto &type : getSubTypes()) { 780 // Skip for TypeDef as it is just an alias of a defined type. 781 if (type->isTypeDef()) { 782 continue; 783 } 784 out << "attribute: {\n"; 785 out.indent(); 786 status_t status = type->emitVtsTypeDeclarations(out); 787 if (status != OK) { 788 return status; 789 } 790 out.unindent(); 791 out << "}\n\n"; 792 } 793 return OK; 794 } 795 796 status_t Interface::emitVtsMethodDeclaration(Formatter &out) const { 797 for (const auto &method : methods()) { 798 if (method->isHidlReserved()) { 799 continue; 800 } 801 802 out << "api: {\n"; 803 out.indent(); 804 out << "name: \"" << method->name() << "\"\n"; 805 // Generate declaration for each return value. 806 for (const auto &result : method->results()) { 807 out << "return_type_hidl: {\n"; 808 out.indent(); 809 status_t status = result->type().emitVtsAttributeType(out); 810 if (status != OK) { 811 return status; 812 } 813 out.unindent(); 814 out << "}\n"; 815 } 816 // Generate declaration for each input argument 817 for (const auto &arg : method->args()) { 818 out << "arg: {\n"; 819 out.indent(); 820 status_t status = arg->type().emitVtsAttributeType(out); 821 if (status != OK) { 822 return status; 823 } 824 out.unindent(); 825 out << "}\n"; 826 } 827 // Generate declaration for each annotation. 828 for (const auto &annotation : method->annotations()) { 829 out << "callflow: {\n"; 830 out.indent(); 831 std::string name = annotation->name(); 832 if (name == "entry") { 833 out << "entry: true\n"; 834 } else if (name == "exit") { 835 out << "exit: true\n"; 836 } else if (name == "callflow") { 837 const AnnotationParam *param = 838 annotation->getParam("next"); 839 if (param != nullptr) { 840 for (auto value : *param->getValues()) { 841 out << "next: " << value << "\n"; 842 } 843 } 844 } else { 845 std::cerr << "Unrecognized annotation '" 846 << name << "' for method: " << method->name() 847 << ". A VTS annotation should be one of: " 848 << "entry, exit, callflow. \n"; 849 } 850 out.unindent(); 851 out << "}\n"; 852 } 853 out.unindent(); 854 out << "}\n\n"; 855 } 856 return OK; 857 } 858 859 status_t Interface::emitVtsAttributeType(Formatter &out) const { 860 out << "type: " << getVtsType() << "\n" 861 << "predefined_type: \"" 862 << fullName() 863 << "\"\n"; 864 return OK; 865 } 866 867 bool Interface::hasOnewayMethods() const { 868 for (auto const &method : methods()) { 869 if (method->isOneway()) { 870 return true; 871 } 872 } 873 874 const Interface* superClass = superType(); 875 876 if (superClass != nullptr) { 877 return superClass->hasOnewayMethods(); 878 } 879 880 return false; 881 } 882 883 bool Interface::isJavaCompatible() const { 884 if (mIsJavaCompatibleInProgress) { 885 // We're currently trying to determine if this Interface is 886 // java-compatible and something is referencing this interface through 887 // one of its methods. Assume we'll ultimately succeed, if we were wrong 888 // the original invocation of Interface::isJavaCompatible() will then 889 // return the correct "false" result. 890 return true; 891 } 892 893 if (mSuperType != nullptr && !mSuperType->isJavaCompatible()) { 894 mIsJavaCompatibleInProgress = false; 895 return false; 896 } 897 898 mIsJavaCompatibleInProgress = true; 899 900 if (!Scope::isJavaCompatible()) { 901 mIsJavaCompatibleInProgress = false; 902 return false; 903 } 904 905 for (const auto &method : methods()) { 906 if (!method->isJavaCompatible()) { 907 mIsJavaCompatibleInProgress = false; 908 return false; 909 } 910 } 911 912 mIsJavaCompatibleInProgress = false; 913 914 return true; 915 } 916 917 } // namespace android 918 919