blob: dcd426ae25f51b1d57ee21ce3e702784d7cbe43f [file] [log] [blame]
Andreas Huber1aec3972016-08-26 09:26:32 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Andreas Huberc9410c72016-07-28 12:18:40 -070017#include "CompoundType.h"
18
Yifan Hongec102272016-12-20 18:10:07 -080019#include "ArrayType.h"
Andreas Huberf630bc82016-09-09 14:52:25 -070020#include "VectorType.h"
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070021#include <hidl-util/Formatter.h>
Andreas Huber5a545442016-08-03 10:44:56 -070022#include <android-base/logging.h>
23
Andreas Huberc9410c72016-07-28 12:18:40 -070024namespace android {
25
Yifan Honga4b53d02016-10-31 17:29:10 -070026CompoundType::CompoundType(Style style, const char *localName, const Location &location)
27 : Scope(localName, location),
Andreas Huber9ed827c2016-08-22 12:31:13 -070028 mStyle(style),
Andreas Huberc9410c72016-07-28 12:18:40 -070029 mFields(NULL) {
30}
31
Yifan Hong27e85db2016-11-09 15:45:52 -080032CompoundType::Style CompoundType::style() const {
33 return mStyle;
34}
35
Andreas Huber0d0f9a22016-08-17 10:26:11 -070036bool CompoundType::setFields(
37 std::vector<CompoundField *> *fields, std::string *errorMsg) {
Andreas Huberc9410c72016-07-28 12:18:40 -070038 mFields = fields;
Andreas Huber5a545442016-08-03 10:44:56 -070039
40 for (const auto &field : *fields) {
41 const Type &type = field->type();
42
Andreas Huber86a112b2016-10-19 14:25:16 -070043 if (type.isBinder()
44 || (type.isVector()
45 && static_cast<const VectorType *>(
46 &type)->isVectorOfBinders())) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -070047 *errorMsg =
48 "Structs/Unions must not contain references to interfaces.";
Andreas Huberb95ea8a2016-08-15 15:35:42 -070049
50 return false;
51 }
52
Andreas Huber5a545442016-08-03 10:44:56 -070053 if (mStyle == STYLE_UNION) {
54 if (type.needsEmbeddedReadWrite()) {
55 // Can't have those in a union.
56
Andreas Huber0d0f9a22016-08-17 10:26:11 -070057 *errorMsg =
58 "Unions must not contain any types that need fixup.";
Andreas Huber5a545442016-08-03 10:44:56 -070059
60 return false;
61 }
Andreas Huber5a545442016-08-03 10:44:56 -070062 }
63 }
64
65 return true;
Andreas Huberc9410c72016-07-28 12:18:40 -070066}
67
Andreas Huberf630bc82016-09-09 14:52:25 -070068bool CompoundType::isCompoundType() const {
69 return true;
70}
71
Yifan Hongc6752dc2016-12-20 14:00:14 -080072bool CompoundType::canCheckEquality() const {
73 if (mStyle == STYLE_UNION) {
74 return false;
75 }
76 for (const auto &field : *mFields) {
77 if (!field->type().canCheckEquality()) {
78 return false;
79 }
80 }
81 return true;
82}
83
84
Andreas Huber881227d2016-08-02 14:20:21 -070085std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -070086 StorageMode mode,
Steven Moreland979e0992016-09-07 09:18:08 -070087 bool specifyNamespaces) const {
Steven Moreland979e0992016-09-07 09:18:08 -070088 const std::string base =
89 specifyNamespaces ? fullName() : partialCppName();
Andreas Huber881227d2016-08-02 14:20:21 -070090
91 switch (mode) {
92 case StorageMode_Stack:
93 return base;
94
95 case StorageMode_Argument:
96 return "const " + base + "&";
97
98 case StorageMode_Result:
99 return "const " + base + "*";
100 }
101}
102
Yifan Hong4ed13472016-11-02 10:44:11 -0700103std::string CompoundType::getJavaType(bool /* forInitializer */) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700104 return fullJavaName();
105}
106
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700107std::string CompoundType::getVtsType() const {
108 switch (mStyle) {
109 case STYLE_STRUCT:
110 {
111 return "TYPE_STRUCT";
112 }
113 case STYLE_UNION:
114 {
115 return "TYPE_UNION";
116 }
117 }
118}
119
Andreas Huber881227d2016-08-02 14:20:21 -0700120void CompoundType::emitReaderWriter(
121 Formatter &out,
122 const std::string &name,
123 const std::string &parcelObj,
124 bool parcelObjIsPointer,
125 bool isReader,
126 ErrorMode mode) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700127 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700128
129 out << "size_t " << parentName << ";\n\n";
130
131 const std::string parcelObjDeref =
132 parcelObj + (parcelObjIsPointer ? "->" : ".");
133
134 if (isReader) {
Martijn Coenen6a082c62017-01-11 12:47:02 +0100135 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700136 << parcelObjDeref
137 << "readBuffer("
138 << "&"
139 << parentName
Martijn Coenen6a082c62017-01-11 12:47:02 +0100140 << ", "
141 << " reinterpret_cast<const void **>("
142 << "&" << name
143 << "));\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700144
Martijn Coenen6a082c62017-01-11 12:47:02 +0100145 handleError(out, mode);
Andreas Huber881227d2016-08-02 14:20:21 -0700146 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700147 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700148 << parcelObjDeref
149 << "writeBuffer(&"
150 << name
151 << ", sizeof("
152 << name
153 << "), &"
154 << parentName
155 << ");\n";
156
157 handleError(out, mode);
158 }
159
160 if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
161 return;
162 }
163
164 emitReaderWriterEmbedded(
165 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700166 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700167 name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700168 name, /* sanitizedName */
Andreas Huber881227d2016-08-02 14:20:21 -0700169 isReader /* nameIsPointer */,
170 parcelObj,
171 parcelObjIsPointer,
172 isReader,
173 mode,
174 parentName,
175 "0 /* parentOffset */");
176}
177
178void CompoundType::emitReaderWriterEmbedded(
179 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700180 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700181 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700182 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700183 bool nameIsPointer,
184 const std::string &parcelObj,
185 bool parcelObjIsPointer,
186 bool isReader,
187 ErrorMode mode,
188 const std::string &parentName,
189 const std::string &offsetText) const {
190 emitReaderWriterEmbeddedForTypeName(
191 out,
192 name,
193 nameIsPointer,
194 parcelObj,
195 parcelObjIsPointer,
196 isReader,
197 mode,
198 parentName,
199 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700200 fullName(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800201 "" /* childName */,
202 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700203}
204
Andreas Huber85eabdb2016-08-25 11:24:49 -0700205void CompoundType::emitJavaReaderWriter(
206 Formatter &out,
207 const std::string &parcelObj,
208 const std::string &argName,
209 bool isReader) const {
210 if (isReader) {
211 out << "new " << fullJavaName() << "();\n";
212 }
213
214 out << argName
215 << "."
216 << (isReader ? "readFromParcel" : "writeToParcel")
217 << "("
218 << parcelObj
219 << ");\n";
220}
221
222void CompoundType::emitJavaFieldInitializer(
223 Formatter &out, const std::string &fieldName) const {
224 out << "final "
225 << fullJavaName()
226 << " "
227 << fieldName
228 << " = new "
229 << fullJavaName()
230 << "();\n";
231}
232
233void CompoundType::emitJavaFieldReaderWriter(
234 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700235 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700236 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700237 const std::string &blobName,
238 const std::string &fieldName,
239 const std::string &offset,
240 bool isReader) const {
241 if (isReader) {
242 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700243 << ".readEmbeddedFromParcel("
244 << parcelName
245 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700246 << blobName
247 << ", "
248 << offset
249 << ");\n";
250
251 return;
252 }
253
254 out << fieldName
255 << ".writeEmbeddedToBlob("
256 << blobName
257 << ", "
258 << offset
259 << ");\n";
260}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700261void CompoundType::emitResolveReferences(
262 Formatter &out,
263 const std::string &name,
264 bool nameIsPointer,
265 const std::string &parcelObj,
266 bool parcelObjIsPointer,
267 bool isReader,
268 ErrorMode mode) const {
269 emitResolveReferencesEmbedded(
270 out,
271 0 /* depth */,
272 name,
273 name /* sanitizedName */,
274 nameIsPointer,
275 parcelObj,
276 parcelObjIsPointer,
277 isReader,
278 mode,
279 "_hidl_" + name + "_parent",
280 "0 /* parentOffset */");
281}
282
283void CompoundType::emitResolveReferencesEmbedded(
284 Formatter &out,
285 size_t /* depth */,
286 const std::string &name,
287 const std::string &/* sanitizedName */,
288 bool nameIsPointer,
289 const std::string &parcelObj,
290 bool parcelObjIsPointer,
291 bool isReader,
292 ErrorMode mode,
293 const std::string &parentName,
294 const std::string &offsetText) const {
295 CHECK(needsResolveReferences());
296
297 const std::string parcelObjDeref =
298 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
299
300 const std::string parcelObjPointer =
301 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
302
Yifan Hong244e82d2016-11-11 11:13:57 -0800303 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700304 const std::string namePointer = nameIsPointer ? name : ("&" + name);
305
306 out << "_hidl_err = ";
307
308 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800309 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700310 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800311 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700312 }
313
Yifan Hong33223ca2016-12-13 15:07:35 -0800314 out.indent(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800315 if (isReader) {
316 out << "const_cast<"
317 << fullName()
318 << " *"
319 << ">("
320 << namePointer
321 << "),\n"
322 << parcelObjDeref;
323 } else {
324 out << nameDerefed
325 << ",\n"
326 << parcelObjPointer;
327 }
328
329 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700330 << parentName
331 << ",\n"
332 << offsetText
333 << ");\n\n";
334 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700335
336 handleError(out, mode);
337}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700338
Andreas Huber881227d2016-08-02 14:20:21 -0700339status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
340 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
341 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700342 << localName()
Yifan Hongb1d2ebc2016-12-20 17:18:07 -0800343 << " final {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700344
345 out.indent();
346
347 Scope::emitTypeDeclarations(out);
348
Andreas Huberca4bc892017-01-09 14:58:12 -0800349 if (!isJavaCompatible()) {
350 for (const auto &field : *mFields) {
351 out << field->type().getCppStackType()
352 << " "
353 << field->name()
354 << ";\n";
355 }
356
357 out.unindent();
358 out << "};\n\n";
359
360 return OK;
Andreas Huber881227d2016-08-02 14:20:21 -0700361 }
362
Andreas Huberca4bc892017-01-09 14:58:12 -0800363 for (int pass = 0; pass < 2; ++pass) {
364 size_t offset = 0;
365 for (const auto &field : *mFields) {
366 size_t fieldAlign, fieldSize;
367 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
368
369 size_t pad = offset % fieldAlign;
370 if (pad > 0) {
371 offset += fieldAlign - pad;
372 }
373
374 if (pass == 0) {
375 out << field->type().getCppStackType()
376 << " "
377 << field->name()
378 << " __attribute__ ((aligned("
379 << fieldAlign
380 << ")));\n";
381 } else {
382 out << "static_assert(offsetof("
383 << fullName()
384 << ", "
385 << field->name()
386 << ") == "
387 << offset
388 << ", \"wrong offset\");\n";
389 }
390
391 offset += fieldSize;
392 }
393
394 if (pass == 0) {
395 out.unindent();
396 out << "};\n\n";
397 }
398 }
399
400 size_t structAlign, structSize;
401 getAlignmentAndSize(&structAlign, &structSize);
402
403 out << "static_assert(sizeof("
404 << fullName()
405 << ") == "
406 << structSize
407 << ", \"wrong size\");\n";
408
409 out << "static_assert(__alignof("
410 << fullName()
411 << ") == "
412 << structAlign
413 << ", \"wrong alignment\");\n\n";
Yifan Hong244e82d2016-11-11 11:13:57 -0800414
415 return OK;
416}
417
418
Yifan Hongc6752dc2016-12-20 14:00:14 -0800419status_t CompoundType::emitGlobalTypeDeclarations(Formatter &out) const {
420 Scope::emitGlobalTypeDeclarations(out);
421
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800422 out << "std::string toString("
423 << getCppArgumentType()
424 << ");\n";
425
Yifan Hongc6752dc2016-12-20 14:00:14 -0800426 if (!canCheckEquality()) {
427 return OK;
428 }
429
430 out << "inline bool operator==("
431 << getCppArgumentType() << " " << (mFields->empty() ? "/* lhs */" : "lhs") << ", "
432 << getCppArgumentType() << " " << (mFields->empty() ? "/* rhs */" : "rhs") << ") ";
433 out.block([&] {
434 for (const auto &field : *mFields) {
435 out.sIf("lhs." + field->name() + " != rhs." + field->name(), [&] {
436 out << "return false;\n";
437 }).endl();
438 }
439 out << "return true;\n";
440 }).endl().endl();
441
442 out << "inline bool operator!=("
443 << getCppArgumentType() << " lhs," << getCppArgumentType() << " rhs)";
444 out.block([&] {
445 out << "return !(lhs == rhs);\n";
446 }).endl().endl();
447
448 return OK;
449}
450
Yifan Hong244e82d2016-11-11 11:13:57 -0800451status_t CompoundType::emitGlobalHwDeclarations(Formatter &out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700452 if (needsEmbeddedReadWrite()) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800453 out << "::android::status_t readEmbeddedFromParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700454
Yifan Hong0a68a282016-10-21 16:32:34 -0700455 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700456
Yifan Hong244e82d2016-11-11 11:13:57 -0800457 out << fullName() << " *obj,\n"
458 << "const ::android::hardware::Parcel &parcel,\n"
459 << "size_t parentHandle,\n"
460 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700461
Yifan Hong0a68a282016-10-21 16:32:34 -0700462 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700463
464 out << "::android::status_t writeEmbeddedToParcel(\n";
465
Yifan Hong0a68a282016-10-21 16:32:34 -0700466 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700467
Yifan Hong244e82d2016-11-11 11:13:57 -0800468 out << "const " << fullName() << " &obj,\n"
469 << "::android::hardware::Parcel *parcel,\n"
470 << "size_t parentHandle,\n"
471 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700472
Yifan Hong0a68a282016-10-21 16:32:34 -0700473 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700474 }
475
Yifan Hongbf459bc2016-08-23 16:50:37 -0700476 if(needsResolveReferences()) {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700477 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700478 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800479 out << fullName() << " *obj,\n"
480 << "const ::android::hardware::Parcel &parcel,\n"
481 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700482 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700483 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700484 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800485 out << "const " << fullName() << " &obj,\n"
486 << "::android::hardware::Parcel *,\n"
487 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700488 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700489 }
490
Andreas Huber881227d2016-08-02 14:20:21 -0700491 return OK;
492}
493
494status_t CompoundType::emitTypeDefinitions(
495 Formatter &out, const std::string prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -0700496 std::string space = prefix.empty() ? "" : (prefix + "::");
497 status_t err = Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700498
499 if (err != OK) {
500 return err;
501 }
502
Yifan Hongbf459bc2016-08-23 16:50:37 -0700503 if (needsEmbeddedReadWrite()) {
504 emitStructReaderWriter(out, prefix, true /* isReader */);
505 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -0700506 }
507
Yifan Hongbf459bc2016-08-23 16:50:37 -0700508 if (needsResolveReferences()) {
509 emitResolveReferenceDef(out, prefix, true /* isReader */);
510 emitResolveReferenceDef(out, prefix, false /* isReader */);
511 }
Andreas Huber881227d2016-08-02 14:20:21 -0700512
Yifan Hongf5cc2f72017-01-04 18:02:34 -0800513 out << "std::string toString("
514 << getCppArgumentType()
515 << (mFields->empty() ? "" : " o")
516 << ") ";
517
518 out.block([&] {
519 // include toString for scalar types
520 out << "using ::android::hardware::details::toString;\n"
521 << "std::string os;\n";
522 out << "os += \"{\";\n";
523
524 for (const CompoundField *field : *mFields) {
525 out << "os += \"";
526 if (field != *(mFields->begin())) {
527 out << ", ";
528 }
529 out << "." << field->name() << " = \";\n";
530 field->type().emitDump(out, "os", "o." + field->name());
531 }
532
533 out << "os += \"}\"; return os;\n";
534 }).endl().endl();
535
Andreas Huber881227d2016-08-02 14:20:21 -0700536 return OK;
537}
538
Andreas Huber85eabdb2016-08-25 11:24:49 -0700539status_t CompoundType::emitJavaTypeDeclarations(
540 Formatter &out, bool atTopLevel) const {
541 out << "public final ";
542
543 if (!atTopLevel) {
544 out << "static ";
545 }
546
547 out << "class "
548 << localName()
549 << " {\n";
550
551 out.indent();
552
553 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
554
555 for (const auto &field : *mFields) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700556 out << "public ";
557
558 field->type().emitJavaFieldInitializer(out, field->name());
559 }
560
561 if (!mFields->empty()) {
562 out << "\n";
563 }
564
Yifan Hongec102272016-12-20 18:10:07 -0800565 ////////////////////////////////////////////////////////////////////////////
566
567 if (canCheckEquality()) {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800568 out << "@Override\npublic final boolean equals(Object otherObject) ";
Yifan Hongec102272016-12-20 18:10:07 -0800569 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800570 out.sIf("this == otherObject", [&] {
571 out << "return true;\n";
572 }).endl();
573 out.sIf("otherObject == null", [&] {
574 out << "return false;\n";
575 }).endl();
576 // Class is final, so we only need to check instanceof, not getClass
577 out.sIf("!(otherObject instanceof " + fullJavaName() + ")", [&] {
578 out << "return false;\n";
579 }).endl();
580 out << fullJavaName() << " other = (" << fullJavaName() << ")otherObject;\n";
Yifan Hongec102272016-12-20 18:10:07 -0800581 for (const auto &field : *mFields) {
582 std::string condition = field->type().isScalar()
583 ? "this." + field->name() + " != other." + field->name()
584 : ("!java.util.Objects.deepEquals(this." + field->name()
585 + ", other." + field->name() + ")");
586 out.sIf(condition, [&] {
587 out << "return false;\n";
588 }).endl();
589 }
590 out << "return true;\n";
591 }).endl().endl();
592
Yifan Hong7d1839f2017-02-22 13:24:29 -0800593 out << "@Override\npublic final int hashCode() ";
Yifan Hongec102272016-12-20 18:10:07 -0800594 out.block([&] {
Yifan Hong7d1839f2017-02-22 13:24:29 -0800595 out << "return java.util.Objects.hash(\n";
596 out.indent(2, [&] {
597 bool first = true;
598 for (const auto &field : *mFields) {
599 if (!first) {
600 out << ", \n";
Yifan Hongec102272016-12-20 18:10:07 -0800601 }
Yifan Hong7d1839f2017-02-22 13:24:29 -0800602 first = false;
603 if (field->type().isArray()) {
604 const ArrayType &type = static_cast<const ArrayType &>(field->type());
605 if (type.countDimensions() == 1 &&
606 type.getElementType()->resolveToScalarType() != nullptr) {
607 out << "java.util.Arrays.hashCode(this." << field->name() << ")";
608 } else {
609 out << "java.util.Arrays.deepHashCode(this." << field->name() << ")";
610 }
611 } else {
612 out << "this." << field->name();
613 }
Yifan Hongec102272016-12-20 18:10:07 -0800614 }
Yifan Hong7d1839f2017-02-22 13:24:29 -0800615 });
Yifan Hongec102272016-12-20 18:10:07 -0800616 out << ");\n";
617 }).endl().endl();
618 }
619
620 ////////////////////////////////////////////////////////////////////////////
621
Yifan Honge45b5302017-02-22 10:49:07 -0800622 out << "@Override\npublic final String toString() ";
623 out.block([&] {
624 out << "java.lang.StringBuilder builder = new java.lang.StringBuilder();\n"
625 << "builder.append(\"{\");\n";
626 for (const auto &field : *mFields) {
627 out << "builder.append(\"";
628 if (field != *(mFields->begin())) {
629 out << ", ";
630 }
631 out << "." << field->name() << " = \");\n";
632 field->type().emitJavaDump(out, "builder", "this." + field->name());
633 }
634 out << "builder.append(\"}\");\nreturn builder.toString();\n";
635 }).endl().endl();
636
637 ////////////////////////////////////////////////////////////////////////////
638
Yifan Hong1af73532016-11-09 14:32:58 -0800639 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700640 out.indent();
Yifan Hong1af73532016-11-09 14:32:58 -0800641 out << "android.os.HwBlob blob = parcel.readBuffer();\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700642 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
643 out.unindent();
644 out << "}\n\n";
645
Andreas Huberf630bc82016-09-09 14:52:25 -0700646 ////////////////////////////////////////////////////////////////////////////
647
Yifan Hong1af73532016-11-09 14:32:58 -0800648 out << "public static final java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700649 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800650 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700651 out.indent();
652
Yifan Hong1af73532016-11-09 14:32:58 -0800653 out << "java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700654 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800655 << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700656
Yifan Hong1af73532016-11-09 14:32:58 -0800657 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer();\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700658
659 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700660 out,
661 0 /* depth */,
662 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700663 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700664 "_hidl_blob",
665 "_hidl_vec",
666 "0",
667 true /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700668
Andreas Huber1b6822b2016-10-18 09:28:40 -0700669 out << "\nreturn _hidl_vec;\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700670
671 out.unindent();
672 out << "}\n\n";
673
674 ////////////////////////////////////////////////////////////////////////////
675
Andreas Huber85eabdb2016-08-25 11:24:49 -0700676 out << "public final void readEmbeddedFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700677 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800678 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700679 out.unindent();
680
681 size_t offset = 0;
682 for (const auto &field : *mFields) {
683 size_t fieldAlign, fieldSize;
684 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
685
686 size_t pad = offset % fieldAlign;
687 if (pad > 0) {
688 offset += fieldAlign - pad;
689 }
690
691 field->type().emitJavaFieldReaderWriter(
692 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700693 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700694 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700695 "_hidl_blob",
696 field->name(),
697 "_hidl_offset + " + std::to_string(offset),
698 true /* isReader */);
699
700 offset += fieldSize;
701 }
702
703 out.unindent();
704 out << "}\n\n";
705
Andreas Huberf630bc82016-09-09 14:52:25 -0700706 ////////////////////////////////////////////////////////////////////////////
707
Andreas Huber709b62d2016-09-19 11:21:18 -0700708 size_t structAlign, structSize;
709 getAlignmentAndSize(&structAlign, &structSize);
710
Yifan Hong1af73532016-11-09 14:32:58 -0800711 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700712 out.indent();
713
Yifan Hong1af73532016-11-09 14:32:58 -0800714 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
Andreas Huber85eabdb2016-08-25 11:24:49 -0700715 << structSize
716 << " /* size */);\n";
717
718 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
719 << "parcel.writeBuffer(_hidl_blob);\n";
720
721 out.unindent();
722 out << "}\n\n";
723
Andreas Huberf630bc82016-09-09 14:52:25 -0700724 ////////////////////////////////////////////////////////////////////////////
725
Andreas Huberf630bc82016-09-09 14:52:25 -0700726 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700727 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800728 out << "android.os.HwParcel parcel, java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700729 << localName()
Andreas Huber1b6822b2016-10-18 09:28:40 -0700730 << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700731 out.unindent();
732
Yifan Hong1af73532016-11-09 14:32:58 -0800733 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700734
735 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700736 out,
737 0 /* depth */,
738 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700739 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700740 "_hidl_blob",
741 "_hidl_vec",
742 "0",
743 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700744
745 out << "\nparcel.writeBuffer(_hidl_blob);\n";
746
747 out.unindent();
748 out << "}\n\n";
749
750 ////////////////////////////////////////////////////////////////////////////
751
Andreas Huber85eabdb2016-08-25 11:24:49 -0700752 out << "public final void writeEmbeddedToBlob(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700753 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800754 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700755 out.unindent();
756
757 offset = 0;
758 for (const auto &field : *mFields) {
759 size_t fieldAlign, fieldSize;
760 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
761
762 size_t pad = offset % fieldAlign;
763 if (pad > 0) {
764 offset += fieldAlign - pad;
765 }
766
767 field->type().emitJavaFieldReaderWriter(
768 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700769 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700770 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700771 "_hidl_blob",
772 field->name(),
773 "_hidl_offset + " + std::to_string(offset),
774 false /* isReader */);
775
776 offset += fieldSize;
777 }
778
779 out.unindent();
780 out << "}\n";
781
782 out.unindent();
783 out << "};\n\n";
784
785 return OK;
786}
787
Andreas Huber881227d2016-08-02 14:20:21 -0700788void CompoundType::emitStructReaderWriter(
789 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800790
791 std::string space = prefix.empty() ? "" : (prefix + "::");
792
Andreas Huber881227d2016-08-02 14:20:21 -0700793 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -0800794 << (isReader ? "readEmbeddedFromParcel"
795 : "writeEmbeddedToParcel")
796 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700797
Yifan Hong0a68a282016-10-21 16:32:34 -0700798 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700799
Yifan Hong244e82d2016-11-11 11:13:57 -0800800 bool useName = false;
801 for (const auto &field : *mFields) {
802 if (field->type().useNameInEmitReaderWriterEmbedded(isReader)) {
803 useName = true;
804 break;
805 }
806 }
807 std::string name = useName ? "obj" : "/* obj */";
808 // if not useName, then obj should not be used at all,
809 // then the #error should not be emitted.
810 std::string error = useName ? "" : "\n#error\n";
811
Andreas Huber881227d2016-08-02 14:20:21 -0700812 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800813 out << space << localName() << " *" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700814 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700815 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800816 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700817 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700818 }
819
820 out << "size_t parentHandle,\n"
821 << "size_t parentOffset)";
822
Andreas Huber881227d2016-08-02 14:20:21 -0700823 out << " {\n";
824
Yifan Hong0a68a282016-10-21 16:32:34 -0700825 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700826 out.indent();
827
Iliyan Malchev549e2592016-08-10 08:59:12 -0700828 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700829
830 for (const auto &field : *mFields) {
831 if (!field->type().needsEmbeddedReadWrite()) {
832 continue;
833 }
834
835 field->type().emitReaderWriterEmbedded(
836 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700837 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -0800838 name + (isReader ? "->" : ".") + field->name() + error,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700839 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700840 false /* nameIsPointer */,
841 "parcel",
842 !isReader /* parcelObjIsPointer */,
843 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700844 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700845 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700846 "parentOffset + offsetof("
847 + fullName()
848 + ", "
849 + field->name()
850 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700851 }
852
Iliyan Malchev549e2592016-08-10 08:59:12 -0700853 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700854
855 out.unindent();
856 out << "}\n\n";
857}
858
Yifan Hongbf459bc2016-08-23 16:50:37 -0700859void CompoundType::emitResolveReferenceDef(
860 Formatter &out, const std::string prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800861 out << "::android::status_t ";
862 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -0700863
864 bool useParent = false;
865 for (const auto &field : *mFields) {
866 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
867 useParent = true;
868 break;
869 }
870 }
871
872 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
873 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
874
Yifan Hongbf459bc2016-08-23 16:50:37 -0700875 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800876 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700877 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800878 out << space + localName() + " *obj,\n"
879 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700880 << "size_t " << parentHandleName << ", "
881 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700882 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700883 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800884 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700885 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800886 out << "const " << space + localName() + " &obj,\n"
887 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700888 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -0800889 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700890 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700891 }
892
893 out << " {\n";
894
895 out.indent();
896
897 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
898
Yifan Hong244e82d2016-11-11 11:13:57 -0800899 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -0700900 // if not useParent, then parentName and offsetText
901 // should not be used at all, then the #error should not be emitted.
902 std::string error = useParent ? "" : "\n#error\n";
903
Yifan Hongbf459bc2016-08-23 16:50:37 -0700904 for (const auto &field : *mFields) {
905 if (!field->type().needsResolveReferences()) {
906 continue;
907 }
908
909 field->type().emitResolveReferencesEmbedded(
910 out,
911 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -0800912 nameDeref + field->name(),
Yifan Hongbf459bc2016-08-23 16:50:37 -0700913 field->name() /* sanitizedName */,
914 false, // nameIsPointer
915 "parcel", // const std::string &parcelObj,
916 !isReader, // bool parcelObjIsPointer,
917 isReader, // bool isReader,
918 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -0700919 parentHandleName + error,
920 parentOffsetName
921 + " + offsetof("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700922 + fullName()
923 + ", "
924 + field->name()
Yifan Hong00f47172016-09-30 14:40:45 -0700925 + ")"
926 + error);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700927 }
928
Yifan Hongbf459bc2016-08-23 16:50:37 -0700929 out << "return _hidl_err;\n";
930
931 out.unindent();
932 out << "}\n\n";
933}
934
Andreas Huber881227d2016-08-02 14:20:21 -0700935bool CompoundType::needsEmbeddedReadWrite() const {
936 if (mStyle != STYLE_STRUCT) {
937 return false;
938 }
939
940 for (const auto &field : *mFields) {
941 if (field->type().needsEmbeddedReadWrite()) {
942 return true;
943 }
944 }
945
946 return false;
947}
948
Yifan Hongbf459bc2016-08-23 16:50:37 -0700949bool CompoundType::needsResolveReferences() const {
950 if (mStyle != STYLE_STRUCT) {
951 return false;
952 }
953
954 for (const auto &field : *mFields) {
955 if (field->type().needsResolveReferences()) {
956 return true;
957 }
958 }
959
960 return false;
961}
962
Andreas Huber881227d2016-08-02 14:20:21 -0700963bool CompoundType::resultNeedsDeref() const {
964 return true;
965}
966
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700967status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700968 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700969 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700970
971 // Emit declaration for each subtype.
972 for (const auto &type : getSubTypes()) {
973 switch (mStyle) {
974 case STYLE_STRUCT:
975 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700976 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700977 break;
978 }
979 case STYLE_UNION:
980 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700981 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700982 break;
983 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700984 }
985 out.indent();
986 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700987 if (status != OK) {
988 return status;
989 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700990 out.unindent();
991 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700992 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700993
994 // Emit declaration for each field.
995 for (const auto &field : *mFields) {
996 switch (mStyle) {
997 case STYLE_STRUCT:
998 {
999 out << "struct_value: {\n";
1000 break;
1001 }
1002 case STYLE_UNION:
1003 {
1004 out << "union_value: {\n";
1005 break;
1006 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001007 }
1008 out.indent();
1009 out << "name: \"" << field->name() << "\"\n";
1010 status_t status = field->type().emitVtsAttributeType(out);
1011 if (status != OK) {
1012 return status;
1013 }
1014 out.unindent();
1015 out << "}\n";
1016 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001017
1018 return OK;
1019}
1020
Zhuoyao Zhang864c7712016-08-16 15:35:28 -07001021status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -07001022 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -07001023 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -07001024 return OK;
1025}
1026
Andreas Huber70a59e12016-08-16 12:57:01 -07001027bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -07001028 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
1029 return false;
1030 }
1031
1032 for (const auto &field : *mFields) {
1033 if (!field->type().isJavaCompatible()) {
1034 return false;
1035 }
1036 }
1037
1038 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -07001039}
1040
1041void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
1042 *align = 1;
1043
1044 size_t offset = 0;
1045 for (const auto &field : *mFields) {
1046 // Each field is aligned according to its alignment requirement.
1047 // The surrounding structure's alignment is the maximum of its
1048 // fields' aligments.
1049
1050 size_t fieldAlign, fieldSize;
1051 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
1052
1053 size_t pad = offset % fieldAlign;
1054 if (pad > 0) {
1055 offset += fieldAlign - pad;
1056 }
1057
1058 offset += fieldSize;
1059
1060 if (fieldAlign > (*align)) {
1061 *align = fieldAlign;
1062 }
1063 }
1064
1065 // Final padding to account for the structure's alignment.
1066 size_t pad = offset % (*align);
1067 if (pad > 0) {
1068 offset += (*align) - pad;
1069 }
1070
1071 *size = offset;
Andreas Huberca4bc892017-01-09 14:58:12 -08001072
1073 if (*size == 0) {
1074 // An empty struct still occupies a byte of space in C++.
1075 *size = 1;
1076 }
Andreas Huber70a59e12016-08-16 12:57:01 -07001077}
1078
Andreas Huber31629bc2016-08-03 09:06:40 -07001079////////////////////////////////////////////////////////////////////////////////
1080
1081CompoundField::CompoundField(const char *name, Type *type)
1082 : mName(name),
1083 mType(type) {
1084}
1085
1086std::string CompoundField::name() const {
1087 return mName;
1088}
1089
1090const Type &CompoundField::type() const {
1091 return *mType;
1092}
1093
Andreas Huberc9410c72016-07-28 12:18:40 -07001094} // namespace android
1095