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