blob: adf7967f0f1bbc28a652e7e90511eb52ad5ebff0 [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 "VectorType.h"
18
Andreas Huberf03332a2016-09-22 15:35:43 -070019#include "ArrayType.h"
20
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070021#include <hidl-util/Formatter.h>
Andreas Huber881227d2016-08-02 14:20:21 -070022#include <android-base/logging.h>
23
Andreas Huberc9410c72016-07-28 12:18:40 -070024namespace android {
25
26VectorType::VectorType(Type *elementType)
27 : mElementType(elementType) {
28}
29
Steven Moreland979e0992016-09-07 09:18:08 -070030void VectorType::addNamedTypesToSet(std::set<const FQName> &set) const {
31 mElementType->addNamedTypesToSet(set);
32}
33
34std::string VectorType::getCppType(StorageMode mode,
35 std::string *extra,
36 bool specifyNamespaces) const {
Andreas Huber881227d2016-08-02 14:20:21 -070037 const std::string base =
Steven Moreland979e0992016-09-07 09:18:08 -070038 std::string(specifyNamespaces ? "::android::hardware::" : "")
39 + "hidl_vec<"
40 + mElementType->getCppType(extra, specifyNamespaces)
Andreas Huberf9d49f12016-09-12 14:58:36 -070041 + (*extra)
Andreas Huber881227d2016-08-02 14:20:21 -070042 + ">";
43
Andreas Huberf9d49f12016-09-12 14:58:36 -070044 extra->clear();
Andreas Huber881227d2016-08-02 14:20:21 -070045
46 switch (mode) {
47 case StorageMode_Stack:
48 return base;
49
50 case StorageMode_Argument:
51 return "const " + base + "&";
52
53 case StorageMode_Result:
54 return "const " + base + "*";
55 }
56}
57
Andreas Huber4c865b72016-09-14 15:26:27 -070058std::string VectorType::getJavaType(
59 std::string *extra, bool /* forInitializer */) const {
60 *extra = "[]";
61
62 std::string elementExtra;
63 return mElementType->getJavaType(&elementExtra) + elementExtra;
Andreas Huber2831d512016-08-15 09:33:47 -070064}
65
Andreas Huber881227d2016-08-02 14:20:21 -070066void VectorType::emitReaderWriter(
67 Formatter &out,
68 const std::string &name,
69 const std::string &parcelObj,
70 bool parcelObjIsPointer,
71 bool isReader,
72 ErrorMode mode) const {
73 std::string baseExtra;
74 std::string baseType = mElementType->getCppType(&baseExtra);
75
Iliyan Malchev549e2592016-08-10 08:59:12 -070076 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -070077
78 out << "size_t " << parentName << ";\n\n";
79
80 const std::string parcelObjDeref =
81 parcelObj + (parcelObjIsPointer ? "->" : ".");
82
83 if (isReader) {
84 out << name
Andreas Huber8a82ff72016-08-04 10:29:39 -070085 << " = (const ::android::hardware::hidl_vec<"
Andreas Huber881227d2016-08-02 14:20:21 -070086 << baseType
Andreas Huberf9d49f12016-09-12 14:58:36 -070087 << baseExtra
Andreas Huber881227d2016-08-02 14:20:21 -070088 << "> *)"
89 << parcelObjDeref
90 << "readBuffer(&"
91 << parentName
92 << ");\n\n";
93
94 out << "if (" << name << " == nullptr) {\n";
95
96 out.indent();
97
Iliyan Malchev549e2592016-08-10 08:59:12 -070098 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
Andreas Huber881227d2016-08-02 14:20:21 -070099 handleError2(out, mode);
100
101 out.unindent();
102 out << "}\n\n";
103 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700104 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700105 << parcelObjDeref
106 << "writeBuffer(&"
107 << name
108 << ", sizeof("
109 << name
110 << "), &"
111 << parentName
112 << ");\n";
113
114 handleError(out, mode);
115 }
116
117 emitReaderWriterEmbedded(
118 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700119 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700120 name,
121 isReader /* nameIsPointer */,
122 parcelObj,
123 parcelObjIsPointer,
124 isReader,
125 mode,
126 parentName,
127 "0 /* parentOffset */");
128}
129
Andreas Huberf9d49f12016-09-12 14:58:36 -0700130// Remove any trailing array indices from the given name, i.e. foo[2][3] => foo
131static std::string StripIndex(const std::string &name) {
132 size_t pos = name.find("[");
133 if (pos == std::string::npos) {
134 return name;
135 }
136
137 return name.substr(0, pos);
138}
139
Andreas Huber881227d2016-08-02 14:20:21 -0700140void VectorType::emitReaderWriterEmbedded(
141 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700142 size_t depth,
Andreas Huber881227d2016-08-02 14:20:21 -0700143 const std::string &name,
144 bool nameIsPointer,
145 const std::string &parcelObj,
146 bool parcelObjIsPointer,
147 bool isReader,
148 ErrorMode mode,
149 const std::string &parentName,
150 const std::string &offsetText) const {
151 std::string baseExtra;
152 std::string baseType = Type::getCppType(&baseExtra);
153
Andreas Huberf9d49f12016-09-12 14:58:36 -0700154 const std::string childName = "_hidl_" + StripIndex(name) + "_child";
Andreas Huber881227d2016-08-02 14:20:21 -0700155 out << "size_t " << childName << ";\n\n";
156
157 emitReaderWriterEmbeddedForTypeName(
158 out,
159 name,
160 nameIsPointer,
161 parcelObj,
162 parcelObjIsPointer,
163 isReader,
164 mode,
165 parentName,
166 offsetText,
167 baseType,
168 childName);
169
170 if (!mElementType->needsEmbeddedReadWrite()) {
171 return;
172 }
173
174 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
175
176 baseType = mElementType->getCppType(&baseExtra);
177
Andreas Huberf9d49f12016-09-12 14:58:36 -0700178 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
179
180 out << "for (size_t "
181 << iteratorName
182 << " = 0; "
183 << iteratorName
184 << " < "
Andreas Huber881227d2016-08-02 14:20:21 -0700185 << nameDeref
Andreas Huberf9d49f12016-09-12 14:58:36 -0700186 << "size(); ++"
187 << iteratorName
188 << ") {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700189
190 out.indent();
191
192 mElementType->emitReaderWriterEmbedded(
193 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700194 depth + 1,
195 (nameIsPointer ? "(*" + name + ")" : name)
196 + "[" + iteratorName + "]",
Andreas Huber881227d2016-08-02 14:20:21 -0700197 false /* nameIsPointer */,
198 parcelObj,
199 parcelObjIsPointer,
200 isReader,
201 mode,
202 childName,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700203 iteratorName + " * sizeof(" + baseType + baseExtra + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700204
205 out.unindent();
206
207 out << "}\n\n";
208}
209
Andreas Huberf630bc82016-09-09 14:52:25 -0700210void VectorType::emitJavaReaderWriter(
211 Formatter &out,
212 const std::string &parcelObj,
213 const std::string &argName,
214 bool isReader) const {
215 if (mElementType->isCompoundType()) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700216 std::string extra; // unused, because CompoundType leaves this empty.
217
Andreas Huberf630bc82016-09-09 14:52:25 -0700218 if (isReader) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700219 out << mElementType->getJavaType(&extra)
Andreas Huberf630bc82016-09-09 14:52:25 -0700220 << ".readVectorFromParcel("
221 << parcelObj
222 << ");\n";
223 } else {
Andreas Huber4c865b72016-09-14 15:26:27 -0700224 out << mElementType->getJavaType(&extra)
Andreas Huberf630bc82016-09-09 14:52:25 -0700225 << ".writeVectorToParcel("
226 << parcelObj
227 << ", "
228 << argName
229 << ");\n";
230 }
231
232 return;
233 }
234
235 emitJavaReaderWriterWithSuffix(
236 out,
237 parcelObj,
238 argName,
239 isReader,
240 mElementType->getJavaSuffix() + "Vector",
241 "" /* extra */);
242}
243
Andreas Huber85eabdb2016-08-25 11:24:49 -0700244void VectorType::emitJavaFieldInitializer(
245 Formatter &out, const std::string &fieldName) const {
Andreas Huberf03332a2016-09-22 15:35:43 -0700246 std::string extra;
247 mElementType->getJavaType(&extra);
248
Andreas Hubera3558b32016-09-14 09:12:42 -0700249 const std::string wrapperType = mElementType->getJavaWrapperType();
250
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700251 out << "final ArrayList<"
Andreas Hubera3558b32016-09-14 09:12:42 -0700252 << wrapperType
Andreas Huberf03332a2016-09-22 15:35:43 -0700253 << extra
Andreas Huber85eabdb2016-08-25 11:24:49 -0700254 << "> "
255 << fieldName
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700256 << " = new ArrayList<"
Andreas Hubera3558b32016-09-14 09:12:42 -0700257 << wrapperType
Andreas Huberf03332a2016-09-22 15:35:43 -0700258 << extra
Andreas Hubera3558b32016-09-14 09:12:42 -0700259 << ">();\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700260}
261
262void VectorType::emitJavaFieldReaderWriter(
263 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700264 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700265 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700266 const std::string &blobName,
267 const std::string &fieldName,
268 const std::string &offset,
269 bool isReader) const {
Andreas Huberf630bc82016-09-09 14:52:25 -0700270 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber709b62d2016-09-19 11:21:18 -0700271 out,
272 depth,
273 mElementType,
274 parcelName,
275 blobName,
276 fieldName,
277 offset,
278 isReader);
Andreas Huberf630bc82016-09-09 14:52:25 -0700279}
280
281// static
282void VectorType::EmitJavaFieldReaderWriterForElementType(
283 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700284 size_t depth,
Andreas Huberf630bc82016-09-09 14:52:25 -0700285 const Type *elementType,
Andreas Huber709b62d2016-09-19 11:21:18 -0700286 const std::string &parcelName,
Andreas Huberf630bc82016-09-09 14:52:25 -0700287 const std::string &blobName,
288 const std::string &fieldName,
289 const std::string &offset,
290 bool isReader) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700291 if (isReader) {
292 out << "{\n";
293 out.indent();
294
Andreas Huber709b62d2016-09-19 11:21:18 -0700295 out << "HwBlob childBlob = "
296 << parcelName
297 << ".readEmbeddedBuffer(\n";
298
Andreas Huber85eabdb2016-08-25 11:24:49 -0700299 out.indent();
300 out.indent();
301
302 out << blobName
303 << ".handle(),\n"
304 << offset
305 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */);\n\n";
306
307 out.unindent();
308 out.unindent();
309
310 out << fieldName << ".clear();\n";
311 out << "long _hidl_vec_size = "
312 << blobName
313 << ".getInt64("
314 << offset
315 << " + 8 /* offsetof(hidl_vec<T>, mSize) */);\n";
316
Andreas Huber4c865b72016-09-14 15:26:27 -0700317 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
318
319 out << "for (int "
320 << iteratorName
321 << " = 0; "
322 << iteratorName
323 << " < _hidl_vec_size; "
324 << "++"
325 << iteratorName
326 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700327
328 out.indent();
329
Andreas Huberf630bc82016-09-09 14:52:25 -0700330 elementType->emitJavaFieldInitializer(out, "_hidl_vec_element");
Andreas Huber85eabdb2016-08-25 11:24:49 -0700331
332 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700333 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700334
Andreas Huberf630bc82016-09-09 14:52:25 -0700335 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700336 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700337 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700338 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700339 "childBlob",
340 "_hidl_vec_element",
Andreas Huber4c865b72016-09-14 15:26:27 -0700341 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700342 true /* isReader */);
343
Andreas Huberf03332a2016-09-22 15:35:43 -0700344 out << fieldName;
345
346 if (elementType->isArray()
347 && static_cast<const ArrayType *>(
348 elementType)->getElementType()->resolveToScalarType()
349 != nullptr) {
350 out << ".add(HwBlob.wrapArray(_hidl_vec_element));\n";
351 } else {
352 out << ".add(_hidl_vec_element);\n";
353 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700354
355 out.unindent();
356
357 out << "}\n";
358
359 out.unindent();
360 out << "}\n";
361
362 return;
363 }
364
365 out << "{\n";
366 out.indent();
367
368 out << "long _hidl_vec_size = "
369 << fieldName
370 << ".size();\n";
371
372 out << blobName
373 << ".putInt64("
374 << offset
375 << " + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);\n";
376
377 out << blobName
378 << ".putBool("
379 << offset
380 << " + 16 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);\n";
381
382 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700383 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700384
385 // XXX make HwBlob constructor take a long instead of an int?
386 out << "HwBlob childBlob = new HwBlob((int)(_hidl_vec_size * "
387 << elementSize
388 << "));\n";
389
Andreas Huber4c865b72016-09-14 15:26:27 -0700390 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
391
392 out << "for (int "
393 << iteratorName
394 << " = 0; "
395 << iteratorName
396 << " < _hidl_vec_size; "
397 << "++"
398 << iteratorName
399 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700400
401 out.indent();
402
Andreas Huberf630bc82016-09-09 14:52:25 -0700403 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700404 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700405 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700406 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700407 "childBlob",
Andreas Huberf1abc2a2016-09-28 09:14:43 -0700408 fieldName + ".get(" + iteratorName + ")",
Andreas Huber4c865b72016-09-14 15:26:27 -0700409 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700410 false /* isReader */);
411
412 out.unindent();
413
414 out << "}\n";
415
416 out << blobName
417 << ".putBlob("
418 << offset
419 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);\n";
420
421 out.unindent();
422 out << "}\n";
423}
424
Andreas Huber881227d2016-08-02 14:20:21 -0700425bool VectorType::needsEmbeddedReadWrite() const {
426 return true;
427}
428
429bool VectorType::resultNeedsDeref() const {
430 return true;
431}
432
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700433status_t VectorType::emitVtsTypeDeclarations(Formatter &out) const {
434 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
435 out.indent();
436 status_t err = mElementType->emitVtsTypeDeclarations(out);
437 if (err != OK) {
438 return err;
439 }
440 out.unindent();
441 out << "}\n";
442 return OK;
443}
444
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700445status_t VectorType::emitVtsAttributeType(Formatter &out) const {
446 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
447 out.indent();
448 status_t status = mElementType->emitVtsAttributeType(out);
449 if (status != OK) {
450 return status;
451 }
452 out.unindent();
453 out << "}\n";
454 return OK;
455}
456
Andreas Huber70a59e12016-08-16 12:57:01 -0700457bool VectorType::isJavaCompatible() const {
Andreas Huberf03332a2016-09-22 15:35:43 -0700458 if (!mElementType->isJavaCompatible()) {
459 return false;
460 }
461
462 if (mElementType->isArray()) {
463 return static_cast<ArrayType *>(mElementType)->countDimensions() == 1;
464 }
465
466 return true;
Andreas Huber70a59e12016-08-16 12:57:01 -0700467}
468
Andreas Huber85eabdb2016-08-25 11:24:49 -0700469void VectorType::getAlignmentAndSize(size_t *align, size_t *size) const {
470 *align = 8; // hidl_vec<T>
471 *size = 24;
472}
473
Andreas Huberc9410c72016-07-28 12:18:40 -0700474} // namespace android
475