VectorType.cpp revision b2a861cf36ba30b0365d42b33fca0188d543c73c
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 26namespace android { 27 28VectorType::VectorType() { 29} 30 31std::string VectorType::typeName() const { 32 return "vector" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName())); 33} 34 35bool VectorType::isCompatibleElementType(Type *elementType) const { 36 if (elementType->isScalar()) { 37 return true; 38 } 39 if (elementType->isString()) { 40 return true; 41 } 42 if (elementType->isEnum()) { 43 return true; 44 } 45 if (elementType->isBitField()) { 46 return true; 47 } 48 if (elementType->isCompoundType() 49 && static_cast<CompoundType *>(elementType)->style() == CompoundType::STYLE_STRUCT) { 50 return true; 51 } 52 if (elementType->isInterface()) { 53 return true; 54 } 55 if (elementType->isHandle()) { 56 return true; 57 } 58 if (elementType->isTemplatedType()) { 59 Type *inner = static_cast<TemplatedType *>(elementType)->getElementType(); 60 return this->isCompatibleElementType(inner) && !inner->isInterface(); 61 } 62 if (elementType->isArray()) { 63 Type *inner = static_cast<ArrayType *>(elementType)->getElementType(); 64 return this->isCompatibleElementType(inner) && !inner->isInterface(); 65 } 66 return false; 67} 68 69void VectorType::addNamedTypesToSet(std::set<const FQName> &set) const { 70 mElementType->addNamedTypesToSet(set); 71} 72 73bool VectorType::isVector() const { 74 return true; 75} 76 77bool VectorType::isVectorOfBinders() const { 78 return mElementType->isBinder(); 79} 80 81bool VectorType::canCheckEquality() const { 82 return mElementType->canCheckEquality(); 83} 84 85std::string VectorType::getCppType(StorageMode mode, 86 bool specifyNamespaces) const { 87 const std::string base = 88 std::string(specifyNamespaces ? "::android::hardware::" : "") 89 + "hidl_vec<" 90 + mElementType->getCppStackType( specifyNamespaces) 91 + ">"; 92 93 switch (mode) { 94 case StorageMode_Stack: 95 return base; 96 97 case StorageMode_Argument: 98 return "const " + base + "&"; 99 100 case StorageMode_Result: 101 { 102 if (isVectorOfBinders()) { 103 return base; 104 } 105 106 return "const " + base + "*"; 107 } 108 } 109} 110 111std::string VectorType::getJavaType(bool /* forInitializer */) const { 112 113 std::string elementJavaType; 114 if (mElementType->isArray()) { 115 elementJavaType = mElementType->getJavaType(); 116 } else { 117 elementJavaType = mElementType->getJavaWrapperType(); 118 } 119 120 return "java.util.ArrayList<" 121 + elementJavaType 122 + ">"; 123} 124 125std::string VectorType::getVtsType() const { 126 return "TYPE_VECTOR"; 127} 128 129std::string VectorType::getVtsValueName() const { 130 return "vector_value"; 131} 132 133void VectorType::emitReaderWriter( 134 Formatter &out, 135 const std::string &name, 136 const std::string &parcelObj, 137 bool parcelObjIsPointer, 138 bool isReader, 139 ErrorMode mode) const { 140 if (isVectorOfBinders()) { 141 emitReaderWriterForVectorOfBinders( 142 out, name, parcelObj, parcelObjIsPointer, isReader, mode); 143 144 return; 145 } 146 147 std::string baseType = mElementType->getCppStackType(); 148 149 const std::string parentName = "_hidl_" + name + "_parent"; 150 151 out << "size_t " << parentName << ";\n\n"; 152 153 const std::string parcelObjDeref = 154 parcelObj + (parcelObjIsPointer ? "->" : "."); 155 156 if (isReader) { 157 out << "_hidl_err = " 158 << parcelObjDeref 159 << "readBuffer(" 160 << "sizeof(*" 161 << name 162 << "), &" 163 << parentName 164 << ", " 165 << " reinterpret_cast<const void **>(" 166 << "&" << name 167 << "));\n\n"; 168 169 handleError(out, mode); 170 } else { 171 out << "_hidl_err = " 172 << parcelObjDeref 173 << "writeBuffer(&" 174 << name 175 << ", sizeof(" 176 << name 177 << "), &" 178 << parentName 179 << ");\n"; 180 181 handleError(out, mode); 182 } 183 184 emitReaderWriterEmbedded( 185 out, 186 0 /* depth */, 187 name, 188 name /* sanitizedName */ , 189 isReader /* nameIsPointer */, 190 parcelObj, 191 parcelObjIsPointer, 192 isReader, 193 mode, 194 parentName, 195 "0 /* parentOffset */"); 196} 197 198void VectorType::emitReaderWriterForVectorOfBinders( 199 Formatter &out, 200 const std::string &name, 201 const std::string &parcelObj, 202 bool parcelObjIsPointer, 203 bool isReader, 204 ErrorMode mode) const { 205 const std::string parcelObjDeref = 206 parcelObj + (parcelObjIsPointer ? "->" : "."); 207 208 if (isReader) { 209 out << "{\n"; 210 out.indent(); 211 212 const std::string sizeName = "_hidl_" + name + "_size"; 213 214 out << "uint64_t " 215 << sizeName 216 << ";\n"; 217 218 out << "_hidl_err = " 219 << parcelObjDeref 220 << "readUint64(&" 221 << sizeName 222 << ");\n"; 223 224 handleError(out, mode); 225 226 out << name 227 << ".resize(" 228 << sizeName 229 << ");\n\n" 230 << "for (size_t _hidl_index = 0; _hidl_index < " 231 << sizeName 232 << "; ++_hidl_index) {\n"; 233 234 out.indent(); 235 236 out << mElementType->getCppStackType(true /* specifyNamespaces */) 237 << " _hidl_base;\n"; 238 239 mElementType->emitReaderWriter( 240 out, 241 "_hidl_base", 242 parcelObj, 243 parcelObjIsPointer, 244 isReader, 245 mode); 246 247 out << name 248 << "[_hidl_index] = _hidl_base;\n"; 249 250 out.unindent(); 251 out << "}\n"; 252 253 out.unindent(); 254 out << "}\n"; 255 } else { 256 out << "_hidl_err = " 257 << parcelObjDeref 258 << "writeUint64(" 259 << name 260 << ".size());\n"; 261 262 handleError(out, mode); 263 264 out << "for (size_t _hidl_index = 0; _hidl_index < " 265 << name 266 << ".size(); ++_hidl_index) {\n"; 267 268 out.indent(); 269 270 mElementType->emitReaderWriter( 271 out, 272 name + "[_hidl_index]", 273 parcelObj, 274 parcelObjIsPointer, 275 isReader, 276 mode); 277 278 out.unindent(); 279 out << "}\n"; 280 } 281} 282 283void VectorType::emitReaderWriterEmbedded( 284 Formatter &out, 285 size_t depth, 286 const std::string &name, 287 const std::string &sanitizedName, 288 bool nameIsPointer, 289 const std::string &parcelObj, 290 bool parcelObjIsPointer, 291 bool isReader, 292 ErrorMode mode, 293 const std::string &parentName, 294 const std::string &offsetText) const { 295 std::string baseType = getCppStackType(); 296 297 const std::string childName = "_hidl_" + sanitizedName + "_child"; 298 out << "size_t " << childName << ";\n\n"; 299 300 emitReaderWriterEmbeddedForTypeName( 301 out, 302 name, 303 nameIsPointer, 304 parcelObj, 305 parcelObjIsPointer, 306 isReader, 307 mode, 308 parentName, 309 offsetText, 310 baseType, 311 childName, 312 "::android::hardware"); 313 314 if (!mElementType->needsEmbeddedReadWrite()) { 315 return; 316 } 317 318 const std::string nameDeref = name + (nameIsPointer ? "->" : "."); 319 320 baseType = mElementType->getCppStackType(); 321 322 std::string iteratorName = "_hidl_index_" + std::to_string(depth); 323 324 out << "for (size_t " 325 << iteratorName 326 << " = 0; " 327 << iteratorName 328 << " < " 329 << nameDeref 330 << "size(); ++" 331 << iteratorName 332 << ") {\n"; 333 334 out.indent(); 335 336 mElementType->emitReaderWriterEmbedded( 337 out, 338 depth + 1, 339 (nameIsPointer ? "(*" + name + ")" : name) 340 + "[" + iteratorName + "]", 341 sanitizedName + (nameIsPointer ? "_deref" : "") + "_indexed", 342 false /* nameIsPointer */, 343 parcelObj, 344 parcelObjIsPointer, 345 isReader, 346 mode, 347 childName, 348 iteratorName + " * sizeof(" + baseType + ")"); 349 350 out.unindent(); 351 352 out << "}\n\n"; 353} 354 355void VectorType::emitResolveReferences( 356 Formatter &out, 357 const std::string &name, 358 bool nameIsPointer, 359 const std::string &parcelObj, 360 bool parcelObjIsPointer, 361 bool isReader, 362 ErrorMode mode) const { 363 emitResolveReferencesEmbeddedHelper( 364 out, 365 0, /* depth */ 366 name, 367 name /* sanitizedName */, 368 nameIsPointer, 369 parcelObj, 370 parcelObjIsPointer, 371 isReader, 372 mode, 373 "_hidl_" + name + "_child", 374 "0 /* parentOffset */"); 375} 376 377void VectorType::emitResolveReferencesEmbedded( 378 Formatter &out, 379 size_t depth, 380 const std::string &name, 381 const std::string &sanitizedName, 382 bool nameIsPointer, 383 const std::string &parcelObj, 384 bool parcelObjIsPointer, 385 bool isReader, 386 ErrorMode mode, 387 const std::string & /* parentName */, 388 const std::string & /* offsetText */) const { 389 emitResolveReferencesEmbeddedHelper( 390 out, depth, name, sanitizedName, nameIsPointer, parcelObj, 391 parcelObjIsPointer, isReader, mode, "", ""); 392} 393 394bool VectorType::useParentInEmitResolveReferencesEmbedded() const { 395 // parentName and offsetText is not used in emitResolveReferencesEmbedded 396 return false; 397} 398 399void VectorType::emitResolveReferencesEmbeddedHelper( 400 Formatter &out, 401 size_t depth, 402 const std::string &name, 403 const std::string &sanitizedName, 404 bool nameIsPointer, 405 const std::string &parcelObj, 406 bool parcelObjIsPointer, 407 bool isReader, 408 ErrorMode mode, 409 const std::string &childName, 410 const std::string &childOffsetText) const { 411 CHECK(needsResolveReferences() && mElementType->needsResolveReferences()); 412 413 const std::string nameDeref = name + (nameIsPointer ? "->" : "."); 414 const std::string nameDerefed = (nameIsPointer ? "*" : "") + name; 415 std::string elementType = mElementType->getCppStackType(); 416 417 std::string myChildName = childName, myChildOffset = childOffsetText; 418 419 if(myChildName.empty() && myChildOffset.empty()) { 420 myChildName = "_hidl_" + sanitizedName + "_child"; 421 myChildOffset = "0"; 422 423 out << "size_t " << myChildName << ";\n"; 424 out << "_hidl_err = ::android::hardware::findInParcel(" 425 << nameDerefed << ", " 426 << (parcelObjIsPointer ? "*" : "") << parcelObj << ", " 427 << "&" << myChildName 428 << ");\n"; 429 430 handleError(out, mode); 431 } 432 433 std::string iteratorName = "_hidl_index_" + std::to_string(depth); 434 435 out << "for (size_t " 436 << iteratorName 437 << " = 0; " 438 << iteratorName 439 << " < " 440 << nameDeref 441 << "size(); ++" 442 << iteratorName 443 << ") {\n"; 444 445 out.indent(); 446 447 mElementType->emitResolveReferencesEmbedded( 448 out, 449 depth + 1, 450 (nameIsPointer ? "(*" + name + ")" : name) + "[" + iteratorName + "]", 451 sanitizedName + (nameIsPointer ? "_deref" : "") + "_indexed", 452 false /* nameIsPointer */, 453 parcelObj, 454 parcelObjIsPointer, 455 isReader, 456 mode, 457 myChildName, 458 myChildOffset + " + " + 459 iteratorName + " * sizeof(" + elementType + ")"); 460 461 out.unindent(); 462 463 out << "}\n\n"; 464} 465 466void VectorType::emitJavaReaderWriter( 467 Formatter &out, 468 const std::string &parcelObj, 469 const std::string &argName, 470 bool isReader) const { 471 if (mElementType->isCompoundType()) { 472 473 if (isReader) { 474 out << mElementType->getJavaType() 475 << ".readVectorFromParcel(" 476 << parcelObj 477 << ");\n"; 478 } else { 479 out << mElementType->getJavaType() 480 << ".writeVectorToParcel(" 481 << parcelObj 482 << ", " 483 << argName 484 << ");\n"; 485 } 486 487 return; 488 } 489 490 if (mElementType->isArray()) { 491 size_t align, size; 492 getAlignmentAndSize(&align, &size); 493 if (isReader) { 494 out << " new " 495 << getJavaType(false /* forInitializer */) 496 << "();\n"; 497 } 498 499 out << "{\n"; 500 out.indent(); 501 502 out << "android.os.HwBlob _hidl_blob = "; 503 504 if (isReader) { 505 out << parcelObj 506 << ".readBuffer(" 507 << size 508 << " /* size */);\n"; 509 } else { 510 511 out << "new android.os.HwBlob(" 512 << size 513 << " /* size */);\n"; 514 } 515 516 emitJavaFieldReaderWriter( 517 out, 518 0 /* depth */, 519 parcelObj, 520 "_hidl_blob", 521 argName, 522 "0 /* offset */", 523 isReader); 524 525 if (!isReader) { 526 out << parcelObj << ".writeBuffer(_hidl_blob);\n"; 527 }; 528 529 out.unindent(); 530 out << "}\n"; 531 532 return; 533 } 534 535 emitJavaReaderWriterWithSuffix( 536 out, 537 parcelObj, 538 argName, 539 isReader, 540 mElementType->getJavaSuffix() + "Vector", 541 "" /* extra */); 542} 543 544void VectorType::emitJavaFieldInitializer( 545 Formatter &out, const std::string &fieldName) const { 546 std::string javaType = getJavaType(false /* forInitializer */); 547 548 out << "final " 549 << javaType 550 << " " 551 << fieldName 552 << " = new " 553 << javaType 554 << "();\n"; 555} 556 557void VectorType::emitJavaFieldReaderWriter( 558 Formatter &out, 559 size_t depth, 560 const std::string &parcelName, 561 const std::string &blobName, 562 const std::string &fieldName, 563 const std::string &offset, 564 bool isReader) const { 565 VectorType::EmitJavaFieldReaderWriterForElementType( 566 out, 567 depth, 568 mElementType, 569 parcelName, 570 blobName, 571 fieldName, 572 offset, 573 isReader); 574} 575 576// static 577void 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 712bool VectorType::needsEmbeddedReadWrite() const { 713 return true; 714} 715 716bool VectorType::needsResolveReferences() const { 717 return mElementType->needsResolveReferences(); 718} 719 720bool VectorType::resultNeedsDeref() const { 721 return !isVectorOfBinders(); 722} 723 724bool VectorType::isJavaCompatible() const { 725 if (!mElementType->isJavaCompatible()) { 726 return false; 727 } 728 729 if (mElementType->isArray()) { 730 return static_cast<ArrayType *>(mElementType)->countDimensions() == 1; 731 } 732 733 if (mElementType->isVector()) { 734 return false; 735 } 736 737 if (isVectorOfBinders()) { 738 return false; 739 } 740 741 return true; 742} 743 744bool VectorType::containsPointer() const { 745 return mElementType->containsPointer(); 746} 747 748// All hidl_vec<T> have the same size. 749static HidlTypeAssertion assertion("hidl_vec<char>", 16 /* size */); 750 751// static 752void VectorType::getAlignmentAndSizeStatic(size_t *align, size_t *size) { 753 *align = 8; // hidl_vec<T> 754 *size = assertion.size(); 755} 756 757void VectorType::getAlignmentAndSize(size_t *align, size_t *size) const { 758 VectorType::getAlignmentAndSizeStatic(align, size); 759} 760 761} // namespace android 762 763