blob: 400dc1f53df279ef981dfa15a0b7cfbbd12bd9c2 [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 Atre0ab82652018-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)
32 : Scope(localName, fullName, location, parent), mStyle(style), mFields(NULL) {}
Andreas Huberc9410c72016-07-28 12:18:40 -070033
Yifan Hong27e85db2016-11-09 15:45:52 -080034CompoundType::Style CompoundType::style() const {
35 return mStyle;
36}
37
Timur Iskhakovcec46c42017-08-09 00:22:02 -070038void CompoundType::setFields(std::vector<NamedReference<Type>*>* fields) {
Andreas Huberc9410c72016-07-28 12:18:40 -070039 mFields = fields;
Timur Iskhakovcec46c42017-08-09 00:22:02 -070040}
Andreas Huber5a545442016-08-03 10:44:56 -070041
Timur Iskhakovb58f4182017-08-29 15:19:24 -070042std::vector<const Reference<Type>*> CompoundType::getReferences() const {
43 std::vector<const Reference<Type>*> ret;
44 ret.insert(ret.begin(), mFields->begin(), mFields->end());
Timur Iskhakov33431e62017-08-21 17:31:23 -070045 return ret;
Timur Iskhakovcec46c42017-08-09 00:22:02 -070046}
47
48status_t CompoundType::validate() const {
49 for (const auto* field : *mFields) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070050 const Type& type = field->type();
Andreas Huber5a545442016-08-03 10:44:56 -070051
Howard Chenecfb4512017-11-21 18:28:53 +080052 if ((type.isVector() && static_cast<const VectorType*>(&type)->isVectorOfBinders())) {
Steven Morelandd927e5c2018-07-10 16:03:43 -070053 std::cerr << "ERROR: Struct/union cannot contain vectors of interfaces at "
Timur Iskhakovcec46c42017-08-09 00:22:02 -070054 << field->location() << "\n";
55 return UNKNOWN_ERROR;
Andreas Huberb95ea8a2016-08-15 15:35:42 -070056 }
57
Andreas Huber5a545442016-08-03 10:44:56 -070058 if (mStyle == STYLE_UNION) {
Steven Morelandd927e5c2018-07-10 16:03:43 -070059 if (type.isBinder()) {
60 std::cerr << "ERROR: Union cannot contain interfaces at " << field->location()
61 << "\n";
62 return UNKNOWN_ERROR;
63 }
64
Andreas Huber5a545442016-08-03 10:44:56 -070065 if (type.needsEmbeddedReadWrite()) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070066 std::cerr << "ERROR: Union must not contain any types that need fixup at "
67 << field->location() << "\n";
68 return UNKNOWN_ERROR;
Andreas Huber5a545442016-08-03 10:44:56 -070069 }
Andreas Huber5a545442016-08-03 10:44:56 -070070 }
71 }
72
Timur Iskhakovcec46c42017-08-09 00:22:02 -070073 status_t err = validateUniqueNames();
74 if (err != OK) return err;
75
Nirav Atre0ab82652018-06-04 11:49:14 -070076 err = validateSubTypeNames();
77 if (err != OK) return err;
78
Timur Iskhakovcec46c42017-08-09 00:22:02 -070079 return Scope::validate();
80}
81
82status_t CompoundType::validateUniqueNames() const {
83 std::unordered_set<std::string> names;
84
85 for (const auto* field : *mFields) {
86 if (names.find(field->name()) != names.end()) {
87 std::cerr << "ERROR: Redefinition of field '" << field->name() << "' at "
88 << field->location() << "\n";
89 return UNKNOWN_ERROR;
90 }
91 names.insert(field->name());
92 }
93
94 return OK;
Andreas Huberc9410c72016-07-28 12:18:40 -070095}
96
Nirav Atre0ab82652018-06-04 11:49:14 -070097void CompoundType::emitInvalidSubTypeNamesError(const std::string& subTypeName,
98 const Location& location) const {
99 std::cerr << "ERROR: Type name '" << subTypeName << "' defined at "
100 << location << " conflicts with a member function of "
101 << "safe_union " << localName() << ". Consider renaming or "
102 << "moving its definition outside the safe_union scope.\n";
103}
104
105status_t CompoundType::validateSubTypeNames() const {
106 if (mStyle != STYLE_SAFE_UNION) { return OK; }
107 const auto& subTypes = Scope::getSubTypes();
108
109 for (const auto& subType : subTypes) {
110 if (subType->localName() == "getDiscriminator") {
111 emitInvalidSubTypeNamesError(subType->localName(),
112 subType->location());
113 return UNKNOWN_ERROR;
114 }
115 }
116
117 return OK;
118}
119
Andreas Huberf630bc82016-09-09 14:52:25 -0700120bool CompoundType::isCompoundType() const {
121 return true;
122}
123
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700124bool CompoundType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
Yifan Hongc6752dc2016-12-20 14:00:14 -0800125 if (mStyle == STYLE_UNION) {
126 return false;
127 }
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700128 for (const auto* field : *mFields) {
129 if (!field->get()->canCheckEquality(visited)) {
Yifan Hongc6752dc2016-12-20 14:00:14 -0800130 return false;
131 }
132 }
133 return true;
134}
135
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700136std::string CompoundType::typeName() const {
137 switch (mStyle) {
138 case STYLE_STRUCT: {
139 return "struct " + localName();
140 }
141 case STYLE_UNION: {
142 return "union " + localName();
143 }
Nirav Atre0ab82652018-06-04 11:49:14 -0700144 case STYLE_SAFE_UNION: {
145 return "safe_union " + localName();
146 }
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700147 }
148 CHECK(!"Should not be here");
149}
150
Andreas Huber881227d2016-08-02 14:20:21 -0700151std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -0700152 StorageMode mode,
Steven Morelande30ee9b2017-05-09 13:31:01 -0700153 bool /* specifyNamespaces */) const {
154 const std::string base = fullName();
Andreas Huber881227d2016-08-02 14:20:21 -0700155
156 switch (mode) {
157 case StorageMode_Stack:
158 return base;
159
160 case StorageMode_Argument:
161 return "const " + base + "&";
162
163 case StorageMode_Result:
Howard Chenecfb4512017-11-21 18:28:53 +0800164 return base + (containsInterface()?"":"*");
Andreas Huber881227d2016-08-02 14:20:21 -0700165 }
Nirav Atre0ab82652018-06-04 11:49:14 -0700166 CHECK(!"Should not be here");
Andreas Huber881227d2016-08-02 14:20:21 -0700167}
168
Yifan Hong4ed13472016-11-02 10:44:11 -0700169std::string CompoundType::getJavaType(bool /* forInitializer */) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700170 return fullJavaName();
171}
172
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700173std::string CompoundType::getVtsType() const {
174 switch (mStyle) {
175 case STYLE_STRUCT:
176 {
177 return "TYPE_STRUCT";
178 }
179 case STYLE_UNION:
180 {
181 return "TYPE_UNION";
182 }
Nirav Atre0ab82652018-06-04 11:49:14 -0700183 case STYLE_SAFE_UNION:
184 {
185 return "TYPE_SAFE_UNION";
186 }
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700187 }
Steven Moreland0ecc7b82017-07-19 12:59:23 -0700188 CHECK(!"Should not be here");
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700189}
190
Howard Chenecfb4512017-11-21 18:28:53 +0800191bool CompoundType::containsInterface() const {
192 for (const auto& field : *mFields) {
193 if (field->type().isCompoundType()) {
194 const Type& t = field->type();
195 const CompoundType* ct = static_cast<const CompoundType*>(&t);
196 if (ct->containsInterface()) {
197 return true;
198 }
199 }
200 if (field->type().isInterface()) {
201 return true;
202 }
203 }
204 return false;
205}
206
Nirav Atreca7a5022018-06-29 20:43:49 -0700207void CompoundType::emitSafeUnionReaderWriterForInterfaces(
208 Formatter &out,
209 const std::string &name,
210 const std::string &parcelObj,
211 bool parcelObjIsPointer,
212 bool isReader,
213 ErrorMode mode) const {
214
215 CHECK(mStyle == STYLE_SAFE_UNION);
216 if (mFields->empty()) { return; }
217
218 out.block([&] {
219 const auto discriminatorType = getUnionDiscriminatorType();
220 if (isReader) {
221 out << discriminatorType->getCppStackType()
222 << " _hidl_d_primitive;\n";
223 } else {
224 out << "const "
225 << discriminatorType->getCppStackType()
226 << " _hidl_d_primitive = "
227 << discriminatorType->getCppTypeCast(name + ".getDiscriminator()")
228 << ";\n";
229 }
230
231 getUnionDiscriminatorType()->emitReaderWriter(out, "_hidl_d_primitive", parcelObj,
232 parcelObjIsPointer, isReader, mode);
233 out << "switch (("
234 << fullName()
235 << "::hidl_discriminator) _hidl_d_primitive) ";
236
237 out.block([&] {
238 for (const auto& field : *mFields) {
239 out << "case "
240 << fullName()
241 << "::hidl_discriminator::"
242 << field->name()
243 << ": ";
244
245 const std::string tempFieldName = "_hidl_temp_" + field->name();
246 out.block([&] {
247 if (isReader) {
248 out << field->type().getCppResultType()
249 << " "
250 << tempFieldName
251 << ";\n";
252
253 field->type().emitReaderWriter(out, tempFieldName, parcelObj,
254 parcelObjIsPointer, isReader, mode);
255
256 const std::string derefOperator = field->type().resultNeedsDeref()
257 ? "*" : "";
258 out << name
259 << "."
260 << field->name()
261 << "("
262 << derefOperator
263 << tempFieldName
264 << ");\n";
265 } else {
266 const std::string fieldValue = name + "." + field->name() + "()";
267 out << field->type().getCppArgumentType()
268 << " "
269 << tempFieldName
270 << " = "
271 << fieldValue
272 << ";\n";
273
274 field->type().emitReaderWriter(out, tempFieldName, parcelObj,
275 parcelObjIsPointer, isReader, mode);
276 }
277 out << "break;\n";
278 }).endl();
279 }
280
281 out << "case " << fullName() << "::hidl_discriminator::"
282 << "hidl_no_init: ";
283
284 out.block([&] {
285 out << "break;\n";
286 }).endl();
287
288 out << "default: ";
289 out.block([&] {
290 out << "details::logAlwaysFatal(\"Unknown union discriminator.\");\n";
291 }).endl();
292 }).endl();
293 }).endl();
294}
295
Andreas Huber881227d2016-08-02 14:20:21 -0700296void CompoundType::emitReaderWriter(
297 Formatter &out,
298 const std::string &name,
299 const std::string &parcelObj,
300 bool parcelObjIsPointer,
301 bool isReader,
302 ErrorMode mode) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700303
304 const std::string parcelObjDeref =
305 parcelObj + (parcelObjIsPointer ? "->" : ".");
306
Howard Chenecfb4512017-11-21 18:28:53 +0800307 if(containsInterface()){
Nirav Atreca7a5022018-06-29 20:43:49 -0700308 if (mStyle == STYLE_SAFE_UNION) {
309 emitSafeUnionReaderWriterForInterfaces(out, name, parcelObj,
310 parcelObjIsPointer,
311 isReader, mode);
312 return;
313 }
314
Howard Chenecfb4512017-11-21 18:28:53 +0800315 for (const auto& field : *mFields) {
Nirav Atre1d565622018-07-13 15:41:21 -0700316 const std::string tempFieldName = "_hidl_temp_" + field->name();
317 const std::string fieldValue = name + "." + field->name();
318
319 out.block([&] {
320 if (isReader) {
321 out << field->type().getCppResultType()
322 << " "
323 << tempFieldName
324 << ";\n";
325 } else {
326 out << field->type().getCppArgumentType()
327 << " "
328 << tempFieldName
329 << " = "
330 << fieldValue
331 << ";\n";
332 }
333
334 field->type().emitReaderWriter(out, tempFieldName, parcelObj,
335 parcelObjIsPointer, isReader, mode);
336 if (isReader) {
337 const std::string derefOperator = field->type().resultNeedsDeref()
338 ? "*" : "";
339 out << fieldValue
340 << " = std::move("
341 << derefOperator
342 << tempFieldName
343 << ");\n";
344 }
345 }).endl();
Howard Chenecfb4512017-11-21 18:28:53 +0800346 }
Andreas Huber881227d2016-08-02 14:20:21 -0700347 } else {
Howard Chenecfb4512017-11-21 18:28:53 +0800348 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700349
Howard Chenecfb4512017-11-21 18:28:53 +0800350 out << "size_t " << parentName << ";\n\n";
351
352 if (isReader) {
353 out << "_hidl_err = " << parcelObjDeref << "readBuffer("
354 << "sizeof(*" << name << "), &" << parentName << ", "
355 << " const_cast<const void**>(reinterpret_cast<void **>("
356 << "&" << name << ")));\n";
357 handleError(out, mode);
358 } else {
359 out << "_hidl_err = "
360 << parcelObjDeref
361 << "writeBuffer(&"
362 << name
363 << ", sizeof("
364 << name
365 << "), &"
366 << parentName
367 << ");\n";
368 handleError(out, mode);
369 }
Nirav Atre0ab82652018-06-04 11:49:14 -0700370
371 bool needEmbeddedReadWrite = needsEmbeddedReadWrite();
372 CHECK(mStyle != STYLE_UNION || !needEmbeddedReadWrite);
373
374 if (needEmbeddedReadWrite) {
Howard Chenecfb4512017-11-21 18:28:53 +0800375 emitReaderWriterEmbedded(out, 0 /* depth */, name, name, /* sanitizedName */
376 isReader /* nameIsPointer */, parcelObj, parcelObjIsPointer,
377 isReader, mode, parentName, "0 /* parentOffset */");
378 }
Andreas Huber881227d2016-08-02 14:20:21 -0700379 }
Andreas Huber881227d2016-08-02 14:20:21 -0700380}
381
382void CompoundType::emitReaderWriterEmbedded(
383 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700384 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700385 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700386 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700387 bool nameIsPointer,
388 const std::string &parcelObj,
389 bool parcelObjIsPointer,
390 bool isReader,
391 ErrorMode mode,
392 const std::string &parentName,
393 const std::string &offsetText) const {
394 emitReaderWriterEmbeddedForTypeName(
395 out,
396 name,
397 nameIsPointer,
398 parcelObj,
399 parcelObjIsPointer,
400 isReader,
401 mode,
402 parentName,
403 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700404 fullName(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800405 "" /* childName */,
406 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700407}
408
Andreas Huber85eabdb2016-08-25 11:24:49 -0700409void CompoundType::emitJavaReaderWriter(
410 Formatter &out,
411 const std::string &parcelObj,
412 const std::string &argName,
413 bool isReader) const {
414 if (isReader) {
415 out << "new " << fullJavaName() << "();\n";
416 }
417
418 out << argName
419 << "."
420 << (isReader ? "readFromParcel" : "writeToParcel")
421 << "("
422 << parcelObj
423 << ");\n";
424}
425
426void CompoundType::emitJavaFieldInitializer(
427 Formatter &out, const std::string &fieldName) const {
Nirav Atre1d565622018-07-13 15:41:21 -0700428 const std::string fieldDeclaration = fullJavaName() + " " + fieldName;
Nirav Atre66842a92018-06-28 18:14:13 -0700429 emitJavaFieldDefaultInitialValue(out, fieldDeclaration);
430}
431
432void CompoundType::emitJavaFieldDefaultInitialValue(
433 Formatter &out, const std::string &declaredFieldName) const {
434 out << declaredFieldName
Andreas Huber85eabdb2016-08-25 11:24:49 -0700435 << " = new "
436 << fullJavaName()
437 << "();\n";
438}
439
440void CompoundType::emitJavaFieldReaderWriter(
441 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700442 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700443 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700444 const std::string &blobName,
445 const std::string &fieldName,
446 const std::string &offset,
447 bool isReader) const {
448 if (isReader) {
Nirav Atre66842a92018-06-28 18:14:13 -0700449 out << "("
450 << getJavaTypeCast(fieldName)
451 << ").readEmbeddedFromParcel("
Andreas Huber709b62d2016-09-19 11:21:18 -0700452 << parcelName
453 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700454 << blobName
455 << ", "
456 << offset
457 << ");\n";
458
459 return;
460 }
461
462 out << fieldName
463 << ".writeEmbeddedToBlob("
464 << blobName
465 << ", "
466 << offset
467 << ");\n";
468}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700469void CompoundType::emitResolveReferences(
470 Formatter &out,
471 const std::string &name,
472 bool nameIsPointer,
473 const std::string &parcelObj,
474 bool parcelObjIsPointer,
475 bool isReader,
476 ErrorMode mode) const {
477 emitResolveReferencesEmbedded(
478 out,
479 0 /* depth */,
480 name,
481 name /* sanitizedName */,
482 nameIsPointer,
483 parcelObj,
484 parcelObjIsPointer,
485 isReader,
486 mode,
487 "_hidl_" + name + "_parent",
488 "0 /* parentOffset */");
489}
490
491void CompoundType::emitResolveReferencesEmbedded(
492 Formatter &out,
493 size_t /* depth */,
494 const std::string &name,
495 const std::string &/* sanitizedName */,
496 bool nameIsPointer,
497 const std::string &parcelObj,
498 bool parcelObjIsPointer,
499 bool isReader,
500 ErrorMode mode,
501 const std::string &parentName,
502 const std::string &offsetText) const {
503 CHECK(needsResolveReferences());
504
505 const std::string parcelObjDeref =
506 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
507
508 const std::string parcelObjPointer =
509 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
510
Yifan Hong244e82d2016-11-11 11:13:57 -0800511 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700512 const std::string namePointer = nameIsPointer ? name : ("&" + name);
513
514 out << "_hidl_err = ";
515
516 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800517 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700518 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800519 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700520 }
521
Yifan Hong33223ca2016-12-13 15:07:35 -0800522 out.indent(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800523 if (isReader) {
524 out << "const_cast<"
525 << fullName()
526 << " *"
527 << ">("
528 << namePointer
529 << "),\n"
530 << parcelObjDeref;
531 } else {
532 out << nameDerefed
533 << ",\n"
534 << parcelObjPointer;
535 }
536
537 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700538 << parentName
539 << ",\n"
540 << offsetText
541 << ");\n\n";
542 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700543
544 handleError(out, mode);
545}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700546
Nirav Atre0ab82652018-06-04 11:49:14 -0700547void CompoundType::emitLayoutAsserts(Formatter& out, const Layout& layout,
548 const std::string& layoutName) const {
549 out << "static_assert(sizeof("
550 << fullName()
551 << layoutName
552 << ") == "
553 << layout.size
554 << ", \"wrong size\");\n";
555
556 out << "static_assert(__alignof("
557 << fullName()
558 << layoutName
559 << ") == "
560 << layout.align
561 << ", \"wrong alignment\");\n";
562}
563
564void CompoundType::emitSafeUnionTypeDeclarations(Formatter& out) const {
565 out << "struct "
566 << localName()
567 << " final {\n";
568
569 out.indent();
570
571 Scope::emitTypeDeclarations(out);
572
Nirav Atre12c597a2018-06-28 09:35:24 -0700573 bool hasPointer = containsPointer();
574 CompoundLayout layout = hasPointer
575 ? CompoundLayout()
576 : getCompoundAlignmentAndSize();
577
Nirav Atre0ab82652018-06-04 11:49:14 -0700578 if (mFields->empty()) {
579 out.unindent();
580 out << "};\n\n";
581
582 emitLayoutAsserts(out, layout.overall, "");
583 out << "\n";
584 return;
585 }
586
587 out << "enum class hidl_discriminator : "
588 << getUnionDiscriminatorType()->getCppType(StorageMode_Stack, false)
589 << " ";
590
591 out.block([&] {
592 for (const auto& field : *mFields) {
593 out << field->name() << ",\n";
594 }
595 out << "hidl_no_init\n";
596 });
597 out << ";\n\n";
598
599 out << localName() << "();\n"
600 << "~" << localName() << "();\n"
601 << localName() << "(const " << localName() << "&);\n\n";
602
603 for (const auto& field : *mFields) {
604 out << "void "
605 << field->name()
606 << "("
607 << field->type().getCppArgumentType()
608 << ");\n";
609
610 out << field->type().getCppStackType()
611 << "& "
612 << field->name()
613 << "();\n";
614
615 out << field->type().getCppArgumentType()
616 << " "
617 << field->name()
618 << "() const;\n\n";
619 }
620
Nirav Atre12c597a2018-06-28 09:35:24 -0700621 out << "// Utility methods\n";
Nirav Atre0ab82652018-06-04 11:49:14 -0700622 out << "hidl_discriminator getDiscriminator() const;\n\n";
623
Nirav Atre12c597a2018-06-28 09:35:24 -0700624 out << "constexpr size_t hidl_getUnionOffset() const ";
625 out.block([&] {
626 out << "return offsetof(" << fullName() << ", hidl_u);\n";
627 }).endl().endl();
628
Nirav Atre0ab82652018-06-04 11:49:14 -0700629 out.unindent();
630 out << "private:\n";
631 out.indent();
632
633 out << "void hidl_destructUnion();\n\n";
Nirav Atre12c597a2018-06-28 09:35:24 -0700634
635 out << "hidl_discriminator hidl_d";
636 if (!hasPointer) {
637 out << " __attribute__ ((aligned("
638 << layout.discriminator.align << "))) ";
639 }
640 out << "{hidl_discriminator::hidl_no_init};\n";
Nirav Atre0ab82652018-06-04 11:49:14 -0700641 out << "union hidl_union final {\n";
642 out.indent();
643
Nirav Atre0ab82652018-06-04 11:49:14 -0700644 for (const auto& field : *mFields) {
645
646 size_t fieldAlign, fieldSize;
647 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
648
649 out << field->type().getCppStackType()
650 << " "
651 << field->name();
652
653 if (!hasPointer) {
654 out << " __attribute__ ((aligned("
655 << fieldAlign
656 << ")))";
657 }
658 out << ";\n";
659 }
660
661 out << "\n"
662 << "hidl_union();\n"
663 << "~hidl_union();\n";
664
665 out.unindent();
Nirav Atre12c597a2018-06-28 09:35:24 -0700666 out << "} hidl_u;\n";
Nirav Atre0ab82652018-06-04 11:49:14 -0700667
668 if (!hasPointer) {
669 out << "\n";
670
671 emitLayoutAsserts(out, layout.innerStruct, "::hidl_union");
672 emitLayoutAsserts(out, layout.discriminator, "::hidl_discriminator");
673 }
674
675 out.unindent();
676 out << "};\n\n";
677
678 if (!hasPointer) {
679 emitLayoutAsserts(out, layout.overall, "");
680 out << "\n";
681 }
682}
683
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800684void CompoundType::emitTypeDeclarations(Formatter& out) const {
Nirav Atre0ab82652018-06-04 11:49:14 -0700685 if (mStyle == STYLE_SAFE_UNION) {
686 emitSafeUnionTypeDeclarations(out);
687 return;
688 }
689
Andreas Huber881227d2016-08-02 14:20:21 -0700690 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
691 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700692 << localName()
Yifan Hongb1d2ebc2016-12-20 17:18:07 -0800693 << " final {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700694
695 out.indent();
696
697 Scope::emitTypeDeclarations(out);
698
Andreas Huber60d3b222017-03-30 09:10:56 -0700699 if (containsPointer()) {
Andreas Huberca4bc892017-01-09 14:58:12 -0800700 for (const auto &field : *mFields) {
Steven Moreland073269e2018-05-17 15:45:26 -0700701 field->emitDocComment(out);
Andreas Huberca4bc892017-01-09 14:58:12 -0800702 out << field->type().getCppStackType()
703 << " "
704 << field->name()
705 << ";\n";
706 }
707
708 out.unindent();
709 out << "};\n\n";
710
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800711 return;
Andreas Huber881227d2016-08-02 14:20:21 -0700712 }
713
Andreas Huberca4bc892017-01-09 14:58:12 -0800714 for (int pass = 0; pass < 2; ++pass) {
715 size_t offset = 0;
716 for (const auto &field : *mFields) {
717 size_t fieldAlign, fieldSize;
718 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
719
Nirav Atre0ab82652018-06-04 11:49:14 -0700720 offset += Layout::getPad(offset, fieldAlign);
Andreas Huberca4bc892017-01-09 14:58:12 -0800721
722 if (pass == 0) {
723 out << field->type().getCppStackType()
724 << " "
725 << field->name()
726 << " __attribute__ ((aligned("
727 << fieldAlign
728 << ")));\n";
729 } else {
730 out << "static_assert(offsetof("
731 << fullName()
732 << ", "
733 << field->name()
734 << ") == "
735 << offset
736 << ", \"wrong offset\");\n";
737 }
738
Andreas Huber60d3b222017-03-30 09:10:56 -0700739 if (mStyle == STYLE_STRUCT) {
740 offset += fieldSize;
741 }
Andreas Huberca4bc892017-01-09 14:58:12 -0800742 }
743
744 if (pass == 0) {
745 out.unindent();
746 out << "};\n\n";
747 }
748 }
749
Nirav Atre0ab82652018-06-04 11:49:14 -0700750 CompoundLayout layout = getCompoundAlignmentAndSize();
751 emitLayoutAsserts(out, layout.overall, "");
752 out << "\n";
Yifan Hong244e82d2016-11-11 11:13:57 -0800753}
754
Timur Iskhakovfd3f2502017-09-05 16:25:02 -0700755void CompoundType::emitTypeForwardDeclaration(Formatter& out) const {
Nirav Atre0ab82652018-06-04 11:49:14 -0700756 switch (mStyle) {
757 case STYLE_UNION: {
758 out << "union";
759 break;
760 }
761 case STYLE_STRUCT:
762 case STYLE_SAFE_UNION: {
763 out << "struct";
764 break;
765 }
766 default: {
767 CHECK(!"Should not be here");
768 }
769 }
770 out << " " << localName() << ";\n";
Timur Iskhakovfd3f2502017-09-05 16:25:02 -0700771}
Yifan Hong244e82d2016-11-11 11:13:57 -0800772
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800773void CompoundType::emitPackageTypeDeclarations(Formatter& out) const {
Steven Moreland4b8f7a12017-11-17 15:39:54 -0800774 Scope::emitPackageTypeDeclarations(out);
Yifan Hongc6752dc2016-12-20 14:00:14 -0800775
Steven Morelandbf714212017-10-27 18:29:01 -0700776 // TODO(b/65200821): remove these ifdefs
777 out << "#ifdef REALLY_IS_HIDL_INTERNAL_LIB" << gCurrentCompileName << "\n";
Steven Moreland3d98bc42017-06-23 21:36:41 +0000778 out << "std::string toString("
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800779 << getCppArgumentType()
Steven Moreland3d98bc42017-06-23 21:36:41 +0000780 << ");\n\n";
Yifan Hong42c68432017-03-13 16:22:03 -0700781 if (canCheckEquality()) {
Steven Morelandf91048a2017-06-23 21:38:35 +0000782 out << "bool operator==("
783 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
Yifan Hong42c68432017-03-13 16:22:03 -0700784
Steven Morelandf91048a2017-06-23 21:38:35 +0000785 out << "bool operator!=("
786 << getCppArgumentType() << ", " << getCppArgumentType() << ");\n\n";
Steven Morelandbf714212017-10-27 18:29:01 -0700787 }
788 out << "#else\n";
789 out << "static inline std::string toString("
790 << getCppArgumentType()
791 << (mFields->empty() ? "" : " o")
792 << ") ";
793
794 out.block([&] {
795 // include toString for scalar types
796 out << "using ::android::hardware::toString;\n"
797 << "std::string os;\n";
798 out << "os += \"{\";\n";
799
Nirav Atre0ab82652018-06-04 11:49:14 -0700800 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
801 out << "\nswitch (o.getDiscriminator()) {\n";
802 out.indent();
Steven Morelandbf714212017-10-27 18:29:01 -0700803 }
804
Nirav Atre0ab82652018-06-04 11:49:14 -0700805 for (const NamedReference<Type>* field : *mFields) {
806 if (mStyle == STYLE_SAFE_UNION) {
807 out << "case "
808 << fullName()
809 << "::hidl_discriminator::"
810 << field->name()
811 << ": ";
812
813 out.block([&] {
814 out << "os += \"."
815 << field->name()
816 << " = \";\n"
817 << "os += toString(o."
818 << field->name()
819 << "());\n"
820 << "break;\n";
821 }).endl();
822 } else {
823 out << "os += \"";
824 if (field != *(mFields->begin())) {
825 out << ", ";
826 }
827 out << "." << field->name() << " = \";\n";
828 field->type().emitDump(out, "os", "o." + field->name());
829 }
830 }
831
832 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
833 out << "case " << fullName() << "::hidl_discriminator::"
834 << "hidl_no_init: ";
835
836 out.block([&] {
837 out << "break;\n";
838 }).endl();
839
840 out << "default: ";
841 out.block([&] {
842 out << "details::logAlwaysFatal(\"Unknown union discriminator.\");\n";
843 }).endl();
844
845 out.unindent();
846 out << "}\n";
847 }
Steven Morelandbf714212017-10-27 18:29:01 -0700848 out << "os += \"}\"; return os;\n";
849 }).endl().endl();
850
851 if (canCheckEquality()) {
852 out << "static inline bool operator==("
853 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
854 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
855 out.block([&] {
Nirav Atre0ab82652018-06-04 11:49:14 -0700856 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
857 out.sIf("lhs.getDiscriminator() != rhs.getDiscriminator()", [&] {
Steven Morelandbf714212017-10-27 18:29:01 -0700858 out << "return false;\n";
859 }).endl();
Nirav Atre0ab82652018-06-04 11:49:14 -0700860
861 out << "switch (lhs.getDiscriminator()) {\n";
862 out.indent();
863 }
864
865 for (const auto& field : *mFields) {
866 if (mStyle == STYLE_SAFE_UNION) {
867 out << "case "
868 << fullName()
869 << "::hidl_discriminator::"
870 << field->name()
871 << ": ";
872
873 out.block([&] {
874 out << "return (lhs."
875 << field->name()
876 << "() == rhs."
877 << field->name()
878 << "());\n";
879 }).endl();
880 } else {
881 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
882 out << "return false;\n";
883 }).endl();
884 }
885 }
886
887 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
888 out << "case " << fullName() << "::hidl_discriminator::"
889 << "hidl_no_init: ";
890
891 out.block([&] {
892 out << "return false;\n";
893 }).endl();
894
895 out << "default: ";
896 out.block([&] {
897 out << "details::logAlwaysFatal(\"Unknown union discriminator.\");\n";
898 }).endl();
899
900 out.unindent();
901 out << "}\n";
Steven Morelandbf714212017-10-27 18:29:01 -0700902 }
903 out << "return true;\n";
904 }).endl().endl();
905
906 out << "static inline bool operator!=("
907 << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
908 out.block([&] {
909 out << "return !(lhs == rhs);\n";
910 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -0700911 } else {
Steven Morelandf91048a2017-06-23 21:38:35 +0000912 out << "// operator== and operator!= are not generated for " << localName() << "\n\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800913 }
Steven Morelandbf714212017-10-27 18:29:01 -0700914 out << "#endif // REALLY_IS_HIDL_INTERNAL_LIB\n";
Yifan Hongc6752dc2016-12-20 14:00:14 -0800915}
916
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800917void CompoundType::emitPackageHwDeclarations(Formatter& out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700918 if (needsEmbeddedReadWrite()) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800919 out << "::android::status_t readEmbeddedFromParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700920
Yifan Hong0a68a282016-10-21 16:32:34 -0700921 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700922
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700923 out << "const " << fullName() << " &obj,\n"
Yifan Hong244e82d2016-11-11 11:13:57 -0800924 << "const ::android::hardware::Parcel &parcel,\n"
925 << "size_t parentHandle,\n"
926 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700927
Yifan Hong0a68a282016-10-21 16:32:34 -0700928 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700929
930 out << "::android::status_t writeEmbeddedToParcel(\n";
931
Yifan Hong0a68a282016-10-21 16:32:34 -0700932 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700933
Yifan Hong244e82d2016-11-11 11:13:57 -0800934 out << "const " << fullName() << " &obj,\n"
935 << "::android::hardware::Parcel *parcel,\n"
936 << "size_t parentHandle,\n"
937 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700938
Yifan Hong0a68a282016-10-21 16:32:34 -0700939 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700940 }
941
Yifan Hongbf459bc2016-08-23 16:50:37 -0700942 if(needsResolveReferences()) {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700943 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700944 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800945 out << fullName() << " *obj,\n"
946 << "const ::android::hardware::Parcel &parcel,\n"
947 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700948 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700949 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700950 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800951 out << "const " << fullName() << " &obj,\n"
952 << "::android::hardware::Parcel *,\n"
953 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700954 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700955 }
Andreas Huber881227d2016-08-02 14:20:21 -0700956}
957
Nirav Atre0ab82652018-06-04 11:49:14 -0700958void emitSafeUnionGetterDefinition(const std::string& fieldName,
959 Formatter& out) {
960 out.block([&] {
961 out << "if (CC_UNLIKELY(hidl_d != hidl_discriminator::"
962 << fieldName
963 << ")) ";
964
965 out.block([&] {
966 out << "details::logAlwaysFatal(\"Bad safe_union access.\");\n";
967 }).endl().endl();
968
969 out << "return hidl_u."
970 << fieldName
971 << ";\n";
972 }).endl().endl();
973}
974
975void CompoundType::emitSafeUnionTypeConstructors(Formatter& out) const {
976
977 // Default constructor
978 out << fullName()
979 << "::"
980 << localName()
Nirav Atre12c597a2018-06-28 09:35:24 -0700981 << "() ";
982
983 out.block([&] {
984 out << "static_assert(offsetof("
985 << fullName()
986 << ", hidl_d) == 0, \"wrong offset\");\n";
987
988 if (!containsPointer()) {
989 CompoundLayout layout = getCompoundAlignmentAndSize();
990 out << "static_assert(offsetof("
991 << fullName()
992 << ", hidl_u) == "
993 << layout.innerStruct.offset
994 << ", \"wrong offset\");\n";
995 }
996 }).endl().endl();
Nirav Atre0ab82652018-06-04 11:49:14 -0700997
998 // Destructor
999 out << fullName()
1000 << "::~"
1001 << localName()
1002 << "() ";
1003
1004 out.block([&] {
1005 out << "hidl_destructUnion();\n";
1006 }).endl().endl();
1007
1008 // Copy constructor
1009 out << fullName()
1010 << "::"
1011 << localName()
1012 << "(const "
1013 << localName()
1014 << "& other) ";
1015
1016 out.block([&] {
Nirav Atre66842a92018-06-28 18:14:13 -07001017 out << "switch (other.hidl_d) ";
Nirav Atre0ab82652018-06-04 11:49:14 -07001018 out.block([&] {
1019
1020 for (const auto& field : *mFields) {
1021 out << "case hidl_discriminator::"
1022 << field->name()
1023 << ": ";
1024
1025 out.block([&] {
1026 out << "new (&hidl_u."
1027 << field->name()
1028 << ") "
1029 << field->type().getCppStackType()
1030 << "(other.hidl_u."
1031 << field->name()
1032 << ");\n"
1033 << "break;\n";
1034 }).endl();
1035 }
1036
1037 out << "case hidl_discriminator::hidl_no_init: { break; }\n";
1038 out << "default: { details::logAlwaysFatal("
1039 << "\"Unknown union discriminator.\"); }\n";
1040 }).endl().endl();
1041
1042 out << "hidl_d = other.hidl_d;\n";
1043 }).endl().endl();
1044}
1045
1046void CompoundType::emitSafeUnionTypeDefinitions(Formatter& out) const {
1047 if (mFields->empty()) { return; }
1048 emitSafeUnionTypeConstructors(out);
1049
1050 out << "void "
1051 << fullName()
1052 << "::hidl_destructUnion() ";
1053
1054 out.block([&] {
Nirav Atre66842a92018-06-28 18:14:13 -07001055 out << "switch (hidl_d) ";
Nirav Atre0ab82652018-06-04 11:49:14 -07001056 out.block([&] {
1057
1058 for (const auto& field : *mFields) {
1059 out << "case hidl_discriminator::"
1060 << field->name()
1061 << ": ";
1062
1063 out.block([&] {
Nirav Atre3b4c7ff2018-07-09 11:57:02 -07001064 out << "details::destructElement(&(hidl_u."
1065 << field->name()
1066 << "));\n"
1067 << "break;\n";
Nirav Atre0ab82652018-06-04 11:49:14 -07001068 }).endl();
1069 }
1070
1071 out << "case hidl_discriminator::hidl_no_init: { break; }\n";
1072 out << "default: { details::logAlwaysFatal("
1073 << "\"Unknown union discriminator.\"); }\n";
1074 }).endl().endl();
1075
1076 out << "hidl_d = hidl_discriminator::hidl_no_init;\n";
1077 }).endl().endl();
1078
Nirav Atre0ab82652018-06-04 11:49:14 -07001079 for (const NamedReference<Type>* field : *mFields) {
1080 // Setter
1081 out << "void "
1082 << fullName()
1083 << "::"
1084 << field->name()
1085 << "("
1086 << field->type().getCppArgumentType()
1087 << " o) ";
1088
1089 out.block([&] {
1090 out << "if (hidl_d != hidl_discriminator::"
1091 << field->name()
1092 << ") ";
1093
1094 out.block([&] {
1095 out << "hidl_destructUnion();\n"
1096 << "::std::memset(&hidl_u, 0, sizeof(hidl_u));\n\n";
1097
1098 out << "new (&hidl_u."
1099 << field->name()
1100 << ") "
1101 << field->type().getCppStackType()
1102 << "(o);\n";
1103
1104 out << "hidl_d = hidl_discriminator::"
1105 << field->name()
1106 << ";\n";
1107 }).endl();
1108
1109 out << "else if (&(hidl_u."
1110 << field->name()
1111 << ") != &o) ";
1112
1113 out.block([&] {
1114 out << "hidl_u."
1115 << field->name()
1116 << " = o;\n";
1117 }).endl();
1118 }).endl().endl();
1119
1120 // Getter (mutable)
1121 out << field->type().getCppStackType()
1122 << "& ("
1123 << fullName()
1124 << "::"
1125 << field->name()
1126 << ")() ";
1127
1128 emitSafeUnionGetterDefinition(field->name(), out);
1129
1130 // Getter (immutable)
1131 out << field->type().getCppArgumentType()
1132 << " ("
1133 << fullName()
1134 << "::"
1135 << field->name()
1136 << ")() const ";
1137
1138 emitSafeUnionGetterDefinition(field->name(), out);
1139 }
1140
1141 // Trivial constructor/destructor for internal union
1142 out << fullName() << "::hidl_union::hidl_union() {}\n\n"
1143 << fullName() << "::hidl_union::~hidl_union() {}\n\n";
1144
1145 // Utility method
Nirav Atreca7a5022018-06-29 20:43:49 -07001146 out << fullName() << "::hidl_discriminator ("
1147 << fullName() << "::getDiscriminator)() const ";
Nirav Atre0ab82652018-06-04 11:49:14 -07001148
1149 out.block([&] {
Nirav Atreca7a5022018-06-29 20:43:49 -07001150 out << "return hidl_d;\n";
Nirav Atre0ab82652018-06-04 11:49:14 -07001151 }).endl().endl();
1152}
1153
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001154void CompoundType::emitTypeDefinitions(Formatter& out, const std::string& prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -07001155 std::string space = prefix.empty() ? "" : (prefix + "::");
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001156 Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -07001157
Yifan Hongbf459bc2016-08-23 16:50:37 -07001158 if (needsEmbeddedReadWrite()) {
1159 emitStructReaderWriter(out, prefix, true /* isReader */);
1160 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -07001161 }
1162
Yifan Hongbf459bc2016-08-23 16:50:37 -07001163 if (needsResolveReferences()) {
1164 emitResolveReferenceDef(out, prefix, true /* isReader */);
1165 emitResolveReferenceDef(out, prefix, false /* isReader */);
1166 }
Andreas Huber881227d2016-08-02 14:20:21 -07001167
Steven Morelandbf714212017-10-27 18:29:01 -07001168 // TODO(b/65200821): remove toString + operator== from .cpp once all prebuilts are rebuilt
Nirav Atre0ab82652018-06-04 11:49:14 -07001169 // For safe unions (which have no legacy users), skip emitting these definitions to .cpp.
1170 if (mStyle == STYLE_SAFE_UNION) {
1171 emitSafeUnionTypeDefinitions(out);
1172 return;
1173 }
Steven Morelandbf714212017-10-27 18:29:01 -07001174
Steven Moreland3d98bc42017-06-23 21:36:41 +00001175 out << "std::string toString("
1176 << getCppArgumentType()
1177 << (mFields->empty() ? "" : " o")
1178 << ") ";
1179
1180 out.block([&] {
1181 // include toString for scalar types
1182 out << "using ::android::hardware::toString;\n"
1183 << "std::string os;\n";
1184 out << "os += \"{\";\n";
1185
Timur Iskhakov7fa79f62017-08-09 11:04:54 -07001186 for (const NamedReference<Type>* field : *mFields) {
Steven Moreland3d98bc42017-06-23 21:36:41 +00001187 out << "os += \"";
1188 if (field != *(mFields->begin())) {
1189 out << ", ";
1190 }
1191 out << "." << field->name() << " = \";\n";
1192 field->type().emitDump(out, "os", "o." + field->name());
1193 }
1194
1195 out << "os += \"}\"; return os;\n";
1196 }).endl().endl();
1197
Steven Morelandf91048a2017-06-23 21:38:35 +00001198 if (canCheckEquality()) {
1199 out << "bool operator==("
1200 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
1201 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
1202 out.block([&] {
1203 for (const auto &field : *mFields) {
1204 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
1205 out << "return false;\n";
1206 }).endl();
1207 }
1208 out << "return true;\n";
1209 }).endl().endl();
1210
1211 out << "bool operator!=("
1212 << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
1213 out.block([&] {
1214 out << "return !(lhs == rhs);\n";
1215 }).endl().endl();
1216 } else {
1217 out << "// operator== and operator!= are not generated for " << localName() << "\n";
1218 }
Andreas Huber881227d2016-08-02 14:20:21 -07001219}
1220
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001221void CompoundType::emitJavaTypeDeclarations(Formatter& out, bool atTopLevel) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -07001222 out << "public final ";
1223
1224 if (!atTopLevel) {
1225 out << "static ";
1226 }
1227
1228 out << "class "
1229 << localName()
1230 << " {\n";
1231
1232 out.indent();
1233
1234 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
1235
Nirav Atre66842a92018-06-28 18:14:13 -07001236 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1237 const std::string discriminatorStorageType = (
1238 getUnionDiscriminatorType()->getJavaType(false));
Steven Moreland073269e2018-05-17 15:45:26 -07001239
Nirav Atre66842a92018-06-28 18:14:13 -07001240 out << "public static final class hidl_discriminator ";
1241 out.block([&] {
1242 std::vector<std::string> enumNames;
1243 for (const auto& field : *mFields) {
1244 enumNames.push_back(field->name());
1245 }
1246 enumNames.push_back("hidl_no_init");
Andreas Huber85eabdb2016-08-25 11:24:49 -07001247
Nirav Atre66842a92018-06-28 18:14:13 -07001248 for (size_t idx = 0; idx < enumNames.size(); idx++) {
1249 out << "public static final "
1250 << discriminatorStorageType
1251 << " "
1252 << enumNames[idx]
1253 << " = "
1254 << idx
1255 << ";\n";
1256 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001257
Nirav Atre66842a92018-06-28 18:14:13 -07001258 out << "\n"
1259 << "public static final String getName("
1260 << discriminatorStorageType
1261 << " value) ";
1262
1263 out.block([&] {
1264 out << "switch (value) ";
1265 out.block([&] {
1266 for (size_t idx = 0; idx < enumNames.size(); idx++) {
1267 out << "case "
1268 << idx
1269 << ": { return \""
1270 << enumNames[idx]
1271 << "\"; }\n";
1272 }
1273 out << "default: { return \"Unknown\"; }\n";
1274 }).endl();
1275 }).endl().endl();
1276
1277 out << "private hidl_discriminator() {}\n";
1278 }).endl().endl();
1279
1280 out << "private "
1281 << discriminatorStorageType
1282 << " hidl_d = hidl_discriminator.hidl_no_init;\n";
1283
1284 out << "private Object hidl_o;\n\n";
1285
1286 for (const auto& field : *mFields) {
1287 // Setter
1288 out << "public void "
1289 << field->name()
1290 << "("
1291 << field->type().getJavaType(false)
1292 << " "
1293 << field->name()
1294 << ") ";
1295
1296 out.block([&] {
1297 out << "hidl_d = hidl_discriminator."
1298 << field->name()
1299 << ";\n";
1300
1301 out << "hidl_o = "
1302 << field->name()
1303 << ";\n";
1304 }).endl().endl();
1305
1306 // Getter
1307 out << "public "
1308 << field->type().getJavaType(false)
1309 << " "
1310 << field->name()
1311 << "() ";
1312
1313 out.block([&] {
1314 out << "if (hidl_d != hidl_discriminator."
1315 << field->name()
1316 << ") ";
1317
1318 out.block([&] {
1319 out << "String className = (hidl_o != null) ? "
1320 << "hidl_o.getClass().getName() : \"null\";\n";
1321
1322 out << "throw new IllegalStateException(\n";
1323 out.indent(2, [&] {
1324 out << "\"Read access to inactive union components is disallowed. \" +\n"
1325 << "\"Discriminator value is \" + hidl_d + \" (corresponding \" +\n"
1326 << "\"to \" + hidl_discriminator.getName(hidl_d) + \"), and \" +\n"
1327 << "\"hidl_o is of type \" + className + \".\");\n";
1328 });
1329 }).endl();
1330
1331 out << "if (hidl_o != null && !"
1332 << field->type().getJavaTypeClass()
1333 << ".class.isInstance(hidl_o)) ";
1334
1335 out.block([&] {
1336 out << "throw new Error(\"Union is in a corrupted state.\");\n";
1337 }).endl();
1338
1339 out << "return ("
1340 << field->type().getJavaTypeCast("hidl_o")
1341 << ");\n";
1342 }).endl().endl();
1343 }
1344
1345 out << "// Utility method\n"
1346 << "public "
1347 << discriminatorStorageType
1348 << " getDiscriminator() { return hidl_d; }\n\n";
1349
1350 } else if (!mFields->empty()) {
1351 for (const auto& field : *mFields) {
1352 field->emitDocComment(out);
1353
1354 out << "public ";
1355 field->type().emitJavaFieldInitializer(out, field->name());
1356 }
1357
Andreas Huber85eabdb2016-08-25 11:24:49 -07001358 out << "\n";
1359 }
1360
Yifan Hongec102272016-12-20 18:10:07 -08001361 ////////////////////////////////////////////////////////////////////////////
1362
1363 if (canCheckEquality()) {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001364 out << "@Override\npublic final boolean equals(Object otherObject) ";
Yifan Hongec102272016-12-20 18:10:07 -08001365 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001366 out.sIf("this == otherObject", [&] {
1367 out << "return true;\n";
1368 }).endl();
1369 out.sIf("otherObject == null", [&] {
1370 out << "return false;\n";
1371 }).endl();
Yifan Hong45b331b2017-03-27 12:59:54 -07001372 // Though class is final, we use getClass instead of instanceof to be explicit.
1373 out.sIf("otherObject.getClass() != " + fullJavaName() + ".class", [&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001374 out << "return false;\n";
1375 }).endl();
1376 out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001377
1378 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1379 out.sIf("this.hidl_d != other.hidl_d", [&] {
Yifan Hongec102272016-12-20 18:10:07 -08001380 out << "return false;\n";
1381 }).endl();
Nirav Atre66842a92018-06-28 18:14:13 -07001382 out.sIf("this.hidl_d == hidl_discriminator.hidl_no_init", [&] {
1383 out << "return false;\n";
1384 }).endl();
1385 out.sIf("!android.os.HidlSupport.deepEquals(this.hidl_o, other.hidl_o)", [&] {
1386 out << "return false;\n";
1387 }).endl();
1388 } else if (!mFields->empty()) {
1389 for (const auto &field : *mFields) {
1390 std::string condition = (field->type().isScalar() || field->type().isEnum())
1391 ? "this." + field->name() + " != other." + field->name()
1392 : ("!android.os.HidlSupport.deepEquals(this." + field->name()
1393 + ", other." + field->name() + ")");
1394 out.sIf(condition, [&] {
1395 out << "return false;\n";
1396 }).endl();
1397 }
Yifan Hongec102272016-12-20 18:10:07 -08001398 }
1399 out << "return true;\n";
1400 }).endl().endl();
1401
Yifan Hong7d1839f2017-02-22 13:24:29 -08001402 out << "@Override\npublic final int hashCode() ";
Yifan Hongec102272016-12-20 18:10:07 -08001403 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -08001404 out << "return java.util.Objects.hash(\n";
1405 out.indent(2, [&] {
Nirav Atre66842a92018-06-28 18:14:13 -07001406 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1407 out << "android.os.HidlSupport.deepHashCode(this.hidl_o),\n"
1408 << "java.util.Objects.hashCode(this.hidl_d)";
1409 } else {
1410 out.join(mFields->begin(), mFields->end(), ", \n", [&] (const auto &field) {
1411 out << "android.os.HidlSupport.deepHashCode(this." << field->name() << ")";
1412 });
1413 }
Yifan Hong7d1839f2017-02-22 13:24:29 -08001414 });
Yifan Hongec102272016-12-20 18:10:07 -08001415 out << ");\n";
1416 }).endl().endl();
Yifan Hong42c68432017-03-13 16:22:03 -07001417 } else {
1418 out << "// equals() is not generated for " << localName() << "\n";
Yifan Hongec102272016-12-20 18:10:07 -08001419 }
1420
1421 ////////////////////////////////////////////////////////////////////////////
1422
Yifan Honge45b5302017-02-22 10:49:07 -08001423 out << "@Override\npublic final String toString() ";
1424 out.block([&] {
1425 out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n"
1426 << "builder.append(\"{\");\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001427
1428 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1429 out << "switch (this.hidl_d) {\n";
1430 out.indent();
Yifan Honge45b5302017-02-22 10:49:07 -08001431 }
Nirav Atre66842a92018-06-28 18:14:13 -07001432
1433 for (const auto &field : *mFields) {
1434 if (mStyle == STYLE_SAFE_UNION) {
1435 out << "case hidl_discriminator."
1436 << field->name()
1437 << ": ";
1438
1439 out.block([&] {
1440 out << "builder.append(\""
1441 << "."
1442 << field->name()
1443 << " = \");\n";
1444
1445 field->type().emitJavaDump(out, "builder", "this." + field->name() + "()");
1446 out << "break;\n";
1447 }).endl();
1448 }
1449 else {
1450 out << "builder.append(\"";
1451 if (field != *(mFields->begin())) {
1452 out << ", ";
1453 }
1454 out << "." << field->name() << " = \");\n";
1455 field->type().emitJavaDump(out, "builder", "this." + field->name());
1456 }
1457 }
1458
1459 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1460 out << "case hidl_discriminator.hidl_no_init: { break; }\n"
1461 << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
1462
1463 out.unindent();
1464 out << "}\n";
1465 }
1466
Yifan Honge45b5302017-02-22 10:49:07 -08001467 out << "builder.append(\"}\");\nreturn builder.toString();\n";
1468 }).endl().endl();
1469
Nirav Atre66842a92018-06-28 18:14:13 -07001470 CompoundLayout layout = getCompoundAlignmentAndSize();
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001471
Yifan Honge45b5302017-02-22 10:49:07 -08001472 ////////////////////////////////////////////////////////////////////////////
1473
Yifan Hong1af73532016-11-09 14:32:58 -08001474 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001475 out.indent();
Howard Chenaf084db2017-12-27 18:46:39 +08001476 if (containsInterface()) {
Nirav Atre66842a92018-06-28 18:14:13 -07001477
1478 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1479 out << "hidl_d = ";
1480 getUnionDiscriminatorType()->emitJavaReaderWriter(
1481 out, "parcel", "hidl_d", true);
1482
1483 out << "switch (hidl_d) {\n";
1484 out.indent();
1485 }
1486
Howard Chenaf084db2017-12-27 18:46:39 +08001487 for (const auto& field : *mFields) {
Nirav Atre66842a92018-06-28 18:14:13 -07001488 if (mStyle == STYLE_SAFE_UNION) {
1489 out << "case hidl_discriminator."
1490 << field->name()
1491 << ": ";
1492
1493 out.block([&] {
1494 out << "hidl_o = ";
1495 field->type().emitJavaReaderWriter(out, "parcel", "hidl_o", true);
1496
1497 out << "break;\n";
1498 }).endl();
1499 } else {
1500 out << field->name() << " = ";
1501 field->type().emitJavaReaderWriter(out, "parcel", field->name(), true);
1502 }
1503 }
1504
1505 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1506 out << "case hidl_discriminator.hidl_no_init: { break; }\n"
1507 << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
1508
1509 out.unindent();
1510 out << "}\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001511 }
1512 } else {
1513 out << "android.os.HwBlob blob = parcel.readBuffer(";
Nirav Atre66842a92018-06-28 18:14:13 -07001514 out << layout.overall.size << " /* size */);\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001515 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
1516 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001517 out.unindent();
1518 out << "}\n\n";
1519
Andreas Huberf630bc82016-09-09 14:52:25 -07001520 ////////////////////////////////////////////////////////////////////////////
1521
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001522 size_t vecAlign, vecSize;
1523 VectorType::getAlignmentAndSizeStatic(&vecAlign, &vecSize);
1524
Howard Chenaf084db2017-12-27 18:46:39 +08001525 out << "public static final java.util.ArrayList<" << localName()
Yifan Hong1af73532016-11-09 14:32:58 -08001526 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001527 out.indent();
1528
Howard Chenaf084db2017-12-27 18:46:39 +08001529 out << "java.util.ArrayList<" << localName() << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001530
Howard Chenaf084db2017-12-27 18:46:39 +08001531 if (containsInterface()) {
1532 out << "int size = parcel.readInt32();\n";
1533 out << "for(int i = 0 ; i < size; i ++) {\n";
1534 out.indent();
1535 out << fullJavaName() << " tmp = ";
1536 emitJavaReaderWriter(out, "parcel", "tmp", true);
1537 out << "_hidl_vec.add(tmp);\n";
1538 out.unindent();
1539 out << "}\n";
1540 } else {
1541 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer(";
1542 out << vecSize << " /* sizeof hidl_vec<T> */);\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001543
Howard Chenaf084db2017-12-27 18:46:39 +08001544 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel",
1545 "_hidl_blob", "_hidl_vec", "0",
1546 true /* isReader */);
Andreas Huber85eabdb2016-08-25 11:24:49 -07001547 }
Howard Chenaf084db2017-12-27 18:46:39 +08001548 out << "\nreturn _hidl_vec;\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001549 out.unindent();
1550 out << "}\n\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001551 ////////////////////////////////////////////////////////////////////////////
1552 if (containsInterface()) {
1553 out << "// readEmbeddedFromParcel is not generated()\n";
1554 } else {
1555 out << "public final void readEmbeddedFromParcel(\n";
1556 out.indent(2);
1557 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
1558 out.unindent();
Nirav Atre66842a92018-06-28 18:14:13 -07001559
1560 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1561 getUnionDiscriminatorType()->emitJavaFieldReaderWriter(
1562 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d",
1563 "_hidl_offset + " + std::to_string(layout.discriminator.offset),
1564 true /* isReader */);
1565
1566 out << "switch (this.hidl_d) {\n";
1567 out.indent();
1568 }
1569
1570 size_t offset = layout.innerStruct.offset;
Howard Chenaf084db2017-12-27 18:46:39 +08001571 for (const auto& field : *mFields) {
Howard Chenaf084db2017-12-27 18:46:39 +08001572
Nirav Atre66842a92018-06-28 18:14:13 -07001573 if (mStyle == STYLE_SAFE_UNION) {
1574 out << "case hidl_discriminator."
1575 << field->name()
1576 << ": ";
Howard Chenaf084db2017-12-27 18:46:39 +08001577
Nirav Atre66842a92018-06-28 18:14:13 -07001578 out.block([&] {
1579 field->type().emitJavaFieldDefaultInitialValue(out, "hidl_o");
1580 field->type().emitJavaFieldReaderWriter(
1581 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_o",
1582 "_hidl_offset + " + std::to_string(offset), true /* isReader */);
1583
1584 out << "break;\n";
1585 }).endl();
1586 } else {
1587 size_t fieldAlign, fieldSize;
1588 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1589
1590 offset += Layout::getPad(offset, fieldAlign);
1591 field->type().emitJavaFieldReaderWriter(
1592 out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
1593 "_hidl_offset + " + std::to_string(offset), true /* isReader */);
1594 offset += fieldSize;
1595 }
1596 }
1597
1598 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1599 out << "case hidl_discriminator.hidl_no_init: { break; }\n"
1600 << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
1601
1602 out.unindent();
1603 out << "}\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001604 }
1605 out.unindent();
1606 out << "}\n\n";
1607 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001608
Andreas Huberf630bc82016-09-09 14:52:25 -07001609 ////////////////////////////////////////////////////////////////////////////
1610
Yifan Hong1af73532016-11-09 14:32:58 -08001611 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001612 out.indent();
1613
Howard Chenaf084db2017-12-27 18:46:39 +08001614 if (containsInterface()) {
Nirav Atre66842a92018-06-28 18:14:13 -07001615 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1616 getUnionDiscriminatorType()->emitJavaReaderWriter(
1617 out, "parcel", "hidl_d", false);
1618
1619 out << "switch (this.hidl_d) {\n";
1620 out.indent();
1621 }
1622
Howard Chenaf084db2017-12-27 18:46:39 +08001623 for (const auto& field : *mFields) {
Nirav Atre66842a92018-06-28 18:14:13 -07001624 if (mStyle == STYLE_SAFE_UNION) {
1625 out << "case hidl_discriminator."
1626 << field->name()
1627 << ": ";
1628
1629 out.block([&] {
1630 field->type().emitJavaReaderWriter(out, "parcel", field->name() + "()", false);
1631 out << "break;\n";
1632 }).endl();
1633 } else {
1634 field->type().emitJavaReaderWriter(out, "parcel", field->name(), false);
1635 }
1636 }
1637
1638 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1639 out << "case hidl_discriminator.hidl_no_init: { break; }\n"
1640 << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
1641
1642 out.unindent();
1643 out << "}\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001644 }
1645 } else {
Nirav Atre66842a92018-06-28 18:14:13 -07001646 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
1647 << layout.overall.size
Howard Chenaf084db2017-12-27 18:46:39 +08001648 << " /* size */);\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001649
Howard Chenaf084db2017-12-27 18:46:39 +08001650 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
1651 << "parcel.writeBuffer(_hidl_blob);\n";
1652 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07001653 out.unindent();
1654 out << "}\n\n";
1655
Andreas Huberf630bc82016-09-09 14:52:25 -07001656 ////////////////////////////////////////////////////////////////////////////
1657
Andreas Huberf630bc82016-09-09 14:52:25 -07001658 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001659 out.indent(2);
Howard Chenaf084db2017-12-27 18:46:39 +08001660 out << "android.os.HwParcel parcel, java.util.ArrayList<" << localName() << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001661 out.unindent();
1662
Howard Chenaf084db2017-12-27 18:46:39 +08001663 if (containsInterface()) {
1664 out << "parcel.writeInt32(_hidl_vec.size());\n";
Nirav Atre66842a92018-06-28 18:14:13 -07001665 out << "for(" << fullJavaName() << " tmp: _hidl_vec) ";
1666 out.block([&] {
1667 emitJavaReaderWriter(out, "parcel", "tmp", false);
1668 }).endl();
Howard Chenaf084db2017-12-27 18:46:39 +08001669 } else {
1670 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(" << vecSize
1671 << " /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001672
Howard Chenaf084db2017-12-27 18:46:39 +08001673 VectorType::EmitJavaFieldReaderWriterForElementType(out, 0 /* depth */, this, "parcel",
1674 "_hidl_blob", "_hidl_vec", "0",
1675 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -07001676
Howard Chenaf084db2017-12-27 18:46:39 +08001677 out << "\nparcel.writeBuffer(_hidl_blob);\n";
1678 }
Andreas Huberf630bc82016-09-09 14:52:25 -07001679 out.unindent();
1680 out << "}\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -07001681 ////////////////////////////////////////////////////////////////////////////
1682
Howard Chenaf084db2017-12-27 18:46:39 +08001683 if (containsInterface()) {
Nirav Atre66842a92018-06-28 18:14:13 -07001684 out << "// writeEmbeddedToBlob() is not generated\n";
Howard Chenaf084db2017-12-27 18:46:39 +08001685 } else {
1686 out << "public final void writeEmbeddedToBlob(\n";
1687 out.indent(2);
1688 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
1689 out.unindent();
Nirav Atre0ab82652018-06-04 11:49:14 -07001690
Nirav Atre66842a92018-06-28 18:14:13 -07001691 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1692 getUnionDiscriminatorType()->emitJavaFieldReaderWriter(
1693 out, 0 /* depth */, "parcel", "_hidl_blob", "hidl_d",
1694 "_hidl_offset + " + std::to_string(layout.discriminator.offset),
1695 false /* isReader */);
Nirav Atre0ab82652018-06-04 11:49:14 -07001696
Nirav Atre66842a92018-06-28 18:14:13 -07001697 out << "switch (this.hidl_d) {\n";
1698 out.indent();
Andreas Huber85eabdb2016-08-25 11:24:49 -07001699 }
1700
Nirav Atre66842a92018-06-28 18:14:13 -07001701 size_t offset = layout.innerStruct.offset;
1702 for (const auto& field : *mFields) {
1703 if (mStyle == STYLE_SAFE_UNION) {
1704 out << "case hidl_discriminator."
1705 << field->name()
1706 << ": ";
1707
1708 out.block([&] {
1709 field->type().emitJavaFieldReaderWriter(
1710 out, 0 /* depth */, "parcel", "_hidl_blob", field->name() + "()",
1711 "_hidl_offset + " + std::to_string(offset), false /* isReader */);
1712
1713 out << "break;\n";
1714 }).endl();
1715 } else {
1716 size_t fieldAlign, fieldSize;
1717 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1718
1719 offset += Layout::getPad(offset, fieldAlign);
1720 field->type().emitJavaFieldReaderWriter(
1721 out, 0 /* depth */, "parcel", "_hidl_blob", field->name(),
1722 "_hidl_offset + " + std::to_string(offset), false /* isReader */);
1723 offset += fieldSize;
1724 }
1725 }
1726
1727 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1728 out << "case hidl_discriminator.hidl_no_init: { break; }\n"
1729 << "default: { throw new Error(\"Unknown union discriminator.\"); }\n";
1730
1731 out.unindent();
1732 out << "}\n";
1733 }
Howard Chenaf084db2017-12-27 18:46:39 +08001734 out.unindent();
1735 out << "}\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001736 }
1737
1738 out.unindent();
Andreas Huber85eabdb2016-08-25 11:24:49 -07001739 out << "};\n\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -07001740}
1741
Andreas Huber881227d2016-08-02 14:20:21 -07001742void CompoundType::emitStructReaderWriter(
1743 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -08001744
1745 std::string space = prefix.empty() ? "" : (prefix + "::");
1746
Andreas Huber881227d2016-08-02 14:20:21 -07001747 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -08001748 << (isReader ? "readEmbeddedFromParcel"
1749 : "writeEmbeddedToParcel")
1750 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001751
Yifan Hong0a68a282016-10-21 16:32:34 -07001752 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -07001753
Yifan Hong244e82d2016-11-11 11:13:57 -08001754 bool useName = false;
1755 for (const auto &field : *mFields) {
1756 if (field->type().useNameInEmitReaderWriterEmbedded(isReader)) {
1757 useName = true;
1758 break;
1759 }
1760 }
1761 std::string name = useName ? "obj" : "/* obj */";
1762 // if not useName, then obj should not be used at all,
1763 // then the #error should not be emitted.
1764 std::string error = useName ? "" : "\n#error\n";
1765
Andreas Huber881227d2016-08-02 14:20:21 -07001766 if (isReader) {
Martijn Coenenb2a861c2017-04-18 15:54:25 -07001767 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001768 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001769 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -08001770 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -07001771 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001772 }
1773
1774 out << "size_t parentHandle,\n"
1775 << "size_t parentOffset)";
1776
Andreas Huber881227d2016-08-02 14:20:21 -07001777 out << " {\n";
1778
Yifan Hong0a68a282016-10-21 16:32:34 -07001779 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -07001780 out.indent();
1781
Iliyan Malchev549e2592016-08-10 08:59:12 -07001782 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001783
Nirav Atre0ab82652018-06-04 11:49:14 -07001784 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1785 out << "switch (" << name << ".getDiscriminator()) {\n";
1786 out.indent();
1787 }
1788
Andreas Huber881227d2016-08-02 14:20:21 -07001789 for (const auto &field : *mFields) {
1790 if (!field->type().needsEmbeddedReadWrite()) {
1791 continue;
1792 }
1793
Nirav Atre0ab82652018-06-04 11:49:14 -07001794 if (mStyle == STYLE_SAFE_UNION) {
1795 out << "case " << fullName() << "::hidl_discriminator::"
1796 << field->name() << ": {\n";
1797 out.indent();
1798 }
1799
1800 const std::string fieldName = (mStyle == STYLE_SAFE_UNION)
1801 ? (name + "." + field->name() + "()" + error)
1802 : (name + "." + field->name() + error);
1803
1804 const std::string fieldOffset = (mStyle == STYLE_SAFE_UNION)
Nirav Atre12c597a2018-06-28 09:35:24 -07001805 ? (name + ".hidl_getUnionOffset() " +
1806 "/* safe_union: union offset into struct */")
Nirav Atre0ab82652018-06-04 11:49:14 -07001807 : ("offsetof(" + fullName() + ", " + field->name() + ")");
1808
Andreas Huber881227d2016-08-02 14:20:21 -07001809 field->type().emitReaderWriterEmbedded(
1810 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -07001811 0 /* depth */,
Nirav Atre0ab82652018-06-04 11:49:14 -07001812 fieldName,
Yifan Hongbe2a3732016-10-05 13:33:41 -07001813 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -07001814 false /* nameIsPointer */,
1815 "parcel",
1816 !isReader /* parcelObjIsPointer */,
1817 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -07001818 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -07001819 "parentHandle",
Nirav Atre0ab82652018-06-04 11:49:14 -07001820 "parentOffset + " + fieldOffset);
1821
1822 if (mStyle == STYLE_SAFE_UNION) {
1823 out << "break;\n";
1824 out.unindent();
1825 out << "}\n";
1826 }
1827 }
1828
1829 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
1830 out << "default: { break; }\n";
1831 out.unindent();
1832 out << "}\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001833 }
1834
Iliyan Malchev549e2592016-08-10 08:59:12 -07001835 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -07001836
1837 out.unindent();
1838 out << "}\n\n";
1839}
1840
Chih-Hung Hsieh8c90cc52017-08-03 14:51:13 -07001841void CompoundType::emitResolveReferenceDef(Formatter& out, const std::string& prefix,
1842 bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -08001843 out << "::android::status_t ";
1844 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -07001845
1846 bool useParent = false;
1847 for (const auto &field : *mFields) {
1848 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
1849 useParent = true;
1850 break;
1851 }
1852 }
1853
1854 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
1855 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
1856
Yifan Hongbf459bc2016-08-23 16:50:37 -07001857 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -08001858 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001859 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -08001860 out << space + localName() + " *obj,\n"
1861 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -07001862 << "size_t " << parentHandleName << ", "
1863 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001864 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001865 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -08001866 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001867 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -08001868 out << "const " << space + localName() + " &obj,\n"
1869 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -07001870 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -08001871 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -07001872 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001873 }
1874
1875 out << " {\n";
1876
1877 out.indent();
1878
1879 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
1880
Yifan Hong244e82d2016-11-11 11:13:57 -08001881 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -07001882 // if not useParent, then parentName and offsetText
1883 // should not be used at all, then the #error should not be emitted.
1884 std::string error = useParent ? "" : "\n#error\n";
1885
Nirav Atre0ab82652018-06-04 11:49:14 -07001886 if (mStyle == STYLE_SAFE_UNION) {
1887 out << "switch (" << nameDeref << "getDiscriminator()) {\n";
1888 out.indent();
1889 }
1890
Yifan Hongbf459bc2016-08-23 16:50:37 -07001891 for (const auto &field : *mFields) {
1892 if (!field->type().needsResolveReferences()) {
1893 continue;
1894 }
1895
Nirav Atre0ab82652018-06-04 11:49:14 -07001896 if (mStyle == STYLE_SAFE_UNION) {
1897 out << "case " << fullName() << "::hidl_discriminator::"
1898 << field->name() << ": {\n";
1899 out.indent();
1900 }
1901
1902 const std::string fieldName = (mStyle == STYLE_SAFE_UNION)
1903 ? (nameDeref + field->name() + "()")
1904 : (nameDeref + field->name());
1905
1906 const std::string fieldOffset = (mStyle == STYLE_SAFE_UNION)
Nirav Atre12c597a2018-06-28 09:35:24 -07001907 ? (nameDeref + "hidl_getUnionOffset() " +
1908 "/* safe_union: union offset into struct */")
Nirav Atre0ab82652018-06-04 11:49:14 -07001909 : ("offsetof(" + fullName() + ", " + field->name() + ")");
1910
Yifan Hongbf459bc2016-08-23 16:50:37 -07001911 field->type().emitResolveReferencesEmbedded(
1912 out,
1913 0 /* depth */,
Nirav Atre0ab82652018-06-04 11:49:14 -07001914 fieldName,
Yifan Hongbf459bc2016-08-23 16:50:37 -07001915 field->name() /* sanitizedName */,
1916 false, // nameIsPointer
1917 "parcel", // const std::string &parcelObj,
1918 !isReader, // bool parcelObjIsPointer,
1919 isReader, // bool isReader,
1920 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -07001921 parentHandleName + error,
1922 parentOffsetName
Nirav Atre0ab82652018-06-04 11:49:14 -07001923 + " + "
1924 + fieldOffset
Yifan Hong00f47172016-09-30 14:40:45 -07001925 + error);
Nirav Atre0ab82652018-06-04 11:49:14 -07001926
1927 if (mStyle == STYLE_SAFE_UNION) {
1928 out << "break;\n";
1929 out.unindent();
1930 out << "}\n";
1931 }
1932 }
1933
1934 if (mStyle == STYLE_SAFE_UNION) {
1935 out << "default: { _hidl_err = ::android::BAD_VALUE; break; }\n";
1936 out.unindent();
1937 out << "}\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -07001938 }
1939
Yifan Hongbf459bc2016-08-23 16:50:37 -07001940 out << "return _hidl_err;\n";
1941
1942 out.unindent();
1943 out << "}\n\n";
1944}
1945
Andreas Huber881227d2016-08-02 14:20:21 -07001946bool CompoundType::needsEmbeddedReadWrite() const {
Nirav Atre0ab82652018-06-04 11:49:14 -07001947 if (mStyle == STYLE_UNION) {
Andreas Huber881227d2016-08-02 14:20:21 -07001948 return false;
1949 }
1950
1951 for (const auto &field : *mFields) {
1952 if (field->type().needsEmbeddedReadWrite()) {
1953 return true;
1954 }
1955 }
1956
1957 return false;
1958}
1959
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001960bool CompoundType::deepNeedsResolveReferences(std::unordered_set<const Type*>* visited) const {
Nirav Atre0ab82652018-06-04 11:49:14 -07001961 if (mStyle == STYLE_UNION) {
Yifan Hongbf459bc2016-08-23 16:50:37 -07001962 return false;
1963 }
1964
1965 for (const auto &field : *mFields) {
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001966 if (field->type().needsResolveReferences(visited)) {
Yifan Hongbf459bc2016-08-23 16:50:37 -07001967 return true;
1968 }
1969 }
1970
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07001971 return Scope::deepNeedsResolveReferences(visited);
Yifan Hongbf459bc2016-08-23 16:50:37 -07001972}
1973
Andreas Huber881227d2016-08-02 14:20:21 -07001974bool CompoundType::resultNeedsDeref() const {
Howard Chenecfb4512017-11-21 18:28:53 +08001975 return !containsInterface() ;
Andreas Huber881227d2016-08-02 14:20:21 -07001976}
1977
Steven Moreland6ec9eb92018-02-16 14:21:49 -08001978void CompoundType::emitVtsTypeDeclarations(Formatter& out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07001979 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001980 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001981
1982 // Emit declaration for each subtype.
1983 for (const auto &type : getSubTypes()) {
1984 switch (mStyle) {
1985 case STYLE_STRUCT:
1986 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001987 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001988 break;
1989 }
1990 case STYLE_UNION:
1991 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001992 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001993 break;
1994 }
Nirav Atre0ab82652018-06-04 11:49:14 -07001995 case STYLE_SAFE_UNION:
1996 {
1997 out << "sub_safe_union: {\n";
1998 break;
1999 }
2000 default:
2001 {
2002 CHECK(!"Should not be here");
2003 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002004 }
2005 out.indent();
Steven Moreland6ec9eb92018-02-16 14:21:49 -08002006 type->emitVtsTypeDeclarations(out);
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002007 out.unindent();
2008 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07002009 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002010
2011 // Emit declaration for each field.
2012 for (const auto &field : *mFields) {
2013 switch (mStyle) {
2014 case STYLE_STRUCT:
2015 {
2016 out << "struct_value: {\n";
2017 break;
2018 }
2019 case STYLE_UNION:
2020 {
2021 out << "union_value: {\n";
2022 break;
2023 }
Nirav Atre0ab82652018-06-04 11:49:14 -07002024 case STYLE_SAFE_UNION:
2025 {
2026 out << "safe_union_value: {\n";
2027 break;
2028 }
2029 default:
2030 {
2031 CHECK(!"Should not be here");
2032 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002033 }
2034 out.indent();
2035 out << "name: \"" << field->name() << "\"\n";
Steven Moreland6ec9eb92018-02-16 14:21:49 -08002036 field->type().emitVtsAttributeType(out);
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07002037 out.unindent();
2038 out << "}\n";
2039 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07002040}
2041
Steven Moreland6ec9eb92018-02-16 14:21:49 -08002042void CompoundType::emitVtsAttributeType(Formatter& out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07002043 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07002044 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07002045}
2046
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002047bool CompoundType::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
Nirav Atre66842a92018-06-28 18:14:13 -07002048 if (mStyle == STYLE_UNION) {
Andreas Huber0fa9e392016-08-31 09:05:44 -07002049 return false;
2050 }
2051
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002052 for (const auto* field : *mFields) {
2053 if (!field->get()->isJavaCompatible(visited)) {
Andreas Huber0fa9e392016-08-31 09:05:44 -07002054 return false;
2055 }
2056 }
2057
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002058 return Scope::deepIsJavaCompatible(visited);
Andreas Huber85eabdb2016-08-25 11:24:49 -07002059}
2060
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002061bool CompoundType::deepContainsPointer(std::unordered_set<const Type*>* visited) const {
2062 for (const auto* field : *mFields) {
2063 if (field->get()->containsPointer(visited)) {
Andreas Huber60d3b222017-03-30 09:10:56 -07002064 return true;
2065 }
2066 }
2067
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -07002068 return Scope::deepContainsPointer(visited);
Andreas Huber60d3b222017-03-30 09:10:56 -07002069}
2070
Andreas Huber85eabdb2016-08-25 11:24:49 -07002071void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
Nirav Atre0ab82652018-06-04 11:49:14 -07002072 CompoundLayout layout = getCompoundAlignmentAndSize();
2073 *align = layout.overall.align;
2074 *size = layout.overall.size;
2075}
Andreas Huber85eabdb2016-08-25 11:24:49 -07002076
Nirav Atre0ab82652018-06-04 11:49:14 -07002077CompoundType::CompoundLayout CompoundType::getCompoundAlignmentAndSize() const {
2078 CompoundLayout compoundLayout;
2079
2080 // Local aliases for convenience
2081 Layout& overall = compoundLayout.overall;
2082 Layout& innerStruct = compoundLayout.innerStruct;
2083 Layout& discriminator = compoundLayout.discriminator;
2084
Nirav Atre12c597a2018-06-28 09:35:24 -07002085 if (mStyle == STYLE_SAFE_UNION && !mFields->empty()) {
2086 getUnionDiscriminatorType()->getAlignmentAndSize(
2087 &(discriminator.align), &(discriminator.size));
2088
2089 innerStruct.offset = discriminator.size;
2090 }
2091
Andreas Huber85eabdb2016-08-25 11:24:49 -07002092 for (const auto &field : *mFields) {
Nirav Atre0ab82652018-06-04 11:49:14 -07002093
Andreas Huber85eabdb2016-08-25 11:24:49 -07002094 // Each field is aligned according to its alignment requirement.
2095 // The surrounding structure's alignment is the maximum of its
2096 // fields' aligments.
Andreas Huber85eabdb2016-08-25 11:24:49 -07002097 size_t fieldAlign, fieldSize;
2098 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
Nirav Atre0ab82652018-06-04 11:49:14 -07002099 size_t lPad = Layout::getPad(innerStruct.size, fieldAlign);
Andreas Huber85eabdb2016-08-25 11:24:49 -07002100
Nirav Atre0ab82652018-06-04 11:49:14 -07002101 innerStruct.size = (mStyle == STYLE_STRUCT)
2102 ? (innerStruct.size + lPad + fieldSize)
2103 : std::max(innerStruct.size, fieldSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -07002104
Nirav Atre0ab82652018-06-04 11:49:14 -07002105 innerStruct.align = std::max(innerStruct.align, fieldAlign);
2106 }
Andreas Huber85eabdb2016-08-25 11:24:49 -07002107
Nirav Atre12c597a2018-06-28 09:35:24 -07002108 // Pad the inner structure's size
Nirav Atre0ab82652018-06-04 11:49:14 -07002109 innerStruct.size += Layout::getPad(innerStruct.size,
2110 innerStruct.align);
2111
Nirav Atre12c597a2018-06-28 09:35:24 -07002112 // Compute its final offset
2113 innerStruct.offset += Layout::getPad(innerStruct.offset,
2114 innerStruct.align);
Nirav Atre0ab82652018-06-04 11:49:14 -07002115
Nirav Atre12c597a2018-06-28 09:35:24 -07002116 overall.size = innerStruct.offset + innerStruct.size;
Nirav Atre0ab82652018-06-04 11:49:14 -07002117
2118 // An empty struct/union still occupies a byte of space in C++.
2119 if (overall.size == 0) {
2120 overall.size = 1;
2121 }
2122
Nirav Atre12c597a2018-06-28 09:35:24 -07002123 // Pad the overall structure's size
Nirav Atre0ab82652018-06-04 11:49:14 -07002124 overall.align = std::max(innerStruct.align, discriminator.align);
2125 overall.size += Layout::getPad(overall.size, overall.align);
2126
2127 return compoundLayout;
2128}
2129
2130std::unique_ptr<ScalarType> CompoundType::getUnionDiscriminatorType() const {
2131 static const std::vector<std::pair<int, ScalarType::Kind> > scalars {
2132 {8, ScalarType::Kind::KIND_UINT8},
2133 {16, ScalarType::Kind::KIND_UINT16},
2134 {32, ScalarType::Kind::KIND_UINT32},
2135 };
2136
2137 size_t numFields = mFields->size() + 1; // +1 for no_init
2138 auto kind = ScalarType::Kind::KIND_UINT64;
2139
2140 for (const auto& scalar : scalars) {
2141 if (numFields <= (1ULL << scalar.first)) {
2142 kind = scalar.second; break;
Andreas Huber85eabdb2016-08-25 11:24:49 -07002143 }
2144 }
2145
Nirav Atre0ab82652018-06-04 11:49:14 -07002146 return std::unique_ptr<ScalarType>(new ScalarType(kind, NULL));
2147}
Andreas Huber85eabdb2016-08-25 11:24:49 -07002148
Nirav Atre0ab82652018-06-04 11:49:14 -07002149size_t CompoundType::Layout::getPad(size_t offset, size_t align) {
2150 size_t remainder = offset % align;
2151 return (remainder > 0) ? (align - remainder) : 0;
Andreas Huber70a59e12016-08-16 12:57:01 -07002152}
2153
Andreas Huberc9410c72016-07-28 12:18:40 -07002154} // namespace android
2155