blob: 6527f86e2ac2a67e01a7d0a7d95dd83a8687462e [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
Yifan Hongec102272016-12-20 18:10:07 -080019#include "ArrayType.h"
Andreas Huberf630bc82016-09-09 14:52:25 -070020#include "VectorType.h"
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070021#include <hidl-util/Formatter.h>
Andreas Huber5a545442016-08-03 10:44:56 -070022#include <android-base/logging.h>
23
Andreas Huberc9410c72016-07-28 12:18:40 -070024namespace android {
25
Yifan Honga4b53d02016-10-31 17:29:10 -070026CompoundType::CompoundType(Style style, const char *localName, const Location &location)
27 : Scope(localName, location),
Andreas Huber9ed827c2016-08-22 12:31:13 -070028 mStyle(style),
Andreas Huberc9410c72016-07-28 12:18:40 -070029 mFields(NULL) {
30}
31
Yifan Hong27e85db2016-11-09 15:45:52 -080032CompoundType::Style CompoundType::style() const {
33 return mStyle;
34}
35
Andreas Huber0d0f9a22016-08-17 10:26:11 -070036bool CompoundType::setFields(
37 std::vector<CompoundField *> *fields, std::string *errorMsg) {
Andreas Huberc9410c72016-07-28 12:18:40 -070038 mFields = fields;
Andreas Huber5a545442016-08-03 10:44:56 -070039
40 for (const auto &field : *fields) {
41 const Type &type = field->type();
42
Andreas Huber86a112b2016-10-19 14:25:16 -070043 if (type.isBinder()
44 || (type.isVector()
45 && static_cast<const VectorType *>(
46 &type)->isVectorOfBinders())) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -070047 *errorMsg =
48 "Structs/Unions must not contain references to interfaces.";
Andreas Huberb95ea8a2016-08-15 15:35:42 -070049
50 return false;
51 }
52
Andreas Huber5a545442016-08-03 10:44:56 -070053 if (mStyle == STYLE_UNION) {
54 if (type.needsEmbeddedReadWrite()) {
55 // Can't have those in a union.
56
Andreas Huber0d0f9a22016-08-17 10:26:11 -070057 *errorMsg =
58 "Unions must not contain any types that need fixup.";
Andreas Huber5a545442016-08-03 10:44:56 -070059
60 return false;
61 }
Andreas Huber5a545442016-08-03 10:44:56 -070062 }
63 }
64
65 return true;
Andreas Huberc9410c72016-07-28 12:18:40 -070066}
67
Andreas Huberf630bc82016-09-09 14:52:25 -070068bool CompoundType::isCompoundType() const {
69 return true;
70}
71
Yifan Hongc6752dc2016-12-20 14:00:14 -080072bool CompoundType::canCheckEquality() const {
73 if (mStyle == STYLE_UNION) {
74 return false;
75 }
76 for (const auto &field : *mFields) {
77 if (!field->type().canCheckEquality()) {
78 return false;
79 }
80 }
81 return true;
82}
83
84
Andreas Huber881227d2016-08-02 14:20:21 -070085std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -070086 StorageMode mode,
Steven Moreland979e0992016-09-07 09:18:08 -070087 bool specifyNamespaces) const {
Steven Moreland979e0992016-09-07 09:18:08 -070088 const std::string base =
89 specifyNamespaces ? fullName() : partialCppName();
Andreas Huber881227d2016-08-02 14:20:21 -070090
91 switch (mode) {
92 case StorageMode_Stack:
93 return base;
94
95 case StorageMode_Argument:
96 return "const " + base + "&";
97
98 case StorageMode_Result:
99 return "const " + base + "*";
100 }
101}
102
Yifan Hong4ed13472016-11-02 10:44:11 -0700103std::string CompoundType::getJavaType(bool /* forInitializer */) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700104 return fullJavaName();
105}
106
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700107std::string CompoundType::getVtsType() const {
108 switch (mStyle) {
109 case STYLE_STRUCT:
110 {
111 return "TYPE_STRUCT";
112 }
113 case STYLE_UNION:
114 {
115 return "TYPE_UNION";
116 }
117 }
118}
119
Andreas Huber881227d2016-08-02 14:20:21 -0700120void CompoundType::emitReaderWriter(
121 Formatter &out,
122 const std::string &name,
123 const std::string &parcelObj,
124 bool parcelObjIsPointer,
125 bool isReader,
126 ErrorMode mode) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700127 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700128
129 out << "size_t " << parentName << ";\n\n";
130
131 const std::string parcelObjDeref =
132 parcelObj + (parcelObjIsPointer ? "->" : ".");
133
134 if (isReader) {
135 out << name
136 << " = (const "
Andreas Huber0e00de42016-08-03 09:56:02 -0700137 << fullName()
Andreas Huber881227d2016-08-02 14:20:21 -0700138 << " *)"
139 << parcelObjDeref
140 << "readBuffer("
141 << "&"
142 << parentName
143 << ");\n";
144
145 out << "if ("
146 << name
147 << " == nullptr) {\n";
148
Yifan Hong33223ca2016-12-13 15:07:35 -0800149 out.indent([&]{
Yifan Hong0a68a282016-10-21 16:32:34 -0700150 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
151 handleError2(out, mode);
152 });
Andreas Huber881227d2016-08-02 14:20:21 -0700153
Andreas Huber881227d2016-08-02 14:20:21 -0700154 out << "}\n\n";
155 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700156 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700157 << parcelObjDeref
158 << "writeBuffer(&"
159 << name
160 << ", sizeof("
161 << name
162 << "), &"
163 << parentName
164 << ");\n";
165
166 handleError(out, mode);
167 }
168
169 if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
170 return;
171 }
172
173 emitReaderWriterEmbedded(
174 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700175 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700176 name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700177 name, /* sanitizedName */
Andreas Huber881227d2016-08-02 14:20:21 -0700178 isReader /* nameIsPointer */,
179 parcelObj,
180 parcelObjIsPointer,
181 isReader,
182 mode,
183 parentName,
184 "0 /* parentOffset */");
185}
186
187void CompoundType::emitReaderWriterEmbedded(
188 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700189 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700190 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700191 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700192 bool nameIsPointer,
193 const std::string &parcelObj,
194 bool parcelObjIsPointer,
195 bool isReader,
196 ErrorMode mode,
197 const std::string &parentName,
198 const std::string &offsetText) const {
199 emitReaderWriterEmbeddedForTypeName(
200 out,
201 name,
202 nameIsPointer,
203 parcelObj,
204 parcelObjIsPointer,
205 isReader,
206 mode,
207 parentName,
208 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700209 fullName(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800210 "" /* childName */,
211 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700212}
213
Andreas Huber85eabdb2016-08-25 11:24:49 -0700214void CompoundType::emitJavaReaderWriter(
215 Formatter &out,
216 const std::string &parcelObj,
217 const std::string &argName,
218 bool isReader) const {
219 if (isReader) {
220 out << "new " << fullJavaName() << "();\n";
221 }
222
223 out << argName
224 << "."
225 << (isReader ? "readFromParcel" : "writeToParcel")
226 << "("
227 << parcelObj
228 << ");\n";
229}
230
231void CompoundType::emitJavaFieldInitializer(
232 Formatter &out, const std::string &fieldName) const {
233 out << "final "
234 << fullJavaName()
235 << " "
236 << fieldName
237 << " = new "
238 << fullJavaName()
239 << "();\n";
240}
241
242void CompoundType::emitJavaFieldReaderWriter(
243 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700244 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700245 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700246 const std::string &blobName,
247 const std::string &fieldName,
248 const std::string &offset,
249 bool isReader) const {
250 if (isReader) {
251 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700252 << ".readEmbeddedFromParcel("
253 << parcelName
254 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700255 << blobName
256 << ", "
257 << offset
258 << ");\n";
259
260 return;
261 }
262
263 out << fieldName
264 << ".writeEmbeddedToBlob("
265 << blobName
266 << ", "
267 << offset
268 << ");\n";
269}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700270void CompoundType::emitResolveReferences(
271 Formatter &out,
272 const std::string &name,
273 bool nameIsPointer,
274 const std::string &parcelObj,
275 bool parcelObjIsPointer,
276 bool isReader,
277 ErrorMode mode) const {
278 emitResolveReferencesEmbedded(
279 out,
280 0 /* depth */,
281 name,
282 name /* sanitizedName */,
283 nameIsPointer,
284 parcelObj,
285 parcelObjIsPointer,
286 isReader,
287 mode,
288 "_hidl_" + name + "_parent",
289 "0 /* parentOffset */");
290}
291
292void CompoundType::emitResolveReferencesEmbedded(
293 Formatter &out,
294 size_t /* depth */,
295 const std::string &name,
296 const std::string &/* sanitizedName */,
297 bool nameIsPointer,
298 const std::string &parcelObj,
299 bool parcelObjIsPointer,
300 bool isReader,
301 ErrorMode mode,
302 const std::string &parentName,
303 const std::string &offsetText) const {
304 CHECK(needsResolveReferences());
305
306 const std::string parcelObjDeref =
307 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
308
309 const std::string parcelObjPointer =
310 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
311
Yifan Hong244e82d2016-11-11 11:13:57 -0800312 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700313 const std::string namePointer = nameIsPointer ? name : ("&" + name);
314
315 out << "_hidl_err = ";
316
317 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800318 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700319 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800320 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700321 }
322
Yifan Hong33223ca2016-12-13 15:07:35 -0800323 out.indent(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800324 if (isReader) {
325 out << "const_cast<"
326 << fullName()
327 << " *"
328 << ">("
329 << namePointer
330 << "),\n"
331 << parcelObjDeref;
332 } else {
333 out << nameDerefed
334 << ",\n"
335 << parcelObjPointer;
336 }
337
338 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700339 << parentName
340 << ",\n"
341 << offsetText
342 << ");\n\n";
343 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700344
345 handleError(out, mode);
346}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700347
Andreas Huber881227d2016-08-02 14:20:21 -0700348status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
349 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
350 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700351 << localName()
Yifan Hongb1d2ebc2016-12-20 17:18:07 -0800352 << " final {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700353
354 out.indent();
355
356 Scope::emitTypeDeclarations(out);
357
358 for (const auto &field : *mFields) {
Martijn Coenen2f69a5b2016-11-18 15:26:38 +0100359 out << field->type().getCppStackType()
Andreas Huber881227d2016-08-02 14:20:21 -0700360 << " "
361 << field->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700362 << ";\n";
363 }
364
Yifan Hong244e82d2016-11-11 11:13:57 -0800365 out.unindent();
366 out << "};\n\n";
367
368 return OK;
369}
370
371
Yifan Hongc6752dc2016-12-20 14:00:14 -0800372status_t CompoundType::emitGlobalTypeDeclarations(Formatter &out) const {
373 Scope::emitGlobalTypeDeclarations(out);
374
375 if (!canCheckEquality()) {
376 return OK;
377 }
378
379 out << "inline bool operator==("
380 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
381 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
382 out.block([&] {
383 for (const auto &field : *mFields) {
384 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
385 out << "return false;\n";
386 }).endl();
387 }
388 out << "return true;\n";
389 }).endl().endl();
390
391 out << "inline bool operator!=("
392 << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
393 out.block([&] {
394 out << "return !(lhs == rhs);\n";
395 }).endl().endl();
396
397 return OK;
398}
399
Yifan Hong244e82d2016-11-11 11:13:57 -0800400status_t CompoundType::emitGlobalHwDeclarations(Formatter &out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700401 if (needsEmbeddedReadWrite()) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800402 out << "::android::status_t readEmbeddedFromParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700403
Yifan Hong0a68a282016-10-21 16:32:34 -0700404 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700405
Yifan Hong244e82d2016-11-11 11:13:57 -0800406 out << fullName() << " *obj,\n"
407 << "const ::android::hardware::Parcel &parcel,\n"
408 << "size_t parentHandle,\n"
409 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700410
Yifan Hong0a68a282016-10-21 16:32:34 -0700411 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700412
413 out << "::android::status_t writeEmbeddedToParcel(\n";
414
Yifan Hong0a68a282016-10-21 16:32:34 -0700415 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700416
Yifan Hong244e82d2016-11-11 11:13:57 -0800417 out << "const " << fullName() << " &obj,\n"
418 << "::android::hardware::Parcel *parcel,\n"
419 << "size_t parentHandle,\n"
420 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700421
Yifan Hong0a68a282016-10-21 16:32:34 -0700422 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700423 }
424
Yifan Hongbf459bc2016-08-23 16:50:37 -0700425 if(needsResolveReferences()) {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700426 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700427 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800428 out << fullName() << " *obj,\n"
429 << "const ::android::hardware::Parcel &parcel,\n"
430 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700431 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700432 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700433 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800434 out << "const " << fullName() << " &obj,\n"
435 << "::android::hardware::Parcel *,\n"
436 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700437 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700438 }
439
Andreas Huber881227d2016-08-02 14:20:21 -0700440 return OK;
441}
442
443status_t CompoundType::emitTypeDefinitions(
444 Formatter &out, const std::string prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -0700445 std::string space = prefix.empty() ? "" : (prefix + "::");
446 status_t err = Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700447
448 if (err != OK) {
449 return err;
450 }
451
Yifan Hongbf459bc2016-08-23 16:50:37 -0700452 if (needsEmbeddedReadWrite()) {
453 emitStructReaderWriter(out, prefix, true /* isReader */);
454 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -0700455 }
456
Yifan Hongbf459bc2016-08-23 16:50:37 -0700457 if (needsResolveReferences()) {
458 emitResolveReferenceDef(out, prefix, true /* isReader */);
459 emitResolveReferenceDef(out, prefix, false /* isReader */);
460 }
Andreas Huber881227d2016-08-02 14:20:21 -0700461
462 return OK;
463}
464
Andreas Huber85eabdb2016-08-25 11:24:49 -0700465status_t CompoundType::emitJavaTypeDeclarations(
466 Formatter &out, bool atTopLevel) const {
467 out << "public final ";
468
469 if (!atTopLevel) {
470 out << "static ";
471 }
472
473 out << "class "
474 << localName()
475 << " {\n";
476
477 out.indent();
478
479 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
480
481 for (const auto &field : *mFields) {
482 const bool isScope = field->type().isScope(); // really isStruct...
483
484 out << "public ";
485
486 field->type().emitJavaFieldInitializer(out, field->name());
487 }
488
489 if (!mFields->empty()) {
490 out << "\n";
491 }
492
Yifan Hongec102272016-12-20 18:10:07 -0800493 ////////////////////////////////////////////////////////////////////////////
494
495 if (canCheckEquality()) {
496 out << "public final boolean equals(" << localName() << " other) ";
497 out.block([&] {
498 for (const auto &field : *mFields) {
499 std::string condition = field->type().isScalar()
500 ? "this." + field->name() + " != other." + field->name()
501 : ("!java.util.Objects.deepEquals(this." + field->name()
502 + ", other." + field->name() + ")");
503 out.sIf(condition, [&] {
504 out << "return false;\n";
505 }).endl();
506 }
507 out << "return true;\n";
508 }).endl().endl();
509
510 out << "public final int hashCode() ";
511 out.block([&] {
512 out << "return java.util.Objects.hash(";
513 bool first = true;
514 for (const auto &field : *mFields) {
515 if (!first) {
516 out << ", ";
517 }
518 first = false;
519 if (field->type().isArray()) {
520 const ArrayType &type = static_cast<const ArrayType &>(field->type());
521 if (type.countDimensions() == 1 &&
522 type.getElementType()->resolveToScalarType() != nullptr) {
523 out << "java.util.Arrays.hashCode(this." << field->name() << ")";
524 } else {
525 out << "java.util.Arrays.deepHashCode(this." << field->name() << ")";
526 }
527 } else {
528 out << "this." << field->name();
529 }
530 }
531 out << ");\n";
532 }).endl().endl();
533 }
534
535 ////////////////////////////////////////////////////////////////////////////
536
Yifan Hong1af73532016-11-09 14:32:58 -0800537 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700538 out.indent();
Yifan Hong1af73532016-11-09 14:32:58 -0800539 out << "android.os.HwBlob blob = parcel.readBuffer();\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700540 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
541 out.unindent();
542 out << "}\n\n";
543
Andreas Huberf630bc82016-09-09 14:52:25 -0700544 ////////////////////////////////////////////////////////////////////////////
545
Yifan Hong1af73532016-11-09 14:32:58 -0800546 out << "public static final java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700547 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800548 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700549 out.indent();
550
Yifan Hong1af73532016-11-09 14:32:58 -0800551 out << "java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700552 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800553 << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700554
Yifan Hong1af73532016-11-09 14:32:58 -0800555 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer();\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700556
557 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700558 out,
559 0 /* depth */,
560 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700561 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700562 "_hidl_blob",
563 "_hidl_vec",
564 "0",
565 true /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700566
Andreas Huber1b6822b2016-10-18 09:28:40 -0700567 out << "\nreturn _hidl_vec;\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700568
569 out.unindent();
570 out << "}\n\n";
571
572 ////////////////////////////////////////////////////////////////////////////
573
Andreas Huber85eabdb2016-08-25 11:24:49 -0700574 out << "public final void readEmbeddedFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700575 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800576 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700577 out.unindent();
578
579 size_t offset = 0;
580 for (const auto &field : *mFields) {
581 size_t fieldAlign, fieldSize;
582 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
583
584 size_t pad = offset % fieldAlign;
585 if (pad > 0) {
586 offset += fieldAlign - pad;
587 }
588
589 field->type().emitJavaFieldReaderWriter(
590 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700591 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700592 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700593 "_hidl_blob",
594 field->name(),
595 "_hidl_offset + " + std::to_string(offset),
596 true /* isReader */);
597
598 offset += fieldSize;
599 }
600
601 out.unindent();
602 out << "}\n\n";
603
Andreas Huberf630bc82016-09-09 14:52:25 -0700604 ////////////////////////////////////////////////////////////////////////////
605
Andreas Huber709b62d2016-09-19 11:21:18 -0700606 size_t structAlign, structSize;
607 getAlignmentAndSize(&structAlign, &structSize);
608
Yifan Hong1af73532016-11-09 14:32:58 -0800609 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700610 out.indent();
611
Yifan Hong1af73532016-11-09 14:32:58 -0800612 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
Andreas Huber85eabdb2016-08-25 11:24:49 -0700613 << structSize
614 << " /* size */);\n";
615
616 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
617 << "parcel.writeBuffer(_hidl_blob);\n";
618
619 out.unindent();
620 out << "}\n\n";
621
Andreas Huberf630bc82016-09-09 14:52:25 -0700622 ////////////////////////////////////////////////////////////////////////////
623
Andreas Huberf630bc82016-09-09 14:52:25 -0700624 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700625 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800626 out << "android.os.HwParcel parcel, java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700627 << localName()
Andreas Huber1b6822b2016-10-18 09:28:40 -0700628 << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700629 out.unindent();
630
Yifan Hong1af73532016-11-09 14:32:58 -0800631 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700632
633 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700634 out,
635 0 /* depth */,
636 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700637 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700638 "_hidl_blob",
639 "_hidl_vec",
640 "0",
641 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700642
643 out << "\nparcel.writeBuffer(_hidl_blob);\n";
644
645 out.unindent();
646 out << "}\n\n";
647
648 ////////////////////////////////////////////////////////////////////////////
649
Andreas Huber85eabdb2016-08-25 11:24:49 -0700650 out << "public final void writeEmbeddedToBlob(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700651 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800652 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700653 out.unindent();
654
655 offset = 0;
656 for (const auto &field : *mFields) {
657 size_t fieldAlign, fieldSize;
658 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
659
660 size_t pad = offset % fieldAlign;
661 if (pad > 0) {
662 offset += fieldAlign - pad;
663 }
664
665 field->type().emitJavaFieldReaderWriter(
666 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700667 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700668 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700669 "_hidl_blob",
670 field->name(),
671 "_hidl_offset + " + std::to_string(offset),
672 false /* isReader */);
673
674 offset += fieldSize;
675 }
676
677 out.unindent();
678 out << "}\n";
679
680 out.unindent();
681 out << "};\n\n";
682
683 return OK;
684}
685
Andreas Huber881227d2016-08-02 14:20:21 -0700686void CompoundType::emitStructReaderWriter(
687 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800688
689 std::string space = prefix.empty() ? "" : (prefix + "::");
690
Andreas Huber881227d2016-08-02 14:20:21 -0700691 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -0800692 << (isReader ? "readEmbeddedFromParcel"
693 : "writeEmbeddedToParcel")
694 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700695
Yifan Hong0a68a282016-10-21 16:32:34 -0700696 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700697
Yifan Hong244e82d2016-11-11 11:13:57 -0800698 bool useName = false;
699 for (const auto &field : *mFields) {
700 if (field->type().useNameInEmitReaderWriterEmbedded(isReader)) {
701 useName = true;
702 break;
703 }
704 }
705 std::string name = useName ? "obj" : "/* obj */";
706 // if not useName, then obj should not be used at all,
707 // then the #error should not be emitted.
708 std::string error = useName ? "" : "\n#error\n";
709
Andreas Huber881227d2016-08-02 14:20:21 -0700710 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800711 out << space << localName() << " *" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700712 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700713 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800714 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700715 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700716 }
717
718 out << "size_t parentHandle,\n"
719 << "size_t parentOffset)";
720
Andreas Huber881227d2016-08-02 14:20:21 -0700721 out << " {\n";
722
Yifan Hong0a68a282016-10-21 16:32:34 -0700723 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700724 out.indent();
725
Iliyan Malchev549e2592016-08-10 08:59:12 -0700726 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700727
728 for (const auto &field : *mFields) {
729 if (!field->type().needsEmbeddedReadWrite()) {
730 continue;
731 }
732
733 field->type().emitReaderWriterEmbedded(
734 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700735 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -0800736 name + (isReader ? "->" : ".") + field->name() + error,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700737 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700738 false /* nameIsPointer */,
739 "parcel",
740 !isReader /* parcelObjIsPointer */,
741 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700742 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700743 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700744 "parentOffset + offsetof("
745 + fullName()
746 + ", "
747 + field->name()
748 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700749 }
750
751 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700752 out << "_hidl_error:\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700753 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700754 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700755
756 out.unindent();
757 out << "}\n\n";
758}
759
Yifan Hongbf459bc2016-08-23 16:50:37 -0700760void CompoundType::emitResolveReferenceDef(
761 Formatter &out, const std::string prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800762 out << "::android::status_t ";
763 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -0700764
765 bool useParent = false;
766 for (const auto &field : *mFields) {
767 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
768 useParent = true;
769 break;
770 }
771 }
772
773 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
774 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
775
Yifan Hongbf459bc2016-08-23 16:50:37 -0700776 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800777 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700778 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800779 out << space + localName() + " *obj,\n"
780 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700781 << "size_t " << parentHandleName << ", "
782 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700783 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700784 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800785 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700786 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800787 out << "const " << space + localName() + " &obj,\n"
788 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700789 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -0800790 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700791 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700792 }
793
794 out << " {\n";
795
796 out.indent();
797
798 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
799
Yifan Hong244e82d2016-11-11 11:13:57 -0800800 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -0700801 // if not useParent, then parentName and offsetText
802 // should not be used at all, then the #error should not be emitted.
803 std::string error = useParent ? "" : "\n#error\n";
804
Yifan Hongbf459bc2016-08-23 16:50:37 -0700805 for (const auto &field : *mFields) {
806 if (!field->type().needsResolveReferences()) {
807 continue;
808 }
809
810 field->type().emitResolveReferencesEmbedded(
811 out,
812 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -0800813 nameDeref + field->name(),
Yifan Hongbf459bc2016-08-23 16:50:37 -0700814 field->name() /* sanitizedName */,
815 false, // nameIsPointer
816 "parcel", // const std::string &parcelObj,
817 !isReader, // bool parcelObjIsPointer,
818 isReader, // bool isReader,
819 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -0700820 parentHandleName + error,
821 parentOffsetName
822 + " + offsetof("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700823 + fullName()
824 + ", "
825 + field->name()
Yifan Hong00f47172016-09-30 14:40:45 -0700826 + ")"
827 + error);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700828 }
829
830 out.unindent();
831 out << "_hidl_error:\n";
832 out.indent();
833 out << "return _hidl_err;\n";
834
835 out.unindent();
836 out << "}\n\n";
837}
838
Andreas Huber881227d2016-08-02 14:20:21 -0700839bool CompoundType::needsEmbeddedReadWrite() const {
840 if (mStyle != STYLE_STRUCT) {
841 return false;
842 }
843
844 for (const auto &field : *mFields) {
845 if (field->type().needsEmbeddedReadWrite()) {
846 return true;
847 }
848 }
849
850 return false;
851}
852
Yifan Hongbf459bc2016-08-23 16:50:37 -0700853bool CompoundType::needsResolveReferences() const {
854 if (mStyle != STYLE_STRUCT) {
855 return false;
856 }
857
858 for (const auto &field : *mFields) {
859 if (field->type().needsResolveReferences()) {
860 return true;
861 }
862 }
863
864 return false;
865}
866
Andreas Huber881227d2016-08-02 14:20:21 -0700867bool CompoundType::resultNeedsDeref() const {
868 return true;
869}
870
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700871status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700872 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700873 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700874
875 // Emit declaration for each subtype.
876 for (const auto &type : getSubTypes()) {
877 switch (mStyle) {
878 case STYLE_STRUCT:
879 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700880 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700881 break;
882 }
883 case STYLE_UNION:
884 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700885 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700886 break;
887 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700888 }
889 out.indent();
890 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700891 if (status != OK) {
892 return status;
893 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700894 out.unindent();
895 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700896 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700897
898 // Emit declaration for each field.
899 for (const auto &field : *mFields) {
900 switch (mStyle) {
901 case STYLE_STRUCT:
902 {
903 out << "struct_value: {\n";
904 break;
905 }
906 case STYLE_UNION:
907 {
908 out << "union_value: {\n";
909 break;
910 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700911 }
912 out.indent();
913 out << "name: \"" << field->name() << "\"\n";
914 status_t status = field->type().emitVtsAttributeType(out);
915 if (status != OK) {
916 return status;
917 }
918 out.unindent();
919 out << "}\n";
920 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700921
922 return OK;
923}
924
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700925status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700926 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700927 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700928 return OK;
929}
930
Andreas Huber70a59e12016-08-16 12:57:01 -0700931bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700932 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
933 return false;
934 }
935
936 for (const auto &field : *mFields) {
937 if (!field->type().isJavaCompatible()) {
938 return false;
939 }
940 }
941
942 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -0700943}
944
945void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
946 *align = 1;
947
948 size_t offset = 0;
949 for (const auto &field : *mFields) {
950 // Each field is aligned according to its alignment requirement.
951 // The surrounding structure's alignment is the maximum of its
952 // fields' aligments.
953
954 size_t fieldAlign, fieldSize;
955 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
956
957 size_t pad = offset % fieldAlign;
958 if (pad > 0) {
959 offset += fieldAlign - pad;
960 }
961
962 offset += fieldSize;
963
964 if (fieldAlign > (*align)) {
965 *align = fieldAlign;
966 }
967 }
968
969 // Final padding to account for the structure's alignment.
970 size_t pad = offset % (*align);
971 if (pad > 0) {
972 offset += (*align) - pad;
973 }
974
975 *size = offset;
Andreas Huber70a59e12016-08-16 12:57:01 -0700976}
977
Andreas Huber31629bc2016-08-03 09:06:40 -0700978////////////////////////////////////////////////////////////////////////////////
979
980CompoundField::CompoundField(const char *name, Type *type)
981 : mName(name),
982 mType(type) {
983}
984
985std::string CompoundField::name() const {
986 return mName;
987}
988
989const Type &CompoundField::type() const {
990 return *mType;
991}
992
Andreas Huberc9410c72016-07-28 12:18:40 -0700993} // namespace android
994