blob: 71d17bff7db16d3c7a03d084c5f4a683a33b5e2e [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 {
Steven Morelandb158de12016-10-10 11:59:09 -0700397 std::string space = prefix.empty() ? "" : (prefix + "::");
398 status_t err = Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700399
400 if (err != OK) {
401 return err;
402 }
403
Yifan Hongbf459bc2016-08-23 16:50:37 -0700404 if (needsEmbeddedReadWrite()) {
405 emitStructReaderWriter(out, prefix, true /* isReader */);
406 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -0700407 }
408
Yifan Hongbf459bc2016-08-23 16:50:37 -0700409 if (needsResolveReferences()) {
410 emitResolveReferenceDef(out, prefix, true /* isReader */);
411 emitResolveReferenceDef(out, prefix, false /* isReader */);
412 }
Andreas Huber881227d2016-08-02 14:20:21 -0700413
414 return OK;
415}
416
Andreas Huber85eabdb2016-08-25 11:24:49 -0700417status_t CompoundType::emitJavaTypeDeclarations(
418 Formatter &out, bool atTopLevel) const {
419 out << "public final ";
420
421 if (!atTopLevel) {
422 out << "static ";
423 }
424
425 out << "class "
426 << localName()
427 << " {\n";
428
429 out.indent();
430
431 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
432
433 for (const auto &field : *mFields) {
434 const bool isScope = field->type().isScope(); // really isStruct...
435
436 out << "public ";
437
438 field->type().emitJavaFieldInitializer(out, field->name());
439 }
440
441 if (!mFields->empty()) {
442 out << "\n";
443 }
444
445 out << "public final void readFromParcel(HwParcel parcel) {\n";
446 out.indent();
447 out << "HwBlob blob = parcel.readBuffer();\n";
448 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
449 out.unindent();
450 out << "}\n\n";
451
Andreas Huberf630bc82016-09-09 14:52:25 -0700452 ////////////////////////////////////////////////////////////////////////////
453
454 out << "public static final "
455 << localName()
Andreas Huberf630bc82016-09-09 14:52:25 -0700456 << "[] readVectorFromParcel(HwParcel parcel) {\n";
457 out.indent();
458
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700459 out << "ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700460 << localName()
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700461 << "> _hidl_vec = new ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700462
463 out << "HwBlob _hidl_blob = parcel.readBuffer();\n\n";
464
465 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700466 out,
467 0 /* depth */,
468 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700469 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700470 "_hidl_blob",
471 "_hidl_vec",
472 "0",
473 true /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700474
475 out << "\nreturn _hidl_vec.toArray(new "
476 << localName()
477 << "[_hidl_vec.size()]);\n";
478
479 out.unindent();
480 out << "}\n\n";
481
482 ////////////////////////////////////////////////////////////////////////////
483
Andreas Huber85eabdb2016-08-25 11:24:49 -0700484 out << "public final void readEmbeddedFromParcel(\n";
485 out.indent();
486 out.indent();
487 out << "HwParcel parcel, HwBlob _hidl_blob, long _hidl_offset) {\n";
488 out.unindent();
489
490 size_t offset = 0;
491 for (const auto &field : *mFields) {
492 size_t fieldAlign, fieldSize;
493 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
494
495 size_t pad = offset % fieldAlign;
496 if (pad > 0) {
497 offset += fieldAlign - pad;
498 }
499
500 field->type().emitJavaFieldReaderWriter(
501 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700502 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700503 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700504 "_hidl_blob",
505 field->name(),
506 "_hidl_offset + " + std::to_string(offset),
507 true /* isReader */);
508
509 offset += fieldSize;
510 }
511
512 out.unindent();
513 out << "}\n\n";
514
Andreas Huberf630bc82016-09-09 14:52:25 -0700515 ////////////////////////////////////////////////////////////////////////////
516
Andreas Huber709b62d2016-09-19 11:21:18 -0700517 size_t structAlign, structSize;
518 getAlignmentAndSize(&structAlign, &structSize);
519
Andreas Huber85eabdb2016-08-25 11:24:49 -0700520 out << "public final void writeToParcel(HwParcel parcel) {\n";
521 out.indent();
522
Andreas Huber85eabdb2016-08-25 11:24:49 -0700523 out << "HwBlob _hidl_blob = new HwBlob("
524 << structSize
525 << " /* size */);\n";
526
527 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
528 << "parcel.writeBuffer(_hidl_blob);\n";
529
530 out.unindent();
531 out << "}\n\n";
532
Andreas Huberf630bc82016-09-09 14:52:25 -0700533 ////////////////////////////////////////////////////////////////////////////
534
Andreas Huberf630bc82016-09-09 14:52:25 -0700535 out << "public static final void writeVectorToParcel(\n";
536 out.indent();
537 out.indent();
538 out << "HwParcel parcel, "
539 << localName()
540 << "[] _hidl_array) {\n";
541 out.unindent();
542
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700543 out << "ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700544 << localName()
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700545 << "> _hidl_vec = new ArrayList(Arrays.asList(_hidl_array));\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700546
547 out << "HwBlob _hidl_blob = new HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
548
549 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700550 out,
551 0 /* depth */,
552 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700553 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700554 "_hidl_blob",
555 "_hidl_vec",
556 "0",
557 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700558
559 out << "\nparcel.writeBuffer(_hidl_blob);\n";
560
561 out.unindent();
562 out << "}\n\n";
563
564 ////////////////////////////////////////////////////////////////////////////
565
Andreas Huber85eabdb2016-08-25 11:24:49 -0700566 out << "public final void writeEmbeddedToBlob(\n";
567 out.indent();
568 out.indent();
569 out << "HwBlob _hidl_blob, long _hidl_offset) {\n";
570 out.unindent();
571
572 offset = 0;
573 for (const auto &field : *mFields) {
574 size_t fieldAlign, fieldSize;
575 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
576
577 size_t pad = offset % fieldAlign;
578 if (pad > 0) {
579 offset += fieldAlign - pad;
580 }
581
582 field->type().emitJavaFieldReaderWriter(
583 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700584 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700585 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700586 "_hidl_blob",
587 field->name(),
588 "_hidl_offset + " + std::to_string(offset),
589 false /* isReader */);
590
591 offset += fieldSize;
592 }
593
594 out.unindent();
595 out << "}\n";
596
597 out.unindent();
598 out << "};\n\n";
599
600 return OK;
601}
602
Andreas Huber881227d2016-08-02 14:20:21 -0700603void CompoundType::emitStructReaderWriter(
604 Formatter &out, const std::string &prefix, bool isReader) const {
605 out << "::android::status_t "
606 << (prefix.empty() ? "" : (prefix + "::"))
Andreas Huber0e00de42016-08-03 09:56:02 -0700607 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700608 << (isReader ? "::readEmbeddedFromParcel"
609 : "::writeEmbeddedToParcel")
610 << "(\n";
611
612 out.indent();
613 out.indent();
614
615 if (isReader) {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700616 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700617 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700618 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700619 }
620
621 out << "size_t parentHandle,\n"
622 << "size_t parentOffset)";
623
624 if (!isReader) {
625 out << " const";
626 }
627
628 out << " {\n";
629
630 out.unindent();
631 out.unindent();
632 out.indent();
633
Iliyan Malchev549e2592016-08-10 08:59:12 -0700634 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700635
636 for (const auto &field : *mFields) {
637 if (!field->type().needsEmbeddedReadWrite()) {
638 continue;
639 }
640
641 field->type().emitReaderWriterEmbedded(
642 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700643 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700644 field->name(),
Yifan Hongbe2a3732016-10-05 13:33:41 -0700645 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700646 false /* nameIsPointer */,
647 "parcel",
648 !isReader /* parcelObjIsPointer */,
649 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700650 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700651 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700652 "parentOffset + offsetof("
653 + fullName()
654 + ", "
655 + field->name()
656 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700657 }
658
659 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700660 out << "_hidl_error:\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700661 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700662 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700663
664 out.unindent();
665 out << "}\n\n";
666}
667
Yifan Hongbf459bc2016-08-23 16:50:37 -0700668void CompoundType::emitResolveReferenceDef(
669 Formatter &out, const std::string prefix, bool isReader) const {
670 out << "::android::status_t "
671 << (prefix.empty() ? "" : (prefix + "::"))
672 << localName();
673
Yifan Hong00f47172016-09-30 14:40:45 -0700674
675 bool useParent = false;
676 for (const auto &field : *mFields) {
677 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
678 useParent = true;
679 break;
680 }
681 }
682
683 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
684 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
685
Yifan Hongbf459bc2016-08-23 16:50:37 -0700686 if (isReader) {
687 out << "::readEmbeddedReferenceFromParcel(\n";
688 out.indent(); out.indent();
689 out << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700690 << "size_t " << parentHandleName << ", "
691 << "size_t " << parentOffsetName << ")\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700692 out.unindent(); out.unindent();
693 } else {
694 out << "::writeEmbeddedReferenceToParcel(\n";
695 out.indent(); out.indent();
696 out << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700697 << "size_t " << parentHandleName << ", "
698 << "size_t " << parentOffsetName << ") const\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700699 out.unindent(); out.unindent();
700 }
701
702 out << " {\n";
703
704 out.indent();
705
706 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
707
Yifan Hong00f47172016-09-30 14:40:45 -0700708 // if not useParent, then parentName and offsetText
709 // should not be used at all, then the #error should not be emitted.
710 std::string error = useParent ? "" : "\n#error\n";
711
Yifan Hongbf459bc2016-08-23 16:50:37 -0700712 for (const auto &field : *mFields) {
713 if (!field->type().needsResolveReferences()) {
714 continue;
715 }
716
717 field->type().emitResolveReferencesEmbedded(
718 out,
719 0 /* depth */,
720 field->name(),
721 field->name() /* sanitizedName */,
722 false, // nameIsPointer
723 "parcel", // const std::string &parcelObj,
724 !isReader, // bool parcelObjIsPointer,
725 isReader, // bool isReader,
726 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -0700727 parentHandleName + error,
728 parentOffsetName
729 + " + offsetof("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700730 + fullName()
731 + ", "
732 + field->name()
Yifan Hong00f47172016-09-30 14:40:45 -0700733 + ")"
734 + error);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700735 }
736
737 out.unindent();
738 out << "_hidl_error:\n";
739 out.indent();
740 out << "return _hidl_err;\n";
741
742 out.unindent();
743 out << "}\n\n";
744}
745
Andreas Huber881227d2016-08-02 14:20:21 -0700746bool CompoundType::needsEmbeddedReadWrite() const {
747 if (mStyle != STYLE_STRUCT) {
748 return false;
749 }
750
751 for (const auto &field : *mFields) {
752 if (field->type().needsEmbeddedReadWrite()) {
753 return true;
754 }
755 }
756
757 return false;
758}
759
Yifan Hongbf459bc2016-08-23 16:50:37 -0700760bool CompoundType::needsResolveReferences() const {
761 if (mStyle != STYLE_STRUCT) {
762 return false;
763 }
764
765 for (const auto &field : *mFields) {
766 if (field->type().needsResolveReferences()) {
767 return true;
768 }
769 }
770
771 return false;
772}
773
Andreas Huber881227d2016-08-02 14:20:21 -0700774bool CompoundType::resultNeedsDeref() const {
775 return true;
776}
777
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700778status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
779 out << "name: \"" << localName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700780 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700781
782 // Emit declaration for each subtype.
783 for (const auto &type : getSubTypes()) {
784 switch (mStyle) {
785 case STYLE_STRUCT:
786 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700787 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700788 break;
789 }
790 case STYLE_UNION:
791 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700792 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700793 break;
794 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700795 }
796 out.indent();
797 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700798 if (status != OK) {
799 return status;
800 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700801 out.unindent();
802 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700803 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700804
805 // Emit declaration for each field.
806 for (const auto &field : *mFields) {
807 switch (mStyle) {
808 case STYLE_STRUCT:
809 {
810 out << "struct_value: {\n";
811 break;
812 }
813 case STYLE_UNION:
814 {
815 out << "union_value: {\n";
816 break;
817 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700818 }
819 out.indent();
820 out << "name: \"" << field->name() << "\"\n";
821 status_t status = field->type().emitVtsAttributeType(out);
822 if (status != OK) {
823 return status;
824 }
825 out.unindent();
826 out << "}\n";
827 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700828
829 return OK;
830}
831
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700832status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700833 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700834 out << "predefined_type: \"" << localName() << "\"\n";
835 return OK;
836}
837
Andreas Huber70a59e12016-08-16 12:57:01 -0700838bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700839 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
840 return false;
841 }
842
843 for (const auto &field : *mFields) {
844 if (!field->type().isJavaCompatible()) {
845 return false;
846 }
847 }
848
849 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -0700850}
851
852void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
853 *align = 1;
854
855 size_t offset = 0;
856 for (const auto &field : *mFields) {
857 // Each field is aligned according to its alignment requirement.
858 // The surrounding structure's alignment is the maximum of its
859 // fields' aligments.
860
861 size_t fieldAlign, fieldSize;
862 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
863
864 size_t pad = offset % fieldAlign;
865 if (pad > 0) {
866 offset += fieldAlign - pad;
867 }
868
869 offset += fieldSize;
870
871 if (fieldAlign > (*align)) {
872 *align = fieldAlign;
873 }
874 }
875
876 // Final padding to account for the structure's alignment.
877 size_t pad = offset % (*align);
878 if (pad > 0) {
879 offset += (*align) - pad;
880 }
881
882 *size = offset;
Andreas Huber70a59e12016-08-16 12:57:01 -0700883}
884
Andreas Huber31629bc2016-08-03 09:06:40 -0700885////////////////////////////////////////////////////////////////////////////////
886
887CompoundField::CompoundField(const char *name, Type *type)
888 : mName(name),
889 mType(type) {
890}
891
892std::string CompoundField::name() const {
893 return mName;
894}
895
896const Type &CompoundField::type() const {
897 return *mType;
898}
899
Andreas Huberc9410c72016-07-28 12:18:40 -0700900} // namespace android
901