blob: 7c8e04ac11923acd566608e923f18c2eeba9f64c [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
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -070091std::string CompoundType::getVtsType() const {
92 switch (mStyle) {
93 case STYLE_STRUCT:
94 {
95 return "TYPE_STRUCT";
96 }
97 case STYLE_UNION:
98 {
99 return "TYPE_UNION";
100 }
101 }
102}
103
Andreas Huber881227d2016-08-02 14:20:21 -0700104void CompoundType::emitReaderWriter(
105 Formatter &out,
106 const std::string &name,
107 const std::string &parcelObj,
108 bool parcelObjIsPointer,
109 bool isReader,
110 ErrorMode mode) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700111 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700112
113 out << "size_t " << parentName << ";\n\n";
114
115 const std::string parcelObjDeref =
116 parcelObj + (parcelObjIsPointer ? "->" : ".");
117
118 if (isReader) {
119 out << name
120 << " = (const "
Andreas Huber0e00de42016-08-03 09:56:02 -0700121 << fullName()
Andreas Huber881227d2016-08-02 14:20:21 -0700122 << " *)"
123 << parcelObjDeref
124 << "readBuffer("
125 << "&"
126 << parentName
127 << ");\n";
128
129 out << "if ("
130 << name
131 << " == nullptr) {\n";
132
133 out.indent();
134
Iliyan Malchev549e2592016-08-10 08:59:12 -0700135 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700136 handleError2(out, mode);
137
138 out.unindent();
139 out << "}\n\n";
140 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700141 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700142 << parcelObjDeref
143 << "writeBuffer(&"
144 << name
145 << ", sizeof("
146 << name
147 << "), &"
148 << parentName
149 << ");\n";
150
151 handleError(out, mode);
152 }
153
154 if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
155 return;
156 }
157
158 emitReaderWriterEmbedded(
159 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700160 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700161 name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700162 name, /* sanitizedName */
Andreas Huber881227d2016-08-02 14:20:21 -0700163 isReader /* nameIsPointer */,
164 parcelObj,
165 parcelObjIsPointer,
166 isReader,
167 mode,
168 parentName,
169 "0 /* parentOffset */");
170}
171
172void CompoundType::emitReaderWriterEmbedded(
173 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700174 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700175 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700176 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700177 bool nameIsPointer,
178 const std::string &parcelObj,
179 bool parcelObjIsPointer,
180 bool isReader,
181 ErrorMode mode,
182 const std::string &parentName,
183 const std::string &offsetText) const {
184 emitReaderWriterEmbeddedForTypeName(
185 out,
186 name,
187 nameIsPointer,
188 parcelObj,
189 parcelObjIsPointer,
190 isReader,
191 mode,
192 parentName,
193 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700194 fullName(),
Andreas Huber881227d2016-08-02 14:20:21 -0700195 "" /* childName */);
196}
197
Andreas Huber85eabdb2016-08-25 11:24:49 -0700198void CompoundType::emitJavaReaderWriter(
199 Formatter &out,
200 const std::string &parcelObj,
201 const std::string &argName,
202 bool isReader) const {
203 if (isReader) {
204 out << "new " << fullJavaName() << "();\n";
205 }
206
207 out << argName
208 << "."
209 << (isReader ? "readFromParcel" : "writeToParcel")
210 << "("
211 << parcelObj
212 << ");\n";
213}
214
215void CompoundType::emitJavaFieldInitializer(
216 Formatter &out, const std::string &fieldName) const {
217 out << "final "
218 << fullJavaName()
219 << " "
220 << fieldName
221 << " = new "
222 << fullJavaName()
223 << "();\n";
224}
225
226void CompoundType::emitJavaFieldReaderWriter(
227 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700228 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700229 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700230 const std::string &blobName,
231 const std::string &fieldName,
232 const std::string &offset,
233 bool isReader) const {
234 if (isReader) {
235 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700236 << ".readEmbeddedFromParcel("
237 << parcelName
238 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700239 << blobName
240 << ", "
241 << offset
242 << ");\n";
243
244 return;
245 }
246
247 out << fieldName
248 << ".writeEmbeddedToBlob("
249 << blobName
250 << ", "
251 << offset
252 << ");\n";
253}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700254void CompoundType::emitResolveReferences(
255 Formatter &out,
256 const std::string &name,
257 bool nameIsPointer,
258 const std::string &parcelObj,
259 bool parcelObjIsPointer,
260 bool isReader,
261 ErrorMode mode) const {
262 emitResolveReferencesEmbedded(
263 out,
264 0 /* depth */,
265 name,
266 name /* sanitizedName */,
267 nameIsPointer,
268 parcelObj,
269 parcelObjIsPointer,
270 isReader,
271 mode,
272 "_hidl_" + name + "_parent",
273 "0 /* parentOffset */");
274}
275
276void CompoundType::emitResolveReferencesEmbedded(
277 Formatter &out,
278 size_t /* depth */,
279 const std::string &name,
280 const std::string &/* sanitizedName */,
281 bool nameIsPointer,
282 const std::string &parcelObj,
283 bool parcelObjIsPointer,
284 bool isReader,
285 ErrorMode mode,
286 const std::string &parentName,
287 const std::string &offsetText) const {
288 CHECK(needsResolveReferences());
289
290 const std::string parcelObjDeref =
291 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
292
293 const std::string parcelObjPointer =
294 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
295
296 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
297 const std::string namePointer = nameIsPointer ? name : ("&" + name);
298
299 out << "_hidl_err = ";
300
301 if (isReader) {
302 out << "const_cast<"
303 << fullName()
304 << " *"
305 << ">("
306 << namePointer
307 << ")->readEmbeddedReferenceFromParcel(\n";
308 } else {
309 out << nameDeref
310 << "writeEmbeddedReferenceToParcel(\n";
311 }
312
313 out.indent();
314 out.indent();
315
316 out << (isReader ? parcelObjDeref : parcelObjPointer);
317 out << ",\n"
318 << parentName
319 << ",\n"
320 << offsetText;
321
322 out << ");\n\n";
323
324 out.unindent();
325 out.unindent();
326
327 handleError(out, mode);
328}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700329
Andreas Huber881227d2016-08-02 14:20:21 -0700330status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
331 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
332 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700333 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700334 << " {\n";
335
336 out.indent();
337
338 Scope::emitTypeDeclarations(out);
339
340 for (const auto &field : *mFields) {
341 std::string extra;
342 out << field->type().getCppType(&extra)
343 << " "
344 << field->name()
345 << extra
346 << ";\n";
347 }
348
349 if (needsEmbeddedReadWrite()) {
350 out << "\n::android::status_t readEmbeddedFromParcel(\n";
351
352 out.indent();
353 out.indent();
354
Andreas Huber8a82ff72016-08-04 10:29:39 -0700355 out << "const ::android::hardware::Parcel &parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700356 << "size_t parentHandle,\n"
357 << "size_t parentOffset);\n\n";
358
359 out.unindent();
360 out.unindent();
361
362 out << "::android::status_t writeEmbeddedToParcel(\n";
363
364 out.indent();
365 out.indent();
366
Andreas Huber8a82ff72016-08-04 10:29:39 -0700367 out << "::android::hardware::Parcel *parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700368 << "size_t parentHandle,\n"
369 << "size_t parentOffset) const;\n";
370
371 out.unindent();
372 out.unindent();
373 }
374
Yifan Hongbf459bc2016-08-23 16:50:37 -0700375 if(needsResolveReferences()) {
376 out << "\n";
377 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
378 out.indent(); out.indent();
379 out << "const ::android::hardware::Parcel &parcel,\n"
380 << "size_t parentHandle, size_t parentOffset);\n";
381 out.unindent(); out.unindent();
382 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
383 out.indent(); out.indent();
384 out << "::android::hardware::Parcel *,\n"
385 << "size_t parentHandle, size_t parentOffset) const;\n";
386 out.unindent(); out.unindent();
387 }
388
Andreas Huber881227d2016-08-02 14:20:21 -0700389 out.unindent();
390 out << "};\n\n";
391
392 return OK;
393}
394
395status_t CompoundType::emitTypeDefinitions(
396 Formatter &out, const std::string prefix) const {
Andreas Huber0e00de42016-08-03 09:56:02 -0700397 status_t err = Scope::emitTypeDefinitions(out, prefix + "::" + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700398
399 if (err != OK) {
400 return err;
401 }
402
Yifan Hongbf459bc2016-08-23 16:50:37 -0700403 if (needsEmbeddedReadWrite()) {
404 emitStructReaderWriter(out, prefix, true /* isReader */);
405 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -0700406 }
407
Yifan Hongbf459bc2016-08-23 16:50:37 -0700408 if (needsResolveReferences()) {
409 emitResolveReferenceDef(out, prefix, true /* isReader */);
410 emitResolveReferenceDef(out, prefix, false /* isReader */);
411 }
Andreas Huber881227d2016-08-02 14:20:21 -0700412
413 return OK;
414}
415
Andreas Huber85eabdb2016-08-25 11:24:49 -0700416status_t CompoundType::emitJavaTypeDeclarations(
417 Formatter &out, bool atTopLevel) const {
418 out << "public final ";
419
420 if (!atTopLevel) {
421 out << "static ";
422 }
423
424 out << "class "
425 << localName()
426 << " {\n";
427
428 out.indent();
429
430 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
431
432 for (const auto &field : *mFields) {
433 const bool isScope = field->type().isScope(); // really isStruct...
434
435 out << "public ";
436
437 field->type().emitJavaFieldInitializer(out, field->name());
438 }
439
440 if (!mFields->empty()) {
441 out << "\n";
442 }
443
444 out << "public final void readFromParcel(HwParcel parcel) {\n";
445 out.indent();
446 out << "HwBlob blob = parcel.readBuffer();\n";
447 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
448 out.unindent();
449 out << "}\n\n";
450
Andreas Huberf630bc82016-09-09 14:52:25 -0700451 ////////////////////////////////////////////////////////////////////////////
452
453 out << "public static final "
454 << localName()
Andreas Huberf630bc82016-09-09 14:52:25 -0700455 << "[] readVectorFromParcel(HwParcel parcel) {\n";
456 out.indent();
457
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700458 out << "ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700459 << localName()
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700460 << "> _hidl_vec = new ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700461
462 out << "HwBlob _hidl_blob = parcel.readBuffer();\n\n";
463
464 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700465 out,
466 0 /* depth */,
467 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700468 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700469 "_hidl_blob",
470 "_hidl_vec",
471 "0",
472 true /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700473
474 out << "\nreturn _hidl_vec.toArray(new "
475 << localName()
476 << "[_hidl_vec.size()]);\n";
477
478 out.unindent();
479 out << "}\n\n";
480
481 ////////////////////////////////////////////////////////////////////////////
482
Andreas Huber85eabdb2016-08-25 11:24:49 -0700483 out << "public final void readEmbeddedFromParcel(\n";
484 out.indent();
485 out.indent();
486 out << "HwParcel parcel, HwBlob _hidl_blob, long _hidl_offset) {\n";
487 out.unindent();
488
489 size_t offset = 0;
490 for (const auto &field : *mFields) {
491 size_t fieldAlign, fieldSize;
492 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
493
494 size_t pad = offset % fieldAlign;
495 if (pad > 0) {
496 offset += fieldAlign - pad;
497 }
498
499 field->type().emitJavaFieldReaderWriter(
500 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700501 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700502 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700503 "_hidl_blob",
504 field->name(),
505 "_hidl_offset + " + std::to_string(offset),
506 true /* isReader */);
507
508 offset += fieldSize;
509 }
510
511 out.unindent();
512 out << "}\n\n";
513
Andreas Huberf630bc82016-09-09 14:52:25 -0700514 ////////////////////////////////////////////////////////////////////////////
515
Andreas Huber709b62d2016-09-19 11:21:18 -0700516 size_t structAlign, structSize;
517 getAlignmentAndSize(&structAlign, &structSize);
518
Andreas Huber85eabdb2016-08-25 11:24:49 -0700519 out << "public final void writeToParcel(HwParcel parcel) {\n";
520 out.indent();
521
Andreas Huber85eabdb2016-08-25 11:24:49 -0700522 out << "HwBlob _hidl_blob = new HwBlob("
523 << structSize
524 << " /* size */);\n";
525
526 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
527 << "parcel.writeBuffer(_hidl_blob);\n";
528
529 out.unindent();
530 out << "}\n\n";
531
Andreas Huberf630bc82016-09-09 14:52:25 -0700532 ////////////////////////////////////////////////////////////////////////////
533
Andreas Huberf630bc82016-09-09 14:52:25 -0700534 out << "public static final void writeVectorToParcel(\n";
535 out.indent();
536 out.indent();
537 out << "HwParcel parcel, "
538 << localName()
539 << "[] _hidl_array) {\n";
540 out.unindent();
541
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700542 out << "ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700543 << localName()
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700544 << "> _hidl_vec = new ArrayList(Arrays.asList(_hidl_array));\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700545
546 out << "HwBlob _hidl_blob = new HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
547
548 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700549 out,
550 0 /* depth */,
551 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700552 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700553 "_hidl_blob",
554 "_hidl_vec",
555 "0",
556 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700557
558 out << "\nparcel.writeBuffer(_hidl_blob);\n";
559
560 out.unindent();
561 out << "}\n\n";
562
563 ////////////////////////////////////////////////////////////////////////////
564
Andreas Huber85eabdb2016-08-25 11:24:49 -0700565 out << "public final void writeEmbeddedToBlob(\n";
566 out.indent();
567 out.indent();
568 out << "HwBlob _hidl_blob, long _hidl_offset) {\n";
569 out.unindent();
570
571 offset = 0;
572 for (const auto &field : *mFields) {
573 size_t fieldAlign, fieldSize;
574 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
575
576 size_t pad = offset % fieldAlign;
577 if (pad > 0) {
578 offset += fieldAlign - pad;
579 }
580
581 field->type().emitJavaFieldReaderWriter(
582 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700583 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700584 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700585 "_hidl_blob",
586 field->name(),
587 "_hidl_offset + " + std::to_string(offset),
588 false /* isReader */);
589
590 offset += fieldSize;
591 }
592
593 out.unindent();
594 out << "}\n";
595
596 out.unindent();
597 out << "};\n\n";
598
599 return OK;
600}
601
Andreas Huber881227d2016-08-02 14:20:21 -0700602void CompoundType::emitStructReaderWriter(
603 Formatter &out, const std::string &prefix, bool isReader) const {
604 out << "::android::status_t "
605 << (prefix.empty() ? "" : (prefix + "::"))
Andreas Huber0e00de42016-08-03 09:56:02 -0700606 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700607 << (isReader ? "::readEmbeddedFromParcel"
608 : "::writeEmbeddedToParcel")
609 << "(\n";
610
611 out.indent();
612 out.indent();
613
614 if (isReader) {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700615 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700616 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700617 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700618 }
619
620 out << "size_t parentHandle,\n"
621 << "size_t parentOffset)";
622
623 if (!isReader) {
624 out << " const";
625 }
626
627 out << " {\n";
628
629 out.unindent();
630 out.unindent();
631 out.indent();
632
Iliyan Malchev549e2592016-08-10 08:59:12 -0700633 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700634
635 for (const auto &field : *mFields) {
636 if (!field->type().needsEmbeddedReadWrite()) {
637 continue;
638 }
639
640 field->type().emitReaderWriterEmbedded(
641 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700642 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700643 field->name(),
Yifan Hongbe2a3732016-10-05 13:33:41 -0700644 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700645 false /* nameIsPointer */,
646 "parcel",
647 !isReader /* parcelObjIsPointer */,
648 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700649 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700650 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700651 "parentOffset + offsetof("
652 + fullName()
653 + ", "
654 + field->name()
655 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700656 }
657
658 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700659 out << "_hidl_error:\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700660 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700661 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700662
663 out.unindent();
664 out << "}\n\n";
665}
666
Yifan Hongbf459bc2016-08-23 16:50:37 -0700667void CompoundType::emitResolveReferenceDef(
668 Formatter &out, const std::string prefix, bool isReader) const {
669 out << "::android::status_t "
670 << (prefix.empty() ? "" : (prefix + "::"))
671 << localName();
672
Yifan Hong00f47172016-09-30 14:40:45 -0700673
674 bool useParent = false;
675 for (const auto &field : *mFields) {
676 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
677 useParent = true;
678 break;
679 }
680 }
681
682 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
683 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
684
Yifan Hongbf459bc2016-08-23 16:50:37 -0700685 if (isReader) {
686 out << "::readEmbeddedReferenceFromParcel(\n";
687 out.indent(); out.indent();
688 out << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700689 << "size_t " << parentHandleName << ", "
690 << "size_t " << parentOffsetName << ")\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700691 out.unindent(); out.unindent();
692 } else {
693 out << "::writeEmbeddedReferenceToParcel(\n";
694 out.indent(); out.indent();
695 out << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700696 << "size_t " << parentHandleName << ", "
697 << "size_t " << parentOffsetName << ") const\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700698 out.unindent(); out.unindent();
699 }
700
701 out << " {\n";
702
703 out.indent();
704
705 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
706
Yifan Hong00f47172016-09-30 14:40:45 -0700707 // if not useParent, then parentName and offsetText
708 // should not be used at all, then the #error should not be emitted.
709 std::string error = useParent ? "" : "\n#error\n";
710
Yifan Hongbf459bc2016-08-23 16:50:37 -0700711 for (const auto &field : *mFields) {
712 if (!field->type().needsResolveReferences()) {
713 continue;
714 }
715
716 field->type().emitResolveReferencesEmbedded(
717 out,
718 0 /* depth */,
719 field->name(),
720 field->name() /* sanitizedName */,
721 false, // nameIsPointer
722 "parcel", // const std::string &parcelObj,
723 !isReader, // bool parcelObjIsPointer,
724 isReader, // bool isReader,
725 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -0700726 parentHandleName + error,
727 parentOffsetName
728 + " + offsetof("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700729 + fullName()
730 + ", "
731 + field->name()
Yifan Hong00f47172016-09-30 14:40:45 -0700732 + ")"
733 + error);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700734 }
735
736 out.unindent();
737 out << "_hidl_error:\n";
738 out.indent();
739 out << "return _hidl_err;\n";
740
741 out.unindent();
742 out << "}\n\n";
743}
744
Andreas Huber881227d2016-08-02 14:20:21 -0700745bool CompoundType::needsEmbeddedReadWrite() const {
746 if (mStyle != STYLE_STRUCT) {
747 return false;
748 }
749
750 for (const auto &field : *mFields) {
751 if (field->type().needsEmbeddedReadWrite()) {
752 return true;
753 }
754 }
755
756 return false;
757}
758
Yifan Hongbf459bc2016-08-23 16:50:37 -0700759bool CompoundType::needsResolveReferences() const {
760 if (mStyle != STYLE_STRUCT) {
761 return false;
762 }
763
764 for (const auto &field : *mFields) {
765 if (field->type().needsResolveReferences()) {
766 return true;
767 }
768 }
769
770 return false;
771}
772
Andreas Huber881227d2016-08-02 14:20:21 -0700773bool CompoundType::resultNeedsDeref() const {
774 return true;
775}
776
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700777status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
778 out << "name: \"" << localName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700779 out << "type: " << getVtsType() << "\n";
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 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700786 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700787 break;
788 }
789 case STYLE_UNION:
790 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700791 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700792 break;
793 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700794 }
795 out.indent();
796 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700797 if (status != OK) {
798 return status;
799 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700800 out.unindent();
801 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700802 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700803
804 // Emit declaration for each field.
805 for (const auto &field : *mFields) {
806 switch (mStyle) {
807 case STYLE_STRUCT:
808 {
809 out << "struct_value: {\n";
810 break;
811 }
812 case STYLE_UNION:
813 {
814 out << "union_value: {\n";
815 break;
816 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700817 }
818 out.indent();
819 out << "name: \"" << field->name() << "\"\n";
820 status_t status = field->type().emitVtsAttributeType(out);
821 if (status != OK) {
822 return status;
823 }
824 out.unindent();
825 out << "}\n";
826 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700827
828 return OK;
829}
830
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700831status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700832 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700833 out << "predefined_type: \"" << localName() << "\"\n";
834 return OK;
835}
836
Andreas Huber70a59e12016-08-16 12:57:01 -0700837bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700838 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
839 return false;
840 }
841
842 for (const auto &field : *mFields) {
843 if (!field->type().isJavaCompatible()) {
844 return false;
845 }
846 }
847
848 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -0700849}
850
851void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
852 *align = 1;
853
854 size_t offset = 0;
855 for (const auto &field : *mFields) {
856 // Each field is aligned according to its alignment requirement.
857 // The surrounding structure's alignment is the maximum of its
858 // fields' aligments.
859
860 size_t fieldAlign, fieldSize;
861 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
862
863 size_t pad = offset % fieldAlign;
864 if (pad > 0) {
865 offset += fieldAlign - pad;
866 }
867
868 offset += fieldSize;
869
870 if (fieldAlign > (*align)) {
871 *align = fieldAlign;
872 }
873 }
874
875 // Final padding to account for the structure's alignment.
876 size_t pad = offset % (*align);
877 if (pad > 0) {
878 offset += (*align) - pad;
879 }
880
881 *size = offset;
Andreas Huber70a59e12016-08-16 12:57:01 -0700882}
883
Andreas Huber31629bc2016-08-03 09:06:40 -0700884////////////////////////////////////////////////////////////////////////////////
885
886CompoundField::CompoundField(const char *name, Type *type)
887 : mName(name),
888 mType(type) {
889}
890
891std::string CompoundField::name() const {
892 return mName;
893}
894
895const Type &CompoundField::type() const {
896 return *mType;
897}
898
Andreas Huberc9410c72016-07-28 12:18:40 -0700899} // namespace android
900