blob: 4d348fb75b51c8a49a91158b3de40bc1ea649c31 [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 Moreland7df0f392018-10-31 13:23:22 -070059 if (type.isInterface()) {
Steven Morelandd927e5c2018-07-10 16:03:43 -070060 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
Steven Moreland5add34d2018-11-08 16:31:30 -0800213void CompoundType::emitSafeUnionUnknownDiscriminatorError(Formatter& out, const std::string& value,
214 bool fatal) const {
215 if (fatal) {
216 out << "::android::hardware::details::logAlwaysFatal(";
217 } else {
218 out << "ALOGE(\"%s\", ";
219 }
220 out << "(\n";
Nirav Atree3cae852018-07-16 12:19:16 -0700221 out.indent(2, [&] {
222 out << "\"Unknown union discriminator (value: \" +\n"
223 << "std::to_string(" << getUnionDiscriminatorType()->getCppTypeCast(value)
224 << ") + \").\").c_str());\n";
225 });
226}
227
Nirav Atreca7a5022018-06-29 20:43:49 -0700228void CompoundType::emitSafeUnionReaderWriterForInterfaces(
229 Formatter &out,
230 const std::string &name,
231 const std::string &parcelObj,
232 bool parcelObjIsPointer,
233 bool isReader,
234 ErrorMode mode) const {
235
236 CHECK(mStyle == STYLE_SAFE_UNION);
Nirav Atreca7a5022018-06-29 20:43:49 -0700237
238 out.block([&] {
239 const auto discriminatorType = getUnionDiscriminatorType();
240 if (isReader) {
241 out << discriminatorType->getCppStackType()
242 << " _hidl_d_primitive;\n";
243 } else {
244 out << "const "
245 << discriminatorType->getCppStackType()
246 << " _hidl_d_primitive = "
247 << discriminatorType->getCppTypeCast(name + ".getDiscriminator()")
248 << ";\n";
249 }
250
251 getUnionDiscriminatorType()->emitReaderWriter(out, "_hidl_d_primitive", parcelObj,
252 parcelObjIsPointer, isReader, mode);
253 out << "switch (("
254 << fullName()
255 << "::hidl_discriminator) _hidl_d_primitive) ";
256
257 out.block([&] {
258 for (const auto& field : *mFields) {
259 out << "case "
260 << fullName()
261 << "::hidl_discriminator::"
262 << field->name()
263 << ": ";
264
265 const std::string tempFieldName = "_hidl_temp_" + field->name();
266 out.block([&] {
267 if (isReader) {
268 out << field->type().getCppResultType()
269 << " "
270 << tempFieldName
271 << ";\n";
272
273 field->type().emitReaderWriter(out, tempFieldName, parcelObj,
274 parcelObjIsPointer, isReader, mode);
275
276 const std::string derefOperator = field->type().resultNeedsDeref()
277 ? "*" : "";
278 out << name
279 << "."
280 << field->name()
Nirav Atre64868d32018-07-15 19:15:18 -0700281 << "(std::move("
Nirav Atreca7a5022018-06-29 20:43:49 -0700282 << derefOperator
283 << tempFieldName
Nirav Atre64868d32018-07-15 19:15:18 -0700284 << "));\n";
Nirav Atreca7a5022018-06-29 20:43:49 -0700285 } else {
286 const std::string fieldValue = name + "." + field->name() + "()";
287 out << field->type().getCppArgumentType()
288 << " "
289 << tempFieldName
290 << " = "
291 << fieldValue
292 << ";\n";
293
294 field->type().emitReaderWriter(out, tempFieldName, parcelObj,
295 parcelObjIsPointer, isReader, mode);
296 }
297 out << "break;\n";
298 }).endl();
299 }
300
Nirav Atreca7a5022018-06-29 20:43:49 -0700301 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -0800302 out.block([&] {
303 emitSafeUnionUnknownDiscriminatorError(out, "_hidl_d_primitive",
304 !isReader /*fatal*/);
305 if (isReader) {
306 out << "_hidl_err = BAD_VALUE;\n";
307 handleError(out, mode);
308 }
309 })
Nirav Atree3cae852018-07-16 12:19:16 -0700310 .endl();
Nirav Atreca7a5022018-06-29 20:43:49 -0700311 }).endl();
312 }).endl();
313}
314
Andreas Huber881227d2016-08-02 14:20:21 -0700315void CompoundType::emitReaderWriter(
316 Formatter &out,
317 const std::string &name,
318 const std::string &parcelObj,
319 bool parcelObjIsPointer,
320 bool isReader,
321 ErrorMode mode) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700322
323 const std::string parcelObjDeref =
324 parcelObj + (parcelObjIsPointer ? "->" : ".");
325
Howard Chenecfb4512017-11-21 18:28:53 +0800326 if(containsInterface()){
Nirav Atreca7a5022018-06-29 20:43:49 -0700327 if (mStyle == STYLE_SAFE_UNION) {
328 emitSafeUnionReaderWriterForInterfaces(out, name, parcelObj,
329 parcelObjIsPointer,
330 isReader, mode);
331 return;
332 }
333
Howard Chenecfb4512017-11-21 18:28:53 +0800334 for (const auto& field : *mFields) {
Nirav Atre1d565622018-07-13 15:41:21 -0700335 const std::string tempFieldName = "_hidl_temp_" + field->name();
336 const std::string fieldValue = name + "." + field->name();
337
338 out.block([&] {
339 if (isReader) {
340 out << field->type().getCppResultType()
341 << " "
342 << tempFieldName
343 << ";\n";
344 } else {
345 out << field->type().getCppArgumentType()
346 << " "
347 << tempFieldName
348 << " = "
349 << fieldValue
350 << ";\n";
351 }
352
353 field->type().emitReaderWriter(out, tempFieldName, parcelObj,
354 parcelObjIsPointer, isReader, mode);
355 if (isReader) {
356 const std::string derefOperator = field->type().resultNeedsDeref()
357 ? "*" : "";
358 out << fieldValue
359 << " = std::move("
360 << derefOperator
361 << tempFieldName
362 << ");\n";
363 }
364 }).endl();
Howard Chenecfb4512017-11-21 18:28:53 +0800365 }
Andreas Huber881227d2016-08-02 14:20:21 -0700366 } else {
Howard Chenecfb4512017-11-21 18:28:53 +0800367 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700368
Howard Chenecfb4512017-11-21 18:28:53 +0800369 out << "size_t " << parentName << ";\n\n";
370
371 if (isReader) {
372 out << "_hidl_err = " << parcelObjDeref << "readBuffer("
373 << "sizeof(*" << name << "), &" << parentName << ", "
374 << " const_cast<const void**>(reinterpret_cast<void **>("
375 << "&" << name << ")));\n";
376 handleError(out, mode);
377 } else {
378 out << "_hidl_err = "
379 << parcelObjDeref
380 << "writeBuffer(&"
381 << name
382 << ", sizeof("
383 << name
384 << "), &"
385 << parentName
386 << ");\n";
387 handleError(out, mode);
388 }
Nirav Atre45e76d52018-06-04 11:49:14 -0700389
390 bool needEmbeddedReadWrite = needsEmbeddedReadWrite();
391 CHECK(mStyle != STYLE_UNION || !needEmbeddedReadWrite);
392
393 if (needEmbeddedReadWrite) {
Howard Chenecfb4512017-11-21 18:28:53 +0800394 emitReaderWriterEmbedded(out, 0 /* depth */, name, name, /* sanitizedName */
395 isReader /* nameIsPointer */, parcelObj, parcelObjIsPointer,
396 isReader, mode, parentName, "0 /* parentOffset */");
397 }
Andreas Huber881227d2016-08-02 14:20:21 -0700398 }
Andreas Huber881227d2016-08-02 14:20:21 -0700399}
400
401void CompoundType::emitReaderWriterEmbedded(
402 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700403 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700404 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700405 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700406 bool nameIsPointer,
407 const std::string &parcelObj,
408 bool parcelObjIsPointer,
409 bool isReader,
410 ErrorMode mode,
411 const std::string &parentName,
412 const std::string &offsetText) const {
413 emitReaderWriterEmbeddedForTypeName(
414 out,
415 name,
416 nameIsPointer,
417 parcelObj,
418 parcelObjIsPointer,
419 isReader,
420 mode,
421 parentName,
422 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700423 fullName(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800424 "" /* childName */,
425 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700426}
427
Andreas Huber85eabdb2016-08-25 11:24:49 -0700428void CompoundType::emitJavaReaderWriter(
429 Formatter &out,
430 const std::string &parcelObj,
431 const std::string &argName,
432 bool isReader) const {
433 if (isReader) {
434 out << "new " << fullJavaName() << "();\n";
435 }
436
Steven Morelandc22e8122018-10-10 13:06:39 -0700437 out << "(" << getJavaTypeCast(argName) << ")."
438 << (isReader ? "readFromParcel" : "writeToParcel") << "(" << parcelObj << ");\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700439}
440
441void CompoundType::emitJavaFieldInitializer(
442 Formatter &out, const std::string &fieldName) const {
Nirav Atre1d565622018-07-13 15:41:21 -0700443 const std::string fieldDeclaration = fullJavaName() + " " + fieldName;
Nirav Atre66842a92018-06-28 18:14:13 -0700444 emitJavaFieldDefaultInitialValue(out, fieldDeclaration);
445}
446
447void CompoundType::emitJavaFieldDefaultInitialValue(
448 Formatter &out, const std::string &declaredFieldName) const {
449 out << declaredFieldName
Andreas Huber85eabdb2016-08-25 11:24:49 -0700450 << " = new "
451 << fullJavaName()
452 << "();\n";
453}
454
455void CompoundType::emitJavaFieldReaderWriter(
456 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700457 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700458 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700459 const std::string &blobName,
460 const std::string &fieldName,
461 const std::string &offset,
462 bool isReader) const {
463 if (isReader) {
Nirav Atre66842a92018-06-28 18:14:13 -0700464 out << "("
465 << getJavaTypeCast(fieldName)
466 << ").readEmbeddedFromParcel("
Andreas Huber709b62d2016-09-19 11:21:18 -0700467 << parcelName
468 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700469 << blobName
470 << ", "
471 << offset
472 << ");\n";
473
474 return;
475 }
476
477 out << fieldName
478 << ".writeEmbeddedToBlob("
479 << blobName
480 << ", "
481 << offset
482 << ");\n";
483}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700484void CompoundType::emitResolveReferences(
485 Formatter &out,
486 const std::string &name,
487 bool nameIsPointer,
488 const std::string &parcelObj,
489 bool parcelObjIsPointer,
490 bool isReader,
491 ErrorMode mode) const {
492 emitResolveReferencesEmbedded(
493 out,
494 0 /* depth */,
495 name,
496 name /* sanitizedName */,
497 nameIsPointer,
498 parcelObj,
499 parcelObjIsPointer,
500 isReader,
501 mode,
502 "_hidl_" + name + "_parent",
503 "0 /* parentOffset */");
504}
505
506void CompoundType::emitResolveReferencesEmbedded(
507 Formatter &out,
508 size_t /* depth */,
509 const std::string &name,
510 const std::string &/* sanitizedName */,
511 bool nameIsPointer,
512 const std::string &parcelObj,
513 bool parcelObjIsPointer,
514 bool isReader,
515 ErrorMode mode,
516 const std::string &parentName,
517 const std::string &offsetText) const {
518 CHECK(needsResolveReferences());
519
520 const std::string parcelObjDeref =
521 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
522
523 const std::string parcelObjPointer =
524 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
525
Yifan Hong244e82d2016-11-11 11:13:57 -0800526 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700527 const std::string namePointer = nameIsPointer ? name : ("&" + name);
528
529 out << "_hidl_err = ";
530
531 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800532 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700533 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800534 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700535 }
536
Yifan Hong33223ca2016-12-13 15:07:35 -0800537 out.indent(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800538 if (isReader) {
539 out << "const_cast<"
540 << fullName()
541 << " *"
542 << ">("
543 << namePointer
544 << "),\n"
545 << parcelObjDeref;
546 } else {
547 out << nameDerefed
548 << ",\n"
549 << parcelObjPointer;
550 }
551
552 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700553 << parentName
554 << ",\n"
555 << offsetText
556 << ");\n\n";
557 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700558
559 handleError(out, mode);
560}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700561
Nirav Atre45e76d52018-06-04 11:49:14 -0700562void CompoundType::emitLayoutAsserts(Formatter& out, const Layout& layout,
563 const std::string& layoutName) const {
564 out << "static_assert(sizeof("
565 << fullName()
566 << layoutName
567 << ") == "
568 << layout.size
569 << ", \"wrong size\");\n";
570
571 out << "static_assert(__alignof("
572 << fullName()
573 << layoutName
574 << ") == "
575 << layout.align
576 << ", \"wrong alignment\");\n";
577}
578
579void CompoundType::emitSafeUnionTypeDeclarations(Formatter& out) const {
580 out << "struct "
581 << localName()
582 << " final {\n";
583
584 out.indent();
585
586 Scope::emitTypeDeclarations(out);
587
Nirav Atre12c597a2018-06-28 09:35:24 -0700588 bool hasPointer = containsPointer();
589 CompoundLayout layout = hasPointer
590 ? CompoundLayout()
591 : getCompoundAlignmentAndSize();
592
Nirav Atre45e76d52018-06-04 11:49:14 -0700593 out << "enum class hidl_discriminator : "
594 << getUnionDiscriminatorType()->getCppType(StorageMode_Stack, false)
595 << " ";
596
597 out.block([&] {
Nirav Atre71ce0082018-08-01 15:39:49 -0700598 const auto elements = getSafeUnionEnumElements(true /* useCppTypeName */);
599 for (size_t i = 0; i < elements.size(); i++) {
600 out << elements[i].fieldName
601 << " = "
602 << i
603 << ",";
604
605 if (!elements[i].fieldTypeName.empty()) {
606 out << " // "
607 << elements[i].fieldTypeName;
608 }
609 out << "\n";
Nirav Atre45e76d52018-06-04 11:49:14 -0700610 }
Nirav Atre45e76d52018-06-04 11:49:14 -0700611 });
612 out << ";\n\n";
613
Nirav Atre64868d32018-07-15 19:15:18 -0700614 out << localName() << "();\n" // Constructor
615 << "~" << localName() << "();\n" // Destructor
616 << localName() << "(" << localName() << "&&);\n" // Move constructor
617 << localName() << "(const " << localName() << "&);\n" // Copy constructor
618 << localName() << "& operator=(" << localName() << "&&);\n" // Move assignment
619 << localName() << "& operator=(const " << localName() << "&);\n\n"; // Copy assignment
Nirav Atre45e76d52018-06-04 11:49:14 -0700620
621 for (const auto& field : *mFields) {
Nirav Atre64868d32018-07-15 19:15:18 -0700622 // Setter (copy)
Nirav Atre45e76d52018-06-04 11:49:14 -0700623 out << "void "
624 << field->name()
625 << "("
626 << field->type().getCppArgumentType()
627 << ");\n";
628
Steven Moreland492bada2018-09-13 16:12:32 -0700629 if (field->type().resolveToScalarType() == nullptr) {
Nirav Atre64868d32018-07-15 19:15:18 -0700630 // Setter (move)
631 out << "void "
632 << field->name()
633 << "("
634 << field->type().getCppStackType()
635 << "&&);\n";
636 }
637
638 // Getter (mutable)
Nirav Atre45e76d52018-06-04 11:49:14 -0700639 out << field->type().getCppStackType()
640 << "& "
641 << field->name()
642 << "();\n";
643
Nirav Atre64868d32018-07-15 19:15:18 -0700644 // Getter (immutable)
Nirav Atre45e76d52018-06-04 11:49:14 -0700645 out << field->type().getCppArgumentType()
646 << " "
647 << field->name()
648 << "() const;\n\n";
649 }
650
Nirav Atre12c597a2018-06-28 09:35:24 -0700651 out << "// Utility methods\n";
Nirav Atre45e76d52018-06-04 11:49:14 -0700652 out << "hidl_discriminator getDiscriminator() const;\n\n";
653
Nirav Atre12c597a2018-06-28 09:35:24 -0700654 out << "constexpr size_t hidl_getUnionOffset() const ";
655 out.block([&] {
656 out << "return offsetof(" << fullName() << ", hidl_u);\n";
657 }).endl().endl();
658
Nirav Atre45e76d52018-06-04 11:49:14 -0700659 out.unindent();
660 out << "private:\n";
661 out.indent();
662
663 out << "void hidl_destructUnion();\n\n";
Nirav Atre12c597a2018-06-28 09:35:24 -0700664
665 out << "hidl_discriminator hidl_d";
666 if (!hasPointer) {
667 out << " __attribute__ ((aligned("
668 << layout.discriminator.align << "))) ";
669 }
Steven Moreland967c2432018-10-10 12:50:43 -0700670 out << ";\n";
Nirav Atre45e76d52018-06-04 11:49:14 -0700671 out << "union hidl_union final {\n";
672 out.indent();
673
Nirav Atre45e76d52018-06-04 11:49:14 -0700674 for (const auto& field : *mFields) {
675
676 size_t fieldAlign, fieldSize;
677 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
678
679 out << field->type().getCppStackType()
680 << " "
681 << field->name();
682
683 if (!hasPointer) {
684 out << " __attribute__ ((aligned("
685 << fieldAlign
686 << ")))";
687 }
688 out << ";\n";
689 }
690
691 out << "\n"
692 << "hidl_union();\n"
693 << "~hidl_union();\n";
694
695 out.unindent();
Nirav Atre12c597a2018-06-28 09:35:24 -0700696 out << "} hidl_u;\n";
Nirav Atre45e76d52018-06-04 11:49:14 -0700697
698 if (!hasPointer) {
699 out << "\n";
700
701 emitLayoutAsserts(out, layout.innerStruct, "::hidl_union");
702 emitLayoutAsserts(out, layout.discriminator, "::hidl_discriminator");
703 }
704
705 out.unindent();
706 out << "};\n\n";
707
708 if (!hasPointer) {
709 emitLayoutAsserts(out, layout.overall, "");
710 out << "\n";
711 }
712}
713
Steven Moreland368e4602018-02-16 14:21:49 -0800714void CompoundType::emitTypeDeclarations(Formatter& out) const {
Nirav Atre45e76d52018-06-04 11:49:14 -0700715 if (mStyle == STYLE_SAFE_UNION) {
716 emitSafeUnionTypeDeclarations(out);
717 return;
718 }
719
Andreas Huber881227d2016-08-02 14:20:21 -0700720 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
721 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700722 << localName()
Yifan Hongb1d2ebc2016-12-20 17:18:07 -0800723 << " final {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700724
725 out.indent();
726
727 Scope::emitTypeDeclarations(out);
728
Andreas Huber60d3b222017-03-30 09:10:56 -0700729 if (containsPointer()) {
Andreas Huberca4bc892017-01-09 14:58:12 -0800730 for (const auto &field : *mFields) {
Steven Moreland49bad8d2018-05-17 15:45:26 -0700731 field->emitDocComment(out);
Andreas Huberca4bc892017-01-09 14:58:12 -0800732 out << field->type().getCppStackType()
733 << " "
734 << field->name()
735 << ";\n";
736 }
737
738 out.unindent();
739 out << "};\n\n";
740
Steven Moreland368e4602018-02-16 14:21:49 -0800741 return;
Andreas Huber881227d2016-08-02 14:20:21 -0700742 }
743
Andreas Huberca4bc892017-01-09 14:58:12 -0800744 for (int pass = 0; pass < 2; ++pass) {
745 size_t offset = 0;
746 for (const auto &field : *mFields) {
747 size_t fieldAlign, fieldSize;
748 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
749
Nirav Atre45e76d52018-06-04 11:49:14 -0700750 offset += Layout::getPad(offset, fieldAlign);
Andreas Huberca4bc892017-01-09 14:58:12 -0800751
752 if (pass == 0) {
753 out << field->type().getCppStackType()
754 << " "
755 << field->name()
756 << " __attribute__ ((aligned("
757 << fieldAlign
758 << ")));\n";
759 } else {
760 out << "static_assert(offsetof("
761 << fullName()
762 << ", "
763 << field->name()
764 << ") == "
765 << offset
766 << ", \"wrong offset\");\n";
767 }
768
Andreas Huber60d3b222017-03-30 09:10:56 -0700769 if (mStyle == STYLE_STRUCT) {
770 offset += fieldSize;
771 }
Andreas Huberca4bc892017-01-09 14:58:12 -0800772 }
773
774 if (pass == 0) {
775 out.unindent();
776 out << "};\n\n";
777 }
778 }
779
Nirav Atre45e76d52018-06-04 11:49:14 -0700780 CompoundLayout layout = getCompoundAlignmentAndSize();
781 emitLayoutAsserts(out, layout.overall, "");
782 out << "\n";
Yifan Hong244e82d2016-11-11 11:13:57 -0800783}
784
Timur Iskhakovfd3f2502017-09-05 16:25:02 -0700785void CompoundType::emitTypeForwardDeclaration(Formatter& out) const {
Nirav Atre45e76d52018-06-04 11:49:14 -0700786 switch (mStyle) {
787 case STYLE_UNION: {
788 out << "union";
789 break;
790 }
791 case STYLE_STRUCT:
792 case STYLE_SAFE_UNION: {
793 out << "struct";
794 break;
795 }
796 default: {
797 CHECK(!"Should not be here");
798 }
799 }
800 out << " " << localName() << ";\n";
Timur Iskhakovfd3f2502017-09-05 16:25:02 -0700801}
Yifan Hong244e82d2016-11-11 11:13:57 -0800802
Steven Moreland368e4602018-02-16 14:21:49 -0800803void CompoundType::emitPackageTypeDeclarations(Formatter& out) const {
Steven Moreland4b8f7a12017-11-17 15:39:54 -0800804 Scope::emitPackageTypeDeclarations(out);
Yifan Hongc6752dc2016-12-20 14:00:14 -0800805
Steven Morelandbf714212017-10-27 18:29:01 -0700806 out << "static inline std::string toString("
807 << getCppArgumentType()
808 << (mFields->empty() ? "" : " o")
Steven Moreland09c6ebe2018-10-09 10:15:48 -0700809 << ");\n";
810
811 if (canCheckEquality()) {
812 out << "static inline bool operator==("
813 << getCppArgumentType() << " lhs, " << getCppArgumentType() << " rhs);\n";
814
815 out << "static inline bool operator!=("
816 << getCppArgumentType() << " lhs, " << getCppArgumentType() << " rhs);\n";
817 } else {
818 out << "// operator== and operator!= are not generated for " << localName() << "\n";
819 }
820
821 out.endl();
822}
823
824void CompoundType::emitPackageTypeHeaderDefinitions(Formatter& out) const {
825 Scope::emitPackageTypeHeaderDefinitions(out);
826
827 out << "static inline std::string toString("
828 << getCppArgumentType()
829 << (mFields->empty() ? "" : " o")
Steven Morelandbf714212017-10-27 18:29:01 -0700830 << ") ";
831
832 out.block([&] {
833 // include toString for scalar types
834 out << "using ::android::hardware::toString;\n"
835 << "std::string os;\n";
836 out << "os += \"{\";\n";
837
Steven Moreland5dec82f2018-10-10 13:33:29 -0700838 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -0700839 out << "\nswitch (o.getDiscriminator()) {\n";
840 out.indent();
Steven Morelandbf714212017-10-27 18:29:01 -0700841 }
842
Nirav Atre45e76d52018-06-04 11:49:14 -0700843 for (const NamedReference<Type>* field : *mFields) {
844 if (mStyle == STYLE_SAFE_UNION) {
845 out << "case "
846 << fullName()
847 << "::hidl_discriminator::"
848 << field->name()
849 << ": ";
850
851 out.block([&] {
852 out << "os += \"."
853 << field->name()
854 << " = \";\n"
855 << "os += toString(o."
856 << field->name()
857 << "());\n"
858 << "break;\n";
859 }).endl();
860 } else {
861 out << "os += \"";
862 if (field != *(mFields->begin())) {
863 out << ", ";
864 }
865 out << "." << field->name() << " = \";\n";
866 field->type().emitDump(out, "os", "o." + field->name());
867 }
868 }
869
Steven Moreland5dec82f2018-10-10 13:33:29 -0700870 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -0700871 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -0800872 out.block([&] {
873 emitSafeUnionUnknownDiscriminatorError(out, "o.getDiscriminator()",
874 true /*fatal*/);
875 })
Nirav Atree3cae852018-07-16 12:19:16 -0700876 .endl();
Nirav Atre45e76d52018-06-04 11:49:14 -0700877
878 out.unindent();
879 out << "}\n";
880 }
Steven Morelandbf714212017-10-27 18:29:01 -0700881 out << "os += \"}\"; return os;\n";
882 }).endl().endl();
883
884 if (canCheckEquality()) {
885 out << "static inline bool operator==("
886 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
887 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
888 out.block([&] {
Steven Moreland5dec82f2018-10-10 13:33:29 -0700889 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -0700890 out.sIf("lhs.getDiscriminator() != rhs.getDiscriminator()", [&] {
Steven Morelandbf714212017-10-27 18:29:01 -0700891 out << "return false;\n";
892 }).endl();
Nirav Atre45e76d52018-06-04 11:49:14 -0700893
894 out << "switch (lhs.getDiscriminator()) {\n";
895 out.indent();
896 }
897
898 for (const auto& field : *mFields) {
899 if (mStyle == STYLE_SAFE_UNION) {
900 out << "case "
901 << fullName()
902 << "::hidl_discriminator::"
903 << field->name()
904 << ": ";
905
906 out.block([&] {
907 out << "return (lhs."
908 << field->name()
909 << "() == rhs."
910 << field->name()
911 << "());\n";
912 }).endl();
913 } else {
914 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
915 out << "return false;\n";
916 }).endl();
917 }
918 }
919
Steven Moreland5dec82f2018-10-10 13:33:29 -0700920 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -0700921 out << "default: ";
922 out.block([&] {
Steven Moreland5add34d2018-11-08 16:31:30 -0800923 emitSafeUnionUnknownDiscriminatorError(out, "lhs.getDiscriminator()",
924 true /*fatal*/);
Nirav Atree3cae852018-07-16 12:19:16 -0700925 })
926 .endl();
Nirav Atre45e76d52018-06-04 11:49:14 -0700927
928 out.unindent();
929 out << "}\n";
Steven Morelandbf714212017-10-27 18:29:01 -0700930 }
931 out << "return true;\n";
932 }).endl().endl();
933
934 out << "static inline bool operator!=("
Steven Moreland09c6ebe2018-10-09 10:15:48 -0700935 << getCppArgumentType() << " lhs, " << getCppArgumentType() << " rhs)";
Steven Morelandbf714212017-10-27 18:29:01 -0700936 out.block([&] {
937 out << "return !(lhs == rhs);\n";
938 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -0700939 } else {
Steven Morelandf91048a2017-06-23 21:38:35 +0000940 out << "// operator== and operator!= are not generated for " << localName() << "\n\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800941 }
Yifan Hongc6752dc2016-12-20 14:00:14 -0800942}
943
Steven Moreland368e4602018-02-16 14:21:49 -0800944void CompoundType::emitPackageHwDeclarations(Formatter& out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700945 if (needsEmbeddedReadWrite()) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800946 out << "::android::status_t readEmbeddedFromParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700947
Yifan Hong0a68a282016-10-21 16:32:34 -0700948 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700949
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700950 out << "const " << fullName() << " &obj,\n"
Yifan Hong244e82d2016-11-11 11:13:57 -0800951 << "const ::android::hardware::Parcel &parcel,\n"
952 << "size_t parentHandle,\n"
953 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700954
Yifan Hong0a68a282016-10-21 16:32:34 -0700955 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700956
957 out << "::android::status_t writeEmbeddedToParcel(\n";
958
Yifan Hong0a68a282016-10-21 16:32:34 -0700959 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700960
Yifan Hong244e82d2016-11-11 11:13:57 -0800961 out << "const " << fullName() << " &obj,\n"
962 << "::android::hardware::Parcel *parcel,\n"
963 << "size_t parentHandle,\n"
964 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700965
Yifan Hong0a68a282016-10-21 16:32:34 -0700966 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700967 }
968
Yifan Hongbf459bc2016-08-23 16:50:37 -0700969 if(needsResolveReferences()) {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700970 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700971 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800972 out << fullName() << " *obj,\n"
973 << "const ::android::hardware::Parcel &parcel,\n"
974 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700975 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700976 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700977 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800978 out << "const " << fullName() << " &obj,\n"
979 << "::android::hardware::Parcel *,\n"
980 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700981 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700982 }
Andreas Huber881227d2016-08-02 14:20:21 -0700983}
984
Nirav Atre64868d32018-07-15 19:15:18 -0700985static void emitSafeUnionFieldConstructor(Formatter& out,
986 const NamedReference<Type>* field,
987 const std::string& initializerObjectName) {
988 out << "new (&hidl_u."
989 << field->name()
990 << ") "
991 << field->type().getCppStackType()
992 << "("
993 << initializerObjectName
994 << ");\n";
995}
996
997static void emitSafeUnionSetterDefinition(Formatter& out,
998 const NamedReference<Type>* field,
999 const std::string& parameterName,
1000 bool usesMoveSemantics) {
1001 out.block([&] {
1002 out << "if (hidl_d != hidl_discriminator::"
1003 << field->name()
1004 << ") ";
1005
1006 const std::string argumentName = usesMoveSemantics
1007 ? ("std::move(" + parameterName + ")")
1008 : parameterName;
1009 out.block([&] {
1010 out << "hidl_destructUnion();\n"
1011 << "::std::memset(&hidl_u, 0, sizeof(hidl_u));\n\n";
1012
1013 emitSafeUnionFieldConstructor(out, field, argumentName);
1014 out << "hidl_d = hidl_discriminator::"
1015 << field->name()
1016 << ";\n";
1017 }).endl();
1018
1019 out << "else if (&(hidl_u."
1020 << field->name()
1021 << ") != &"
1022 << parameterName
1023 << ") ";
1024
1025 out.block([&] {
1026 out << "hidl_u."
1027 << field->name()
1028 << " = "
1029 << argumentName
1030 << ";\n";
1031 }).endl();
1032 }).endl().endl();
1033}
1034
1035static void emitSafeUnionGetterDefinition(Formatter& out, const std::string& fieldName) {
Nirav Atre45e76d52018-06-04 11:49:14 -07001036 out.block([&] {
1037 out << "if (CC_UNLIKELY(hidl_d != hidl_discriminator::"
1038 << fieldName
1039 << ")) ";
1040
1041 out.block([&] {
Steven Moreland35835f12018-11-08 17:04:16 -08001042 out << "LOG_ALWAYS_FATAL(\"Bad safe_union access: safe_union has discriminator %\" "
1043 << "PRIu64 \" but discriminator %\" PRIu64 \" was accessed.\",\n";
1044 out.indent(2, [&] {
1045 out << "static_cast<uint64_t>(hidl_d), "
1046 << "static_cast<uint64_t>(hidl_discriminator::" << fieldName << "));";
1047 }).endl();
Nirav Atre45e76d52018-06-04 11:49:14 -07001048 }).endl().endl();
1049
1050 out << "return hidl_u."
1051 << fieldName
1052 << ";\n";
1053 }).endl().endl();
1054}
1055
Nirav Atre71ce0082018-08-01 15:39:49 -07001056std::vector<CompoundType::SafeUnionEnumElement> CompoundType::getSafeUnionEnumElements(
1057 bool useCppTypeName) const {
1058 std::vector<SafeUnionEnumElement> elements;
Nirav Atre71ce0082018-08-01 15:39:49 -07001059
1060 for (const auto& field : *mFields) {
1061 const std::string fieldTypeName = useCppTypeName
1062 ? field->type().getCppStackType(true /* specifyNamespaces */)
1063 : field->type().getJavaType(true /* forInitializer */);
1064
1065 elements.push_back({field->name(), fieldTypeName});
1066 }
1067
1068 return elements;
1069}
1070
Nirav Atre64868d32018-07-15 19:15:18 -07001071void CompoundType::emitSafeUnionCopyAndAssignDefinition(Formatter& out,
1072 const std::string& parameterName,
1073 bool isCopyConstructor,
1074 bool usesMoveSemantics) const {
1075 out.block([&] {
1076 if (!isCopyConstructor) {
1077 out << "if (this == &"
1078 << parameterName
1079 << ") { return *this; }\n\n";
1080 }
1081
1082 out << "switch ("
1083 << parameterName
1084 << ".hidl_d) ";
1085
1086 out.block([&] {
1087 for (const auto& field : *mFields) {
1088 const std::string parameterFieldName = (parameterName + ".hidl_u." +
1089 field->name());
1090
1091 const std::string argumentName = usesMoveSemantics
1092 ? ("std::move(" + parameterFieldName + ")")
1093 : parameterFieldName;
1094
1095 out << "case hidl_discriminator::"
1096 << field->name()
1097 << ": ";
1098
1099 if (isCopyConstructor) {
1100 out.block([&] {
1101 emitSafeUnionFieldConstructor(out, field, argumentName);
1102 out << "break;\n";
1103 }).endl();
1104 } else {
1105 out.block([&] {
1106 out << field->name()
1107 << "("
1108 << argumentName
1109 << ");\n"
1110 << "break;\n";
1111 }).endl();
1112 }
1113 }
1114
Nirav Atree3cae852018-07-16 12:19:16 -07001115 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -08001116 out.block([&] {
1117 emitSafeUnionUnknownDiscriminatorError(out, parameterName + ".hidl_d",
1118 true /*fatal*/);
1119 })
Nirav Atree3cae852018-07-16 12:19:16 -07001120 .endl();
Nirav Atre64868d32018-07-15 19:15:18 -07001121 }).endl();
1122
1123 if (isCopyConstructor) {
1124 out << "\nhidl_d = "
1125 << parameterName
1126 << ".hidl_d;\n";
1127 } else {
1128 out << "return *this;\n";
1129 }
1130 }).endl().endl();
1131}
1132
Nirav Atre45e76d52018-06-04 11:49:14 -07001133void CompoundType::emitSafeUnionTypeConstructors(Formatter& out) const {
1134
1135 // Default constructor
1136 out << fullName()
1137 << "::"
1138 << localName()
Nirav Atre12c597a2018-06-28 09:35:24 -07001139 << "() ";
1140
1141 out.block([&] {
1142 out << "static_assert(offsetof("
1143 << fullName()
1144 << ", hidl_d) == 0, \"wrong offset\");\n";
1145
Steven Moreland5e20b652019-04-22 18:42:38 -07001146 const CompoundLayout layout = getCompoundAlignmentAndSize();
1147
Nirav Atre12c597a2018-06-28 09:35:24 -07001148 if (!containsPointer()) {
Steven Moreland5e20b652019-04-22 18:42:38 -07001149 out << "static_assert(offsetof(" << fullName()
1150 << ", hidl_u) == " << layout.innerStruct.offset << ", \"wrong offset\");\n";
Nirav Atre12c597a2018-06-28 09:35:24 -07001151 }
Steven Moreland5e20b652019-04-22 18:42:38 -07001152
1153 out.endl();
1154
Steven Moreland37303be2019-04-26 16:52:38 -07001155 out << "::std::memset(&hidl_u, 0, sizeof(hidl_u));\n";
1156
Steven Moreland5e20b652019-04-22 18:42:38 -07001157 // union itself is zero'd when set
1158 // padding after descriminator
1159 size_t dpad = layout.innerStruct.offset - layout.discriminator.size;
1160 emitPaddingZero(out, layout.discriminator.size /*offset*/, dpad /*size*/);
1161
1162 size_t innerStructEnd = layout.innerStruct.offset + layout.innerStruct.size;
1163 // final padding of the struct
1164 size_t fpad = layout.overall.size - innerStructEnd;
1165 emitPaddingZero(out, innerStructEnd /*offset*/, fpad /*size*/);
1166
Steven Moreland967c2432018-10-10 12:50:43 -07001167 out.endl();
1168
1169 CHECK(!mFields->empty());
1170 out << "hidl_d = hidl_discriminator::" << mFields->at(0)->name() << ";\n";
1171 emitSafeUnionFieldConstructor(out, mFields->at(0), "");
Nirav Atre12c597a2018-06-28 09:35:24 -07001172 }).endl().endl();
Nirav Atre45e76d52018-06-04 11:49:14 -07001173
1174 // Destructor
1175 out << fullName()
1176 << "::~"
1177 << localName()
1178 << "() ";
1179
1180 out.block([&] {
1181 out << "hidl_destructUnion();\n";
1182 }).endl().endl();
1183
Nirav Atre64868d32018-07-15 19:15:18 -07001184 // Move constructor
1185 out << fullName()
1186 << "::"
1187 << localName()
1188 << "("
1189 << localName()
1190 << "&& other) ";
1191
1192 emitSafeUnionCopyAndAssignDefinition(
1193 out, "other", true /* isCopyConstructor */, true /* usesMoveSemantics */);
1194
Nirav Atre45e76d52018-06-04 11:49:14 -07001195 // Copy constructor
1196 out << fullName()
1197 << "::"
1198 << localName()
1199 << "(const "
1200 << localName()
1201 << "& other) ";
1202
Nirav Atre64868d32018-07-15 19:15:18 -07001203 emitSafeUnionCopyAndAssignDefinition(
1204 out, "other", true /* isCopyConstructor */, false /* usesMoveSemantics */);
Nirav Atre45e76d52018-06-04 11:49:14 -07001205
Nirav Atre64868d32018-07-15 19:15:18 -07001206 // Move assignment operator
1207 out << fullName()
1208 << "& ("
1209 << fullName()
1210 << "::operator=)("
1211 << localName()
1212 << "&& other) ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001213
Nirav Atre64868d32018-07-15 19:15:18 -07001214 emitSafeUnionCopyAndAssignDefinition(
1215 out, "other", false /* isCopyConstructor */, true /* usesMoveSemantics */);
Nirav Atre45e76d52018-06-04 11:49:14 -07001216
Nirav Atre64868d32018-07-15 19:15:18 -07001217 // Copy assignment operator
1218 out << fullName()
1219 << "& ("
1220 << fullName()
1221 << "::operator=)(const "
1222 << localName()
1223 << "& other) ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001224
Nirav Atre64868d32018-07-15 19:15:18 -07001225 emitSafeUnionCopyAndAssignDefinition(
1226 out, "other", false /* isCopyConstructor */, false /* usesMoveSemantics */);
Nirav Atre45e76d52018-06-04 11:49:14 -07001227}
1228
1229void CompoundType::emitSafeUnionTypeDefinitions(Formatter& out) const {
Nirav Atre45e76d52018-06-04 11:49:14 -07001230 emitSafeUnionTypeConstructors(out);
1231
1232 out << "void "
1233 << fullName()
1234 << "::hidl_destructUnion() ";
1235
1236 out.block([&] {
Nirav Atre66842a92018-06-28 18:14:13 -07001237 out << "switch (hidl_d) ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001238 out.block([&] {
1239
1240 for (const auto& field : *mFields) {
1241 out << "case hidl_discriminator::"
1242 << field->name()
1243 << ": ";
1244
1245 out.block([&] {
Steven Moreland9b37ed12018-10-25 11:10:57 -07001246 out << "::android::hardware::details::destructElement(&(hidl_u."
Nirav Atre3b4c7ff2018-07-09 11:57:02 -07001247 << field->name()
1248 << "));\n"
1249 << "break;\n";
Nirav Atre45e76d52018-06-04 11:49:14 -07001250 }).endl();
1251 }
1252
Nirav Atree3cae852018-07-16 12:19:16 -07001253 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -08001254 out.block(
1255 [&] { emitSafeUnionUnknownDiscriminatorError(out, "hidl_d", true /*fatal*/); })
1256 .endl();
Nirav Atre45e76d52018-06-04 11:49:14 -07001257 }).endl().endl();
Nirav Atre45e76d52018-06-04 11:49:14 -07001258 }).endl().endl();
1259
Nirav Atre45e76d52018-06-04 11:49:14 -07001260 for (const NamedReference<Type>* field : *mFields) {
Nirav Atre64868d32018-07-15 19:15:18 -07001261 // Setter (copy)
Nirav Atre45e76d52018-06-04 11:49:14 -07001262 out << "void "
1263 << fullName()
1264 << "::"
1265 << field->name()
1266 << "("
1267 << field->type().getCppArgumentType()
1268 << " o) ";
1269
Nirav Atre64868d32018-07-15 19:15:18 -07001270 emitSafeUnionSetterDefinition(out, field, "o", false /* usesMoveSemantics */);
1271
Steven Moreland492bada2018-09-13 16:12:32 -07001272 if (field->type().resolveToScalarType() == nullptr) {
Nirav Atre64868d32018-07-15 19:15:18 -07001273 // Setter (move)
1274 out << "void "
1275 << fullName()
1276 << "::"
Nirav Atre45e76d52018-06-04 11:49:14 -07001277 << field->name()
Nirav Atre64868d32018-07-15 19:15:18 -07001278 << "("
1279 << field->type().getCppStackType()
1280 << "&& o) ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001281
Nirav Atre64868d32018-07-15 19:15:18 -07001282 emitSafeUnionSetterDefinition(out, field, "o", true /* usesMoveSemantics */);
1283 }
Nirav Atre45e76d52018-06-04 11:49:14 -07001284
1285 // Getter (mutable)
1286 out << field->type().getCppStackType()
1287 << "& ("
1288 << fullName()
1289 << "::"
1290 << field->name()
1291 << ")() ";
1292
Nirav Atre64868d32018-07-15 19:15:18 -07001293 emitSafeUnionGetterDefinition(out, field->name());
Nirav Atre45e76d52018-06-04 11:49:14 -07001294
1295 // Getter (immutable)
1296 out << field->type().getCppArgumentType()
1297 << " ("
1298 << fullName()
1299 << "::"
1300 << field->name()
1301 << ")() const ";
1302
Nirav Atre64868d32018-07-15 19:15:18 -07001303 emitSafeUnionGetterDefinition(out, field->name());
Nirav Atre45e76d52018-06-04 11:49:14 -07001304 }
1305
1306 // Trivial constructor/destructor for internal union
1307 out << fullName() << "::hidl_union::hidl_union() {}\n\n"
1308 << fullName() << "::hidl_union::~hidl_union() {}\n\n";
1309
1310 // Utility method
Nirav Atreca7a5022018-06-29 20:43:49 -07001311 out << fullName() << "::hidl_discriminator ("
1312 << fullName() << "::getDiscriminator)() const ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001313
1314 out.block([&] {
Nirav Atreca7a5022018-06-29 20:43:49 -07001315 out << "return hidl_d;\n";
Nirav Atre45e76d52018-06-04 11:49:14 -07001316 }).endl().endl();
1317}
1318
Steven Moreland368e4602018-02-16 14:21:49 -08001319void CompoundType::emitTypeDefinitions(Formatter& out, const std::string& prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -07001320 std::string space = prefix.empty() ? "" : (prefix + "::");
Steven Moreland368e4602018-02-16 14:21:49 -08001321 Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -07001322
Yifan Hongbf459bc2016-08-23 16:50:37 -07001323 if (needsEmbeddedReadWrite()) {
1324 emitStructReaderWriter(out, prefix, true /* isReader */);
1325 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -07001326 }
1327
Yifan Hongbf459bc2016-08-23 16:50:37 -07001328 if (needsResolveReferences()) {
1329 emitResolveReferenceDef(out, prefix, true /* isReader */);
1330 emitResolveReferenceDef(out, prefix, false /* isReader */);
1331 }
Nirav Atre45e76d52018-06-04 11:49:14 -07001332
1333 if (mStyle == STYLE_SAFE_UNION) {
1334 emitSafeUnionTypeDefinitions(out);
1335 }
Andreas Huber881227d2016-08-02 14:20:21 -07001336}
1337
Steven Moreland5add34d2018-11-08 16:31:30 -08001338static void emitJavaSafeUnionUnknownDiscriminatorError(Formatter& out, bool fatal) {
1339 out << "throw new ";
1340
1341 if (fatal) {
1342 out << "Error";
1343 } else {
1344 out << "IllegalStateException";
1345 }
1346
1347 out << "(\"Unknown union discriminator (value: \" + hidl_d + \").\");\n";
Nirav Atree3cae852018-07-16 12:19:16 -07001348}
1349
Steven Moreland368e4602018-02-16 14:21:49 -08001350void CompoundType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -07001351 out << "public final ";
1352
1353 if (!atTopLevel) {
1354 out << "static ";
1355 }
1356
1357 out << "class "
1358 << localName()
1359 << " {\n";
1360
1361 out.indent();
1362
1363 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
1364
Steven Moreland5dec82f2018-10-10 13:33:29 -07001365 if (mStyle == STYLE_SAFE_UNION) {
Steven Moreland579b0f62018-10-25 13:40:47 -07001366 out << "public " << localName() << "() ";
1367 out.block([&] {
1368 CHECK(!mFields->empty());
1369 mFields->at(0)->type().emitJavaFieldDefaultInitialValue(out, "hidl_o");
1370 }).endl().endl();
1371
Nirav Atre66842a92018-06-28 18:14:13 -07001372 const std::string discriminatorStorageType = (
1373 getUnionDiscriminatorType()->getJavaType(false));
Steven Moreland49bad8d2018-05-17 15:45:26 -07001374
Nirav Atre66842a92018-06-28 18:14:13 -07001375 out << "public static final class hidl_discriminator ";
1376 out.block([&] {
Nirav Atre71ce0082018-08-01 15:39:49 -07001377 const auto elements = getSafeUnionEnumElements(false /* useCppTypeName */);
1378 for (size_t idx = 0; idx < elements.size(); idx++) {
Nirav Atre66842a92018-06-28 18:14:13 -07001379 out << "public static final "
1380 << discriminatorStorageType
1381 << " "
Nirav Atre71ce0082018-08-01 15:39:49 -07001382 << elements[idx].fieldName
Nirav Atre66842a92018-06-28 18:14:13 -07001383 << " = "
1384 << idx
Nirav Atre71ce0082018-08-01 15:39:49 -07001385 << ";";
1386
1387 if (!elements[idx].fieldTypeName.empty()) {
1388 out << " // "
1389 << elements[idx].fieldTypeName;
1390 }
1391 out << "\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001392 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001393
Nirav Atre66842a92018-06-28 18:14:13 -07001394 out << "\n"
1395 << "public static final String getName("
1396 << discriminatorStorageType
1397 << " value) ";
1398
1399 out.block([&] {
1400 out << "switch (value) ";
1401 out.block([&] {
Nirav Atre71ce0082018-08-01 15:39:49 -07001402 for (size_t idx = 0; idx < elements.size(); idx++) {
Nirav Atre66842a92018-06-28 18:14:13 -07001403 out << "case "
1404 << idx
1405 << ": { return \""
Nirav Atre71ce0082018-08-01 15:39:49 -07001406 << elements[idx].fieldName
Nirav Atre66842a92018-06-28 18:14:13 -07001407 << "\"; }\n";
1408 }
1409 out << "default: { return \"Unknown\"; }\n";
1410 }).endl();
1411 }).endl().endl();
1412
1413 out << "private hidl_discriminator() {}\n";
1414 }).endl().endl();
1415
Steven Moreland967c2432018-10-10 12:50:43 -07001416 out << "private " << discriminatorStorageType << " hidl_d = 0;\n";
Steven Moreland579b0f62018-10-25 13:40:47 -07001417 out << "private Object hidl_o = null;\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001418
1419 for (const auto& field : *mFields) {
1420 // Setter
1421 out << "public void "
1422 << field->name()
1423 << "("
1424 << field->type().getJavaType(false)
1425 << " "
1426 << field->name()
1427 << ") ";
1428
1429 out.block([&] {
1430 out << "hidl_d = hidl_discriminator."
1431 << field->name()
1432 << ";\n";
1433
1434 out << "hidl_o = "
1435 << field->name()
1436 << ";\n";
1437 }).endl().endl();
1438
1439 // Getter
1440 out << "public "
1441 << field->type().getJavaType(false)
1442 << " "
1443 << field->name()
1444 << "() ";
1445
1446 out.block([&] {
1447 out << "if (hidl_d != hidl_discriminator."
1448 << field->name()
1449 << ") ";
1450
1451 out.block([&] {
1452 out << "String className = (hidl_o != null) ? "
1453 << "hidl_o.getClass().getName() : \"null\";\n";
1454
1455 out << "throw new IllegalStateException(\n";
1456 out.indent(2, [&] {
1457 out << "\"Read access to inactive union components is disallowed. \" +\n"
1458 << "\"Discriminator value is \" + hidl_d + \" (corresponding \" +\n"
1459 << "\"to \" + hidl_discriminator.getName(hidl_d) + \"), and \" +\n"
1460 << "\"hidl_o is of type \" + className + \".\");\n";
1461 });
1462 }).endl();
1463
1464 out << "if (hidl_o != null && !"
1465 << field->type().getJavaTypeClass()
1466 << ".class.isInstance(hidl_o)) ";
1467
1468 out.block([&] {
1469 out << "throw new Error(\"Union is in a corrupted state.\");\n";
1470 }).endl();
1471
1472 out << "return ("
1473 << field->type().getJavaTypeCast("hidl_o")
1474 << ");\n";
1475 }).endl().endl();
1476 }
1477
1478 out << "// Utility method\n"
1479 << "public "
1480 << discriminatorStorageType
1481 << " getDiscriminator() { return hidl_d; }\n\n";
1482
Steven Moreland5dec82f2018-10-10 13:33:29 -07001483 } else {
Nirav Atre66842a92018-06-28 18:14:13 -07001484 for (const auto& field : *mFields) {
1485 field->emitDocComment(out);
1486
1487 out << "public ";
1488 field->type().emitJavaFieldInitializer(out, field->name());
1489 }
1490
Andreas Huber85eabdb2016-08-25 11:24:49 -07001491 out << "\n";
1492 }
1493
Yifan Hongec102272016-12-20 18:10:07 -08001494 ////////////////////////////////////////////////////////////////////////////
1495
1496 if (canCheckEquality()) {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001497 out << "@Override\npublic final boolean equals(Object otherObject) ";
Yifan Hongec102272016-12-20 18:10:07 -08001498 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001499 out.sIf("this == otherObject", [&] {
1500 out << "return true;\n";
1501 }).endl();
1502 out.sIf("otherObject == null", [&] {
1503 out << "return false;\n";
1504 }).endl();
Yifan Hong45b331b2017-03-27 12:59:54 -07001505 // Though class is final, we use getClass instead of instanceof to be explicit.
1506 out.sIf("otherObject.getClass() != " + fullJavaName() + ".class", [&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001507 out << "return false;\n";
1508 }).endl();
1509 out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001510
Steven Moreland5dec82f2018-10-10 13:33:29 -07001511 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001512 out.sIf("this.hidl_d != other.hidl_d", [&] {
Yifan Hongec102272016-12-20 18:10:07 -08001513 out << "return false;\n";
1514 }).endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001515 out.sIf("!android.os.HidlSupport.deepEquals(this.hidl_o, other.hidl_o)", [&] {
1516 out << "return false;\n";
1517 }).endl();
Steven Moreland5dec82f2018-10-10 13:33:29 -07001518 } else {
Nirav Atre66842a92018-06-28 18:14:13 -07001519 for (const auto &field : *mFields) {
1520 std::string condition = (field->type().isScalar() || field->type().isEnum())
1521 ? "this." + field->name() + " != other." + field->name()
1522 : ("!android.os.HidlSupport.deepEquals(this." + field->name()
1523 + ", other." + field->name() + ")");
1524 out.sIf(condition, [&] {
1525 out << "return false;\n";
1526 }).endl();
1527 }
Yifan Hongec102272016-12-20 18:10:07 -08001528 }
1529 out << "return true;\n";
1530 }).endl().endl();
1531
Yifan Hong7d1839f2017-02-22 13:24:29 -08001532 out << "@Override\npublic final int hashCode() ";
Yifan Hongec102272016-12-20 18:10:07 -08001533 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001534 out << "return java.util.Objects.hash(\n";
1535 out.indent(2, [&] {
Steven Moreland5dec82f2018-10-10 13:33:29 -07001536 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001537 out << "android.os.HidlSupport.deepHashCode(this.hidl_o),\n"
1538 << "java.util.Objects.hashCode(this.hidl_d)";
1539 } else {
1540 out.join(mFields->begin(), mFields->end(), ", \n", [&] (const auto &field) {
1541 out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")";
1542 });
1543 }
Yifan Hong7d1839f2017-02-22 13:24:29 -08001544 });
Yifan Hongec102272016-12-20 18:10:07 -08001545 out << ");\n";
1546 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -07001547 } else {
1548 out << "// equals() is not generated for " << localName() << "\n";
Yifan Hongec102272016-12-20 18:10:07 -08001549 }
1550
1551 ////////////////////////////////////////////////////////////////////////////
1552
Steven Moreland51d20e92019-03-27 23:17:16 +00001553 out << "@Override\npublic final String toString() ";
1554 out.block([&] {
1555 out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n"
1556 << "builder.append(\"{\");\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001557
Steven Moreland51d20e92019-03-27 23:17:16 +00001558 if (mStyle == STYLE_SAFE_UNION) {
1559 out << "switch (this.hidl_d) {\n";
1560 out.indent();
1561 }
1562
1563 for (const auto &field : *mFields) {
Nirav Atre66842a92018-06-28 18:14:13 -07001564 if (mStyle == STYLE_SAFE_UNION) {
Steven Moreland51d20e92019-03-27 23:17:16 +00001565 out << "case hidl_discriminator."
1566 << field->name()
1567 << ": ";
Nirav Atre66842a92018-06-28 18:14:13 -07001568
Steven Moreland51d20e92019-03-27 23:17:16 +00001569 out.block([&] {
1570 out << "builder.append(\""
1571 << "."
Nirav Atre66842a92018-06-28 18:14:13 -07001572 << field->name()
Steven Moreland51d20e92019-03-27 23:17:16 +00001573 << " = \");\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001574
Steven Moreland51d20e92019-03-27 23:17:16 +00001575 field->type().emitJavaDump(out, "builder", "this." + field->name() + "()");
1576 out << "break;\n";
1577 }).endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001578 }
Steven Moreland51d20e92019-03-27 23:17:16 +00001579 else {
1580 out << "builder.append(\"";
1581 if (field != *(mFields->begin())) {
1582 out << ", ";
1583 }
1584 out << "." << field->name() << " = \");\n";
1585 field->type().emitJavaDump(out, "builder", "this." + field->name());
Steven Moreland78ab7532019-01-10 13:04:23 -08001586 }
Steven Moreland51d20e92019-03-27 23:17:16 +00001587 }
Nirav Atre66842a92018-06-28 18:14:13 -07001588
Steven Moreland51d20e92019-03-27 23:17:16 +00001589 if (mStyle == STYLE_SAFE_UNION) {
1590 out << "default: ";
1591 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, true /*fatal*/); })
1592 .endl();
1593
1594 out.unindent();
1595 out << "}\n";
1596 }
1597
1598 out << "builder.append(\"}\");\nreturn builder.toString();\n";
1599 }).endl().endl();
Yifan Honge45b5302017-02-22 10:49:07 -08001600
Nirav Atre66842a92018-06-28 18:14:13 -07001601 CompoundLayout layout = getCompoundAlignmentAndSize();
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001602
Yifan Honge45b5302017-02-22 10:49:07 -08001603 ////////////////////////////////////////////////////////////////////////////
1604
Yifan Hong1af73532016-11-09 14:32:58 -08001605 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001606 out.indent();
Howard Chenaf084db2017-12-27 18:46:39 +08001607 if (containsInterface()) {
Nirav Atre66842a92018-06-28 18:14:13 -07001608
Steven Moreland5dec82f2018-10-10 13:33:29 -07001609 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001610 out << "hidl_d = ";
1611 getUnionDiscriminatorType()->emitJavaReaderWriter(
1612 out, "parcel", "hidl_d", true);
1613
1614 out << "switch (hidl_d) {\n";
1615 out.indent();
1616 }
1617
Howard Chenaf084db2017-12-27 18:46:39 +08001618 for (const auto& field : *mFields) {
Nirav Atre66842a92018-06-28 18:14:13 -07001619 if (mStyle == STYLE_SAFE_UNION) {
1620 out << "case hidl_discriminator."
1621 << field->name()
1622 << ": ";
1623
1624 out.block([&] {
1625 out << "hidl_o = ";
1626 field->type().emitJavaReaderWriter(out, "parcel", "hidl_o", true);
1627
1628 out << "break;\n";
1629 }).endl();
1630 } else {
1631 out << field->name() << " = ";
1632 field->type().emitJavaReaderWriter(out, "parcel", field->name(), true);
1633 }
1634 }
1635
Steven Moreland5dec82f2018-10-10 13:33:29 -07001636 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atree3cae852018-07-16 12:19:16 -07001637 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -08001638 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, false /*fatal*/); })
1639 .endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001640
1641 out.unindent();
1642 out << "}\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001643 }
1644 } else {
1645 out << "android.os.HwBlob blob = parcel.readBuffer(";
Nirav Atre66842a92018-06-28 18:14:13 -07001646 out << layout.overall.size << " /* size */);\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001647 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
1648 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001649 out.unindent();
1650 out << "}\n\n";
1651
Andreas Huberf630bc82016-09-09 14:52:25 -07001652 ////////////////////////////////////////////////////////////////////////////
1653
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001654 size_t vecAlign, vecSize;
1655 VectorType::getAlignmentAndSizeStatic(&vecAlign, &vecSize);
1656
Howard Chenaf084db2017-12-27 18:46:39 +08001657 out << "public static final java.util.ArrayList<" << localName()
Yifan Hong1af73532016-11-09 14:32:58 -08001658 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001659 out.indent();
1660
Howard Chenaf084db2017-12-27 18:46:39 +08001661 out << "java.util.ArrayList<" << localName() << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001662
Howard Chenaf084db2017-12-27 18:46:39 +08001663 if (containsInterface()) {
1664 out << "int size = parcel.readInt32();\n";
1665 out << "for(int i = 0 ; i < size; i ++) {\n";
1666 out.indent();
1667 out << fullJavaName() << " tmp = ";
1668 emitJavaReaderWriter(out, "parcel", "tmp", true);
1669 out << "_hidl_vec.add(tmp);\n";
1670 out.unindent();
1671 out << "}\n";
1672 } else {
1673 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer(";
1674 out << vecSize << " /* sizeof hidl_vec<T> */);\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001675
Howard Chenaf084db2017-12-27 18:46:39 +08001676 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel",
1677 "_hidl_blob", "_hidl_vec", "0",
1678 true /* isReader */);
Andreas Huber85eabdb2016-08-25 11:24:49 -07001679 }
Howard Chenaf084db2017-12-27 18:46:39 +08001680 out << "\nreturn _hidl_vec;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001681 out.unindent();
1682 out << "}\n\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001683 ////////////////////////////////////////////////////////////////////////////
1684 if (containsInterface()) {
1685 out << "// readEmbeddedFromParcel is not generated()\n";
1686 } else {
1687 out << "public final void readEmbeddedFromParcel(\n";
1688 out.indent(2);
1689 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
1690 out.unindent();
Nirav Atre66842a92018-06-28 18:14:13 -07001691
Steven Moreland5dec82f2018-10-10 13:33:29 -07001692 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001693 getUnionDiscriminatorType()->emitJavaFieldReaderWriter(
1694 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d",
1695 "_hidl_offset + " + std::to_string(layout.discriminator.offset),
1696 true /* isReader */);
1697
1698 out << "switch (this.hidl_d) {\n";
1699 out.indent();
1700 }
1701
1702 size_t offset = layout.innerStruct.offset;
Howard Chenaf084db2017-12-27 18:46:39 +08001703 for (const auto& field : *mFields) {
Howard Chenaf084db2017-12-27 18:46:39 +08001704
Nirav Atre66842a92018-06-28 18:14:13 -07001705 if (mStyle == STYLE_SAFE_UNION) {
1706 out << "case hidl_discriminator."
1707 << field->name()
1708 << ": ";
Howard Chenaf084db2017-12-27 18:46:39 +08001709
Nirav Atre66842a92018-06-28 18:14:13 -07001710 out.block([&] {
1711 field->type().emitJavaFieldDefaultInitialValue(out, "hidl_o");
1712 field->type().emitJavaFieldReaderWriter(
1713 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_o",
1714 "_hidl_offset + " + std::to_string(offset), true /* isReader */);
1715
1716 out << "break;\n";
1717 }).endl();
1718 } else {
1719 size_t fieldAlign, fieldSize;
1720 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1721
1722 offset += Layout::getPad(offset, fieldAlign);
1723 field->type().emitJavaFieldReaderWriter(
1724 out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
1725 "_hidl_offset + " + std::to_string(offset), true /* isReader */);
1726 offset += fieldSize;
1727 }
1728 }
1729
Steven Moreland5dec82f2018-10-10 13:33:29 -07001730 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atree3cae852018-07-16 12:19:16 -07001731 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -08001732 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, false /*fatal*/); })
1733 .endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001734
1735 out.unindent();
1736 out << "}\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001737 }
1738 out.unindent();
1739 out << "}\n\n";
1740 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001741
Andreas Huberf630bc82016-09-09 14:52:25 -07001742 ////////////////////////////////////////////////////////////////////////////
1743
Yifan Hong1af73532016-11-09 14:32:58 -08001744 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001745 out.indent();
1746
Howard Chenaf084db2017-12-27 18:46:39 +08001747 if (containsInterface()) {
Steven Moreland5dec82f2018-10-10 13:33:29 -07001748 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001749 getUnionDiscriminatorType()->emitJavaReaderWriter(
1750 out, "parcel", "hidl_d", false);
1751
1752 out << "switch (this.hidl_d) {\n";
1753 out.indent();
1754 }
1755
Howard Chenaf084db2017-12-27 18:46:39 +08001756 for (const auto& field : *mFields) {
Nirav Atre66842a92018-06-28 18:14:13 -07001757 if (mStyle == STYLE_SAFE_UNION) {
1758 out << "case hidl_discriminator."
1759 << field->name()
1760 << ": ";
1761
1762 out.block([&] {
1763 field->type().emitJavaReaderWriter(out, "parcel", field->name() + "()", false);
1764 out << "break;\n";
1765 }).endl();
1766 } else {
1767 field->type().emitJavaReaderWriter(out, "parcel", field->name(), false);
1768 }
1769 }
1770
Steven Moreland5dec82f2018-10-10 13:33:29 -07001771 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atree3cae852018-07-16 12:19:16 -07001772 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -08001773 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, true /*fatal*/); })
1774 .endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001775
1776 out.unindent();
1777 out << "}\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001778 }
1779 } else {
Nirav Atre66842a92018-06-28 18:14:13 -07001780 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
1781 << layout.overall.size
Howard Chenaf084db2017-12-27 18:46:39 +08001782 << " /* size */);\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001783
Howard Chenaf084db2017-12-27 18:46:39 +08001784 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
1785 << "parcel.writeBuffer(_hidl_blob);\n";
1786 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001787 out.unindent();
1788 out << "}\n\n";
1789
Andreas Huberf630bc82016-09-09 14:52:25 -07001790 ////////////////////////////////////////////////////////////////////////////
1791
Andreas Huberf630bc82016-09-09 14:52:25 -07001792 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001793 out.indent(2);
Howard Chenaf084db2017-12-27 18:46:39 +08001794 out << "android.os.HwParcel parcel, java.util.ArrayList<" << localName() << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001795 out.unindent();
1796
Howard Chenaf084db2017-12-27 18:46:39 +08001797 if (containsInterface()) {
1798 out << "parcel.writeInt32(_hidl_vec.size());\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001799 out << "for(" << fullJavaName() << " tmp: _hidl_vec) ";
1800 out.block([&] {
1801 emitJavaReaderWriter(out, "parcel", "tmp", false);
1802 }).endl();
Howard Chenaf084db2017-12-27 18:46:39 +08001803 } else {
1804 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(" << vecSize
1805 << " /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001806
Howard Chenaf084db2017-12-27 18:46:39 +08001807 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel",
1808 "_hidl_blob", "_hidl_vec", "0",
1809 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -07001810
Howard Chenaf084db2017-12-27 18:46:39 +08001811 out << "\nparcel.writeBuffer(_hidl_blob);\n";
1812 }
Andreas Huberf630bc82016-09-09 14:52:25 -07001813 out.unindent();
1814 out << "}\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001815 ////////////////////////////////////////////////////////////////////////////
1816
Howard Chenaf084db2017-12-27 18:46:39 +08001817 if (containsInterface()) {
Nirav Atre66842a92018-06-28 18:14:13 -07001818 out << "// writeEmbeddedToBlob() is not generated\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001819 } else {
1820 out << "public final void writeEmbeddedToBlob(\n";
1821 out.indent(2);
1822 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
1823 out.unindent();
Nirav Atre45e76d52018-06-04 11:49:14 -07001824
Steven Moreland5dec82f2018-10-10 13:33:29 -07001825 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001826 getUnionDiscriminatorType()->emitJavaFieldReaderWriter(
1827 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d",
1828 "_hidl_offset + " + std::to_string(layout.discriminator.offset),
1829 false /* isReader */);
Nirav Atre45e76d52018-06-04 11:49:14 -07001830
Nirav Atre66842a92018-06-28 18:14:13 -07001831 out << "switch (this.hidl_d) {\n";
1832 out.indent();
Andreas Huber85eabdb2016-08-25 11:24:49 -07001833 }
1834
Nirav Atre66842a92018-06-28 18:14:13 -07001835 size_t offset = layout.innerStruct.offset;
1836 for (const auto& field : *mFields) {
1837 if (mStyle == STYLE_SAFE_UNION) {
1838 out << "case hidl_discriminator."
1839 << field->name()
1840 << ": ";
1841
1842 out.block([&] {
1843 field->type().emitJavaFieldReaderWriter(
1844 out, 0 /* depth */, "parcel", "_hidl_blob", field->name() + "()",
1845 "_hidl_offset + " + std::to_string(offset), false /* isReader */);
1846
1847 out << "break;\n";
1848 }).endl();
1849 } else {
1850 size_t fieldAlign, fieldSize;
1851 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1852
1853 offset += Layout::getPad(offset, fieldAlign);
1854 field->type().emitJavaFieldReaderWriter(
1855 out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
1856 "_hidl_offset + " + std::to_string(offset), false /* isReader */);
1857 offset += fieldSize;
1858 }
1859 }
1860
Steven Moreland5dec82f2018-10-10 13:33:29 -07001861 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atree3cae852018-07-16 12:19:16 -07001862 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -08001863 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, true /*fatal*/); })
1864 .endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001865
1866 out.unindent();
1867 out << "}\n";
1868 }
Howard Chenaf084db2017-12-27 18:46:39 +08001869 out.unindent();
1870 out << "}\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001871 }
1872
1873 out.unindent();
Andreas Huber85eabdb2016-08-25 11:24:49 -07001874 out << "};\n\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001875}
1876
Andreas Huber881227d2016-08-02 14:20:21 -07001877void CompoundType::emitStructReaderWriter(
1878 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -08001879
1880 std::string space = prefix.empty() ? "" : (prefix + "::");
1881
Andreas Huber881227d2016-08-02 14:20:21 -07001882 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -08001883 << (isReader ? "readEmbeddedFromParcel"
1884 : "writeEmbeddedToParcel")
1885 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001886
Yifan Hong0a68a282016-10-21 16:32:34 -07001887 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -07001888
Nirav Atre97b7e9c2018-07-26 19:29:40 -07001889 const std::string name = "obj";
Andreas Huber881227d2016-08-02 14:20:21 -07001890 if (isReader) {
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001891 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001892 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001893 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -08001894 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001895 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001896 }
1897
1898 out << "size_t parentHandle,\n"
1899 << "size_t parentOffset)";
1900
Andreas Huber881227d2016-08-02 14:20:21 -07001901 out << " {\n";
1902
Yifan Hong0a68a282016-10-21 16:32:34 -07001903 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -07001904 out.indent();
1905
Iliyan Malchev549e2592016-08-10 08:59:12 -07001906 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001907
Steven Moreland5dec82f2018-10-10 13:33:29 -07001908 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -07001909 out << "switch (" << name << ".getDiscriminator()) {\n";
1910 out.indent();
1911 }
1912
Andreas Huber881227d2016-08-02 14:20:21 -07001913 for (const auto &field : *mFields) {
1914 if (!field->type().needsEmbeddedReadWrite()) {
1915 continue;
1916 }
1917
Nirav Atre45e76d52018-06-04 11:49:14 -07001918 if (mStyle == STYLE_SAFE_UNION) {
1919 out << "case " << fullName() << "::hidl_discriminator::"
1920 << field->name() << ": {\n";
1921 out.indent();
1922 }
1923
1924 const std::string fieldName = (mStyle == STYLE_SAFE_UNION)
Nirav Atre97b7e9c2018-07-26 19:29:40 -07001925 ? (name + "." + field->name() + "()")
1926 : (name + "." + field->name());
Nirav Atre45e76d52018-06-04 11:49:14 -07001927
1928 const std::string fieldOffset = (mStyle == STYLE_SAFE_UNION)
Nirav Atre12c597a2018-06-28 09:35:24 -07001929 ? (name + ".hidl_getUnionOffset() " +
1930 "/* safe_union: union offset into struct */")
Nirav Atre45e76d52018-06-04 11:49:14 -07001931 : ("offsetof(" + fullName() + ", " + field->name() + ")");
1932
Andreas Huber881227d2016-08-02 14:20:21 -07001933 field->type().emitReaderWriterEmbedded(
1934 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -07001935 0 /* depth */,
Nirav Atre45e76d52018-06-04 11:49:14 -07001936 fieldName,
Yifan Hongbe2a3732016-10-05 13:33:41 -07001937 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -07001938 false /* nameIsPointer */,
1939 "parcel",
1940 !isReader /* parcelObjIsPointer */,
1941 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -07001942 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -07001943 "parentHandle",
Nirav Atre45e76d52018-06-04 11:49:14 -07001944 "parentOffset + " + fieldOffset);
1945
1946 if (mStyle == STYLE_SAFE_UNION) {
1947 out << "break;\n";
1948 out.unindent();
1949 out << "}\n";
1950 }
1951 }
1952
Steven Moreland5dec82f2018-10-10 13:33:29 -07001953 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -07001954 out << "default: { break; }\n";
1955 out.unindent();
1956 out << "}\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001957 }
1958
Iliyan Malchev549e2592016-08-10 08:59:12 -07001959 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001960
1961 out.unindent();
1962 out << "}\n\n";
1963}
1964
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -07001965void CompoundType::emitResolveReferenceDef(Formatter& out, const std::string& prefix,
1966 bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -08001967 out << "::android::status_t ";
1968 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -07001969
1970 bool useParent = false;
1971 for (const auto &field : *mFields) {
1972 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
1973 useParent = true;
1974 break;
1975 }
1976 }
1977
1978 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
1979 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
1980
Yifan Hongbf459bc2016-08-23 16:50:37 -07001981 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -08001982 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001983 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -08001984 out << space + localName() + " *obj,\n"
1985 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -07001986 << "size_t " << parentHandleName << ", "
1987 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001988 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001989 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -08001990 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001991 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -08001992 out << "const " << space + localName() + " &obj,\n"
1993 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -07001994 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -08001995 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001996 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001997 }
1998
1999 out << " {\n";
2000
2001 out.indent();
2002
2003 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
2004
Yifan Hong244e82d2016-11-11 11:13:57 -08002005 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -07002006 // if not useParent, then parentName and offsetText
2007 // should not be used at all, then the #error should not be emitted.
2008 std::string error = useParent ? "" : "\n#error\n";
2009
Nirav Atre45e76d52018-06-04 11:49:14 -07002010 if (mStyle == STYLE_SAFE_UNION) {
2011 out << "switch (" << nameDeref << "getDiscriminator()) {\n";
2012 out.indent();
2013 }
2014
Yifan Hongbf459bc2016-08-23 16:50:37 -07002015 for (const auto &field : *mFields) {
2016 if (!field->type().needsResolveReferences()) {
2017 continue;
2018 }
2019
Nirav Atre45e76d52018-06-04 11:49:14 -07002020 if (mStyle == STYLE_SAFE_UNION) {
2021 out << "case " << fullName() << "::hidl_discriminator::"
2022 << field->name() << ": {\n";
2023 out.indent();
2024 }
2025
2026 const std::string fieldName = (mStyle == STYLE_SAFE_UNION)
2027 ? (nameDeref + field->name() + "()")
2028 : (nameDeref + field->name());
2029
2030 const std::string fieldOffset = (mStyle == STYLE_SAFE_UNION)
Nirav Atre12c597a2018-06-28 09:35:24 -07002031 ? (nameDeref + "hidl_getUnionOffset() " +
2032 "/* safe_union: union offset into struct */")
Nirav Atre45e76d52018-06-04 11:49:14 -07002033 : ("offsetof(" + fullName() + ", " + field->name() + ")");
2034
Yifan Hongbf459bc2016-08-23 16:50:37 -07002035 field->type().emitResolveReferencesEmbedded(
2036 out,
2037 0 /* depth */,
Nirav Atre45e76d52018-06-04 11:49:14 -07002038 fieldName,
Yifan Hongbf459bc2016-08-23 16:50:37 -07002039 field->name() /* sanitizedName */,
2040 false, // nameIsPointer
2041 "parcel", // const std::string &parcelObj,
2042 !isReader, // bool parcelObjIsPointer,
2043 isReader, // bool isReader,
2044 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -07002045 parentHandleName + error,
2046 parentOffsetName
Nirav Atre45e76d52018-06-04 11:49:14 -07002047 + " + "
2048 + fieldOffset
Yifan Hong00f47172016-09-30 14:40:45 -07002049 + error);
Nirav Atre45e76d52018-06-04 11:49:14 -07002050
2051 if (mStyle == STYLE_SAFE_UNION) {
2052 out << "break;\n";
2053 out.unindent();
2054 out << "}\n";
2055 }
2056 }
2057
2058 if (mStyle == STYLE_SAFE_UNION) {
2059 out << "default: { _hidl_err = ::android::BAD_VALUE; break; }\n";
2060 out.unindent();
2061 out << "}\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -07002062 }
2063
Yifan Hongbf459bc2016-08-23 16:50:37 -07002064 out << "return _hidl_err;\n";
2065
2066 out.unindent();
2067 out << "}\n\n";
2068}
2069
Andreas Huber881227d2016-08-02 14:20:21 -07002070bool CompoundType::needsEmbeddedReadWrite() const {
Nirav Atre45e76d52018-06-04 11:49:14 -07002071 if (mStyle == STYLE_UNION) {
Andreas Huber881227d2016-08-02 14:20:21 -07002072 return false;
2073 }
2074
2075 for (const auto &field : *mFields) {
2076 if (field->type().needsEmbeddedReadWrite()) {
2077 return true;
2078 }
2079 }
2080
2081 return false;
2082}
2083
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002084bool CompoundType::deepNeedsResolveReferences(std::unordered_set<const Type*>* visited) const {
Nirav Atre45e76d52018-06-04 11:49:14 -07002085 if (mStyle == STYLE_UNION) {
Yifan Hongbf459bc2016-08-23 16:50:37 -07002086 return false;
2087 }
2088
2089 for (const auto &field : *mFields) {
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002090 if (field->type().needsResolveReferences(visited)) {
Yifan Hongbf459bc2016-08-23 16:50:37 -07002091 return true;
2092 }
2093 }
2094
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002095 return Scope::deepNeedsResolveReferences(visited);
Yifan Hongbf459bc2016-08-23 16:50:37 -07002096}
2097
Andreas Huber881227d2016-08-02 14:20:21 -07002098bool CompoundType::resultNeedsDeref() const {
Howard Chenecfb4512017-11-21 18:28:53 +08002099 return !containsInterface() ;
Andreas Huber881227d2016-08-02 14:20:21 -07002100}
2101
Steven Moreland368e4602018-02-16 14:21:49 -08002102void CompoundType::emitVtsTypeDeclarations(Formatter& out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07002103 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07002104 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002105
2106 // Emit declaration for each subtype.
2107 for (const auto &type : getSubTypes()) {
2108 switch (mStyle) {
2109 case STYLE_STRUCT:
2110 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07002111 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002112 break;
2113 }
2114 case STYLE_UNION:
2115 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07002116 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002117 break;
2118 }
Nirav Atre45e76d52018-06-04 11:49:14 -07002119 case STYLE_SAFE_UNION:
2120 {
2121 out << "sub_safe_union: {\n";
2122 break;
2123 }
2124 default:
2125 {
2126 CHECK(!"Should not be here");
2127 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002128 }
2129 out.indent();
Steven Moreland368e4602018-02-16 14:21:49 -08002130 type->emitVtsTypeDeclarations(out);
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002131 out.unindent();
2132 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07002133 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002134
2135 // Emit declaration for each field.
2136 for (const auto &field : *mFields) {
2137 switch (mStyle) {
2138 case STYLE_STRUCT:
2139 {
2140 out << "struct_value: {\n";
2141 break;
2142 }
2143 case STYLE_UNION:
2144 {
2145 out << "union_value: {\n";
2146 break;
2147 }
Nirav Atre45e76d52018-06-04 11:49:14 -07002148 case STYLE_SAFE_UNION:
2149 {
2150 out << "safe_union_value: {\n";
2151 break;
2152 }
2153 default:
2154 {
2155 CHECK(!"Should not be here");
2156 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002157 }
2158 out.indent();
2159 out << "name: \"" << field->name() << "\"\n";
Steven Moreland368e4602018-02-16 14:21:49 -08002160 field->type().emitVtsAttributeType(out);
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002161 out.unindent();
2162 out << "}\n";
2163 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07002164}
2165
Steven Moreland368e4602018-02-16 14:21:49 -08002166void CompoundType::emitVtsAttributeType(Formatter& out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07002167 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07002168 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07002169}
2170
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002171bool CompoundType::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
Nirav Atre66842a92018-06-28 18:14:13 -07002172 if (mStyle == STYLE_UNION) {
Andreas Huber0fa9e392016-08-31 09:05:44 -07002173 return false;
2174 }
2175
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002176 for (const auto* field : *mFields) {
2177 if (!field->get()->isJavaCompatible(visited)) {
Andreas Huber0fa9e392016-08-31 09:05:44 -07002178 return false;
2179 }
2180 }
2181
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002182 return Scope::deepIsJavaCompatible(visited);
Andreas Huber85eabdb2016-08-25 11:24:49 -07002183}
2184
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002185bool CompoundType::deepContainsPointer(std::unordered_set<const Type*>* visited) const {
2186 for (const auto* field : *mFields) {
2187 if (field->get()->containsPointer(visited)) {
Andreas Huber60d3b222017-03-30 09:10:56 -07002188 return true;
2189 }
2190 }
2191
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002192 return Scope::deepContainsPointer(visited);
Andreas Huber60d3b222017-03-30 09:10:56 -07002193}
2194
Andreas Huber85eabdb2016-08-25 11:24:49 -07002195void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
Nirav Atre45e76d52018-06-04 11:49:14 -07002196 CompoundLayout layout = getCompoundAlignmentAndSize();
2197 *align = layout.overall.align;
2198 *size = layout.overall.size;
2199}
Andreas Huber85eabdb2016-08-25 11:24:49 -07002200
Nirav Atre45e76d52018-06-04 11:49:14 -07002201CompoundType::CompoundLayout CompoundType::getCompoundAlignmentAndSize() const {
2202 CompoundLayout compoundLayout;
2203
2204 // Local aliases for convenience
2205 Layout& overall = compoundLayout.overall;
2206 Layout& innerStruct = compoundLayout.innerStruct;
2207 Layout& discriminator = compoundLayout.discriminator;
2208
Steven Moreland5dec82f2018-10-10 13:33:29 -07002209 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre12c597a2018-06-28 09:35:24 -07002210 getUnionDiscriminatorType()->getAlignmentAndSize(
2211 &(discriminator.align), &(discriminator.size));
2212
2213 innerStruct.offset = discriminator.size;
2214 }
2215
Andreas Huber85eabdb2016-08-25 11:24:49 -07002216 for (const auto &field : *mFields) {
Nirav Atre45e76d52018-06-04 11:49:14 -07002217
Andreas Huber85eabdb2016-08-25 11:24:49 -07002218 // Each field is aligned according to its alignment requirement.
2219 // The surrounding structure's alignment is the maximum of its
2220 // fields' aligments.
Andreas Huber85eabdb2016-08-25 11:24:49 -07002221 size_t fieldAlign, fieldSize;
2222 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
Nirav Atre45e76d52018-06-04 11:49:14 -07002223 size_t lPad = Layout::getPad(innerStruct.size, fieldAlign);
Andreas Huber85eabdb2016-08-25 11:24:49 -07002224
Nirav Atre45e76d52018-06-04 11:49:14 -07002225 innerStruct.size = (mStyle == STYLE_STRUCT)
2226 ? (innerStruct.size + lPad + fieldSize)
2227 : std::max(innerStruct.size, fieldSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -07002228
Nirav Atre45e76d52018-06-04 11:49:14 -07002229 innerStruct.align = std::max(innerStruct.align, fieldAlign);
2230 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07002231
Nirav Atre12c597a2018-06-28 09:35:24 -07002232 // Pad the inner structure's size
Nirav Atre45e76d52018-06-04 11:49:14 -07002233 innerStruct.size += Layout::getPad(innerStruct.size,
2234 innerStruct.align);
2235
Nirav Atre12c597a2018-06-28 09:35:24 -07002236 // Compute its final offset
2237 innerStruct.offset += Layout::getPad(innerStruct.offset,
2238 innerStruct.align);
Nirav Atre45e76d52018-06-04 11:49:14 -07002239
Nirav Atre45e76d52018-06-04 11:49:14 -07002240 // An empty struct/union still occupies a byte of space in C++.
Steven Moreland5e20b652019-04-22 18:42:38 -07002241 if (innerStruct.size == 0) {
2242 innerStruct.size = 1;
Nirav Atre45e76d52018-06-04 11:49:14 -07002243 }
2244
Steven Moreland5e20b652019-04-22 18:42:38 -07002245 overall.size = innerStruct.offset + innerStruct.size;
2246
Nirav Atre12c597a2018-06-28 09:35:24 -07002247 // Pad the overall structure's size
Nirav Atre45e76d52018-06-04 11:49:14 -07002248 overall.align = std::max(innerStruct.align, discriminator.align);
2249 overall.size += Layout::getPad(overall.size, overall.align);
2250
Steven Moreland5e20b652019-04-22 18:42:38 -07002251 if (mStyle != STYLE_SAFE_UNION) {
2252 CHECK(overall.offset == innerStruct.offset) << overall.offset << " " << innerStruct.offset;
2253 CHECK(overall.align == innerStruct.align) << overall.align << " " << innerStruct.align;
2254 CHECK(overall.size == innerStruct.size) << overall.size << " " << innerStruct.size;
2255 }
2256
Nirav Atre45e76d52018-06-04 11:49:14 -07002257 return compoundLayout;
2258}
2259
Steven Moreland5e20b652019-04-22 18:42:38 -07002260void CompoundType::emitPaddingZero(Formatter& out, size_t offset, size_t size) const {
2261 if (size > 0) {
2262 out << "::std::memset(reinterpret_cast<uint8_t*>(this) + " << offset << ", 0, " << size
2263 << ");\n";
2264 } else {
2265 out << "// no padding to zero starting at offset " << offset << "\n";
2266 }
2267}
2268
Nirav Atre45e76d52018-06-04 11:49:14 -07002269std::unique_ptr<ScalarType> CompoundType::getUnionDiscriminatorType() const {
2270 static const std::vector<std::pair<int, ScalarType::Kind> > scalars {
2271 {8, ScalarType::Kind::KIND_UINT8},
2272 {16, ScalarType::Kind::KIND_UINT16},
2273 {32, ScalarType::Kind::KIND_UINT32},
2274 };
2275
Steven Moreland967c2432018-10-10 12:50:43 -07002276 size_t numFields = mFields->size();
Nirav Atre45e76d52018-06-04 11:49:14 -07002277 auto kind = ScalarType::Kind::KIND_UINT64;
2278
2279 for (const auto& scalar : scalars) {
2280 if (numFields <= (1ULL << scalar.first)) {
2281 kind = scalar.second; break;
Andreas Huber85eabdb2016-08-25 11:24:49 -07002282 }
2283 }
2284
Yi Kong56758da2018-07-24 16:21:37 -07002285 return std::unique_ptr<ScalarType>(new ScalarType(kind, nullptr));
Nirav Atre45e76d52018-06-04 11:49:14 -07002286}
Andreas Huber85eabdb2016-08-25 11:24:49 -07002287
Nirav Atre45e76d52018-06-04 11:49:14 -07002288size_t CompoundType::Layout::getPad(size_t offset, size_t align) {
2289 size_t remainder = offset % align;
2290 return (remainder > 0) ? (align - remainder) : 0;
Andreas Huber70a59e12016-08-16 12:57:01 -07002291}
2292
Andreas Huberc9410c72016-07-28 12:18:40 -07002293} // namespace android
2294