blob: 00e171c36b4b9f063e348b814b36cee001521cb4 [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
Iliyan Malcheva72e0d22016-09-09 11:03:08 -070019#include <hidl-util/Formatter.h>
Andreas Huber881227d2016-08-02 14:20:21 -070020#include <android-base/logging.h>
21
Andreas Huberc9410c72016-07-28 12:18:40 -070022namespace android {
23
24VectorType::VectorType(Type *elementType)
25 : mElementType(elementType) {
26}
27
Steven Moreland979e0992016-09-07 09:18:08 -070028void VectorType::addNamedTypesToSet(std::set<const FQName> &set) const {
29 mElementType->addNamedTypesToSet(set);
30}
31
32std::string VectorType::getCppType(StorageMode mode,
33 std::string *extra,
34 bool specifyNamespaces) const {
Andreas Huber881227d2016-08-02 14:20:21 -070035 const std::string base =
Steven Moreland979e0992016-09-07 09:18:08 -070036 std::string(specifyNamespaces ? "::android::hardware::" : "")
37 + "hidl_vec<"
38 + mElementType->getCppType(extra, specifyNamespaces)
Andreas Huberf9d49f12016-09-12 14:58:36 -070039 + (*extra)
Andreas Huber881227d2016-08-02 14:20:21 -070040 + ">";
41
Andreas Huberf9d49f12016-09-12 14:58:36 -070042 extra->clear();
Andreas Huber881227d2016-08-02 14:20:21 -070043
44 switch (mode) {
45 case StorageMode_Stack:
46 return base;
47
48 case StorageMode_Argument:
49 return "const " + base + "&";
50
51 case StorageMode_Result:
52 return "const " + base + "*";
53 }
54}
55
Andreas Huber4c865b72016-09-14 15:26:27 -070056std::string VectorType::getJavaType(
57 std::string *extra, bool /* forInitializer */) const {
58 *extra = "[]";
59
60 std::string elementExtra;
61 return mElementType->getJavaType(&elementExtra) + elementExtra;
Andreas Huber2831d512016-08-15 09:33:47 -070062}
63
Andreas Huber881227d2016-08-02 14:20:21 -070064void VectorType::emitReaderWriter(
65 Formatter &out,
66 const std::string &name,
67 const std::string &parcelObj,
68 bool parcelObjIsPointer,
69 bool isReader,
70 ErrorMode mode) const {
71 std::string baseExtra;
72 std::string baseType = mElementType->getCppType(&baseExtra);
73
Iliyan Malchev549e2592016-08-10 08:59:12 -070074 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -070075
76 out << "size_t " << parentName << ";\n\n";
77
78 const std::string parcelObjDeref =
79 parcelObj + (parcelObjIsPointer ? "->" : ".");
80
81 if (isReader) {
82 out << name
Andreas Huber8a82ff72016-08-04 10:29:39 -070083 << " = (const ::android::hardware::hidl_vec<"
Andreas Huber881227d2016-08-02 14:20:21 -070084 << baseType
Andreas Huberf9d49f12016-09-12 14:58:36 -070085 << baseExtra
Andreas Huber881227d2016-08-02 14:20:21 -070086 << "> *)"
87 << parcelObjDeref
88 << "readBuffer(&"
89 << parentName
90 << ");\n\n";
91
92 out << "if (" << name << " == nullptr) {\n";
93
94 out.indent();
95
Iliyan Malchev549e2592016-08-10 08:59:12 -070096 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
Andreas Huber881227d2016-08-02 14:20:21 -070097 handleError2(out, mode);
98
99 out.unindent();
100 out << "}\n\n";
101 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -0700102 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700103 << parcelObjDeref
104 << "writeBuffer(&"
105 << name
106 << ", sizeof("
107 << name
108 << "), &"
109 << parentName
110 << ");\n";
111
112 handleError(out, mode);
113 }
114
115 emitReaderWriterEmbedded(
116 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700117 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700118 name,
119 isReader /* nameIsPointer */,
120 parcelObj,
121 parcelObjIsPointer,
122 isReader,
123 mode,
124 parentName,
125 "0 /* parentOffset */");
126}
127
Andreas Huberf9d49f12016-09-12 14:58:36 -0700128// Remove any trailing array indices from the given name, i.e. foo[2][3] => foo
129static std::string StripIndex(const std::string &name) {
130 size_t pos = name.find("[");
131 if (pos == std::string::npos) {
132 return name;
133 }
134
135 return name.substr(0, pos);
136}
137
Andreas Huber881227d2016-08-02 14:20:21 -0700138void VectorType::emitReaderWriterEmbedded(
139 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700140 size_t depth,
Andreas Huber881227d2016-08-02 14:20:21 -0700141 const std::string &name,
142 bool nameIsPointer,
143 const std::string &parcelObj,
144 bool parcelObjIsPointer,
145 bool isReader,
146 ErrorMode mode,
147 const std::string &parentName,
148 const std::string &offsetText) const {
149 std::string baseExtra;
150 std::string baseType = Type::getCppType(&baseExtra);
151
Andreas Huberf9d49f12016-09-12 14:58:36 -0700152 const std::string childName = "_hidl_" + StripIndex(name) + "_child";
Andreas Huber881227d2016-08-02 14:20:21 -0700153 out << "size_t " << childName << ";\n\n";
154
155 emitReaderWriterEmbeddedForTypeName(
156 out,
157 name,
158 nameIsPointer,
159 parcelObj,
160 parcelObjIsPointer,
161 isReader,
162 mode,
163 parentName,
164 offsetText,
165 baseType,
166 childName);
167
168 if (!mElementType->needsEmbeddedReadWrite()) {
169 return;
170 }
171
172 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
173
174 baseType = mElementType->getCppType(&baseExtra);
175
Andreas Huberf9d49f12016-09-12 14:58:36 -0700176 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
177
178 out << "for (size_t "
179 << iteratorName
180 << " = 0; "
181 << iteratorName
182 << " < "
Andreas Huber881227d2016-08-02 14:20:21 -0700183 << nameDeref
Andreas Huberf9d49f12016-09-12 14:58:36 -0700184 << "size(); ++"
185 << iteratorName
186 << ") {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700187
188 out.indent();
189
190 mElementType->emitReaderWriterEmbedded(
191 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700192 depth + 1,
193 (nameIsPointer ? "(*" + name + ")" : name)
194 + "[" + iteratorName + "]",
Andreas Huber881227d2016-08-02 14:20:21 -0700195 false /* nameIsPointer */,
196 parcelObj,
197 parcelObjIsPointer,
198 isReader,
199 mode,
200 childName,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700201 iteratorName + " * sizeof(" + baseType + baseExtra + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700202
203 out.unindent();
204
205 out << "}\n\n";
206}
207
Andreas Huberf630bc82016-09-09 14:52:25 -0700208void VectorType::emitJavaReaderWriter(
209 Formatter &out,
210 const std::string &parcelObj,
211 const std::string &argName,
212 bool isReader) const {
213 if (mElementType->isCompoundType()) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700214 std::string extra; // unused, because CompoundType leaves this empty.
215
Andreas Huberf630bc82016-09-09 14:52:25 -0700216 if (isReader) {
Andreas Huber4c865b72016-09-14 15:26:27 -0700217 out << mElementType->getJavaType(&extra)
Andreas Huberf630bc82016-09-09 14:52:25 -0700218 << ".readVectorFromParcel("
219 << parcelObj
220 << ");\n";
221 } else {
Andreas Huber4c865b72016-09-14 15:26:27 -0700222 out << mElementType->getJavaType(&extra)
Andreas Huberf630bc82016-09-09 14:52:25 -0700223 << ".writeVectorToParcel("
224 << parcelObj
225 << ", "
226 << argName
227 << ");\n";
228 }
229
230 return;
231 }
232
233 emitJavaReaderWriterWithSuffix(
234 out,
235 parcelObj,
236 argName,
237 isReader,
238 mElementType->getJavaSuffix() + "Vector",
239 "" /* extra */);
240}
241
Andreas Huber85eabdb2016-08-25 11:24:49 -0700242void VectorType::emitJavaFieldInitializer(
243 Formatter &out, const std::string &fieldName) const {
Andreas Hubera3558b32016-09-14 09:12:42 -0700244 const std::string wrapperType = mElementType->getJavaWrapperType();
245
Andreas Huber85eabdb2016-08-25 11:24:49 -0700246 out << "final Vector<"
Andreas Hubera3558b32016-09-14 09:12:42 -0700247 << wrapperType
Andreas Huber85eabdb2016-08-25 11:24:49 -0700248 << "> "
249 << fieldName
Andreas Hubera3558b32016-09-14 09:12:42 -0700250 << " = new Vector<"
251 << wrapperType
252 << ">();\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700253}
254
255void VectorType::emitJavaFieldReaderWriter(
256 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700257 size_t depth,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700258 const std::string &blobName,
259 const std::string &fieldName,
260 const std::string &offset,
261 bool isReader) const {
Andreas Huberf630bc82016-09-09 14:52:25 -0700262 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber4c865b72016-09-14 15:26:27 -0700263 out, depth, mElementType, blobName, fieldName, offset, isReader);
Andreas Huberf630bc82016-09-09 14:52:25 -0700264}
265
266// static
267void VectorType::EmitJavaFieldReaderWriterForElementType(
268 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700269 size_t depth,
Andreas Huberf630bc82016-09-09 14:52:25 -0700270 const Type *elementType,
271 const std::string &blobName,
272 const std::string &fieldName,
273 const std::string &offset,
274 bool isReader) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700275 if (isReader) {
276 out << "{\n";
277 out.indent();
278
279 out << "HwBlob childBlob = parcel.readEmbeddedBuffer(\n";
280 out.indent();
281 out.indent();
282
283 out << blobName
284 << ".handle(),\n"
285 << offset
286 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */);\n\n";
287
288 out.unindent();
289 out.unindent();
290
291 out << fieldName << ".clear();\n";
292 out << "long _hidl_vec_size = "
293 << blobName
294 << ".getInt64("
295 << offset
296 << " + 8 /* offsetof(hidl_vec<T>, mSize) */);\n";
297
Andreas Huber4c865b72016-09-14 15:26:27 -0700298 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
299
300 out << "for (int "
301 << iteratorName
302 << " = 0; "
303 << iteratorName
304 << " < _hidl_vec_size; "
305 << "++"
306 << iteratorName
307 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700308
309 out.indent();
310
Andreas Huberf630bc82016-09-09 14:52:25 -0700311 elementType->emitJavaFieldInitializer(out, "_hidl_vec_element");
Andreas Huber85eabdb2016-08-25 11:24:49 -0700312
313 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700314 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700315
Andreas Huberf630bc82016-09-09 14:52:25 -0700316 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700317 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700318 depth + 1,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700319 "childBlob",
320 "_hidl_vec_element",
Andreas Huber4c865b72016-09-14 15:26:27 -0700321 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700322 true /* isReader */);
323
324 out << fieldName
325 << ".add(_hidl_vec_element);\n";
326
327 out.unindent();
328
329 out << "}\n";
330
331 out.unindent();
332 out << "}\n";
333
334 return;
335 }
336
337 out << "{\n";
338 out.indent();
339
340 out << "long _hidl_vec_size = "
341 << fieldName
342 << ".size();\n";
343
344 out << blobName
345 << ".putInt64("
346 << offset
347 << " + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);\n";
348
349 out << blobName
350 << ".putBool("
351 << offset
352 << " + 16 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);\n";
353
354 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700355 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700356
357 // XXX make HwBlob constructor take a long instead of an int?
358 out << "HwBlob childBlob = new HwBlob((int)(_hidl_vec_size * "
359 << elementSize
360 << "));\n";
361
Andreas Huber4c865b72016-09-14 15:26:27 -0700362 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
363
364 out << "for (int "
365 << iteratorName
366 << " = 0; "
367 << iteratorName
368 << " < _hidl_vec_size; "
369 << "++"
370 << iteratorName
371 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700372
373 out.indent();
374
Andreas Huberf630bc82016-09-09 14:52:25 -0700375 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700376 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700377 depth + 1,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700378 "childBlob",
Andreas Huber4c865b72016-09-14 15:26:27 -0700379 fieldName + ".elementAt(" + iteratorName + ")",
380 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700381 false /* isReader */);
382
383 out.unindent();
384
385 out << "}\n";
386
387 out << blobName
388 << ".putBlob("
389 << offset
390 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);\n";
391
392 out.unindent();
393 out << "}\n";
394}
395
Andreas Huber881227d2016-08-02 14:20:21 -0700396bool VectorType::needsEmbeddedReadWrite() const {
397 return true;
398}
399
400bool VectorType::resultNeedsDeref() const {
401 return true;
402}
403
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700404status_t VectorType::emitVtsTypeDeclarations(Formatter &out) const {
405 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
406 out.indent();
407 status_t err = mElementType->emitVtsTypeDeclarations(out);
408 if (err != OK) {
409 return err;
410 }
411 out.unindent();
412 out << "}\n";
413 return OK;
414}
415
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700416status_t VectorType::emitVtsAttributeType(Formatter &out) const {
417 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
418 out.indent();
419 status_t status = mElementType->emitVtsAttributeType(out);
420 if (status != OK) {
421 return status;
422 }
423 out.unindent();
424 out << "}\n";
425 return OK;
426}
427
Andreas Huber70a59e12016-08-16 12:57:01 -0700428bool VectorType::isJavaCompatible() const {
429 return mElementType->isJavaCompatible();
430}
431
Andreas Huber85eabdb2016-08-25 11:24:49 -0700432void VectorType::getAlignmentAndSize(size_t *align, size_t *size) const {
433 *align = 8; // hidl_vec<T>
434 *size = 24;
435}
436
Andreas Huberc9410c72016-07-28 12:18:40 -0700437} // namespace android
438