blob: a262e175422d63b3a8bb6beadf4961940caa8a56 [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
Yifan Honga4b53d02016-10-31 17:29:10 -070025CompoundType::CompoundType(Style style, const char *localName, const Location &location)
26 : Scope(localName, location),
Andreas Huber9ed827c2016-08-22 12:31:13 -070027 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 Huber86a112b2016-10-19 14:25:16 -070038 if (type.isBinder()
39 || (type.isVector()
40 && static_cast<const VectorType *>(
41 &type)->isVectorOfBinders())) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -070042 *errorMsg =
43 "Structs/Unions must not contain references to interfaces.";
Andreas Huberb95ea8a2016-08-15 15:35:42 -070044
45 return false;
46 }
47
Andreas Huber5a545442016-08-03 10:44:56 -070048 if (mStyle == STYLE_UNION) {
49 if (type.needsEmbeddedReadWrite()) {
50 // Can't have those in a union.
51
Andreas Huber0d0f9a22016-08-17 10:26:11 -070052 *errorMsg =
53 "Unions must not contain any types that need fixup.";
Andreas Huber5a545442016-08-03 10:44:56 -070054
55 return false;
56 }
Andreas Huber5a545442016-08-03 10:44:56 -070057 }
58 }
59
60 return true;
Andreas Huberc9410c72016-07-28 12:18:40 -070061}
62
Andreas Huberf630bc82016-09-09 14:52:25 -070063bool CompoundType::isCompoundType() const {
64 return true;
65}
66
Andreas Huber881227d2016-08-02 14:20:21 -070067std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -070068 StorageMode mode,
69 std::string *extra,
70 bool specifyNamespaces) const {
71
Andreas Huber881227d2016-08-02 14:20:21 -070072 extra->clear();
Steven Moreland979e0992016-09-07 09:18:08 -070073 const std::string base =
74 specifyNamespaces ? fullName() : partialCppName();
Andreas Huber881227d2016-08-02 14:20:21 -070075
76 switch (mode) {
77 case StorageMode_Stack:
78 return base;
79
80 case StorageMode_Argument:
81 return "const " + base + "&";
82
83 case StorageMode_Result:
84 return "const " + base + "*";
85 }
86}
87
Andreas Huber4c865b72016-09-14 15:26:27 -070088std::string CompoundType::getJavaType(
89 std::string *extra, bool /* forInitializer */) const {
90 extra->clear();
Andreas Huber85eabdb2016-08-25 11:24:49 -070091 return fullJavaName();
92}
93
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -070094std::string CompoundType::getVtsType() const {
95 switch (mStyle) {
96 case STYLE_STRUCT:
97 {
98 return "TYPE_STRUCT";
99 }
100 case STYLE_UNION:
101 {
102 return "TYPE_UNION";
103 }
104 }
105}
106
Andreas Huber881227d2016-08-02 14:20:21 -0700107void CompoundType::emitReaderWriter(
108 Formatter &out,
109 const std::string &name,
110 const std::string &parcelObj,
111 bool parcelObjIsPointer,
112 bool isReader,
113 ErrorMode mode) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700114 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700115
116 out << "size_t " << parentName << ";\n\n";
117
118 const std::string parcelObjDeref =
119 parcelObj + (parcelObjIsPointer ? "->" : ".");
120
121 if (isReader) {
122 out << name
123 << " = (const "
Andreas Huber0e00de42016-08-03 09:56:02 -0700124 << fullName()
Andreas Huber881227d2016-08-02 14:20:21 -0700125 << " *)"
126 << parcelObjDeref
127 << "readBuffer("
128 << "&"
129 << parentName
130 << ");\n";
131
132 out << "if ("
133 << name
134 << " == nullptr) {\n";
135
Yifan Hong0a68a282016-10-21 16:32:34 -0700136 out.indentBlock([&]{
137 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
138 handleError2(out, mode);
139 });
Andreas Huber881227d2016-08-02 14:20:21 -0700140
Andreas Huber881227d2016-08-02 14:20:21 -0700141 out << "}\n\n";
142 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700143 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700144 << parcelObjDeref
145 << "writeBuffer(&"
146 << name
147 << ", sizeof("
148 << name
149 << "), &"
150 << parentName
151 << ");\n";
152
153 handleError(out, mode);
154 }
155
156 if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
157 return;
158 }
159
160 emitReaderWriterEmbedded(
161 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700162 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700163 name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700164 name, /* sanitizedName */
Andreas Huber881227d2016-08-02 14:20:21 -0700165 isReader /* nameIsPointer */,
166 parcelObj,
167 parcelObjIsPointer,
168 isReader,
169 mode,
170 parentName,
171 "0 /* parentOffset */");
172}
173
174void CompoundType::emitReaderWriterEmbedded(
175 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700176 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700177 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700178 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700179 bool nameIsPointer,
180 const std::string &parcelObj,
181 bool parcelObjIsPointer,
182 bool isReader,
183 ErrorMode mode,
184 const std::string &parentName,
185 const std::string &offsetText) const {
186 emitReaderWriterEmbeddedForTypeName(
187 out,
188 name,
189 nameIsPointer,
190 parcelObj,
191 parcelObjIsPointer,
192 isReader,
193 mode,
194 parentName,
195 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700196 fullName(),
Andreas Huber881227d2016-08-02 14:20:21 -0700197 "" /* childName */);
198}
199
Andreas Huber85eabdb2016-08-25 11:24:49 -0700200void CompoundType::emitJavaReaderWriter(
201 Formatter &out,
202 const std::string &parcelObj,
203 const std::string &argName,
204 bool isReader) const {
205 if (isReader) {
206 out << "new " << fullJavaName() << "();\n";
207 }
208
209 out << argName
210 << "."
211 << (isReader ? "readFromParcel" : "writeToParcel")
212 << "("
213 << parcelObj
214 << ");\n";
215}
216
217void CompoundType::emitJavaFieldInitializer(
218 Formatter &out, const std::string &fieldName) const {
219 out << "final "
220 << fullJavaName()
221 << " "
222 << fieldName
223 << " = new "
224 << fullJavaName()
225 << "();\n";
226}
227
228void CompoundType::emitJavaFieldReaderWriter(
229 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700230 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700231 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700232 const std::string &blobName,
233 const std::string &fieldName,
234 const std::string &offset,
235 bool isReader) const {
236 if (isReader) {
237 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700238 << ".readEmbeddedFromParcel("
239 << parcelName
240 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700241 << blobName
242 << ", "
243 << offset
244 << ");\n";
245
246 return;
247 }
248
249 out << fieldName
250 << ".writeEmbeddedToBlob("
251 << blobName
252 << ", "
253 << offset
254 << ");\n";
255}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700256void CompoundType::emitResolveReferences(
257 Formatter &out,
258 const std::string &name,
259 bool nameIsPointer,
260 const std::string &parcelObj,
261 bool parcelObjIsPointer,
262 bool isReader,
263 ErrorMode mode) const {
264 emitResolveReferencesEmbedded(
265 out,
266 0 /* depth */,
267 name,
268 name /* sanitizedName */,
269 nameIsPointer,
270 parcelObj,
271 parcelObjIsPointer,
272 isReader,
273 mode,
274 "_hidl_" + name + "_parent",
275 "0 /* parentOffset */");
276}
277
278void CompoundType::emitResolveReferencesEmbedded(
279 Formatter &out,
280 size_t /* depth */,
281 const std::string &name,
282 const std::string &/* sanitizedName */,
283 bool nameIsPointer,
284 const std::string &parcelObj,
285 bool parcelObjIsPointer,
286 bool isReader,
287 ErrorMode mode,
288 const std::string &parentName,
289 const std::string &offsetText) const {
290 CHECK(needsResolveReferences());
291
292 const std::string parcelObjDeref =
293 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
294
295 const std::string parcelObjPointer =
296 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
297
298 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
299 const std::string namePointer = nameIsPointer ? name : ("&" + name);
300
301 out << "_hidl_err = ";
302
303 if (isReader) {
304 out << "const_cast<"
305 << fullName()
306 << " *"
307 << ">("
308 << namePointer
309 << ")->readEmbeddedReferenceFromParcel(\n";
310 } else {
311 out << nameDeref
312 << "writeEmbeddedReferenceToParcel(\n";
313 }
314
Yifan Hong0a68a282016-10-21 16:32:34 -0700315 out.indentBlock(2, [&]{
316 out << (isReader ? parcelObjDeref : parcelObjPointer)
317 << ",\n"
318 << parentName
319 << ",\n"
320 << offsetText
321 << ");\n\n";
322 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700323
324 handleError(out, mode);
325}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700326
Andreas Huber881227d2016-08-02 14:20:21 -0700327status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
328 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
329 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700330 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700331 << " {\n";
332
333 out.indent();
334
335 Scope::emitTypeDeclarations(out);
336
337 for (const auto &field : *mFields) {
338 std::string extra;
339 out << field->type().getCppType(&extra)
340 << " "
341 << field->name()
342 << extra
343 << ";\n";
344 }
345
346 if (needsEmbeddedReadWrite()) {
347 out << "\n::android::status_t readEmbeddedFromParcel(\n";
348
Yifan Hong0a68a282016-10-21 16:32:34 -0700349 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700350
Andreas Huber8a82ff72016-08-04 10:29:39 -0700351 out << "const ::android::hardware::Parcel &parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700352 << "size_t parentHandle,\n"
353 << "size_t parentOffset);\n\n";
354
Yifan Hong0a68a282016-10-21 16:32:34 -0700355 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700356
357 out << "::android::status_t writeEmbeddedToParcel(\n";
358
Yifan Hong0a68a282016-10-21 16:32:34 -0700359 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700360
Andreas Huber8a82ff72016-08-04 10:29:39 -0700361 out << "::android::hardware::Parcel *parcel,\n"
Andreas Huber881227d2016-08-02 14:20:21 -0700362 << "size_t parentHandle,\n"
363 << "size_t parentOffset) const;\n";
364
Yifan Hong0a68a282016-10-21 16:32:34 -0700365 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700366 }
367
Yifan Hongbf459bc2016-08-23 16:50:37 -0700368 if(needsResolveReferences()) {
369 out << "\n";
370 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700371 out.indent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700372 out << "const ::android::hardware::Parcel &parcel,\n"
373 << "size_t parentHandle, size_t parentOffset);\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700374 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700375 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700376 out.indent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700377 out << "::android::hardware::Parcel *,\n"
378 << "size_t parentHandle, size_t parentOffset) const;\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700379 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700380 }
381
Andreas Huber881227d2016-08-02 14:20:21 -0700382 out.unindent();
383 out << "};\n\n";
384
385 return OK;
386}
387
388status_t CompoundType::emitTypeDefinitions(
389 Formatter &out, const std::string prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -0700390 std::string space = prefix.empty() ? "" : (prefix + "::");
391 status_t err = Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700392
393 if (err != OK) {
394 return err;
395 }
396
Yifan Hongbf459bc2016-08-23 16:50:37 -0700397 if (needsEmbeddedReadWrite()) {
398 emitStructReaderWriter(out, prefix, true /* isReader */);
399 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -0700400 }
401
Yifan Hongbf459bc2016-08-23 16:50:37 -0700402 if (needsResolveReferences()) {
403 emitResolveReferenceDef(out, prefix, true /* isReader */);
404 emitResolveReferenceDef(out, prefix, false /* isReader */);
405 }
Andreas Huber881227d2016-08-02 14:20:21 -0700406
407 return OK;
408}
409
Andreas Huber85eabdb2016-08-25 11:24:49 -0700410status_t CompoundType::emitJavaTypeDeclarations(
411 Formatter &out, bool atTopLevel) const {
412 out << "public final ";
413
414 if (!atTopLevel) {
415 out << "static ";
416 }
417
418 out << "class "
419 << localName()
420 << " {\n";
421
422 out.indent();
423
424 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
425
426 for (const auto &field : *mFields) {
427 const bool isScope = field->type().isScope(); // really isStruct...
428
429 out << "public ";
430
431 field->type().emitJavaFieldInitializer(out, field->name());
432 }
433
434 if (!mFields->empty()) {
435 out << "\n";
436 }
437
438 out << "public final void readFromParcel(HwParcel parcel) {\n";
439 out.indent();
440 out << "HwBlob blob = parcel.readBuffer();\n";
441 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
442 out.unindent();
443 out << "}\n\n";
444
Andreas Huberf630bc82016-09-09 14:52:25 -0700445 ////////////////////////////////////////////////////////////////////////////
446
Andreas Huber1b6822b2016-10-18 09:28:40 -0700447 out << "public static final ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700448 << localName()
Andreas Huber1b6822b2016-10-18 09:28:40 -0700449 << "> readVectorFromParcel(HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700450 out.indent();
451
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700452 out << "ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700453 << localName()
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700454 << "> _hidl_vec = new ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700455
456 out << "HwBlob _hidl_blob = parcel.readBuffer();\n\n";
457
458 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700459 out,
460 0 /* depth */,
461 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700462 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700463 "_hidl_blob",
464 "_hidl_vec",
465 "0",
466 true /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700467
Andreas Huber1b6822b2016-10-18 09:28:40 -0700468 out << "\nreturn _hidl_vec;\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700469
470 out.unindent();
471 out << "}\n\n";
472
473 ////////////////////////////////////////////////////////////////////////////
474
Andreas Huber85eabdb2016-08-25 11:24:49 -0700475 out << "public final void readEmbeddedFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700476 out.indent(2);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700477 out << "HwParcel parcel, HwBlob _hidl_blob, long _hidl_offset) {\n";
478 out.unindent();
479
480 size_t offset = 0;
481 for (const auto &field : *mFields) {
482 size_t fieldAlign, fieldSize;
483 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
484
485 size_t pad = offset % fieldAlign;
486 if (pad > 0) {
487 offset += fieldAlign - pad;
488 }
489
490 field->type().emitJavaFieldReaderWriter(
491 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700492 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700493 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700494 "_hidl_blob",
495 field->name(),
496 "_hidl_offset + " + std::to_string(offset),
497 true /* isReader */);
498
499 offset += fieldSize;
500 }
501
502 out.unindent();
503 out << "}\n\n";
504
Andreas Huberf630bc82016-09-09 14:52:25 -0700505 ////////////////////////////////////////////////////////////////////////////
506
Andreas Huber709b62d2016-09-19 11:21:18 -0700507 size_t structAlign, structSize;
508 getAlignmentAndSize(&structAlign, &structSize);
509
Andreas Huber85eabdb2016-08-25 11:24:49 -0700510 out << "public final void writeToParcel(HwParcel parcel) {\n";
511 out.indent();
512
Andreas Huber85eabdb2016-08-25 11:24:49 -0700513 out << "HwBlob _hidl_blob = new HwBlob("
514 << structSize
515 << " /* size */);\n";
516
517 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
518 << "parcel.writeBuffer(_hidl_blob);\n";
519
520 out.unindent();
521 out << "}\n\n";
522
Andreas Huberf630bc82016-09-09 14:52:25 -0700523 ////////////////////////////////////////////////////////////////////////////
524
Andreas Huberf630bc82016-09-09 14:52:25 -0700525 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700526 out.indent(2);
Andreas Huber1b6822b2016-10-18 09:28:40 -0700527 out << "HwParcel parcel, ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700528 << localName()
Andreas Huber1b6822b2016-10-18 09:28:40 -0700529 << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700530 out.unindent();
531
Andreas Huberf630bc82016-09-09 14:52:25 -0700532 out << "HwBlob _hidl_blob = new HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
533
534 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700535 out,
536 0 /* depth */,
537 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700538 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700539 "_hidl_blob",
540 "_hidl_vec",
541 "0",
542 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700543
544 out << "\nparcel.writeBuffer(_hidl_blob);\n";
545
546 out.unindent();
547 out << "}\n\n";
548
549 ////////////////////////////////////////////////////////////////////////////
550
Andreas Huber85eabdb2016-08-25 11:24:49 -0700551 out << "public final void writeEmbeddedToBlob(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700552 out.indent(2);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700553 out << "HwBlob _hidl_blob, long _hidl_offset) {\n";
554 out.unindent();
555
556 offset = 0;
557 for (const auto &field : *mFields) {
558 size_t fieldAlign, fieldSize;
559 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
560
561 size_t pad = offset % fieldAlign;
562 if (pad > 0) {
563 offset += fieldAlign - pad;
564 }
565
566 field->type().emitJavaFieldReaderWriter(
567 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700568 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700569 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700570 "_hidl_blob",
571 field->name(),
572 "_hidl_offset + " + std::to_string(offset),
573 false /* isReader */);
574
575 offset += fieldSize;
576 }
577
578 out.unindent();
579 out << "}\n";
580
581 out.unindent();
582 out << "};\n\n";
583
584 return OK;
585}
586
Andreas Huber881227d2016-08-02 14:20:21 -0700587void CompoundType::emitStructReaderWriter(
588 Formatter &out, const std::string &prefix, bool isReader) const {
589 out << "::android::status_t "
590 << (prefix.empty() ? "" : (prefix + "::"))
Andreas Huber0e00de42016-08-03 09:56:02 -0700591 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700592 << (isReader ? "::readEmbeddedFromParcel"
593 : "::writeEmbeddedToParcel")
594 << "(\n";
595
Yifan Hong0a68a282016-10-21 16:32:34 -0700596 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700597
598 if (isReader) {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700599 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700600 } else {
Andreas Huber8a82ff72016-08-04 10:29:39 -0700601 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700602 }
603
604 out << "size_t parentHandle,\n"
605 << "size_t parentOffset)";
606
607 if (!isReader) {
608 out << " const";
609 }
610
611 out << " {\n";
612
Yifan Hong0a68a282016-10-21 16:32:34 -0700613 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700614 out.indent();
615
Iliyan Malchev549e2592016-08-10 08:59:12 -0700616 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700617
618 for (const auto &field : *mFields) {
619 if (!field->type().needsEmbeddedReadWrite()) {
620 continue;
621 }
622
623 field->type().emitReaderWriterEmbedded(
624 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700625 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700626 field->name(),
Yifan Hongbe2a3732016-10-05 13:33:41 -0700627 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700628 false /* nameIsPointer */,
629 "parcel",
630 !isReader /* parcelObjIsPointer */,
631 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700632 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700633 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700634 "parentOffset + offsetof("
635 + fullName()
636 + ", "
637 + field->name()
638 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700639 }
640
641 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700642 out << "_hidl_error:\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700643 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700644 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700645
646 out.unindent();
647 out << "}\n\n";
648}
649
Yifan Hongbf459bc2016-08-23 16:50:37 -0700650void CompoundType::emitResolveReferenceDef(
651 Formatter &out, const std::string prefix, bool isReader) const {
652 out << "::android::status_t "
653 << (prefix.empty() ? "" : (prefix + "::"))
654 << localName();
655
Yifan Hong00f47172016-09-30 14:40:45 -0700656
657 bool useParent = false;
658 for (const auto &field : *mFields) {
659 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
660 useParent = true;
661 break;
662 }
663 }
664
665 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
666 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
667
Yifan Hongbf459bc2016-08-23 16:50:37 -0700668 if (isReader) {
669 out << "::readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700670 out.indent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700671 out << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700672 << "size_t " << parentHandleName << ", "
673 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700674 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700675 } else {
676 out << "::writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700677 out.indent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700678 out << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700679 << "size_t " << parentHandleName << ", "
680 << "size_t " << parentOffsetName << ") const\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700681 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700682 }
683
684 out << " {\n";
685
686 out.indent();
687
688 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
689
Yifan Hong00f47172016-09-30 14:40:45 -0700690 // if not useParent, then parentName and offsetText
691 // should not be used at all, then the #error should not be emitted.
692 std::string error = useParent ? "" : "\n#error\n";
693
Yifan Hongbf459bc2016-08-23 16:50:37 -0700694 for (const auto &field : *mFields) {
695 if (!field->type().needsResolveReferences()) {
696 continue;
697 }
698
699 field->type().emitResolveReferencesEmbedded(
700 out,
701 0 /* depth */,
702 field->name(),
703 field->name() /* sanitizedName */,
704 false, // nameIsPointer
705 "parcel", // const std::string &parcelObj,
706 !isReader, // bool parcelObjIsPointer,
707 isReader, // bool isReader,
708 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -0700709 parentHandleName + error,
710 parentOffsetName
711 + " + offsetof("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700712 + fullName()
713 + ", "
714 + field->name()
Yifan Hong00f47172016-09-30 14:40:45 -0700715 + ")"
716 + error);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700717 }
718
719 out.unindent();
720 out << "_hidl_error:\n";
721 out.indent();
722 out << "return _hidl_err;\n";
723
724 out.unindent();
725 out << "}\n\n";
726}
727
Andreas Huber881227d2016-08-02 14:20:21 -0700728bool CompoundType::needsEmbeddedReadWrite() const {
729 if (mStyle != STYLE_STRUCT) {
730 return false;
731 }
732
733 for (const auto &field : *mFields) {
734 if (field->type().needsEmbeddedReadWrite()) {
735 return true;
736 }
737 }
738
739 return false;
740}
741
Yifan Hongbf459bc2016-08-23 16:50:37 -0700742bool CompoundType::needsResolveReferences() const {
743 if (mStyle != STYLE_STRUCT) {
744 return false;
745 }
746
747 for (const auto &field : *mFields) {
748 if (field->type().needsResolveReferences()) {
749 return true;
750 }
751 }
752
753 return false;
754}
755
Andreas Huber881227d2016-08-02 14:20:21 -0700756bool CompoundType::resultNeedsDeref() const {
757 return true;
758}
759
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700760status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700761 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700762 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700763
764 // Emit declaration for each subtype.
765 for (const auto &type : getSubTypes()) {
766 switch (mStyle) {
767 case STYLE_STRUCT:
768 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700769 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700770 break;
771 }
772 case STYLE_UNION:
773 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700774 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700775 break;
776 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700777 }
778 out.indent();
779 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700780 if (status != OK) {
781 return status;
782 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700783 out.unindent();
784 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700785 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700786
787 // Emit declaration for each field.
788 for (const auto &field : *mFields) {
789 switch (mStyle) {
790 case STYLE_STRUCT:
791 {
792 out << "struct_value: {\n";
793 break;
794 }
795 case STYLE_UNION:
796 {
797 out << "union_value: {\n";
798 break;
799 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700800 }
801 out.indent();
802 out << "name: \"" << field->name() << "\"\n";
803 status_t status = field->type().emitVtsAttributeType(out);
804 if (status != OK) {
805 return status;
806 }
807 out.unindent();
808 out << "}\n";
809 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700810
811 return OK;
812}
813
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700814status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700815 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700816 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700817 return OK;
818}
819
Andreas Huber70a59e12016-08-16 12:57:01 -0700820bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700821 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
822 return false;
823 }
824
825 for (const auto &field : *mFields) {
826 if (!field->type().isJavaCompatible()) {
827 return false;
828 }
829 }
830
831 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -0700832}
833
834void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
835 *align = 1;
836
837 size_t offset = 0;
838 for (const auto &field : *mFields) {
839 // Each field is aligned according to its alignment requirement.
840 // The surrounding structure's alignment is the maximum of its
841 // fields' aligments.
842
843 size_t fieldAlign, fieldSize;
844 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
845
846 size_t pad = offset % fieldAlign;
847 if (pad > 0) {
848 offset += fieldAlign - pad;
849 }
850
851 offset += fieldSize;
852
853 if (fieldAlign > (*align)) {
854 *align = fieldAlign;
855 }
856 }
857
858 // Final padding to account for the structure's alignment.
859 size_t pad = offset % (*align);
860 if (pad > 0) {
861 offset += (*align) - pad;
862 }
863
864 *size = offset;
Andreas Huber70a59e12016-08-16 12:57:01 -0700865}
866
Andreas Huber31629bc2016-08-03 09:06:40 -0700867////////////////////////////////////////////////////////////////////////////////
868
869CompoundField::CompoundField(const char *name, Type *type)
870 : mName(name),
871 mType(type) {
872}
873
874std::string CompoundField::name() const {
875 return mName;
876}
877
878const Type &CompoundField::type() const {
879 return *mType;
880}
881
Andreas Huberc9410c72016-07-28 12:18:40 -0700882} // namespace android
883