blob: 91bf0cfd9831cf1c2521fcc32e65ab06e6c689b8 [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"
Timur Iskhakovcec46c42017-08-09 00:22:02 -070021
Andreas Huber5a545442016-08-03 10:44:56 -070022#include <android-base/logging.h>
Timur Iskhakovcec46c42017-08-09 00:22:02 -070023#include <hidl-util/Formatter.h>
Timur Iskhakove8ee6a02017-09-06 11:42:10 -070024#include <iostream>
Timur Iskhakovcec46c42017-08-09 00:22:02 -070025#include <unordered_set>
Andreas Huber5a545442016-08-03 10:44:56 -070026
Andreas Huberc9410c72016-07-28 12:18:40 -070027namespace android {
28
Timur Iskhakov565b0132017-09-06 18:07:11 -070029CompoundType::CompoundType(Style style, const char* localName, const FQName& fullName,
30 const Location& location, Scope* parent)
31 : Scope(localName, fullName, location, parent), mStyle(style), mFields(NULL) {}
Andreas Huberc9410c72016-07-28 12:18:40 -070032
Yifan Hong27e85db2016-11-09 15:45:52 -080033CompoundType::Style CompoundType::style() const {
34 return mStyle;
35}
36
Timur Iskhakovcec46c42017-08-09 00:22:02 -070037void CompoundType::setFields(std::vector<NamedReference<Type>*>* fields) {
Andreas Huberc9410c72016-07-28 12:18:40 -070038 mFields = fields;
Timur Iskhakovcec46c42017-08-09 00:22:02 -070039}
Andreas Huber5a545442016-08-03 10:44:56 -070040
Timur Iskhakovb58f4182017-08-29 15:19:24 -070041std::vector<const Reference<Type>*> CompoundType::getReferences() const {
42 std::vector<const Reference<Type>*> ret;
43 ret.insert(ret.begin(), mFields->begin(), mFields->end());
Timur Iskhakov33431e62017-08-21 17:31:23 -070044 return ret;
Timur Iskhakovcec46c42017-08-09 00:22:02 -070045}
46
47status_t CompoundType::validate() const {
48 for (const auto* field : *mFields) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070049 const Type& type = field->type();
Andreas Huber5a545442016-08-03 10:44:56 -070050
Andreas Huber86a112b2016-10-19 14:25:16 -070051 if (type.isBinder()
52 || (type.isVector()
53 && static_cast<const VectorType *>(
54 &type)->isVectorOfBinders())) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070055 std::cerr << "ERROR: Struct/Union must not contain references to interfaces at "
56 << field->location() << "\n";
57 return UNKNOWN_ERROR;
Andreas Huberb95ea8a2016-08-15 15:35:42 -070058 }
59
Andreas Huber5a545442016-08-03 10:44:56 -070060 if (mStyle == STYLE_UNION) {
61 if (type.needsEmbeddedReadWrite()) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070062 std::cerr << "ERROR: Union must not contain any types that need fixup at "
63 << field->location() << "\n";
64 return UNKNOWN_ERROR;
Andreas Huber5a545442016-08-03 10:44:56 -070065 }
Andreas Huber5a545442016-08-03 10:44:56 -070066 }
67 }
68
Timur Iskhakovcec46c42017-08-09 00:22:02 -070069 status_t err = validateUniqueNames();
70 if (err != OK) return err;
71
72 return Scope::validate();
73}
74
75status_t CompoundType::validateUniqueNames() const {
76 std::unordered_set<std::string> names;
77
78 for (const auto* field : *mFields) {
79 if (names.find(field->name()) != names.end()) {
80 std::cerr << "ERROR: Redefinition of field '" << field->name() << "' at "
81 << field->location() << "\n";
82 return UNKNOWN_ERROR;
83 }
84 names.insert(field->name());
85 }
86
87 return OK;
Andreas Huberc9410c72016-07-28 12:18:40 -070088}
89
Andreas Huberf630bc82016-09-09 14:52:25 -070090bool CompoundType::isCompoundType() const {
91 return true;
92}
93
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -070094bool CompoundType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
Yifan Hongc6752dc2016-12-20 14:00:14 -080095 if (mStyle == STYLE_UNION) {
96 return false;
97 }
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -070098 for (const auto* field : *mFields) {
99 if (!field->get()->canCheckEquality(visited)) {
Yifan Hongc6752dc2016-12-20 14:00:14 -0800100 return false;
101 }
102 }
103 return true;
104}
105
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700106std::string CompoundType::typeName() const {
107 switch (mStyle) {
108 case STYLE_STRUCT: {
109 return "struct " + localName();
110 }
111 case STYLE_UNION: {
112 return "union " + localName();
113 }
114 }
115 CHECK(!"Should not be here");
116}
117
Andreas Huber881227d2016-08-02 14:20:21 -0700118std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -0700119 StorageMode mode,
Steven Morelande30ee9b2017-05-09 13:31:01 -0700120 bool /* specifyNamespaces */) const {
121 const std::string base = fullName();
Andreas Huber881227d2016-08-02 14:20:21 -0700122
123 switch (mode) {
124 case StorageMode_Stack:
125 return base;
126
127 case StorageMode_Argument:
128 return "const " + base + "&";
129
130 case StorageMode_Result:
131 return "const " + base + "*";
132 }
133}
134
Yifan Hong4ed13472016-11-02 10:44:11 -0700135std::string CompoundType::getJavaType(bool /* forInitializer */) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700136 return fullJavaName();
137}
138
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700139std::string CompoundType::getVtsType() const {
140 switch (mStyle) {
141 case STYLE_STRUCT:
142 {
143 return "TYPE_STRUCT";
144 }
145 case STYLE_UNION:
146 {
147 return "TYPE_UNION";
148 }
149 }
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700150 CHECK(!"Should not be here");
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700151}
152
Andreas Huber881227d2016-08-02 14:20:21 -0700153void CompoundType::emitReaderWriter(
154 Formatter &out,
155 const std::string &name,
156 const std::string &parcelObj,
157 bool parcelObjIsPointer,
158 bool isReader,
159 ErrorMode mode) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700160 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700161
162 out << "size_t " << parentName << ";\n\n";
163
164 const std::string parcelObjDeref =
165 parcelObj + (parcelObjIsPointer ? "->" : ".");
166
167 if (isReader) {
Martijn Coenen6a082c62017-01-11 12:47:02 +0100168 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700169 << parcelObjDeref
170 << "readBuffer("
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700171 << "sizeof(*"
172 << name
173 << "), &"
Andreas Huber881227d2016-08-02 14:20:21 -0700174 << parentName
Martijn Coenen6a082c62017-01-11 12:47:02 +0100175 << ", "
176 << " reinterpret_cast<const void **>("
177 << "&" << name
178 << "));\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700179
Martijn Coenen6a082c62017-01-11 12:47:02 +0100180 handleError(out, mode);
Andreas Huber881227d2016-08-02 14:20:21 -0700181 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700182 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700183 << parcelObjDeref
184 << "writeBuffer(&"
185 << name
186 << ", sizeof("
187 << name
188 << "), &"
189 << parentName
190 << ");\n";
191
192 handleError(out, mode);
193 }
194
195 if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
196 return;
197 }
198
199 emitReaderWriterEmbedded(
200 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700201 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700202 name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700203 name, /* sanitizedName */
Andreas Huber881227d2016-08-02 14:20:21 -0700204 isReader /* nameIsPointer */,
205 parcelObj,
206 parcelObjIsPointer,
207 isReader,
208 mode,
209 parentName,
210 "0 /* parentOffset */");
211}
212
213void CompoundType::emitReaderWriterEmbedded(
214 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700215 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700216 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700217 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700218 bool nameIsPointer,
219 const std::string &parcelObj,
220 bool parcelObjIsPointer,
221 bool isReader,
222 ErrorMode mode,
223 const std::string &parentName,
224 const std::string &offsetText) const {
225 emitReaderWriterEmbeddedForTypeName(
226 out,
227 name,
228 nameIsPointer,
229 parcelObj,
230 parcelObjIsPointer,
231 isReader,
232 mode,
233 parentName,
234 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700235 fullName(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800236 "" /* childName */,
237 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700238}
239
Andreas Huber85eabdb2016-08-25 11:24:49 -0700240void CompoundType::emitJavaReaderWriter(
241 Formatter &out,
242 const std::string &parcelObj,
243 const std::string &argName,
244 bool isReader) const {
245 if (isReader) {
246 out << "new " << fullJavaName() << "();\n";
247 }
248
249 out << argName
250 << "."
251 << (isReader ? "readFromParcel" : "writeToParcel")
252 << "("
253 << parcelObj
254 << ");\n";
255}
256
257void CompoundType::emitJavaFieldInitializer(
258 Formatter &out, const std::string &fieldName) const {
259 out << "final "
260 << fullJavaName()
261 << " "
262 << fieldName
263 << " = new "
264 << fullJavaName()
265 << "();\n";
266}
267
268void CompoundType::emitJavaFieldReaderWriter(
269 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700270 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700271 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700272 const std::string &blobName,
273 const std::string &fieldName,
274 const std::string &offset,
275 bool isReader) const {
276 if (isReader) {
277 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700278 << ".readEmbeddedFromParcel("
279 << parcelName
280 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700281 << blobName
282 << ", "
283 << offset
284 << ");\n";
285
286 return;
287 }
288
289 out << fieldName
290 << ".writeEmbeddedToBlob("
291 << blobName
292 << ", "
293 << offset
294 << ");\n";
295}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700296void CompoundType::emitResolveReferences(
297 Formatter &out,
298 const std::string &name,
299 bool nameIsPointer,
300 const std::string &parcelObj,
301 bool parcelObjIsPointer,
302 bool isReader,
303 ErrorMode mode) const {
304 emitResolveReferencesEmbedded(
305 out,
306 0 /* depth */,
307 name,
308 name /* sanitizedName */,
309 nameIsPointer,
310 parcelObj,
311 parcelObjIsPointer,
312 isReader,
313 mode,
314 "_hidl_" + name + "_parent",
315 "0 /* parentOffset */");
316}
317
318void CompoundType::emitResolveReferencesEmbedded(
319 Formatter &out,
320 size_t /* depth */,
321 const std::string &name,
322 const std::string &/* sanitizedName */,
323 bool nameIsPointer,
324 const std::string &parcelObj,
325 bool parcelObjIsPointer,
326 bool isReader,
327 ErrorMode mode,
328 const std::string &parentName,
329 const std::string &offsetText) const {
330 CHECK(needsResolveReferences());
331
332 const std::string parcelObjDeref =
333 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
334
335 const std::string parcelObjPointer =
336 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
337
Yifan Hong244e82d2016-11-11 11:13:57 -0800338 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700339 const std::string namePointer = nameIsPointer ? name : ("&" + name);
340
341 out << "_hidl_err = ";
342
343 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800344 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700345 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800346 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700347 }
348
Yifan Hong33223ca2016-12-13 15:07:35 -0800349 out.indent(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800350 if (isReader) {
351 out << "const_cast<"
352 << fullName()
353 << " *"
354 << ">("
355 << namePointer
356 << "),\n"
357 << parcelObjDeref;
358 } else {
359 out << nameDerefed
360 << ",\n"
361 << parcelObjPointer;
362 }
363
364 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700365 << parentName
366 << ",\n"
367 << offsetText
368 << ");\n\n";
369 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700370
371 handleError(out, mode);
372}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700373
Andreas Huber881227d2016-08-02 14:20:21 -0700374status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
375 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
376 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700377 << localName()
Yifan Hongb1d2ebc2016-12-20 17:18:07 -0800378 << " final {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700379
380 out.indent();
381
382 Scope::emitTypeDeclarations(out);
383
Andreas Huber60d3b222017-03-30 09:10:56 -0700384 if (containsPointer()) {
Andreas Huberca4bc892017-01-09 14:58:12 -0800385 for (const auto &field : *mFields) {
386 out << field->type().getCppStackType()
387 << " "
388 << field->name()
389 << ";\n";
390 }
391
392 out.unindent();
393 out << "};\n\n";
394
395 return OK;
Andreas Huber881227d2016-08-02 14:20:21 -0700396 }
397
Andreas Huberca4bc892017-01-09 14:58:12 -0800398 for (int pass = 0; pass < 2; ++pass) {
399 size_t offset = 0;
400 for (const auto &field : *mFields) {
401 size_t fieldAlign, fieldSize;
402 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
403
404 size_t pad = offset % fieldAlign;
405 if (pad > 0) {
406 offset += fieldAlign - pad;
407 }
408
409 if (pass == 0) {
410 out << field->type().getCppStackType()
411 << " "
412 << field->name()
413 << " __attribute__ ((aligned("
414 << fieldAlign
415 << ")));\n";
416 } else {
417 out << "static_assert(offsetof("
418 << fullName()
419 << ", "
420 << field->name()
421 << ") == "
422 << offset
423 << ", \"wrong offset\");\n";
424 }
425
Andreas Huber60d3b222017-03-30 09:10:56 -0700426 if (mStyle == STYLE_STRUCT) {
427 offset += fieldSize;
428 }
Andreas Huberca4bc892017-01-09 14:58:12 -0800429 }
430
431 if (pass == 0) {
432 out.unindent();
433 out << "};\n\n";
434 }
435 }
436
437 size_t structAlign, structSize;
438 getAlignmentAndSize(&structAlign, &structSize);
439
440 out << "static_assert(sizeof("
441 << fullName()
442 << ") == "
443 << structSize
444 << ", \"wrong size\");\n";
445
446 out << "static_assert(__alignof("
447 << fullName()
448 << ") == "
449 << structAlign
450 << ", \"wrong alignment\");\n\n";
Yifan Hong244e82d2016-11-11 11:13:57 -0800451
452 return OK;
453}
454
Timur Iskhakovfd3f2502017-09-05 16:25:02 -0700455void CompoundType::emitTypeForwardDeclaration(Formatter& out) const {
456 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union") << " " << localName() << ";\n";
457}
Yifan Hong244e82d2016-11-11 11:13:57 -0800458
Yifan Hongc6752dc2016-12-20 14:00:14 -0800459status_t CompoundType::emitGlobalTypeDeclarations(Formatter &out) const {
460 Scope::emitGlobalTypeDeclarations(out);
461
Steven Morelandbf714212017-10-27 18:29:01 -0700462 // TODO(b/65200821): remove these ifdefs
463 out << "#ifdef REALLY_IS_HIDL_INTERNAL_LIB" << gCurrentCompileName << "\n";
Steven Moreland3d98bc42017-06-23 21:36:41 +0000464 out << "std::string toString("
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800465 << getCppArgumentType()
Steven Moreland3d98bc42017-06-23 21:36:41 +0000466 << ");\n\n";
Yifan Hong42c68432017-03-13 16:22:03 -0700467 if (canCheckEquality()) {
Steven Morelandf91048a2017-06-23 21:38:35 +0000468 out << "bool operator==("
469 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
Yifan Hong42c68432017-03-13 16:22:03 -0700470
Steven Morelandf91048a2017-06-23 21:38:35 +0000471 out << "bool operator!=("
472 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
Steven Morelandbf714212017-10-27 18:29:01 -0700473 }
474 out << "#else\n";
475 out << "static inline std::string toString("
476 << getCppArgumentType()
477 << (mFields->empty() ? "" : " o")
478 << ") ";
479
480 out.block([&] {
481 // include toString for scalar types
482 out << "using ::android::hardware::toString;\n"
483 << "std::string os;\n";
484 out << "os += \"{\";\n";
485
486 for (const NamedReference<Type>* field : *mFields) {
487 out << "os += \"";
488 if (field != *(mFields->begin())) {
489 out << ", ";
490 }
491 out << "." << field->name() << " = \";\n";
492 field->type().emitDump(out, "os", "o." + field->name());
493 }
494
495 out << "os += \"}\"; return os;\n";
496 }).endl().endl();
497
498 if (canCheckEquality()) {
499 out << "static inline bool operator==("
500 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
501 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
502 out.block([&] {
503 for (const auto &field : *mFields) {
504 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
505 out << "return false;\n";
506 }).endl();
507 }
508 out << "return true;\n";
509 }).endl().endl();
510
511 out << "static inline bool operator!=("
512 << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
513 out.block([&] {
514 out << "return !(lhs == rhs);\n";
515 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -0700516 } else {
Steven Morelandf91048a2017-06-23 21:38:35 +0000517 out << "// operator== and operator!= are not generated for " << localName() << "\n\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800518 }
Steven Morelandbf714212017-10-27 18:29:01 -0700519 out << "#endif // REALLY_IS_HIDL_INTERNAL_LIB\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800520
Yifan Hongc6752dc2016-12-20 14:00:14 -0800521 return OK;
522}
523
Yifan Hong244e82d2016-11-11 11:13:57 -0800524status_t CompoundType::emitGlobalHwDeclarations(Formatter &out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700525 if (needsEmbeddedReadWrite()) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800526 out << "::android::status_t readEmbeddedFromParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700527
Yifan Hong0a68a282016-10-21 16:32:34 -0700528 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700529
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700530 out << "const " << fullName() << " &obj,\n"
Yifan Hong244e82d2016-11-11 11:13:57 -0800531 << "const ::android::hardware::Parcel &parcel,\n"
532 << "size_t parentHandle,\n"
533 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700534
Yifan Hong0a68a282016-10-21 16:32:34 -0700535 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700536
537 out << "::android::status_t writeEmbeddedToParcel(\n";
538
Yifan Hong0a68a282016-10-21 16:32:34 -0700539 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700540
Yifan Hong244e82d2016-11-11 11:13:57 -0800541 out << "const " << fullName() << " &obj,\n"
542 << "::android::hardware::Parcel *parcel,\n"
543 << "size_t parentHandle,\n"
544 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700545
Yifan Hong0a68a282016-10-21 16:32:34 -0700546 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700547 }
548
Yifan Hongbf459bc2016-08-23 16:50:37 -0700549 if(needsResolveReferences()) {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700550 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700551 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800552 out << fullName() << " *obj,\n"
553 << "const ::android::hardware::Parcel &parcel,\n"
554 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700555 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700556 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700557 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800558 out << "const " << fullName() << " &obj,\n"
559 << "::android::hardware::Parcel *,\n"
560 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700561 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700562 }
563
Andreas Huber881227d2016-08-02 14:20:21 -0700564 return OK;
565}
566
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -0700567status_t CompoundType::emitTypeDefinitions(Formatter& out, const std::string& prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -0700568 std::string space = prefix.empty() ? "" : (prefix + "::");
569 status_t err = Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700570
571 if (err != OK) {
572 return err;
573 }
574
Yifan Hongbf459bc2016-08-23 16:50:37 -0700575 if (needsEmbeddedReadWrite()) {
576 emitStructReaderWriter(out, prefix, true /* isReader */);
577 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -0700578 }
579
Yifan Hongbf459bc2016-08-23 16:50:37 -0700580 if (needsResolveReferences()) {
581 emitResolveReferenceDef(out, prefix, true /* isReader */);
582 emitResolveReferenceDef(out, prefix, false /* isReader */);
583 }
Andreas Huber881227d2016-08-02 14:20:21 -0700584
Steven Morelandbf714212017-10-27 18:29:01 -0700585 // TODO(b/65200821): remove toString + operator== from .cpp once all prebuilts are rebuilt
586
Steven Moreland3d98bc42017-06-23 21:36:41 +0000587 out << "std::string toString("
588 << getCppArgumentType()
589 << (mFields->empty() ? "" : " o")
590 << ") ";
591
592 out.block([&] {
593 // include toString for scalar types
594 out << "using ::android::hardware::toString;\n"
595 << "std::string os;\n";
596 out << "os += \"{\";\n";
597
Timur Iskhakov7fa79f62017-08-09 11:04:54 -0700598 for (const NamedReference<Type>* field : *mFields) {
Steven Moreland3d98bc42017-06-23 21:36:41 +0000599 out << "os += \"";
600 if (field != *(mFields->begin())) {
601 out << ", ";
602 }
603 out << "." << field->name() << " = \";\n";
604 field->type().emitDump(out, "os", "o." + field->name());
605 }
606
607 out << "os += \"}\"; return os;\n";
608 }).endl().endl();
609
Steven Morelandf91048a2017-06-23 21:38:35 +0000610 if (canCheckEquality()) {
611 out << "bool operator==("
612 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
613 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
614 out.block([&] {
615 for (const auto &field : *mFields) {
616 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
617 out << "return false;\n";
618 }).endl();
619 }
620 out << "return true;\n";
621 }).endl().endl();
622
623 out << "bool operator!=("
624 << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
625 out.block([&] {
626 out << "return !(lhs == rhs);\n";
627 }).endl().endl();
628 } else {
629 out << "// operator== and operator!= are not generated for " << localName() << "\n";
630 }
631
Andreas Huber881227d2016-08-02 14:20:21 -0700632 return OK;
633}
634
Andreas Huber85eabdb2016-08-25 11:24:49 -0700635status_t CompoundType::emitJavaTypeDeclarations(
636 Formatter &out, bool atTopLevel) const {
637 out << "public final ";
638
639 if (!atTopLevel) {
640 out << "static ";
641 }
642
643 out << "class "
644 << localName()
645 << " {\n";
646
647 out.indent();
648
649 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
650
651 for (const auto &field : *mFields) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700652 out << "public ";
653
654 field->type().emitJavaFieldInitializer(out, field->name());
655 }
656
657 if (!mFields->empty()) {
658 out << "\n";
659 }
660
Yifan Hongec102272016-12-20 18:10:07 -0800661 ////////////////////////////////////////////////////////////////////////////
662
663 if (canCheckEquality()) {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800664 out << "@Override\npublic final boolean equals(Object otherObject) ";
Yifan Hongec102272016-12-20 18:10:07 -0800665 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800666 out.sIf("this == otherObject", [&] {
667 out << "return true;\n";
668 }).endl();
669 out.sIf("otherObject == null", [&] {
670 out << "return false;\n";
671 }).endl();
Yifan Hong45b331b2017-03-27 12:59:54 -0700672 // Though class is final, we use getClass instead of instanceof to be explicit.
673 out.sIf("otherObject.getClass() != " + fullJavaName() + ".class", [&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800674 out << "return false;\n";
675 }).endl();
676 out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n";
Yifan Hongec102272016-12-20 18:10:07 -0800677 for (const auto &field : *mFields) {
Yifan Hong45b331b2017-03-27 12:59:54 -0700678 std::string condition = (field->type().isScalar() || field->type().isEnum())
Yifan Hongec102272016-12-20 18:10:07 -0800679 ? "this." + field->name() + " != other." + field->name()
Yifan Hong45b331b2017-03-27 12:59:54 -0700680 : ("!android.os.HidlSupport.deepEquals(this." + field->name()
Yifan Hongec102272016-12-20 18:10:07 -0800681 + ", other." + field->name() + ")");
682 out.sIf(condition, [&] {
683 out << "return false;\n";
684 }).endl();
685 }
686 out << "return true;\n";
687 }).endl().endl();
688
Yifan Hong7d1839f2017-02-22 13:24:29 -0800689 out << "@Override\npublic final int hashCode() ";
Yifan Hongec102272016-12-20 18:10:07 -0800690 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800691 out << "return java.util.Objects.hash(\n";
692 out.indent(2, [&] {
Yifan Hong932464e2017-03-30 15:40:22 -0700693 out.join(mFields->begin(), mFields->end(), ", \n", [&] (const auto &field) {
Yifan Hong45b331b2017-03-27 12:59:54 -0700694 out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")";
Yifan Hong932464e2017-03-30 15:40:22 -0700695 });
Yifan Hong7d1839f2017-02-22 13:24:29 -0800696 });
Yifan Hongec102272016-12-20 18:10:07 -0800697 out << ");\n";
698 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -0700699 } else {
700 out << "// equals() is not generated for " << localName() << "\n";
Yifan Hongec102272016-12-20 18:10:07 -0800701 }
702
703 ////////////////////////////////////////////////////////////////////////////
704
Yifan Honge45b5302017-02-22 10:49:07 -0800705 out << "@Override\npublic final String toString() ";
706 out.block([&] {
707 out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n"
708 << "builder.append(\"{\");\n";
709 for (const auto &field : *mFields) {
710 out << "builder.append(\"";
711 if (field != *(mFields->begin())) {
712 out << ", ";
713 }
714 out << "." << field->name() << " = \");\n";
715 field->type().emitJavaDump(out, "builder", "this." + field->name());
716 }
717 out << "builder.append(\"}\");\nreturn builder.toString();\n";
718 }).endl().endl();
719
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700720 size_t structAlign, structSize;
721 getAlignmentAndSize(&structAlign, &structSize);
722
Yifan Honge45b5302017-02-22 10:49:07 -0800723 ////////////////////////////////////////////////////////////////////////////
724
Yifan Hong1af73532016-11-09 14:32:58 -0800725 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700726 out.indent();
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700727 out << "android.os.HwBlob blob = parcel.readBuffer(";
728 out << structSize << "/* size */);\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700729 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
730 out.unindent();
731 out << "}\n\n";
732
Andreas Huberf630bc82016-09-09 14:52:25 -0700733 ////////////////////////////////////////////////////////////////////////////
734
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700735 size_t vecAlign, vecSize;
736 VectorType::getAlignmentAndSizeStatic(&vecAlign, &vecSize);
737
Yifan Hong1af73532016-11-09 14:32:58 -0800738 out << "public static final java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700739 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800740 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700741 out.indent();
742
Yifan Hong1af73532016-11-09 14:32:58 -0800743 out << "java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700744 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800745 << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700746
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700747 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer(";
748 out << vecSize << " /* sizeof hidl_vec<T> */);\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700749
750 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700751 out,
752 0 /* depth */,
753 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700754 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700755 "_hidl_blob",
756 "_hidl_vec",
757 "0",
758 true /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700759
Andreas Huber1b6822b2016-10-18 09:28:40 -0700760 out << "\nreturn _hidl_vec;\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700761
762 out.unindent();
763 out << "}\n\n";
764
765 ////////////////////////////////////////////////////////////////////////////
766
Andreas Huber85eabdb2016-08-25 11:24:49 -0700767 out << "public final void readEmbeddedFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700768 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800769 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700770 out.unindent();
771
772 size_t offset = 0;
773 for (const auto &field : *mFields) {
774 size_t fieldAlign, fieldSize;
775 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
776
777 size_t pad = offset % fieldAlign;
778 if (pad > 0) {
779 offset += fieldAlign - pad;
780 }
781
782 field->type().emitJavaFieldReaderWriter(
783 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700784 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700785 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700786 "_hidl_blob",
787 field->name(),
788 "_hidl_offset + " + std::to_string(offset),
789 true /* isReader */);
790
791 offset += fieldSize;
792 }
793
794 out.unindent();
795 out << "}\n\n";
796
Andreas Huberf630bc82016-09-09 14:52:25 -0700797 ////////////////////////////////////////////////////////////////////////////
798
Yifan Hong1af73532016-11-09 14:32:58 -0800799 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700800 out.indent();
801
Yifan Hong1af73532016-11-09 14:32:58 -0800802 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
Andreas Huber85eabdb2016-08-25 11:24:49 -0700803 << structSize
804 << " /* size */);\n";
805
806 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
807 << "parcel.writeBuffer(_hidl_blob);\n";
808
809 out.unindent();
810 out << "}\n\n";
811
Andreas Huberf630bc82016-09-09 14:52:25 -0700812 ////////////////////////////////////////////////////////////////////////////
813
Andreas Huberf630bc82016-09-09 14:52:25 -0700814 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700815 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800816 out << "android.os.HwParcel parcel, java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700817 << localName()
Andreas Huber1b6822b2016-10-18 09:28:40 -0700818 << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700819 out.unindent();
820
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700821 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
822 << vecSize << " /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700823
824 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700825 out,
826 0 /* depth */,
827 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700828 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700829 "_hidl_blob",
830 "_hidl_vec",
831 "0",
832 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700833
834 out << "\nparcel.writeBuffer(_hidl_blob);\n";
835
836 out.unindent();
837 out << "}\n\n";
838
839 ////////////////////////////////////////////////////////////////////////////
840
Andreas Huber85eabdb2016-08-25 11:24:49 -0700841 out << "public final void writeEmbeddedToBlob(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700842 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800843 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700844 out.unindent();
845
846 offset = 0;
847 for (const auto &field : *mFields) {
848 size_t fieldAlign, fieldSize;
849 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
850
851 size_t pad = offset % fieldAlign;
852 if (pad > 0) {
853 offset += fieldAlign - pad;
854 }
855
856 field->type().emitJavaFieldReaderWriter(
857 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700858 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700859 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700860 "_hidl_blob",
861 field->name(),
862 "_hidl_offset + " + std::to_string(offset),
863 false /* isReader */);
864
865 offset += fieldSize;
866 }
867
868 out.unindent();
869 out << "}\n";
870
871 out.unindent();
872 out << "};\n\n";
873
874 return OK;
875}
876
Andreas Huber881227d2016-08-02 14:20:21 -0700877void CompoundType::emitStructReaderWriter(
878 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800879
880 std::string space = prefix.empty() ? "" : (prefix + "::");
881
Andreas Huber881227d2016-08-02 14:20:21 -0700882 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -0800883 << (isReader ? "readEmbeddedFromParcel"
884 : "writeEmbeddedToParcel")
885 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700886
Yifan Hong0a68a282016-10-21 16:32:34 -0700887 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700888
Yifan Hong244e82d2016-11-11 11:13:57 -0800889 bool useName = false;
890 for (const auto &field : *mFields) {
891 if (field->type().useNameInEmitReaderWriterEmbedded(isReader)) {
892 useName = true;
893 break;
894 }
895 }
896 std::string name = useName ? "obj" : "/* obj */";
897 // if not useName, then obj should not be used at all,
898 // then the #error should not be emitted.
899 std::string error = useName ? "" : "\n#error\n";
900
Andreas Huber881227d2016-08-02 14:20:21 -0700901 if (isReader) {
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700902 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700903 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700904 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800905 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700906 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700907 }
908
909 out << "size_t parentHandle,\n"
910 << "size_t parentOffset)";
911
Andreas Huber881227d2016-08-02 14:20:21 -0700912 out << " {\n";
913
Yifan Hong0a68a282016-10-21 16:32:34 -0700914 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700915 out.indent();
916
Iliyan Malchev549e2592016-08-10 08:59:12 -0700917 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700918
919 for (const auto &field : *mFields) {
920 if (!field->type().needsEmbeddedReadWrite()) {
921 continue;
922 }
923
924 field->type().emitReaderWriterEmbedded(
925 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700926 0 /* depth */,
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700927 name + "." + field->name() + error,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700928 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700929 false /* nameIsPointer */,
930 "parcel",
931 !isReader /* parcelObjIsPointer */,
932 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700933 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700934 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700935 "parentOffset + offsetof("
936 + fullName()
937 + ", "
938 + field->name()
939 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700940 }
941
Iliyan Malchev549e2592016-08-10 08:59:12 -0700942 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700943
944 out.unindent();
945 out << "}\n\n";
946}
947
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -0700948void CompoundType::emitResolveReferenceDef(Formatter& out, const std::string& prefix,
949 bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800950 out << "::android::status_t ";
951 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -0700952
953 bool useParent = false;
954 for (const auto &field : *mFields) {
955 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
956 useParent = true;
957 break;
958 }
959 }
960
961 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
962 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
963
Yifan Hongbf459bc2016-08-23 16:50:37 -0700964 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800965 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700966 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800967 out << space + localName() + " *obj,\n"
968 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700969 << "size_t " << parentHandleName << ", "
970 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700971 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700972 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800973 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700974 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800975 out << "const " << space + localName() + " &obj,\n"
976 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700977 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -0800978 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700979 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700980 }
981
982 out << " {\n";
983
984 out.indent();
985
986 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
987
Yifan Hong244e82d2016-11-11 11:13:57 -0800988 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -0700989 // if not useParent, then parentName and offsetText
990 // should not be used at all, then the #error should not be emitted.
991 std::string error = useParent ? "" : "\n#error\n";
992
Yifan Hongbf459bc2016-08-23 16:50:37 -0700993 for (const auto &field : *mFields) {
994 if (!field->type().needsResolveReferences()) {
995 continue;
996 }
997
998 field->type().emitResolveReferencesEmbedded(
999 out,
1000 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -08001001 nameDeref + field->name(),
Yifan Hongbf459bc2016-08-23 16:50:37 -07001002 field->name() /* sanitizedName */,
1003 false, // nameIsPointer
1004 "parcel", // const std::string &parcelObj,
1005 !isReader, // bool parcelObjIsPointer,
1006 isReader, // bool isReader,
1007 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -07001008 parentHandleName + error,
1009 parentOffsetName
1010 + " + offsetof("
Yifan Hongbf459bc2016-08-23 16:50:37 -07001011 + fullName()
1012 + ", "
1013 + field->name()
Yifan Hong00f47172016-09-30 14:40:45 -07001014 + ")"
1015 + error);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001016 }
1017
Yifan Hongbf459bc2016-08-23 16:50:37 -07001018 out << "return _hidl_err;\n";
1019
1020 out.unindent();
1021 out << "}\n\n";
1022}
1023
Andreas Huber881227d2016-08-02 14:20:21 -07001024bool CompoundType::needsEmbeddedReadWrite() const {
1025 if (mStyle != STYLE_STRUCT) {
1026 return false;
1027 }
1028
1029 for (const auto &field : *mFields) {
1030 if (field->type().needsEmbeddedReadWrite()) {
1031 return true;
1032 }
1033 }
1034
1035 return false;
1036}
1037
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001038bool CompoundType::deepNeedsResolveReferences(std::unordered_set<const Type*>* visited) const {
Yifan Hongbf459bc2016-08-23 16:50:37 -07001039 if (mStyle != STYLE_STRUCT) {
1040 return false;
1041 }
1042
1043 for (const auto &field : *mFields) {
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001044 if (field->type().needsResolveReferences(visited)) {
Yifan Hongbf459bc2016-08-23 16:50:37 -07001045 return true;
1046 }
1047 }
1048
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001049 return Scope::deepNeedsResolveReferences(visited);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001050}
1051
Andreas Huber881227d2016-08-02 14:20:21 -07001052bool CompoundType::resultNeedsDeref() const {
1053 return true;
1054}
1055
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001056status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07001057 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001058 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001059
1060 // Emit declaration for each subtype.
1061 for (const auto &type : getSubTypes()) {
1062 switch (mStyle) {
1063 case STYLE_STRUCT:
1064 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001065 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001066 break;
1067 }
1068 case STYLE_UNION:
1069 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001070 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001071 break;
1072 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001073 }
1074 out.indent();
1075 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001076 if (status != OK) {
1077 return status;
1078 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001079 out.unindent();
1080 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001081 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001082
1083 // Emit declaration for each field.
1084 for (const auto &field : *mFields) {
1085 switch (mStyle) {
1086 case STYLE_STRUCT:
1087 {
1088 out << "struct_value: {\n";
1089 break;
1090 }
1091 case STYLE_UNION:
1092 {
1093 out << "union_value: {\n";
1094 break;
1095 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001096 }
1097 out.indent();
1098 out << "name: \"" << field->name() << "\"\n";
1099 status_t status = field->type().emitVtsAttributeType(out);
1100 if (status != OK) {
1101 return status;
1102 }
1103 out.unindent();
1104 out << "}\n";
1105 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001106
1107 return OK;
1108}
1109
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001110status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001111 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07001112 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001113 return OK;
1114}
1115
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001116bool CompoundType::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
1117 if (mStyle != STYLE_STRUCT) {
Andreas Huber0fa9e392016-08-31 09:05:44 -07001118 return false;
1119 }
1120
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001121 for (const auto* field : *mFields) {
1122 if (!field->get()->isJavaCompatible(visited)) {
Andreas Huber0fa9e392016-08-31 09:05:44 -07001123 return false;
1124 }
1125 }
1126
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001127 return Scope::deepIsJavaCompatible(visited);
Andreas Huber85eabdb2016-08-25 11:24:49 -07001128}
1129
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001130bool CompoundType::deepContainsPointer(std::unordered_set<const Type*>* visited) const {
1131 for (const auto* field : *mFields) {
1132 if (field->get()->containsPointer(visited)) {
Andreas Huber60d3b222017-03-30 09:10:56 -07001133 return true;
1134 }
1135 }
1136
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001137 return Scope::deepContainsPointer(visited);
Andreas Huber60d3b222017-03-30 09:10:56 -07001138}
1139
Andreas Huber85eabdb2016-08-25 11:24:49 -07001140void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
1141 *align = 1;
Andreas Huber60d3b222017-03-30 09:10:56 -07001142 *size = 0;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001143
1144 size_t offset = 0;
1145 for (const auto &field : *mFields) {
1146 // Each field is aligned according to its alignment requirement.
1147 // The surrounding structure's alignment is the maximum of its
1148 // fields' aligments.
1149
1150 size_t fieldAlign, fieldSize;
1151 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1152
1153 size_t pad = offset % fieldAlign;
1154 if (pad > 0) {
1155 offset += fieldAlign - pad;
1156 }
1157
Andreas Huber60d3b222017-03-30 09:10:56 -07001158 if (mStyle == STYLE_STRUCT) {
1159 offset += fieldSize;
1160 } else {
1161 *size = std::max(*size, fieldSize);
1162 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001163
1164 if (fieldAlign > (*align)) {
1165 *align = fieldAlign;
1166 }
1167 }
1168
Andreas Huber60d3b222017-03-30 09:10:56 -07001169 if (mStyle == STYLE_STRUCT) {
1170 *size = offset;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001171 }
1172
Andreas Huber60d3b222017-03-30 09:10:56 -07001173 // Final padding to account for the structure's alignment.
1174 size_t pad = (*size) % (*align);
1175 if (pad > 0) {
1176 (*size) += (*align) - pad;
1177 }
Andreas Huberca4bc892017-01-09 14:58:12 -08001178
1179 if (*size == 0) {
1180 // An empty struct still occupies a byte of space in C++.
1181 *size = 1;
1182 }
Andreas Huber70a59e12016-08-16 12:57:01 -07001183}
1184
Andreas Huberc9410c72016-07-28 12:18:40 -07001185} // namespace android
1186