blob: 8bf3ede2c400e74a19ec352fdd25075234748110 [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
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
Andreas Huberc9410c72016-07-28 12:18:40 -070017#include "VectorType.h"
18
Andreas Huberf03332a2016-09-22 15:35:43 -070019#include "ArrayType.h"
20
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070021#include <hidl-util/Formatter.h>
Andreas Huber881227d2016-08-02 14:20:21 -070022#include <android-base/logging.h>
23
Andreas Huberc9410c72016-07-28 12:18:40 -070024namespace android {
25
Yifan Hongbf459bc2016-08-23 16:50:37 -070026VectorType::VectorType() {
Andreas Huberc9410c72016-07-28 12:18:40 -070027}
28
Steven Moreland979e0992016-09-07 09:18:08 -070029void VectorType::addNamedTypesToSet(std::set<const FQName> &set) const {
30 mElementType->addNamedTypesToSet(set);
31}
32
33std::string VectorType::getCppType(StorageMode mode,
34 std::string *extra,
35 bool specifyNamespaces) const {
Yifan Hongbf459bc2016-08-23 16:50:37 -070036 std::string elementExtra;
37 const std::string elementBase = mElementType->getCppType(&elementExtra, specifyNamespaces);
38
Andreas Huber881227d2016-08-02 14:20:21 -070039 const std::string base =
Steven Moreland979e0992016-09-07 09:18:08 -070040 std::string(specifyNamespaces ? "::android::hardware::" : "")
41 + "hidl_vec<"
42 + mElementType->getCppType(extra, specifyNamespaces)
Andreas Huberf9d49f12016-09-12 14:58:36 -070043 + (*extra)
Andreas Huber881227d2016-08-02 14:20:21 -070044 + ">";
45
Andreas Huberf9d49f12016-09-12 14:58:36 -070046 extra->clear();
Andreas Huber881227d2016-08-02 14:20:21 -070047
48 switch (mode) {
49 case StorageMode_Stack:
50 return base;
51
52 case StorageMode_Argument:
53 return "const " + base + "&";
54
55 case StorageMode_Result:
56 return "const " + base + "*";
57 }
58}
59
Andreas Huber4c865b72016-09-14 15:26:27 -070060std::string VectorType::getJavaType(
61 std::string *extra, bool /* forInitializer */) const {
62 *extra = "[]";
63
64 std::string elementExtra;
65 return mElementType->getJavaType(&elementExtra) + elementExtra;
Andreas Huber2831d512016-08-15 09:33:47 -070066}
67
Andreas Huber881227d2016-08-02 14:20:21 -070068void VectorType::emitReaderWriter(
69 Formatter &out,
70 const std::string &name,
71 const std::string &parcelObj,
72 bool parcelObjIsPointer,
73 bool isReader,
74 ErrorMode mode) const {
75 std::string baseExtra;
76 std::string baseType = mElementType->getCppType(&baseExtra);
77
Iliyan Malchev549e2592016-08-10 08:59:12 -070078 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -070079
80 out << "size_t " << parentName << ";\n\n";
81
82 const std::string parcelObjDeref =
83 parcelObj + (parcelObjIsPointer ? "->" : ".");
84
85 if (isReader) {
86 out << name
Andreas Huber8a82ff72016-08-04 10:29:39 -070087 << " = (const ::android::hardware::hidl_vec<"
Andreas Huber881227d2016-08-02 14:20:21 -070088 << baseType
Andreas Huberf9d49f12016-09-12 14:58:36 -070089 << baseExtra
Andreas Huber881227d2016-08-02 14:20:21 -070090 << "> *)"
91 << parcelObjDeref
92 << "readBuffer(&"
93 << parentName
94 << ");\n\n";
95
96 out << "if (" << name << " == nullptr) {\n";
97
98 out.indent();
99
Iliyan Malchev549e2592016-08-10 08:59:12 -0700100 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700101 handleError2(out, mode);
102
103 out.unindent();
104 out << "}\n\n";
105 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700106 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700107 << parcelObjDeref
108 << "writeBuffer(&"
109 << name
110 << ", sizeof("
111 << name
112 << "), &"
113 << parentName
114 << ");\n";
115
116 handleError(out, mode);
117 }
118
119 emitReaderWriterEmbedded(
120 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700121 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700122 name,
123 isReader /* nameIsPointer */,
124 parcelObj,
125 parcelObjIsPointer,
126 isReader,
127 mode,
128 parentName,
129 "0 /* parentOffset */");
130}
131
Andreas Huberf9d49f12016-09-12 14:58:36 -0700132// Remove any trailing array indices from the given name, i.e. foo[2][3] => foo
133static std::string StripIndex(const std::string &name) {
134 size_t pos = name.find("[");
135 if (pos == std::string::npos) {
136 return name;
137 }
138
139 return name.substr(0, pos);
140}
141
Andreas Huber881227d2016-08-02 14:20:21 -0700142void VectorType::emitReaderWriterEmbedded(
143 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700144 size_t depth,
Andreas Huber881227d2016-08-02 14:20:21 -0700145 const std::string &name,
146 bool nameIsPointer,
147 const std::string &parcelObj,
148 bool parcelObjIsPointer,
149 bool isReader,
150 ErrorMode mode,
151 const std::string &parentName,
152 const std::string &offsetText) const {
153 std::string baseExtra;
154 std::string baseType = Type::getCppType(&baseExtra);
155
Andreas Huberf9d49f12016-09-12 14:58:36 -0700156 const std::string childName = "_hidl_" + StripIndex(name) + "_child";
Andreas Huber881227d2016-08-02 14:20:21 -0700157 out << "size_t " << childName << ";\n\n";
158
159 emitReaderWriterEmbeddedForTypeName(
160 out,
161 name,
162 nameIsPointer,
163 parcelObj,
164 parcelObjIsPointer,
165 isReader,
166 mode,
167 parentName,
168 offsetText,
169 baseType,
170 childName);
171
172 if (!mElementType->needsEmbeddedReadWrite()) {
173 return;
174 }
175
176 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
177
178 baseType = mElementType->getCppType(&baseExtra);
179
Andreas Huberf9d49f12016-09-12 14:58:36 -0700180 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
181
182 out << "for (size_t "
183 << iteratorName
184 << " = 0; "
185 << iteratorName
186 << " < "
Andreas Huber881227d2016-08-02 14:20:21 -0700187 << nameDeref
Andreas Huberf9d49f12016-09-12 14:58:36 -0700188 << "size(); ++"
189 << iteratorName
190 << ") {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700191
192 out.indent();
193
194 mElementType->emitReaderWriterEmbedded(
195 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700196 depth + 1,
197 (nameIsPointer ? "(*" + name + ")" : name)
198 + "[" + iteratorName + "]",
Andreas Huber881227d2016-08-02 14:20:21 -0700199 false /* nameIsPointer */,
200 parcelObj,
201 parcelObjIsPointer,
202 isReader,
203 mode,
204 childName,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700205 iteratorName + " * sizeof(" + baseType + baseExtra + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700206
207 out.unindent();
208
209 out << "}\n\n";
210}
211
Yifan Hongbf459bc2016-08-23 16:50:37 -0700212void VectorType::emitResolveReferences(
213 Formatter &out,
214 const std::string &name,
215 bool nameIsPointer,
216 const std::string &parcelObj,
217 bool parcelObjIsPointer,
218 bool isReader,
219 ErrorMode mode) const {
220 emitResolveReferencesEmbeddedHelper(
221 out,
222 0, /* depth */
223 name,
224 name /* sanitizedName */,
225 nameIsPointer,
226 parcelObj,
227 parcelObjIsPointer,
228 isReader,
229 mode,
230 "_hidl_" + name + "_child",
231 "0 /* parentOffset */");
232}
233
234void VectorType::emitResolveReferencesEmbedded(
235 Formatter &out,
236 size_t depth,
237 const std::string &name,
238 const std::string &sanitizedName,
239 bool nameIsPointer,
240 const std::string &parcelObj,
241 bool parcelObjIsPointer,
242 bool isReader,
243 ErrorMode mode,
244 const std::string & /* parentName */,
245 const std::string & /* offsetText */) const {
246 emitResolveReferencesEmbeddedHelper(
247 out, depth, name, sanitizedName, nameIsPointer, parcelObj,
248 parcelObjIsPointer, isReader, mode, "", "");
249}
250
251void VectorType::emitResolveReferencesEmbeddedHelper(
252 Formatter &out,
253 size_t depth,
254 const std::string &name,
255 const std::string &sanitizedName,
256 bool nameIsPointer,
257 const std::string &parcelObj,
258 bool parcelObjIsPointer,
259 bool isReader,
260 ErrorMode mode,
261 const std::string &childName,
262 const std::string &childOffsetText) const {
263 CHECK(needsResolveReferences() && mElementType->needsResolveReferences());
264
265 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
266 std::string elementExtra;
267 std::string elementType = mElementType->getCppType(&elementExtra);
268
269 std::string myChildName = childName, myChildOffset = childOffsetText;
270
271 if(myChildName.empty() && myChildOffset.empty()) {
272 myChildName = "_hidl_" + sanitizedName + "_child";
273 myChildOffset = "0";
274
275 out << "size_t " << myChildName << ";\n";
276 out << "_hidl_err = " << nameDeref << "findInParcel("
277 << (parcelObjIsPointer ? "*" : "") << parcelObj << ", "
278 << "&" << myChildName
279 << ");\n";
280
281 handleError(out, mode);
282 }
283
284 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
285
286 out << "for (size_t "
287 << iteratorName
288 << " = 0; "
289 << iteratorName
290 << " < "
291 << nameDeref
292 << "size(); ++"
293 << iteratorName
294 << ") {\n";
295
296 out.indent();
297
298 mElementType->emitResolveReferencesEmbedded(
299 out,
300 depth + 1,
301 (nameIsPointer ? "(*" + name + ")" : name) + "[" + iteratorName + "]",
302 sanitizedName + (nameIsPointer ? "_deref" : "") + "_indexed",
303 false /* nameIsPointer */,
304 parcelObj,
305 parcelObjIsPointer,
306 isReader,
307 mode,
308 myChildName,
309 myChildOffset + " + " +
310 iteratorName + " * sizeof(" + elementType + elementExtra + ")");
311
312 out.unindent();
313
314 out << "}\n\n";
315}
316
Andreas Huberf630bc82016-09-09 14:52:25 -0700317void VectorType::emitJavaReaderWriter(
318 Formatter &out,
319 const std::string &parcelObj,
320 const std::string &argName,
321 bool isReader) const {
322 if (mElementType->isCompoundType()) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700323 std::string extra; // unused, because CompoundType leaves this empty.
324
Andreas Huberf630bc82016-09-09 14:52:25 -0700325 if (isReader) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700326 out << mElementType->getJavaType(&extra)
Andreas Huberf630bc82016-09-09 14:52:25 -0700327 << ".readVectorFromParcel("
328 << parcelObj
329 << ");\n";
330 } else {
Andreas Huber4c865b72016-09-14 15:26:27 -0700331 out << mElementType->getJavaType(&extra)
Andreas Huberf630bc82016-09-09 14:52:25 -0700332 << ".writeVectorToParcel("
333 << parcelObj
334 << ", "
335 << argName
336 << ");\n";
337 }
338
339 return;
340 }
341
342 emitJavaReaderWriterWithSuffix(
343 out,
344 parcelObj,
345 argName,
346 isReader,
347 mElementType->getJavaSuffix() + "Vector",
348 "" /* extra */);
349}
350
Andreas Huber85eabdb2016-08-25 11:24:49 -0700351void VectorType::emitJavaFieldInitializer(
352 Formatter &out, const std::string &fieldName) const {
Andreas Huberf03332a2016-09-22 15:35:43 -0700353 std::string extra;
354 mElementType->getJavaType(&extra);
355
Andreas Hubera3558b32016-09-14 09:12:42 -0700356 const std::string wrapperType = mElementType->getJavaWrapperType();
357
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700358 out << "final ArrayList<"
Andreas Hubera3558b32016-09-14 09:12:42 -0700359 << wrapperType
Andreas Huberf03332a2016-09-22 15:35:43 -0700360 << extra
Andreas Huber85eabdb2016-08-25 11:24:49 -0700361 << "> "
362 << fieldName
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700363 << " = new ArrayList<"
Andreas Hubera3558b32016-09-14 09:12:42 -0700364 << wrapperType
Andreas Huberf03332a2016-09-22 15:35:43 -0700365 << extra
Andreas Hubera3558b32016-09-14 09:12:42 -0700366 << ">();\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700367}
368
369void VectorType::emitJavaFieldReaderWriter(
370 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700371 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700372 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700373 const std::string &blobName,
374 const std::string &fieldName,
375 const std::string &offset,
376 bool isReader) const {
Andreas Huberf630bc82016-09-09 14:52:25 -0700377 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber709b62d2016-09-19 11:21:18 -0700378 out,
379 depth,
380 mElementType,
381 parcelName,
382 blobName,
383 fieldName,
384 offset,
385 isReader);
Andreas Huberf630bc82016-09-09 14:52:25 -0700386}
387
388// static
389void VectorType::EmitJavaFieldReaderWriterForElementType(
390 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700391 size_t depth,
Andreas Huberf630bc82016-09-09 14:52:25 -0700392 const Type *elementType,
Andreas Huber709b62d2016-09-19 11:21:18 -0700393 const std::string &parcelName,
Andreas Huberf630bc82016-09-09 14:52:25 -0700394 const std::string &blobName,
395 const std::string &fieldName,
396 const std::string &offset,
397 bool isReader) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700398 if (isReader) {
399 out << "{\n";
400 out.indent();
401
Andreas Huber709b62d2016-09-19 11:21:18 -0700402 out << "HwBlob childBlob = "
403 << parcelName
404 << ".readEmbeddedBuffer(\n";
405
Andreas Huber85eabdb2016-08-25 11:24:49 -0700406 out.indent();
407 out.indent();
408
409 out << blobName
410 << ".handle(),\n"
411 << offset
412 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */);\n\n";
413
414 out.unindent();
415 out.unindent();
416
417 out << fieldName << ".clear();\n";
418 out << "long _hidl_vec_size = "
419 << blobName
420 << ".getInt64("
421 << offset
422 << " + 8 /* offsetof(hidl_vec<T>, mSize) */);\n";
423
Andreas Huber4c865b72016-09-14 15:26:27 -0700424 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
425
426 out << "for (int "
427 << iteratorName
428 << " = 0; "
429 << iteratorName
430 << " < _hidl_vec_size; "
431 << "++"
432 << iteratorName
433 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700434
435 out.indent();
436
Andreas Huberf630bc82016-09-09 14:52:25 -0700437 elementType->emitJavaFieldInitializer(out, "_hidl_vec_element");
Andreas Huber85eabdb2016-08-25 11:24:49 -0700438
439 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700440 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700441
Andreas Huberf630bc82016-09-09 14:52:25 -0700442 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700443 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700444 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700445 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700446 "childBlob",
447 "_hidl_vec_element",
Andreas Huber4c865b72016-09-14 15:26:27 -0700448 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700449 true /* isReader */);
450
Andreas Huberf03332a2016-09-22 15:35:43 -0700451 out << fieldName;
452
453 if (elementType->isArray()
454 && static_cast<const ArrayType *>(
455 elementType)->getElementType()->resolveToScalarType()
456 != nullptr) {
457 out << ".add(HwBlob.wrapArray(_hidl_vec_element));\n";
458 } else {
459 out << ".add(_hidl_vec_element);\n";
460 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700461
462 out.unindent();
463
464 out << "}\n";
465
466 out.unindent();
467 out << "}\n";
468
469 return;
470 }
471
472 out << "{\n";
473 out.indent();
474
475 out << "long _hidl_vec_size = "
476 << fieldName
477 << ".size();\n";
478
479 out << blobName
480 << ".putInt64("
481 << offset
482 << " + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);\n";
483
484 out << blobName
485 << ".putBool("
486 << offset
487 << " + 16 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);\n";
488
489 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700490 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700491
492 // XXX make HwBlob constructor take a long instead of an int?
493 out << "HwBlob childBlob = new HwBlob((int)(_hidl_vec_size * "
494 << elementSize
495 << "));\n";
496
Andreas Huber4c865b72016-09-14 15:26:27 -0700497 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
498
499 out << "for (int "
500 << iteratorName
501 << " = 0; "
502 << iteratorName
503 << " < _hidl_vec_size; "
504 << "++"
505 << iteratorName
506 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700507
508 out.indent();
509
Andreas Huberf630bc82016-09-09 14:52:25 -0700510 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700511 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700512 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700513 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700514 "childBlob",
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700515 fieldName + ".get(" + iteratorName + ")",
Andreas Huber4c865b72016-09-14 15:26:27 -0700516 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700517 false /* isReader */);
518
519 out.unindent();
520
521 out << "}\n";
522
523 out << blobName
524 << ".putBlob("
525 << offset
526 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);\n";
527
528 out.unindent();
529 out << "}\n";
530}
531
Andreas Huber881227d2016-08-02 14:20:21 -0700532bool VectorType::needsEmbeddedReadWrite() const {
533 return true;
534}
535
Yifan Hongbf459bc2016-08-23 16:50:37 -0700536bool VectorType::needsResolveReferences() const {
537 return mElementType->needsResolveReferences();
538}
539
Andreas Huber881227d2016-08-02 14:20:21 -0700540bool VectorType::resultNeedsDeref() const {
541 return true;
542}
543
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700544status_t VectorType::emitVtsTypeDeclarations(Formatter &out) const {
545 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
546 out.indent();
547 status_t err = mElementType->emitVtsTypeDeclarations(out);
548 if (err != OK) {
549 return err;
550 }
551 out.unindent();
552 out << "}\n";
553 return OK;
554}
555
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700556status_t VectorType::emitVtsAttributeType(Formatter &out) const {
557 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
558 out.indent();
559 status_t status = mElementType->emitVtsAttributeType(out);
560 if (status != OK) {
561 return status;
562 }
563 out.unindent();
564 out << "}\n";
565 return OK;
566}
567
Andreas Huber70a59e12016-08-16 12:57:01 -0700568bool VectorType::isJavaCompatible() const {
Andreas Huberf03332a2016-09-22 15:35:43 -0700569 if (!mElementType->isJavaCompatible()) {
570 return false;
571 }
572
573 if (mElementType->isArray()) {
574 return static_cast<ArrayType *>(mElementType)->countDimensions() == 1;
575 }
576
577 return true;
Andreas Huber70a59e12016-08-16 12:57:01 -0700578}
579
Andreas Huber85eabdb2016-08-25 11:24:49 -0700580void VectorType::getAlignmentAndSize(size_t *align, size_t *size) const {
581 *align = 8; // hidl_vec<T>
582 *size = 24;
583}
584
Andreas Huberc9410c72016-07-28 12:18:40 -0700585} // namespace android
586