blob: b7bebe43129fcfcd5d06b4502000b2740d0ea489 [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
Yifan Hong00f47172016-09-30 14:40:45 -0700251bool VectorType::useParentInEmitResolveReferencesEmbedded() const {
252 // parentName and offsetText is not used in emitResolveReferencesEmbedded
253 return false;
254}
255
Yifan Hongbf459bc2016-08-23 16:50:37 -0700256void VectorType::emitResolveReferencesEmbeddedHelper(
257 Formatter &out,
258 size_t depth,
259 const std::string &name,
260 const std::string &sanitizedName,
261 bool nameIsPointer,
262 const std::string &parcelObj,
263 bool parcelObjIsPointer,
264 bool isReader,
265 ErrorMode mode,
266 const std::string &childName,
267 const std::string &childOffsetText) const {
268 CHECK(needsResolveReferences() && mElementType->needsResolveReferences());
269
270 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
271 std::string elementExtra;
272 std::string elementType = mElementType->getCppType(&elementExtra);
273
274 std::string myChildName = childName, myChildOffset = childOffsetText;
275
276 if(myChildName.empty() && myChildOffset.empty()) {
277 myChildName = "_hidl_" + sanitizedName + "_child";
278 myChildOffset = "0";
279
280 out << "size_t " << myChildName << ";\n";
281 out << "_hidl_err = " << nameDeref << "findInParcel("
282 << (parcelObjIsPointer ? "*" : "") << parcelObj << ", "
283 << "&" << myChildName
284 << ");\n";
285
286 handleError(out, mode);
287 }
288
289 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
290
291 out << "for (size_t "
292 << iteratorName
293 << " = 0; "
294 << iteratorName
295 << " < "
296 << nameDeref
297 << "size(); ++"
298 << iteratorName
299 << ") {\n";
300
301 out.indent();
302
303 mElementType->emitResolveReferencesEmbedded(
304 out,
305 depth + 1,
306 (nameIsPointer ? "(*" + name + ")" : name) + "[" + iteratorName + "]",
307 sanitizedName + (nameIsPointer ? "_deref" : "") + "_indexed",
308 false /* nameIsPointer */,
309 parcelObj,
310 parcelObjIsPointer,
311 isReader,
312 mode,
313 myChildName,
314 myChildOffset + " + " +
315 iteratorName + " * sizeof(" + elementType + elementExtra + ")");
316
317 out.unindent();
318
319 out << "}\n\n";
320}
321
Andreas Huberf630bc82016-09-09 14:52:25 -0700322void VectorType::emitJavaReaderWriter(
323 Formatter &out,
324 const std::string &parcelObj,
325 const std::string &argName,
326 bool isReader) const {
327 if (mElementType->isCompoundType()) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700328 std::string extra; // unused, because CompoundType leaves this empty.
329
Andreas Huberf630bc82016-09-09 14:52:25 -0700330 if (isReader) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700331 out << mElementType->getJavaType(&extra)
Andreas Huberf630bc82016-09-09 14:52:25 -0700332 << ".readVectorFromParcel("
333 << parcelObj
334 << ");\n";
335 } else {
Andreas Huber4c865b72016-09-14 15:26:27 -0700336 out << mElementType->getJavaType(&extra)
Andreas Huberf630bc82016-09-09 14:52:25 -0700337 << ".writeVectorToParcel("
338 << parcelObj
339 << ", "
340 << argName
341 << ");\n";
342 }
343
344 return;
345 }
346
347 emitJavaReaderWriterWithSuffix(
348 out,
349 parcelObj,
350 argName,
351 isReader,
352 mElementType->getJavaSuffix() + "Vector",
353 "" /* extra */);
354}
355
Andreas Huber85eabdb2016-08-25 11:24:49 -0700356void VectorType::emitJavaFieldInitializer(
357 Formatter &out, const std::string &fieldName) const {
Andreas Huberf03332a2016-09-22 15:35:43 -0700358 std::string extra;
359 mElementType->getJavaType(&extra);
360
Andreas Hubera3558b32016-09-14 09:12:42 -0700361 const std::string wrapperType = mElementType->getJavaWrapperType();
362
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700363 out << "final ArrayList<"
Andreas Hubera3558b32016-09-14 09:12:42 -0700364 << wrapperType
Andreas Huberf03332a2016-09-22 15:35:43 -0700365 << extra
Andreas Huber85eabdb2016-08-25 11:24:49 -0700366 << "> "
367 << fieldName
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700368 << " = new ArrayList<"
Andreas Hubera3558b32016-09-14 09:12:42 -0700369 << wrapperType
Andreas Huberf03332a2016-09-22 15:35:43 -0700370 << extra
Andreas Hubera3558b32016-09-14 09:12:42 -0700371 << ">();\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700372}
373
374void VectorType::emitJavaFieldReaderWriter(
375 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700376 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700377 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700378 const std::string &blobName,
379 const std::string &fieldName,
380 const std::string &offset,
381 bool isReader) const {
Andreas Huberf630bc82016-09-09 14:52:25 -0700382 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber709b62d2016-09-19 11:21:18 -0700383 out,
384 depth,
385 mElementType,
386 parcelName,
387 blobName,
388 fieldName,
389 offset,
390 isReader);
Andreas Huberf630bc82016-09-09 14:52:25 -0700391}
392
393// static
394void VectorType::EmitJavaFieldReaderWriterForElementType(
395 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700396 size_t depth,
Andreas Huberf630bc82016-09-09 14:52:25 -0700397 const Type *elementType,
Andreas Huber709b62d2016-09-19 11:21:18 -0700398 const std::string &parcelName,
Andreas Huberf630bc82016-09-09 14:52:25 -0700399 const std::string &blobName,
400 const std::string &fieldName,
401 const std::string &offset,
402 bool isReader) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700403 if (isReader) {
404 out << "{\n";
405 out.indent();
406
Andreas Huber709b62d2016-09-19 11:21:18 -0700407 out << "HwBlob childBlob = "
408 << parcelName
409 << ".readEmbeddedBuffer(\n";
410
Andreas Huber85eabdb2016-08-25 11:24:49 -0700411 out.indent();
412 out.indent();
413
414 out << blobName
415 << ".handle(),\n"
416 << offset
417 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */);\n\n";
418
419 out.unindent();
420 out.unindent();
421
422 out << fieldName << ".clear();\n";
423 out << "long _hidl_vec_size = "
424 << blobName
425 << ".getInt64("
426 << offset
427 << " + 8 /* offsetof(hidl_vec<T>, mSize) */);\n";
428
Andreas Huber4c865b72016-09-14 15:26:27 -0700429 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
430
431 out << "for (int "
432 << iteratorName
433 << " = 0; "
434 << iteratorName
435 << " < _hidl_vec_size; "
436 << "++"
437 << iteratorName
438 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700439
440 out.indent();
441
Andreas Huberf630bc82016-09-09 14:52:25 -0700442 elementType->emitJavaFieldInitializer(out, "_hidl_vec_element");
Andreas Huber85eabdb2016-08-25 11:24:49 -0700443
444 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700445 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700446
Andreas Huberf630bc82016-09-09 14:52:25 -0700447 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700448 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700449 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700450 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700451 "childBlob",
452 "_hidl_vec_element",
Andreas Huber4c865b72016-09-14 15:26:27 -0700453 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700454 true /* isReader */);
455
Andreas Huberf03332a2016-09-22 15:35:43 -0700456 out << fieldName;
457
458 if (elementType->isArray()
459 && static_cast<const ArrayType *>(
460 elementType)->getElementType()->resolveToScalarType()
461 != nullptr) {
462 out << ".add(HwBlob.wrapArray(_hidl_vec_element));\n";
463 } else {
464 out << ".add(_hidl_vec_element);\n";
465 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700466
467 out.unindent();
468
469 out << "}\n";
470
471 out.unindent();
472 out << "}\n";
473
474 return;
475 }
476
477 out << "{\n";
478 out.indent();
479
480 out << "long _hidl_vec_size = "
481 << fieldName
482 << ".size();\n";
483
484 out << blobName
485 << ".putInt64("
486 << offset
487 << " + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);\n";
488
489 out << blobName
490 << ".putBool("
491 << offset
492 << " + 16 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);\n";
493
494 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700495 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700496
497 // XXX make HwBlob constructor take a long instead of an int?
498 out << "HwBlob childBlob = new HwBlob((int)(_hidl_vec_size * "
499 << elementSize
500 << "));\n";
501
Andreas Huber4c865b72016-09-14 15:26:27 -0700502 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
503
504 out << "for (int "
505 << iteratorName
506 << " = 0; "
507 << iteratorName
508 << " < _hidl_vec_size; "
509 << "++"
510 << iteratorName
511 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700512
513 out.indent();
514
Andreas Huberf630bc82016-09-09 14:52:25 -0700515 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700516 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700517 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700518 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700519 "childBlob",
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700520 fieldName + ".get(" + iteratorName + ")",
Andreas Huber4c865b72016-09-14 15:26:27 -0700521 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700522 false /* isReader */);
523
524 out.unindent();
525
526 out << "}\n";
527
528 out << blobName
529 << ".putBlob("
530 << offset
531 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);\n";
532
533 out.unindent();
534 out << "}\n";
535}
536
Andreas Huber881227d2016-08-02 14:20:21 -0700537bool VectorType::needsEmbeddedReadWrite() const {
538 return true;
539}
540
Yifan Hongbf459bc2016-08-23 16:50:37 -0700541bool VectorType::needsResolveReferences() const {
542 return mElementType->needsResolveReferences();
543}
544
Andreas Huber881227d2016-08-02 14:20:21 -0700545bool VectorType::resultNeedsDeref() const {
546 return true;
547}
548
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700549status_t VectorType::emitVtsTypeDeclarations(Formatter &out) const {
550 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
551 out.indent();
552 status_t err = mElementType->emitVtsTypeDeclarations(out);
553 if (err != OK) {
554 return err;
555 }
556 out.unindent();
557 out << "}\n";
558 return OK;
559}
560
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700561status_t VectorType::emitVtsAttributeType(Formatter &out) const {
562 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
563 out.indent();
564 status_t status = mElementType->emitVtsAttributeType(out);
565 if (status != OK) {
566 return status;
567 }
568 out.unindent();
569 out << "}\n";
570 return OK;
571}
572
Andreas Huber70a59e12016-08-16 12:57:01 -0700573bool VectorType::isJavaCompatible() const {
Andreas Huberf03332a2016-09-22 15:35:43 -0700574 if (!mElementType->isJavaCompatible()) {
575 return false;
576 }
577
578 if (mElementType->isArray()) {
579 return static_cast<ArrayType *>(mElementType)->countDimensions() == 1;
580 }
581
582 return true;
Andreas Huber70a59e12016-08-16 12:57:01 -0700583}
584
Andreas Huber85eabdb2016-08-25 11:24:49 -0700585void VectorType::getAlignmentAndSize(size_t *align, size_t *size) const {
586 *align = 8; // hidl_vec<T>
587 *size = 24;
588}
589
Andreas Huberc9410c72016-07-28 12:18:40 -0700590} // namespace android
591