blob: 2e7d9322c6225812cb39e167ee04829a5bbb4ad3 [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,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700123 name /* sanitizedName */ ,
Andreas Huber881227d2016-08-02 14:20:21 -0700124 isReader /* nameIsPointer */,
125 parcelObj,
126 parcelObjIsPointer,
127 isReader,
128 mode,
129 parentName,
130 "0 /* parentOffset */");
131}
132
133void VectorType::emitReaderWriterEmbedded(
134 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700135 size_t depth,
Andreas Huber881227d2016-08-02 14:20:21 -0700136 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700137 const std::string &sanitizedName,
Andreas Huber881227d2016-08-02 14:20:21 -0700138 bool nameIsPointer,
139 const std::string &parcelObj,
140 bool parcelObjIsPointer,
141 bool isReader,
142 ErrorMode mode,
143 const std::string &parentName,
144 const std::string &offsetText) const {
145 std::string baseExtra;
146 std::string baseType = Type::getCppType(&baseExtra);
147
Yifan Hongbe2a3732016-10-05 13:33:41 -0700148 const std::string childName = "_hidl_" + sanitizedName + "_child";
Andreas Huber881227d2016-08-02 14:20:21 -0700149 out << "size_t " << childName << ";\n\n";
150
151 emitReaderWriterEmbeddedForTypeName(
152 out,
153 name,
154 nameIsPointer,
155 parcelObj,
156 parcelObjIsPointer,
157 isReader,
158 mode,
159 parentName,
160 offsetText,
161 baseType,
162 childName);
163
164 if (!mElementType->needsEmbeddedReadWrite()) {
165 return;
166 }
167
168 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
169
170 baseType = mElementType->getCppType(&baseExtra);
171
Andreas Huberf9d49f12016-09-12 14:58:36 -0700172 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
173
174 out << "for (size_t "
175 << iteratorName
176 << " = 0; "
177 << iteratorName
178 << " < "
Andreas Huber881227d2016-08-02 14:20:21 -0700179 << nameDeref
Andreas Huberf9d49f12016-09-12 14:58:36 -0700180 << "size(); ++"
181 << iteratorName
182 << ") {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700183
184 out.indent();
185
186 mElementType->emitReaderWriterEmbedded(
187 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700188 depth + 1,
189 (nameIsPointer ? "(*" + name + ")" : name)
190 + "[" + iteratorName + "]",
Yifan Hongbe2a3732016-10-05 13:33:41 -0700191 sanitizedName + (nameIsPointer ? "_deref" : "") + "_indexed",
Andreas Huber881227d2016-08-02 14:20:21 -0700192 false /* nameIsPointer */,
193 parcelObj,
194 parcelObjIsPointer,
195 isReader,
196 mode,
197 childName,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700198 iteratorName + " * sizeof(" + baseType + baseExtra + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700199
200 out.unindent();
201
202 out << "}\n\n";
203}
204
Yifan Hongbf459bc2016-08-23 16:50:37 -0700205void VectorType::emitResolveReferences(
206 Formatter &out,
207 const std::string &name,
208 bool nameIsPointer,
209 const std::string &parcelObj,
210 bool parcelObjIsPointer,
211 bool isReader,
212 ErrorMode mode) const {
213 emitResolveReferencesEmbeddedHelper(
214 out,
215 0, /* depth */
216 name,
217 name /* sanitizedName */,
218 nameIsPointer,
219 parcelObj,
220 parcelObjIsPointer,
221 isReader,
222 mode,
223 "_hidl_" + name + "_child",
224 "0 /* parentOffset */");
225}
226
227void VectorType::emitResolveReferencesEmbedded(
228 Formatter &out,
229 size_t depth,
230 const std::string &name,
231 const std::string &sanitizedName,
232 bool nameIsPointer,
233 const std::string &parcelObj,
234 bool parcelObjIsPointer,
235 bool isReader,
236 ErrorMode mode,
237 const std::string & /* parentName */,
238 const std::string & /* offsetText */) const {
239 emitResolveReferencesEmbeddedHelper(
240 out, depth, name, sanitizedName, nameIsPointer, parcelObj,
241 parcelObjIsPointer, isReader, mode, "", "");
242}
243
Yifan Hong00f47172016-09-30 14:40:45 -0700244bool VectorType::useParentInEmitResolveReferencesEmbedded() const {
245 // parentName and offsetText is not used in emitResolveReferencesEmbedded
246 return false;
247}
248
Yifan Hongbf459bc2016-08-23 16:50:37 -0700249void VectorType::emitResolveReferencesEmbeddedHelper(
250 Formatter &out,
251 size_t depth,
252 const std::string &name,
253 const std::string &sanitizedName,
254 bool nameIsPointer,
255 const std::string &parcelObj,
256 bool parcelObjIsPointer,
257 bool isReader,
258 ErrorMode mode,
259 const std::string &childName,
260 const std::string &childOffsetText) const {
261 CHECK(needsResolveReferences() && mElementType->needsResolveReferences());
262
263 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
264 std::string elementExtra;
265 std::string elementType = mElementType->getCppType(&elementExtra);
266
267 std::string myChildName = childName, myChildOffset = childOffsetText;
268
269 if(myChildName.empty() && myChildOffset.empty()) {
270 myChildName = "_hidl_" + sanitizedName + "_child";
271 myChildOffset = "0";
272
273 out << "size_t " << myChildName << ";\n";
274 out << "_hidl_err = " << nameDeref << "findInParcel("
275 << (parcelObjIsPointer ? "*" : "") << parcelObj << ", "
276 << "&" << myChildName
277 << ");\n";
278
279 handleError(out, mode);
280 }
281
282 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
283
284 out << "for (size_t "
285 << iteratorName
286 << " = 0; "
287 << iteratorName
288 << " < "
289 << nameDeref
290 << "size(); ++"
291 << iteratorName
292 << ") {\n";
293
294 out.indent();
295
296 mElementType->emitResolveReferencesEmbedded(
297 out,
298 depth + 1,
299 (nameIsPointer ? "(*" + name + ")" : name) + "[" + iteratorName + "]",
300 sanitizedName + (nameIsPointer ? "_deref" : "") + "_indexed",
301 false /* nameIsPointer */,
302 parcelObj,
303 parcelObjIsPointer,
304 isReader,
305 mode,
306 myChildName,
307 myChildOffset + " + " +
308 iteratorName + " * sizeof(" + elementType + elementExtra + ")");
309
310 out.unindent();
311
312 out << "}\n\n";
313}
314
Andreas Huberf630bc82016-09-09 14:52:25 -0700315void VectorType::emitJavaReaderWriter(
316 Formatter &out,
317 const std::string &parcelObj,
318 const std::string &argName,
319 bool isReader) const {
320 if (mElementType->isCompoundType()) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700321 std::string extra; // unused, because CompoundType leaves this empty.
322
Andreas Huberf630bc82016-09-09 14:52:25 -0700323 if (isReader) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700324 out << mElementType->getJavaType(&extra)
Andreas Huberf630bc82016-09-09 14:52:25 -0700325 << ".readVectorFromParcel("
326 << parcelObj
327 << ");\n";
328 } else {
Andreas Huber4c865b72016-09-14 15:26:27 -0700329 out << mElementType->getJavaType(&extra)
Andreas Huberf630bc82016-09-09 14:52:25 -0700330 << ".writeVectorToParcel("
331 << parcelObj
332 << ", "
333 << argName
334 << ");\n";
335 }
336
337 return;
338 }
339
340 emitJavaReaderWriterWithSuffix(
341 out,
342 parcelObj,
343 argName,
344 isReader,
345 mElementType->getJavaSuffix() + "Vector",
346 "" /* extra */);
347}
348
Andreas Huber85eabdb2016-08-25 11:24:49 -0700349void VectorType::emitJavaFieldInitializer(
350 Formatter &out, const std::string &fieldName) const {
Andreas Huberf03332a2016-09-22 15:35:43 -0700351 std::string extra;
352 mElementType->getJavaType(&extra);
353
Andreas Hubera3558b32016-09-14 09:12:42 -0700354 const std::string wrapperType = mElementType->getJavaWrapperType();
355
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700356 out << "final ArrayList<"
Andreas Hubera3558b32016-09-14 09:12:42 -0700357 << wrapperType
Andreas Huberf03332a2016-09-22 15:35:43 -0700358 << extra
Andreas Huber85eabdb2016-08-25 11:24:49 -0700359 << "> "
360 << fieldName
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700361 << " = new ArrayList<"
Andreas Hubera3558b32016-09-14 09:12:42 -0700362 << wrapperType
Andreas Huberf03332a2016-09-22 15:35:43 -0700363 << extra
Andreas Hubera3558b32016-09-14 09:12:42 -0700364 << ">();\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700365}
366
367void VectorType::emitJavaFieldReaderWriter(
368 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700369 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700370 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700371 const std::string &blobName,
372 const std::string &fieldName,
373 const std::string &offset,
374 bool isReader) const {
Andreas Huberf630bc82016-09-09 14:52:25 -0700375 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber709b62d2016-09-19 11:21:18 -0700376 out,
377 depth,
378 mElementType,
379 parcelName,
380 blobName,
381 fieldName,
382 offset,
383 isReader);
Andreas Huberf630bc82016-09-09 14:52:25 -0700384}
385
386// static
387void VectorType::EmitJavaFieldReaderWriterForElementType(
388 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700389 size_t depth,
Andreas Huberf630bc82016-09-09 14:52:25 -0700390 const Type *elementType,
Andreas Huber709b62d2016-09-19 11:21:18 -0700391 const std::string &parcelName,
Andreas Huberf630bc82016-09-09 14:52:25 -0700392 const std::string &blobName,
393 const std::string &fieldName,
394 const std::string &offset,
395 bool isReader) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700396 if (isReader) {
397 out << "{\n";
398 out.indent();
399
Andreas Huber709b62d2016-09-19 11:21:18 -0700400 out << "HwBlob childBlob = "
401 << parcelName
402 << ".readEmbeddedBuffer(\n";
403
Andreas Huber85eabdb2016-08-25 11:24:49 -0700404 out.indent();
405 out.indent();
406
407 out << blobName
408 << ".handle(),\n"
409 << offset
410 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */);\n\n";
411
412 out.unindent();
413 out.unindent();
414
415 out << fieldName << ".clear();\n";
416 out << "long _hidl_vec_size = "
417 << blobName
418 << ".getInt64("
419 << offset
420 << " + 8 /* offsetof(hidl_vec<T>, mSize) */);\n";
421
Andreas Huber4c865b72016-09-14 15:26:27 -0700422 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
423
424 out << "for (int "
425 << iteratorName
426 << " = 0; "
427 << iteratorName
428 << " < _hidl_vec_size; "
429 << "++"
430 << iteratorName
431 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700432
433 out.indent();
434
Andreas Huberf630bc82016-09-09 14:52:25 -0700435 elementType->emitJavaFieldInitializer(out, "_hidl_vec_element");
Andreas Huber85eabdb2016-08-25 11:24:49 -0700436
437 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700438 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700439
Andreas Huberf630bc82016-09-09 14:52:25 -0700440 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700441 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700442 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700443 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700444 "childBlob",
445 "_hidl_vec_element",
Andreas Huber4c865b72016-09-14 15:26:27 -0700446 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700447 true /* isReader */);
448
Andreas Huberf03332a2016-09-22 15:35:43 -0700449 out << fieldName;
450
451 if (elementType->isArray()
452 && static_cast<const ArrayType *>(
453 elementType)->getElementType()->resolveToScalarType()
454 != nullptr) {
455 out << ".add(HwBlob.wrapArray(_hidl_vec_element));\n";
456 } else {
457 out << ".add(_hidl_vec_element);\n";
458 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700459
460 out.unindent();
461
462 out << "}\n";
463
464 out.unindent();
465 out << "}\n";
466
467 return;
468 }
469
470 out << "{\n";
471 out.indent();
472
473 out << "long _hidl_vec_size = "
474 << fieldName
475 << ".size();\n";
476
477 out << blobName
478 << ".putInt64("
479 << offset
480 << " + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);\n";
481
482 out << blobName
483 << ".putBool("
484 << offset
485 << " + 16 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);\n";
486
487 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700488 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700489
490 // XXX make HwBlob constructor take a long instead of an int?
491 out << "HwBlob childBlob = new HwBlob((int)(_hidl_vec_size * "
492 << elementSize
493 << "));\n";
494
Andreas Huber4c865b72016-09-14 15:26:27 -0700495 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
496
497 out << "for (int "
498 << iteratorName
499 << " = 0; "
500 << iteratorName
501 << " < _hidl_vec_size; "
502 << "++"
503 << iteratorName
504 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700505
506 out.indent();
507
Andreas Huberf630bc82016-09-09 14:52:25 -0700508 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700509 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700510 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700511 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700512 "childBlob",
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700513 fieldName + ".get(" + iteratorName + ")",
Andreas Huber4c865b72016-09-14 15:26:27 -0700514 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700515 false /* isReader */);
516
517 out.unindent();
518
519 out << "}\n";
520
521 out << blobName
522 << ".putBlob("
523 << offset
524 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);\n";
525
526 out.unindent();
527 out << "}\n";
528}
529
Andreas Huber881227d2016-08-02 14:20:21 -0700530bool VectorType::needsEmbeddedReadWrite() const {
531 return true;
532}
533
Yifan Hongbf459bc2016-08-23 16:50:37 -0700534bool VectorType::needsResolveReferences() const {
535 return mElementType->needsResolveReferences();
536}
537
Andreas Huber881227d2016-08-02 14:20:21 -0700538bool VectorType::resultNeedsDeref() const {
539 return true;
540}
541
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700542status_t VectorType::emitVtsTypeDeclarations(Formatter &out) const {
543 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
544 out.indent();
545 status_t err = mElementType->emitVtsTypeDeclarations(out);
546 if (err != OK) {
547 return err;
548 }
549 out.unindent();
550 out << "}\n";
551 return OK;
552}
553
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700554status_t VectorType::emitVtsAttributeType(Formatter &out) const {
555 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
556 out.indent();
557 status_t status = mElementType->emitVtsAttributeType(out);
558 if (status != OK) {
559 return status;
560 }
561 out.unindent();
562 out << "}\n";
563 return OK;
564}
565
Andreas Huber70a59e12016-08-16 12:57:01 -0700566bool VectorType::isJavaCompatible() const {
Andreas Huberf03332a2016-09-22 15:35:43 -0700567 if (!mElementType->isJavaCompatible()) {
568 return false;
569 }
570
571 if (mElementType->isArray()) {
572 return static_cast<ArrayType *>(mElementType)->countDimensions() == 1;
573 }
574
575 return true;
Andreas Huber70a59e12016-08-16 12:57:01 -0700576}
577
Andreas Huber85eabdb2016-08-25 11:24:49 -0700578void VectorType::getAlignmentAndSize(size_t *align, size_t *size) const {
579 *align = 8; // hidl_vec<T>
580 *size = 24;
581}
582
Andreas Huberc9410c72016-07-28 12:18:40 -0700583} // namespace android
584