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, "vec") {} 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 if (static_cast<const CompoundType*>(elementType)->containsInterface()) { 49 return false; 50 } 51 return true; 52 } 53 if (elementType->isInterface()) { 54 return true; 55 } 56 if (elementType->isHandle()) { 57 return true; 58 } 59 if (elementType->isMemory()) { 60 return true; 61 } 62 if (elementType->isTemplatedType()) { 63 const Type* inner = static_cast<const TemplatedType*>(elementType)->getElementType(); 64 return this->isCompatibleElementType(inner) && !inner->isInterface(); 65 } 66 if (elementType->isArray()) { 67 const Type* inner = static_cast<const ArrayType*>(elementType)->getElementType(); 68 return this->isCompatibleElementType(inner) && !inner->isInterface(); 69 } 70 return false; 71 } 72 73 bool VectorType::isVector() const { 74 return true; 75 } 76 77 bool VectorType::isVectorOfBinders() const { 78 return mElementType->isInterface(); 79 } 80 81 bool VectorType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const { 82 return mElementType->canCheckEquality(visited); 83 } 84 85 std::vector<const Reference<Type>*> VectorType::getStrongReferences() const { 86 return {}; 87 } 88 89 std::string VectorType::getCppType(StorageMode mode, 90 bool specifyNamespaces) const { 91 const std::string base = 92 std::string(specifyNamespaces ? "::android::hardware::" : "") 93 + "hidl_vec<" 94 + mElementType->getCppStackType( specifyNamespaces) 95 + ">"; 96 97 switch (mode) { 98 case StorageMode_Stack: 99 return base; 100 101 case StorageMode_Argument: 102 return "const " + base + "&"; 103 104 case StorageMode_Result: 105 { 106 if (isVectorOfBinders()) { 107 return base; 108 } 109 110 return "const " + base + "*"; 111 } 112 } 113 } 114 115 std::string VectorType::getJavaType(bool /* forInitializer */) const { 116 // this will break if the type is templated in Java, but there are no types 117 // like this currently 118 const std::string elementJavaType = mElementType->getJavaTypeClass(); 119 return "java.util.ArrayList<" + elementJavaType + ">"; 120 } 121 122 std::string VectorType::getJavaTypeClass() const { 123 return "java.util.ArrayList"; 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::emitJavaReaderWriter( 357 Formatter &out, 358 const std::string &parcelObj, 359 const std::string &argName, 360 bool isReader) const { 361 if (mElementType->isCompoundType()) { 362 363 if (isReader) { 364 out << mElementType->getJavaType() 365 << ".readVectorFromParcel(" 366 << parcelObj 367 << ");\n"; 368 } else { 369 out << mElementType->getJavaType() 370 << ".writeVectorToParcel(" 371 << parcelObj 372 << ", " 373 << argName 374 << ");\n"; 375 } 376 377 return; 378 } 379 380 if (mElementType->isArray()) { 381 size_t align, size; 382 getAlignmentAndSize(&align, &size); 383 if (isReader) { 384 out << " new " 385 << getJavaType(false /* forInitializer */) 386 << "();\n"; 387 } 388 389 out << "{\n"; 390 out.indent(); 391 392 out << "android.os.HwBlob _hidl_blob = "; 393 394 if (isReader) { 395 out << parcelObj 396 << ".readBuffer(" 397 << size 398 << " /* size */);\n"; 399 } else { 400 401 out << "new android.os.HwBlob(" 402 << size 403 << " /* size */);\n"; 404 } 405 406 emitJavaFieldReaderWriter( 407 out, 408 0 /* depth */, 409 parcelObj, 410 "_hidl_blob", 411 argName, 412 "0 /* offset */", 413 isReader); 414 415 if (!isReader) { 416 out << parcelObj << ".writeBuffer(_hidl_blob);\n"; 417 }; 418 419 out.unindent(); 420 out << "}\n"; 421 422 return; 423 } 424 425 emitJavaReaderWriterWithSuffix( 426 out, 427 parcelObj, 428 argName, 429 isReader, 430 mElementType->getJavaSuffix() + "Vector", 431 "" /* extra */); 432 } 433 434 void VectorType::emitJavaFieldInitializer( 435 Formatter &out, const std::string &fieldName) const { 436 const std::string typeName = getJavaType(false /* forInitializer */); 437 const std::string fieldDeclaration = typeName + " " + fieldName; 438 439 emitJavaFieldDefaultInitialValue(out, fieldDeclaration); 440 } 441 442 void VectorType::emitJavaFieldDefaultInitialValue( 443 Formatter &out, const std::string &declaredFieldName) const { 444 out << declaredFieldName 445 << " = new " 446 << getJavaType(false /* forInitializer */) 447 << "();\n"; 448 } 449 450 void VectorType::emitJavaFieldReaderWriter( 451 Formatter &out, 452 size_t depth, 453 const std::string &parcelName, 454 const std::string &blobName, 455 const std::string &fieldName, 456 const std::string &offset, 457 bool isReader) const { 458 459 const std::string fieldNameWithCast = isReader 460 ? "(" + getJavaTypeCast(fieldName) + ")" 461 : fieldName; 462 463 VectorType::EmitJavaFieldReaderWriterForElementType( 464 out, 465 depth, 466 mElementType.get(), 467 parcelName, 468 blobName, 469 fieldNameWithCast, 470 offset, 471 isReader); 472 } 473 474 void VectorType::EmitJavaFieldReaderWriterForElementType( 475 Formatter &out, 476 size_t depth, 477 const Type *elementType, 478 const std::string &parcelName, 479 const std::string &blobName, 480 const std::string &fieldName, 481 const std::string &offset, 482 bool isReader) { 483 size_t elementAlign, elementSize; 484 elementType->getAlignmentAndSize(&elementAlign, &elementSize); 485 486 if (isReader) { 487 out << "{\n"; 488 out.indent(); 489 490 out << "int _hidl_vec_size = " 491 << blobName 492 << ".getInt32(" 493 << offset 494 << " + 8 /* offsetof(hidl_vec<T>, mSize) */);\n"; 495 496 out << "android.os.HwBlob childBlob = " 497 << parcelName 498 << ".readEmbeddedBuffer(\n"; 499 500 out.indent(); 501 out.indent(); 502 503 out << "_hidl_vec_size * " 504 << elementSize << "," 505 << blobName 506 << ".handle(),\n" 507 << offset 508 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */," 509 << "true /* nullable */);\n\n"; 510 511 out.unindent(); 512 out.unindent(); 513 514 out << fieldName << ".clear();\n"; 515 std::string iteratorName = "_hidl_index_" + std::to_string(depth); 516 517 out << "for (int " 518 << iteratorName 519 << " = 0; " 520 << iteratorName 521 << " < _hidl_vec_size; " 522 << "++" 523 << iteratorName 524 << ") {\n"; 525 526 out.indent(); 527 528 elementType->emitJavaFieldInitializer(out, "_hidl_vec_element"); 529 530 elementType->emitJavaFieldReaderWriter( 531 out, 532 depth + 1, 533 parcelName, 534 "childBlob", 535 "_hidl_vec_element", 536 iteratorName + " * " + std::to_string(elementSize), 537 true /* isReader */); 538 539 out << fieldName 540 << ".add(_hidl_vec_element);\n"; 541 542 out.unindent(); 543 544 out << "}\n"; 545 546 out.unindent(); 547 out << "}\n"; 548 549 return; 550 } 551 552 out << "{\n"; 553 out.indent(); 554 555 out << "int _hidl_vec_size = " 556 << fieldName 557 << ".size();\n"; 558 559 out << blobName 560 << ".putInt32(" 561 << offset 562 << " + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);\n"; 563 564 out << blobName 565 << ".putBool(" 566 << offset 567 << " + 12 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);\n"; 568 569 // XXX make HwBlob constructor take a long instead of an int? 570 out << "android.os.HwBlob childBlob = new android.os.HwBlob((int)(_hidl_vec_size * " 571 << elementSize 572 << "));\n"; 573 574 std::string iteratorName = "_hidl_index_" + std::to_string(depth); 575 576 out << "for (int " 577 << iteratorName 578 << " = 0; " 579 << iteratorName 580 << " < _hidl_vec_size; " 581 << "++" 582 << iteratorName 583 << ") {\n"; 584 585 out.indent(); 586 587 elementType->emitJavaFieldReaderWriter( 588 out, 589 depth + 1, 590 parcelName, 591 "childBlob", 592 fieldName + ".get(" + iteratorName + ")", 593 iteratorName + " * " + std::to_string(elementSize), 594 false /* isReader */); 595 596 out.unindent(); 597 598 out << "}\n"; 599 600 out << blobName 601 << ".putBlob(" 602 << offset 603 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);\n"; 604 605 out.unindent(); 606 out << "}\n"; 607 } 608 609 bool VectorType::needsEmbeddedReadWrite() const { 610 return true; 611 } 612 613 bool VectorType::resultNeedsDeref() const { 614 return !isVectorOfBinders(); 615 } 616 617 bool VectorType::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const { 618 if (!mElementType->isJavaCompatible(visited)) { 619 return false; 620 } 621 622 if (mElementType->isArray()) { 623 return static_cast<const ArrayType*>(mElementType.get())->countDimensions() == 1; 624 } 625 626 if (mElementType->isVector()) { 627 return false; 628 } 629 630 if (mElementType->isMemory()) { 631 return false; 632 } 633 634 if (isVectorOfBinders()) { 635 return false; 636 } 637 638 return TemplatedType::deepIsJavaCompatible(visited); 639 } 640 641 bool VectorType::deepContainsPointer(std::unordered_set<const Type*>* visited) const { 642 if (mElementType->containsPointer(visited)) { 643 return true; 644 } 645 return TemplatedType::deepContainsPointer(visited); 646 } 647 648 // All hidl_vec<T> have the same size. 649 static HidlTypeAssertion assertion("hidl_vec<char>", 16 /* size */); 650 651 void VectorType::getAlignmentAndSizeStatic(size_t *align, size_t *size) { 652 *align = 8; // hidl_vec<T> 653 *size = assertion.size(); 654 } 655 656 void VectorType::getAlignmentAndSize(size_t *align, size_t *size) const { 657 VectorType::getAlignmentAndSizeStatic(align, size); 658 } 659 660 } // namespace android 661 662