blob: 6908317b1c1982b44520088b355cd7a566e55bc4 [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"
Nirav Atre45e76d52018-06-04 11:49:14 -070020#include "ScalarType.h"
Andreas Huberf630bc82016-09-09 14:52:25 -070021#include "VectorType.h"
Timur Iskhakovcec46c42017-08-09 00:22:02 -070022
Andreas Huber5a545442016-08-03 10:44:56 -070023#include <android-base/logging.h>
Timur Iskhakovcec46c42017-08-09 00:22:02 -070024#include <hidl-util/Formatter.h>
Timur Iskhakove8ee6a02017-09-06 11:42:10 -070025#include <iostream>
Timur Iskhakovcec46c42017-08-09 00:22:02 -070026#include <unordered_set>
Andreas Huber5a545442016-08-03 10:44:56 -070027
Andreas Huberc9410c72016-07-28 12:18:40 -070028namespace android {
29
Timur Iskhakov565b0132017-09-06 18:07:11 -070030CompoundType::CompoundType(Style style, const char* localName, const FQName& fullName,
31 const Location& location, Scope* parent)
Yi Kong56758da2018-07-24 16:21:37 -070032 : Scope(localName, fullName, location, parent), mStyle(style), mFields(nullptr) {}
Andreas Huberc9410c72016-07-28 12:18:40 -070033
Yifan Hong27e85db2016-11-09 15:45:52 -080034CompoundType::Style CompoundType::style() const {
35 return mStyle;
36}
37
Timur Iskhakovcec46c42017-08-09 00:22:02 -070038void CompoundType::setFields(std::vector<NamedReference<Type>*>* fields) {
Andreas Huberc9410c72016-07-28 12:18:40 -070039 mFields = fields;
Timur Iskhakovcec46c42017-08-09 00:22:02 -070040}
Andreas Huber5a545442016-08-03 10:44:56 -070041
Timur Iskhakovb58f4182017-08-29 15:19:24 -070042std::vector<const Reference<Type>*> CompoundType::getReferences() const {
43 std::vector<const Reference<Type>*> ret;
44 ret.insert(ret.begin(), mFields->begin(), mFields->end());
Timur Iskhakov33431e62017-08-21 17:31:23 -070045 return ret;
Timur Iskhakovcec46c42017-08-09 00:22:02 -070046}
47
48status_t CompoundType::validate() const {
49 for (const auto* field : *mFields) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070050 const Type& type = field->type();
Andreas Huber5a545442016-08-03 10:44:56 -070051
Howard Chenecfb4512017-11-21 18:28:53 +080052 if ((type.isVector() && static_cast<const VectorType*>(&type)->isVectorOfBinders())) {
Steven Morelandd927e5c2018-07-10 16:03:43 -070053 std::cerr << "ERROR: Struct/union cannot contain vectors of interfaces at "
Timur Iskhakovcec46c42017-08-09 00:22:02 -070054 << field->location() << "\n";
55 return UNKNOWN_ERROR;
Andreas Huberb95ea8a2016-08-15 15:35:42 -070056 }
57
Andreas Huber5a545442016-08-03 10:44:56 -070058 if (mStyle == STYLE_UNION) {
Steven Morelandd927e5c2018-07-10 16:03:43 -070059 if (type.isBinder()) {
60 std::cerr << "ERROR: Union cannot contain interfaces at " << field->location()
61 << "\n";
62 return UNKNOWN_ERROR;
63 }
64
Andreas Huber5a545442016-08-03 10:44:56 -070065 if (type.needsEmbeddedReadWrite()) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070066 std::cerr << "ERROR: Union must not contain any types that need fixup at "
67 << field->location() << "\n";
68 return UNKNOWN_ERROR;
Andreas Huber5a545442016-08-03 10:44:56 -070069 }
Andreas Huber5a545442016-08-03 10:44:56 -070070 }
71 }
72
Steven Moreland5dec82f2018-10-10 13:33:29 -070073 if (mStyle == STYLE_SAFE_UNION && mFields->size() < 2) {
74 std::cerr << "ERROR: Safe union must contain at least two types to be useful at "
75 << location() << "\n";
76 return UNKNOWN_ERROR;
77 }
78
Timur Iskhakovcec46c42017-08-09 00:22:02 -070079 status_t err = validateUniqueNames();
80 if (err != OK) return err;
81
Nirav Atre45e76d52018-06-04 11:49:14 -070082 err = validateSubTypeNames();
83 if (err != OK) return err;
84
Timur Iskhakovcec46c42017-08-09 00:22:02 -070085 return Scope::validate();
86}
87
88status_t CompoundType::validateUniqueNames() const {
89 std::unordered_set<std::string> names;
90
91 for (const auto* field : *mFields) {
92 if (names.find(field->name()) != names.end()) {
93 std::cerr << "ERROR: Redefinition of field '" << field->name() << "' at "
94 << field->location() << "\n";
95 return UNKNOWN_ERROR;
96 }
97 names.insert(field->name());
98 }
99
100 return OK;
Andreas Huberc9410c72016-07-28 12:18:40 -0700101}
102
Nirav Atre45e76d52018-06-04 11:49:14 -0700103void CompoundType::emitInvalidSubTypeNamesError(const std::string& subTypeName,
104 const Location& location) const {
105 std::cerr << "ERROR: Type name '" << subTypeName << "' defined at "
106 << location << " conflicts with a member function of "
107 << "safe_union " << localName() << ". Consider renaming or "
108 << "moving its definition outside the safe_union scope.\n";
109}
110
111status_t CompoundType::validateSubTypeNames() const {
112 if (mStyle != STYLE_SAFE_UNION) { return OK; }
113 const auto& subTypes = Scope::getSubTypes();
114
115 for (const auto& subType : subTypes) {
116 if (subType->localName() == "getDiscriminator") {
117 emitInvalidSubTypeNamesError(subType->localName(),
118 subType->location());
119 return UNKNOWN_ERROR;
120 }
121 }
122
123 return OK;
124}
125
Andreas Huberf630bc82016-09-09 14:52:25 -0700126bool CompoundType::isCompoundType() const {
127 return true;
128}
129
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700130bool CompoundType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
Yifan Hongc6752dc2016-12-20 14:00:14 -0800131 if (mStyle == STYLE_UNION) {
132 return false;
133 }
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700134 for (const auto* field : *mFields) {
135 if (!field->get()->canCheckEquality(visited)) {
Yifan Hongc6752dc2016-12-20 14:00:14 -0800136 return false;
137 }
138 }
139 return true;
140}
141
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700142std::string CompoundType::typeName() const {
143 switch (mStyle) {
144 case STYLE_STRUCT: {
145 return "struct " + localName();
146 }
147 case STYLE_UNION: {
148 return "union " + localName();
149 }
Nirav Atre45e76d52018-06-04 11:49:14 -0700150 case STYLE_SAFE_UNION: {
151 return "safe_union " + localName();
152 }
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700153 }
154 CHECK(!"Should not be here");
155}
156
Andreas Huber881227d2016-08-02 14:20:21 -0700157std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -0700158 StorageMode mode,
Steven Morelande30ee9b2017-05-09 13:31:01 -0700159 bool /* specifyNamespaces */) const {
160 const std::string base = fullName();
Andreas Huber881227d2016-08-02 14:20:21 -0700161
162 switch (mode) {
163 case StorageMode_Stack:
164 return base;
165
166 case StorageMode_Argument:
167 return "const " + base + "&";
168
169 case StorageMode_Result:
Howard Chenecfb4512017-11-21 18:28:53 +0800170 return base + (containsInterface()?"":"*");
Andreas Huber881227d2016-08-02 14:20:21 -0700171 }
Nirav Atre45e76d52018-06-04 11:49:14 -0700172 CHECK(!"Should not be here");
Andreas Huber881227d2016-08-02 14:20:21 -0700173}
174
Yifan Hong4ed13472016-11-02 10:44:11 -0700175std::string CompoundType::getJavaType(bool /* forInitializer */) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700176 return fullJavaName();
177}
178
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700179std::string CompoundType::getVtsType() const {
180 switch (mStyle) {
181 case STYLE_STRUCT:
182 {
183 return "TYPE_STRUCT";
184 }
185 case STYLE_UNION:
186 {
187 return "TYPE_UNION";
188 }
Nirav Atre45e76d52018-06-04 11:49:14 -0700189 case STYLE_SAFE_UNION:
190 {
191 return "TYPE_SAFE_UNION";
192 }
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700193 }
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700194 CHECK(!"Should not be here");
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700195}
196
Howard Chenecfb4512017-11-21 18:28:53 +0800197bool CompoundType::containsInterface() const {
198 for (const auto& field : *mFields) {
199 if (field->type().isCompoundType()) {
200 const Type& t = field->type();
201 const CompoundType* ct = static_cast<const CompoundType*>(&t);
202 if (ct->containsInterface()) {
203 return true;
204 }
205 }
206 if (field->type().isInterface()) {
207 return true;
208 }
209 }
210 return false;
211}
212
Nirav Atree3cae852018-07-16 12:19:16 -0700213void CompoundType::emitSafeUnionUnknownDiscriminatorError(Formatter& out,
214 const std::string& value) const {
Steven Moreland9b37ed12018-10-25 11:10:57 -0700215 out << "::android::hardware::details::logAlwaysFatal((\n";
Nirav Atree3cae852018-07-16 12:19:16 -0700216 out.indent(2, [&] {
217 out << "\"Unknown union discriminator (value: \" +\n"
218 << "std::to_string(" << getUnionDiscriminatorType()->getCppTypeCast(value)
219 << ") + \").\").c_str());\n";
220 });
221}
222
Nirav Atreca7a5022018-06-29 20:43:49 -0700223void CompoundType::emitSafeUnionReaderWriterForInterfaces(
224 Formatter &out,
225 const std::string &name,
226 const std::string &parcelObj,
227 bool parcelObjIsPointer,
228 bool isReader,
229 ErrorMode mode) const {
230
231 CHECK(mStyle == STYLE_SAFE_UNION);
Nirav Atreca7a5022018-06-29 20:43:49 -0700232
233 out.block([&] {
234 const auto discriminatorType = getUnionDiscriminatorType();
235 if (isReader) {
236 out << discriminatorType->getCppStackType()
237 << " _hidl_d_primitive;\n";
238 } else {
239 out << "const "
240 << discriminatorType->getCppStackType()
241 << " _hidl_d_primitive = "
242 << discriminatorType->getCppTypeCast(name + ".getDiscriminator()")
243 << ";\n";
244 }
245
246 getUnionDiscriminatorType()->emitReaderWriter(out, "_hidl_d_primitive", parcelObj,
247 parcelObjIsPointer, isReader, mode);
248 out << "switch (("
249 << fullName()
250 << "::hidl_discriminator) _hidl_d_primitive) ";
251
252 out.block([&] {
253 for (const auto& field : *mFields) {
254 out << "case "
255 << fullName()
256 << "::hidl_discriminator::"
257 << field->name()
258 << ": ";
259
260 const std::string tempFieldName = "_hidl_temp_" + field->name();
261 out.block([&] {
262 if (isReader) {
263 out << field->type().getCppResultType()
264 << " "
265 << tempFieldName
266 << ";\n";
267
268 field->type().emitReaderWriter(out, tempFieldName, parcelObj,
269 parcelObjIsPointer, isReader, mode);
270
271 const std::string derefOperator = field->type().resultNeedsDeref()
272 ? "*" : "";
273 out << name
274 << "."
275 << field->name()
Nirav Atre64868d32018-07-15 19:15:18 -0700276 << "(std::move("
Nirav Atreca7a5022018-06-29 20:43:49 -0700277 << derefOperator
278 << tempFieldName
Nirav Atre64868d32018-07-15 19:15:18 -0700279 << "));\n";
Nirav Atreca7a5022018-06-29 20:43:49 -0700280 } else {
281 const std::string fieldValue = name + "." + field->name() + "()";
282 out << field->type().getCppArgumentType()
283 << " "
284 << tempFieldName
285 << " = "
286 << fieldValue
287 << ";\n";
288
289 field->type().emitReaderWriter(out, tempFieldName, parcelObj,
290 parcelObjIsPointer, isReader, mode);
291 }
292 out << "break;\n";
293 }).endl();
294 }
295
Nirav Atreca7a5022018-06-29 20:43:49 -0700296 out << "default: ";
Nirav Atree3cae852018-07-16 12:19:16 -0700297 out.block([&] { emitSafeUnionUnknownDiscriminatorError(out, "_hidl_d_primitive"); })
298 .endl();
Nirav Atreca7a5022018-06-29 20:43:49 -0700299 }).endl();
300 }).endl();
301}
302
Andreas Huber881227d2016-08-02 14:20:21 -0700303void CompoundType::emitReaderWriter(
304 Formatter &out,
305 const std::string &name,
306 const std::string &parcelObj,
307 bool parcelObjIsPointer,
308 bool isReader,
309 ErrorMode mode) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700310
311 const std::string parcelObjDeref =
312 parcelObj + (parcelObjIsPointer ? "->" : ".");
313
Howard Chenecfb4512017-11-21 18:28:53 +0800314 if(containsInterface()){
Nirav Atreca7a5022018-06-29 20:43:49 -0700315 if (mStyle == STYLE_SAFE_UNION) {
316 emitSafeUnionReaderWriterForInterfaces(out, name, parcelObj,
317 parcelObjIsPointer,
318 isReader, mode);
319 return;
320 }
321
Howard Chenecfb4512017-11-21 18:28:53 +0800322 for (const auto& field : *mFields) {
Nirav Atre1d565622018-07-13 15:41:21 -0700323 const std::string tempFieldName = "_hidl_temp_" + field->name();
324 const std::string fieldValue = name + "." + field->name();
325
326 out.block([&] {
327 if (isReader) {
328 out << field->type().getCppResultType()
329 << " "
330 << tempFieldName
331 << ";\n";
332 } else {
333 out << field->type().getCppArgumentType()
334 << " "
335 << tempFieldName
336 << " = "
337 << fieldValue
338 << ";\n";
339 }
340
341 field->type().emitReaderWriter(out, tempFieldName, parcelObj,
342 parcelObjIsPointer, isReader, mode);
343 if (isReader) {
344 const std::string derefOperator = field->type().resultNeedsDeref()
345 ? "*" : "";
346 out << fieldValue
347 << " = std::move("
348 << derefOperator
349 << tempFieldName
350 << ");\n";
351 }
352 }).endl();
Howard Chenecfb4512017-11-21 18:28:53 +0800353 }
Andreas Huber881227d2016-08-02 14:20:21 -0700354 } else {
Howard Chenecfb4512017-11-21 18:28:53 +0800355 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700356
Howard Chenecfb4512017-11-21 18:28:53 +0800357 out << "size_t " << parentName << ";\n\n";
358
359 if (isReader) {
360 out << "_hidl_err = " << parcelObjDeref << "readBuffer("
361 << "sizeof(*" << name << "), &" << parentName << ", "
362 << " const_cast<const void**>(reinterpret_cast<void **>("
363 << "&" << name << ")));\n";
364 handleError(out, mode);
365 } else {
366 out << "_hidl_err = "
367 << parcelObjDeref
368 << "writeBuffer(&"
369 << name
370 << ", sizeof("
371 << name
372 << "), &"
373 << parentName
374 << ");\n";
375 handleError(out, mode);
376 }
Nirav Atre45e76d52018-06-04 11:49:14 -0700377
378 bool needEmbeddedReadWrite = needsEmbeddedReadWrite();
379 CHECK(mStyle != STYLE_UNION || !needEmbeddedReadWrite);
380
381 if (needEmbeddedReadWrite) {
Howard Chenecfb4512017-11-21 18:28:53 +0800382 emitReaderWriterEmbedded(out, 0 /* depth */, name, name, /* sanitizedName */
383 isReader /* nameIsPointer */, parcelObj, parcelObjIsPointer,
384 isReader, mode, parentName, "0 /* parentOffset */");
385 }
Andreas Huber881227d2016-08-02 14:20:21 -0700386 }
Andreas Huber881227d2016-08-02 14:20:21 -0700387}
388
389void CompoundType::emitReaderWriterEmbedded(
390 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700391 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700392 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700393 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700394 bool nameIsPointer,
395 const std::string &parcelObj,
396 bool parcelObjIsPointer,
397 bool isReader,
398 ErrorMode mode,
399 const std::string &parentName,
400 const std::string &offsetText) const {
401 emitReaderWriterEmbeddedForTypeName(
402 out,
403 name,
404 nameIsPointer,
405 parcelObj,
406 parcelObjIsPointer,
407 isReader,
408 mode,
409 parentName,
410 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700411 fullName(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800412 "" /* childName */,
413 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700414}
415
Andreas Huber85eabdb2016-08-25 11:24:49 -0700416void CompoundType::emitJavaReaderWriter(
417 Formatter &out,
418 const std::string &parcelObj,
419 const std::string &argName,
420 bool isReader) const {
421 if (isReader) {
422 out << "new " << fullJavaName() << "();\n";
423 }
424
Steven Morelandc22e8122018-10-10 13:06:39 -0700425 out << "(" << getJavaTypeCast(argName) << ")."
426 << (isReader ? "readFromParcel" : "writeToParcel") << "(" << parcelObj << ");\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700427}
428
429void CompoundType::emitJavaFieldInitializer(
430 Formatter &out, const std::string &fieldName) const {
Nirav Atre1d565622018-07-13 15:41:21 -0700431 const std::string fieldDeclaration = fullJavaName() + " " + fieldName;
Nirav Atre66842a92018-06-28 18:14:13 -0700432 emitJavaFieldDefaultInitialValue(out, fieldDeclaration);
433}
434
435void CompoundType::emitJavaFieldDefaultInitialValue(
436 Formatter &out, const std::string &declaredFieldName) const {
437 out << declaredFieldName
Andreas Huber85eabdb2016-08-25 11:24:49 -0700438 << " = new "
439 << fullJavaName()
440 << "();\n";
441}
442
443void CompoundType::emitJavaFieldReaderWriter(
444 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700445 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700446 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700447 const std::string &blobName,
448 const std::string &fieldName,
449 const std::string &offset,
450 bool isReader) const {
451 if (isReader) {
Nirav Atre66842a92018-06-28 18:14:13 -0700452 out << "("
453 << getJavaTypeCast(fieldName)
454 << ").readEmbeddedFromParcel("
Andreas Huber709b62d2016-09-19 11:21:18 -0700455 << parcelName
456 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700457 << blobName
458 << ", "
459 << offset
460 << ");\n";
461
462 return;
463 }
464
465 out << fieldName
466 << ".writeEmbeddedToBlob("
467 << blobName
468 << ", "
469 << offset
470 << ");\n";
471}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700472void CompoundType::emitResolveReferences(
473 Formatter &out,
474 const std::string &name,
475 bool nameIsPointer,
476 const std::string &parcelObj,
477 bool parcelObjIsPointer,
478 bool isReader,
479 ErrorMode mode) const {
480 emitResolveReferencesEmbedded(
481 out,
482 0 /* depth */,
483 name,
484 name /* sanitizedName */,
485 nameIsPointer,
486 parcelObj,
487 parcelObjIsPointer,
488 isReader,
489 mode,
490 "_hidl_" + name + "_parent",
491 "0 /* parentOffset */");
492}
493
494void CompoundType::emitResolveReferencesEmbedded(
495 Formatter &out,
496 size_t /* depth */,
497 const std::string &name,
498 const std::string &/* sanitizedName */,
499 bool nameIsPointer,
500 const std::string &parcelObj,
501 bool parcelObjIsPointer,
502 bool isReader,
503 ErrorMode mode,
504 const std::string &parentName,
505 const std::string &offsetText) const {
506 CHECK(needsResolveReferences());
507
508 const std::string parcelObjDeref =
509 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
510
511 const std::string parcelObjPointer =
512 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
513
Yifan Hong244e82d2016-11-11 11:13:57 -0800514 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700515 const std::string namePointer = nameIsPointer ? name : ("&" + name);
516
517 out << "_hidl_err = ";
518
519 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800520 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700521 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800522 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700523 }
524
Yifan Hong33223ca2016-12-13 15:07:35 -0800525 out.indent(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800526 if (isReader) {
527 out << "const_cast<"
528 << fullName()
529 << " *"
530 << ">("
531 << namePointer
532 << "),\n"
533 << parcelObjDeref;
534 } else {
535 out << nameDerefed
536 << ",\n"
537 << parcelObjPointer;
538 }
539
540 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700541 << parentName
542 << ",\n"
543 << offsetText
544 << ");\n\n";
545 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700546
547 handleError(out, mode);
548}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700549
Nirav Atre45e76d52018-06-04 11:49:14 -0700550void CompoundType::emitLayoutAsserts(Formatter& out, const Layout& layout,
551 const std::string& layoutName) const {
552 out << "static_assert(sizeof("
553 << fullName()
554 << layoutName
555 << ") == "
556 << layout.size
557 << ", \"wrong size\");\n";
558
559 out << "static_assert(__alignof("
560 << fullName()
561 << layoutName
562 << ") == "
563 << layout.align
564 << ", \"wrong alignment\");\n";
565}
566
567void CompoundType::emitSafeUnionTypeDeclarations(Formatter& out) const {
568 out << "struct "
569 << localName()
570 << " final {\n";
571
572 out.indent();
573
574 Scope::emitTypeDeclarations(out);
575
Nirav Atre12c597a2018-06-28 09:35:24 -0700576 bool hasPointer = containsPointer();
577 CompoundLayout layout = hasPointer
578 ? CompoundLayout()
579 : getCompoundAlignmentAndSize();
580
Nirav Atre45e76d52018-06-04 11:49:14 -0700581 out << "enum class hidl_discriminator : "
582 << getUnionDiscriminatorType()->getCppType(StorageMode_Stack, false)
583 << " ";
584
585 out.block([&] {
Nirav Atre71ce0082018-08-01 15:39:49 -0700586 const auto elements = getSafeUnionEnumElements(true /* useCppTypeName */);
587 for (size_t i = 0; i < elements.size(); i++) {
588 out << elements[i].fieldName
589 << " = "
590 << i
591 << ",";
592
593 if (!elements[i].fieldTypeName.empty()) {
594 out << " // "
595 << elements[i].fieldTypeName;
596 }
597 out << "\n";
Nirav Atre45e76d52018-06-04 11:49:14 -0700598 }
Nirav Atre45e76d52018-06-04 11:49:14 -0700599 });
600 out << ";\n\n";
601
Nirav Atre64868d32018-07-15 19:15:18 -0700602 out << localName() << "();\n" // Constructor
603 << "~" << localName() << "();\n" // Destructor
604 << localName() << "(" << localName() << "&&);\n" // Move constructor
605 << localName() << "(const " << localName() << "&);\n" // Copy constructor
606 << localName() << "& operator=(" << localName() << "&&);\n" // Move assignment
607 << localName() << "& operator=(const " << localName() << "&);\n\n"; // Copy assignment
Nirav Atre45e76d52018-06-04 11:49:14 -0700608
609 for (const auto& field : *mFields) {
Nirav Atre64868d32018-07-15 19:15:18 -0700610 // Setter (copy)
Nirav Atre45e76d52018-06-04 11:49:14 -0700611 out << "void "
612 << field->name()
613 << "("
614 << field->type().getCppArgumentType()
615 << ");\n";
616
Steven Moreland492bada2018-09-13 16:12:32 -0700617 if (field->type().resolveToScalarType() == nullptr) {
Nirav Atre64868d32018-07-15 19:15:18 -0700618 // Setter (move)
619 out << "void "
620 << field->name()
621 << "("
622 << field->type().getCppStackType()
623 << "&&);\n";
624 }
625
626 // Getter (mutable)
Nirav Atre45e76d52018-06-04 11:49:14 -0700627 out << field->type().getCppStackType()
628 << "& "
629 << field->name()
630 << "();\n";
631
Nirav Atre64868d32018-07-15 19:15:18 -0700632 // Getter (immutable)
Nirav Atre45e76d52018-06-04 11:49:14 -0700633 out << field->type().getCppArgumentType()
634 << " "
635 << field->name()
636 << "() const;\n\n";
637 }
638
Nirav Atre12c597a2018-06-28 09:35:24 -0700639 out << "// Utility methods\n";
Nirav Atre45e76d52018-06-04 11:49:14 -0700640 out << "hidl_discriminator getDiscriminator() const;\n\n";
641
Nirav Atre12c597a2018-06-28 09:35:24 -0700642 out << "constexpr size_t hidl_getUnionOffset() const ";
643 out.block([&] {
644 out << "return offsetof(" << fullName() << ", hidl_u);\n";
645 }).endl().endl();
646
Nirav Atre45e76d52018-06-04 11:49:14 -0700647 out.unindent();
648 out << "private:\n";
649 out.indent();
650
651 out << "void hidl_destructUnion();\n\n";
Nirav Atre12c597a2018-06-28 09:35:24 -0700652
653 out << "hidl_discriminator hidl_d";
654 if (!hasPointer) {
655 out << " __attribute__ ((aligned("
656 << layout.discriminator.align << "))) ";
657 }
Steven Moreland967c2432018-10-10 12:50:43 -0700658 out << ";\n";
Nirav Atre45e76d52018-06-04 11:49:14 -0700659 out << "union hidl_union final {\n";
660 out.indent();
661
Nirav Atre45e76d52018-06-04 11:49:14 -0700662 for (const auto& field : *mFields) {
663
664 size_t fieldAlign, fieldSize;
665 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
666
667 out << field->type().getCppStackType()
668 << " "
669 << field->name();
670
671 if (!hasPointer) {
672 out << " __attribute__ ((aligned("
673 << fieldAlign
674 << ")))";
675 }
676 out << ";\n";
677 }
678
679 out << "\n"
680 << "hidl_union();\n"
681 << "~hidl_union();\n";
682
683 out.unindent();
Nirav Atre12c597a2018-06-28 09:35:24 -0700684 out << "} hidl_u;\n";
Nirav Atre45e76d52018-06-04 11:49:14 -0700685
686 if (!hasPointer) {
687 out << "\n";
688
689 emitLayoutAsserts(out, layout.innerStruct, "::hidl_union");
690 emitLayoutAsserts(out, layout.discriminator, "::hidl_discriminator");
691 }
692
693 out.unindent();
694 out << "};\n\n";
695
696 if (!hasPointer) {
697 emitLayoutAsserts(out, layout.overall, "");
698 out << "\n";
699 }
700}
701
Steven Moreland368e4602018-02-16 14:21:49 -0800702void CompoundType::emitTypeDeclarations(Formatter& out) const {
Nirav Atre45e76d52018-06-04 11:49:14 -0700703 if (mStyle == STYLE_SAFE_UNION) {
704 emitSafeUnionTypeDeclarations(out);
705 return;
706 }
707
Andreas Huber881227d2016-08-02 14:20:21 -0700708 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
709 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700710 << localName()
Yifan Hongb1d2ebc2016-12-20 17:18:07 -0800711 << " final {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700712
713 out.indent();
714
715 Scope::emitTypeDeclarations(out);
716
Andreas Huber60d3b222017-03-30 09:10:56 -0700717 if (containsPointer()) {
Andreas Huberca4bc892017-01-09 14:58:12 -0800718 for (const auto &field : *mFields) {
Steven Moreland49bad8d2018-05-17 15:45:26 -0700719 field->emitDocComment(out);
Andreas Huberca4bc892017-01-09 14:58:12 -0800720 out << field->type().getCppStackType()
721 << " "
722 << field->name()
723 << ";\n";
724 }
725
726 out.unindent();
727 out << "};\n\n";
728
Steven Moreland368e4602018-02-16 14:21:49 -0800729 return;
Andreas Huber881227d2016-08-02 14:20:21 -0700730 }
731
Andreas Huberca4bc892017-01-09 14:58:12 -0800732 for (int pass = 0; pass < 2; ++pass) {
733 size_t offset = 0;
734 for (const auto &field : *mFields) {
735 size_t fieldAlign, fieldSize;
736 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
737
Nirav Atre45e76d52018-06-04 11:49:14 -0700738 offset += Layout::getPad(offset, fieldAlign);
Andreas Huberca4bc892017-01-09 14:58:12 -0800739
740 if (pass == 0) {
741 out << field->type().getCppStackType()
742 << " "
743 << field->name()
744 << " __attribute__ ((aligned("
745 << fieldAlign
746 << ")));\n";
747 } else {
748 out << "static_assert(offsetof("
749 << fullName()
750 << ", "
751 << field->name()
752 << ") == "
753 << offset
754 << ", \"wrong offset\");\n";
755 }
756
Andreas Huber60d3b222017-03-30 09:10:56 -0700757 if (mStyle == STYLE_STRUCT) {
758 offset += fieldSize;
759 }
Andreas Huberca4bc892017-01-09 14:58:12 -0800760 }
761
762 if (pass == 0) {
763 out.unindent();
764 out << "};\n\n";
765 }
766 }
767
Nirav Atre45e76d52018-06-04 11:49:14 -0700768 CompoundLayout layout = getCompoundAlignmentAndSize();
769 emitLayoutAsserts(out, layout.overall, "");
770 out << "\n";
Yifan Hong244e82d2016-11-11 11:13:57 -0800771}
772
Timur Iskhakovfd3f2502017-09-05 16:25:02 -0700773void CompoundType::emitTypeForwardDeclaration(Formatter& out) const {
Nirav Atre45e76d52018-06-04 11:49:14 -0700774 switch (mStyle) {
775 case STYLE_UNION: {
776 out << "union";
777 break;
778 }
779 case STYLE_STRUCT:
780 case STYLE_SAFE_UNION: {
781 out << "struct";
782 break;
783 }
784 default: {
785 CHECK(!"Should not be here");
786 }
787 }
788 out << " " << localName() << ";\n";
Timur Iskhakovfd3f2502017-09-05 16:25:02 -0700789}
Yifan Hong244e82d2016-11-11 11:13:57 -0800790
Steven Moreland368e4602018-02-16 14:21:49 -0800791void CompoundType::emitPackageTypeDeclarations(Formatter& out) const {
Steven Moreland4b8f7a12017-11-17 15:39:54 -0800792 Scope::emitPackageTypeDeclarations(out);
Yifan Hongc6752dc2016-12-20 14:00:14 -0800793
Steven Morelandbf714212017-10-27 18:29:01 -0700794 out << "static inline std::string toString("
795 << getCppArgumentType()
796 << (mFields->empty() ? "" : " o")
Steven Moreland09c6ebe2018-10-09 10:15:48 -0700797 << ");\n";
798
799 if (canCheckEquality()) {
800 out << "static inline bool operator==("
801 << getCppArgumentType() << " lhs, " << getCppArgumentType() << " rhs);\n";
802
803 out << "static inline bool operator!=("
804 << getCppArgumentType() << " lhs, " << getCppArgumentType() << " rhs);\n";
805 } else {
806 out << "// operator== and operator!= are not generated for " << localName() << "\n";
807 }
808
809 out.endl();
810}
811
812void CompoundType::emitPackageTypeHeaderDefinitions(Formatter& out) const {
813 Scope::emitPackageTypeHeaderDefinitions(out);
814
815 out << "static inline std::string toString("
816 << getCppArgumentType()
817 << (mFields->empty() ? "" : " o")
Steven Morelandbf714212017-10-27 18:29:01 -0700818 << ") ";
819
820 out.block([&] {
821 // include toString for scalar types
822 out << "using ::android::hardware::toString;\n"
823 << "std::string os;\n";
824 out << "os += \"{\";\n";
825
Steven Moreland5dec82f2018-10-10 13:33:29 -0700826 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -0700827 out << "\nswitch (o.getDiscriminator()) {\n";
828 out.indent();
Steven Morelandbf714212017-10-27 18:29:01 -0700829 }
830
Nirav Atre45e76d52018-06-04 11:49:14 -0700831 for (const NamedReference<Type>* field : *mFields) {
832 if (mStyle == STYLE_SAFE_UNION) {
833 out << "case "
834 << fullName()
835 << "::hidl_discriminator::"
836 << field->name()
837 << ": ";
838
839 out.block([&] {
840 out << "os += \"."
841 << field->name()
842 << " = \";\n"
843 << "os += toString(o."
844 << field->name()
845 << "());\n"
846 << "break;\n";
847 }).endl();
848 } else {
849 out << "os += \"";
850 if (field != *(mFields->begin())) {
851 out << ", ";
852 }
853 out << "." << field->name() << " = \";\n";
854 field->type().emitDump(out, "os", "o." + field->name());
855 }
856 }
857
Steven Moreland5dec82f2018-10-10 13:33:29 -0700858 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -0700859 out << "default: ";
Nirav Atree3cae852018-07-16 12:19:16 -0700860 out.block([&] { emitSafeUnionUnknownDiscriminatorError(out, "o.getDiscriminator()"); })
861 .endl();
Nirav Atre45e76d52018-06-04 11:49:14 -0700862
863 out.unindent();
864 out << "}\n";
865 }
Steven Morelandbf714212017-10-27 18:29:01 -0700866 out << "os += \"}\"; return os;\n";
867 }).endl().endl();
868
869 if (canCheckEquality()) {
870 out << "static inline bool operator==("
871 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
872 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
873 out.block([&] {
Steven Moreland5dec82f2018-10-10 13:33:29 -0700874 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -0700875 out.sIf("lhs.getDiscriminator() != rhs.getDiscriminator()", [&] {
Steven Morelandbf714212017-10-27 18:29:01 -0700876 out << "return false;\n";
877 }).endl();
Nirav Atre45e76d52018-06-04 11:49:14 -0700878
879 out << "switch (lhs.getDiscriminator()) {\n";
880 out.indent();
881 }
882
883 for (const auto& field : *mFields) {
884 if (mStyle == STYLE_SAFE_UNION) {
885 out << "case "
886 << fullName()
887 << "::hidl_discriminator::"
888 << field->name()
889 << ": ";
890
891 out.block([&] {
892 out << "return (lhs."
893 << field->name()
894 << "() == rhs."
895 << field->name()
896 << "());\n";
897 }).endl();
898 } else {
899 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
900 out << "return false;\n";
901 }).endl();
902 }
903 }
904
Steven Moreland5dec82f2018-10-10 13:33:29 -0700905 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -0700906 out << "default: ";
907 out.block([&] {
Nirav Atree3cae852018-07-16 12:19:16 -0700908 emitSafeUnionUnknownDiscriminatorError(out, "lhs.getDiscriminator()");
909 })
910 .endl();
Nirav Atre45e76d52018-06-04 11:49:14 -0700911
912 out.unindent();
913 out << "}\n";
Steven Morelandbf714212017-10-27 18:29:01 -0700914 }
915 out << "return true;\n";
916 }).endl().endl();
917
918 out << "static inline bool operator!=("
Steven Moreland09c6ebe2018-10-09 10:15:48 -0700919 << getCppArgumentType() << " lhs, " << getCppArgumentType() << " rhs)";
Steven Morelandbf714212017-10-27 18:29:01 -0700920 out.block([&] {
921 out << "return !(lhs == rhs);\n";
922 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -0700923 } else {
Steven Morelandf91048a2017-06-23 21:38:35 +0000924 out << "// operator== and operator!= are not generated for " << localName() << "\n\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800925 }
Yifan Hongc6752dc2016-12-20 14:00:14 -0800926}
927
Steven Moreland368e4602018-02-16 14:21:49 -0800928void CompoundType::emitPackageHwDeclarations(Formatter& out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700929 if (needsEmbeddedReadWrite()) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800930 out << "::android::status_t readEmbeddedFromParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700931
Yifan Hong0a68a282016-10-21 16:32:34 -0700932 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700933
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700934 out << "const " << fullName() << " &obj,\n"
Yifan Hong244e82d2016-11-11 11:13:57 -0800935 << "const ::android::hardware::Parcel &parcel,\n"
936 << "size_t parentHandle,\n"
937 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700938
Yifan Hong0a68a282016-10-21 16:32:34 -0700939 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700940
941 out << "::android::status_t writeEmbeddedToParcel(\n";
942
Yifan Hong0a68a282016-10-21 16:32:34 -0700943 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700944
Yifan Hong244e82d2016-11-11 11:13:57 -0800945 out << "const " << fullName() << " &obj,\n"
946 << "::android::hardware::Parcel *parcel,\n"
947 << "size_t parentHandle,\n"
948 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700949
Yifan Hong0a68a282016-10-21 16:32:34 -0700950 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700951 }
952
Yifan Hongbf459bc2016-08-23 16:50:37 -0700953 if(needsResolveReferences()) {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700954 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700955 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800956 out << fullName() << " *obj,\n"
957 << "const ::android::hardware::Parcel &parcel,\n"
958 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700959 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700960 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700961 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800962 out << "const " << fullName() << " &obj,\n"
963 << "::android::hardware::Parcel *,\n"
964 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700965 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700966 }
Andreas Huber881227d2016-08-02 14:20:21 -0700967}
968
Nirav Atre64868d32018-07-15 19:15:18 -0700969static void emitSafeUnionFieldConstructor(Formatter& out,
970 const NamedReference<Type>* field,
971 const std::string& initializerObjectName) {
972 out << "new (&hidl_u."
973 << field->name()
974 << ") "
975 << field->type().getCppStackType()
976 << "("
977 << initializerObjectName
978 << ");\n";
979}
980
981static void emitSafeUnionSetterDefinition(Formatter& out,
982 const NamedReference<Type>* field,
983 const std::string& parameterName,
984 bool usesMoveSemantics) {
985 out.block([&] {
986 out << "if (hidl_d != hidl_discriminator::"
987 << field->name()
988 << ") ";
989
990 const std::string argumentName = usesMoveSemantics
991 ? ("std::move(" + parameterName + ")")
992 : parameterName;
993 out.block([&] {
994 out << "hidl_destructUnion();\n"
995 << "::std::memset(&hidl_u, 0, sizeof(hidl_u));\n\n";
996
997 emitSafeUnionFieldConstructor(out, field, argumentName);
998 out << "hidl_d = hidl_discriminator::"
999 << field->name()
1000 << ";\n";
1001 }).endl();
1002
1003 out << "else if (&(hidl_u."
1004 << field->name()
1005 << ") != &"
1006 << parameterName
1007 << ") ";
1008
1009 out.block([&] {
1010 out << "hidl_u."
1011 << field->name()
1012 << " = "
1013 << argumentName
1014 << ";\n";
1015 }).endl();
1016 }).endl().endl();
1017}
1018
1019static void emitSafeUnionGetterDefinition(Formatter& out, const std::string& fieldName) {
Nirav Atre45e76d52018-06-04 11:49:14 -07001020 out.block([&] {
1021 out << "if (CC_UNLIKELY(hidl_d != hidl_discriminator::"
1022 << fieldName
1023 << ")) ";
1024
1025 out.block([&] {
Steven Moreland9b37ed12018-10-25 11:10:57 -07001026 out << "::android::hardware::details::logAlwaysFatal(\"Bad safe_union access.\");\n";
Nirav Atre45e76d52018-06-04 11:49:14 -07001027 }).endl().endl();
1028
1029 out << "return hidl_u."
1030 << fieldName
1031 << ";\n";
1032 }).endl().endl();
1033}
1034
Nirav Atre71ce0082018-08-01 15:39:49 -07001035std::vector<CompoundType::SafeUnionEnumElement> CompoundType::getSafeUnionEnumElements(
1036 bool useCppTypeName) const {
1037 std::vector<SafeUnionEnumElement> elements;
Nirav Atre71ce0082018-08-01 15:39:49 -07001038
1039 for (const auto& field : *mFields) {
1040 const std::string fieldTypeName = useCppTypeName
1041 ? field->type().getCppStackType(true /* specifyNamespaces */)
1042 : field->type().getJavaType(true /* forInitializer */);
1043
1044 elements.push_back({field->name(), fieldTypeName});
1045 }
1046
1047 return elements;
1048}
1049
Nirav Atre64868d32018-07-15 19:15:18 -07001050void CompoundType::emitSafeUnionCopyAndAssignDefinition(Formatter& out,
1051 const std::string& parameterName,
1052 bool isCopyConstructor,
1053 bool usesMoveSemantics) const {
1054 out.block([&] {
1055 if (!isCopyConstructor) {
1056 out << "if (this == &"
1057 << parameterName
1058 << ") { return *this; }\n\n";
1059 }
1060
1061 out << "switch ("
1062 << parameterName
1063 << ".hidl_d) ";
1064
1065 out.block([&] {
1066 for (const auto& field : *mFields) {
1067 const std::string parameterFieldName = (parameterName + ".hidl_u." +
1068 field->name());
1069
1070 const std::string argumentName = usesMoveSemantics
1071 ? ("std::move(" + parameterFieldName + ")")
1072 : parameterFieldName;
1073
1074 out << "case hidl_discriminator::"
1075 << field->name()
1076 << ": ";
1077
1078 if (isCopyConstructor) {
1079 out.block([&] {
1080 emitSafeUnionFieldConstructor(out, field, argumentName);
1081 out << "break;\n";
1082 }).endl();
1083 } else {
1084 out.block([&] {
1085 out << field->name()
1086 << "("
1087 << argumentName
1088 << ");\n"
1089 << "break;\n";
1090 }).endl();
1091 }
1092 }
1093
Nirav Atree3cae852018-07-16 12:19:16 -07001094 out << "default: ";
1095 out.block(
1096 [&] { emitSafeUnionUnknownDiscriminatorError(out, parameterName + ".hidl_d"); })
1097 .endl();
Nirav Atre64868d32018-07-15 19:15:18 -07001098 }).endl();
1099
1100 if (isCopyConstructor) {
1101 out << "\nhidl_d = "
1102 << parameterName
1103 << ".hidl_d;\n";
1104 } else {
1105 out << "return *this;\n";
1106 }
1107 }).endl().endl();
1108}
1109
Nirav Atre45e76d52018-06-04 11:49:14 -07001110void CompoundType::emitSafeUnionTypeConstructors(Formatter& out) const {
1111
1112 // Default constructor
1113 out << fullName()
1114 << "::"
1115 << localName()
Nirav Atre12c597a2018-06-28 09:35:24 -07001116 << "() ";
1117
1118 out.block([&] {
1119 out << "static_assert(offsetof("
1120 << fullName()
1121 << ", hidl_d) == 0, \"wrong offset\");\n";
1122
1123 if (!containsPointer()) {
1124 CompoundLayout layout = getCompoundAlignmentAndSize();
1125 out << "static_assert(offsetof("
1126 << fullName()
1127 << ", hidl_u) == "
1128 << layout.innerStruct.offset
1129 << ", \"wrong offset\");\n";
1130 }
Steven Moreland967c2432018-10-10 12:50:43 -07001131 out.endl();
1132
1133 CHECK(!mFields->empty());
1134 out << "hidl_d = hidl_discriminator::" << mFields->at(0)->name() << ";\n";
1135 emitSafeUnionFieldConstructor(out, mFields->at(0), "");
Nirav Atre12c597a2018-06-28 09:35:24 -07001136 }).endl().endl();
Nirav Atre45e76d52018-06-04 11:49:14 -07001137
1138 // Destructor
1139 out << fullName()
1140 << "::~"
1141 << localName()
1142 << "() ";
1143
1144 out.block([&] {
1145 out << "hidl_destructUnion();\n";
1146 }).endl().endl();
1147
Nirav Atre64868d32018-07-15 19:15:18 -07001148 // Move constructor
1149 out << fullName()
1150 << "::"
1151 << localName()
1152 << "("
1153 << localName()
1154 << "&& other) ";
1155
1156 emitSafeUnionCopyAndAssignDefinition(
1157 out, "other", true /* isCopyConstructor */, true /* usesMoveSemantics */);
1158
Nirav Atre45e76d52018-06-04 11:49:14 -07001159 // Copy constructor
1160 out << fullName()
1161 << "::"
1162 << localName()
1163 << "(const "
1164 << localName()
1165 << "& other) ";
1166
Nirav Atre64868d32018-07-15 19:15:18 -07001167 emitSafeUnionCopyAndAssignDefinition(
1168 out, "other", true /* isCopyConstructor */, false /* usesMoveSemantics */);
Nirav Atre45e76d52018-06-04 11:49:14 -07001169
Nirav Atre64868d32018-07-15 19:15:18 -07001170 // Move assignment operator
1171 out << fullName()
1172 << "& ("
1173 << fullName()
1174 << "::operator=)("
1175 << localName()
1176 << "&& other) ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001177
Nirav Atre64868d32018-07-15 19:15:18 -07001178 emitSafeUnionCopyAndAssignDefinition(
1179 out, "other", false /* isCopyConstructor */, true /* usesMoveSemantics */);
Nirav Atre45e76d52018-06-04 11:49:14 -07001180
Nirav Atre64868d32018-07-15 19:15:18 -07001181 // Copy assignment operator
1182 out << fullName()
1183 << "& ("
1184 << fullName()
1185 << "::operator=)(const "
1186 << localName()
1187 << "& other) ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001188
Nirav Atre64868d32018-07-15 19:15:18 -07001189 emitSafeUnionCopyAndAssignDefinition(
1190 out, "other", false /* isCopyConstructor */, false /* usesMoveSemantics */);
Nirav Atre45e76d52018-06-04 11:49:14 -07001191}
1192
1193void CompoundType::emitSafeUnionTypeDefinitions(Formatter& out) const {
Nirav Atre45e76d52018-06-04 11:49:14 -07001194 emitSafeUnionTypeConstructors(out);
1195
1196 out << "void "
1197 << fullName()
1198 << "::hidl_destructUnion() ";
1199
1200 out.block([&] {
Nirav Atre66842a92018-06-28 18:14:13 -07001201 out << "switch (hidl_d) ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001202 out.block([&] {
1203
1204 for (const auto& field : *mFields) {
1205 out << "case hidl_discriminator::"
1206 << field->name()
1207 << ": ";
1208
1209 out.block([&] {
Steven Moreland9b37ed12018-10-25 11:10:57 -07001210 out << "::android::hardware::details::destructElement(&(hidl_u."
Nirav Atre3b4c7ff2018-07-09 11:57:02 -07001211 << field->name()
1212 << "));\n"
1213 << "break;\n";
Nirav Atre45e76d52018-06-04 11:49:14 -07001214 }).endl();
1215 }
1216
Nirav Atree3cae852018-07-16 12:19:16 -07001217 out << "default: ";
1218 out.block([&] { emitSafeUnionUnknownDiscriminatorError(out, "hidl_d"); }).endl();
Nirav Atre45e76d52018-06-04 11:49:14 -07001219 }).endl().endl();
Nirav Atre45e76d52018-06-04 11:49:14 -07001220 }).endl().endl();
1221
Nirav Atre45e76d52018-06-04 11:49:14 -07001222 for (const NamedReference<Type>* field : *mFields) {
Nirav Atre64868d32018-07-15 19:15:18 -07001223 // Setter (copy)
Nirav Atre45e76d52018-06-04 11:49:14 -07001224 out << "void "
1225 << fullName()
1226 << "::"
1227 << field->name()
1228 << "("
1229 << field->type().getCppArgumentType()
1230 << " o) ";
1231
Nirav Atre64868d32018-07-15 19:15:18 -07001232 emitSafeUnionSetterDefinition(out, field, "o", false /* usesMoveSemantics */);
1233
Steven Moreland492bada2018-09-13 16:12:32 -07001234 if (field->type().resolveToScalarType() == nullptr) {
Nirav Atre64868d32018-07-15 19:15:18 -07001235 // Setter (move)
1236 out << "void "
1237 << fullName()
1238 << "::"
Nirav Atre45e76d52018-06-04 11:49:14 -07001239 << field->name()
Nirav Atre64868d32018-07-15 19:15:18 -07001240 << "("
1241 << field->type().getCppStackType()
1242 << "&& o) ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001243
Nirav Atre64868d32018-07-15 19:15:18 -07001244 emitSafeUnionSetterDefinition(out, field, "o", true /* usesMoveSemantics */);
1245 }
Nirav Atre45e76d52018-06-04 11:49:14 -07001246
1247 // Getter (mutable)
1248 out << field->type().getCppStackType()
1249 << "& ("
1250 << fullName()
1251 << "::"
1252 << field->name()
1253 << ")() ";
1254
Nirav Atre64868d32018-07-15 19:15:18 -07001255 emitSafeUnionGetterDefinition(out, field->name());
Nirav Atre45e76d52018-06-04 11:49:14 -07001256
1257 // Getter (immutable)
1258 out << field->type().getCppArgumentType()
1259 << " ("
1260 << fullName()
1261 << "::"
1262 << field->name()
1263 << ")() const ";
1264
Nirav Atre64868d32018-07-15 19:15:18 -07001265 emitSafeUnionGetterDefinition(out, field->name());
Nirav Atre45e76d52018-06-04 11:49:14 -07001266 }
1267
1268 // Trivial constructor/destructor for internal union
1269 out << fullName() << "::hidl_union::hidl_union() {}\n\n"
1270 << fullName() << "::hidl_union::~hidl_union() {}\n\n";
1271
1272 // Utility method
Nirav Atreca7a5022018-06-29 20:43:49 -07001273 out << fullName() << "::hidl_discriminator ("
1274 << fullName() << "::getDiscriminator)() const ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001275
1276 out.block([&] {
Nirav Atreca7a5022018-06-29 20:43:49 -07001277 out << "return hidl_d;\n";
Nirav Atre45e76d52018-06-04 11:49:14 -07001278 }).endl().endl();
1279}
1280
Steven Moreland368e4602018-02-16 14:21:49 -08001281void CompoundType::emitTypeDefinitions(Formatter& out, const std::string& prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -07001282 std::string space = prefix.empty() ? "" : (prefix + "::");
Steven Moreland368e4602018-02-16 14:21:49 -08001283 Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -07001284
Yifan Hongbf459bc2016-08-23 16:50:37 -07001285 if (needsEmbeddedReadWrite()) {
1286 emitStructReaderWriter(out, prefix, true /* isReader */);
1287 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -07001288 }
1289
Yifan Hongbf459bc2016-08-23 16:50:37 -07001290 if (needsResolveReferences()) {
1291 emitResolveReferenceDef(out, prefix, true /* isReader */);
1292 emitResolveReferenceDef(out, prefix, false /* isReader */);
1293 }
Nirav Atre45e76d52018-06-04 11:49:14 -07001294
1295 if (mStyle == STYLE_SAFE_UNION) {
1296 emitSafeUnionTypeDefinitions(out);
1297 }
Andreas Huber881227d2016-08-02 14:20:21 -07001298}
1299
Nirav Atree3cae852018-07-16 12:19:16 -07001300static void emitJavaSafeUnionUnknownDiscriminatorError(Formatter& out) {
1301 out << "throw new Error(\"Unknown union discriminator "
1302 << "(value: \" + hidl_d + \").\");\n";
1303}
1304
Steven Moreland368e4602018-02-16 14:21:49 -08001305void CompoundType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -07001306 out << "public final ";
1307
1308 if (!atTopLevel) {
1309 out << "static ";
1310 }
1311
1312 out << "class "
1313 << localName()
1314 << " {\n";
1315
1316 out.indent();
1317
1318 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
1319
Steven Moreland5dec82f2018-10-10 13:33:29 -07001320 if (mStyle == STYLE_SAFE_UNION) {
Steven Moreland579b0f62018-10-25 13:40:47 -07001321 out << "public " << localName() << "() ";
1322 out.block([&] {
1323 CHECK(!mFields->empty());
1324 mFields->at(0)->type().emitJavaFieldDefaultInitialValue(out, "hidl_o");
1325 }).endl().endl();
1326
Nirav Atre66842a92018-06-28 18:14:13 -07001327 const std::string discriminatorStorageType = (
1328 getUnionDiscriminatorType()->getJavaType(false));
Steven Moreland49bad8d2018-05-17 15:45:26 -07001329
Nirav Atre66842a92018-06-28 18:14:13 -07001330 out << "public static final class hidl_discriminator ";
1331 out.block([&] {
Nirav Atre71ce0082018-08-01 15:39:49 -07001332 const auto elements = getSafeUnionEnumElements(false /* useCppTypeName */);
1333 for (size_t idx = 0; idx < elements.size(); idx++) {
Nirav Atre66842a92018-06-28 18:14:13 -07001334 out << "public static final "
1335 << discriminatorStorageType
1336 << " "
Nirav Atre71ce0082018-08-01 15:39:49 -07001337 << elements[idx].fieldName
Nirav Atre66842a92018-06-28 18:14:13 -07001338 << " = "
1339 << idx
Nirav Atre71ce0082018-08-01 15:39:49 -07001340 << ";";
1341
1342 if (!elements[idx].fieldTypeName.empty()) {
1343 out << " // "
1344 << elements[idx].fieldTypeName;
1345 }
1346 out << "\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001347 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001348
Nirav Atre66842a92018-06-28 18:14:13 -07001349 out << "\n"
1350 << "public static final String getName("
1351 << discriminatorStorageType
1352 << " value) ";
1353
1354 out.block([&] {
1355 out << "switch (value) ";
1356 out.block([&] {
Nirav Atre71ce0082018-08-01 15:39:49 -07001357 for (size_t idx = 0; idx < elements.size(); idx++) {
Nirav Atre66842a92018-06-28 18:14:13 -07001358 out << "case "
1359 << idx
1360 << ": { return \""
Nirav Atre71ce0082018-08-01 15:39:49 -07001361 << elements[idx].fieldName
Nirav Atre66842a92018-06-28 18:14:13 -07001362 << "\"; }\n";
1363 }
1364 out << "default: { return \"Unknown\"; }\n";
1365 }).endl();
1366 }).endl().endl();
1367
1368 out << "private hidl_discriminator() {}\n";
1369 }).endl().endl();
1370
Steven Moreland967c2432018-10-10 12:50:43 -07001371 out << "private " << discriminatorStorageType << " hidl_d = 0;\n";
Steven Moreland579b0f62018-10-25 13:40:47 -07001372 out << "private Object hidl_o = null;\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001373
1374 for (const auto& field : *mFields) {
1375 // Setter
1376 out << "public void "
1377 << field->name()
1378 << "("
1379 << field->type().getJavaType(false)
1380 << " "
1381 << field->name()
1382 << ") ";
1383
1384 out.block([&] {
1385 out << "hidl_d = hidl_discriminator."
1386 << field->name()
1387 << ";\n";
1388
1389 out << "hidl_o = "
1390 << field->name()
1391 << ";\n";
1392 }).endl().endl();
1393
1394 // Getter
1395 out << "public "
1396 << field->type().getJavaType(false)
1397 << " "
1398 << field->name()
1399 << "() ";
1400
1401 out.block([&] {
1402 out << "if (hidl_d != hidl_discriminator."
1403 << field->name()
1404 << ") ";
1405
1406 out.block([&] {
1407 out << "String className = (hidl_o != null) ? "
1408 << "hidl_o.getClass().getName() : \"null\";\n";
1409
1410 out << "throw new IllegalStateException(\n";
1411 out.indent(2, [&] {
1412 out << "\"Read access to inactive union components is disallowed. \" +\n"
1413 << "\"Discriminator value is \" + hidl_d + \" (corresponding \" +\n"
1414 << "\"to \" + hidl_discriminator.getName(hidl_d) + \"), and \" +\n"
1415 << "\"hidl_o is of type \" + className + \".\");\n";
1416 });
1417 }).endl();
1418
1419 out << "if (hidl_o != null && !"
1420 << field->type().getJavaTypeClass()
1421 << ".class.isInstance(hidl_o)) ";
1422
1423 out.block([&] {
1424 out << "throw new Error(\"Union is in a corrupted state.\");\n";
1425 }).endl();
1426
1427 out << "return ("
1428 << field->type().getJavaTypeCast("hidl_o")
1429 << ");\n";
1430 }).endl().endl();
1431 }
1432
1433 out << "// Utility method\n"
1434 << "public "
1435 << discriminatorStorageType
1436 << " getDiscriminator() { return hidl_d; }\n\n";
1437
Steven Moreland5dec82f2018-10-10 13:33:29 -07001438 } else {
Nirav Atre66842a92018-06-28 18:14:13 -07001439 for (const auto& field : *mFields) {
1440 field->emitDocComment(out);
1441
1442 out << "public ";
1443 field->type().emitJavaFieldInitializer(out, field->name());
1444 }
1445
Andreas Huber85eabdb2016-08-25 11:24:49 -07001446 out << "\n";
1447 }
1448
Yifan Hongec102272016-12-20 18:10:07 -08001449 ////////////////////////////////////////////////////////////////////////////
1450
1451 if (canCheckEquality()) {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001452 out << "@Override\npublic final boolean equals(Object otherObject) ";
Yifan Hongec102272016-12-20 18:10:07 -08001453 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001454 out.sIf("this == otherObject", [&] {
1455 out << "return true;\n";
1456 }).endl();
1457 out.sIf("otherObject == null", [&] {
1458 out << "return false;\n";
1459 }).endl();
Yifan Hong45b331b2017-03-27 12:59:54 -07001460 // Though class is final, we use getClass instead of instanceof to be explicit.
1461 out.sIf("otherObject.getClass() != " + fullJavaName() + ".class", [&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001462 out << "return false;\n";
1463 }).endl();
1464 out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001465
Steven Moreland5dec82f2018-10-10 13:33:29 -07001466 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001467 out.sIf("this.hidl_d != other.hidl_d", [&] {
Yifan Hongec102272016-12-20 18:10:07 -08001468 out << "return false;\n";
1469 }).endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001470 out.sIf("!android.os.HidlSupport.deepEquals(this.hidl_o, other.hidl_o)", [&] {
1471 out << "return false;\n";
1472 }).endl();
Steven Moreland5dec82f2018-10-10 13:33:29 -07001473 } else {
Nirav Atre66842a92018-06-28 18:14:13 -07001474 for (const auto &field : *mFields) {
1475 std::string condition = (field->type().isScalar() || field->type().isEnum())
1476 ? "this." + field->name() + " != other." + field->name()
1477 : ("!android.os.HidlSupport.deepEquals(this." + field->name()
1478 + ", other." + field->name() + ")");
1479 out.sIf(condition, [&] {
1480 out << "return false;\n";
1481 }).endl();
1482 }
Yifan Hongec102272016-12-20 18:10:07 -08001483 }
1484 out << "return true;\n";
1485 }).endl().endl();
1486
Yifan Hong7d1839f2017-02-22 13:24:29 -08001487 out << "@Override\npublic final int hashCode() ";
Yifan Hongec102272016-12-20 18:10:07 -08001488 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001489 out << "return java.util.Objects.hash(\n";
1490 out.indent(2, [&] {
Steven Moreland5dec82f2018-10-10 13:33:29 -07001491 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001492 out << "android.os.HidlSupport.deepHashCode(this.hidl_o),\n"
1493 << "java.util.Objects.hashCode(this.hidl_d)";
1494 } else {
1495 out.join(mFields->begin(), mFields->end(), ", \n", [&] (const auto &field) {
1496 out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")";
1497 });
1498 }
Yifan Hong7d1839f2017-02-22 13:24:29 -08001499 });
Yifan Hongec102272016-12-20 18:10:07 -08001500 out << ");\n";
1501 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -07001502 } else {
1503 out << "// equals() is not generated for " << localName() << "\n";
Yifan Hongec102272016-12-20 18:10:07 -08001504 }
1505
1506 ////////////////////////////////////////////////////////////////////////////
1507
Yifan Honge45b5302017-02-22 10:49:07 -08001508 out << "@Override\npublic final String toString() ";
1509 out.block([&] {
1510 out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n"
1511 << "builder.append(\"{\");\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001512
Steven Moreland5dec82f2018-10-10 13:33:29 -07001513 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001514 out << "switch (this.hidl_d) {\n";
1515 out.indent();
Yifan Honge45b5302017-02-22 10:49:07 -08001516 }
Nirav Atre66842a92018-06-28 18:14:13 -07001517
1518 for (const auto &field : *mFields) {
1519 if (mStyle == STYLE_SAFE_UNION) {
1520 out << "case hidl_discriminator."
1521 << field->name()
1522 << ": ";
1523
1524 out.block([&] {
1525 out << "builder.append(\""
1526 << "."
1527 << field->name()
1528 << " = \");\n";
1529
1530 field->type().emitJavaDump(out, "builder", "this." + field->name() + "()");
1531 out << "break;\n";
1532 }).endl();
1533 }
1534 else {
1535 out << "builder.append(\"";
1536 if (field != *(mFields->begin())) {
1537 out << ", ";
1538 }
1539 out << "." << field->name() << " = \");\n";
1540 field->type().emitJavaDump(out, "builder", "this." + field->name());
1541 }
1542 }
1543
Steven Moreland5dec82f2018-10-10 13:33:29 -07001544 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atree3cae852018-07-16 12:19:16 -07001545 out << "default: ";
1546 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out); }).endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001547
1548 out.unindent();
1549 out << "}\n";
1550 }
1551
Yifan Honge45b5302017-02-22 10:49:07 -08001552 out << "builder.append(\"}\");\nreturn builder.toString();\n";
1553 }).endl().endl();
1554
Nirav Atre66842a92018-06-28 18:14:13 -07001555 CompoundLayout layout = getCompoundAlignmentAndSize();
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001556
Yifan Honge45b5302017-02-22 10:49:07 -08001557 ////////////////////////////////////////////////////////////////////////////
1558
Yifan Hong1af73532016-11-09 14:32:58 -08001559 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001560 out.indent();
Howard Chenaf084db2017-12-27 18:46:39 +08001561 if (containsInterface()) {
Nirav Atre66842a92018-06-28 18:14:13 -07001562
Steven Moreland5dec82f2018-10-10 13:33:29 -07001563 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001564 out << "hidl_d = ";
1565 getUnionDiscriminatorType()->emitJavaReaderWriter(
1566 out, "parcel", "hidl_d", true);
1567
1568 out << "switch (hidl_d) {\n";
1569 out.indent();
1570 }
1571
Howard Chenaf084db2017-12-27 18:46:39 +08001572 for (const auto& field : *mFields) {
Nirav Atre66842a92018-06-28 18:14:13 -07001573 if (mStyle == STYLE_SAFE_UNION) {
1574 out << "case hidl_discriminator."
1575 << field->name()
1576 << ": ";
1577
1578 out.block([&] {
1579 out << "hidl_o = ";
1580 field->type().emitJavaReaderWriter(out, "parcel", "hidl_o", true);
1581
1582 out << "break;\n";
1583 }).endl();
1584 } else {
1585 out << field->name() << " = ";
1586 field->type().emitJavaReaderWriter(out, "parcel", field->name(), true);
1587 }
1588 }
1589
Steven Moreland5dec82f2018-10-10 13:33:29 -07001590 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atree3cae852018-07-16 12:19:16 -07001591 out << "default: ";
1592 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out); }).endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001593
1594 out.unindent();
1595 out << "}\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001596 }
1597 } else {
1598 out << "android.os.HwBlob blob = parcel.readBuffer(";
Nirav Atre66842a92018-06-28 18:14:13 -07001599 out << layout.overall.size << " /* size */);\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001600 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
1601 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001602 out.unindent();
1603 out << "}\n\n";
1604
Andreas Huberf630bc82016-09-09 14:52:25 -07001605 ////////////////////////////////////////////////////////////////////////////
1606
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001607 size_t vecAlign, vecSize;
1608 VectorType::getAlignmentAndSizeStatic(&vecAlign, &vecSize);
1609
Howard Chenaf084db2017-12-27 18:46:39 +08001610 out << "public static final java.util.ArrayList<" << localName()
Yifan Hong1af73532016-11-09 14:32:58 -08001611 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001612 out.indent();
1613
Howard Chenaf084db2017-12-27 18:46:39 +08001614 out << "java.util.ArrayList<" << localName() << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001615
Howard Chenaf084db2017-12-27 18:46:39 +08001616 if (containsInterface()) {
1617 out << "int size = parcel.readInt32();\n";
1618 out << "for(int i = 0 ; i < size; i ++) {\n";
1619 out.indent();
1620 out << fullJavaName() << " tmp = ";
1621 emitJavaReaderWriter(out, "parcel", "tmp", true);
1622 out << "_hidl_vec.add(tmp);\n";
1623 out.unindent();
1624 out << "}\n";
1625 } else {
1626 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer(";
1627 out << vecSize << " /* sizeof hidl_vec<T> */);\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001628
Howard Chenaf084db2017-12-27 18:46:39 +08001629 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel",
1630 "_hidl_blob", "_hidl_vec", "0",
1631 true /* isReader */);
Andreas Huber85eabdb2016-08-25 11:24:49 -07001632 }
Howard Chenaf084db2017-12-27 18:46:39 +08001633 out << "\nreturn _hidl_vec;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001634 out.unindent();
1635 out << "}\n\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001636 ////////////////////////////////////////////////////////////////////////////
1637 if (containsInterface()) {
1638 out << "// readEmbeddedFromParcel is not generated()\n";
1639 } else {
1640 out << "public final void readEmbeddedFromParcel(\n";
1641 out.indent(2);
1642 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
1643 out.unindent();
Nirav Atre66842a92018-06-28 18:14:13 -07001644
Steven Moreland5dec82f2018-10-10 13:33:29 -07001645 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001646 getUnionDiscriminatorType()->emitJavaFieldReaderWriter(
1647 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d",
1648 "_hidl_offset + " + std::to_string(layout.discriminator.offset),
1649 true /* isReader */);
1650
1651 out << "switch (this.hidl_d) {\n";
1652 out.indent();
1653 }
1654
1655 size_t offset = layout.innerStruct.offset;
Howard Chenaf084db2017-12-27 18:46:39 +08001656 for (const auto& field : *mFields) {
Howard Chenaf084db2017-12-27 18:46:39 +08001657
Nirav Atre66842a92018-06-28 18:14:13 -07001658 if (mStyle == STYLE_SAFE_UNION) {
1659 out << "case hidl_discriminator."
1660 << field->name()
1661 << ": ";
Howard Chenaf084db2017-12-27 18:46:39 +08001662
Nirav Atre66842a92018-06-28 18:14:13 -07001663 out.block([&] {
1664 field->type().emitJavaFieldDefaultInitialValue(out, "hidl_o");
1665 field->type().emitJavaFieldReaderWriter(
1666 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_o",
1667 "_hidl_offset + " + std::to_string(offset), true /* isReader */);
1668
1669 out << "break;\n";
1670 }).endl();
1671 } else {
1672 size_t fieldAlign, fieldSize;
1673 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1674
1675 offset += Layout::getPad(offset, fieldAlign);
1676 field->type().emitJavaFieldReaderWriter(
1677 out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
1678 "_hidl_offset + " + std::to_string(offset), true /* isReader */);
1679 offset += fieldSize;
1680 }
1681 }
1682
Steven Moreland5dec82f2018-10-10 13:33:29 -07001683 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atree3cae852018-07-16 12:19:16 -07001684 out << "default: ";
1685 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out); }).endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001686
1687 out.unindent();
1688 out << "}\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001689 }
1690 out.unindent();
1691 out << "}\n\n";
1692 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001693
Andreas Huberf630bc82016-09-09 14:52:25 -07001694 ////////////////////////////////////////////////////////////////////////////
1695
Yifan Hong1af73532016-11-09 14:32:58 -08001696 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001697 out.indent();
1698
Howard Chenaf084db2017-12-27 18:46:39 +08001699 if (containsInterface()) {
Steven Moreland5dec82f2018-10-10 13:33:29 -07001700 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001701 getUnionDiscriminatorType()->emitJavaReaderWriter(
1702 out, "parcel", "hidl_d", false);
1703
1704 out << "switch (this.hidl_d) {\n";
1705 out.indent();
1706 }
1707
Howard Chenaf084db2017-12-27 18:46:39 +08001708 for (const auto& field : *mFields) {
Nirav Atre66842a92018-06-28 18:14:13 -07001709 if (mStyle == STYLE_SAFE_UNION) {
1710 out << "case hidl_discriminator."
1711 << field->name()
1712 << ": ";
1713
1714 out.block([&] {
1715 field->type().emitJavaReaderWriter(out, "parcel", field->name() + "()", false);
1716 out << "break;\n";
1717 }).endl();
1718 } else {
1719 field->type().emitJavaReaderWriter(out, "parcel", field->name(), false);
1720 }
1721 }
1722
Steven Moreland5dec82f2018-10-10 13:33:29 -07001723 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atree3cae852018-07-16 12:19:16 -07001724 out << "default: ";
1725 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out); }).endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001726
1727 out.unindent();
1728 out << "}\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001729 }
1730 } else {
Nirav Atre66842a92018-06-28 18:14:13 -07001731 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
1732 << layout.overall.size
Howard Chenaf084db2017-12-27 18:46:39 +08001733 << " /* size */);\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001734
Howard Chenaf084db2017-12-27 18:46:39 +08001735 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
1736 << "parcel.writeBuffer(_hidl_blob);\n";
1737 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001738 out.unindent();
1739 out << "}\n\n";
1740
Andreas Huberf630bc82016-09-09 14:52:25 -07001741 ////////////////////////////////////////////////////////////////////////////
1742
Andreas Huberf630bc82016-09-09 14:52:25 -07001743 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001744 out.indent(2);
Howard Chenaf084db2017-12-27 18:46:39 +08001745 out << "android.os.HwParcel parcel, java.util.ArrayList<" << localName() << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001746 out.unindent();
1747
Howard Chenaf084db2017-12-27 18:46:39 +08001748 if (containsInterface()) {
1749 out << "parcel.writeInt32(_hidl_vec.size());\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001750 out << "for(" << fullJavaName() << " tmp: _hidl_vec) ";
1751 out.block([&] {
1752 emitJavaReaderWriter(out, "parcel", "tmp", false);
1753 }).endl();
Howard Chenaf084db2017-12-27 18:46:39 +08001754 } else {
1755 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(" << vecSize
1756 << " /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001757
Howard Chenaf084db2017-12-27 18:46:39 +08001758 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel",
1759 "_hidl_blob", "_hidl_vec", "0",
1760 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -07001761
Howard Chenaf084db2017-12-27 18:46:39 +08001762 out << "\nparcel.writeBuffer(_hidl_blob);\n";
1763 }
Andreas Huberf630bc82016-09-09 14:52:25 -07001764 out.unindent();
1765 out << "}\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001766 ////////////////////////////////////////////////////////////////////////////
1767
Howard Chenaf084db2017-12-27 18:46:39 +08001768 if (containsInterface()) {
Nirav Atre66842a92018-06-28 18:14:13 -07001769 out << "// writeEmbeddedToBlob() is not generated\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001770 } else {
1771 out << "public final void writeEmbeddedToBlob(\n";
1772 out.indent(2);
1773 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
1774 out.unindent();
Nirav Atre45e76d52018-06-04 11:49:14 -07001775
Steven Moreland5dec82f2018-10-10 13:33:29 -07001776 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001777 getUnionDiscriminatorType()->emitJavaFieldReaderWriter(
1778 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d",
1779 "_hidl_offset + " + std::to_string(layout.discriminator.offset),
1780 false /* isReader */);
Nirav Atre45e76d52018-06-04 11:49:14 -07001781
Nirav Atre66842a92018-06-28 18:14:13 -07001782 out << "switch (this.hidl_d) {\n";
1783 out.indent();
Andreas Huber85eabdb2016-08-25 11:24:49 -07001784 }
1785
Nirav Atre66842a92018-06-28 18:14:13 -07001786 size_t offset = layout.innerStruct.offset;
1787 for (const auto& field : *mFields) {
1788 if (mStyle == STYLE_SAFE_UNION) {
1789 out << "case hidl_discriminator."
1790 << field->name()
1791 << ": ";
1792
1793 out.block([&] {
1794 field->type().emitJavaFieldReaderWriter(
1795 out, 0 /* depth */, "parcel", "_hidl_blob", field->name() + "()",
1796 "_hidl_offset + " + std::to_string(offset), false /* isReader */);
1797
1798 out << "break;\n";
1799 }).endl();
1800 } else {
1801 size_t fieldAlign, fieldSize;
1802 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1803
1804 offset += Layout::getPad(offset, fieldAlign);
1805 field->type().emitJavaFieldReaderWriter(
1806 out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
1807 "_hidl_offset + " + std::to_string(offset), false /* isReader */);
1808 offset += fieldSize;
1809 }
1810 }
1811
Steven Moreland5dec82f2018-10-10 13:33:29 -07001812 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atree3cae852018-07-16 12:19:16 -07001813 out << "default: ";
1814 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out); }).endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001815
1816 out.unindent();
1817 out << "}\n";
1818 }
Howard Chenaf084db2017-12-27 18:46:39 +08001819 out.unindent();
1820 out << "}\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001821 }
1822
1823 out.unindent();
Andreas Huber85eabdb2016-08-25 11:24:49 -07001824 out << "};\n\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001825}
1826
Andreas Huber881227d2016-08-02 14:20:21 -07001827void CompoundType::emitStructReaderWriter(
1828 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -08001829
1830 std::string space = prefix.empty() ? "" : (prefix + "::");
1831
Andreas Huber881227d2016-08-02 14:20:21 -07001832 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -08001833 << (isReader ? "readEmbeddedFromParcel"
1834 : "writeEmbeddedToParcel")
1835 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001836
Yifan Hong0a68a282016-10-21 16:32:34 -07001837 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -07001838
Nirav Atre97b7e9c2018-07-26 19:29:40 -07001839 const std::string name = "obj";
Andreas Huber881227d2016-08-02 14:20:21 -07001840 if (isReader) {
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001841 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001842 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001843 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -08001844 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001845 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001846 }
1847
1848 out << "size_t parentHandle,\n"
1849 << "size_t parentOffset)";
1850
Andreas Huber881227d2016-08-02 14:20:21 -07001851 out << " {\n";
1852
Yifan Hong0a68a282016-10-21 16:32:34 -07001853 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -07001854 out.indent();
1855
Iliyan Malchev549e2592016-08-10 08:59:12 -07001856 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001857
Steven Moreland5dec82f2018-10-10 13:33:29 -07001858 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -07001859 out << "switch (" << name << ".getDiscriminator()) {\n";
1860 out.indent();
1861 }
1862
Andreas Huber881227d2016-08-02 14:20:21 -07001863 for (const auto &field : *mFields) {
1864 if (!field->type().needsEmbeddedReadWrite()) {
1865 continue;
1866 }
1867
Nirav Atre45e76d52018-06-04 11:49:14 -07001868 if (mStyle == STYLE_SAFE_UNION) {
1869 out << "case " << fullName() << "::hidl_discriminator::"
1870 << field->name() << ": {\n";
1871 out.indent();
1872 }
1873
1874 const std::string fieldName = (mStyle == STYLE_SAFE_UNION)
Nirav Atre97b7e9c2018-07-26 19:29:40 -07001875 ? (name + "." + field->name() + "()")
1876 : (name + "." + field->name());
Nirav Atre45e76d52018-06-04 11:49:14 -07001877
1878 const std::string fieldOffset = (mStyle == STYLE_SAFE_UNION)
Nirav Atre12c597a2018-06-28 09:35:24 -07001879 ? (name + ".hidl_getUnionOffset() " +
1880 "/* safe_union: union offset into struct */")
Nirav Atre45e76d52018-06-04 11:49:14 -07001881 : ("offsetof(" + fullName() + ", " + field->name() + ")");
1882
Andreas Huber881227d2016-08-02 14:20:21 -07001883 field->type().emitReaderWriterEmbedded(
1884 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -07001885 0 /* depth */,
Nirav Atre45e76d52018-06-04 11:49:14 -07001886 fieldName,
Yifan Hongbe2a3732016-10-05 13:33:41 -07001887 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -07001888 false /* nameIsPointer */,
1889 "parcel",
1890 !isReader /* parcelObjIsPointer */,
1891 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -07001892 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -07001893 "parentHandle",
Nirav Atre45e76d52018-06-04 11:49:14 -07001894 "parentOffset + " + fieldOffset);
1895
1896 if (mStyle == STYLE_SAFE_UNION) {
1897 out << "break;\n";
1898 out.unindent();
1899 out << "}\n";
1900 }
1901 }
1902
Steven Moreland5dec82f2018-10-10 13:33:29 -07001903 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -07001904 out << "default: { break; }\n";
1905 out.unindent();
1906 out << "}\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001907 }
1908
Iliyan Malchev549e2592016-08-10 08:59:12 -07001909 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001910
1911 out.unindent();
1912 out << "}\n\n";
1913}
1914
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -07001915void CompoundType::emitResolveReferenceDef(Formatter& out, const std::string& prefix,
1916 bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -08001917 out << "::android::status_t ";
1918 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -07001919
1920 bool useParent = false;
1921 for (const auto &field : *mFields) {
1922 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
1923 useParent = true;
1924 break;
1925 }
1926 }
1927
1928 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
1929 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
1930
Yifan Hongbf459bc2016-08-23 16:50:37 -07001931 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -08001932 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001933 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -08001934 out << space + localName() + " *obj,\n"
1935 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -07001936 << "size_t " << parentHandleName << ", "
1937 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001938 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001939 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -08001940 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001941 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -08001942 out << "const " << space + localName() + " &obj,\n"
1943 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -07001944 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -08001945 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001946 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001947 }
1948
1949 out << " {\n";
1950
1951 out.indent();
1952
1953 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
1954
Yifan Hong244e82d2016-11-11 11:13:57 -08001955 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -07001956 // if not useParent, then parentName and offsetText
1957 // should not be used at all, then the #error should not be emitted.
1958 std::string error = useParent ? "" : "\n#error\n";
1959
Nirav Atre45e76d52018-06-04 11:49:14 -07001960 if (mStyle == STYLE_SAFE_UNION) {
1961 out << "switch (" << nameDeref << "getDiscriminator()) {\n";
1962 out.indent();
1963 }
1964
Yifan Hongbf459bc2016-08-23 16:50:37 -07001965 for (const auto &field : *mFields) {
1966 if (!field->type().needsResolveReferences()) {
1967 continue;
1968 }
1969
Nirav Atre45e76d52018-06-04 11:49:14 -07001970 if (mStyle == STYLE_SAFE_UNION) {
1971 out << "case " << fullName() << "::hidl_discriminator::"
1972 << field->name() << ": {\n";
1973 out.indent();
1974 }
1975
1976 const std::string fieldName = (mStyle == STYLE_SAFE_UNION)
1977 ? (nameDeref + field->name() + "()")
1978 : (nameDeref + field->name());
1979
1980 const std::string fieldOffset = (mStyle == STYLE_SAFE_UNION)
Nirav Atre12c597a2018-06-28 09:35:24 -07001981 ? (nameDeref + "hidl_getUnionOffset() " +
1982 "/* safe_union: union offset into struct */")
Nirav Atre45e76d52018-06-04 11:49:14 -07001983 : ("offsetof(" + fullName() + ", " + field->name() + ")");
1984
Yifan Hongbf459bc2016-08-23 16:50:37 -07001985 field->type().emitResolveReferencesEmbedded(
1986 out,
1987 0 /* depth */,
Nirav Atre45e76d52018-06-04 11:49:14 -07001988 fieldName,
Yifan Hongbf459bc2016-08-23 16:50:37 -07001989 field->name() /* sanitizedName */,
1990 false, // nameIsPointer
1991 "parcel", // const std::string &parcelObj,
1992 !isReader, // bool parcelObjIsPointer,
1993 isReader, // bool isReader,
1994 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -07001995 parentHandleName + error,
1996 parentOffsetName
Nirav Atre45e76d52018-06-04 11:49:14 -07001997 + " + "
1998 + fieldOffset
Yifan Hong00f47172016-09-30 14:40:45 -07001999 + error);
Nirav Atre45e76d52018-06-04 11:49:14 -07002000
2001 if (mStyle == STYLE_SAFE_UNION) {
2002 out << "break;\n";
2003 out.unindent();
2004 out << "}\n";
2005 }
2006 }
2007
2008 if (mStyle == STYLE_SAFE_UNION) {
2009 out << "default: { _hidl_err = ::android::BAD_VALUE; break; }\n";
2010 out.unindent();
2011 out << "}\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -07002012 }
2013
Yifan Hongbf459bc2016-08-23 16:50:37 -07002014 out << "return _hidl_err;\n";
2015
2016 out.unindent();
2017 out << "}\n\n";
2018}
2019
Andreas Huber881227d2016-08-02 14:20:21 -07002020bool CompoundType::needsEmbeddedReadWrite() const {
Nirav Atre45e76d52018-06-04 11:49:14 -07002021 if (mStyle == STYLE_UNION) {
Andreas Huber881227d2016-08-02 14:20:21 -07002022 return false;
2023 }
2024
2025 for (const auto &field : *mFields) {
2026 if (field->type().needsEmbeddedReadWrite()) {
2027 return true;
2028 }
2029 }
2030
2031 return false;
2032}
2033
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002034bool CompoundType::deepNeedsResolveReferences(std::unordered_set<const Type*>* visited) const {
Nirav Atre45e76d52018-06-04 11:49:14 -07002035 if (mStyle == STYLE_UNION) {
Yifan Hongbf459bc2016-08-23 16:50:37 -07002036 return false;
2037 }
2038
2039 for (const auto &field : *mFields) {
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002040 if (field->type().needsResolveReferences(visited)) {
Yifan Hongbf459bc2016-08-23 16:50:37 -07002041 return true;
2042 }
2043 }
2044
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002045 return Scope::deepNeedsResolveReferences(visited);
Yifan Hongbf459bc2016-08-23 16:50:37 -07002046}
2047
Andreas Huber881227d2016-08-02 14:20:21 -07002048bool CompoundType::resultNeedsDeref() const {
Howard Chenecfb4512017-11-21 18:28:53 +08002049 return !containsInterface() ;
Andreas Huber881227d2016-08-02 14:20:21 -07002050}
2051
Steven Moreland368e4602018-02-16 14:21:49 -08002052void CompoundType::emitVtsTypeDeclarations(Formatter& out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07002053 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07002054 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002055
2056 // Emit declaration for each subtype.
2057 for (const auto &type : getSubTypes()) {
2058 switch (mStyle) {
2059 case STYLE_STRUCT:
2060 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07002061 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002062 break;
2063 }
2064 case STYLE_UNION:
2065 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07002066 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002067 break;
2068 }
Nirav Atre45e76d52018-06-04 11:49:14 -07002069 case STYLE_SAFE_UNION:
2070 {
2071 out << "sub_safe_union: {\n";
2072 break;
2073 }
2074 default:
2075 {
2076 CHECK(!"Should not be here");
2077 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002078 }
2079 out.indent();
Steven Moreland368e4602018-02-16 14:21:49 -08002080 type->emitVtsTypeDeclarations(out);
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002081 out.unindent();
2082 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07002083 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002084
2085 // Emit declaration for each field.
2086 for (const auto &field : *mFields) {
2087 switch (mStyle) {
2088 case STYLE_STRUCT:
2089 {
2090 out << "struct_value: {\n";
2091 break;
2092 }
2093 case STYLE_UNION:
2094 {
2095 out << "union_value: {\n";
2096 break;
2097 }
Nirav Atre45e76d52018-06-04 11:49:14 -07002098 case STYLE_SAFE_UNION:
2099 {
2100 out << "safe_union_value: {\n";
2101 break;
2102 }
2103 default:
2104 {
2105 CHECK(!"Should not be here");
2106 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002107 }
2108 out.indent();
2109 out << "name: \"" << field->name() << "\"\n";
Steven Moreland368e4602018-02-16 14:21:49 -08002110 field->type().emitVtsAttributeType(out);
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002111 out.unindent();
2112 out << "}\n";
2113 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07002114}
2115
Steven Moreland368e4602018-02-16 14:21:49 -08002116void CompoundType::emitVtsAttributeType(Formatter& out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07002117 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07002118 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07002119}
2120
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002121bool CompoundType::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
Nirav Atre66842a92018-06-28 18:14:13 -07002122 if (mStyle == STYLE_UNION) {
Andreas Huber0fa9e392016-08-31 09:05:44 -07002123 return false;
2124 }
2125
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002126 for (const auto* field : *mFields) {
2127 if (!field->get()->isJavaCompatible(visited)) {
Andreas Huber0fa9e392016-08-31 09:05:44 -07002128 return false;
2129 }
2130 }
2131
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002132 return Scope::deepIsJavaCompatible(visited);
Andreas Huber85eabdb2016-08-25 11:24:49 -07002133}
2134
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002135bool CompoundType::deepContainsPointer(std::unordered_set<const Type*>* visited) const {
2136 for (const auto* field : *mFields) {
2137 if (field->get()->containsPointer(visited)) {
Andreas Huber60d3b222017-03-30 09:10:56 -07002138 return true;
2139 }
2140 }
2141
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002142 return Scope::deepContainsPointer(visited);
Andreas Huber60d3b222017-03-30 09:10:56 -07002143}
2144
Andreas Huber85eabdb2016-08-25 11:24:49 -07002145void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
Nirav Atre45e76d52018-06-04 11:49:14 -07002146 CompoundLayout layout = getCompoundAlignmentAndSize();
2147 *align = layout.overall.align;
2148 *size = layout.overall.size;
2149}
Andreas Huber85eabdb2016-08-25 11:24:49 -07002150
Nirav Atre45e76d52018-06-04 11:49:14 -07002151CompoundType::CompoundLayout CompoundType::getCompoundAlignmentAndSize() const {
2152 CompoundLayout compoundLayout;
2153
2154 // Local aliases for convenience
2155 Layout& overall = compoundLayout.overall;
2156 Layout& innerStruct = compoundLayout.innerStruct;
2157 Layout& discriminator = compoundLayout.discriminator;
2158
Steven Moreland5dec82f2018-10-10 13:33:29 -07002159 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre12c597a2018-06-28 09:35:24 -07002160 getUnionDiscriminatorType()->getAlignmentAndSize(
2161 &(discriminator.align), &(discriminator.size));
2162
2163 innerStruct.offset = discriminator.size;
2164 }
2165
Andreas Huber85eabdb2016-08-25 11:24:49 -07002166 for (const auto &field : *mFields) {
Nirav Atre45e76d52018-06-04 11:49:14 -07002167
Andreas Huber85eabdb2016-08-25 11:24:49 -07002168 // Each field is aligned according to its alignment requirement.
2169 // The surrounding structure's alignment is the maximum of its
2170 // fields' aligments.
Andreas Huber85eabdb2016-08-25 11:24:49 -07002171 size_t fieldAlign, fieldSize;
2172 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
Nirav Atre45e76d52018-06-04 11:49:14 -07002173 size_t lPad = Layout::getPad(innerStruct.size, fieldAlign);
Andreas Huber85eabdb2016-08-25 11:24:49 -07002174
Nirav Atre45e76d52018-06-04 11:49:14 -07002175 innerStruct.size = (mStyle == STYLE_STRUCT)
2176 ? (innerStruct.size + lPad + fieldSize)
2177 : std::max(innerStruct.size, fieldSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -07002178
Nirav Atre45e76d52018-06-04 11:49:14 -07002179 innerStruct.align = std::max(innerStruct.align, fieldAlign);
2180 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07002181
Nirav Atre12c597a2018-06-28 09:35:24 -07002182 // Pad the inner structure's size
Nirav Atre45e76d52018-06-04 11:49:14 -07002183 innerStruct.size += Layout::getPad(innerStruct.size,
2184 innerStruct.align);
2185
Nirav Atre12c597a2018-06-28 09:35:24 -07002186 // Compute its final offset
2187 innerStruct.offset += Layout::getPad(innerStruct.offset,
2188 innerStruct.align);
Nirav Atre45e76d52018-06-04 11:49:14 -07002189
Nirav Atre12c597a2018-06-28 09:35:24 -07002190 overall.size = innerStruct.offset + innerStruct.size;
Nirav Atre45e76d52018-06-04 11:49:14 -07002191
2192 // An empty struct/union still occupies a byte of space in C++.
2193 if (overall.size == 0) {
2194 overall.size = 1;
2195 }
2196
Nirav Atre12c597a2018-06-28 09:35:24 -07002197 // Pad the overall structure's size
Nirav Atre45e76d52018-06-04 11:49:14 -07002198 overall.align = std::max(innerStruct.align, discriminator.align);
2199 overall.size += Layout::getPad(overall.size, overall.align);
2200
2201 return compoundLayout;
2202}
2203
2204std::unique_ptr<ScalarType> CompoundType::getUnionDiscriminatorType() const {
2205 static const std::vector<std::pair<int, ScalarType::Kind> > scalars {
2206 {8, ScalarType::Kind::KIND_UINT8},
2207 {16, ScalarType::Kind::KIND_UINT16},
2208 {32, ScalarType::Kind::KIND_UINT32},
2209 };
2210
Steven Moreland967c2432018-10-10 12:50:43 -07002211 size_t numFields = mFields->size();
Nirav Atre45e76d52018-06-04 11:49:14 -07002212 auto kind = ScalarType::Kind::KIND_UINT64;
2213
2214 for (const auto& scalar : scalars) {
2215 if (numFields <= (1ULL << scalar.first)) {
2216 kind = scalar.second; break;
Andreas Huber85eabdb2016-08-25 11:24:49 -07002217 }
2218 }
2219
Yi Kong56758da2018-07-24 16:21:37 -07002220 return std::unique_ptr<ScalarType>(new ScalarType(kind, nullptr));
Nirav Atre45e76d52018-06-04 11:49:14 -07002221}
Andreas Huber85eabdb2016-08-25 11:24:49 -07002222
Nirav Atre45e76d52018-06-04 11:49:14 -07002223size_t CompoundType::Layout::getPad(size_t offset, size_t align) {
2224 size_t remainder = offset % align;
2225 return (remainder > 0) ? (align - remainder) : 0;
Andreas Huber70a59e12016-08-16 12:57:01 -07002226}
2227
Andreas Huberc9410c72016-07-28 12:18:40 -07002228} // namespace android
2229