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