blob: 400cc1941b8356a4a3aa4d4602447c2cdec53e35 [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 "CompoundType.h"
18
Andreas Huberf630bc82016-09-09 14:52:25 -070019#include "VectorType.h"
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070020#include <hidl-util/Formatter.h>
Andreas Huber5a545442016-08-03 10:44:56 -070021#include <android-base/logging.h>
22
Andreas Huberc9410c72016-07-28 12:18:40 -070023namespace android {
24
Andreas Huber9ed827c2016-08-22 12:31:13 -070025CompoundType::CompoundType(Style style, const char *localName)
26 : Scope(localName),
27 mStyle(style),
Andreas Huberc9410c72016-07-28 12:18:40 -070028 mFields(NULL) {
29}
30
Andreas Huber0d0f9a22016-08-17 10:26:11 -070031bool CompoundType::setFields(
32 std::vector<CompoundField *> *fields, std::string *errorMsg) {
Andreas Huberc9410c72016-07-28 12:18:40 -070033 mFields = fields;
Andreas Huber5a545442016-08-03 10:44:56 -070034
35 for (const auto &field : *fields) {
36 const Type &type = field->type();
37
Andreas Huber295ad302016-08-16 11:35:00 -070038 if (type.isBinder()) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -070039 *errorMsg =
40 "Structs/Unions must not contain references to interfaces.";
Andreas Huberb95ea8a2016-08-15 15:35:42 -070041
42 return false;
43 }
44
Andreas Huber5a545442016-08-03 10:44:56 -070045 if (mStyle == STYLE_UNION) {
46 if (type.needsEmbeddedReadWrite()) {
47 // Can't have those in a union.
48
Andreas Huber0d0f9a22016-08-17 10:26:11 -070049 *errorMsg =
50 "Unions must not contain any types that need fixup.";
Andreas Huber5a545442016-08-03 10:44:56 -070051
52 return false;
53 }
Andreas Huber5a545442016-08-03 10:44:56 -070054 }
55 }
56
57 return true;
Andreas Huberc9410c72016-07-28 12:18:40 -070058}
59
Andreas Huberf630bc82016-09-09 14:52:25 -070060bool CompoundType::isCompoundType() const {
61 return true;
62}
63
Andreas Huber881227d2016-08-02 14:20:21 -070064std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -070065 StorageMode mode,
66 std::string *extra,
67 bool specifyNamespaces) const {
68
Andreas Huber881227d2016-08-02 14:20:21 -070069 extra->clear();
Steven Moreland979e0992016-09-07 09:18:08 -070070 const std::string base =
71 specifyNamespaces ? fullName() : partialCppName();
Andreas Huber881227d2016-08-02 14:20:21 -070072
73 switch (mode) {
74 case StorageMode_Stack:
75 return base;
76
77 case StorageMode_Argument:
78 return "const " + base + "&";
79
80 case StorageMode_Result:
81 return "const " + base + "*";
82 }
83}
84
Andreas Huber4c865b72016-09-14 15:26:27 -070085std::string CompoundType::getJavaType(
86 std::string *extra, bool /* forInitializer */) const {
87 extra->clear();
Andreas Huber85eabdb2016-08-25 11:24:49 -070088 return fullJavaName();
89}
90
Andreas Huber881227d2016-08-02 14:20:21 -070091void CompoundType::emitReaderWriter(
92 Formatter &out,
93 const std::string &name,
94 const std::string &parcelObj,
95 bool parcelObjIsPointer,
96 bool isReader,
97 ErrorMode mode) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -070098 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -070099
100 out << "size_t " << parentName << ";\n\n";
101
102 const std::string parcelObjDeref =
103 parcelObj + (parcelObjIsPointer ? "->" : ".");
104
105 if (isReader) {
106 out << name
107 << " = (const "
Andreas Huber0e00de42016-08-03 09:56:02 -0700108 << fullName()
Andreas Huber881227d2016-08-02 14:20:21 -0700109 << " *)"
110 << parcelObjDeref
111 << "readBuffer("
112 << "&"
113 << parentName
114 << ");\n";
115
116 out << "if ("
117 << name
118 << " == nullptr) {\n";
119
120 out.indent();
121
Iliyan Malchev549e2592016-08-10 08:59:12 -0700122 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700123 handleError2(out, mode);
124
125 out.unindent();
126 out << "}\n\n";
127 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700128 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700129 << parcelObjDeref
130 << "writeBuffer(&"
131 << name
132 << ", sizeof("
133 << name
134 << "), &"
135 << parentName
136 << ");\n";
137
138 handleError(out, mode);
139 }
140
141 if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
142 return;
143 }
144
145 emitReaderWriterEmbedded(
146 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700147 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700148 name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700149 name, /* sanitizedName */
Andreas Huber881227d2016-08-02 14:20:21 -0700150 isReader /* nameIsPointer */,
151 parcelObj,
152 parcelObjIsPointer,
153 isReader,
154 mode,
155 parentName,
156 "0 /* parentOffset */");
157}
158
159void CompoundType::emitReaderWriterEmbedded(
160 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700161 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700162 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700163 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700164 bool nameIsPointer,
165 const std::string &parcelObj,
166 bool parcelObjIsPointer,
167 bool isReader,
168 ErrorMode mode,
169 const std::string &parentName,
170 const std::string &offsetText) const {
171 emitReaderWriterEmbeddedForTypeName(
172 out,
173 name,
174 nameIsPointer,
175 parcelObj,
176 parcelObjIsPointer,
177 isReader,
178 mode,
179 parentName,
180 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700181 fullName(),
Andreas Huber881227d2016-08-02 14:20:21 -0700182 "" /* childName */);
183}
184
Andreas Huber85eabdb2016-08-25 11:24:49 -0700185void CompoundType::emitJavaReaderWriter(
186 Formatter &out,
187 const std::string &parcelObj,
188 const std::string &argName,
189 bool isReader) const {
190 if (isReader) {
191 out << "new " << fullJavaName() << "();\n";
192 }
193
194 out << argName
195 << "."
196 << (isReader ? "readFromParcel" : "writeToParcel")
197 << "("
198 << parcelObj
199 << ");\n";
200}
201
202void CompoundType::emitJavaFieldInitializer(
203 Formatter &out, const std::string &fieldName) const {
204 out << "final "
205 << fullJavaName()
206 << " "
207 << fieldName
208 << " = new "
209 << fullJavaName()
210 << "();\n";
211}
212
213void CompoundType::emitJavaFieldReaderWriter(
214 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700215 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700216 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700217 const std::string &blobName,
218 const std::string &fieldName,
219 const std::string &offset,
220 bool isReader) const {
221 if (isReader) {
222 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700223 << ".readEmbeddedFromParcel("
224 << parcelName
225 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700226 << blobName
227 << ", "
228 << offset
229 << ");\n";
230
231 return;
232 }
233
234 out << fieldName
235 << ".writeEmbeddedToBlob("
236 << blobName
237 << ", "
238 << offset
239 << ");\n";
240}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700241void CompoundType::emitResolveReferences(
242 Formatter &out,
243 const std::string &name,
244 bool nameIsPointer,
245 const std::string &parcelObj,
246 bool parcelObjIsPointer,
247 bool isReader,
248 ErrorMode mode) const {
249 emitResolveReferencesEmbedded(
250 out,
251 0 /* depth */,
252 name,
253 name /* sanitizedName */,
254 nameIsPointer,
255 parcelObj,
256 parcelObjIsPointer,
257 isReader,
258 mode,
259 "_hidl_" + name + "_parent",
260 "0 /* parentOffset */");
261}
262
263void CompoundType::emitResolveReferencesEmbedded(
264 Formatter &out,
265 size_t /* depth */,
266 const std::string &name,
267 const std::string &/* sanitizedName */,
268 bool nameIsPointer,
269 const std::string &parcelObj,
270 bool parcelObjIsPointer,
271 bool isReader,
272 ErrorMode mode,
273 const std::string &parentName,
274 const std::string &offsetText) const {
275 CHECK(needsResolveReferences());
276
277 const std::string parcelObjDeref =
278 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
279
280 const std::string parcelObjPointer =
281 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
282
283 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
284 const std::string namePointer = nameIsPointer ? name : ("&" + name);
285
286 out << "_hidl_err = ";
287
288 if (isReader) {
289 out << "const_cast<"
290 << fullName()
291 << " *"
292 << ">("
293 << namePointer
294 << ")->readEmbeddedReferenceFromParcel(\n";
295 } else {
296 out << nameDeref
297 << "writeEmbeddedReferenceToParcel(\n";
298 }
299
300 out.indent();
301 out.indent();
302
303 out << (isReader ? parcelObjDeref : parcelObjPointer);
304 out << ",\n"
305 << parentName
306 << ",\n"
307 << offsetText;
308
309 out << ");\n\n";
310
311 out.unindent();
312 out.unindent();
313
314 handleError(out, mode);
315}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700316
Andreas Huber881227d2016-08-02 14:20:21 -0700317status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
318 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
319 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700320 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700321 << " {\n";
322
323 out.indent();
324
325 Scope::emitTypeDeclarations(out);
326
327 for (const auto &field : *mFields) {
328 std::string extra;
329 out << field->type().getCppType(&extra)
330 << " "
331 << field->name()
332 << extra
333 << ";\n";
334 }
335
336 if (needsEmbeddedReadWrite()) {
337 out << "\n::android::status_t readEmbeddedFromParcel(\n";
338
339 out.indent();
340 out.indent();
341
Andreas Huber8a82ff72016-08-04 10:29:39 -0700342 out << "const ::android::hardware::Parcel &parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700343 << "size_t parentHandle,\n"
344 << "size_t parentOffset);\n\n";
345
346 out.unindent();
347 out.unindent();
348
349 out << "::android::status_t writeEmbeddedToParcel(\n";
350
351 out.indent();
352 out.indent();
353
Andreas Huber8a82ff72016-08-04 10:29:39 -0700354 out << "::android::hardware::Parcel *parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700355 << "size_t parentHandle,\n"
356 << "size_t parentOffset) const;\n";
357
358 out.unindent();
359 out.unindent();
360 }
361
Yifan Hongbf459bc2016-08-23 16:50:37 -0700362 if(needsResolveReferences()) {
363 out << "\n";
364 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
365 out.indent(); out.indent();
366 out << "const ::android::hardware::Parcel &parcel,\n"
367 << "size_t parentHandle, size_t parentOffset);\n";
368 out.unindent(); out.unindent();
369 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
370 out.indent(); out.indent();
371 out << "::android::hardware::Parcel *,\n"
372 << "size_t parentHandle, size_t parentOffset) const;\n";
373 out.unindent(); out.unindent();
374 }
375
Andreas Huber881227d2016-08-02 14:20:21 -0700376 out.unindent();
377 out << "};\n\n";
378
379 return OK;
380}
381
382status_t CompoundType::emitTypeDefinitions(
383 Formatter &out, const std::string prefix) const {
Andreas Huber0e00de42016-08-03 09:56:02 -0700384 status_t err = Scope::emitTypeDefinitions(out, prefix + "::" + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700385
386 if (err != OK) {
387 return err;
388 }
389
Yifan Hongbf459bc2016-08-23 16:50:37 -0700390 if (needsEmbeddedReadWrite()) {
391 emitStructReaderWriter(out, prefix, true /* isReader */);
392 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -0700393 }
394
Yifan Hongbf459bc2016-08-23 16:50:37 -0700395 if (needsResolveReferences()) {
396 emitResolveReferenceDef(out, prefix, true /* isReader */);
397 emitResolveReferenceDef(out, prefix, false /* isReader */);
398 }
Andreas Huber881227d2016-08-02 14:20:21 -0700399
400 return OK;
401}
402
Andreas Huber85eabdb2016-08-25 11:24:49 -0700403status_t CompoundType::emitJavaTypeDeclarations(
404 Formatter &out, bool atTopLevel) const {
405 out << "public final ";
406
407 if (!atTopLevel) {
408 out << "static ";
409 }
410
411 out << "class "
412 << localName()
413 << " {\n";
414
415 out.indent();
416
417 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
418
419 for (const auto &field : *mFields) {
420 const bool isScope = field->type().isScope(); // really isStruct...
421
422 out << "public ";
423
424 field->type().emitJavaFieldInitializer(out, field->name());
425 }
426
427 if (!mFields->empty()) {
428 out << "\n";
429 }
430
431 out << "public final void readFromParcel(HwParcel parcel) {\n";
432 out.indent();
433 out << "HwBlob blob = parcel.readBuffer();\n";
434 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
435 out.unindent();
436 out << "}\n\n";
437
Andreas Huberf630bc82016-09-09 14:52:25 -0700438 ////////////////////////////////////////////////////////////////////////////
439
440 out << "public static final "
441 << localName()
Andreas Huberf630bc82016-09-09 14:52:25 -0700442 << "[] readVectorFromParcel(HwParcel parcel) {\n";
443 out.indent();
444
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700445 out << "ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700446 << localName()
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700447 << "> _hidl_vec = new ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700448
449 out << "HwBlob _hidl_blob = parcel.readBuffer();\n\n";
450
451 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700452 out,
453 0 /* depth */,
454 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700455 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700456 "_hidl_blob",
457 "_hidl_vec",
458 "0",
459 true /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700460
461 out << "\nreturn _hidl_vec.toArray(new "
462 << localName()
463 << "[_hidl_vec.size()]);\n";
464
465 out.unindent();
466 out << "}\n\n";
467
468 ////////////////////////////////////////////////////////////////////////////
469
Andreas Huber85eabdb2016-08-25 11:24:49 -0700470 out << "public final void readEmbeddedFromParcel(\n";
471 out.indent();
472 out.indent();
473 out << "HwParcel parcel, HwBlob _hidl_blob, long _hidl_offset) {\n";
474 out.unindent();
475
476 size_t offset = 0;
477 for (const auto &field : *mFields) {
478 size_t fieldAlign, fieldSize;
479 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
480
481 size_t pad = offset % fieldAlign;
482 if (pad > 0) {
483 offset += fieldAlign - pad;
484 }
485
486 field->type().emitJavaFieldReaderWriter(
487 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700488 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700489 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700490 "_hidl_blob",
491 field->name(),
492 "_hidl_offset + " + std::to_string(offset),
493 true /* isReader */);
494
495 offset += fieldSize;
496 }
497
498 out.unindent();
499 out << "}\n\n";
500
Andreas Huberf630bc82016-09-09 14:52:25 -0700501 ////////////////////////////////////////////////////////////////////////////
502
Andreas Huber709b62d2016-09-19 11:21:18 -0700503 size_t structAlign, structSize;
504 getAlignmentAndSize(&structAlign, &structSize);
505
Andreas Huber85eabdb2016-08-25 11:24:49 -0700506 out << "public final void writeToParcel(HwParcel parcel) {\n";
507 out.indent();
508
Andreas Huber85eabdb2016-08-25 11:24:49 -0700509 out << "HwBlob _hidl_blob = new HwBlob("
510 << structSize
511 << " /* size */);\n";
512
513 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
514 << "parcel.writeBuffer(_hidl_blob);\n";
515
516 out.unindent();
517 out << "}\n\n";
518
Andreas Huberf630bc82016-09-09 14:52:25 -0700519 ////////////////////////////////////////////////////////////////////////////
520
Andreas Huberf630bc82016-09-09 14:52:25 -0700521 out << "public static final void writeVectorToParcel(\n";
522 out.indent();
523 out.indent();
524 out << "HwParcel parcel, "
525 << localName()
526 << "[] _hidl_array) {\n";
527 out.unindent();
528
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700529 out << "ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700530 << localName()
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700531 << "> _hidl_vec = new ArrayList(Arrays.asList(_hidl_array));\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700532
533 out << "HwBlob _hidl_blob = new HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
534
535 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700536 out,
537 0 /* depth */,
538 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700539 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700540 "_hidl_blob",
541 "_hidl_vec",
542 "0",
543 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700544
545 out << "\nparcel.writeBuffer(_hidl_blob);\n";
546
547 out.unindent();
548 out << "}\n\n";
549
550 ////////////////////////////////////////////////////////////////////////////
551
Andreas Huber85eabdb2016-08-25 11:24:49 -0700552 out << "public final void writeEmbeddedToBlob(\n";
553 out.indent();
554 out.indent();
555 out << "HwBlob _hidl_blob, long _hidl_offset) {\n";
556 out.unindent();
557
558 offset = 0;
559 for (const auto &field : *mFields) {
560 size_t fieldAlign, fieldSize;
561 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
562
563 size_t pad = offset % fieldAlign;
564 if (pad > 0) {
565 offset += fieldAlign - pad;
566 }
567
568 field->type().emitJavaFieldReaderWriter(
569 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700570 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700571 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700572 "_hidl_blob",
573 field->name(),
574 "_hidl_offset + " + std::to_string(offset),
575 false /* isReader */);
576
577 offset += fieldSize;
578 }
579
580 out.unindent();
581 out << "}\n";
582
583 out.unindent();
584 out << "};\n\n";
585
586 return OK;
587}
588
Andreas Huber881227d2016-08-02 14:20:21 -0700589void CompoundType::emitStructReaderWriter(
590 Formatter &out, const std::string &prefix, bool isReader) const {
591 out << "::android::status_t "
592 << (prefix.empty() ? "" : (prefix + "::"))
Andreas Huber0e00de42016-08-03 09:56:02 -0700593 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700594 << (isReader ? "::readEmbeddedFromParcel"
595 : "::writeEmbeddedToParcel")
596 << "(\n";
597
598 out.indent();
599 out.indent();
600
601 if (isReader) {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700602 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700603 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700604 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700605 }
606
607 out << "size_t parentHandle,\n"
608 << "size_t parentOffset)";
609
610 if (!isReader) {
611 out << " const";
612 }
613
614 out << " {\n";
615
616 out.unindent();
617 out.unindent();
618 out.indent();
619
Iliyan Malchev549e2592016-08-10 08:59:12 -0700620 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700621
622 for (const auto &field : *mFields) {
623 if (!field->type().needsEmbeddedReadWrite()) {
624 continue;
625 }
626
627 field->type().emitReaderWriterEmbedded(
628 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700629 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700630 field->name(),
Yifan Hongbe2a3732016-10-05 13:33:41 -0700631 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700632 false /* nameIsPointer */,
633 "parcel",
634 !isReader /* parcelObjIsPointer */,
635 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700636 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700637 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700638 "parentOffset + offsetof("
639 + fullName()
640 + ", "
641 + field->name()
642 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700643 }
644
645 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700646 out << "_hidl_error:\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700647 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700648 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700649
650 out.unindent();
651 out << "}\n\n";
652}
653
Yifan Hongbf459bc2016-08-23 16:50:37 -0700654void CompoundType::emitResolveReferenceDef(
655 Formatter &out, const std::string prefix, bool isReader) const {
656 out << "::android::status_t "
657 << (prefix.empty() ? "" : (prefix + "::"))
658 << localName();
659
Yifan Hong00f47172016-09-30 14:40:45 -0700660
661 bool useParent = false;
662 for (const auto &field : *mFields) {
663 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
664 useParent = true;
665 break;
666 }
667 }
668
669 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
670 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
671
Yifan Hongbf459bc2016-08-23 16:50:37 -0700672 if (isReader) {
673 out << "::readEmbeddedReferenceFromParcel(\n";
674 out.indent(); out.indent();
675 out << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700676 << "size_t " << parentHandleName << ", "
677 << "size_t " << parentOffsetName << ")\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700678 out.unindent(); out.unindent();
679 } else {
680 out << "::writeEmbeddedReferenceToParcel(\n";
681 out.indent(); out.indent();
682 out << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700683 << "size_t " << parentHandleName << ", "
684 << "size_t " << parentOffsetName << ") const\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700685 out.unindent(); out.unindent();
686 }
687
688 out << " {\n";
689
690 out.indent();
691
692 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
693
Yifan Hong00f47172016-09-30 14:40:45 -0700694 // if not useParent, then parentName and offsetText
695 // should not be used at all, then the #error should not be emitted.
696 std::string error = useParent ? "" : "\n#error\n";
697
Yifan Hongbf459bc2016-08-23 16:50:37 -0700698 for (const auto &field : *mFields) {
699 if (!field->type().needsResolveReferences()) {
700 continue;
701 }
702
703 field->type().emitResolveReferencesEmbedded(
704 out,
705 0 /* depth */,
706 field->name(),
707 field->name() /* sanitizedName */,
708 false, // nameIsPointer
709 "parcel", // const std::string &parcelObj,
710 !isReader, // bool parcelObjIsPointer,
711 isReader, // bool isReader,
712 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -0700713 parentHandleName + error,
714 parentOffsetName
715 + " + offsetof("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700716 + fullName()
717 + ", "
718 + field->name()
Yifan Hong00f47172016-09-30 14:40:45 -0700719 + ")"
720 + error);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700721 }
722
723 out.unindent();
724 out << "_hidl_error:\n";
725 out.indent();
726 out << "return _hidl_err;\n";
727
728 out.unindent();
729 out << "}\n\n";
730}
731
Andreas Huber881227d2016-08-02 14:20:21 -0700732bool CompoundType::needsEmbeddedReadWrite() const {
733 if (mStyle != STYLE_STRUCT) {
734 return false;
735 }
736
737 for (const auto &field : *mFields) {
738 if (field->type().needsEmbeddedReadWrite()) {
739 return true;
740 }
741 }
742
743 return false;
744}
745
Yifan Hongbf459bc2016-08-23 16:50:37 -0700746bool CompoundType::needsResolveReferences() const {
747 if (mStyle != STYLE_STRUCT) {
748 return false;
749 }
750
751 for (const auto &field : *mFields) {
752 if (field->type().needsResolveReferences()) {
753 return true;
754 }
755 }
756
757 return false;
758}
759
Andreas Huber881227d2016-08-02 14:20:21 -0700760bool CompoundType::resultNeedsDeref() const {
761 return true;
762}
763
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700764status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
765 out << "name: \"" << localName() << "\"\n";
766 switch (mStyle) {
767 case STYLE_STRUCT:
768 {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700769 out << "type: TYPE_STRUCT\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700770 break;
771 }
772 case STYLE_UNION:
773 {
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700774 out << "type: TYPE_UNION\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700775 break;
776 }
777 default:
778 break;
779 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700780
781 // Emit declaration for each subtype.
782 for (const auto &type : getSubTypes()) {
783 switch (mStyle) {
784 case STYLE_STRUCT:
785 {
786 out << "struct_value: {\n";
787 break;
788 }
789 case STYLE_UNION:
790 {
791 out << "union_value: {\n";
792 break;
793 }
794 default:
795 break;
796 }
797 out.indent();
798 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700799 if (status != OK) {
800 return status;
801 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700802 out.unindent();
803 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700804 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700805
806 // Emit declaration for each field.
807 for (const auto &field : *mFields) {
808 switch (mStyle) {
809 case STYLE_STRUCT:
810 {
811 out << "struct_value: {\n";
812 break;
813 }
814 case STYLE_UNION:
815 {
816 out << "union_value: {\n";
817 break;
818 }
819 default:
820 break;
821 }
822 out.indent();
823 out << "name: \"" << field->name() << "\"\n";
824 status_t status = field->type().emitVtsAttributeType(out);
825 if (status != OK) {
826 return status;
827 }
828 out.unindent();
829 out << "}\n";
830 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700831
832 return OK;
833}
834
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700835status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700836 switch (mStyle) {
837 case STYLE_STRUCT:
838 {
839 out << "type: TYPE_STRUCT\n";
840 break;
841 }
842 case STYLE_UNION:
843 {
844 out << "type: TYPE_UNION\n";
845 break;
846 }
847 default:
848 break;
849 }
850 out << "predefined_type: \"" << localName() << "\"\n";
851 return OK;
852}
853
Andreas Huber70a59e12016-08-16 12:57:01 -0700854bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700855 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
856 return false;
857 }
858
859 for (const auto &field : *mFields) {
860 if (!field->type().isJavaCompatible()) {
861 return false;
862 }
863 }
864
865 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -0700866}
867
868void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
869 *align = 1;
870
871 size_t offset = 0;
872 for (const auto &field : *mFields) {
873 // Each field is aligned according to its alignment requirement.
874 // The surrounding structure's alignment is the maximum of its
875 // fields' aligments.
876
877 size_t fieldAlign, fieldSize;
878 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
879
880 size_t pad = offset % fieldAlign;
881 if (pad > 0) {
882 offset += fieldAlign - pad;
883 }
884
885 offset += fieldSize;
886
887 if (fieldAlign > (*align)) {
888 *align = fieldAlign;
889 }
890 }
891
892 // Final padding to account for the structure's alignment.
893 size_t pad = offset % (*align);
894 if (pad > 0) {
895 offset += (*align) - pad;
896 }
897
898 *size = offset;
Andreas Huber70a59e12016-08-16 12:57:01 -0700899}
900
Andreas Huber31629bc2016-08-03 09:06:40 -0700901////////////////////////////////////////////////////////////////////////////////
902
903CompoundField::CompoundField(const char *name, Type *type)
904 : mName(name),
905 mType(type) {
906}
907
908std::string CompoundField::name() const {
909 return mName;
910}
911
912const Type &CompoundField::type() const {
913 return *mType;
914}
915
Andreas Huberc9410c72016-07-28 12:18:40 -0700916} // namespace android
917