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