blob: b00f114ad686858e6e797a07f469590550edfb8f [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
Yifan Hong27e85db2016-11-09 15:45:52 -080031CompoundType::Style CompoundType::style() const {
32 return mStyle;
33}
34
Andreas Huber0d0f9a22016-08-17 10:26:11 -070035bool CompoundType::setFields(
36 std::vector<CompoundField *> *fields, std::string *errorMsg) {
Andreas Huberc9410c72016-07-28 12:18:40 -070037 mFields = fields;
Andreas Huber5a545442016-08-03 10:44:56 -070038
39 for (const auto &field : *fields) {
40 const Type &type = field->type();
41
Andreas Huber86a112b2016-10-19 14:25:16 -070042 if (type.isBinder()
43 || (type.isVector()
44 && static_cast<const VectorType *>(
45 &type)->isVectorOfBinders())) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -070046 *errorMsg =
47 "Structs/Unions must not contain references to interfaces.";
Andreas Huberb95ea8a2016-08-15 15:35:42 -070048
49 return false;
50 }
51
Andreas Huber5a545442016-08-03 10:44:56 -070052 if (mStyle == STYLE_UNION) {
53 if (type.needsEmbeddedReadWrite()) {
54 // Can't have those in a union.
55
Andreas Huber0d0f9a22016-08-17 10:26:11 -070056 *errorMsg =
57 "Unions must not contain any types that need fixup.";
Andreas Huber5a545442016-08-03 10:44:56 -070058
59 return false;
60 }
Andreas Huber5a545442016-08-03 10:44:56 -070061 }
62 }
63
64 return true;
Andreas Huberc9410c72016-07-28 12:18:40 -070065}
66
Andreas Huberf630bc82016-09-09 14:52:25 -070067bool CompoundType::isCompoundType() const {
68 return true;
69}
70
Andreas Huber881227d2016-08-02 14:20:21 -070071std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -070072 StorageMode mode,
Steven Moreland979e0992016-09-07 09:18:08 -070073 bool specifyNamespaces) const {
Steven Moreland979e0992016-09-07 09:18:08 -070074 const std::string base =
75 specifyNamespaces ? fullName() : partialCppName();
Andreas Huber881227d2016-08-02 14:20:21 -070076
77 switch (mode) {
Martijn Coenenac587892016-11-17 15:14:19 +010078 case StorageMode_Compound:
Andreas Huber881227d2016-08-02 14:20:21 -070079 case StorageMode_Stack:
80 return base;
81
82 case StorageMode_Argument:
83 return "const " + base + "&";
84
85 case StorageMode_Result:
86 return "const " + base + "*";
87 }
88}
89
Yifan Hong4ed13472016-11-02 10:44:11 -070090std::string CompoundType::getJavaType(bool /* forInitializer */) const {
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(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800197 "" /* childName */,
198 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700199}
200
Andreas Huber85eabdb2016-08-25 11:24:49 -0700201void CompoundType::emitJavaReaderWriter(
202 Formatter &out,
203 const std::string &parcelObj,
204 const std::string &argName,
205 bool isReader) const {
206 if (isReader) {
207 out << "new " << fullJavaName() << "();\n";
208 }
209
210 out << argName
211 << "."
212 << (isReader ? "readFromParcel" : "writeToParcel")
213 << "("
214 << parcelObj
215 << ");\n";
216}
217
218void CompoundType::emitJavaFieldInitializer(
219 Formatter &out, const std::string &fieldName) const {
220 out << "final "
221 << fullJavaName()
222 << " "
223 << fieldName
224 << " = new "
225 << fullJavaName()
226 << "();\n";
227}
228
229void CompoundType::emitJavaFieldReaderWriter(
230 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700231 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700232 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700233 const std::string &blobName,
234 const std::string &fieldName,
235 const std::string &offset,
236 bool isReader) const {
237 if (isReader) {
238 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700239 << ".readEmbeddedFromParcel("
240 << parcelName
241 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700242 << blobName
243 << ", "
244 << offset
245 << ");\n";
246
247 return;
248 }
249
250 out << fieldName
251 << ".writeEmbeddedToBlob("
252 << blobName
253 << ", "
254 << offset
255 << ");\n";
256}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700257void CompoundType::emitResolveReferences(
258 Formatter &out,
259 const std::string &name,
260 bool nameIsPointer,
261 const std::string &parcelObj,
262 bool parcelObjIsPointer,
263 bool isReader,
264 ErrorMode mode) const {
265 emitResolveReferencesEmbedded(
266 out,
267 0 /* depth */,
268 name,
269 name /* sanitizedName */,
270 nameIsPointer,
271 parcelObj,
272 parcelObjIsPointer,
273 isReader,
274 mode,
275 "_hidl_" + name + "_parent",
276 "0 /* parentOffset */");
277}
278
279void CompoundType::emitResolveReferencesEmbedded(
280 Formatter &out,
281 size_t /* depth */,
282 const std::string &name,
283 const std::string &/* sanitizedName */,
284 bool nameIsPointer,
285 const std::string &parcelObj,
286 bool parcelObjIsPointer,
287 bool isReader,
288 ErrorMode mode,
289 const std::string &parentName,
290 const std::string &offsetText) const {
291 CHECK(needsResolveReferences());
292
293 const std::string parcelObjDeref =
294 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
295
296 const std::string parcelObjPointer =
297 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
298
Yifan Hong244e82d2016-11-11 11:13:57 -0800299 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700300 const std::string namePointer = nameIsPointer ? name : ("&" + name);
301
302 out << "_hidl_err = ";
303
304 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800305 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700306 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800307 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700308 }
309
Yifan Hong0a68a282016-10-21 16:32:34 -0700310 out.indentBlock(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800311 if (isReader) {
312 out << "const_cast<"
313 << fullName()
314 << " *"
315 << ">("
316 << namePointer
317 << "),\n"
318 << parcelObjDeref;
319 } else {
320 out << nameDerefed
321 << ",\n"
322 << parcelObjPointer;
323 }
324
325 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700326 << parentName
327 << ",\n"
328 << offsetText
329 << ");\n\n";
330 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700331
332 handleError(out, mode);
333}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700334
Andreas Huber881227d2016-08-02 14:20:21 -0700335status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
336 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
337 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700338 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700339 << " {\n";
340
341 out.indent();
342
343 Scope::emitTypeDeclarations(out);
344
345 for (const auto &field : *mFields) {
Martijn Coenenac587892016-11-17 15:14:19 +0100346 out << field->type().getCppCompoundType()
Andreas Huber881227d2016-08-02 14:20:21 -0700347 << " "
348 << field->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700349 << ";\n";
350 }
351
Yifan Hong244e82d2016-11-11 11:13:57 -0800352 out.unindent();
353 out << "};\n\n";
354
355 return OK;
356}
357
358
359status_t CompoundType::emitGlobalHwDeclarations(Formatter &out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700360 if (needsEmbeddedReadWrite()) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800361 out << "::android::status_t readEmbeddedFromParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700362
Yifan Hong0a68a282016-10-21 16:32:34 -0700363 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700364
Yifan Hong244e82d2016-11-11 11:13:57 -0800365 out << fullName() << " *obj,\n"
366 << "const ::android::hardware::Parcel &parcel,\n"
367 << "size_t parentHandle,\n"
368 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700369
Yifan Hong0a68a282016-10-21 16:32:34 -0700370 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700371
372 out << "::android::status_t writeEmbeddedToParcel(\n";
373
Yifan Hong0a68a282016-10-21 16:32:34 -0700374 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700375
Yifan Hong244e82d2016-11-11 11:13:57 -0800376 out << "const " << fullName() << " &obj,\n"
377 << "::android::hardware::Parcel *parcel,\n"
378 << "size_t parentHandle,\n"
379 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700380
Yifan Hong0a68a282016-10-21 16:32:34 -0700381 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700382 }
383
Yifan Hongbf459bc2016-08-23 16:50:37 -0700384 if(needsResolveReferences()) {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700385 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700386 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800387 out << fullName() << " *obj,\n"
388 << "const ::android::hardware::Parcel &parcel,\n"
389 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700390 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700391 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700392 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800393 out << "const " << fullName() << " &obj,\n"
394 << "::android::hardware::Parcel *,\n"
395 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700396 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700397 }
398
Andreas Huber881227d2016-08-02 14:20:21 -0700399 return OK;
400}
401
402status_t CompoundType::emitTypeDefinitions(
403 Formatter &out, const std::string prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -0700404 std::string space = prefix.empty() ? "" : (prefix + "::");
405 status_t err = Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700406
407 if (err != OK) {
408 return err;
409 }
410
Yifan Hongbf459bc2016-08-23 16:50:37 -0700411 if (needsEmbeddedReadWrite()) {
412 emitStructReaderWriter(out, prefix, true /* isReader */);
413 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -0700414 }
415
Yifan Hongbf459bc2016-08-23 16:50:37 -0700416 if (needsResolveReferences()) {
417 emitResolveReferenceDef(out, prefix, true /* isReader */);
418 emitResolveReferenceDef(out, prefix, false /* isReader */);
419 }
Andreas Huber881227d2016-08-02 14:20:21 -0700420
421 return OK;
422}
423
Andreas Huber85eabdb2016-08-25 11:24:49 -0700424status_t CompoundType::emitJavaTypeDeclarations(
425 Formatter &out, bool atTopLevel) const {
426 out << "public final ";
427
428 if (!atTopLevel) {
429 out << "static ";
430 }
431
432 out << "class "
433 << localName()
434 << " {\n";
435
436 out.indent();
437
438 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
439
440 for (const auto &field : *mFields) {
441 const bool isScope = field->type().isScope(); // really isStruct...
442
443 out << "public ";
444
445 field->type().emitJavaFieldInitializer(out, field->name());
446 }
447
448 if (!mFields->empty()) {
449 out << "\n";
450 }
451
Yifan Hong1af73532016-11-09 14:32:58 -0800452 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700453 out.indent();
Yifan Hong1af73532016-11-09 14:32:58 -0800454 out << "android.os.HwBlob blob = parcel.readBuffer();\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700455 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
456 out.unindent();
457 out << "}\n\n";
458
Andreas Huberf630bc82016-09-09 14:52:25 -0700459 ////////////////////////////////////////////////////////////////////////////
460
Yifan Hong1af73532016-11-09 14:32:58 -0800461 out << "public static final java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700462 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800463 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700464 out.indent();
465
Yifan Hong1af73532016-11-09 14:32:58 -0800466 out << "java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700467 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800468 << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700469
Yifan Hong1af73532016-11-09 14:32:58 -0800470 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer();\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700471
472 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700473 out,
474 0 /* depth */,
475 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700476 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700477 "_hidl_blob",
478 "_hidl_vec",
479 "0",
480 true /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700481
Andreas Huber1b6822b2016-10-18 09:28:40 -0700482 out << "\nreturn _hidl_vec;\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700483
484 out.unindent();
485 out << "}\n\n";
486
487 ////////////////////////////////////////////////////////////////////////////
488
Andreas Huber85eabdb2016-08-25 11:24:49 -0700489 out << "public final void readEmbeddedFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700490 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800491 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700492 out.unindent();
493
494 size_t offset = 0;
495 for (const auto &field : *mFields) {
496 size_t fieldAlign, fieldSize;
497 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
498
499 size_t pad = offset % fieldAlign;
500 if (pad > 0) {
501 offset += fieldAlign - pad;
502 }
503
504 field->type().emitJavaFieldReaderWriter(
505 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700506 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700507 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700508 "_hidl_blob",
509 field->name(),
510 "_hidl_offset + " + std::to_string(offset),
511 true /* isReader */);
512
513 offset += fieldSize;
514 }
515
516 out.unindent();
517 out << "}\n\n";
518
Andreas Huberf630bc82016-09-09 14:52:25 -0700519 ////////////////////////////////////////////////////////////////////////////
520
Andreas Huber709b62d2016-09-19 11:21:18 -0700521 size_t structAlign, structSize;
522 getAlignmentAndSize(&structAlign, &structSize);
523
Yifan Hong1af73532016-11-09 14:32:58 -0800524 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700525 out.indent();
526
Yifan Hong1af73532016-11-09 14:32:58 -0800527 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
Andreas Huber85eabdb2016-08-25 11:24:49 -0700528 << structSize
529 << " /* size */);\n";
530
531 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
532 << "parcel.writeBuffer(_hidl_blob);\n";
533
534 out.unindent();
535 out << "}\n\n";
536
Andreas Huberf630bc82016-09-09 14:52:25 -0700537 ////////////////////////////////////////////////////////////////////////////
538
Andreas Huberf630bc82016-09-09 14:52:25 -0700539 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700540 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800541 out << "android.os.HwParcel parcel, java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700542 << localName()
Andreas Huber1b6822b2016-10-18 09:28:40 -0700543 << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700544 out.unindent();
545
Yifan Hong1af73532016-11-09 14:32:58 -0800546 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700547
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";
Yifan Hong0a68a282016-10-21 16:32:34 -0700566 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800567 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700568 out.unindent();
569
570 offset = 0;
571 for (const auto &field : *mFields) {
572 size_t fieldAlign, fieldSize;
573 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
574
575 size_t pad = offset % fieldAlign;
576 if (pad > 0) {
577 offset += fieldAlign - pad;
578 }
579
580 field->type().emitJavaFieldReaderWriter(
581 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700582 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700583 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700584 "_hidl_blob",
585 field->name(),
586 "_hidl_offset + " + std::to_string(offset),
587 false /* isReader */);
588
589 offset += fieldSize;
590 }
591
592 out.unindent();
593 out << "}\n";
594
595 out.unindent();
596 out << "};\n\n";
597
598 return OK;
599}
600
Andreas Huber881227d2016-08-02 14:20:21 -0700601void CompoundType::emitStructReaderWriter(
602 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800603
604 std::string space = prefix.empty() ? "" : (prefix + "::");
605
Andreas Huber881227d2016-08-02 14:20:21 -0700606 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -0800607 << (isReader ? "readEmbeddedFromParcel"
608 : "writeEmbeddedToParcel")
609 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700610
Yifan Hong0a68a282016-10-21 16:32:34 -0700611 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700612
Yifan Hong244e82d2016-11-11 11:13:57 -0800613 bool useName = false;
614 for (const auto &field : *mFields) {
615 if (field->type().useNameInEmitReaderWriterEmbedded(isReader)) {
616 useName = true;
617 break;
618 }
619 }
620 std::string name = useName ? "obj" : "/* obj */";
621 // if not useName, then obj should not be used at all,
622 // then the #error should not be emitted.
623 std::string error = useName ? "" : "\n#error\n";
624
Andreas Huber881227d2016-08-02 14:20:21 -0700625 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800626 out << space << localName() << " *" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700627 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700628 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800629 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700630 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700631 }
632
633 out << "size_t parentHandle,\n"
634 << "size_t parentOffset)";
635
Andreas Huber881227d2016-08-02 14:20:21 -0700636 out << " {\n";
637
Yifan Hong0a68a282016-10-21 16:32:34 -0700638 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700639 out.indent();
640
Iliyan Malchev549e2592016-08-10 08:59:12 -0700641 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700642
643 for (const auto &field : *mFields) {
644 if (!field->type().needsEmbeddedReadWrite()) {
645 continue;
646 }
647
648 field->type().emitReaderWriterEmbedded(
649 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700650 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -0800651 name + (isReader ? "->" : ".") + field->name() + error,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700652 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700653 false /* nameIsPointer */,
654 "parcel",
655 !isReader /* parcelObjIsPointer */,
656 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700657 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700658 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700659 "parentOffset + offsetof("
660 + fullName()
661 + ", "
662 + field->name()
663 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700664 }
665
666 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700667 out << "_hidl_error:\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700668 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700669 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700670
671 out.unindent();
672 out << "}\n\n";
673}
674
Yifan Hongbf459bc2016-08-23 16:50:37 -0700675void CompoundType::emitResolveReferenceDef(
676 Formatter &out, const std::string prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800677 out << "::android::status_t ";
678 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -0700679
680 bool useParent = false;
681 for (const auto &field : *mFields) {
682 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
683 useParent = true;
684 break;
685 }
686 }
687
688 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
689 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
690
Yifan Hongbf459bc2016-08-23 16:50:37 -0700691 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800692 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700693 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800694 out << space + localName() + " *obj,\n"
695 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700696 << "size_t " << parentHandleName << ", "
697 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700698 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700699 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800700 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700701 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800702 out << "const " << space + localName() + " &obj,\n"
703 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700704 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -0800705 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700706 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700707 }
708
709 out << " {\n";
710
711 out.indent();
712
713 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
714
Yifan Hong244e82d2016-11-11 11:13:57 -0800715 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -0700716 // if not useParent, then parentName and offsetText
717 // should not be used at all, then the #error should not be emitted.
718 std::string error = useParent ? "" : "\n#error\n";
719
Yifan Hongbf459bc2016-08-23 16:50:37 -0700720 for (const auto &field : *mFields) {
721 if (!field->type().needsResolveReferences()) {
722 continue;
723 }
724
725 field->type().emitResolveReferencesEmbedded(
726 out,
727 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -0800728 nameDeref + field->name(),
Yifan Hongbf459bc2016-08-23 16:50:37 -0700729 field->name() /* sanitizedName */,
730 false, // nameIsPointer
731 "parcel", // const std::string &parcelObj,
732 !isReader, // bool parcelObjIsPointer,
733 isReader, // bool isReader,
734 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -0700735 parentHandleName + error,
736 parentOffsetName
737 + " + offsetof("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700738 + fullName()
739 + ", "
740 + field->name()
Yifan Hong00f47172016-09-30 14:40:45 -0700741 + ")"
742 + error);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700743 }
744
745 out.unindent();
746 out << "_hidl_error:\n";
747 out.indent();
748 out << "return _hidl_err;\n";
749
750 out.unindent();
751 out << "}\n\n";
752}
753
Andreas Huber881227d2016-08-02 14:20:21 -0700754bool CompoundType::needsEmbeddedReadWrite() const {
755 if (mStyle != STYLE_STRUCT) {
756 return false;
757 }
758
759 for (const auto &field : *mFields) {
760 if (field->type().needsEmbeddedReadWrite()) {
761 return true;
762 }
763 }
764
765 return false;
766}
767
Yifan Hongbf459bc2016-08-23 16:50:37 -0700768bool CompoundType::needsResolveReferences() const {
769 if (mStyle != STYLE_STRUCT) {
770 return false;
771 }
772
773 for (const auto &field : *mFields) {
774 if (field->type().needsResolveReferences()) {
775 return true;
776 }
777 }
778
779 return false;
780}
781
Andreas Huber881227d2016-08-02 14:20:21 -0700782bool CompoundType::resultNeedsDeref() const {
783 return true;
784}
785
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700786status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700787 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700788 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700789
790 // Emit declaration for each subtype.
791 for (const auto &type : getSubTypes()) {
792 switch (mStyle) {
793 case STYLE_STRUCT:
794 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700795 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700796 break;
797 }
798 case STYLE_UNION:
799 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700800 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700801 break;
802 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700803 }
804 out.indent();
805 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700806 if (status != OK) {
807 return status;
808 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700809 out.unindent();
810 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700811 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700812
813 // Emit declaration for each field.
814 for (const auto &field : *mFields) {
815 switch (mStyle) {
816 case STYLE_STRUCT:
817 {
818 out << "struct_value: {\n";
819 break;
820 }
821 case STYLE_UNION:
822 {
823 out << "union_value: {\n";
824 break;
825 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700826 }
827 out.indent();
828 out << "name: \"" << field->name() << "\"\n";
829 status_t status = field->type().emitVtsAttributeType(out);
830 if (status != OK) {
831 return status;
832 }
833 out.unindent();
834 out << "}\n";
835 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700836
837 return OK;
838}
839
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700840status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700841 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700842 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700843 return OK;
844}
845
Andreas Huber70a59e12016-08-16 12:57:01 -0700846bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700847 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
848 return false;
849 }
850
851 for (const auto &field : *mFields) {
852 if (!field->type().isJavaCompatible()) {
853 return false;
854 }
855 }
856
857 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -0700858}
859
860void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
861 *align = 1;
862
863 size_t offset = 0;
864 for (const auto &field : *mFields) {
865 // Each field is aligned according to its alignment requirement.
866 // The surrounding structure's alignment is the maximum of its
867 // fields' aligments.
868
869 size_t fieldAlign, fieldSize;
870 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
871
872 size_t pad = offset % fieldAlign;
873 if (pad > 0) {
874 offset += fieldAlign - pad;
875 }
876
877 offset += fieldSize;
878
879 if (fieldAlign > (*align)) {
880 *align = fieldAlign;
881 }
882 }
883
884 // Final padding to account for the structure's alignment.
885 size_t pad = offset % (*align);
886 if (pad > 0) {
887 offset += (*align) - pad;
888 }
889
890 *size = offset;
Andreas Huber70a59e12016-08-16 12:57:01 -0700891}
892
Andreas Huber31629bc2016-08-03 09:06:40 -0700893////////////////////////////////////////////////////////////////////////////////
894
895CompoundField::CompoundField(const char *name, Type *type)
896 : mName(name),
897 mType(type) {
898}
899
900std::string CompoundField::name() const {
901 return mName;
902}
903
904const Type &CompoundField::type() const {
905 return *mType;
906}
907
Andreas Huberc9410c72016-07-28 12:18:40 -0700908} // namespace android
909