blob: f656281d3235fb539cfa892f1aca50c50d3b9cae [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
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -070068std::string VectorType::getVtsType() const {
69 return "TYPE_VECTOR";
70}
71
Andreas Huber881227d2016-08-02 14:20:21 -070072void VectorType::emitReaderWriter(
73 Formatter &out,
74 const std::string &name,
75 const std::string &parcelObj,
76 bool parcelObjIsPointer,
77 bool isReader,
78 ErrorMode mode) const {
79 std::string baseExtra;
80 std::string baseType = mElementType->getCppType(&baseExtra);
81
Iliyan Malchev549e2592016-08-10 08:59:12 -070082 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -070083
84 out << "size_t " << parentName << ";\n\n";
85
86 const std::string parcelObjDeref =
87 parcelObj + (parcelObjIsPointer ? "->" : ".");
88
89 if (isReader) {
90 out << name
Andreas Huber8a82ff72016-08-04 10:29:39 -070091 << " = (const ::android::hardware::hidl_vec<"
Andreas Huber881227d2016-08-02 14:20:21 -070092 << baseType
Andreas Huberf9d49f12016-09-12 14:58:36 -070093 << baseExtra
Andreas Huber881227d2016-08-02 14:20:21 -070094 << "> *)"
95 << parcelObjDeref
96 << "readBuffer(&"
97 << parentName
98 << ");\n\n";
99
100 out << "if (" << name << " == nullptr) {\n";
101
102 out.indent();
103
Iliyan Malchev549e2592016-08-10 08:59:12 -0700104 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700105 handleError2(out, mode);
106
107 out.unindent();
108 out << "}\n\n";
109 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700110 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700111 << parcelObjDeref
112 << "writeBuffer(&"
113 << name
114 << ", sizeof("
115 << name
116 << "), &"
117 << parentName
118 << ");\n";
119
120 handleError(out, mode);
121 }
122
123 emitReaderWriterEmbedded(
124 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700125 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700126 name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700127 name /* sanitizedName */ ,
Andreas Huber881227d2016-08-02 14:20:21 -0700128 isReader /* nameIsPointer */,
129 parcelObj,
130 parcelObjIsPointer,
131 isReader,
132 mode,
133 parentName,
134 "0 /* parentOffset */");
135}
136
137void VectorType::emitReaderWriterEmbedded(
138 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700139 size_t depth,
Andreas Huber881227d2016-08-02 14:20:21 -0700140 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700141 const std::string &sanitizedName,
Andreas Huber881227d2016-08-02 14:20:21 -0700142 bool nameIsPointer,
143 const std::string &parcelObj,
144 bool parcelObjIsPointer,
145 bool isReader,
146 ErrorMode mode,
147 const std::string &parentName,
148 const std::string &offsetText) const {
149 std::string baseExtra;
150 std::string baseType = Type::getCppType(&baseExtra);
151
Yifan Hongbe2a3732016-10-05 13:33:41 -0700152 const std::string childName = "_hidl_" + sanitizedName + "_child";
Andreas Huber881227d2016-08-02 14:20:21 -0700153 out << "size_t " << childName << ";\n\n";
154
155 emitReaderWriterEmbeddedForTypeName(
156 out,
157 name,
158 nameIsPointer,
159 parcelObj,
160 parcelObjIsPointer,
161 isReader,
162 mode,
163 parentName,
164 offsetText,
165 baseType,
166 childName);
167
168 if (!mElementType->needsEmbeddedReadWrite()) {
169 return;
170 }
171
172 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
173
174 baseType = mElementType->getCppType(&baseExtra);
175
Andreas Huberf9d49f12016-09-12 14:58:36 -0700176 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
177
178 out << "for (size_t "
179 << iteratorName
180 << " = 0; "
181 << iteratorName
182 << " < "
Andreas Huber881227d2016-08-02 14:20:21 -0700183 << nameDeref
Andreas Huberf9d49f12016-09-12 14:58:36 -0700184 << "size(); ++"
185 << iteratorName
186 << ") {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700187
188 out.indent();
189
190 mElementType->emitReaderWriterEmbedded(
191 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700192 depth + 1,
193 (nameIsPointer ? "(*" + name + ")" : name)
194 + "[" + iteratorName + "]",
Yifan Hongbe2a3732016-10-05 13:33:41 -0700195 sanitizedName + (nameIsPointer ? "_deref" : "") + "_indexed",
Andreas Huber881227d2016-08-02 14:20:21 -0700196 false /* nameIsPointer */,
197 parcelObj,
198 parcelObjIsPointer,
199 isReader,
200 mode,
201 childName,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700202 iteratorName + " * sizeof(" + baseType + baseExtra + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700203
204 out.unindent();
205
206 out << "}\n\n";
207}
208
Yifan Hongbf459bc2016-08-23 16:50:37 -0700209void VectorType::emitResolveReferences(
210 Formatter &out,
211 const std::string &name,
212 bool nameIsPointer,
213 const std::string &parcelObj,
214 bool parcelObjIsPointer,
215 bool isReader,
216 ErrorMode mode) const {
217 emitResolveReferencesEmbeddedHelper(
218 out,
219 0, /* depth */
220 name,
221 name /* sanitizedName */,
222 nameIsPointer,
223 parcelObj,
224 parcelObjIsPointer,
225 isReader,
226 mode,
227 "_hidl_" + name + "_child",
228 "0 /* parentOffset */");
229}
230
231void VectorType::emitResolveReferencesEmbedded(
232 Formatter &out,
233 size_t depth,
234 const std::string &name,
235 const std::string &sanitizedName,
236 bool nameIsPointer,
237 const std::string &parcelObj,
238 bool parcelObjIsPointer,
239 bool isReader,
240 ErrorMode mode,
241 const std::string & /* parentName */,
242 const std::string & /* offsetText */) const {
243 emitResolveReferencesEmbeddedHelper(
244 out, depth, name, sanitizedName, nameIsPointer, parcelObj,
245 parcelObjIsPointer, isReader, mode, "", "");
246}
247
Yifan Hong00f47172016-09-30 14:40:45 -0700248bool VectorType::useParentInEmitResolveReferencesEmbedded() const {
249 // parentName and offsetText is not used in emitResolveReferencesEmbedded
250 return false;
251}
252
Yifan Hongbf459bc2016-08-23 16:50:37 -0700253void VectorType::emitResolveReferencesEmbeddedHelper(
254 Formatter &out,
255 size_t depth,
256 const std::string &name,
257 const std::string &sanitizedName,
258 bool nameIsPointer,
259 const std::string &parcelObj,
260 bool parcelObjIsPointer,
261 bool isReader,
262 ErrorMode mode,
263 const std::string &childName,
264 const std::string &childOffsetText) const {
265 CHECK(needsResolveReferences() && mElementType->needsResolveReferences());
266
267 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
268 std::string elementExtra;
269 std::string elementType = mElementType->getCppType(&elementExtra);
270
271 std::string myChildName = childName, myChildOffset = childOffsetText;
272
273 if(myChildName.empty() && myChildOffset.empty()) {
274 myChildName = "_hidl_" + sanitizedName + "_child";
275 myChildOffset = "0";
276
277 out << "size_t " << myChildName << ";\n";
278 out << "_hidl_err = " << nameDeref << "findInParcel("
279 << (parcelObjIsPointer ? "*" : "") << parcelObj << ", "
280 << "&" << myChildName
281 << ");\n";
282
283 handleError(out, mode);
284 }
285
286 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
287
288 out << "for (size_t "
289 << iteratorName
290 << " = 0; "
291 << iteratorName
292 << " < "
293 << nameDeref
294 << "size(); ++"
295 << iteratorName
296 << ") {\n";
297
298 out.indent();
299
300 mElementType->emitResolveReferencesEmbedded(
301 out,
302 depth + 1,
303 (nameIsPointer ? "(*" + name + ")" : name) + "[" + iteratorName + "]",
304 sanitizedName + (nameIsPointer ? "_deref" : "") + "_indexed",
305 false /* nameIsPointer */,
306 parcelObj,
307 parcelObjIsPointer,
308 isReader,
309 mode,
310 myChildName,
311 myChildOffset + " + " +
312 iteratorName + " * sizeof(" + elementType + elementExtra + ")");
313
314 out.unindent();
315
316 out << "}\n\n";
317}
318
Andreas Huberf630bc82016-09-09 14:52:25 -0700319void VectorType::emitJavaReaderWriter(
320 Formatter &out,
321 const std::string &parcelObj,
322 const std::string &argName,
323 bool isReader) const {
324 if (mElementType->isCompoundType()) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700325 std::string extra; // unused, because CompoundType leaves this empty.
326
Andreas Huberf630bc82016-09-09 14:52:25 -0700327 if (isReader) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700328 out << mElementType->getJavaType(&extra)
Andreas Huberf630bc82016-09-09 14:52:25 -0700329 << ".readVectorFromParcel("
330 << parcelObj
331 << ");\n";
332 } else {
Andreas Huber4c865b72016-09-14 15:26:27 -0700333 out << mElementType->getJavaType(&extra)
Andreas Huberf630bc82016-09-09 14:52:25 -0700334 << ".writeVectorToParcel("
335 << parcelObj
336 << ", "
337 << argName
338 << ");\n";
339 }
340
341 return;
342 }
343
344 emitJavaReaderWriterWithSuffix(
345 out,
346 parcelObj,
347 argName,
348 isReader,
349 mElementType->getJavaSuffix() + "Vector",
350 "" /* extra */);
351}
352
Andreas Huber85eabdb2016-08-25 11:24:49 -0700353void VectorType::emitJavaFieldInitializer(
354 Formatter &out, const std::string &fieldName) const {
Andreas Huberf03332a2016-09-22 15:35:43 -0700355 std::string extra;
356 mElementType->getJavaType(&extra);
357
Andreas Hubera3558b32016-09-14 09:12:42 -0700358 const std::string wrapperType = mElementType->getJavaWrapperType();
359
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700360 out << "final ArrayList<"
Andreas Hubera3558b32016-09-14 09:12:42 -0700361 << wrapperType
Andreas Huberf03332a2016-09-22 15:35:43 -0700362 << extra
Andreas Huber85eabdb2016-08-25 11:24:49 -0700363 << "> "
364 << fieldName
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700365 << " = new ArrayList<"
Andreas Hubera3558b32016-09-14 09:12:42 -0700366 << wrapperType
Andreas Huberf03332a2016-09-22 15:35:43 -0700367 << extra
Andreas Hubera3558b32016-09-14 09:12:42 -0700368 << ">();\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700369}
370
371void VectorType::emitJavaFieldReaderWriter(
372 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700373 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700374 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700375 const std::string &blobName,
376 const std::string &fieldName,
377 const std::string &offset,
378 bool isReader) const {
Andreas Huberf630bc82016-09-09 14:52:25 -0700379 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber709b62d2016-09-19 11:21:18 -0700380 out,
381 depth,
382 mElementType,
383 parcelName,
384 blobName,
385 fieldName,
386 offset,
387 isReader);
Andreas Huberf630bc82016-09-09 14:52:25 -0700388}
389
390// static
391void VectorType::EmitJavaFieldReaderWriterForElementType(
392 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700393 size_t depth,
Andreas Huberf630bc82016-09-09 14:52:25 -0700394 const Type *elementType,
Andreas Huber709b62d2016-09-19 11:21:18 -0700395 const std::string &parcelName,
Andreas Huberf630bc82016-09-09 14:52:25 -0700396 const std::string &blobName,
397 const std::string &fieldName,
398 const std::string &offset,
399 bool isReader) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700400 if (isReader) {
401 out << "{\n";
402 out.indent();
403
Andreas Huber709b62d2016-09-19 11:21:18 -0700404 out << "HwBlob childBlob = "
405 << parcelName
406 << ".readEmbeddedBuffer(\n";
407
Andreas Huber85eabdb2016-08-25 11:24:49 -0700408 out.indent();
409 out.indent();
410
411 out << blobName
412 << ".handle(),\n"
413 << offset
414 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */);\n\n";
415
416 out.unindent();
417 out.unindent();
418
419 out << fieldName << ".clear();\n";
420 out << "long _hidl_vec_size = "
421 << blobName
422 << ".getInt64("
423 << offset
424 << " + 8 /* offsetof(hidl_vec<T>, mSize) */);\n";
425
Andreas Huber4c865b72016-09-14 15:26:27 -0700426 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
427
428 out << "for (int "
429 << iteratorName
430 << " = 0; "
431 << iteratorName
432 << " < _hidl_vec_size; "
433 << "++"
434 << iteratorName
435 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700436
437 out.indent();
438
Andreas Huberf630bc82016-09-09 14:52:25 -0700439 elementType->emitJavaFieldInitializer(out, "_hidl_vec_element");
Andreas Huber85eabdb2016-08-25 11:24:49 -0700440
441 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700442 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700443
Andreas Huberf630bc82016-09-09 14:52:25 -0700444 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700445 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700446 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700447 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700448 "childBlob",
449 "_hidl_vec_element",
Andreas Huber4c865b72016-09-14 15:26:27 -0700450 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700451 true /* isReader */);
452
Andreas Huberf03332a2016-09-22 15:35:43 -0700453 out << fieldName;
454
455 if (elementType->isArray()
456 && static_cast<const ArrayType *>(
457 elementType)->getElementType()->resolveToScalarType()
458 != nullptr) {
459 out << ".add(HwBlob.wrapArray(_hidl_vec_element));\n";
460 } else {
461 out << ".add(_hidl_vec_element);\n";
462 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700463
464 out.unindent();
465
466 out << "}\n";
467
468 out.unindent();
469 out << "}\n";
470
471 return;
472 }
473
474 out << "{\n";
475 out.indent();
476
477 out << "long _hidl_vec_size = "
478 << fieldName
479 << ".size();\n";
480
481 out << blobName
482 << ".putInt64("
483 << offset
484 << " + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);\n";
485
486 out << blobName
487 << ".putBool("
488 << offset
489 << " + 16 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);\n";
490
491 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700492 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700493
494 // XXX make HwBlob constructor take a long instead of an int?
495 out << "HwBlob childBlob = new HwBlob((int)(_hidl_vec_size * "
496 << elementSize
497 << "));\n";
498
Andreas Huber4c865b72016-09-14 15:26:27 -0700499 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
500
501 out << "for (int "
502 << iteratorName
503 << " = 0; "
504 << iteratorName
505 << " < _hidl_vec_size; "
506 << "++"
507 << iteratorName
508 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700509
510 out.indent();
511
Andreas Huberf630bc82016-09-09 14:52:25 -0700512 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700513 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700514 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700515 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700516 "childBlob",
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700517 fieldName + ".get(" + iteratorName + ")",
Andreas Huber4c865b72016-09-14 15:26:27 -0700518 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700519 false /* isReader */);
520
521 out.unindent();
522
523 out << "}\n";
524
525 out << blobName
526 << ".putBlob("
527 << offset
528 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);\n";
529
530 out.unindent();
531 out << "}\n";
532}
533
Andreas Huber881227d2016-08-02 14:20:21 -0700534bool VectorType::needsEmbeddedReadWrite() const {
535 return true;
536}
537
Yifan Hongbf459bc2016-08-23 16:50:37 -0700538bool VectorType::needsResolveReferences() const {
539 return mElementType->needsResolveReferences();
540}
541
Andreas Huber881227d2016-08-02 14:20:21 -0700542bool VectorType::resultNeedsDeref() const {
543 return true;
544}
545
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700546status_t VectorType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700547 out << "type: " << getVtsType() << "\n";
548 out << "vector_value: {\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700549 out.indent();
550 status_t err = mElementType->emitVtsTypeDeclarations(out);
551 if (err != OK) {
552 return err;
553 }
554 out.unindent();
555 out << "}\n";
556 return OK;
557}
558
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700559status_t VectorType::emitVtsAttributeType(Formatter &out) const {
560 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
561 out.indent();
562 status_t status = mElementType->emitVtsAttributeType(out);
563 if (status != OK) {
564 return status;
565 }
566 out.unindent();
567 out << "}\n";
568 return OK;
569}
570
Andreas Huber70a59e12016-08-16 12:57:01 -0700571bool VectorType::isJavaCompatible() const {
Andreas Huberf03332a2016-09-22 15:35:43 -0700572 if (!mElementType->isJavaCompatible()) {
573 return false;
574 }
575
576 if (mElementType->isArray()) {
577 return static_cast<ArrayType *>(mElementType)->countDimensions() == 1;
578 }
579
580 return true;
Andreas Huber70a59e12016-08-16 12:57:01 -0700581}
582
Andreas Huber85eabdb2016-08-25 11:24:49 -0700583void VectorType::getAlignmentAndSize(size_t *align, size_t *size) const {
584 *align = 8; // hidl_vec<T>
585 *size = 24;
586}
587
Andreas Huberc9410c72016-07-28 12:18:40 -0700588} // namespace android
589