• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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