blob: a07882d5d1f1e32c4cf73e101fd3ba8f3af22d55 [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
Andreas Huberf630bc82016-09-09 14:52:25 -070019#include "VectorType.h"
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070020#include <hidl-util/Formatter.h>
Andreas Huber5a545442016-08-03 10:44:56 -070021#include <android-base/logging.h>
22
Andreas Huberc9410c72016-07-28 12:18:40 -070023namespace android {
24
Yifan Honga4b53d02016-10-31 17:29:10 -070025CompoundType::CompoundType(Style style, const char *localName, const Location &location)
26 : Scope(localName, location),
Andreas Huber9ed827c2016-08-22 12:31:13 -070027 mStyle(style),
Andreas Huberc9410c72016-07-28 12:18:40 -070028 mFields(NULL) {
29}
30
Yifan Hong27e85db2016-11-09 15:45:52 -080031CompoundType::Style CompoundType::style() const {
32 return mStyle;
33}
34
Andreas Huber0d0f9a22016-08-17 10:26:11 -070035bool CompoundType::setFields(
36 std::vector<CompoundField *> *fields, std::string *errorMsg) {
Andreas Huberc9410c72016-07-28 12:18:40 -070037 mFields = fields;
Andreas Huber5a545442016-08-03 10:44:56 -070038
39 for (const auto &field : *fields) {
40 const Type &type = field->type();
41
Andreas Huber86a112b2016-10-19 14:25:16 -070042 if (type.isBinder()
43 || (type.isVector()
44 && static_cast<const VectorType *>(
45 &type)->isVectorOfBinders())) {
Andreas Huber0d0f9a22016-08-17 10:26:11 -070046 *errorMsg =
47 "Structs/Unions must not contain references to interfaces.";
Andreas Huberb95ea8a2016-08-15 15:35:42 -070048
49 return false;
50 }
51
Andreas Huber5a545442016-08-03 10:44:56 -070052 if (mStyle == STYLE_UNION) {
53 if (type.needsEmbeddedReadWrite()) {
54 // Can't have those in a union.
55
Andreas Huber0d0f9a22016-08-17 10:26:11 -070056 *errorMsg =
57 "Unions must not contain any types that need fixup.";
Andreas Huber5a545442016-08-03 10:44:56 -070058
59 return false;
60 }
Andreas Huber5a545442016-08-03 10:44:56 -070061 }
62 }
63
64 return true;
Andreas Huberc9410c72016-07-28 12:18:40 -070065}
66
Andreas Huberf630bc82016-09-09 14:52:25 -070067bool CompoundType::isCompoundType() const {
68 return true;
69}
70
Andreas Huber881227d2016-08-02 14:20:21 -070071std::string CompoundType::getCppType(
Steven Moreland979e0992016-09-07 09:18:08 -070072 StorageMode mode,
Steven Moreland979e0992016-09-07 09:18:08 -070073 bool specifyNamespaces) const {
Steven Moreland979e0992016-09-07 09:18:08 -070074 const std::string base =
75 specifyNamespaces ? fullName() : partialCppName();
Andreas Huber881227d2016-08-02 14:20:21 -070076
77 switch (mode) {
78 case StorageMode_Stack:
79 return base;
80
81 case StorageMode_Argument:
82 return "const " + base + "&";
83
84 case StorageMode_Result:
85 return "const " + base + "*";
86 }
87}
88
Yifan Hong4ed13472016-11-02 10:44:11 -070089std::string CompoundType::getJavaType(bool /* forInitializer */) const {
Andreas Huber85eabdb2016-08-25 11:24:49 -070090 return fullJavaName();
91}
92
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -070093std::string CompoundType::getVtsType() const {
94 switch (mStyle) {
95 case STYLE_STRUCT:
96 {
97 return "TYPE_STRUCT";
98 }
99 case STYLE_UNION:
100 {
101 return "TYPE_UNION";
102 }
103 }
104}
105
Andreas Huber881227d2016-08-02 14:20:21 -0700106void CompoundType::emitReaderWriter(
107 Formatter &out,
108 const std::string &name,
109 const std::string &parcelObj,
110 bool parcelObjIsPointer,
111 bool isReader,
112 ErrorMode mode) const {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700113 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700114
115 out << "size_t " << parentName << ";\n\n";
116
117 const std::string parcelObjDeref =
118 parcelObj + (parcelObjIsPointer ? "->" : ".");
119
120 if (isReader) {
121 out << name
122 << " = (const "
Andreas Huber0e00de42016-08-03 09:56:02 -0700123 << fullName()
Andreas Huber881227d2016-08-02 14:20:21 -0700124 << " *)"
125 << parcelObjDeref
126 << "readBuffer("
127 << "&"
128 << parentName
129 << ");\n";
130
131 out << "if ("
132 << name
133 << " == nullptr) {\n";
134
Yifan Hong0a68a282016-10-21 16:32:34 -0700135 out.indentBlock([&]{
136 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
137 handleError2(out, mode);
138 });
Andreas Huber881227d2016-08-02 14:20:21 -0700139
Andreas Huber881227d2016-08-02 14:20:21 -0700140 out << "}\n\n";
141 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700142 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700143 << parcelObjDeref
144 << "writeBuffer(&"
145 << name
146 << ", sizeof("
147 << name
148 << "), &"
149 << parentName
150 << ");\n";
151
152 handleError(out, mode);
153 }
154
155 if (mStyle != STYLE_STRUCT || !needsEmbeddedReadWrite()) {
156 return;
157 }
158
159 emitReaderWriterEmbedded(
160 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700161 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700162 name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700163 name, /* sanitizedName */
Andreas Huber881227d2016-08-02 14:20:21 -0700164 isReader /* nameIsPointer */,
165 parcelObj,
166 parcelObjIsPointer,
167 isReader,
168 mode,
169 parentName,
170 "0 /* parentOffset */");
171}
172
173void CompoundType::emitReaderWriterEmbedded(
174 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700175 size_t /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700176 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700177 const std::string & /*sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700178 bool nameIsPointer,
179 const std::string &parcelObj,
180 bool parcelObjIsPointer,
181 bool isReader,
182 ErrorMode mode,
183 const std::string &parentName,
184 const std::string &offsetText) const {
185 emitReaderWriterEmbeddedForTypeName(
186 out,
187 name,
188 nameIsPointer,
189 parcelObj,
190 parcelObjIsPointer,
191 isReader,
192 mode,
193 parentName,
194 offsetText,
Andreas Huber0e00de42016-08-03 09:56:02 -0700195 fullName(),
Yifan Hong244e82d2016-11-11 11:13:57 -0800196 "" /* childName */,
197 "" /* namespace */);
Andreas Huber881227d2016-08-02 14:20:21 -0700198}
199
Andreas Huber85eabdb2016-08-25 11:24:49 -0700200void CompoundType::emitJavaReaderWriter(
201 Formatter &out,
202 const std::string &parcelObj,
203 const std::string &argName,
204 bool isReader) const {
205 if (isReader) {
206 out << "new " << fullJavaName() << "();\n";
207 }
208
209 out << argName
210 << "."
211 << (isReader ? "readFromParcel" : "writeToParcel")
212 << "("
213 << parcelObj
214 << ");\n";
215}
216
217void CompoundType::emitJavaFieldInitializer(
218 Formatter &out, const std::string &fieldName) const {
219 out << "final "
220 << fullJavaName()
221 << " "
222 << fieldName
223 << " = new "
224 << fullJavaName()
225 << "();\n";
226}
227
228void CompoundType::emitJavaFieldReaderWriter(
229 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700230 size_t /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700231 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700232 const std::string &blobName,
233 const std::string &fieldName,
234 const std::string &offset,
235 bool isReader) const {
236 if (isReader) {
237 out << fieldName
Andreas Huber709b62d2016-09-19 11:21:18 -0700238 << ".readEmbeddedFromParcel("
239 << parcelName
240 << ", "
Andreas Huber85eabdb2016-08-25 11:24:49 -0700241 << blobName
242 << ", "
243 << offset
244 << ");\n";
245
246 return;
247 }
248
249 out << fieldName
250 << ".writeEmbeddedToBlob("
251 << blobName
252 << ", "
253 << offset
254 << ");\n";
255}
Yifan Hongbf459bc2016-08-23 16:50:37 -0700256void CompoundType::emitResolveReferences(
257 Formatter &out,
258 const std::string &name,
259 bool nameIsPointer,
260 const std::string &parcelObj,
261 bool parcelObjIsPointer,
262 bool isReader,
263 ErrorMode mode) const {
264 emitResolveReferencesEmbedded(
265 out,
266 0 /* depth */,
267 name,
268 name /* sanitizedName */,
269 nameIsPointer,
270 parcelObj,
271 parcelObjIsPointer,
272 isReader,
273 mode,
274 "_hidl_" + name + "_parent",
275 "0 /* parentOffset */");
276}
277
278void CompoundType::emitResolveReferencesEmbedded(
279 Formatter &out,
280 size_t /* depth */,
281 const std::string &name,
282 const std::string &/* sanitizedName */,
283 bool nameIsPointer,
284 const std::string &parcelObj,
285 bool parcelObjIsPointer,
286 bool isReader,
287 ErrorMode mode,
288 const std::string &parentName,
289 const std::string &offsetText) const {
290 CHECK(needsResolveReferences());
291
292 const std::string parcelObjDeref =
293 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
294
295 const std::string parcelObjPointer =
296 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
297
Yifan Hong244e82d2016-11-11 11:13:57 -0800298 const std::string nameDerefed = nameIsPointer ? ("*" + name) : name;
Yifan Hongbf459bc2016-08-23 16:50:37 -0700299 const std::string namePointer = nameIsPointer ? name : ("&" + name);
300
301 out << "_hidl_err = ";
302
303 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800304 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700305 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800306 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hongbf459bc2016-08-23 16:50:37 -0700307 }
308
Yifan Hong0a68a282016-10-21 16:32:34 -0700309 out.indentBlock(2, [&]{
Yifan Hong244e82d2016-11-11 11:13:57 -0800310 if (isReader) {
311 out << "const_cast<"
312 << fullName()
313 << " *"
314 << ">("
315 << namePointer
316 << "),\n"
317 << parcelObjDeref;
318 } else {
319 out << nameDerefed
320 << ",\n"
321 << parcelObjPointer;
322 }
323
324 out << ",\n"
Yifan Hong0a68a282016-10-21 16:32:34 -0700325 << parentName
326 << ",\n"
327 << offsetText
328 << ");\n\n";
329 });
Yifan Hongbf459bc2016-08-23 16:50:37 -0700330
331 handleError(out, mode);
332}
Andreas Huber85eabdb2016-08-25 11:24:49 -0700333
Andreas Huber881227d2016-08-02 14:20:21 -0700334status_t CompoundType::emitTypeDeclarations(Formatter &out) const {
335 out << ((mStyle == STYLE_STRUCT) ? "struct" : "union")
336 << " "
Andreas Huber0e00de42016-08-03 09:56:02 -0700337 << localName()
Andreas Huber881227d2016-08-02 14:20:21 -0700338 << " {\n";
339
340 out.indent();
341
342 Scope::emitTypeDeclarations(out);
343
344 for (const auto &field : *mFields) {
Yifan Hong3b320f82016-11-01 15:15:54 -0700345 out << field->type().getCppStackType()
Andreas Huber881227d2016-08-02 14:20:21 -0700346 << " "
347 << field->name()
Andreas Huber881227d2016-08-02 14:20:21 -0700348 << ";\n";
349 }
350
Yifan Hong244e82d2016-11-11 11:13:57 -0800351 out.unindent();
352 out << "};\n\n";
353
354 return OK;
355}
356
357
358status_t CompoundType::emitGlobalHwDeclarations(Formatter &out) const {
Andreas Huber881227d2016-08-02 14:20:21 -0700359 if (needsEmbeddedReadWrite()) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800360 out << "::android::status_t readEmbeddedFromParcel(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700361
Yifan Hong0a68a282016-10-21 16:32:34 -0700362 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700363
Yifan Hong244e82d2016-11-11 11:13:57 -0800364 out << fullName() << " *obj,\n"
365 << "const ::android::hardware::Parcel &parcel,\n"
366 << "size_t parentHandle,\n"
367 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700368
Yifan Hong0a68a282016-10-21 16:32:34 -0700369 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700370
371 out << "::android::status_t writeEmbeddedToParcel(\n";
372
Yifan Hong0a68a282016-10-21 16:32:34 -0700373 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700374
Yifan Hong244e82d2016-11-11 11:13:57 -0800375 out << "const " << fullName() << " &obj,\n"
376 << "::android::hardware::Parcel *parcel,\n"
377 << "size_t parentHandle,\n"
378 << "size_t parentOffset);\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700379
Yifan Hong0a68a282016-10-21 16:32:34 -0700380 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700381 }
382
Yifan Hongbf459bc2016-08-23 16:50:37 -0700383 if(needsResolveReferences()) {
Yifan Hongbf459bc2016-08-23 16:50:37 -0700384 out << "::android::status_t readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700385 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800386 out << fullName() << " *obj,\n"
387 << "const ::android::hardware::Parcel &parcel,\n"
388 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700389 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700390 out << "::android::status_t writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700391 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800392 out << "const " << fullName() << " &obj,\n"
393 << "::android::hardware::Parcel *,\n"
394 << "size_t parentHandle, size_t parentOffset);\n\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700395 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700396 }
397
Andreas Huber881227d2016-08-02 14:20:21 -0700398 return OK;
399}
400
401status_t CompoundType::emitTypeDefinitions(
402 Formatter &out, const std::string prefix) const {
Steven Morelandb158de12016-10-10 11:59:09 -0700403 std::string space = prefix.empty() ? "" : (prefix + "::");
404 status_t err = Scope::emitTypeDefinitions(out, space + localName());
Andreas Huber881227d2016-08-02 14:20:21 -0700405
406 if (err != OK) {
407 return err;
408 }
409
Yifan Hongbf459bc2016-08-23 16:50:37 -0700410 if (needsEmbeddedReadWrite()) {
411 emitStructReaderWriter(out, prefix, true /* isReader */);
412 emitStructReaderWriter(out, prefix, false /* isReader */);
Andreas Huber881227d2016-08-02 14:20:21 -0700413 }
414
Yifan Hongbf459bc2016-08-23 16:50:37 -0700415 if (needsResolveReferences()) {
416 emitResolveReferenceDef(out, prefix, true /* isReader */);
417 emitResolveReferenceDef(out, prefix, false /* isReader */);
418 }
Andreas Huber881227d2016-08-02 14:20:21 -0700419
420 return OK;
421}
422
Andreas Huber85eabdb2016-08-25 11:24:49 -0700423status_t CompoundType::emitJavaTypeDeclarations(
424 Formatter &out, bool atTopLevel) const {
425 out << "public final ";
426
427 if (!atTopLevel) {
428 out << "static ";
429 }
430
431 out << "class "
432 << localName()
433 << " {\n";
434
435 out.indent();
436
437 Scope::emitJavaTypeDeclarations(out, false /* atTopLevel */);
438
439 for (const auto &field : *mFields) {
440 const bool isScope = field->type().isScope(); // really isStruct...
441
442 out << "public ";
443
444 field->type().emitJavaFieldInitializer(out, field->name());
445 }
446
447 if (!mFields->empty()) {
448 out << "\n";
449 }
450
Yifan Hong1af73532016-11-09 14:32:58 -0800451 out << "public final void readFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700452 out.indent();
Yifan Hong1af73532016-11-09 14:32:58 -0800453 out << "android.os.HwBlob blob = parcel.readBuffer();\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700454 out << "readEmbeddedFromParcel(parcel, blob, 0 /* parentOffset */);\n";
455 out.unindent();
456 out << "}\n\n";
457
Andreas Huberf630bc82016-09-09 14:52:25 -0700458 ////////////////////////////////////////////////////////////////////////////
459
Yifan Hong1af73532016-11-09 14:32:58 -0800460 out << "public static final java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700461 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800462 << "> readVectorFromParcel(android.os.HwParcel parcel) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700463 out.indent();
464
Yifan Hong1af73532016-11-09 14:32:58 -0800465 out << "java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700466 << localName()
Yifan Hong1af73532016-11-09 14:32:58 -0800467 << "> _hidl_vec = new java.util.ArrayList();\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700468
Yifan Hong1af73532016-11-09 14:32:58 -0800469 out << "android.os.HwBlob _hidl_blob = parcel.readBuffer();\n\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700470
471 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700472 out,
473 0 /* depth */,
474 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700475 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700476 "_hidl_blob",
477 "_hidl_vec",
478 "0",
479 true /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700480
Andreas Huber1b6822b2016-10-18 09:28:40 -0700481 out << "\nreturn _hidl_vec;\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700482
483 out.unindent();
484 out << "}\n\n";
485
486 ////////////////////////////////////////////////////////////////////////////
487
Andreas Huber85eabdb2016-08-25 11:24:49 -0700488 out << "public final void readEmbeddedFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700489 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800490 out << "android.os.HwParcel parcel, android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700491 out.unindent();
492
493 size_t offset = 0;
494 for (const auto &field : *mFields) {
495 size_t fieldAlign, fieldSize;
496 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
497
498 size_t pad = offset % fieldAlign;
499 if (pad > 0) {
500 offset += fieldAlign - pad;
501 }
502
503 field->type().emitJavaFieldReaderWriter(
504 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700505 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700506 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700507 "_hidl_blob",
508 field->name(),
509 "_hidl_offset + " + std::to_string(offset),
510 true /* isReader */);
511
512 offset += fieldSize;
513 }
514
515 out.unindent();
516 out << "}\n\n";
517
Andreas Huberf630bc82016-09-09 14:52:25 -0700518 ////////////////////////////////////////////////////////////////////////////
519
Andreas Huber709b62d2016-09-19 11:21:18 -0700520 size_t structAlign, structSize;
521 getAlignmentAndSize(&structAlign, &structSize);
522
Yifan Hong1af73532016-11-09 14:32:58 -0800523 out << "public final void writeToParcel(android.os.HwParcel parcel) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700524 out.indent();
525
Yifan Hong1af73532016-11-09 14:32:58 -0800526 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob("
Andreas Huber85eabdb2016-08-25 11:24:49 -0700527 << structSize
528 << " /* size */);\n";
529
530 out << "writeEmbeddedToBlob(_hidl_blob, 0 /* parentOffset */);\n"
531 << "parcel.writeBuffer(_hidl_blob);\n";
532
533 out.unindent();
534 out << "}\n\n";
535
Andreas Huberf630bc82016-09-09 14:52:25 -0700536 ////////////////////////////////////////////////////////////////////////////
537
Andreas Huberf630bc82016-09-09 14:52:25 -0700538 out << "public static final void writeVectorToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700539 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800540 out << "android.os.HwParcel parcel, java.util.ArrayList<"
Andreas Huberf630bc82016-09-09 14:52:25 -0700541 << localName()
Andreas Huber1b6822b2016-10-18 09:28:40 -0700542 << "> _hidl_vec) {\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700543 out.unindent();
544
Yifan Hong1af73532016-11-09 14:32:58 -0800545 out << "android.os.HwBlob _hidl_blob = new android.os.HwBlob(24 /* sizeof(hidl_vec<T>) */);\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700546
547 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700548 out,
549 0 /* depth */,
550 this,
Andreas Huber709b62d2016-09-19 11:21:18 -0700551 "parcel",
Andreas Huber4c865b72016-09-14 15:26:27 -0700552 "_hidl_blob",
553 "_hidl_vec",
554 "0",
555 false /* isReader */);
Andreas Huberf630bc82016-09-09 14:52:25 -0700556
557 out << "\nparcel.writeBuffer(_hidl_blob);\n";
558
559 out.unindent();
560 out << "}\n\n";
561
562 ////////////////////////////////////////////////////////////////////////////
563
Andreas Huber85eabdb2016-08-25 11:24:49 -0700564 out << "public final void writeEmbeddedToBlob(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700565 out.indent(2);
Yifan Hong1af73532016-11-09 14:32:58 -0800566 out << "android.os.HwBlob _hidl_blob, long _hidl_offset) {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700567 out.unindent();
568
569 offset = 0;
570 for (const auto &field : *mFields) {
571 size_t fieldAlign, fieldSize;
572 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
573
574 size_t pad = offset % fieldAlign;
575 if (pad > 0) {
576 offset += fieldAlign - pad;
577 }
578
579 field->type().emitJavaFieldReaderWriter(
580 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700581 0 /* depth */,
Andreas Huber709b62d2016-09-19 11:21:18 -0700582 "parcel",
Andreas Huber85eabdb2016-08-25 11:24:49 -0700583 "_hidl_blob",
584 field->name(),
585 "_hidl_offset + " + std::to_string(offset),
586 false /* isReader */);
587
588 offset += fieldSize;
589 }
590
591 out.unindent();
592 out << "}\n";
593
594 out.unindent();
595 out << "};\n\n";
596
597 return OK;
598}
599
Andreas Huber881227d2016-08-02 14:20:21 -0700600void CompoundType::emitStructReaderWriter(
601 Formatter &out, const std::string &prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800602
603 std::string space = prefix.empty() ? "" : (prefix + "::");
604
Andreas Huber881227d2016-08-02 14:20:21 -0700605 out << "::android::status_t "
Yifan Hong244e82d2016-11-11 11:13:57 -0800606 << (isReader ? "readEmbeddedFromParcel"
607 : "writeEmbeddedToParcel")
608 << "(\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700609
Yifan Hong0a68a282016-10-21 16:32:34 -0700610 out.indent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700611
Yifan Hong244e82d2016-11-11 11:13:57 -0800612 bool useName = false;
613 for (const auto &field : *mFields) {
614 if (field->type().useNameInEmitReaderWriterEmbedded(isReader)) {
615 useName = true;
616 break;
617 }
618 }
619 std::string name = useName ? "obj" : "/* obj */";
620 // if not useName, then obj should not be used at all,
621 // then the #error should not be emitted.
622 std::string error = useName ? "" : "\n#error\n";
623
Andreas Huber881227d2016-08-02 14:20:21 -0700624 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800625 out << space << localName() << " *" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700626 out << "const ::android::hardware::Parcel &parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700627 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800628 out << "const " << space << localName() << " &" << name << ",\n";
Andreas Huber8a82ff72016-08-04 10:29:39 -0700629 out << "::android::hardware::Parcel *parcel,\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700630 }
631
632 out << "size_t parentHandle,\n"
633 << "size_t parentOffset)";
634
Andreas Huber881227d2016-08-02 14:20:21 -0700635 out << " {\n";
636
Yifan Hong0a68a282016-10-21 16:32:34 -0700637 out.unindent(2);
Andreas Huber881227d2016-08-02 14:20:21 -0700638 out.indent();
639
Iliyan Malchev549e2592016-08-10 08:59:12 -0700640 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700641
642 for (const auto &field : *mFields) {
643 if (!field->type().needsEmbeddedReadWrite()) {
644 continue;
645 }
646
647 field->type().emitReaderWriterEmbedded(
648 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700649 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -0800650 name + (isReader ? "->" : ".") + field->name() + error,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700651 field->name() /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700652 false /* nameIsPointer */,
653 "parcel",
654 !isReader /* parcelObjIsPointer */,
655 isReader,
Andreas Huber737080b2016-08-02 15:38:04 -0700656 ErrorMode_Return,
Andreas Huber881227d2016-08-02 14:20:21 -0700657 "parentHandle",
Andreas Huber0e00de42016-08-03 09:56:02 -0700658 "parentOffset + offsetof("
659 + fullName()
660 + ", "
661 + field->name()
662 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700663 }
664
665 out.unindent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700666 out << "_hidl_error:\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700667 out.indent();
Iliyan Malchev549e2592016-08-10 08:59:12 -0700668 out << "return _hidl_err;\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700669
670 out.unindent();
671 out << "}\n\n";
672}
673
Yifan Hongbf459bc2016-08-23 16:50:37 -0700674void CompoundType::emitResolveReferenceDef(
675 Formatter &out, const std::string prefix, bool isReader) const {
Yifan Hong244e82d2016-11-11 11:13:57 -0800676 out << "::android::status_t ";
677 const std::string space(prefix.empty() ? "" : (prefix + "::"));
Yifan Hong00f47172016-09-30 14:40:45 -0700678
679 bool useParent = false;
680 for (const auto &field : *mFields) {
681 if (field->type().useParentInEmitResolveReferencesEmbedded()) {
682 useParent = true;
683 break;
684 }
685 }
686
687 std::string parentHandleName = useParent ? "parentHandle" : "/* parentHandle */";
688 std::string parentOffsetName = useParent ? "parentOffset" : "/* parentOffset */";
689
Yifan Hongbf459bc2016-08-23 16:50:37 -0700690 if (isReader) {
Yifan Hong244e82d2016-11-11 11:13:57 -0800691 out << "readEmbeddedReferenceFromParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700692 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800693 out << space + localName() + " *obj,\n"
694 << "const ::android::hardware::Parcel &parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700695 << "size_t " << parentHandleName << ", "
696 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700697 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700698 } else {
Yifan Hong244e82d2016-11-11 11:13:57 -0800699 out << "writeEmbeddedReferenceToParcel(\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700700 out.indent(2);
Yifan Hong244e82d2016-11-11 11:13:57 -0800701 out << "const " << space + localName() + " &obj,\n"
702 << "::android::hardware::Parcel *parcel,\n"
Yifan Hong00f47172016-09-30 14:40:45 -0700703 << "size_t " << parentHandleName << ", "
Yifan Hong244e82d2016-11-11 11:13:57 -0800704 << "size_t " << parentOffsetName << ")\n";
Yifan Hong0a68a282016-10-21 16:32:34 -0700705 out.unindent(2);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700706 }
707
708 out << " {\n";
709
710 out.indent();
711
712 out << "::android::status_t _hidl_err = ::android::OK;\n\n";
713
Yifan Hong244e82d2016-11-11 11:13:57 -0800714 const std::string nameDeref(isReader ? "obj->" : "obj.");
Yifan Hong00f47172016-09-30 14:40:45 -0700715 // if not useParent, then parentName and offsetText
716 // should not be used at all, then the #error should not be emitted.
717 std::string error = useParent ? "" : "\n#error\n";
718
Yifan Hongbf459bc2016-08-23 16:50:37 -0700719 for (const auto &field : *mFields) {
720 if (!field->type().needsResolveReferences()) {
721 continue;
722 }
723
724 field->type().emitResolveReferencesEmbedded(
725 out,
726 0 /* depth */,
Yifan Hong244e82d2016-11-11 11:13:57 -0800727 nameDeref + field->name(),
Yifan Hongbf459bc2016-08-23 16:50:37 -0700728 field->name() /* sanitizedName */,
729 false, // nameIsPointer
730 "parcel", // const std::string &parcelObj,
731 !isReader, // bool parcelObjIsPointer,
732 isReader, // bool isReader,
733 ErrorMode_Return,
Yifan Hong00f47172016-09-30 14:40:45 -0700734 parentHandleName + error,
735 parentOffsetName
736 + " + offsetof("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700737 + fullName()
738 + ", "
739 + field->name()
Yifan Hong00f47172016-09-30 14:40:45 -0700740 + ")"
741 + error);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700742 }
743
744 out.unindent();
745 out << "_hidl_error:\n";
746 out.indent();
747 out << "return _hidl_err;\n";
748
749 out.unindent();
750 out << "}\n\n";
751}
752
Andreas Huber881227d2016-08-02 14:20:21 -0700753bool CompoundType::needsEmbeddedReadWrite() const {
754 if (mStyle != STYLE_STRUCT) {
755 return false;
756 }
757
758 for (const auto &field : *mFields) {
759 if (field->type().needsEmbeddedReadWrite()) {
760 return true;
761 }
762 }
763
764 return false;
765}
766
Yifan Hongbf459bc2016-08-23 16:50:37 -0700767bool CompoundType::needsResolveReferences() const {
768 if (mStyle != STYLE_STRUCT) {
769 return false;
770 }
771
772 for (const auto &field : *mFields) {
773 if (field->type().needsResolveReferences()) {
774 return true;
775 }
776 }
777
778 return false;
779}
780
Andreas Huber881227d2016-08-02 14:20:21 -0700781bool CompoundType::resultNeedsDeref() const {
782 return true;
783}
784
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700785status_t CompoundType::emitVtsTypeDeclarations(Formatter &out) const {
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700786 out << "name: \"" << fullName() << "\"\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700787 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700788
789 // Emit declaration for each subtype.
790 for (const auto &type : getSubTypes()) {
791 switch (mStyle) {
792 case STYLE_STRUCT:
793 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700794 out << "sub_struct: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700795 break;
796 }
797 case STYLE_UNION:
798 {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700799 out << "sub_union: {\n";
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700800 break;
801 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700802 }
803 out.indent();
804 status_t status(type->emitVtsTypeDeclarations(out));
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700805 if (status != OK) {
806 return status;
807 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700808 out.unindent();
809 out << "}\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700810 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700811
812 // Emit declaration for each field.
813 for (const auto &field : *mFields) {
814 switch (mStyle) {
815 case STYLE_STRUCT:
816 {
817 out << "struct_value: {\n";
818 break;
819 }
820 case STYLE_UNION:
821 {
822 out << "union_value: {\n";
823 break;
824 }
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700825 }
826 out.indent();
827 out << "name: \"" << field->name() << "\"\n";
828 status_t status = field->type().emitVtsAttributeType(out);
829 if (status != OK) {
830 return status;
831 }
832 out.unindent();
833 out << "}\n";
834 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700835
836 return OK;
837}
838
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700839status_t CompoundType::emitVtsAttributeType(Formatter &out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700840 out << "type: " << getVtsType() << "\n";
Zhuoyao Zhangbf828c82016-10-26 14:15:10 -0700841 out << "predefined_type: \"" << fullName() << "\"\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700842 return OK;
843}
844
Andreas Huber70a59e12016-08-16 12:57:01 -0700845bool CompoundType::isJavaCompatible() const {
Andreas Huber0fa9e392016-08-31 09:05:44 -0700846 if (mStyle != STYLE_STRUCT || !Scope::isJavaCompatible()) {
847 return false;
848 }
849
850 for (const auto &field : *mFields) {
851 if (!field->type().isJavaCompatible()) {
852 return false;
853 }
854 }
855
856 return true;
Andreas Huber85eabdb2016-08-25 11:24:49 -0700857}
858
859void CompoundType::getAlignmentAndSize(size_t *align, size_t *size) const {
860 *align = 1;
861
862 size_t offset = 0;
863 for (const auto &field : *mFields) {
864 // Each field is aligned according to its alignment requirement.
865 // The surrounding structure's alignment is the maximum of its
866 // fields' aligments.
867
868 size_t fieldAlign, fieldSize;
869 field->type().getAlignmentAndSize(&fieldAlign, &fieldSize);
870
871 size_t pad = offset % fieldAlign;
872 if (pad > 0) {
873 offset += fieldAlign - pad;
874 }
875
876 offset += fieldSize;
877
878 if (fieldAlign > (*align)) {
879 *align = fieldAlign;
880 }
881 }
882
883 // Final padding to account for the structure's alignment.
884 size_t pad = offset % (*align);
885 if (pad > 0) {
886 offset += (*align) - pad;
887 }
888
889 *size = offset;
Andreas Huber70a59e12016-08-16 12:57:01 -0700890}
891
Andreas Huber31629bc2016-08-03 09:06:40 -0700892////////////////////////////////////////////////////////////////////////////////
893
894CompoundField::CompoundField(const char *name, Type *type)
895 : mName(name),
896 mType(type) {
897}
898
899std::string CompoundField::name() const {
900 return mName;
901}
902
903const Type &CompoundField::type() const {
904 return *mType;
905}
906
Andreas Huberc9410c72016-07-28 12:18:40 -0700907} // namespace android
908