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 "VectorType.h" 18 19 #include "ArrayType.h" 20 #include "CompoundType.h" 21 #include "HidlTypeAssertion.h" 22 23 #include <hidl-util/Formatter.h> 24 #include <android-base/logging.h> 25 26 namespace android { 27 28 VectorType::VectorType(Scope* parent) : TemplatedType(parent) {} 29 30 std::string VectorType::templatedTypeName() const { 31 return "vector"; 32 } 33 34 bool VectorType::isCompatibleElementType(const Type* elementType) const { 35 if (elementType->isScalar()) { 36 return true; 37 } 38 if (elementType->isString()) { 39 return true; 40 } 41 if (elementType->isEnum()) { 42 return true; 43 } 44 if (elementType->isBitField()) { 45 return true; 46 } 47 if (elementType->isCompoundType()) { 48 return true; 49 } 50 if (elementType->isInterface()) { 51 return true; 52 } 53 if (elementType->isHandle()) { 54 return true; 55 } 56 if (elementType->isMemory()) { 57 return true; 58 } 59 if (elementType->isTemplatedType()) { 60 const Type* inner = static_cast<const TemplatedType*>(elementType)->getElementType(); 61 return this->isCompatibleElementType(inner) && !inner->isInterface(); 62 } 63 if (elementType->isArray()) { 64 const Type* inner = static_cast<const ArrayType*>(elementType)->getElementType(); 65 return this->isCompatibleElementType(inner) && !inner->isInterface(); 66 } 67 return false; 68 } 69 70 bool VectorType::isVector() const { 71 return true; 72 } 73 74 bool VectorType::isVectorOfBinders() const { 75 return mElementType->isBinder(); 76 } 77 78 bool VectorType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const { 79 return mElementType->canCheckEquality(visited); 80 } 81 82 std::vector<const Reference<Type>*> VectorType::getStrongReferences() const { 83 return {}; 84 } 85 86 std::string VectorType::getCppType(StorageMode mode, 87 bool specifyNamespaces) const { 88 const std::string base = 89 std::string(specifyNamespaces ? "::android::hardware::" : "") 90 + "hidl_vec<" 91 + mElementType->getCppStackType( specifyNamespaces) 92 + ">"; 93 94 switch (mode) { 95 case StorageMode_Stack: 96 return base; 97 98 case StorageMode_Argument: 99 return "const " + base + "&"; 100 101 case StorageMode_Result: 102 { 103 if (isVectorOfBinders()) { 104 return base; 105 } 106 107 return "const " + base + "*"; 108 } 109 } 110 } 111 112 std::string VectorType::getJavaType(bool /* forInitializer */) const { 113 114 std::string elementJavaType; 115 if (mElementType->isArray()) { 116 elementJavaType = mElementType->getJavaType(); 117 } else { 118 elementJavaType = mElementType->getJavaWrapperType(); 119 } 120 121 return "java.util.ArrayList<" 122 + elementJavaType 123 + ">"; 124 } 125 126 std::string VectorType::getVtsType() const { 127 return "TYPE_VECTOR"; 128 } 129 130 std::string VectorType::getVtsValueName() const { 131 return "vector_value"; 132 } 133 134 void VectorType::emitReaderWriter( 135 Formatter &out, 136 const std::string &name, 137 const std::string &parcelObj, 138 bool parcelObjIsPointer, 139 bool isReader, 140 ErrorMode mode) const { 141 if (isVectorOfBinders()) { 142 emitReaderWriterForVectorOfBinders( 143 out, name, parcelObj, parcelObjIsPointer, isReader, mode); 144 145 return; 146 } 147 148 std::string baseType = mElementType->getCppStackType(); 149 150 const std::string parentName = "_hidl_" + name + "_parent"; 151 152 out << "size_t " << parentName << ";\n\n"; 153 154 const std::string parcelObjDeref = 155 parcelObj + (parcelObjIsPointer ? "->" : "."); 156 157 if (isReader) { 158 out << "_hidl_err = " 159 << parcelObjDeref 160 << "readBuffer(" 161 << "sizeof(*" 162 << name 163 << "), &" 164 << parentName 165 << ", " 166 << " reinterpret_cast<const void **>(" 167 << "&" << name 168 << "));\n\n"; 169 170 handleError(out, mode); 171 } else { 172 out << "_hidl_err = " 173 << parcelObjDeref 174 << "writeBuffer(&" 175 << name 176 << ", sizeof(" 177 << name 178 << "), &" 179 << parentName 180 << ");\n"; 181 182 handleError(out, mode); 183 } 184 185 emitReaderWriterEmbedded( 186 out, 187 0 /* depth */, 188 name, 189 name /* sanitizedName */ , 190 isReader /* nameIsPointer */, 191 parcelObj, 192 parcelObjIsPointer, 193 isReader, 194 mode, 195 parentName, 196 "0 /* parentOffset */"); 197 } 198 199 void VectorType::emitReaderWriterForVectorOfBinders( 200 Formatter &out, 201 const std::string &name, 202 const std::string &parcelObj, 203 bool parcelObjIsPointer, 204 bool isReader, 205 ErrorMode mode) const { 206 const std::string parcelObjDeref = 207 parcelObj + (parcelObjIsPointer ? "->" : "."); 208 209 if (isReader) { 210 out << "{\n"; 211 out.indent(); 212 213 const std::string sizeName = "_hidl_" + name + "_size"; 214 215 out << "uint64_t " 216 << sizeName 217 << ";\n"; 218 219 out << "_hidl_err = " 220 << parcelObjDeref 221 << "readUint64(&" 222 << sizeName 223 << ");\n"; 224 225 handleError(out, mode); 226 227 out << name 228 << ".resize(" 229 << sizeName 230 << ");\n\n" 231 << "for (size_t _hidl_index = 0; _hidl_index < " 232 << sizeName 233 << "; ++_hidl_index) {\n"; 234 235 out.indent(); 236 237 out << mElementType->getCppStackType(true /* specifyNamespaces */) 238 << " _hidl_base;\n"; 239 240 mElementType->emitReaderWriter( 241 out, 242 "_hidl_base", 243 parcelObj, 244 parcelObjIsPointer, 245 isReader, 246 mode); 247 248 out << name 249 << "[_hidl_index] = _hidl_base;\n"; 250 251 out.unindent(); 252 out << "}\n"; 253 254 out.unindent(); 255 out << "}\n"; 256 } else { 257 out << "_hidl_err = " 258 << parcelObjDeref 259 << "writeUint64(" 260 << name 261 << ".size());\n"; 262 263 handleError(out, mode); 264 265 out << "for (size_t _hidl_index = 0; _hidl_index < " 266 << name 267 << ".size(); ++_hidl_index) {\n"; 268 269 out.indent(); 270 271 mElementType->emitReaderWriter( 272 out, 273 name + "[_hidl_index]", 274 parcelObj, 275 parcelObjIsPointer, 276 isReader, 277 mode); 278 279 out.unindent(); 280 out << "}\n"; 281 } 282 } 283 284 void VectorType::emitReaderWriterEmbedded( 285 Formatter &out, 286 size_t depth, 287 const std::string &name, 288 const std::string &sanitizedName, 289 bool nameIsPointer, 290 const std::string &parcelObj, 291 bool parcelObjIsPointer, 292 bool isReader, 293 ErrorMode mode, 294 const std::string &parentName, 295 const std::string &offsetText) const { 296 std::string baseType = getCppStackType(); 297 298 const std::string childName = "_hidl_" + sanitizedName + "_child"; 299 out << "size_t " << childName << ";\n\n"; 300 301 emitReaderWriterEmbeddedForTypeName( 302 out, 303 name, 304 nameIsPointer, 305 parcelObj, 306 parcelObjIsPointer, 307 isReader, 308 mode, 309 parentName, 310 offsetText, 311 baseType, 312 childName, 313 "::android::hardware"); 314 315 if (!mElementType->needsEmbeddedReadWrite()) { 316 return; 317 } 318 319 const std::string nameDeref = name + (nameIsPointer ? "->" : "."); 320 321 baseType = mElementType->getCppStackType(); 322 323 std::string iteratorName = "_hidl_index_" + std::to_string(depth); 324 325 out << "for (size_t " 326 << iteratorName 327 << " = 0; " 328 << iteratorName 329 << " < " 330 << nameDeref 331 << "size(); ++" 332 << iteratorName 333 << ") {\n"; 334 335 out.indent(); 336 337 mElementType->emitReaderWriterEmbedded( 338 out, 339 depth + 1, 340 (nameIsPointer ? "(*" + name + ")" : name) 341 + "[" + iteratorName + "]", 342 sanitizedName + (nameIsPointer ? "_deref" : "") + "_indexed", 343 false /* nameIsPointer */, 344 parcelObj, 345 parcelObjIsPointer, 346 isReader, 347 mode, 348 childName, 349 iteratorName + " * sizeof(" + baseType + ")"); 350 351 out.unindent(); 352 353 out << "}\n\n"; 354 } 355 356 void VectorType::emitResolveReferences( 357 Formatter &out, 358 const std::string &name, 359 bool nameIsPointer, 360 const std::string &parcelObj, 361 bool parcelObjIsPointer, 362 bool isReader, 363 ErrorMode mode) const { 364 emitResolveReferencesEmbeddedHelper( 365 out, 366 0, /* depth */ 367 name, 368 name /* sanitizedName */, 369 nameIsPointer, 370 parcelObj, 371 parcelObjIsPointer, 372 isReader, 373 mode, 374 "_hidl_" + name + "_child", 375 "0 /* parentOffset */"); 376 } 377 378 void VectorType::emitResolveReferencesEmbedded( 379 Formatter &out, 380 size_t depth, 381 const std::string &name, 382 const std::string &sanitizedName, 383 bool nameIsPointer, 384 const std::string &parcelObj, 385 bool parcelObjIsPointer, 386 bool isReader, 387 ErrorMode mode, 388 const std::string & /* parentName */, 389 const std::string & /* offsetText */) const { 390 emitResolveReferencesEmbeddedHelper( 391 out, depth, name, sanitizedName, nameIsPointer, parcelObj, 392 parcelObjIsPointer, isReader, mode, "", ""); 393 } 394 395 bool VectorType::useParentInEmitResolveReferencesEmbedded() const { 396 // parentName and offsetText is not used in emitResolveReferencesEmbedded 397 return false; 398 } 399 400 void VectorType::emitResolveReferencesEmbeddedHelper( 401 Formatter &out, 402 size_t depth, 403 const std::string &name, 404 const std::string &sanitizedName, 405 bool nameIsPointer, 406 const std::string &parcelObj, 407 bool parcelObjIsPointer, 408 bool isReader, 409 ErrorMode mode, 410 const std::string &childName, 411 const std::string &childOffsetText) const { 412 CHECK(needsResolveReferences() && mElementType->needsResolveReferences()); 413 414 const std::string nameDeref = name + (nameIsPointer ? "->" : "."); 415 const std::string nameDerefed = (nameIsPointer ? "*" : "") + name; 416 std::string elementType = mElementType->getCppStackType(); 417 418 std::string myChildName = childName, myChildOffset = childOffsetText; 419 420 if(myChildName.empty() && myChildOffset.empty()) { 421 myChildName = "_hidl_" + sanitizedName + "_child"; 422 myChildOffset = "0"; 423 424 out << "size_t " << myChildName << ";\n"; 425 out << "_hidl_err = ::android::hardware::findInParcel(" 426 << nameDerefed << ", " 427 << (parcelObjIsPointer ? "*" : "") << parcelObj << ", " 428 << "&" << myChildName 429 << ");\n"; 430 431 handleError(out, mode); 432 } 433 434 std::string iteratorName = "_hidl_index_" + std::to_string(depth); 435 436 out << "for (size_t " 437 << iteratorName 438 << " = 0; " 439 << iteratorName 440 << " < " 441 << nameDeref 442 << "size(); ++" 443 << iteratorName 444 << ") {\n"; 445 446 out.indent(); 447 448 mElementType->emitResolveReferencesEmbedded( 449 out, 450 depth + 1, 451 (nameIsPointer ? "(*" + name + ")" : name) + "[" + iteratorName + "]", 452 sanitizedName + (nameIsPointer ? "_deref" : "") + "_indexed", 453 false /* nameIsPointer */, 454 parcelObj, 455 parcelObjIsPointer, 456 isReader, 457 mode, 458 myChildName, 459 myChildOffset + " + " + 460 iteratorName + " * sizeof(" + elementType + ")"); 461 462 out.unindent(); 463 464 out << "}\n\n"; 465 } 466 467 void VectorType::emitJavaReaderWriter( 468 Formatter &out, 469 const std::string &parcelObj, 470 const std::string &argName, 471 bool isReader) const { 472 if (mElementType->isCompoundType()) { 473 474 if (isReader) { 475 out << mElementType->getJavaType() 476 << ".readVectorFromParcel(" 477 << parcelObj 478 << ");\n"; 479 } else { 480 out << mElementType->getJavaType() 481 << ".writeVectorToParcel(" 482 << parcelObj 483 << ", " 484 << argName 485 << ");\n"; 486 } 487 488 return; 489 } 490 491 if (mElementType->isArray()) { 492 size_t align, size; 493 getAlignmentAndSize(&align, &size); 494 if (isReader) { 495 out << " new " 496 << getJavaType(false /* forInitializer */) 497 << "();\n"; 498 } 499 500 out << "{\n"; 501 out.indent(); 502 503 out << "android.os.HwBlob _hidl_blob = "; 504 505 if (isReader) { 506 out << parcelObj 507 << ".readBuffer(" 508 << size 509 << " /* size */);\n"; 510 } else { 511 512 out << "new android.os.HwBlob(" 513 << size 514 << " /* size */);\n"; 515 } 516 517 emitJavaFieldReaderWriter( 518 out, 519 0 /* depth */, 520 parcelObj, 521 "_hidl_blob", 522 argName, 523 "0 /* offset */", 524 isReader); 525 526 if (!isReader) { 527 out << parcelObj << ".writeBuffer(_hidl_blob);\n"; 528 }; 529 530 out.unindent(); 531 out << "}\n"; 532 533 return; 534 } 535 536 emitJavaReaderWriterWithSuffix( 537 out, 538 parcelObj, 539 argName, 540 isReader, 541 mElementType->getJavaSuffix() + "Vector", 542 "" /* extra */); 543 } 544 545 void VectorType::emitJavaFieldInitializer( 546 Formatter &out, const std::string &fieldName) const { 547 std::string javaType = getJavaType(false /* forInitializer */); 548 549 out << "final " 550 << javaType 551 << " " 552 << fieldName 553 << " = new " 554 << javaType 555 << "();\n"; 556 } 557 558 void VectorType::emitJavaFieldReaderWriter( 559 Formatter &out, 560 size_t depth, 561 const std::string &parcelName, 562 const std::string &blobName, 563 const std::string &fieldName, 564 const std::string &offset, 565 bool isReader) const { 566 VectorType::EmitJavaFieldReaderWriterForElementType( 567 out, 568 depth, 569 mElementType.get(), 570 parcelName, 571 blobName, 572 fieldName, 573 offset, 574 isReader); 575 } 576 577 void VectorType::EmitJavaFieldReaderWriterForElementType( 578 Formatter &out, 579 size_t depth, 580 const Type *elementType, 581 const std::string &parcelName, 582 const std::string &blobName, 583 const std::string &fieldName, 584 const std::string &offset, 585 bool isReader) { 586 size_t elementAlign, elementSize; 587 elementType->getAlignmentAndSize(&elementAlign, &elementSize); 588 589 if (isReader) { 590 out << "{\n"; 591 out.indent(); 592 593 out << "int _hidl_vec_size = " 594 << blobName 595 << ".getInt32(" 596 << offset 597 << " + 8 /* offsetof(hidl_vec<T>, mSize) */);\n"; 598 599 out << "android.os.HwBlob childBlob = " 600 << parcelName 601 << ".readEmbeddedBuffer(\n"; 602 603 out.indent(); 604 out.indent(); 605 606 out << "_hidl_vec_size * " 607 << elementSize << "," 608 << blobName 609 << ".handle(),\n" 610 << offset 611 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */," 612 << "true /* nullable */);\n\n"; 613 614 out.unindent(); 615 out.unindent(); 616 617 out << fieldName << ".clear();\n"; 618 std::string iteratorName = "_hidl_index_" + std::to_string(depth); 619 620 out << "for (int " 621 << iteratorName 622 << " = 0; " 623 << iteratorName 624 << " < _hidl_vec_size; " 625 << "++" 626 << iteratorName 627 << ") {\n"; 628 629 out.indent(); 630 631 elementType->emitJavaFieldInitializer(out, "_hidl_vec_element"); 632 633 elementType->emitJavaFieldReaderWriter( 634 out, 635 depth + 1, 636 parcelName, 637 "childBlob", 638 "_hidl_vec_element", 639 iteratorName + " * " + std::to_string(elementSize), 640 true /* isReader */); 641 642 out << fieldName 643 << ".add(_hidl_vec_element);\n"; 644 645 out.unindent(); 646 647 out << "}\n"; 648 649 out.unindent(); 650 out << "}\n"; 651 652 return; 653 } 654 655 out << "{\n"; 656 out.indent(); 657 658 out << "int _hidl_vec_size = " 659 << fieldName 660 << ".size();\n"; 661 662 out << blobName 663 << ".putInt32(" 664 << offset 665 << " + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);\n"; 666 667 out << blobName 668 << ".putBool(" 669 << offset 670 << " + 12 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);\n"; 671 672 // XXX make HwBlob constructor take a long instead of an int? 673 out << "android.os.HwBlob childBlob = new android.os.HwBlob((int)(_hidl_vec_size * " 674 << elementSize 675 << "));\n"; 676 677 std::string iteratorName = "_hidl_index_" + std::to_string(depth); 678 679 out << "for (int " 680 << iteratorName 681 << " = 0; " 682 << iteratorName 683 << " < _hidl_vec_size; " 684 << "++" 685 << iteratorName 686 << ") {\n"; 687 688 out.indent(); 689 690 elementType->emitJavaFieldReaderWriter( 691 out, 692 depth + 1, 693 parcelName, 694 "childBlob", 695 fieldName + ".get(" + iteratorName + ")", 696 iteratorName + " * " + std::to_string(elementSize), 697 false /* isReader */); 698 699 out.unindent(); 700 701 out << "}\n"; 702 703 out << blobName 704 << ".putBlob(" 705 << offset 706 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);\n"; 707 708 out.unindent(); 709 out << "}\n"; 710 } 711 712 bool VectorType::needsEmbeddedReadWrite() const { 713 return true; 714 } 715 716 bool VectorType::deepNeedsResolveReferences(std::unordered_set<const Type*>* visited) const { 717 if (mElementType->needsResolveReferences(visited)) { 718 return true; 719 } 720 return TemplatedType::deepNeedsResolveReferences(visited); 721 } 722 723 bool VectorType::resultNeedsDeref() const { 724 return !isVectorOfBinders(); 725 } 726 727 bool VectorType::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const { 728 if (!mElementType->isJavaCompatible(visited)) { 729 return false; 730 } 731 732 if (mElementType->isArray()) { 733 return static_cast<const ArrayType*>(mElementType.get())->countDimensions() == 1; 734 } 735 736 if (mElementType->isVector()) { 737 return false; 738 } 739 740 if (isVectorOfBinders()) { 741 return false; 742 } 743 744 return TemplatedType::deepIsJavaCompatible(visited); 745 } 746 747 bool VectorType::deepContainsPointer(std::unordered_set<const Type*>* visited) const { 748 if (mElementType->containsPointer(visited)) { 749 return true; 750 } 751 return TemplatedType::deepContainsPointer(visited); 752 } 753 754 // All hidl_vec<T> have the same size. 755 static HidlTypeAssertion assertion("hidl_vec<char>", 16 /* size */); 756 757 void VectorType::getAlignmentAndSizeStatic(size_t *align, size_t *size) { 758 *align = 8; // hidl_vec<T> 759 *size = assertion.size(); 760 } 761 762 void VectorType::getAlignmentAndSize(size_t *align, size_t *size) const { 763 VectorType::getAlignmentAndSizeStatic(align, size); 764 } 765 766 } // namespace android 767 768