blob: 699bbfc3a98ef5306d365747a159f7e88918f887 [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"
Steven Moreland78ab7532019-01-10 13:04:23 -080020#include "CompileToggles.h"
Nirav Atre45e76d52018-06-04 11:49:14 -070021#include "ScalarType.h"
Andreas Huberf630bc82016-09-09 14:52:25 -070022#include "VectorType.h"
Timur Iskhakovcec46c42017-08-09 00:22:02 -070023
Andreas Huber5a545442016-08-03 10:44:56 -070024#include <android-base/logging.h>
Timur Iskhakovcec46c42017-08-09 00:22:02 -070025#include <hidl-util/Formatter.h>
Timur Iskhakove8ee6a02017-09-06 11:42:10 -070026#include <iostream>
Timur Iskhakovcec46c42017-08-09 00:22:02 -070027#include <unordered_set>
Andreas Huber5a545442016-08-03 10:44:56 -070028
Andreas Huberc9410c72016-07-28 12:18:40 -070029namespace android {
30
Timur Iskhakov565b0132017-09-06 18:07:11 -070031CompoundType::CompoundType(Style style, const char* localName, const FQName& fullName,
32 const Location& location, Scope* parent)
Yi Kong56758da2018-07-24 16:21:37 -070033 : Scope(localName, fullName, location, parent), mStyle(style), mFields(nullptr) {}
Andreas Huberc9410c72016-07-28 12:18:40 -070034
Yifan Hong27e85db2016-11-09 15:45:52 -080035CompoundType::Style CompoundType::style() const {
36 return mStyle;
37}
38
Timur Iskhakovcec46c42017-08-09 00:22:02 -070039void CompoundType::setFields(std::vector<NamedReference<Type>*>* fields) {
Andreas Huberc9410c72016-07-28 12:18:40 -070040 mFields = fields;
Timur Iskhakovcec46c42017-08-09 00:22:02 -070041}
Andreas Huber5a545442016-08-03 10:44:56 -070042
Timur Iskhakovb58f4182017-08-29 15:19:24 -070043std::vector<const Reference<Type>*> CompoundType::getReferences() const {
44 std::vector<const Reference<Type>*> ret;
45 ret.insert(ret.begin(), mFields->begin(), mFields->end());
Timur Iskhakov33431e62017-08-21 17:31:23 -070046 return ret;
Timur Iskhakovcec46c42017-08-09 00:22:02 -070047}
48
49status_t CompoundType::validate() const {
50 for (const auto* field : *mFields) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070051 const Type& type = field->type();
Andreas Huber5a545442016-08-03 10:44:56 -070052
Howard Chenecfb4512017-11-21 18:28:53 +080053 if ((type.isVector() && static_cast<const VectorType*>(&type)->isVectorOfBinders())) {
Steven Morelandd927e5c2018-07-10 16:03:43 -070054 std::cerr << "ERROR: Struct/union cannot contain vectors of interfaces at "
Timur Iskhakovcec46c42017-08-09 00:22:02 -070055 << field->location() << "\n";
56 return UNKNOWN_ERROR;
Andreas Huberb95ea8a2016-08-15 15:35:42 -070057 }
58
Andreas Huber5a545442016-08-03 10:44:56 -070059 if (mStyle == STYLE_UNION) {
Steven Moreland7df0f392018-10-31 13:23:22 -070060 if (type.isInterface()) {
Steven Morelandd927e5c2018-07-10 16:03:43 -070061 std::cerr << "ERROR: Union cannot contain interfaces at " << field->location()
62 << "\n";
63 return UNKNOWN_ERROR;
64 }
65
Andreas Huber5a545442016-08-03 10:44:56 -070066 if (type.needsEmbeddedReadWrite()) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070067 std::cerr << "ERROR: Union must not contain any types that need fixup at "
68 << field->location() << "\n";
69 return UNKNOWN_ERROR;
Andreas Huber5a545442016-08-03 10:44:56 -070070 }
Andreas Huber5a545442016-08-03 10:44:56 -070071 }
72 }
73
Steven Moreland5dec82f2018-10-10 13:33:29 -070074 if (mStyle == STYLE_SAFE_UNION && mFields->size() < 2) {
75 std::cerr << "ERROR: Safe union must contain at least two types to be useful at "
76 << location() << "\n";
77 return UNKNOWN_ERROR;
78 }
79
Timur Iskhakovcec46c42017-08-09 00:22:02 -070080 status_t err = validateUniqueNames();
81 if (err != OK) return err;
82
Nirav Atre45e76d52018-06-04 11:49:14 -070083 err = validateSubTypeNames();
84 if (err != OK) return err;
85
Timur Iskhakovcec46c42017-08-09 00:22:02 -070086 return Scope::validate();
87}
88
89status_t CompoundType::validateUniqueNames() const {
90 std::unordered_set<std::string> names;
91
92 for (const auto* field : *mFields) {
93 if (names.find(field->name()) != names.end()) {
94 std::cerr << "ERROR: Redefinition of field '" << field->name() << "' at "
95 << field->location() << "\n";
96 return UNKNOWN_ERROR;
97 }
98 names.insert(field->name());
99 }
100
101 return OK;
Andreas Huberc9410c72016-07-28 12:18:40 -0700102}
103
Nirav Atre45e76d52018-06-04 11:49:14 -0700104void CompoundType::emitInvalidSubTypeNamesError(const std::string& subTypeName,
105 const Location& location) const {
106 std::cerr << "ERROR: Type name '" << subTypeName << "' defined at "
107 << location << " conflicts with a member function of "
108 << "safe_union " << localName() << ". Consider renaming or "
109 << "moving its definition outside the safe_union scope.\n";
110}
111
112status_t CompoundType::validateSubTypeNames() const {
113 if (mStyle != STYLE_SAFE_UNION) { return OK; }
114 const auto& subTypes = Scope::getSubTypes();
115
116 for (const auto& subType : subTypes) {
117 if (subType->localName() == "getDiscriminator") {
118 emitInvalidSubTypeNamesError(subType->localName(),
119 subType->location());
120 return UNKNOWN_ERROR;
121 }
122 }
123
124 return OK;
125}
126
Andreas Huberf630bc82016-09-09 14:52:25 -0700127bool CompoundType::isCompoundType() const {
128 return true;
129}
130
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700131bool CompoundType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
Yifan Hongc6752dc2016-12-20 14:00:14 -0800132 if (mStyle == STYLE_UNION) {
133 return false;
134 }
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700135 for (const auto* field : *mFields) {
136 if (!field->get()->canCheckEquality(visited)) {
Yifan Hongc6752dc2016-12-20 14:00:14 -0800137 return false;
138 }
139 }
140 return true;
141}
142
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700143std::string CompoundType::typeName() const {
144 switch (mStyle) {
145 case STYLE_STRUCT: {
146 return "struct " + localName();
147 }
148 case STYLE_UNION: {
149 return "union " + localName();
150 }
Nirav Atre45e76d52018-06-04 11:49:14 -0700151 case STYLE_SAFE_UNION: {
152 return "safe_union " + localName();
153 }
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700154 }
155 CHECK(!"Should not be here");
156}
157
Andreas Huber881227d2016-08-02 14:20:21 -0700158std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -0700159 StorageMode mode,
Steven Morelande30ee9b2017-05-09 13:31:01 -0700160 bool /* specifyNamespaces */) const {
161 const std::string base = fullName();
Andreas Huber881227d2016-08-02 14:20:21 -0700162
163 switch (mode) {
164 case StorageMode_Stack:
165 return base;
166
167 case StorageMode_Argument:
168 return "const " + base + "&";
169
170 case StorageMode_Result:
Howard Chenecfb4512017-11-21 18:28:53 +0800171 return base + (containsInterface()?"":"*");
Andreas Huber881227d2016-08-02 14:20:21 -0700172 }
Nirav Atre45e76d52018-06-04 11:49:14 -0700173 CHECK(!"Should not be here");
Andreas Huber881227d2016-08-02 14:20:21 -0700174}
175
Yifan Hong4ed13472016-11-02 10:44:11 -0700176std::string CompoundType::getJavaType(bool /* forInitializer */) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700177 return fullJavaName();
178}
179
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700180std::string CompoundType::getVtsType() const {
181 switch (mStyle) {
182 case STYLE_STRUCT:
183 {
184 return "TYPE_STRUCT";
185 }
186 case STYLE_UNION:
187 {
188 return "TYPE_UNION";
189 }
Nirav Atre45e76d52018-06-04 11:49:14 -0700190 case STYLE_SAFE_UNION:
191 {
192 return "TYPE_SAFE_UNION";
193 }
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700194 }
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700195 CHECK(!"Should not be here");
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700196}
197
Howard Chenecfb4512017-11-21 18:28:53 +0800198bool CompoundType::containsInterface() const {
199 for (const auto& field : *mFields) {
200 if (field->type().isCompoundType()) {
201 const Type& t = field->type();
202 const CompoundType* ct = static_cast<const CompoundType*>(&t);
203 if (ct->containsInterface()) {
204 return true;
205 }
206 }
207 if (field->type().isInterface()) {
208 return true;
209 }
210 }
211 return false;
212}
213
Steven Moreland5add34d2018-11-08 16:31:30 -0800214void CompoundType::emitSafeUnionUnknownDiscriminatorError(Formatter& out, const std::string& value,
215 bool fatal) const {
216 if (fatal) {
217 out << "::android::hardware::details::logAlwaysFatal(";
218 } else {
219 out << "ALOGE(\"%s\", ";
220 }
221 out << "(\n";
Nirav Atree3cae852018-07-16 12:19:16 -0700222 out.indent(2, [&] {
223 out << "\"Unknown union discriminator (value: \" +\n"
224 << "std::to_string(" << getUnionDiscriminatorType()->getCppTypeCast(value)
225 << ") + \").\").c_str());\n";
226 });
227}
228
Nirav Atreca7a5022018-06-29 20:43:49 -0700229void CompoundType::emitSafeUnionReaderWriterForInterfaces(
230 Formatter &out,
231 const std::string &name,
232 const std::string &parcelObj,
233 bool parcelObjIsPointer,
234 bool isReader,
235 ErrorMode mode) const {
236
237 CHECK(mStyle == STYLE_SAFE_UNION);
Nirav Atreca7a5022018-06-29 20:43:49 -0700238
239 out.block([&] {
240 const auto discriminatorType = getUnionDiscriminatorType();
241 if (isReader) {
242 out << discriminatorType->getCppStackType()
243 << " _hidl_d_primitive;\n";
244 } else {
245 out << "const "
246 << discriminatorType->getCppStackType()
247 << " _hidl_d_primitive = "
248 << discriminatorType->getCppTypeCast(name + ".getDiscriminator()")
249 << ";\n";
250 }
251
252 getUnionDiscriminatorType()->emitReaderWriter(out, "_hidl_d_primitive", parcelObj,
253 parcelObjIsPointer, isReader, mode);
254 out << "switch (("
255 << fullName()
256 << "::hidl_discriminator) _hidl_d_primitive) ";
257
258 out.block([&] {
259 for (const auto& field : *mFields) {
260 out << "case "
261 << fullName()
262 << "::hidl_discriminator::"
263 << field->name()
264 << ": ";
265
266 const std::string tempFieldName = "_hidl_temp_" + field->name();
267 out.block([&] {
268 if (isReader) {
269 out << field->type().getCppResultType()
270 << " "
271 << tempFieldName
272 << ";\n";
273
274 field->type().emitReaderWriter(out, tempFieldName, parcelObj,
275 parcelObjIsPointer, isReader, mode);
276
277 const std::string derefOperator = field->type().resultNeedsDeref()
278 ? "*" : "";
279 out << name
280 << "."
281 << field->name()
Nirav Atre64868d32018-07-15 19:15:18 -0700282 << "(std::move("
Nirav Atreca7a5022018-06-29 20:43:49 -0700283 << derefOperator
284 << tempFieldName
Nirav Atre64868d32018-07-15 19:15:18 -0700285 << "));\n";
Nirav Atreca7a5022018-06-29 20:43:49 -0700286 } else {
287 const std::string fieldValue = name + "." + field->name() + "()";
288 out << field->type().getCppArgumentType()
289 << " "
290 << tempFieldName
291 << " = "
292 << fieldValue
293 << ";\n";
294
295 field->type().emitReaderWriter(out, tempFieldName, parcelObj,
296 parcelObjIsPointer, isReader, mode);
297 }
298 out << "break;\n";
299 }).endl();
300 }
301
Nirav Atreca7a5022018-06-29 20:43:49 -0700302 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -0800303 out.block([&] {
304 emitSafeUnionUnknownDiscriminatorError(out, "_hidl_d_primitive",
305 !isReader /*fatal*/);
306 if (isReader) {
307 out << "_hidl_err = BAD_VALUE;\n";
308 handleError(out, mode);
309 }
310 })
Nirav Atree3cae852018-07-16 12:19:16 -0700311 .endl();
Nirav Atreca7a5022018-06-29 20:43:49 -0700312 }).endl();
313 }).endl();
314}
315
Andreas Huber881227d2016-08-02 14:20:21 -0700316void CompoundType::emitReaderWriter(
317 Formatter &out,
318 const std::string &name,
319 const std::string &parcelObj,
320 bool parcelObjIsPointer,
321 bool isReader,
322 ErrorMode mode) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700323
324 const std::string parcelObjDeref =
325 parcelObj + (parcelObjIsPointer ? "->" : ".");
326
Howard Chenecfb4512017-11-21 18:28:53 +0800327 if(containsInterface()){
Nirav Atreca7a5022018-06-29 20:43:49 -0700328 if (mStyle == STYLE_SAFE_UNION) {
329 emitSafeUnionReaderWriterForInterfaces(out, name, parcelObj,
330 parcelObjIsPointer,
331 isReader, mode);
332 return;
333 }
334
Howard Chenecfb4512017-11-21 18:28:53 +0800335 for (const auto& field : *mFields) {
Nirav Atre1d565622018-07-13 15:41:21 -0700336 const std::string tempFieldName = "_hidl_temp_" + field->name();
337 const std::string fieldValue = name + "." + field->name();
338
339 out.block([&] {
340 if (isReader) {
341 out << field->type().getCppResultType()
342 << " "
343 << tempFieldName
344 << ";\n";
345 } else {
346 out << field->type().getCppArgumentType()
347 << " "
348 << tempFieldName
349 << " = "
350 << fieldValue
351 << ";\n";
352 }
353
354 field->type().emitReaderWriter(out, tempFieldName, parcelObj,
355 parcelObjIsPointer, isReader, mode);
356 if (isReader) {
357 const std::string derefOperator = field->type().resultNeedsDeref()
358 ? "*" : "";
359 out << fieldValue
360 << " = std::move("
361 << derefOperator
362 << tempFieldName
363 << ");\n";
364 }
365 }).endl();
Howard Chenecfb4512017-11-21 18:28:53 +0800366 }
Andreas Huber881227d2016-08-02 14:20:21 -0700367 } else {
Howard Chenecfb4512017-11-21 18:28:53 +0800368 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700369
Howard Chenecfb4512017-11-21 18:28:53 +0800370 out << "size_t " << parentName << ";\n\n";
371
372 if (isReader) {
373 out << "_hidl_err = " << parcelObjDeref << "readBuffer("
374 << "sizeof(*" << name << "), &" << parentName << ", "
375 << " const_cast<const void**>(reinterpret_cast<void **>("
376 << "&" << name << ")));\n";
377 handleError(out, mode);
378 } else {
379 out << "_hidl_err = "
380 << parcelObjDeref
381 << "writeBuffer(&"
382 << name
383 << ", sizeof("
384 << name
385 << "), &"
386 << parentName
387 << ");\n";
388 handleError(out, mode);
389 }
Nirav Atre45e76d52018-06-04 11:49:14 -0700390
391 bool needEmbeddedReadWrite = needsEmbeddedReadWrite();
392 CHECK(mStyle != STYLE_UNION || !needEmbeddedReadWrite);
393
394 if (needEmbeddedReadWrite) {
Howard Chenecfb4512017-11-21 18:28:53 +0800395 emitReaderWriterEmbedded(out, 0 /* depth */, name, name, /* sanitizedName */
396 isReader /* nameIsPointer */, parcelObj, parcelObjIsPointer,
397 isReader, mode, parentName, "0 /* parentOffset */");
398 }
Andreas Huber881227d2016-08-02 14:20:21 -0700399 }
Andreas Huber881227d2016-08-02 14:20:21 -0700400}
401
402void CompoundType::emitReaderWriterEmbedded(
403 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700404 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700405 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700406 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700407 bool nameIsPointer,
408 const std::string &parcelObj,
409 bool parcelObjIsPointer,
410 bool isReader,
411 ErrorMode mode,
412 const std::string &parentName,
413 const std::string &offsetText) const {
414 emitReaderWriterEmbeddedForTypeName(
415 out,
416 name,
417 nameIsPointer,
418 parcelObj,
419 parcelObjIsPointer,
420 isReader,
421 mode,
422 parentName,
423 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700424 fullName(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800425 "" /* childName */,
426 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700427}
428
Andreas Huber85eabdb2016-08-25 11:24:49 -0700429void CompoundType::emitJavaReaderWriter(
430 Formatter &out,
431 const std::string &parcelObj,
432 const std::string &argName,
433 bool isReader) const {
434 if (isReader) {
435 out << "new " << fullJavaName() << "();\n";
436 }
437
Steven Morelandc22e8122018-10-10 13:06:39 -0700438 out << "(" << getJavaTypeCast(argName) << ")."
439 << (isReader ? "readFromParcel" : "writeToParcel") << "(" << parcelObj << ");\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700440}
441
442void CompoundType::emitJavaFieldInitializer(
443 Formatter &out, const std::string &fieldName) const {
Nirav Atre1d565622018-07-13 15:41:21 -0700444 const std::string fieldDeclaration = fullJavaName() + " " + fieldName;
Nirav Atre66842a92018-06-28 18:14:13 -0700445 emitJavaFieldDefaultInitialValue(out, fieldDeclaration);
446}
447
448void CompoundType::emitJavaFieldDefaultInitialValue(
449 Formatter &out, const std::string &declaredFieldName) const {
450 out << declaredFieldName
Andreas Huber85eabdb2016-08-25 11:24:49 -0700451 << " = new "
452 << fullJavaName()
453 << "();\n";
454}
455
456void CompoundType::emitJavaFieldReaderWriter(
457 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700458 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700459 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700460 const std::string &blobName,
461 const std::string &fieldName,
462 const std::string &offset,
463 bool isReader) const {
464 if (isReader) {
Nirav Atre66842a92018-06-28 18:14:13 -0700465 out << "("
466 << getJavaTypeCast(fieldName)
467 << ").readEmbeddedFromParcel("
Andreas Huber709b62d2016-09-19 11:21:18 -0700468 << parcelName
469 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700470 << blobName
471 << ", "
472 << offset
473 << ");\n";
474
475 return;
476 }
477
478 out << fieldName
479 << ".writeEmbeddedToBlob("
480 << blobName
481 << ", "
482 << offset
483 << ");\n";
484}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700485void CompoundType::emitResolveReferences(
486 Formatter &out,
487 const std::string &name,
488 bool nameIsPointer,
489 const std::string &parcelObj,
490 bool parcelObjIsPointer,
491 bool isReader,
492 ErrorMode mode) const {
493 emitResolveReferencesEmbedded(
494 out,
495 0 /* depth */,
496 name,
497 name /* sanitizedName */,
498 nameIsPointer,
499 parcelObj,
500 parcelObjIsPointer,
501 isReader,
502 mode,
503 "_hidl_" + name + "_parent",
504 "0 /* parentOffset */");
505}
506
507void CompoundType::emitResolveReferencesEmbedded(
508 Formatter &out,
509 size_t /* depth */,
510 const std::string &name,
511 const std::string &/* sanitizedName */,
512 bool nameIsPointer,
513 const std::string &parcelObj,
514 bool parcelObjIsPointer,
515 bool isReader,
516 ErrorMode mode,
517 const std::string &parentName,
518 const std::string &offsetText) const {
519 CHECK(needsResolveReferences());
520
521 const std::string parcelObjDeref =
522 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
523
524 const std::string parcelObjPointer =
525 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
526
Yifan Hong244e82d2016-11-11 11:13:57 -0800527 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700528 const std::string namePointer = nameIsPointer ? name : ("&" + name);
529
530 out << "_hidl_err = ";
531
532 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800533 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700534 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800535 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700536 }
537
Yifan Hong33223ca2016-12-13 15:07:35 -0800538 out.indent(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800539 if (isReader) {
540 out << "const_cast<"
541 << fullName()
542 << " *"
543 << ">("
544 << namePointer
545 << "),\n"
546 << parcelObjDeref;
547 } else {
548 out << nameDerefed
549 << ",\n"
550 << parcelObjPointer;
551 }
552
553 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700554 << parentName
555 << ",\n"
556 << offsetText
557 << ");\n\n";
558 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700559
560 handleError(out, mode);
561}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700562
Nirav Atre45e76d52018-06-04 11:49:14 -0700563void CompoundType::emitLayoutAsserts(Formatter& out, const Layout& layout,
564 const std::string& layoutName) const {
565 out << "static_assert(sizeof("
566 << fullName()
567 << layoutName
568 << ") == "
569 << layout.size
570 << ", \"wrong size\");\n";
571
572 out << "static_assert(__alignof("
573 << fullName()
574 << layoutName
575 << ") == "
576 << layout.align
577 << ", \"wrong alignment\");\n";
578}
579
580void CompoundType::emitSafeUnionTypeDeclarations(Formatter& out) const {
581 out << "struct "
582 << localName()
583 << " final {\n";
584
585 out.indent();
586
587 Scope::emitTypeDeclarations(out);
588
Nirav Atre12c597a2018-06-28 09:35:24 -0700589 bool hasPointer = containsPointer();
590 CompoundLayout layout = hasPointer
591 ? CompoundLayout()
592 : getCompoundAlignmentAndSize();
593
Nirav Atre45e76d52018-06-04 11:49:14 -0700594 out << "enum class hidl_discriminator : "
595 << getUnionDiscriminatorType()->getCppType(StorageMode_Stack, false)
596 << " ";
597
598 out.block([&] {
Nirav Atre71ce0082018-08-01 15:39:49 -0700599 const auto elements = getSafeUnionEnumElements(true /* useCppTypeName */);
600 for (size_t i = 0; i < elements.size(); i++) {
601 out << elements[i].fieldName
602 << " = "
603 << i
604 << ",";
605
606 if (!elements[i].fieldTypeName.empty()) {
607 out << " // "
608 << elements[i].fieldTypeName;
609 }
610 out << "\n";
Nirav Atre45e76d52018-06-04 11:49:14 -0700611 }
Nirav Atre45e76d52018-06-04 11:49:14 -0700612 });
613 out << ";\n\n";
614
Nirav Atre64868d32018-07-15 19:15:18 -0700615 out << localName() << "();\n" // Constructor
616 << "~" << localName() << "();\n" // Destructor
617 << localName() << "(" << localName() << "&&);\n" // Move constructor
618 << localName() << "(const " << localName() << "&);\n" // Copy constructor
619 << localName() << "& operator=(" << localName() << "&&);\n" // Move assignment
620 << localName() << "& operator=(const " << localName() << "&);\n\n"; // Copy assignment
Nirav Atre45e76d52018-06-04 11:49:14 -0700621
622 for (const auto& field : *mFields) {
Nirav Atre64868d32018-07-15 19:15:18 -0700623 // Setter (copy)
Nirav Atre45e76d52018-06-04 11:49:14 -0700624 out << "void "
625 << field->name()
626 << "("
627 << field->type().getCppArgumentType()
628 << ");\n";
629
Steven Moreland492bada2018-09-13 16:12:32 -0700630 if (field->type().resolveToScalarType() == nullptr) {
Nirav Atre64868d32018-07-15 19:15:18 -0700631 // Setter (move)
632 out << "void "
633 << field->name()
634 << "("
635 << field->type().getCppStackType()
636 << "&&);\n";
637 }
638
639 // Getter (mutable)
Nirav Atre45e76d52018-06-04 11:49:14 -0700640 out << field->type().getCppStackType()
641 << "& "
642 << field->name()
643 << "();\n";
644
Nirav Atre64868d32018-07-15 19:15:18 -0700645 // Getter (immutable)
Nirav Atre45e76d52018-06-04 11:49:14 -0700646 out << field->type().getCppArgumentType()
647 << " "
648 << field->name()
649 << "() const;\n\n";
650 }
651
Nirav Atre12c597a2018-06-28 09:35:24 -0700652 out << "// Utility methods\n";
Nirav Atre45e76d52018-06-04 11:49:14 -0700653 out << "hidl_discriminator getDiscriminator() const;\n\n";
654
Nirav Atre12c597a2018-06-28 09:35:24 -0700655 out << "constexpr size_t hidl_getUnionOffset() const ";
656 out.block([&] {
657 out << "return offsetof(" << fullName() << ", hidl_u);\n";
658 }).endl().endl();
659
Nirav Atre45e76d52018-06-04 11:49:14 -0700660 out.unindent();
661 out << "private:\n";
662 out.indent();
663
664 out << "void hidl_destructUnion();\n\n";
Nirav Atre12c597a2018-06-28 09:35:24 -0700665
666 out << "hidl_discriminator hidl_d";
667 if (!hasPointer) {
668 out << " __attribute__ ((aligned("
669 << layout.discriminator.align << "))) ";
670 }
Steven Moreland967c2432018-10-10 12:50:43 -0700671 out << ";\n";
Nirav Atre45e76d52018-06-04 11:49:14 -0700672 out << "union hidl_union final {\n";
673 out.indent();
674
Nirav Atre45e76d52018-06-04 11:49:14 -0700675 for (const auto& field : *mFields) {
676
677 size_t fieldAlign, fieldSize;
678 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
679
680 out << field->type().getCppStackType()
681 << " "
682 << field->name();
683
684 if (!hasPointer) {
685 out << " __attribute__ ((aligned("
686 << fieldAlign
687 << ")))";
688 }
689 out << ";\n";
690 }
691
692 out << "\n"
693 << "hidl_union();\n"
694 << "~hidl_union();\n";
695
696 out.unindent();
Nirav Atre12c597a2018-06-28 09:35:24 -0700697 out << "} hidl_u;\n";
Nirav Atre45e76d52018-06-04 11:49:14 -0700698
699 if (!hasPointer) {
700 out << "\n";
701
702 emitLayoutAsserts(out, layout.innerStruct, "::hidl_union");
703 emitLayoutAsserts(out, layout.discriminator, "::hidl_discriminator");
704 }
705
706 out.unindent();
707 out << "};\n\n";
708
709 if (!hasPointer) {
710 emitLayoutAsserts(out, layout.overall, "");
711 out << "\n";
712 }
713}
714
Steven Moreland368e4602018-02-16 14:21:49 -0800715void CompoundType::emitTypeDeclarations(Formatter& out) const {
Nirav Atre45e76d52018-06-04 11:49:14 -0700716 if (mStyle == STYLE_SAFE_UNION) {
717 emitSafeUnionTypeDeclarations(out);
718 return;
719 }
720
Andreas Huber881227d2016-08-02 14:20:21 -0700721 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
722 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700723 << localName()
Yifan Hongb1d2ebc2016-12-20 17:18:07 -0800724 << " final {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700725
726 out.indent();
727
728 Scope::emitTypeDeclarations(out);
729
Andreas Huber60d3b222017-03-30 09:10:56 -0700730 if (containsPointer()) {
Andreas Huberca4bc892017-01-09 14:58:12 -0800731 for (const auto &field : *mFields) {
Steven Moreland49bad8d2018-05-17 15:45:26 -0700732 field->emitDocComment(out);
Andreas Huberca4bc892017-01-09 14:58:12 -0800733 out << field->type().getCppStackType()
734 << " "
735 << field->name()
736 << ";\n";
737 }
738
739 out.unindent();
740 out << "};\n\n";
741
Steven Moreland368e4602018-02-16 14:21:49 -0800742 return;
Andreas Huber881227d2016-08-02 14:20:21 -0700743 }
744
Andreas Huberca4bc892017-01-09 14:58:12 -0800745 for (int pass = 0; pass < 2; ++pass) {
746 size_t offset = 0;
747 for (const auto &field : *mFields) {
748 size_t fieldAlign, fieldSize;
749 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
750
Nirav Atre45e76d52018-06-04 11:49:14 -0700751 offset += Layout::getPad(offset, fieldAlign);
Andreas Huberca4bc892017-01-09 14:58:12 -0800752
753 if (pass == 0) {
754 out << field->type().getCppStackType()
755 << " "
756 << field->name()
757 << " __attribute__ ((aligned("
758 << fieldAlign
759 << ")));\n";
760 } else {
761 out << "static_assert(offsetof("
762 << fullName()
763 << ", "
764 << field->name()
765 << ") == "
766 << offset
767 << ", \"wrong offset\");\n";
768 }
769
Andreas Huber60d3b222017-03-30 09:10:56 -0700770 if (mStyle == STYLE_STRUCT) {
771 offset += fieldSize;
772 }
Andreas Huberca4bc892017-01-09 14:58:12 -0800773 }
774
775 if (pass == 0) {
776 out.unindent();
777 out << "};\n\n";
778 }
779 }
780
Nirav Atre45e76d52018-06-04 11:49:14 -0700781 CompoundLayout layout = getCompoundAlignmentAndSize();
782 emitLayoutAsserts(out, layout.overall, "");
783 out << "\n";
Yifan Hong244e82d2016-11-11 11:13:57 -0800784}
785
Timur Iskhakovfd3f2502017-09-05 16:25:02 -0700786void CompoundType::emitTypeForwardDeclaration(Formatter& out) const {
Nirav Atre45e76d52018-06-04 11:49:14 -0700787 switch (mStyle) {
788 case STYLE_UNION: {
789 out << "union";
790 break;
791 }
792 case STYLE_STRUCT:
793 case STYLE_SAFE_UNION: {
794 out << "struct";
795 break;
796 }
797 default: {
798 CHECK(!"Should not be here");
799 }
800 }
801 out << " " << localName() << ";\n";
Timur Iskhakovfd3f2502017-09-05 16:25:02 -0700802}
Yifan Hong244e82d2016-11-11 11:13:57 -0800803
Steven Moreland368e4602018-02-16 14:21:49 -0800804void CompoundType::emitPackageTypeDeclarations(Formatter& out) const {
Steven Moreland4b8f7a12017-11-17 15:39:54 -0800805 Scope::emitPackageTypeDeclarations(out);
Yifan Hongc6752dc2016-12-20 14:00:14 -0800806
Steven Morelandbf714212017-10-27 18:29:01 -0700807 out << "static inline std::string toString("
808 << getCppArgumentType()
809 << (mFields->empty() ? "" : " o")
Steven Moreland09c6ebe2018-10-09 10:15:48 -0700810 << ");\n";
811
812 if (canCheckEquality()) {
813 out << "static inline bool operator==("
814 << getCppArgumentType() << " lhs, " << getCppArgumentType() << " rhs);\n";
815
816 out << "static inline bool operator!=("
817 << getCppArgumentType() << " lhs, " << getCppArgumentType() << " rhs);\n";
818 } else {
819 out << "// operator== and operator!= are not generated for " << localName() << "\n";
820 }
821
822 out.endl();
823}
824
825void CompoundType::emitPackageTypeHeaderDefinitions(Formatter& out) const {
826 Scope::emitPackageTypeHeaderDefinitions(out);
827
828 out << "static inline std::string toString("
829 << getCppArgumentType()
830 << (mFields->empty() ? "" : " o")
Steven Morelandbf714212017-10-27 18:29:01 -0700831 << ") ";
832
833 out.block([&] {
834 // include toString for scalar types
835 out << "using ::android::hardware::toString;\n"
836 << "std::string os;\n";
837 out << "os += \"{\";\n";
838
Steven Moreland5dec82f2018-10-10 13:33:29 -0700839 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -0700840 out << "\nswitch (o.getDiscriminator()) {\n";
841 out.indent();
Steven Morelandbf714212017-10-27 18:29:01 -0700842 }
843
Nirav Atre45e76d52018-06-04 11:49:14 -0700844 for (const NamedReference<Type>* field : *mFields) {
845 if (mStyle == STYLE_SAFE_UNION) {
846 out << "case "
847 << fullName()
848 << "::hidl_discriminator::"
849 << field->name()
850 << ": ";
851
852 out.block([&] {
853 out << "os += \"."
854 << field->name()
855 << " = \";\n"
856 << "os += toString(o."
857 << field->name()
858 << "());\n"
859 << "break;\n";
860 }).endl();
861 } else {
862 out << "os += \"";
863 if (field != *(mFields->begin())) {
864 out << ", ";
865 }
866 out << "." << field->name() << " = \";\n";
867 field->type().emitDump(out, "os", "o." + field->name());
868 }
869 }
870
Steven Moreland5dec82f2018-10-10 13:33:29 -0700871 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -0700872 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -0800873 out.block([&] {
874 emitSafeUnionUnknownDiscriminatorError(out, "o.getDiscriminator()",
875 true /*fatal*/);
876 })
Nirav Atree3cae852018-07-16 12:19:16 -0700877 .endl();
Nirav Atre45e76d52018-06-04 11:49:14 -0700878
879 out.unindent();
880 out << "}\n";
881 }
Steven Morelandbf714212017-10-27 18:29:01 -0700882 out << "os += \"}\"; return os;\n";
883 }).endl().endl();
884
885 if (canCheckEquality()) {
886 out << "static inline bool operator==("
887 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
888 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
889 out.block([&] {
Steven Moreland5dec82f2018-10-10 13:33:29 -0700890 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -0700891 out.sIf("lhs.getDiscriminator() != rhs.getDiscriminator()", [&] {
Steven Morelandbf714212017-10-27 18:29:01 -0700892 out << "return false;\n";
893 }).endl();
Nirav Atre45e76d52018-06-04 11:49:14 -0700894
895 out << "switch (lhs.getDiscriminator()) {\n";
896 out.indent();
897 }
898
899 for (const auto& field : *mFields) {
900 if (mStyle == STYLE_SAFE_UNION) {
901 out << "case "
902 << fullName()
903 << "::hidl_discriminator::"
904 << field->name()
905 << ": ";
906
907 out.block([&] {
908 out << "return (lhs."
909 << field->name()
910 << "() == rhs."
911 << field->name()
912 << "());\n";
913 }).endl();
914 } else {
915 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
916 out << "return false;\n";
917 }).endl();
918 }
919 }
920
Steven Moreland5dec82f2018-10-10 13:33:29 -0700921 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -0700922 out << "default: ";
923 out.block([&] {
Steven Moreland5add34d2018-11-08 16:31:30 -0800924 emitSafeUnionUnknownDiscriminatorError(out, "lhs.getDiscriminator()",
925 true /*fatal*/);
Nirav Atree3cae852018-07-16 12:19:16 -0700926 })
927 .endl();
Nirav Atre45e76d52018-06-04 11:49:14 -0700928
929 out.unindent();
930 out << "}\n";
Steven Morelandbf714212017-10-27 18:29:01 -0700931 }
932 out << "return true;\n";
933 }).endl().endl();
934
935 out << "static inline bool operator!=("
Steven Moreland09c6ebe2018-10-09 10:15:48 -0700936 << getCppArgumentType() << " lhs, " << getCppArgumentType() << " rhs)";
Steven Morelandbf714212017-10-27 18:29:01 -0700937 out.block([&] {
938 out << "return !(lhs == rhs);\n";
939 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -0700940 } else {
Steven Morelandf91048a2017-06-23 21:38:35 +0000941 out << "// operator== and operator!= are not generated for " << localName() << "\n\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800942 }
Yifan Hongc6752dc2016-12-20 14:00:14 -0800943}
944
Steven Moreland368e4602018-02-16 14:21:49 -0800945void CompoundType::emitPackageHwDeclarations(Formatter& out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700946 if (needsEmbeddedReadWrite()) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800947 out << "::android::status_t readEmbeddedFromParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700948
Yifan Hong0a68a282016-10-21 16:32:34 -0700949 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700950
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700951 out << "const " << fullName() << " &obj,\n"
Yifan Hong244e82d2016-11-11 11:13:57 -0800952 << "const ::android::hardware::Parcel &parcel,\n"
953 << "size_t parentHandle,\n"
954 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700955
Yifan Hong0a68a282016-10-21 16:32:34 -0700956 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700957
958 out << "::android::status_t writeEmbeddedToParcel(\n";
959
Yifan Hong0a68a282016-10-21 16:32:34 -0700960 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700961
Yifan Hong244e82d2016-11-11 11:13:57 -0800962 out << "const " << fullName() << " &obj,\n"
963 << "::android::hardware::Parcel *parcel,\n"
964 << "size_t parentHandle,\n"
965 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700966
Yifan Hong0a68a282016-10-21 16:32:34 -0700967 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700968 }
969
Yifan Hongbf459bc2016-08-23 16:50:37 -0700970 if(needsResolveReferences()) {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700971 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700972 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800973 out << fullName() << " *obj,\n"
974 << "const ::android::hardware::Parcel &parcel,\n"
975 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700976 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700977 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700978 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800979 out << "const " << fullName() << " &obj,\n"
980 << "::android::hardware::Parcel *,\n"
981 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700982 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700983 }
Andreas Huber881227d2016-08-02 14:20:21 -0700984}
985
Nirav Atre64868d32018-07-15 19:15:18 -0700986static void emitSafeUnionFieldConstructor(Formatter& out,
987 const NamedReference<Type>* field,
988 const std::string& initializerObjectName) {
989 out << "new (&hidl_u."
990 << field->name()
991 << ") "
992 << field->type().getCppStackType()
993 << "("
994 << initializerObjectName
995 << ");\n";
996}
997
998static void emitSafeUnionSetterDefinition(Formatter& out,
999 const NamedReference<Type>* field,
1000 const std::string& parameterName,
1001 bool usesMoveSemantics) {
1002 out.block([&] {
1003 out << "if (hidl_d != hidl_discriminator::"
1004 << field->name()
1005 << ") ";
1006
1007 const std::string argumentName = usesMoveSemantics
1008 ? ("std::move(" + parameterName + ")")
1009 : parameterName;
1010 out.block([&] {
1011 out << "hidl_destructUnion();\n"
1012 << "::std::memset(&hidl_u, 0, sizeof(hidl_u));\n\n";
1013
1014 emitSafeUnionFieldConstructor(out, field, argumentName);
1015 out << "hidl_d = hidl_discriminator::"
1016 << field->name()
1017 << ";\n";
1018 }).endl();
1019
1020 out << "else if (&(hidl_u."
1021 << field->name()
1022 << ") != &"
1023 << parameterName
1024 << ") ";
1025
1026 out.block([&] {
1027 out << "hidl_u."
1028 << field->name()
1029 << " = "
1030 << argumentName
1031 << ";\n";
1032 }).endl();
1033 }).endl().endl();
1034}
1035
1036static void emitSafeUnionGetterDefinition(Formatter& out, const std::string& fieldName) {
Nirav Atre45e76d52018-06-04 11:49:14 -07001037 out.block([&] {
1038 out << "if (CC_UNLIKELY(hidl_d != hidl_discriminator::"
1039 << fieldName
1040 << ")) ";
1041
1042 out.block([&] {
Steven Moreland35835f12018-11-08 17:04:16 -08001043 out << "LOG_ALWAYS_FATAL(\"Bad safe_union access: safe_union has discriminator %\" "
1044 << "PRIu64 \" but discriminator %\" PRIu64 \" was accessed.\",\n";
1045 out.indent(2, [&] {
1046 out << "static_cast<uint64_t>(hidl_d), "
1047 << "static_cast<uint64_t>(hidl_discriminator::" << fieldName << "));";
1048 }).endl();
Nirav Atre45e76d52018-06-04 11:49:14 -07001049 }).endl().endl();
1050
1051 out << "return hidl_u."
1052 << fieldName
1053 << ";\n";
1054 }).endl().endl();
1055}
1056
Nirav Atre71ce0082018-08-01 15:39:49 -07001057std::vector<CompoundType::SafeUnionEnumElement> CompoundType::getSafeUnionEnumElements(
1058 bool useCppTypeName) const {
1059 std::vector<SafeUnionEnumElement> elements;
Nirav Atre71ce0082018-08-01 15:39:49 -07001060
1061 for (const auto& field : *mFields) {
1062 const std::string fieldTypeName = useCppTypeName
1063 ? field->type().getCppStackType(true /* specifyNamespaces */)
1064 : field->type().getJavaType(true /* forInitializer */);
1065
1066 elements.push_back({field->name(), fieldTypeName});
1067 }
1068
1069 return elements;
1070}
1071
Nirav Atre64868d32018-07-15 19:15:18 -07001072void CompoundType::emitSafeUnionCopyAndAssignDefinition(Formatter& out,
1073 const std::string& parameterName,
1074 bool isCopyConstructor,
1075 bool usesMoveSemantics) const {
1076 out.block([&] {
1077 if (!isCopyConstructor) {
1078 out << "if (this == &"
1079 << parameterName
1080 << ") { return *this; }\n\n";
1081 }
1082
1083 out << "switch ("
1084 << parameterName
1085 << ".hidl_d) ";
1086
1087 out.block([&] {
1088 for (const auto& field : *mFields) {
1089 const std::string parameterFieldName = (parameterName + ".hidl_u." +
1090 field->name());
1091
1092 const std::string argumentName = usesMoveSemantics
1093 ? ("std::move(" + parameterFieldName + ")")
1094 : parameterFieldName;
1095
1096 out << "case hidl_discriminator::"
1097 << field->name()
1098 << ": ";
1099
1100 if (isCopyConstructor) {
1101 out.block([&] {
1102 emitSafeUnionFieldConstructor(out, field, argumentName);
1103 out << "break;\n";
1104 }).endl();
1105 } else {
1106 out.block([&] {
1107 out << field->name()
1108 << "("
1109 << argumentName
1110 << ");\n"
1111 << "break;\n";
1112 }).endl();
1113 }
1114 }
1115
Nirav Atree3cae852018-07-16 12:19:16 -07001116 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -08001117 out.block([&] {
1118 emitSafeUnionUnknownDiscriminatorError(out, parameterName + ".hidl_d",
1119 true /*fatal*/);
1120 })
Nirav Atree3cae852018-07-16 12:19:16 -07001121 .endl();
Nirav Atre64868d32018-07-15 19:15:18 -07001122 }).endl();
1123
1124 if (isCopyConstructor) {
1125 out << "\nhidl_d = "
1126 << parameterName
1127 << ".hidl_d;\n";
1128 } else {
1129 out << "return *this;\n";
1130 }
1131 }).endl().endl();
1132}
1133
Nirav Atre45e76d52018-06-04 11:49:14 -07001134void CompoundType::emitSafeUnionTypeConstructors(Formatter& out) const {
1135
1136 // Default constructor
1137 out << fullName()
1138 << "::"
1139 << localName()
Nirav Atre12c597a2018-06-28 09:35:24 -07001140 << "() ";
1141
1142 out.block([&] {
1143 out << "static_assert(offsetof("
1144 << fullName()
1145 << ", hidl_d) == 0, \"wrong offset\");\n";
1146
1147 if (!containsPointer()) {
1148 CompoundLayout layout = getCompoundAlignmentAndSize();
1149 out << "static_assert(offsetof("
1150 << fullName()
1151 << ", hidl_u) == "
1152 << layout.innerStruct.offset
1153 << ", \"wrong offset\");\n";
1154 }
Steven Moreland967c2432018-10-10 12:50:43 -07001155 out.endl();
1156
1157 CHECK(!mFields->empty());
1158 out << "hidl_d = hidl_discriminator::" << mFields->at(0)->name() << ";\n";
1159 emitSafeUnionFieldConstructor(out, mFields->at(0), "");
Nirav Atre12c597a2018-06-28 09:35:24 -07001160 }).endl().endl();
Nirav Atre45e76d52018-06-04 11:49:14 -07001161
1162 // Destructor
1163 out << fullName()
1164 << "::~"
1165 << localName()
1166 << "() ";
1167
1168 out.block([&] {
1169 out << "hidl_destructUnion();\n";
1170 }).endl().endl();
1171
Nirav Atre64868d32018-07-15 19:15:18 -07001172 // Move constructor
1173 out << fullName()
1174 << "::"
1175 << localName()
1176 << "("
1177 << localName()
1178 << "&& other) ";
1179
1180 emitSafeUnionCopyAndAssignDefinition(
1181 out, "other", true /* isCopyConstructor */, true /* usesMoveSemantics */);
1182
Nirav Atre45e76d52018-06-04 11:49:14 -07001183 // Copy constructor
1184 out << fullName()
1185 << "::"
1186 << localName()
1187 << "(const "
1188 << localName()
1189 << "& other) ";
1190
Nirav Atre64868d32018-07-15 19:15:18 -07001191 emitSafeUnionCopyAndAssignDefinition(
1192 out, "other", true /* isCopyConstructor */, false /* usesMoveSemantics */);
Nirav Atre45e76d52018-06-04 11:49:14 -07001193
Nirav Atre64868d32018-07-15 19:15:18 -07001194 // Move assignment operator
1195 out << fullName()
1196 << "& ("
1197 << fullName()
1198 << "::operator=)("
1199 << localName()
1200 << "&& other) ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001201
Nirav Atre64868d32018-07-15 19:15:18 -07001202 emitSafeUnionCopyAndAssignDefinition(
1203 out, "other", false /* isCopyConstructor */, true /* usesMoveSemantics */);
Nirav Atre45e76d52018-06-04 11:49:14 -07001204
Nirav Atre64868d32018-07-15 19:15:18 -07001205 // Copy assignment operator
1206 out << fullName()
1207 << "& ("
1208 << fullName()
1209 << "::operator=)(const "
1210 << localName()
1211 << "& other) ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001212
Nirav Atre64868d32018-07-15 19:15:18 -07001213 emitSafeUnionCopyAndAssignDefinition(
1214 out, "other", false /* isCopyConstructor */, false /* usesMoveSemantics */);
Nirav Atre45e76d52018-06-04 11:49:14 -07001215}
1216
1217void CompoundType::emitSafeUnionTypeDefinitions(Formatter& out) const {
Nirav Atre45e76d52018-06-04 11:49:14 -07001218 emitSafeUnionTypeConstructors(out);
1219
1220 out << "void "
1221 << fullName()
1222 << "::hidl_destructUnion() ";
1223
1224 out.block([&] {
Nirav Atre66842a92018-06-28 18:14:13 -07001225 out << "switch (hidl_d) ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001226 out.block([&] {
1227
1228 for (const auto& field : *mFields) {
1229 out << "case hidl_discriminator::"
1230 << field->name()
1231 << ": ";
1232
1233 out.block([&] {
Steven Moreland9b37ed12018-10-25 11:10:57 -07001234 out << "::android::hardware::details::destructElement(&(hidl_u."
Nirav Atre3b4c7ff2018-07-09 11:57:02 -07001235 << field->name()
1236 << "));\n"
1237 << "break;\n";
Nirav Atre45e76d52018-06-04 11:49:14 -07001238 }).endl();
1239 }
1240
Nirav Atree3cae852018-07-16 12:19:16 -07001241 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -08001242 out.block(
1243 [&] { emitSafeUnionUnknownDiscriminatorError(out, "hidl_d", true /*fatal*/); })
1244 .endl();
Nirav Atre45e76d52018-06-04 11:49:14 -07001245 }).endl().endl();
Nirav Atre45e76d52018-06-04 11:49:14 -07001246 }).endl().endl();
1247
Nirav Atre45e76d52018-06-04 11:49:14 -07001248 for (const NamedReference<Type>* field : *mFields) {
Nirav Atre64868d32018-07-15 19:15:18 -07001249 // Setter (copy)
Nirav Atre45e76d52018-06-04 11:49:14 -07001250 out << "void "
1251 << fullName()
1252 << "::"
1253 << field->name()
1254 << "("
1255 << field->type().getCppArgumentType()
1256 << " o) ";
1257
Nirav Atre64868d32018-07-15 19:15:18 -07001258 emitSafeUnionSetterDefinition(out, field, "o", false /* usesMoveSemantics */);
1259
Steven Moreland492bada2018-09-13 16:12:32 -07001260 if (field->type().resolveToScalarType() == nullptr) {
Nirav Atre64868d32018-07-15 19:15:18 -07001261 // Setter (move)
1262 out << "void "
1263 << fullName()
1264 << "::"
Nirav Atre45e76d52018-06-04 11:49:14 -07001265 << field->name()
Nirav Atre64868d32018-07-15 19:15:18 -07001266 << "("
1267 << field->type().getCppStackType()
1268 << "&& o) ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001269
Nirav Atre64868d32018-07-15 19:15:18 -07001270 emitSafeUnionSetterDefinition(out, field, "o", true /* usesMoveSemantics */);
1271 }
Nirav Atre45e76d52018-06-04 11:49:14 -07001272
1273 // Getter (mutable)
1274 out << field->type().getCppStackType()
1275 << "& ("
1276 << fullName()
1277 << "::"
1278 << field->name()
1279 << ")() ";
1280
Nirav Atre64868d32018-07-15 19:15:18 -07001281 emitSafeUnionGetterDefinition(out, field->name());
Nirav Atre45e76d52018-06-04 11:49:14 -07001282
1283 // Getter (immutable)
1284 out << field->type().getCppArgumentType()
1285 << " ("
1286 << fullName()
1287 << "::"
1288 << field->name()
1289 << ")() const ";
1290
Nirav Atre64868d32018-07-15 19:15:18 -07001291 emitSafeUnionGetterDefinition(out, field->name());
Nirav Atre45e76d52018-06-04 11:49:14 -07001292 }
1293
1294 // Trivial constructor/destructor for internal union
1295 out << fullName() << "::hidl_union::hidl_union() {}\n\n"
1296 << fullName() << "::hidl_union::~hidl_union() {}\n\n";
1297
1298 // Utility method
Nirav Atreca7a5022018-06-29 20:43:49 -07001299 out << fullName() << "::hidl_discriminator ("
1300 << fullName() << "::getDiscriminator)() const ";
Nirav Atre45e76d52018-06-04 11:49:14 -07001301
1302 out.block([&] {
Nirav Atreca7a5022018-06-29 20:43:49 -07001303 out << "return hidl_d;\n";
Nirav Atre45e76d52018-06-04 11:49:14 -07001304 }).endl().endl();
1305}
1306
Steven Moreland368e4602018-02-16 14:21:49 -08001307void CompoundType::emitTypeDefinitions(Formatter& out, const std::string& prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -07001308 std::string space = prefix.empty() ? "" : (prefix + "::");
Steven Moreland368e4602018-02-16 14:21:49 -08001309 Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -07001310
Yifan Hongbf459bc2016-08-23 16:50:37 -07001311 if (needsEmbeddedReadWrite()) {
1312 emitStructReaderWriter(out, prefix, true /* isReader */);
1313 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -07001314 }
1315
Yifan Hongbf459bc2016-08-23 16:50:37 -07001316 if (needsResolveReferences()) {
1317 emitResolveReferenceDef(out, prefix, true /* isReader */);
1318 emitResolveReferenceDef(out, prefix, false /* isReader */);
1319 }
Nirav Atre45e76d52018-06-04 11:49:14 -07001320
1321 if (mStyle == STYLE_SAFE_UNION) {
1322 emitSafeUnionTypeDefinitions(out);
1323 }
Andreas Huber881227d2016-08-02 14:20:21 -07001324}
1325
Steven Moreland5add34d2018-11-08 16:31:30 -08001326static void emitJavaSafeUnionUnknownDiscriminatorError(Formatter& out, bool fatal) {
1327 out << "throw new ";
1328
1329 if (fatal) {
1330 out << "Error";
1331 } else {
1332 out << "IllegalStateException";
1333 }
1334
1335 out << "(\"Unknown union discriminator (value: \" + hidl_d + \").\");\n";
Nirav Atree3cae852018-07-16 12:19:16 -07001336}
1337
Steven Moreland368e4602018-02-16 14:21:49 -08001338void CompoundType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -07001339 out << "public final ";
1340
1341 if (!atTopLevel) {
1342 out << "static ";
1343 }
1344
1345 out << "class "
1346 << localName()
1347 << " {\n";
1348
1349 out.indent();
1350
1351 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
1352
Steven Moreland5dec82f2018-10-10 13:33:29 -07001353 if (mStyle == STYLE_SAFE_UNION) {
Steven Moreland579b0f62018-10-25 13:40:47 -07001354 out << "public " << localName() << "() ";
1355 out.block([&] {
1356 CHECK(!mFields->empty());
1357 mFields->at(0)->type().emitJavaFieldDefaultInitialValue(out, "hidl_o");
1358 }).endl().endl();
1359
Nirav Atre66842a92018-06-28 18:14:13 -07001360 const std::string discriminatorStorageType = (
1361 getUnionDiscriminatorType()->getJavaType(false));
Steven Moreland49bad8d2018-05-17 15:45:26 -07001362
Nirav Atre66842a92018-06-28 18:14:13 -07001363 out << "public static final class hidl_discriminator ";
1364 out.block([&] {
Nirav Atre71ce0082018-08-01 15:39:49 -07001365 const auto elements = getSafeUnionEnumElements(false /* useCppTypeName */);
1366 for (size_t idx = 0; idx < elements.size(); idx++) {
Nirav Atre66842a92018-06-28 18:14:13 -07001367 out << "public static final "
1368 << discriminatorStorageType
1369 << " "
Nirav Atre71ce0082018-08-01 15:39:49 -07001370 << elements[idx].fieldName
Nirav Atre66842a92018-06-28 18:14:13 -07001371 << " = "
1372 << idx
Nirav Atre71ce0082018-08-01 15:39:49 -07001373 << ";";
1374
1375 if (!elements[idx].fieldTypeName.empty()) {
1376 out << " // "
1377 << elements[idx].fieldTypeName;
1378 }
1379 out << "\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001380 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001381
Nirav Atre66842a92018-06-28 18:14:13 -07001382 out << "\n"
1383 << "public static final String getName("
1384 << discriminatorStorageType
1385 << " value) ";
1386
1387 out.block([&] {
1388 out << "switch (value) ";
1389 out.block([&] {
Nirav Atre71ce0082018-08-01 15:39:49 -07001390 for (size_t idx = 0; idx < elements.size(); idx++) {
Nirav Atre66842a92018-06-28 18:14:13 -07001391 out << "case "
1392 << idx
1393 << ": { return \""
Nirav Atre71ce0082018-08-01 15:39:49 -07001394 << elements[idx].fieldName
Nirav Atre66842a92018-06-28 18:14:13 -07001395 << "\"; }\n";
1396 }
1397 out << "default: { return \"Unknown\"; }\n";
1398 }).endl();
1399 }).endl().endl();
1400
1401 out << "private hidl_discriminator() {}\n";
1402 }).endl().endl();
1403
Steven Moreland967c2432018-10-10 12:50:43 -07001404 out << "private " << discriminatorStorageType << " hidl_d = 0;\n";
Steven Moreland579b0f62018-10-25 13:40:47 -07001405 out << "private Object hidl_o = null;\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001406
1407 for (const auto& field : *mFields) {
1408 // Setter
1409 out << "public void "
1410 << field->name()
1411 << "("
1412 << field->type().getJavaType(false)
1413 << " "
1414 << field->name()
1415 << ") ";
1416
1417 out.block([&] {
1418 out << "hidl_d = hidl_discriminator."
1419 << field->name()
1420 << ";\n";
1421
1422 out << "hidl_o = "
1423 << field->name()
1424 << ";\n";
1425 }).endl().endl();
1426
1427 // Getter
1428 out << "public "
1429 << field->type().getJavaType(false)
1430 << " "
1431 << field->name()
1432 << "() ";
1433
1434 out.block([&] {
1435 out << "if (hidl_d != hidl_discriminator."
1436 << field->name()
1437 << ") ";
1438
1439 out.block([&] {
1440 out << "String className = (hidl_o != null) ? "
1441 << "hidl_o.getClass().getName() : \"null\";\n";
1442
1443 out << "throw new IllegalStateException(\n";
1444 out.indent(2, [&] {
1445 out << "\"Read access to inactive union components is disallowed. \" +\n"
1446 << "\"Discriminator value is \" + hidl_d + \" (corresponding \" +\n"
1447 << "\"to \" + hidl_discriminator.getName(hidl_d) + \"), and \" +\n"
1448 << "\"hidl_o is of type \" + className + \".\");\n";
1449 });
1450 }).endl();
1451
1452 out << "if (hidl_o != null && !"
1453 << field->type().getJavaTypeClass()
1454 << ".class.isInstance(hidl_o)) ";
1455
1456 out.block([&] {
1457 out << "throw new Error(\"Union is in a corrupted state.\");\n";
1458 }).endl();
1459
1460 out << "return ("
1461 << field->type().getJavaTypeCast("hidl_o")
1462 << ");\n";
1463 }).endl().endl();
1464 }
1465
1466 out << "// Utility method\n"
1467 << "public "
1468 << discriminatorStorageType
1469 << " getDiscriminator() { return hidl_d; }\n\n";
1470
Steven Moreland5dec82f2018-10-10 13:33:29 -07001471 } else {
Nirav Atre66842a92018-06-28 18:14:13 -07001472 for (const auto& field : *mFields) {
1473 field->emitDocComment(out);
1474
1475 out << "public ";
1476 field->type().emitJavaFieldInitializer(out, field->name());
1477 }
1478
Andreas Huber85eabdb2016-08-25 11:24:49 -07001479 out << "\n";
1480 }
1481
Yifan Hongec102272016-12-20 18:10:07 -08001482 ////////////////////////////////////////////////////////////////////////////
1483
1484 if (canCheckEquality()) {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001485 out << "@Override\npublic final boolean equals(Object otherObject) ";
Yifan Hongec102272016-12-20 18:10:07 -08001486 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001487 out.sIf("this == otherObject", [&] {
1488 out << "return true;\n";
1489 }).endl();
1490 out.sIf("otherObject == null", [&] {
1491 out << "return false;\n";
1492 }).endl();
Yifan Hong45b331b2017-03-27 12:59:54 -07001493 // Though class is final, we use getClass instead of instanceof to be explicit.
1494 out.sIf("otherObject.getClass() != " + fullJavaName() + ".class", [&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001495 out << "return false;\n";
1496 }).endl();
1497 out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001498
Steven Moreland5dec82f2018-10-10 13:33:29 -07001499 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001500 out.sIf("this.hidl_d != other.hidl_d", [&] {
Yifan Hongec102272016-12-20 18:10:07 -08001501 out << "return false;\n";
1502 }).endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001503 out.sIf("!android.os.HidlSupport.deepEquals(this.hidl_o, other.hidl_o)", [&] {
1504 out << "return false;\n";
1505 }).endl();
Steven Moreland5dec82f2018-10-10 13:33:29 -07001506 } else {
Nirav Atre66842a92018-06-28 18:14:13 -07001507 for (const auto &field : *mFields) {
1508 std::string condition = (field->type().isScalar() || field->type().isEnum())
1509 ? "this." + field->name() + " != other." + field->name()
1510 : ("!android.os.HidlSupport.deepEquals(this." + field->name()
1511 + ", other." + field->name() + ")");
1512 out.sIf(condition, [&] {
1513 out << "return false;\n";
1514 }).endl();
1515 }
Yifan Hongec102272016-12-20 18:10:07 -08001516 }
1517 out << "return true;\n";
1518 }).endl().endl();
1519
Yifan Hong7d1839f2017-02-22 13:24:29 -08001520 out << "@Override\npublic final int hashCode() ";
Yifan Hongec102272016-12-20 18:10:07 -08001521 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001522 out << "return java.util.Objects.hash(\n";
1523 out.indent(2, [&] {
Steven Moreland5dec82f2018-10-10 13:33:29 -07001524 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001525 out << "android.os.HidlSupport.deepHashCode(this.hidl_o),\n"
1526 << "java.util.Objects.hashCode(this.hidl_d)";
1527 } else {
1528 out.join(mFields->begin(), mFields->end(), ", \n", [&] (const auto &field) {
1529 out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")";
1530 });
1531 }
Yifan Hong7d1839f2017-02-22 13:24:29 -08001532 });
Yifan Hongec102272016-12-20 18:10:07 -08001533 out << ");\n";
1534 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -07001535 } else {
1536 out << "// equals() is not generated for " << localName() << "\n";
Yifan Hongec102272016-12-20 18:10:07 -08001537 }
1538
1539 ////////////////////////////////////////////////////////////////////////////
1540
Steven Moreland78ab7532019-01-10 13:04:23 -08001541 if (kDetailJavaToString) {
1542 out << "@Override\npublic final String toString() ";
1543 out.block([&] {
1544 out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n"
1545 << "builder.append(\"{\");\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001546
Nirav Atre66842a92018-06-28 18:14:13 -07001547 if (mStyle == STYLE_SAFE_UNION) {
Steven Moreland78ab7532019-01-10 13:04:23 -08001548 out << "switch (this.hidl_d) {\n";
1549 out.indent();
1550 }
Nirav Atre66842a92018-06-28 18:14:13 -07001551
Steven Moreland78ab7532019-01-10 13:04:23 -08001552 for (const auto &field : *mFields) {
1553 if (mStyle == STYLE_SAFE_UNION) {
1554 out << "case hidl_discriminator."
Nirav Atre66842a92018-06-28 18:14:13 -07001555 << field->name()
Steven Moreland78ab7532019-01-10 13:04:23 -08001556 << ": ";
Nirav Atre66842a92018-06-28 18:14:13 -07001557
Steven Moreland78ab7532019-01-10 13:04:23 -08001558 out.block([&] {
1559 out << "builder.append(\""
1560 << "."
1561 << field->name()
1562 << " = \");\n";
1563
1564 field->type().emitJavaDump(out, "builder", "this." + field->name() + "()");
1565 out << "break;\n";
1566 }).endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001567 }
Steven Moreland78ab7532019-01-10 13:04:23 -08001568 else {
1569 out << "builder.append(\"";
1570 if (field != *(mFields->begin())) {
1571 out << ", ";
1572 }
1573 out << "." << field->name() << " = \");\n";
1574 field->type().emitJavaDump(out, "builder", "this." + field->name());
1575 }
Nirav Atre66842a92018-06-28 18:14:13 -07001576 }
Nirav Atre66842a92018-06-28 18:14:13 -07001577
Steven Moreland78ab7532019-01-10 13:04:23 -08001578 if (mStyle == STYLE_SAFE_UNION) {
1579 out << "default: ";
1580 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, true /*fatal*/); })
1581 .endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001582
Steven Moreland78ab7532019-01-10 13:04:23 -08001583 out.unindent();
1584 out << "}\n";
1585 }
Nirav Atre66842a92018-06-28 18:14:13 -07001586
Steven Moreland78ab7532019-01-10 13:04:23 -08001587 out << "builder.append(\"}\");\nreturn builder.toString();\n";
1588 }).endl().endl();
1589 }
Yifan Honge45b5302017-02-22 10:49:07 -08001590
Nirav Atre66842a92018-06-28 18:14:13 -07001591 CompoundLayout layout = getCompoundAlignmentAndSize();
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001592
Yifan Honge45b5302017-02-22 10:49:07 -08001593 ////////////////////////////////////////////////////////////////////////////
1594
Yifan Hong1af73532016-11-09 14:32:58 -08001595 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001596 out.indent();
Howard Chenaf084db2017-12-27 18:46:39 +08001597 if (containsInterface()) {
Nirav Atre66842a92018-06-28 18:14:13 -07001598
Steven Moreland5dec82f2018-10-10 13:33:29 -07001599 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001600 out << "hidl_d = ";
1601 getUnionDiscriminatorType()->emitJavaReaderWriter(
1602 out, "parcel", "hidl_d", true);
1603
1604 out << "switch (hidl_d) {\n";
1605 out.indent();
1606 }
1607
Howard Chenaf084db2017-12-27 18:46:39 +08001608 for (const auto& field : *mFields) {
Nirav Atre66842a92018-06-28 18:14:13 -07001609 if (mStyle == STYLE_SAFE_UNION) {
1610 out << "case hidl_discriminator."
1611 << field->name()
1612 << ": ";
1613
1614 out.block([&] {
1615 out << "hidl_o = ";
1616 field->type().emitJavaReaderWriter(out, "parcel", "hidl_o", true);
1617
1618 out << "break;\n";
1619 }).endl();
1620 } else {
1621 out << field->name() << " = ";
1622 field->type().emitJavaReaderWriter(out, "parcel", field->name(), true);
1623 }
1624 }
1625
Steven Moreland5dec82f2018-10-10 13:33:29 -07001626 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atree3cae852018-07-16 12:19:16 -07001627 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -08001628 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, false /*fatal*/); })
1629 .endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001630
1631 out.unindent();
1632 out << "}\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001633 }
1634 } else {
1635 out << "android.os.HwBlob blob = parcel.readBuffer(";
Nirav Atre66842a92018-06-28 18:14:13 -07001636 out << layout.overall.size << " /* size */);\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001637 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
1638 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001639 out.unindent();
1640 out << "}\n\n";
1641
Andreas Huberf630bc82016-09-09 14:52:25 -07001642 ////////////////////////////////////////////////////////////////////////////
1643
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001644 size_t vecAlign, vecSize;
1645 VectorType::getAlignmentAndSizeStatic(&vecAlign, &vecSize);
1646
Howard Chenaf084db2017-12-27 18:46:39 +08001647 out << "public static final java.util.ArrayList<" << localName()
Yifan Hong1af73532016-11-09 14:32:58 -08001648 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001649 out.indent();
1650
Howard Chenaf084db2017-12-27 18:46:39 +08001651 out << "java.util.ArrayList<" << localName() << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001652
Howard Chenaf084db2017-12-27 18:46:39 +08001653 if (containsInterface()) {
1654 out << "int size = parcel.readInt32();\n";
1655 out << "for(int i = 0 ; i < size; i ++) {\n";
1656 out.indent();
1657 out << fullJavaName() << " tmp = ";
1658 emitJavaReaderWriter(out, "parcel", "tmp", true);
1659 out << "_hidl_vec.add(tmp);\n";
1660 out.unindent();
1661 out << "}\n";
1662 } else {
1663 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer(";
1664 out << vecSize << " /* sizeof hidl_vec<T> */);\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001665
Howard Chenaf084db2017-12-27 18:46:39 +08001666 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel",
1667 "_hidl_blob", "_hidl_vec", "0",
1668 true /* isReader */);
Andreas Huber85eabdb2016-08-25 11:24:49 -07001669 }
Howard Chenaf084db2017-12-27 18:46:39 +08001670 out << "\nreturn _hidl_vec;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001671 out.unindent();
1672 out << "}\n\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001673 ////////////////////////////////////////////////////////////////////////////
1674 if (containsInterface()) {
1675 out << "// readEmbeddedFromParcel is not generated()\n";
1676 } else {
1677 out << "public final void readEmbeddedFromParcel(\n";
1678 out.indent(2);
1679 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
1680 out.unindent();
Nirav Atre66842a92018-06-28 18:14:13 -07001681
Steven Moreland5dec82f2018-10-10 13:33:29 -07001682 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001683 getUnionDiscriminatorType()->emitJavaFieldReaderWriter(
1684 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d",
1685 "_hidl_offset + " + std::to_string(layout.discriminator.offset),
1686 true /* isReader */);
1687
1688 out << "switch (this.hidl_d) {\n";
1689 out.indent();
1690 }
1691
1692 size_t offset = layout.innerStruct.offset;
Howard Chenaf084db2017-12-27 18:46:39 +08001693 for (const auto& field : *mFields) {
Howard Chenaf084db2017-12-27 18:46:39 +08001694
Nirav Atre66842a92018-06-28 18:14:13 -07001695 if (mStyle == STYLE_SAFE_UNION) {
1696 out << "case hidl_discriminator."
1697 << field->name()
1698 << ": ";
Howard Chenaf084db2017-12-27 18:46:39 +08001699
Nirav Atre66842a92018-06-28 18:14:13 -07001700 out.block([&] {
1701 field->type().emitJavaFieldDefaultInitialValue(out, "hidl_o");
1702 field->type().emitJavaFieldReaderWriter(
1703 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_o",
1704 "_hidl_offset + " + std::to_string(offset), true /* isReader */);
1705
1706 out << "break;\n";
1707 }).endl();
1708 } else {
1709 size_t fieldAlign, fieldSize;
1710 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1711
1712 offset += Layout::getPad(offset, fieldAlign);
1713 field->type().emitJavaFieldReaderWriter(
1714 out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
1715 "_hidl_offset + " + std::to_string(offset), true /* isReader */);
1716 offset += fieldSize;
1717 }
1718 }
1719
Steven Moreland5dec82f2018-10-10 13:33:29 -07001720 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atree3cae852018-07-16 12:19:16 -07001721 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -08001722 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, false /*fatal*/); })
1723 .endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001724
1725 out.unindent();
1726 out << "}\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001727 }
1728 out.unindent();
1729 out << "}\n\n";
1730 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001731
Andreas Huberf630bc82016-09-09 14:52:25 -07001732 ////////////////////////////////////////////////////////////////////////////
1733
Yifan Hong1af73532016-11-09 14:32:58 -08001734 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001735 out.indent();
1736
Howard Chenaf084db2017-12-27 18:46:39 +08001737 if (containsInterface()) {
Steven Moreland5dec82f2018-10-10 13:33:29 -07001738 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001739 getUnionDiscriminatorType()->emitJavaReaderWriter(
1740 out, "parcel", "hidl_d", false);
1741
1742 out << "switch (this.hidl_d) {\n";
1743 out.indent();
1744 }
1745
Howard Chenaf084db2017-12-27 18:46:39 +08001746 for (const auto& field : *mFields) {
Nirav Atre66842a92018-06-28 18:14:13 -07001747 if (mStyle == STYLE_SAFE_UNION) {
1748 out << "case hidl_discriminator."
1749 << field->name()
1750 << ": ";
1751
1752 out.block([&] {
1753 field->type().emitJavaReaderWriter(out, "parcel", field->name() + "()", false);
1754 out << "break;\n";
1755 }).endl();
1756 } else {
1757 field->type().emitJavaReaderWriter(out, "parcel", field->name(), false);
1758 }
1759 }
1760
Steven Moreland5dec82f2018-10-10 13:33:29 -07001761 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atree3cae852018-07-16 12:19:16 -07001762 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -08001763 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, true /*fatal*/); })
1764 .endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001765
1766 out.unindent();
1767 out << "}\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001768 }
1769 } else {
Nirav Atre66842a92018-06-28 18:14:13 -07001770 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
1771 << layout.overall.size
Howard Chenaf084db2017-12-27 18:46:39 +08001772 << " /* size */);\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001773
Howard Chenaf084db2017-12-27 18:46:39 +08001774 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
1775 << "parcel.writeBuffer(_hidl_blob);\n";
1776 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001777 out.unindent();
1778 out << "}\n\n";
1779
Andreas Huberf630bc82016-09-09 14:52:25 -07001780 ////////////////////////////////////////////////////////////////////////////
1781
Andreas Huberf630bc82016-09-09 14:52:25 -07001782 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001783 out.indent(2);
Howard Chenaf084db2017-12-27 18:46:39 +08001784 out << "android.os.HwParcel parcel, java.util.ArrayList<" << localName() << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001785 out.unindent();
1786
Howard Chenaf084db2017-12-27 18:46:39 +08001787 if (containsInterface()) {
1788 out << "parcel.writeInt32(_hidl_vec.size());\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001789 out << "for(" << fullJavaName() << " tmp: _hidl_vec) ";
1790 out.block([&] {
1791 emitJavaReaderWriter(out, "parcel", "tmp", false);
1792 }).endl();
Howard Chenaf084db2017-12-27 18:46:39 +08001793 } else {
1794 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(" << vecSize
1795 << " /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001796
Howard Chenaf084db2017-12-27 18:46:39 +08001797 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel",
1798 "_hidl_blob", "_hidl_vec", "0",
1799 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -07001800
Howard Chenaf084db2017-12-27 18:46:39 +08001801 out << "\nparcel.writeBuffer(_hidl_blob);\n";
1802 }
Andreas Huberf630bc82016-09-09 14:52:25 -07001803 out.unindent();
1804 out << "}\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001805 ////////////////////////////////////////////////////////////////////////////
1806
Howard Chenaf084db2017-12-27 18:46:39 +08001807 if (containsInterface()) {
Nirav Atre66842a92018-06-28 18:14:13 -07001808 out << "// writeEmbeddedToBlob() is not generated\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001809 } else {
1810 out << "public final void writeEmbeddedToBlob(\n";
1811 out.indent(2);
1812 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
1813 out.unindent();
Nirav Atre45e76d52018-06-04 11:49:14 -07001814
Steven Moreland5dec82f2018-10-10 13:33:29 -07001815 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre66842a92018-06-28 18:14:13 -07001816 getUnionDiscriminatorType()->emitJavaFieldReaderWriter(
1817 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d",
1818 "_hidl_offset + " + std::to_string(layout.discriminator.offset),
1819 false /* isReader */);
Nirav Atre45e76d52018-06-04 11:49:14 -07001820
Nirav Atre66842a92018-06-28 18:14:13 -07001821 out << "switch (this.hidl_d) {\n";
1822 out.indent();
Andreas Huber85eabdb2016-08-25 11:24:49 -07001823 }
1824
Nirav Atre66842a92018-06-28 18:14:13 -07001825 size_t offset = layout.innerStruct.offset;
1826 for (const auto& field : *mFields) {
1827 if (mStyle == STYLE_SAFE_UNION) {
1828 out << "case hidl_discriminator."
1829 << field->name()
1830 << ": ";
1831
1832 out.block([&] {
1833 field->type().emitJavaFieldReaderWriter(
1834 out, 0 /* depth */, "parcel", "_hidl_blob", field->name() + "()",
1835 "_hidl_offset + " + std::to_string(offset), false /* isReader */);
1836
1837 out << "break;\n";
1838 }).endl();
1839 } else {
1840 size_t fieldAlign, fieldSize;
1841 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1842
1843 offset += Layout::getPad(offset, fieldAlign);
1844 field->type().emitJavaFieldReaderWriter(
1845 out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
1846 "_hidl_offset + " + std::to_string(offset), false /* isReader */);
1847 offset += fieldSize;
1848 }
1849 }
1850
Steven Moreland5dec82f2018-10-10 13:33:29 -07001851 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atree3cae852018-07-16 12:19:16 -07001852 out << "default: ";
Steven Moreland5add34d2018-11-08 16:31:30 -08001853 out.block([&] { emitJavaSafeUnionUnknownDiscriminatorError(out, true /*fatal*/); })
1854 .endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001855
1856 out.unindent();
1857 out << "}\n";
1858 }
Howard Chenaf084db2017-12-27 18:46:39 +08001859 out.unindent();
1860 out << "}\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001861 }
1862
1863 out.unindent();
Andreas Huber85eabdb2016-08-25 11:24:49 -07001864 out << "};\n\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001865}
1866
Andreas Huber881227d2016-08-02 14:20:21 -07001867void CompoundType::emitStructReaderWriter(
1868 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -08001869
1870 std::string space = prefix.empty() ? "" : (prefix + "::");
1871
Andreas Huber881227d2016-08-02 14:20:21 -07001872 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -08001873 << (isReader ? "readEmbeddedFromParcel"
1874 : "writeEmbeddedToParcel")
1875 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001876
Yifan Hong0a68a282016-10-21 16:32:34 -07001877 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -07001878
Nirav Atre97b7e9c2018-07-26 19:29:40 -07001879 const std::string name = "obj";
Andreas Huber881227d2016-08-02 14:20:21 -07001880 if (isReader) {
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001881 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001882 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001883 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -08001884 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001885 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001886 }
1887
1888 out << "size_t parentHandle,\n"
1889 << "size_t parentOffset)";
1890
Andreas Huber881227d2016-08-02 14:20:21 -07001891 out << " {\n";
1892
Yifan Hong0a68a282016-10-21 16:32:34 -07001893 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -07001894 out.indent();
1895
Iliyan Malchev549e2592016-08-10 08:59:12 -07001896 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001897
Steven Moreland5dec82f2018-10-10 13:33:29 -07001898 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -07001899 out << "switch (" << name << ".getDiscriminator()) {\n";
1900 out.indent();
1901 }
1902
Andreas Huber881227d2016-08-02 14:20:21 -07001903 for (const auto &field : *mFields) {
1904 if (!field->type().needsEmbeddedReadWrite()) {
1905 continue;
1906 }
1907
Nirav Atre45e76d52018-06-04 11:49:14 -07001908 if (mStyle == STYLE_SAFE_UNION) {
1909 out << "case " << fullName() << "::hidl_discriminator::"
1910 << field->name() << ": {\n";
1911 out.indent();
1912 }
1913
1914 const std::string fieldName = (mStyle == STYLE_SAFE_UNION)
Nirav Atre97b7e9c2018-07-26 19:29:40 -07001915 ? (name + "." + field->name() + "()")
1916 : (name + "." + field->name());
Nirav Atre45e76d52018-06-04 11:49:14 -07001917
1918 const std::string fieldOffset = (mStyle == STYLE_SAFE_UNION)
Nirav Atre12c597a2018-06-28 09:35:24 -07001919 ? (name + ".hidl_getUnionOffset() " +
1920 "/* safe_union: union offset into struct */")
Nirav Atre45e76d52018-06-04 11:49:14 -07001921 : ("offsetof(" + fullName() + ", " + field->name() + ")");
1922
Andreas Huber881227d2016-08-02 14:20:21 -07001923 field->type().emitReaderWriterEmbedded(
1924 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -07001925 0 /* depth */,
Nirav Atre45e76d52018-06-04 11:49:14 -07001926 fieldName,
Yifan Hongbe2a3732016-10-05 13:33:41 -07001927 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -07001928 false /* nameIsPointer */,
1929 "parcel",
1930 !isReader /* parcelObjIsPointer */,
1931 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -07001932 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -07001933 "parentHandle",
Nirav Atre45e76d52018-06-04 11:49:14 -07001934 "parentOffset + " + fieldOffset);
1935
1936 if (mStyle == STYLE_SAFE_UNION) {
1937 out << "break;\n";
1938 out.unindent();
1939 out << "}\n";
1940 }
1941 }
1942
Steven Moreland5dec82f2018-10-10 13:33:29 -07001943 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre45e76d52018-06-04 11:49:14 -07001944 out << "default: { break; }\n";
1945 out.unindent();
1946 out << "}\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001947 }
1948
Iliyan Malchev549e2592016-08-10 08:59:12 -07001949 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001950
1951 out.unindent();
1952 out << "}\n\n";
1953}
1954
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -07001955void CompoundType::emitResolveReferenceDef(Formatter& out, const std::string& prefix,
1956 bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -08001957 out << "::android::status_t ";
1958 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -07001959
1960 bool useParent = false;
1961 for (const auto &field : *mFields) {
1962 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
1963 useParent = true;
1964 break;
1965 }
1966 }
1967
1968 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
1969 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
1970
Yifan Hongbf459bc2016-08-23 16:50:37 -07001971 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -08001972 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001973 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -08001974 out << space + localName() + " *obj,\n"
1975 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -07001976 << "size_t " << parentHandleName << ", "
1977 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001978 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001979 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -08001980 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001981 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -08001982 out << "const " << space + localName() + " &obj,\n"
1983 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -07001984 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -08001985 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001986 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001987 }
1988
1989 out << " {\n";
1990
1991 out.indent();
1992
1993 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
1994
Yifan Hong244e82d2016-11-11 11:13:57 -08001995 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -07001996 // if not useParent, then parentName and offsetText
1997 // should not be used at all, then the #error should not be emitted.
1998 std::string error = useParent ? "" : "\n#error\n";
1999
Nirav Atre45e76d52018-06-04 11:49:14 -07002000 if (mStyle == STYLE_SAFE_UNION) {
2001 out << "switch (" << nameDeref << "getDiscriminator()) {\n";
2002 out.indent();
2003 }
2004
Yifan Hongbf459bc2016-08-23 16:50:37 -07002005 for (const auto &field : *mFields) {
2006 if (!field->type().needsResolveReferences()) {
2007 continue;
2008 }
2009
Nirav Atre45e76d52018-06-04 11:49:14 -07002010 if (mStyle == STYLE_SAFE_UNION) {
2011 out << "case " << fullName() << "::hidl_discriminator::"
2012 << field->name() << ": {\n";
2013 out.indent();
2014 }
2015
2016 const std::string fieldName = (mStyle == STYLE_SAFE_UNION)
2017 ? (nameDeref + field->name() + "()")
2018 : (nameDeref + field->name());
2019
2020 const std::string fieldOffset = (mStyle == STYLE_SAFE_UNION)
Nirav Atre12c597a2018-06-28 09:35:24 -07002021 ? (nameDeref + "hidl_getUnionOffset() " +
2022 "/* safe_union: union offset into struct */")
Nirav Atre45e76d52018-06-04 11:49:14 -07002023 : ("offsetof(" + fullName() + ", " + field->name() + ")");
2024
Yifan Hongbf459bc2016-08-23 16:50:37 -07002025 field->type().emitResolveReferencesEmbedded(
2026 out,
2027 0 /* depth */,
Nirav Atre45e76d52018-06-04 11:49:14 -07002028 fieldName,
Yifan Hongbf459bc2016-08-23 16:50:37 -07002029 field->name() /* sanitizedName */,
2030 false, // nameIsPointer
2031 "parcel", // const std::string &parcelObj,
2032 !isReader, // bool parcelObjIsPointer,
2033 isReader, // bool isReader,
2034 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -07002035 parentHandleName + error,
2036 parentOffsetName
Nirav Atre45e76d52018-06-04 11:49:14 -07002037 + " + "
2038 + fieldOffset
Yifan Hong00f47172016-09-30 14:40:45 -07002039 + error);
Nirav Atre45e76d52018-06-04 11:49:14 -07002040
2041 if (mStyle == STYLE_SAFE_UNION) {
2042 out << "break;\n";
2043 out.unindent();
2044 out << "}\n";
2045 }
2046 }
2047
2048 if (mStyle == STYLE_SAFE_UNION) {
2049 out << "default: { _hidl_err = ::android::BAD_VALUE; break; }\n";
2050 out.unindent();
2051 out << "}\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -07002052 }
2053
Yifan Hongbf459bc2016-08-23 16:50:37 -07002054 out << "return _hidl_err;\n";
2055
2056 out.unindent();
2057 out << "}\n\n";
2058}
2059
Andreas Huber881227d2016-08-02 14:20:21 -07002060bool CompoundType::needsEmbeddedReadWrite() const {
Nirav Atre45e76d52018-06-04 11:49:14 -07002061 if (mStyle == STYLE_UNION) {
Andreas Huber881227d2016-08-02 14:20:21 -07002062 return false;
2063 }
2064
2065 for (const auto &field : *mFields) {
2066 if (field->type().needsEmbeddedReadWrite()) {
2067 return true;
2068 }
2069 }
2070
2071 return false;
2072}
2073
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002074bool CompoundType::deepNeedsResolveReferences(std::unordered_set<const Type*>* visited) const {
Nirav Atre45e76d52018-06-04 11:49:14 -07002075 if (mStyle == STYLE_UNION) {
Yifan Hongbf459bc2016-08-23 16:50:37 -07002076 return false;
2077 }
2078
2079 for (const auto &field : *mFields) {
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002080 if (field->type().needsResolveReferences(visited)) {
Yifan Hongbf459bc2016-08-23 16:50:37 -07002081 return true;
2082 }
2083 }
2084
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002085 return Scope::deepNeedsResolveReferences(visited);
Yifan Hongbf459bc2016-08-23 16:50:37 -07002086}
2087
Andreas Huber881227d2016-08-02 14:20:21 -07002088bool CompoundType::resultNeedsDeref() const {
Howard Chenecfb4512017-11-21 18:28:53 +08002089 return !containsInterface() ;
Andreas Huber881227d2016-08-02 14:20:21 -07002090}
2091
Steven Moreland368e4602018-02-16 14:21:49 -08002092void CompoundType::emitVtsTypeDeclarations(Formatter& out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07002093 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07002094 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002095
2096 // Emit declaration for each subtype.
2097 for (const auto &type : getSubTypes()) {
2098 switch (mStyle) {
2099 case STYLE_STRUCT:
2100 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07002101 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002102 break;
2103 }
2104 case STYLE_UNION:
2105 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07002106 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002107 break;
2108 }
Nirav Atre45e76d52018-06-04 11:49:14 -07002109 case STYLE_SAFE_UNION:
2110 {
2111 out << "sub_safe_union: {\n";
2112 break;
2113 }
2114 default:
2115 {
2116 CHECK(!"Should not be here");
2117 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002118 }
2119 out.indent();
Steven Moreland368e4602018-02-16 14:21:49 -08002120 type->emitVtsTypeDeclarations(out);
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002121 out.unindent();
2122 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07002123 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002124
2125 // Emit declaration for each field.
2126 for (const auto &field : *mFields) {
2127 switch (mStyle) {
2128 case STYLE_STRUCT:
2129 {
2130 out << "struct_value: {\n";
2131 break;
2132 }
2133 case STYLE_UNION:
2134 {
2135 out << "union_value: {\n";
2136 break;
2137 }
Nirav Atre45e76d52018-06-04 11:49:14 -07002138 case STYLE_SAFE_UNION:
2139 {
2140 out << "safe_union_value: {\n";
2141 break;
2142 }
2143 default:
2144 {
2145 CHECK(!"Should not be here");
2146 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002147 }
2148 out.indent();
2149 out << "name: \"" << field->name() << "\"\n";
Steven Moreland368e4602018-02-16 14:21:49 -08002150 field->type().emitVtsAttributeType(out);
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002151 out.unindent();
2152 out << "}\n";
2153 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07002154}
2155
Steven Moreland368e4602018-02-16 14:21:49 -08002156void CompoundType::emitVtsAttributeType(Formatter& out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07002157 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07002158 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07002159}
2160
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002161bool CompoundType::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
Nirav Atre66842a92018-06-28 18:14:13 -07002162 if (mStyle == STYLE_UNION) {
Andreas Huber0fa9e392016-08-31 09:05:44 -07002163 return false;
2164 }
2165
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002166 for (const auto* field : *mFields) {
2167 if (!field->get()->isJavaCompatible(visited)) {
Andreas Huber0fa9e392016-08-31 09:05:44 -07002168 return false;
2169 }
2170 }
2171
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002172 return Scope::deepIsJavaCompatible(visited);
Andreas Huber85eabdb2016-08-25 11:24:49 -07002173}
2174
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002175bool CompoundType::deepContainsPointer(std::unordered_set<const Type*>* visited) const {
2176 for (const auto* field : *mFields) {
2177 if (field->get()->containsPointer(visited)) {
Andreas Huber60d3b222017-03-30 09:10:56 -07002178 return true;
2179 }
2180 }
2181
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002182 return Scope::deepContainsPointer(visited);
Andreas Huber60d3b222017-03-30 09:10:56 -07002183}
2184
Andreas Huber85eabdb2016-08-25 11:24:49 -07002185void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
Nirav Atre45e76d52018-06-04 11:49:14 -07002186 CompoundLayout layout = getCompoundAlignmentAndSize();
2187 *align = layout.overall.align;
2188 *size = layout.overall.size;
2189}
Andreas Huber85eabdb2016-08-25 11:24:49 -07002190
Nirav Atre45e76d52018-06-04 11:49:14 -07002191CompoundType::CompoundLayout CompoundType::getCompoundAlignmentAndSize() const {
2192 CompoundLayout compoundLayout;
2193
2194 // Local aliases for convenience
2195 Layout& overall = compoundLayout.overall;
2196 Layout& innerStruct = compoundLayout.innerStruct;
2197 Layout& discriminator = compoundLayout.discriminator;
2198
Steven Moreland5dec82f2018-10-10 13:33:29 -07002199 if (mStyle == STYLE_SAFE_UNION) {
Nirav Atre12c597a2018-06-28 09:35:24 -07002200 getUnionDiscriminatorType()->getAlignmentAndSize(
2201 &(discriminator.align), &(discriminator.size));
2202
2203 innerStruct.offset = discriminator.size;
2204 }
2205
Andreas Huber85eabdb2016-08-25 11:24:49 -07002206 for (const auto &field : *mFields) {
Nirav Atre45e76d52018-06-04 11:49:14 -07002207
Andreas Huber85eabdb2016-08-25 11:24:49 -07002208 // Each field is aligned according to its alignment requirement.
2209 // The surrounding structure's alignment is the maximum of its
2210 // fields' aligments.
Andreas Huber85eabdb2016-08-25 11:24:49 -07002211 size_t fieldAlign, fieldSize;
2212 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
Nirav Atre45e76d52018-06-04 11:49:14 -07002213 size_t lPad = Layout::getPad(innerStruct.size, fieldAlign);
Andreas Huber85eabdb2016-08-25 11:24:49 -07002214
Nirav Atre45e76d52018-06-04 11:49:14 -07002215 innerStruct.size = (mStyle == STYLE_STRUCT)
2216 ? (innerStruct.size + lPad + fieldSize)
2217 : std::max(innerStruct.size, fieldSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -07002218
Nirav Atre45e76d52018-06-04 11:49:14 -07002219 innerStruct.align = std::max(innerStruct.align, fieldAlign);
2220 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07002221
Nirav Atre12c597a2018-06-28 09:35:24 -07002222 // Pad the inner structure's size
Nirav Atre45e76d52018-06-04 11:49:14 -07002223 innerStruct.size += Layout::getPad(innerStruct.size,
2224 innerStruct.align);
2225
Nirav Atre12c597a2018-06-28 09:35:24 -07002226 // Compute its final offset
2227 innerStruct.offset += Layout::getPad(innerStruct.offset,
2228 innerStruct.align);
Nirav Atre45e76d52018-06-04 11:49:14 -07002229
Nirav Atre12c597a2018-06-28 09:35:24 -07002230 overall.size = innerStruct.offset + innerStruct.size;
Nirav Atre45e76d52018-06-04 11:49:14 -07002231
2232 // An empty struct/union still occupies a byte of space in C++.
2233 if (overall.size == 0) {
2234 overall.size = 1;
2235 }
2236
Nirav Atre12c597a2018-06-28 09:35:24 -07002237 // Pad the overall structure's size
Nirav Atre45e76d52018-06-04 11:49:14 -07002238 overall.align = std::max(innerStruct.align, discriminator.align);
2239 overall.size += Layout::getPad(overall.size, overall.align);
2240
2241 return compoundLayout;
2242}
2243
2244std::unique_ptr<ScalarType> CompoundType::getUnionDiscriminatorType() const {
2245 static const std::vector<std::pair<int, ScalarType::Kind> > scalars {
2246 {8, ScalarType::Kind::KIND_UINT8},
2247 {16, ScalarType::Kind::KIND_UINT16},
2248 {32, ScalarType::Kind::KIND_UINT32},
2249 };
2250
Steven Moreland967c2432018-10-10 12:50:43 -07002251 size_t numFields = mFields->size();
Nirav Atre45e76d52018-06-04 11:49:14 -07002252 auto kind = ScalarType::Kind::KIND_UINT64;
2253
2254 for (const auto& scalar : scalars) {
2255 if (numFields <= (1ULL << scalar.first)) {
2256 kind = scalar.second; break;
Andreas Huber85eabdb2016-08-25 11:24:49 -07002257 }
2258 }
2259
Yi Kong56758da2018-07-24 16:21:37 -07002260 return std::unique_ptr<ScalarType>(new ScalarType(kind, nullptr));
Nirav Atre45e76d52018-06-04 11:49:14 -07002261}
Andreas Huber85eabdb2016-08-25 11:24:49 -07002262
Nirav Atre45e76d52018-06-04 11:49:14 -07002263size_t CompoundType::Layout::getPad(size_t offset, size_t align) {
2264 size_t remainder = offset % align;
2265 return (remainder > 0) ? (align - remainder) : 0;
Andreas Huber70a59e12016-08-16 12:57:01 -07002266}
2267
Andreas Huberc9410c72016-07-28 12:18:40 -07002268} // namespace android
2269