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