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