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 "AST.h" 18 19 #include "Coordinator.h" 20 #include "Interface.h" 21 #include "Method.h" 22 #include "Scope.h" 23 24 #include <hidl-util/Formatter.h> 25 #include <android-base/logging.h> 26 27 namespace android { 28 29 void AST::emitJavaReaderWriter( 30 Formatter &out, 31 const std::string &parcelObj, 32 const TypedVar *arg, 33 bool isReader, 34 bool addPrefixToName) const { 35 if (isReader) { 36 out << arg->type().getJavaType() 37 << " " 38 << (addPrefixToName ? "_hidl_out_" : "") 39 << arg->name() 40 << " = "; 41 } 42 43 arg->type().emitJavaReaderWriter(out, parcelObj, 44 (addPrefixToName ? "_hidl_out_" : "") + arg->name(), 45 isReader); 46 } 47 48 status_t AST::generateJavaTypes( 49 const std::string &outputPath, const std::string &limitToType) const { 50 // Splits types.hal up into one java file per declared type. 51 52 for (const auto &type : mRootScope->getSubTypes()) { 53 std::string typeName = type->localName(); 54 55 if (type->isTypeDef()) { 56 continue; 57 } 58 59 if (!limitToType.empty() && typeName != limitToType) { 60 continue; 61 } 62 63 std::string path = outputPath; 64 path.append(mCoordinator->convertPackageRootToPath(mPackage)); 65 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */, 66 true /* sanitized */)); 67 path.append(typeName); 68 path.append(".java"); 69 70 CHECK(Coordinator::MakeParentHierarchy(path)); 71 FILE *file = fopen(path.c_str(), "w"); 72 73 if (file == NULL) { 74 return -errno; 75 } 76 77 Formatter out(file); 78 79 std::vector<std::string> packageComponents; 80 getPackageAndVersionComponents( 81 &packageComponents, true /* cpp_compatible */); 82 83 out << "package " << mPackage.javaPackage() << ";\n\n"; 84 85 out << "\n"; 86 87 status_t err = 88 type->emitJavaTypeDeclarations(out, true /* atTopLevel */); 89 90 if (err != OK) { 91 return err; 92 } 93 } 94 95 return OK; 96 } 97 98 status_t AST::generateJava( 99 const std::string &outputPath, const std::string &limitToType) const { 100 if (!isJavaCompatible()) { 101 fprintf(stderr, 102 "ERROR: This interface is not Java compatible. The Java backend" 103 " does NOT support union types nor native handles. " 104 "In addition, vectors of arrays are limited to at most " 105 "one-dimensional arrays and vectors of {vectors,interfaces} are" 106 " not supported.\n"); 107 108 return UNKNOWN_ERROR; 109 } 110 111 std::string ifaceName; 112 if (!AST::isInterface(&ifaceName)) { 113 return generateJavaTypes(outputPath, limitToType); 114 } 115 116 const Interface *iface = mRootScope->getInterface(); 117 118 const std::string baseName = iface->getBaseName(); 119 120 std::string path = outputPath; 121 path.append(mCoordinator->convertPackageRootToPath(mPackage)); 122 path.append(mCoordinator->getPackagePath(mPackage, true /* relative */, 123 true /* sanitized */)); 124 path.append(ifaceName); 125 path.append(".java"); 126 127 CHECK(Coordinator::MakeParentHierarchy(path)); 128 FILE *file = fopen(path.c_str(), "w"); 129 130 if (file == NULL) { 131 return -errno; 132 } 133 134 Formatter out(file); 135 136 std::vector<std::string> packageComponents; 137 getPackageAndVersionComponents( 138 &packageComponents, true /* cpp_compatible */); 139 140 out << "package " << mPackage.javaPackage() << ";\n\n"; 141 142 out.setNamespace(mPackage.javaPackage() + "."); 143 144 const Interface *superType = iface->superType(); 145 146 out << "public interface " << ifaceName << " extends "; 147 148 if (superType != NULL) { 149 out << superType->fullJavaName(); 150 } else { 151 out << "android.os.IHwInterface"; 152 } 153 154 out << " {\n"; 155 out.indent(); 156 157 out << "public static final String kInterfaceName = \"" 158 << mPackage.string() 159 << "::" 160 << ifaceName 161 << "\";\n\n"; 162 163 out << "/* package private */ static " 164 << ifaceName 165 << " asInterface(android.os.IHwBinder binder) {\n"; 166 167 out.indent(); 168 169 out << "if (binder == null) {\n"; 170 out.indent(); 171 out << "return null;\n"; 172 out.unindent(); 173 out << "}\n\n"; 174 175 out << "android.os.IHwInterface iface =\n"; 176 out.indent(); 177 out.indent(); 178 out << "binder.queryLocalInterface(kInterfaceName);\n\n"; 179 out.unindent(); 180 out.unindent(); 181 182 out << "if ((iface != null) && (iface instanceof " 183 << ifaceName 184 << ")) {\n"; 185 186 out.indent(); 187 out << "return (" << ifaceName << ")iface;\n"; 188 out.unindent(); 189 out << "}\n\n"; 190 191 out << ifaceName << " proxy = new " << ifaceName << ".Proxy(binder);\n\n"; 192 out << "try {\n"; 193 out.indent(); 194 out << "for (String descriptor : proxy.interfaceChain()) {\n"; 195 out.indent(); 196 out << "if (descriptor.equals(kInterfaceName)) {\n"; 197 out.indent(); 198 out << "return proxy;\n"; 199 out.unindent(); 200 out << "}\n"; 201 out.unindent(); 202 out << "}\n"; 203 out.unindent(); 204 out << "} catch (android.os.RemoteException e) {\n"; 205 out.indent(); 206 out.unindent(); 207 out << "}\n\n"; 208 209 out << "return null;\n"; 210 211 out.unindent(); 212 out << "}\n\n"; 213 214 out << "public static " 215 << ifaceName 216 << " castFrom(android.os.IHwInterface iface) {\n"; 217 out.indent(); 218 219 out << "return (iface == null) ? null : " 220 << ifaceName 221 << ".asInterface(iface.asBinder());\n"; 222 223 out.unindent(); 224 out << "}\n\n"; 225 226 out << "@Override\npublic android.os.IHwBinder asBinder();\n\n"; 227 228 out << "public static " 229 << ifaceName 230 << " getService(String serviceName) throws android.os.RemoteException {\n"; 231 232 out.indent(); 233 234 out << "return " 235 << ifaceName 236 << ".asInterface(android.os.HwBinder.getService(\"" 237 << iface->fqName().string() 238 << "\",serviceName));\n"; 239 240 out.unindent(); 241 242 out << "}\n\n"; 243 244 out << "public static " 245 << ifaceName 246 << " getService() throws android.os.RemoteException {\n"; 247 248 out.indent(); 249 250 out << "return " 251 << ifaceName 252 << ".asInterface(android.os.HwBinder.getService(\"" 253 << iface->fqName().string() 254 << "\",\"default\"));\n"; 255 256 out.unindent(); 257 258 out << "}\n\n"; 259 260 status_t err = emitJavaTypeDeclarations(out); 261 262 if (err != OK) { 263 return err; 264 } 265 266 for (const auto &method : iface->methods()) { 267 if (method->isHiddenFromJava()) { 268 continue; 269 } 270 271 const bool returnsValue = !method->results().empty(); 272 const bool needsCallback = method->results().size() > 1; 273 274 if (needsCallback) { 275 out << "\npublic interface " 276 << method->name() 277 << "Callback {\n"; 278 279 out.indent(); 280 281 out << "public void onValues("; 282 method->emitJavaResultSignature(out); 283 out << ");\n"; 284 285 out.unindent(); 286 out << "}\n\n"; 287 } 288 289 if (returnsValue && !needsCallback) { 290 out << method->results()[0]->type().getJavaType(); 291 } else { 292 out << "void"; 293 } 294 295 out << " " 296 << method->name() 297 << "("; 298 method->emitJavaArgSignature(out); 299 300 if (needsCallback) { 301 if (!method->args().empty()) { 302 out << ", "; 303 } 304 305 out << method->name() 306 << "Callback cb"; 307 } 308 309 out << ")\n"; 310 out.indent(); 311 out << "throws android.os.RemoteException;\n"; 312 out.unindent(); 313 } 314 315 out << "\npublic static final class Proxy implements " 316 << ifaceName 317 << " {\n"; 318 319 out.indent(); 320 321 out << "private android.os.IHwBinder mRemote;\n\n"; 322 out << "public Proxy(android.os.IHwBinder remote) {\n"; 323 out.indent(); 324 out << "mRemote = java.util.Objects.requireNonNull(remote);\n"; 325 out.unindent(); 326 out << "}\n\n"; 327 328 out << "@Override\npublic android.os.IHwBinder asBinder() {\n"; 329 out.indent(); 330 out << "return mRemote;\n"; 331 out.unindent(); 332 out << "}\n\n"; 333 334 335 out << "@Override\npublic String toString() "; 336 out.block([&] { 337 out.sTry([&] { 338 out << "return this.interfaceDescriptor() + \"@Proxy\";\n"; 339 }).sCatch("android.os.RemoteException ex", [&] { 340 out << "/* ignored; handled below. */\n"; 341 }).endl(); 342 out << "return \"[class or subclass of \" + " 343 << ifaceName << ".kInterfaceName + \"]@Proxy\";\n"; 344 }).endl().endl(); 345 346 const Interface *prevInterface = nullptr; 347 for (const auto &tuple : iface->allMethodsFromRoot()) { 348 const Method *method = tuple.method(); 349 350 if (method->isHiddenFromJava()) { 351 continue; 352 } 353 354 const Interface *superInterface = tuple.interface(); 355 if (prevInterface != superInterface) { 356 out << "// Methods from " 357 << superInterface->fullName() 358 << " follow.\n"; 359 prevInterface = superInterface; 360 } 361 const bool returnsValue = !method->results().empty(); 362 const bool needsCallback = method->results().size() > 1; 363 364 out << "@Override\npublic "; 365 if (returnsValue && !needsCallback) { 366 out << method->results()[0]->type().getJavaType(); 367 } else { 368 out << "void"; 369 } 370 371 out << " " 372 << method->name() 373 << "("; 374 method->emitJavaArgSignature(out); 375 376 if (needsCallback) { 377 if (!method->args().empty()) { 378 out << ", "; 379 } 380 381 out << method->name() 382 << "Callback cb"; 383 } 384 385 out << ")\n"; 386 out.indent(); 387 out.indent(); 388 out << "throws android.os.RemoteException {\n"; 389 out.unindent(); 390 391 if (method->isHidlReserved() && method->overridesJavaImpl(IMPL_PROXY)) { 392 method->javaImpl(IMPL_PROXY, out); 393 out.unindent(); 394 out << "}\n"; 395 continue; 396 } 397 out << "android.os.HwParcel _hidl_request = new android.os.HwParcel();\n"; 398 out << "_hidl_request.writeInterfaceToken(" 399 << superInterface->fullJavaName() 400 << ".kInterfaceName);\n"; 401 402 for (const auto &arg : method->args()) { 403 emitJavaReaderWriter( 404 out, 405 "_hidl_request", 406 arg, 407 false /* isReader */, 408 false /* addPrefixToName */); 409 } 410 411 out << "\nandroid.os.HwParcel _hidl_reply = new android.os.HwParcel();\n"; 412 413 out.sTry([&] { 414 out << "mRemote.transact(" 415 << method->getSerialId() 416 << " /* " 417 << method->name() 418 << " */, _hidl_request, _hidl_reply, "; 419 420 if (method->isOneway()) { 421 out << "android.os.IHwBinder.FLAG_ONEWAY"; 422 } else { 423 out << "0 /* flags */"; 424 } 425 426 out << ");\n"; 427 428 if (!method->isOneway()) { 429 out << "_hidl_reply.verifySuccess();\n"; 430 } else { 431 CHECK(!returnsValue); 432 } 433 434 out << "_hidl_request.releaseTemporaryStorage();\n"; 435 436 if (returnsValue) { 437 out << "\n"; 438 439 for (const auto &arg : method->results()) { 440 emitJavaReaderWriter( 441 out, 442 "_hidl_reply", 443 arg, 444 true /* isReader */, 445 true /* addPrefixToName */); 446 } 447 448 if (needsCallback) { 449 out << "cb.onValues("; 450 451 bool firstField = true; 452 for (const auto &arg : method->results()) { 453 if (!firstField) { 454 out << ", "; 455 } 456 457 out << "_hidl_out_" << arg->name(); 458 firstField = false; 459 } 460 461 out << ");\n"; 462 } else { 463 const std::string returnName = method->results()[0]->name(); 464 out << "return _hidl_out_" << returnName << ";\n"; 465 } 466 } 467 }).sFinally([&] { 468 out << "_hidl_reply.release();\n"; 469 }).endl(); 470 471 out.unindent(); 472 out << "}\n\n"; 473 } 474 475 out.unindent(); 476 out << "}\n"; 477 478 //////////////////////////////////////////////////////////////////////////// 479 480 out << "\npublic static abstract class Stub extends android.os.HwBinder " 481 << "implements " 482 << ifaceName << " {\n"; 483 484 out.indent(); 485 486 out << "@Override\npublic android.os.IHwBinder asBinder() {\n"; 487 out.indent(); 488 out << "return this;\n"; 489 out.unindent(); 490 out << "}\n\n"; 491 492 for (Method *method : iface->hidlReservedMethods()) { 493 if (method->isHiddenFromJava()) { 494 continue; 495 } 496 497 // b/32383557 this is a hack. We need to change this if we have more reserved methods. 498 CHECK_LE(method->results().size(), 1u); 499 std::string resultType = method->results().size() == 0 ? "void" : 500 method->results()[0]->type().getJavaType(); 501 out << "@Override\npublic final " 502 << resultType 503 << " " 504 << method->name() 505 << "("; 506 method->emitJavaArgSignature(out); 507 out << ") {\n"; 508 509 out.indent(); 510 method->javaImpl(IMPL_INTERFACE, out); 511 out.unindent(); 512 out << "\n}\n\n"; 513 } 514 515 out << "@Override\n" 516 << "public android.os.IHwInterface queryLocalInterface(String descriptor) {\n"; 517 out.indent(); 518 // XXX what about potential superClasses? 519 out << "if (kInterfaceName.equals(descriptor)) {\n"; 520 out.indent(); 521 out << "return this;\n"; 522 out.unindent(); 523 out << "}\n"; 524 out << "return null;\n"; 525 out.unindent(); 526 out << "}\n\n"; 527 528 out << "public void registerAsService(String serviceName) throws android.os.RemoteException {\n"; 529 out.indent(); 530 531 out << "registerService(serviceName);\n"; 532 533 out.unindent(); 534 out << "}\n\n"; 535 536 out << "@Override\npublic String toString() "; 537 out.block([&] { 538 out << "return this.interfaceDescriptor() + \"@Stub\";\n"; 539 }).endl().endl(); 540 541 out << "@Override\n" 542 << "public void onTransact(" 543 << "int _hidl_code, " 544 << "android.os.HwParcel _hidl_request, " 545 << "final android.os.HwParcel _hidl_reply, " 546 << "int _hidl_flags)\n"; 547 out.indent(); 548 out.indent(); 549 out << "throws android.os.RemoteException {\n"; 550 out.unindent(); 551 552 out << "switch (_hidl_code) {\n"; 553 554 out.indent(); 555 556 for (const auto &tuple : iface->allMethodsFromRoot()) { 557 const Method *method = tuple.method(); 558 559 const Interface *superInterface = tuple.interface(); 560 const bool returnsValue = !method->results().empty(); 561 const bool needsCallback = method->results().size() > 1; 562 563 out << "case " 564 << method->getSerialId() 565 << " /* " 566 << method->name() 567 << " */:\n{\n"; 568 569 out.indent(); 570 571 if (method->isHidlReserved() && method->overridesJavaImpl(IMPL_STUB)) { 572 method->javaImpl(IMPL_STUB, out); 573 out.unindent(); 574 out << "break;\n"; 575 out << "}\n\n"; 576 continue; 577 } 578 579 out << "_hidl_request.enforceInterface(" 580 << superInterface->fullJavaName() 581 << ".kInterfaceName);\n\n"; 582 583 if (method->isHiddenFromJava()) { 584 // This is a method hidden from the Java side of things, it must not 585 // return any value and will simply signal success. 586 CHECK(!returnsValue); 587 588 out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n"; 589 out << "_hidl_reply.send();\n"; 590 out << "break;\n"; 591 out.unindent(); 592 out << "}\n\n"; 593 continue; 594 } 595 596 for (const auto &arg : method->args()) { 597 emitJavaReaderWriter( 598 out, 599 "_hidl_request", 600 arg, 601 true /* isReader */, 602 false /* addPrefixToName */); 603 } 604 605 if (!needsCallback && returnsValue) { 606 const TypedVar *returnArg = method->results()[0]; 607 608 out << returnArg->type().getJavaType() 609 << " _hidl_out_" 610 << returnArg->name() 611 << " = "; 612 } 613 614 out << method->name() 615 << "("; 616 617 bool firstField = true; 618 for (const auto &arg : method->args()) { 619 if (!firstField) { 620 out << ", "; 621 } 622 623 out << arg->name(); 624 625 firstField = false; 626 } 627 628 if (needsCallback) { 629 if (!firstField) { 630 out << ", "; 631 } 632 633 out << "new " << method->name() << "Callback() {\n"; 634 out.indent(); 635 636 out << "@Override\n" 637 << "public void onValues("; 638 method->emitJavaResultSignature(out); 639 out << ") {\n"; 640 641 out.indent(); 642 out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n"; 643 644 for (const auto &arg : method->results()) { 645 emitJavaReaderWriter( 646 out, 647 "_hidl_reply", 648 arg, 649 false /* isReader */, 650 false /* addPrefixToName */); 651 // no need to add _hidl_out because out vars are are scoped 652 } 653 654 out << "_hidl_reply.send();\n" 655 << "}}"; 656 657 out.unindent(); 658 out.unindent(); 659 } 660 661 out << ");\n"; 662 663 if (!needsCallback && !method->isOneway()) { 664 out << "_hidl_reply.writeStatus(android.os.HwParcel.STATUS_SUCCESS);\n"; 665 666 if (returnsValue) { 667 const TypedVar *returnArg = method->results()[0]; 668 669 emitJavaReaderWriter( 670 out, 671 "_hidl_reply", 672 returnArg, 673 false /* isReader */, 674 true /* addPrefixToName */); 675 } 676 677 out << "_hidl_reply.send();\n"; 678 } 679 680 out << "break;\n"; 681 out.unindent(); 682 out << "}\n\n"; 683 } 684 685 out.unindent(); 686 out << "}\n"; 687 688 out.unindent(); 689 out << "}\n"; 690 691 out.unindent(); 692 out << "}\n"; 693 694 out.unindent(); 695 out << "}\n"; 696 697 return OK; 698 } 699 700 status_t AST::emitJavaTypeDeclarations(Formatter &out) const { 701 return mRootScope->emitJavaTypeDeclarations(out, false /* atTopLevel */); 702 } 703 704 } // namespace android 705