blob: 544315c1ea99505f5b3a3c80fc7a59a26a492a5c [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 Huber709b62d2016-09-19 11:21:18 -0700258 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700259 const std::string &blobName,
260 const std::string &fieldName,
261 const std::string &offset,
262 bool isReader) const {
Andreas Huberf630bc82016-09-09 14:52:25 -0700263 VectorType::EmitJavaFieldReaderWriterForElementType(
Andreas Huber709b62d2016-09-19 11:21:18 -0700264 out,
265 depth,
266 mElementType,
267 parcelName,
268 blobName,
269 fieldName,
270 offset,
271 isReader);
Andreas Huberf630bc82016-09-09 14:52:25 -0700272}
273
274// static
275void VectorType::EmitJavaFieldReaderWriterForElementType(
276 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700277 size_t depth,
Andreas Huberf630bc82016-09-09 14:52:25 -0700278 const Type *elementType,
Andreas Huber709b62d2016-09-19 11:21:18 -0700279 const std::string &parcelName,
Andreas Huberf630bc82016-09-09 14:52:25 -0700280 const std::string &blobName,
281 const std::string &fieldName,
282 const std::string &offset,
283 bool isReader) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700284 if (isReader) {
285 out << "{\n";
286 out.indent();
287
Andreas Huber709b62d2016-09-19 11:21:18 -0700288 out << "HwBlob childBlob = "
289 << parcelName
290 << ".readEmbeddedBuffer(\n";
291
Andreas Huber85eabdb2016-08-25 11:24:49 -0700292 out.indent();
293 out.indent();
294
295 out << blobName
296 << ".handle(),\n"
297 << offset
298 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */);\n\n";
299
300 out.unindent();
301 out.unindent();
302
303 out << fieldName << ".clear();\n";
304 out << "long _hidl_vec_size = "
305 << blobName
306 << ".getInt64("
307 << offset
308 << " + 8 /* offsetof(hidl_vec<T>, mSize) */);\n";
309
Andreas Huber4c865b72016-09-14 15:26:27 -0700310 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
311
312 out << "for (int "
313 << iteratorName
314 << " = 0; "
315 << iteratorName
316 << " < _hidl_vec_size; "
317 << "++"
318 << iteratorName
319 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700320
321 out.indent();
322
Andreas Huberf630bc82016-09-09 14:52:25 -0700323 elementType->emitJavaFieldInitializer(out, "_hidl_vec_element");
Andreas Huber85eabdb2016-08-25 11:24:49 -0700324
325 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700326 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700327
Andreas Huberf630bc82016-09-09 14:52:25 -0700328 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700329 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700330 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700331 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700332 "childBlob",
333 "_hidl_vec_element",
Andreas Huber4c865b72016-09-14 15:26:27 -0700334 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700335 true /* isReader */);
336
337 out << fieldName
338 << ".add(_hidl_vec_element);\n";
339
340 out.unindent();
341
342 out << "}\n";
343
344 out.unindent();
345 out << "}\n";
346
347 return;
348 }
349
350 out << "{\n";
351 out.indent();
352
353 out << "long _hidl_vec_size = "
354 << fieldName
355 << ".size();\n";
356
357 out << blobName
358 << ".putInt64("
359 << offset
360 << " + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);\n";
361
362 out << blobName
363 << ".putBool("
364 << offset
365 << " + 16 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);\n";
366
367 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700368 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700369
370 // XXX make HwBlob constructor take a long instead of an int?
371 out << "HwBlob childBlob = new HwBlob((int)(_hidl_vec_size * "
372 << elementSize
373 << "));\n";
374
Andreas Huber4c865b72016-09-14 15:26:27 -0700375 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
376
377 out << "for (int "
378 << iteratorName
379 << " = 0; "
380 << iteratorName
381 << " < _hidl_vec_size; "
382 << "++"
383 << iteratorName
384 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700385
386 out.indent();
387
Andreas Huberf630bc82016-09-09 14:52:25 -0700388 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700389 out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700390 depth + 1,
Andreas Huber709b62d2016-09-19 11:21:18 -0700391 parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700392 "childBlob",
Andreas Huber4c865b72016-09-14 15:26:27 -0700393 fieldName + ".elementAt(" + iteratorName + ")",
394 iteratorName + " * " + std::to_string(elementSize),
Andreas Huber85eabdb2016-08-25 11:24:49 -0700395 false /* isReader */);
396
397 out.unindent();
398
399 out << "}\n";
400
401 out << blobName
402 << ".putBlob("
403 << offset
404 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);\n";
405
406 out.unindent();
407 out << "}\n";
408}
409
Andreas Huber881227d2016-08-02 14:20:21 -0700410bool VectorType::needsEmbeddedReadWrite() const {
411 return true;
412}
413
414bool VectorType::resultNeedsDeref() const {
415 return true;
416}
417
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700418status_t VectorType::emitVtsTypeDeclarations(Formatter &out) const {
419 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
420 out.indent();
421 status_t err = mElementType->emitVtsTypeDeclarations(out);
422 if (err != OK) {
423 return err;
424 }
425 out.unindent();
426 out << "}\n";
427 return OK;
428}
429
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700430status_t VectorType::emitVtsAttributeType(Formatter &out) const {
431 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
432 out.indent();
433 status_t status = mElementType->emitVtsAttributeType(out);
434 if (status != OK) {
435 return status;
436 }
437 out.unindent();
438 out << "}\n";
439 return OK;
440}
441
Andreas Huber70a59e12016-08-16 12:57:01 -0700442bool VectorType::isJavaCompatible() const {
443 return mElementType->isJavaCompatible();
444}
445
Andreas Huber85eabdb2016-08-25 11:24:49 -0700446void VectorType::getAlignmentAndSize(size_t *align, size_t *size) const {
447 *align = 8; // hidl_vec<T>
448 *size = 24;
449}
450
Andreas Huberc9410c72016-07-28 12:18:40 -0700451} // namespace android
452