blob: ddbe58178d7a0f8eed5a9fe3f9dc505aa668fae6 [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
Howard Chenecfb4512017-11-21 18:28:53 +080051 if ((type.isVector() && static_cast<const VectorType*>(&type)->isVectorOfBinders())) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070052 std::cerr << "ERROR: Struct/Union must not contain references to interfaces at "
53 << field->location() << "\n";
54 return UNKNOWN_ERROR;
Andreas Huberb95ea8a2016-08-15 15:35:42 -070055 }
56
Andreas Huber5a545442016-08-03 10:44:56 -070057 if (mStyle == STYLE_UNION) {
58 if (type.needsEmbeddedReadWrite()) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070059 std::cerr << "ERROR: Union must not contain any types that need fixup at "
60 << field->location() << "\n";
61 return UNKNOWN_ERROR;
Andreas Huber5a545442016-08-03 10:44:56 -070062 }
Andreas Huber5a545442016-08-03 10:44:56 -070063 }
64 }
65
Timur Iskhakovcec46c42017-08-09 00:22:02 -070066 status_t err = validateUniqueNames();
67 if (err != OK) return err;
68
69 return Scope::validate();
70}
71
72status_t CompoundType::validateUniqueNames() const {
73 std::unordered_set<std::string> names;
74
75 for (const auto* field : *mFields) {
76 if (names.find(field->name()) != names.end()) {
77 std::cerr << "ERROR: Redefinition of field '" << field->name() << "' at "
78 << field->location() << "\n";
79 return UNKNOWN_ERROR;
80 }
81 names.insert(field->name());
82 }
83
84 return OK;
Andreas Huberc9410c72016-07-28 12:18:40 -070085}
86
Andreas Huberf630bc82016-09-09 14:52:25 -070087bool CompoundType::isCompoundType() const {
88 return true;
89}
90
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -070091bool CompoundType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
Yifan Hongc6752dc2016-12-20 14:00:14 -080092 if (mStyle == STYLE_UNION) {
93 return false;
94 }
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -070095 for (const auto* field : *mFields) {
96 if (!field->get()->canCheckEquality(visited)) {
Yifan Hongc6752dc2016-12-20 14:00:14 -080097 return false;
98 }
99 }
100 return true;
101}
102
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700103std::string CompoundType::typeName() const {
104 switch (mStyle) {
105 case STYLE_STRUCT: {
106 return "struct " + localName();
107 }
108 case STYLE_UNION: {
109 return "union " + localName();
110 }
111 }
112 CHECK(!"Should not be here");
113}
114
Andreas Huber881227d2016-08-02 14:20:21 -0700115std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -0700116 StorageMode mode,
Steven Morelande30ee9b2017-05-09 13:31:01 -0700117 bool /* specifyNamespaces */) const {
118 const std::string base = fullName();
Andreas Huber881227d2016-08-02 14:20:21 -0700119
120 switch (mode) {
121 case StorageMode_Stack:
122 return base;
123
124 case StorageMode_Argument:
125 return "const " + base + "&";
126
127 case StorageMode_Result:
Howard Chenecfb4512017-11-21 18:28:53 +0800128 return base + (containsInterface()?"":"*");
Andreas Huber881227d2016-08-02 14:20:21 -0700129 }
130}
131
Yifan Hong4ed13472016-11-02 10:44:11 -0700132std::string CompoundType::getJavaType(bool /* forInitializer */) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700133 return fullJavaName();
134}
135
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700136std::string CompoundType::getVtsType() const {
137 switch (mStyle) {
138 case STYLE_STRUCT:
139 {
140 return "TYPE_STRUCT";
141 }
142 case STYLE_UNION:
143 {
144 return "TYPE_UNION";
145 }
146 }
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700147 CHECK(!"Should not be here");
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700148}
149
Howard Chenecfb4512017-11-21 18:28:53 +0800150bool CompoundType::containsInterface() const {
151 for (const auto& field : *mFields) {
152 if (field->type().isCompoundType()) {
153 const Type& t = field->type();
154 const CompoundType* ct = static_cast<const CompoundType*>(&t);
155 if (ct->containsInterface()) {
156 return true;
157 }
158 }
159 if (field->type().isInterface()) {
160 return true;
161 }
162 }
163 return false;
164}
165
Andreas Huber881227d2016-08-02 14:20:21 -0700166void CompoundType::emitReaderWriter(
167 Formatter &out,
168 const std::string &name,
169 const std::string &parcelObj,
170 bool parcelObjIsPointer,
171 bool isReader,
172 ErrorMode mode) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700173
174 const std::string parcelObjDeref =
175 parcelObj + (parcelObjIsPointer ? "->" : ".");
176
Howard Chenecfb4512017-11-21 18:28:53 +0800177 if(containsInterface()){
178 for (const auto& field : *mFields) {
179 field->type().emitReaderWriter(out, name + "." + field->name(),
180 parcelObj, parcelObjIsPointer, isReader, mode);
181 }
Andreas Huber881227d2016-08-02 14:20:21 -0700182 } else {
Howard Chenecfb4512017-11-21 18:28:53 +0800183 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700184
Howard Chenecfb4512017-11-21 18:28:53 +0800185 out << "size_t " << parentName << ";\n\n";
186
187 if (isReader) {
188 out << "_hidl_err = " << parcelObjDeref << "readBuffer("
189 << "sizeof(*" << name << "), &" << parentName << ", "
190 << " const_cast<const void**>(reinterpret_cast<void **>("
191 << "&" << name << ")));\n";
192 handleError(out, mode);
193 } else {
194 out << "_hidl_err = "
195 << parcelObjDeref
196 << "writeBuffer(&"
197 << name
198 << ", sizeof("
199 << name
200 << "), &"
201 << parentName
202 << ");\n";
203 handleError(out, mode);
204 }
205 if (mStyle != STYLE_STRUCT) {
206 return;
207 }
208 if (needsEmbeddedReadWrite()) {
209 emitReaderWriterEmbedded(out, 0 /* depth */, name, name, /* sanitizedName */
210 isReader /* nameIsPointer */, parcelObj, parcelObjIsPointer,
211 isReader, mode, parentName, "0 /* parentOffset */");
212 }
Andreas Huber881227d2016-08-02 14:20:21 -0700213 }
Andreas Huber881227d2016-08-02 14:20:21 -0700214}
215
216void CompoundType::emitReaderWriterEmbedded(
217 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700218 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700219 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700220 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700221 bool nameIsPointer,
222 const std::string &parcelObj,
223 bool parcelObjIsPointer,
224 bool isReader,
225 ErrorMode mode,
226 const std::string &parentName,
227 const std::string &offsetText) const {
228 emitReaderWriterEmbeddedForTypeName(
229 out,
230 name,
231 nameIsPointer,
232 parcelObj,
233 parcelObjIsPointer,
234 isReader,
235 mode,
236 parentName,
237 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700238 fullName(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800239 "" /* childName */,
240 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700241}
242
Andreas Huber85eabdb2016-08-25 11:24:49 -0700243void CompoundType::emitJavaReaderWriter(
244 Formatter &out,
245 const std::string &parcelObj,
246 const std::string &argName,
247 bool isReader) const {
248 if (isReader) {
249 out << "new " << fullJavaName() << "();\n";
250 }
251
252 out << argName
253 << "."
254 << (isReader ? "readFromParcel" : "writeToParcel")
255 << "("
256 << parcelObj
257 << ");\n";
258}
259
260void CompoundType::emitJavaFieldInitializer(
261 Formatter &out, const std::string &fieldName) const {
262 out << "final "
263 << fullJavaName()
264 << " "
265 << fieldName
266 << " = new "
267 << fullJavaName()
268 << "();\n";
269}
270
271void CompoundType::emitJavaFieldReaderWriter(
272 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700273 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700274 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700275 const std::string &blobName,
276 const std::string &fieldName,
277 const std::string &offset,
278 bool isReader) const {
279 if (isReader) {
280 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700281 << ".readEmbeddedFromParcel("
282 << parcelName
283 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700284 << blobName
285 << ", "
286 << offset
287 << ");\n";
288
289 return;
290 }
291
292 out << fieldName
293 << ".writeEmbeddedToBlob("
294 << blobName
295 << ", "
296 << offset
297 << ");\n";
298}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700299void CompoundType::emitResolveReferences(
300 Formatter &out,
301 const std::string &name,
302 bool nameIsPointer,
303 const std::string &parcelObj,
304 bool parcelObjIsPointer,
305 bool isReader,
306 ErrorMode mode) const {
307 emitResolveReferencesEmbedded(
308 out,
309 0 /* depth */,
310 name,
311 name /* sanitizedName */,
312 nameIsPointer,
313 parcelObj,
314 parcelObjIsPointer,
315 isReader,
316 mode,
317 "_hidl_" + name + "_parent",
318 "0 /* parentOffset */");
319}
320
321void CompoundType::emitResolveReferencesEmbedded(
322 Formatter &out,
323 size_t /* depth */,
324 const std::string &name,
325 const std::string &/* sanitizedName */,
326 bool nameIsPointer,
327 const std::string &parcelObj,
328 bool parcelObjIsPointer,
329 bool isReader,
330 ErrorMode mode,
331 const std::string &parentName,
332 const std::string &offsetText) const {
333 CHECK(needsResolveReferences());
334
335 const std::string parcelObjDeref =
336 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
337
338 const std::string parcelObjPointer =
339 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
340
Yifan Hong244e82d2016-11-11 11:13:57 -0800341 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700342 const std::string namePointer = nameIsPointer ? name : ("&" + name);
343
344 out << "_hidl_err = ";
345
346 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800347 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700348 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800349 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700350 }
351
Yifan Hong33223ca2016-12-13 15:07:35 -0800352 out.indent(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800353 if (isReader) {
354 out << "const_cast<"
355 << fullName()
356 << " *"
357 << ">("
358 << namePointer
359 << "),\n"
360 << parcelObjDeref;
361 } else {
362 out << nameDerefed
363 << ",\n"
364 << parcelObjPointer;
365 }
366
367 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700368 << parentName
369 << ",\n"
370 << offsetText
371 << ");\n\n";
372 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700373
374 handleError(out, mode);
375}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700376
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800377void CompoundType::emitTypeDeclarations(Formatter& out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700378 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
379 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700380 << localName()
Yifan Hongb1d2ebc2016-12-20 17:18:07 -0800381 << " final {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700382
383 out.indent();
384
385 Scope::emitTypeDeclarations(out);
386
Andreas Huber60d3b222017-03-30 09:10:56 -0700387 if (containsPointer()) {
Andreas Huberca4bc892017-01-09 14:58:12 -0800388 for (const auto &field : *mFields) {
Steven Moreland073269e2018-05-17 15:45:26 -0700389 field->emitDocComment(out);
Andreas Huberca4bc892017-01-09 14:58:12 -0800390 out << field->type().getCppStackType()
391 << " "
392 << field->name()
393 << ";\n";
394 }
395
396 out.unindent();
397 out << "};\n\n";
398
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800399 return;
Andreas Huber881227d2016-08-02 14:20:21 -0700400 }
401
Andreas Huberca4bc892017-01-09 14:58:12 -0800402 for (int pass = 0; pass < 2; ++pass) {
403 size_t offset = 0;
404 for (const auto &field : *mFields) {
405 size_t fieldAlign, fieldSize;
406 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
407
408 size_t pad = offset % fieldAlign;
409 if (pad > 0) {
410 offset += fieldAlign - pad;
411 }
412
413 if (pass == 0) {
414 out << field->type().getCppStackType()
415 << " "
416 << field->name()
417 << " __attribute__ ((aligned("
418 << fieldAlign
419 << ")));\n";
420 } else {
421 out << "static_assert(offsetof("
422 << fullName()
423 << ", "
424 << field->name()
425 << ") == "
426 << offset
427 << ", \"wrong offset\");\n";
428 }
429
Andreas Huber60d3b222017-03-30 09:10:56 -0700430 if (mStyle == STYLE_STRUCT) {
431 offset += fieldSize;
432 }
Andreas Huberca4bc892017-01-09 14:58:12 -0800433 }
434
435 if (pass == 0) {
436 out.unindent();
437 out << "};\n\n";
438 }
439 }
440
441 size_t structAlign, structSize;
442 getAlignmentAndSize(&structAlign, &structSize);
443
444 out << "static_assert(sizeof("
445 << fullName()
446 << ") == "
447 << structSize
448 << ", \"wrong size\");\n";
449
450 out << "static_assert(__alignof("
451 << fullName()
452 << ") == "
453 << structAlign
454 << ", \"wrong alignment\");\n\n";
Yifan Hong244e82d2016-11-11 11:13:57 -0800455}
456
Timur Iskhakovfd3f2502017-09-05 16:25:02 -0700457void CompoundType::emitTypeForwardDeclaration(Formatter& out) const {
458 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union") << " " << localName() << ";\n";
459}
Yifan Hong244e82d2016-11-11 11:13:57 -0800460
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800461void CompoundType::emitPackageTypeDeclarations(Formatter& out) const {
Steven Moreland4b8f7a12017-11-17 15:39:54 -0800462 Scope::emitPackageTypeDeclarations(out);
Yifan Hongc6752dc2016-12-20 14:00:14 -0800463
Steven Morelandbf714212017-10-27 18:29:01 -0700464 // TODO(b/65200821): remove these ifdefs
465 out << "#ifdef REALLY_IS_HIDL_INTERNAL_LIB" << gCurrentCompileName << "\n";
Steven Moreland3d98bc42017-06-23 21:36:41 +0000466 out << "std::string toString("
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800467 << getCppArgumentType()
Steven Moreland3d98bc42017-06-23 21:36:41 +0000468 << ");\n\n";
Yifan Hong42c68432017-03-13 16:22:03 -0700469 if (canCheckEquality()) {
Steven Morelandf91048a2017-06-23 21:38:35 +0000470 out << "bool operator==("
471 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
Yifan Hong42c68432017-03-13 16:22:03 -0700472
Steven Morelandf91048a2017-06-23 21:38:35 +0000473 out << "bool operator!=("
474 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
Steven Morelandbf714212017-10-27 18:29:01 -0700475 }
476 out << "#else\n";
477 out << "static inline std::string toString("
478 << getCppArgumentType()
479 << (mFields->empty() ? "" : " o")
480 << ") ";
481
482 out.block([&] {
483 // include toString for scalar types
484 out << "using ::android::hardware::toString;\n"
485 << "std::string os;\n";
486 out << "os += \"{\";\n";
487
488 for (const NamedReference<Type>* field : *mFields) {
489 out << "os += \"";
490 if (field != *(mFields->begin())) {
491 out << ", ";
492 }
493 out << "." << field->name() << " = \";\n";
494 field->type().emitDump(out, "os", "o." + field->name());
495 }
496
497 out << "os += \"}\"; return os;\n";
498 }).endl().endl();
499
500 if (canCheckEquality()) {
501 out << "static inline bool operator==("
502 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
503 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
504 out.block([&] {
505 for (const auto &field : *mFields) {
506 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
507 out << "return false;\n";
508 }).endl();
509 }
510 out << "return true;\n";
511 }).endl().endl();
512
513 out << "static inline bool operator!=("
514 << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
515 out.block([&] {
516 out << "return !(lhs == rhs);\n";
517 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -0700518 } else {
Steven Morelandf91048a2017-06-23 21:38:35 +0000519 out << "// operator== and operator!= are not generated for " << localName() << "\n\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800520 }
Steven Morelandbf714212017-10-27 18:29:01 -0700521 out << "#endif // REALLY_IS_HIDL_INTERNAL_LIB\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800522}
523
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800524void CompoundType::emitPackageHwDeclarations(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 }
Andreas Huber881227d2016-08-02 14:20:21 -0700563}
564
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800565void CompoundType::emitTypeDefinitions(Formatter& out, const std::string& prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -0700566 std::string space = prefix.empty() ? "" : (prefix + "::");
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800567 Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700568
Yifan Hongbf459bc2016-08-23 16:50:37 -0700569 if (needsEmbeddedReadWrite()) {
570 emitStructReaderWriter(out, prefix, true /* isReader */);
571 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -0700572 }
573
Yifan Hongbf459bc2016-08-23 16:50:37 -0700574 if (needsResolveReferences()) {
575 emitResolveReferenceDef(out, prefix, true /* isReader */);
576 emitResolveReferenceDef(out, prefix, false /* isReader */);
577 }
Andreas Huber881227d2016-08-02 14:20:21 -0700578
Steven Morelandbf714212017-10-27 18:29:01 -0700579 // TODO(b/65200821): remove toString + operator== from .cpp once all prebuilts are rebuilt
580
Steven Moreland3d98bc42017-06-23 21:36:41 +0000581 out << "std::string toString("
582 << getCppArgumentType()
583 << (mFields->empty() ? "" : " o")
584 << ") ";
585
586 out.block([&] {
587 // include toString for scalar types
588 out << "using ::android::hardware::toString;\n"
589 << "std::string os;\n";
590 out << "os += \"{\";\n";
591
Timur Iskhakov7fa79f62017-08-09 11:04:54 -0700592 for (const NamedReference<Type>* field : *mFields) {
Steven Moreland3d98bc42017-06-23 21:36:41 +0000593 out << "os += \"";
594 if (field != *(mFields->begin())) {
595 out << ", ";
596 }
597 out << "." << field->name() << " = \";\n";
598 field->type().emitDump(out, "os", "o." + field->name());
599 }
600
601 out << "os += \"}\"; return os;\n";
602 }).endl().endl();
603
Steven Morelandf91048a2017-06-23 21:38:35 +0000604 if (canCheckEquality()) {
605 out << "bool operator==("
606 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
607 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
608 out.block([&] {
609 for (const auto &field : *mFields) {
610 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
611 out << "return false;\n";
612 }).endl();
613 }
614 out << "return true;\n";
615 }).endl().endl();
616
617 out << "bool operator!=("
618 << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
619 out.block([&] {
620 out << "return !(lhs == rhs);\n";
621 }).endl().endl();
622 } else {
623 out << "// operator== and operator!= are not generated for " << localName() << "\n";
624 }
Andreas Huber881227d2016-08-02 14:20:21 -0700625}
626
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800627void CompoundType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700628 out << "public final ";
629
630 if (!atTopLevel) {
631 out << "static ";
632 }
633
634 out << "class "
635 << localName()
636 << " {\n";
637
638 out.indent();
639
640 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
641
Steven Moreland073269e2018-05-17 15:45:26 -0700642 for (const auto& field : *mFields) {
643 field->emitDocComment(out);
644
Andreas Huber85eabdb2016-08-25 11:24:49 -0700645 out << "public ";
646
647 field->type().emitJavaFieldInitializer(out, field->name());
648 }
649
650 if (!mFields->empty()) {
651 out << "\n";
652 }
653
Yifan Hongec102272016-12-20 18:10:07 -0800654 ////////////////////////////////////////////////////////////////////////////
655
656 if (canCheckEquality()) {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800657 out << "@Override\npublic final boolean equals(Object otherObject) ";
Yifan Hongec102272016-12-20 18:10:07 -0800658 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800659 out.sIf("this == otherObject", [&] {
660 out << "return true;\n";
661 }).endl();
662 out.sIf("otherObject == null", [&] {
663 out << "return false;\n";
664 }).endl();
Yifan Hong45b331b2017-03-27 12:59:54 -0700665 // Though class is final, we use getClass instead of instanceof to be explicit.
666 out.sIf("otherObject.getClass() != " + fullJavaName() + ".class", [&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800667 out << "return false;\n";
668 }).endl();
669 out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n";
Yifan Hongec102272016-12-20 18:10:07 -0800670 for (const auto &field : *mFields) {
Yifan Hong45b331b2017-03-27 12:59:54 -0700671 std::string condition = (field->type().isScalar() || field->type().isEnum())
Yifan Hongec102272016-12-20 18:10:07 -0800672 ? "this." + field->name() + " != other." + field->name()
Yifan Hong45b331b2017-03-27 12:59:54 -0700673 : ("!android.os.HidlSupport.deepEquals(this." + field->name()
Yifan Hongec102272016-12-20 18:10:07 -0800674 + ", other." + field->name() + ")");
675 out.sIf(condition, [&] {
676 out << "return false;\n";
677 }).endl();
678 }
679 out << "return true;\n";
680 }).endl().endl();
681
Yifan Hong7d1839f2017-02-22 13:24:29 -0800682 out << "@Override\npublic final int hashCode() ";
Yifan Hongec102272016-12-20 18:10:07 -0800683 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800684 out << "return java.util.Objects.hash(\n";
685 out.indent(2, [&] {
Yifan Hong932464e2017-03-30 15:40:22 -0700686 out.join(mFields->begin(), mFields->end(), ", \n", [&] (const auto &field) {
Yifan Hong45b331b2017-03-27 12:59:54 -0700687 out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")";
Yifan Hong932464e2017-03-30 15:40:22 -0700688 });
Yifan Hong7d1839f2017-02-22 13:24:29 -0800689 });
Yifan Hongec102272016-12-20 18:10:07 -0800690 out << ");\n";
691 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -0700692 } else {
693 out << "// equals() is not generated for " << localName() << "\n";
Yifan Hongec102272016-12-20 18:10:07 -0800694 }
695
696 ////////////////////////////////////////////////////////////////////////////
697
Yifan Honge45b5302017-02-22 10:49:07 -0800698 out << "@Override\npublic final String toString() ";
699 out.block([&] {
700 out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n"
701 << "builder.append(\"{\");\n";
702 for (const auto &field : *mFields) {
703 out << "builder.append(\"";
704 if (field != *(mFields->begin())) {
705 out << ", ";
706 }
707 out << "." << field->name() << " = \");\n";
708 field->type().emitJavaDump(out, "builder", "this." + field->name());
709 }
710 out << "builder.append(\"}\");\nreturn builder.toString();\n";
711 }).endl().endl();
712
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700713 size_t structAlign, structSize;
714 getAlignmentAndSize(&structAlign, &structSize);
715
Yifan Honge45b5302017-02-22 10:49:07 -0800716 ////////////////////////////////////////////////////////////////////////////
717
Yifan Hong1af73532016-11-09 14:32:58 -0800718 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700719 out.indent();
Howard Chenaf084db2017-12-27 18:46:39 +0800720 if (containsInterface()) {
721 for (const auto& field : *mFields) {
722 out << field->name() << " = ";
723 field->type().emitJavaReaderWriter(out, "parcel", field->name(), true);
724 }
725 } else {
726 out << "android.os.HwBlob blob = parcel.readBuffer(";
727 out << structSize << "/* size */);\n";
728 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
729 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700730 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
Howard Chenaf084db2017-12-27 18:46:39 +0800738 out << "public static final java.util.ArrayList<" << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800739 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700740 out.indent();
741
Howard Chenaf084db2017-12-27 18:46:39 +0800742 out << "java.util.ArrayList<" << localName() << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700743
Howard Chenaf084db2017-12-27 18:46:39 +0800744 if (containsInterface()) {
745 out << "int size = parcel.readInt32();\n";
746 out << "for(int i = 0 ; i < size; i ++) {\n";
747 out.indent();
748 out << fullJavaName() << " tmp = ";
749 emitJavaReaderWriter(out, "parcel", "tmp", true);
750 out << "_hidl_vec.add(tmp);\n";
751 out.unindent();
752 out << "}\n";
753 } else {
754 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer(";
755 out << vecSize << " /* sizeof hidl_vec<T> */);\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700756
Howard Chenaf084db2017-12-27 18:46:39 +0800757 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel",
758 "_hidl_blob", "_hidl_vec", "0",
759 true /* isReader */);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700760 }
Howard Chenaf084db2017-12-27 18:46:39 +0800761 out << "\nreturn _hidl_vec;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700762 out.unindent();
763 out << "}\n\n";
Howard Chenaf084db2017-12-27 18:46:39 +0800764 ////////////////////////////////////////////////////////////////////////////
765 if (containsInterface()) {
766 out << "// readEmbeddedFromParcel is not generated()\n";
767 } else {
768 out << "public final void readEmbeddedFromParcel(\n";
769 out.indent(2);
770 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
771 out.unindent();
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, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
784 "_hidl_offset + " + std::to_string(offset), true /* isReader */);
785 offset += fieldSize;
786 }
787 out.unindent();
788 out << "}\n\n";
789 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700790
Andreas Huberf630bc82016-09-09 14:52:25 -0700791 ////////////////////////////////////////////////////////////////////////////
792
Yifan Hong1af73532016-11-09 14:32:58 -0800793 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700794 out.indent();
795
Howard Chenaf084db2017-12-27 18:46:39 +0800796 if (containsInterface()) {
797 for (const auto& field : *mFields) {
798 field->type().emitJavaReaderWriter(out, "parcel", field->name(), false);
799 }
800 } else {
801 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(" << structSize
802 << " /* size */);\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700803
Howard Chenaf084db2017-12-27 18:46:39 +0800804 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
805 << "parcel.writeBuffer(_hidl_blob);\n";
806 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700807 out.unindent();
808 out << "}\n\n";
809
Andreas Huberf630bc82016-09-09 14:52:25 -0700810 ////////////////////////////////////////////////////////////////////////////
811
Andreas Huberf630bc82016-09-09 14:52:25 -0700812 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700813 out.indent(2);
Howard Chenaf084db2017-12-27 18:46:39 +0800814 out << "android.os.HwParcel parcel, java.util.ArrayList<" << localName() << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700815 out.unindent();
816
Howard Chenaf084db2017-12-27 18:46:39 +0800817 if (containsInterface()) {
818 out << "parcel.writeInt32(_hidl_vec.size());\n";
819 out << "for(" << fullJavaName() << " tmp: _hidl_vec)\n";
820 out.indent();
821 emitJavaReaderWriter(out, "parcel", "tmp", false);
822 out.unindent();
823 } else {
824 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(" << vecSize
825 << " /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700826
Howard Chenaf084db2017-12-27 18:46:39 +0800827 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel",
828 "_hidl_blob", "_hidl_vec", "0",
829 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700830
Howard Chenaf084db2017-12-27 18:46:39 +0800831 out << "\nparcel.writeBuffer(_hidl_blob);\n";
832 }
Andreas Huberf630bc82016-09-09 14:52:25 -0700833 out.unindent();
834 out << "}\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700835 ////////////////////////////////////////////////////////////////////////////
836
Howard Chenaf084db2017-12-27 18:46:39 +0800837 if (containsInterface()) {
838 out << "// writeEmbeddedFromParcel() is not generated\n";
839 } else {
840 out << "public final void writeEmbeddedToBlob(\n";
841 out.indent(2);
842 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
843 out.unindent();
844 size_t offset = 0;
845 for (const auto& field : *mFields) {
846 size_t fieldAlign, fieldSize;
847 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
848 size_t pad = offset % fieldAlign;
849 if (pad > 0) {
850 offset += fieldAlign - pad;
851 }
852 field->type().emitJavaFieldReaderWriter(
853 out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
854 "_hidl_offset + " + std::to_string(offset), false /* isReader */);
855 offset += fieldSize;
Andreas Huber85eabdb2016-08-25 11:24:49 -0700856 }
857
Howard Chenaf084db2017-12-27 18:46:39 +0800858 out.unindent();
859 out << "}\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700860 }
861
862 out.unindent();
Andreas Huber85eabdb2016-08-25 11:24:49 -0700863 out << "};\n\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700864}
865
Andreas Huber881227d2016-08-02 14:20:21 -0700866void CompoundType::emitStructReaderWriter(
867 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800868
869 std::string space = prefix.empty() ? "" : (prefix + "::");
870
Andreas Huber881227d2016-08-02 14:20:21 -0700871 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -0800872 << (isReader ? "readEmbeddedFromParcel"
873 : "writeEmbeddedToParcel")
874 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700875
Yifan Hong0a68a282016-10-21 16:32:34 -0700876 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700877
Yifan Hong244e82d2016-11-11 11:13:57 -0800878 bool useName = false;
879 for (const auto &field : *mFields) {
880 if (field->type().useNameInEmitReaderWriterEmbedded(isReader)) {
881 useName = true;
882 break;
883 }
884 }
885 std::string name = useName ? "obj" : "/* obj */";
886 // if not useName, then obj should not be used at all,
887 // then the #error should not be emitted.
888 std::string error = useName ? "" : "\n#error\n";
889
Andreas Huber881227d2016-08-02 14:20:21 -0700890 if (isReader) {
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700891 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700892 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700893 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800894 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700895 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700896 }
897
898 out << "size_t parentHandle,\n"
899 << "size_t parentOffset)";
900
Andreas Huber881227d2016-08-02 14:20:21 -0700901 out << " {\n";
902
Yifan Hong0a68a282016-10-21 16:32:34 -0700903 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700904 out.indent();
905
Iliyan Malchev549e2592016-08-10 08:59:12 -0700906 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700907
908 for (const auto &field : *mFields) {
909 if (!field->type().needsEmbeddedReadWrite()) {
910 continue;
911 }
912
913 field->type().emitReaderWriterEmbedded(
914 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700915 0 /* depth */,
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700916 name + "." + field->name() + error,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700917 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700918 false /* nameIsPointer */,
919 "parcel",
920 !isReader /* parcelObjIsPointer */,
921 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700922 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700923 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700924 "parentOffset + offsetof("
925 + fullName()
926 + ", "
927 + field->name()
928 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700929 }
930
Iliyan Malchev549e2592016-08-10 08:59:12 -0700931 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700932
933 out.unindent();
934 out << "}\n\n";
935}
936
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -0700937void CompoundType::emitResolveReferenceDef(Formatter& out, const std::string& prefix,
938 bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800939 out << "::android::status_t ";
940 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -0700941
942 bool useParent = false;
943 for (const auto &field : *mFields) {
944 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
945 useParent = true;
946 break;
947 }
948 }
949
950 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
951 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
952
Yifan Hongbf459bc2016-08-23 16:50:37 -0700953 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800954 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700955 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800956 out << space + localName() + " *obj,\n"
957 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700958 << "size_t " << parentHandleName << ", "
959 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700960 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700961 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800962 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700963 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800964 out << "const " << space + localName() + " &obj,\n"
965 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700966 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -0800967 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700968 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700969 }
970
971 out << " {\n";
972
973 out.indent();
974
975 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
976
Yifan Hong244e82d2016-11-11 11:13:57 -0800977 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -0700978 // if not useParent, then parentName and offsetText
979 // should not be used at all, then the #error should not be emitted.
980 std::string error = useParent ? "" : "\n#error\n";
981
Yifan Hongbf459bc2016-08-23 16:50:37 -0700982 for (const auto &field : *mFields) {
983 if (!field->type().needsResolveReferences()) {
984 continue;
985 }
986
987 field->type().emitResolveReferencesEmbedded(
988 out,
989 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -0800990 nameDeref + field->name(),
Yifan Hongbf459bc2016-08-23 16:50:37 -0700991 field->name() /* sanitizedName */,
992 false, // nameIsPointer
993 "parcel", // const std::string &parcelObj,
994 !isReader, // bool parcelObjIsPointer,
995 isReader, // bool isReader,
996 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -0700997 parentHandleName + error,
998 parentOffsetName
999 + " + offsetof("
Yifan Hongbf459bc2016-08-23 16:50:37 -07001000 + fullName()
1001 + ", "
1002 + field->name()
Yifan Hong00f47172016-09-30 14:40:45 -07001003 + ")"
1004 + error);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001005 }
1006
Yifan Hongbf459bc2016-08-23 16:50:37 -07001007 out << "return _hidl_err;\n";
1008
1009 out.unindent();
1010 out << "}\n\n";
1011}
1012
Andreas Huber881227d2016-08-02 14:20:21 -07001013bool CompoundType::needsEmbeddedReadWrite() const {
1014 if (mStyle != STYLE_STRUCT) {
1015 return false;
1016 }
1017
1018 for (const auto &field : *mFields) {
1019 if (field->type().needsEmbeddedReadWrite()) {
1020 return true;
1021 }
1022 }
1023
1024 return false;
1025}
1026
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001027bool CompoundType::deepNeedsResolveReferences(std::unordered_set<const Type*>* visited) const {
Yifan Hongbf459bc2016-08-23 16:50:37 -07001028 if (mStyle != STYLE_STRUCT) {
1029 return false;
1030 }
1031
1032 for (const auto &field : *mFields) {
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001033 if (field->type().needsResolveReferences(visited)) {
Yifan Hongbf459bc2016-08-23 16:50:37 -07001034 return true;
1035 }
1036 }
1037
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001038 return Scope::deepNeedsResolveReferences(visited);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001039}
1040
Andreas Huber881227d2016-08-02 14:20:21 -07001041bool CompoundType::resultNeedsDeref() const {
Howard Chenecfb4512017-11-21 18:28:53 +08001042 return !containsInterface() ;
Andreas Huber881227d2016-08-02 14:20:21 -07001043}
1044
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001045void CompoundType::emitVtsTypeDeclarations(Formatter& out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07001046 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001047 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001048
1049 // Emit declaration for each subtype.
1050 for (const auto &type : getSubTypes()) {
1051 switch (mStyle) {
1052 case STYLE_STRUCT:
1053 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001054 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001055 break;
1056 }
1057 case STYLE_UNION:
1058 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001059 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001060 break;
1061 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001062 }
1063 out.indent();
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001064 type->emitVtsTypeDeclarations(out);
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001065 out.unindent();
1066 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001067 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001068
1069 // Emit declaration for each field.
1070 for (const auto &field : *mFields) {
1071 switch (mStyle) {
1072 case STYLE_STRUCT:
1073 {
1074 out << "struct_value: {\n";
1075 break;
1076 }
1077 case STYLE_UNION:
1078 {
1079 out << "union_value: {\n";
1080 break;
1081 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001082 }
1083 out.indent();
1084 out << "name: \"" << field->name() << "\"\n";
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001085 field->type().emitVtsAttributeType(out);
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001086 out.unindent();
1087 out << "}\n";
1088 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001089}
1090
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001091void CompoundType::emitVtsAttributeType(Formatter& out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001092 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07001093 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001094}
1095
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001096bool CompoundType::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
1097 if (mStyle != STYLE_STRUCT) {
Andreas Huber0fa9e392016-08-31 09:05:44 -07001098 return false;
1099 }
1100
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001101 for (const auto* field : *mFields) {
1102 if (!field->get()->isJavaCompatible(visited)) {
Andreas Huber0fa9e392016-08-31 09:05:44 -07001103 return false;
1104 }
1105 }
1106
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001107 return Scope::deepIsJavaCompatible(visited);
Andreas Huber85eabdb2016-08-25 11:24:49 -07001108}
1109
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001110bool CompoundType::deepContainsPointer(std::unordered_set<const Type*>* visited) const {
1111 for (const auto* field : *mFields) {
1112 if (field->get()->containsPointer(visited)) {
Andreas Huber60d3b222017-03-30 09:10:56 -07001113 return true;
1114 }
1115 }
1116
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001117 return Scope::deepContainsPointer(visited);
Andreas Huber60d3b222017-03-30 09:10:56 -07001118}
1119
Andreas Huber85eabdb2016-08-25 11:24:49 -07001120void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
1121 *align = 1;
Andreas Huber60d3b222017-03-30 09:10:56 -07001122 *size = 0;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001123
1124 size_t offset = 0;
1125 for (const auto &field : *mFields) {
1126 // Each field is aligned according to its alignment requirement.
1127 // The surrounding structure's alignment is the maximum of its
1128 // fields' aligments.
1129
1130 size_t fieldAlign, fieldSize;
1131 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1132
1133 size_t pad = offset % fieldAlign;
1134 if (pad > 0) {
1135 offset += fieldAlign - pad;
1136 }
1137
Andreas Huber60d3b222017-03-30 09:10:56 -07001138 if (mStyle == STYLE_STRUCT) {
1139 offset += fieldSize;
1140 } else {
1141 *size = std::max(*size, fieldSize);
1142 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001143
1144 if (fieldAlign > (*align)) {
1145 *align = fieldAlign;
1146 }
1147 }
1148
Andreas Huber60d3b222017-03-30 09:10:56 -07001149 if (mStyle == STYLE_STRUCT) {
1150 *size = offset;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001151 }
1152
Andreas Huber60d3b222017-03-30 09:10:56 -07001153 // Final padding to account for the structure's alignment.
1154 size_t pad = (*size) % (*align);
1155 if (pad > 0) {
1156 (*size) += (*align) - pad;
1157 }
Andreas Huberca4bc892017-01-09 14:58:12 -08001158
1159 if (*size == 0) {
1160 // An empty struct still occupies a byte of space in C++.
1161 *size = 1;
1162 }
Andreas Huber70a59e12016-08-16 12:57:01 -07001163}
1164
Andreas Huberc9410c72016-07-28 12:18:40 -07001165} // namespace android
1166