blob: 8e2c59907b7d3fa7d6254d8466a4b3b8a1c1ff93 [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 Huber2831d512016-08-15 09:33:47 -070056std::string VectorType::getJavaType() const {
57 return mElementType->getJavaType() + "[]";
58}
59
Andreas Huber881227d2016-08-02 14:20:21 -070060void VectorType::emitReaderWriter(
61 Formatter &out,
62 const std::string &name,
63 const std::string &parcelObj,
64 bool parcelObjIsPointer,
65 bool isReader,
66 ErrorMode mode) const {
67 std::string baseExtra;
68 std::string baseType = mElementType->getCppType(&baseExtra);
69
Iliyan Malchev549e2592016-08-10 08:59:12 -070070 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -070071
72 out << "size_t " << parentName << ";\n\n";
73
74 const std::string parcelObjDeref =
75 parcelObj + (parcelObjIsPointer ? "->" : ".");
76
77 if (isReader) {
78 out << name
Andreas Huber8a82ff72016-08-04 10:29:39 -070079 << " = (const ::android::hardware::hidl_vec<"
Andreas Huber881227d2016-08-02 14:20:21 -070080 << baseType
Andreas Huberf9d49f12016-09-12 14:58:36 -070081 << baseExtra
Andreas Huber881227d2016-08-02 14:20:21 -070082 << "> *)"
83 << parcelObjDeref
84 << "readBuffer(&"
85 << parentName
86 << ");\n\n";
87
88 out << "if (" << name << " == nullptr) {\n";
89
90 out.indent();
91
Iliyan Malchev549e2592016-08-10 08:59:12 -070092 out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
Andreas Huber881227d2016-08-02 14:20:21 -070093 handleError2(out, mode);
94
95 out.unindent();
96 out << "}\n\n";
97 } else {
Iliyan Malchev549e2592016-08-10 08:59:12 -070098 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -070099 << parcelObjDeref
100 << "writeBuffer(&"
101 << name
102 << ", sizeof("
103 << name
104 << "), &"
105 << parentName
106 << ");\n";
107
108 handleError(out, mode);
109 }
110
111 emitReaderWriterEmbedded(
112 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700113 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700114 name,
115 isReader /* nameIsPointer */,
116 parcelObj,
117 parcelObjIsPointer,
118 isReader,
119 mode,
120 parentName,
121 "0 /* parentOffset */");
122}
123
Andreas Huberf9d49f12016-09-12 14:58:36 -0700124// Remove any trailing array indices from the given name, i.e. foo[2][3] => foo
125static std::string StripIndex(const std::string &name) {
126 size_t pos = name.find("[");
127 if (pos == std::string::npos) {
128 return name;
129 }
130
131 return name.substr(0, pos);
132}
133
Andreas Huber881227d2016-08-02 14:20:21 -0700134void VectorType::emitReaderWriterEmbedded(
135 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700136 size_t depth,
Andreas Huber881227d2016-08-02 14:20:21 -0700137 const std::string &name,
138 bool nameIsPointer,
139 const std::string &parcelObj,
140 bool parcelObjIsPointer,
141 bool isReader,
142 ErrorMode mode,
143 const std::string &parentName,
144 const std::string &offsetText) const {
145 std::string baseExtra;
146 std::string baseType = Type::getCppType(&baseExtra);
147
Andreas Huberf9d49f12016-09-12 14:58:36 -0700148 const std::string childName = "_hidl_" + StripIndex(name) + "_child";
Andreas Huber881227d2016-08-02 14:20:21 -0700149 out << "size_t " << childName << ";\n\n";
150
151 emitReaderWriterEmbeddedForTypeName(
152 out,
153 name,
154 nameIsPointer,
155 parcelObj,
156 parcelObjIsPointer,
157 isReader,
158 mode,
159 parentName,
160 offsetText,
161 baseType,
162 childName);
163
164 if (!mElementType->needsEmbeddedReadWrite()) {
165 return;
166 }
167
168 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
169
170 baseType = mElementType->getCppType(&baseExtra);
171
Andreas Huberf9d49f12016-09-12 14:58:36 -0700172 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
173
174 out << "for (size_t "
175 << iteratorName
176 << " = 0; "
177 << iteratorName
178 << " < "
Andreas Huber881227d2016-08-02 14:20:21 -0700179 << nameDeref
Andreas Huberf9d49f12016-09-12 14:58:36 -0700180 << "size(); ++"
181 << iteratorName
182 << ") {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700183
184 out.indent();
185
186 mElementType->emitReaderWriterEmbedded(
187 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700188 depth + 1,
189 (nameIsPointer ? "(*" + name + ")" : name)
190 + "[" + iteratorName + "]",
Andreas Huber881227d2016-08-02 14:20:21 -0700191 false /* nameIsPointer */,
192 parcelObj,
193 parcelObjIsPointer,
194 isReader,
195 mode,
196 childName,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700197 iteratorName + " * sizeof(" + baseType + baseExtra + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700198
199 out.unindent();
200
201 out << "}\n\n";
202}
203
Andreas Huberf630bc82016-09-09 14:52:25 -0700204void VectorType::emitJavaReaderWriter(
205 Formatter &out,
206 const std::string &parcelObj,
207 const std::string &argName,
208 bool isReader) const {
209 if (mElementType->isCompoundType()) {
210 if (isReader) {
211 out << mElementType->getJavaType()
212 << ".readVectorFromParcel("
213 << parcelObj
214 << ");\n";
215 } else {
216 out << mElementType->getJavaType()
217 << ".writeVectorToParcel("
218 << parcelObj
219 << ", "
220 << argName
221 << ");\n";
222 }
223
224 return;
225 }
226
227 emitJavaReaderWriterWithSuffix(
228 out,
229 parcelObj,
230 argName,
231 isReader,
232 mElementType->getJavaSuffix() + "Vector",
233 "" /* extra */);
234}
235
Andreas Huber85eabdb2016-08-25 11:24:49 -0700236void VectorType::emitJavaFieldInitializer(
237 Formatter &out, const std::string &fieldName) const {
238 out << "final Vector<"
239 << mElementType->getJavaWrapperType()
240 << "> "
241 << fieldName
242 << " = new Vector();\n";
243}
244
245void VectorType::emitJavaFieldReaderWriter(
246 Formatter &out,
247 const std::string &blobName,
248 const std::string &fieldName,
249 const std::string &offset,
250 bool isReader) const {
Andreas Huberf630bc82016-09-09 14:52:25 -0700251 VectorType::EmitJavaFieldReaderWriterForElementType(
252 out, mElementType, blobName, fieldName, offset, isReader);
253}
254
255// static
256void VectorType::EmitJavaFieldReaderWriterForElementType(
257 Formatter &out,
258 const Type *elementType,
259 const std::string &blobName,
260 const std::string &fieldName,
261 const std::string &offset,
262 bool isReader) {
Andreas Huber85eabdb2016-08-25 11:24:49 -0700263 if (isReader) {
264 out << "{\n";
265 out.indent();
266
267 out << "HwBlob childBlob = parcel.readEmbeddedBuffer(\n";
268 out.indent();
269 out.indent();
270
271 out << blobName
272 << ".handle(),\n"
273 << offset
274 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */);\n\n";
275
276 out.unindent();
277 out.unindent();
278
279 out << fieldName << ".clear();\n";
280 out << "long _hidl_vec_size = "
281 << blobName
282 << ".getInt64("
283 << offset
284 << " + 8 /* offsetof(hidl_vec<T>, mSize) */);\n";
285
286 out << "for (int _hidl_index = 0; _hidl_index < _hidl_vec_size; "
287 << "++_hidl_index) {\n";
288
289 out.indent();
290
Andreas Huberf630bc82016-09-09 14:52:25 -0700291 elementType->emitJavaFieldInitializer(out, "_hidl_vec_element");
Andreas Huber85eabdb2016-08-25 11:24:49 -0700292
293 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700294 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700295
Andreas Huberf630bc82016-09-09 14:52:25 -0700296 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700297 out,
298 "childBlob",
299 "_hidl_vec_element",
300 "_hidl_index * " + std::to_string(elementSize),
301 true /* isReader */);
302
303 out << fieldName
304 << ".add(_hidl_vec_element);\n";
305
306 out.unindent();
307
308 out << "}\n";
309
310 out.unindent();
311 out << "}\n";
312
313 return;
314 }
315
316 out << "{\n";
317 out.indent();
318
319 out << "long _hidl_vec_size = "
320 << fieldName
321 << ".size();\n";
322
323 out << blobName
324 << ".putInt64("
325 << offset
326 << " + 8 /* offsetof(hidl_vec<T>, mSize) */, _hidl_vec_size);\n";
327
328 out << blobName
329 << ".putBool("
330 << offset
331 << " + 16 /* offsetof(hidl_vec<T>, mOwnsBuffer) */, false);\n";
332
333 size_t elementAlign, elementSize;
Andreas Huberf630bc82016-09-09 14:52:25 -0700334 elementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700335
336 // XXX make HwBlob constructor take a long instead of an int?
337 out << "HwBlob childBlob = new HwBlob((int)(_hidl_vec_size * "
338 << elementSize
339 << "));\n";
340
341 out << "for (int _hidl_index = 0; _hidl_index < _hidl_vec_size; "
342 << "++_hidl_index) {\n";
343
344 out.indent();
345
Andreas Huberf630bc82016-09-09 14:52:25 -0700346 elementType->emitJavaFieldReaderWriter(
Andreas Huber85eabdb2016-08-25 11:24:49 -0700347 out,
348 "childBlob",
349 fieldName + ".elementAt(_hidl_index)",
350 "_hidl_index * " + std::to_string(elementSize),
351 false /* isReader */);
352
353 out.unindent();
354
355 out << "}\n";
356
357 out << blobName
358 << ".putBlob("
359 << offset
360 << " + 0 /* offsetof(hidl_vec<T>, mBuffer) */, childBlob);\n";
361
362 out.unindent();
363 out << "}\n";
364}
365
Andreas Huber881227d2016-08-02 14:20:21 -0700366bool VectorType::needsEmbeddedReadWrite() const {
367 return true;
368}
369
370bool VectorType::resultNeedsDeref() const {
371 return true;
372}
373
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700374status_t VectorType::emitVtsTypeDeclarations(Formatter &out) const {
375 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
376 out.indent();
377 status_t err = mElementType->emitVtsTypeDeclarations(out);
378 if (err != OK) {
379 return err;
380 }
381 out.unindent();
382 out << "}\n";
383 return OK;
384}
385
Zhuoyao Zhang864c7712016-08-16 15:35:28 -0700386status_t VectorType::emitVtsAttributeType(Formatter &out) const {
387 out << "type: TYPE_VECTOR\n" << "vector_value: {\n";
388 out.indent();
389 status_t status = mElementType->emitVtsAttributeType(out);
390 if (status != OK) {
391 return status;
392 }
393 out.unindent();
394 out << "}\n";
395 return OK;
396}
397
Andreas Huber70a59e12016-08-16 12:57:01 -0700398bool VectorType::isJavaCompatible() const {
399 return mElementType->isJavaCompatible();
400}
401
Andreas Huber85eabdb2016-08-25 11:24:49 -0700402void VectorType::getAlignmentAndSize(size_t *align, size_t *size) const {
403 *align = 8; // hidl_vec<T>
404 *size = 24;
405}
406
Andreas Huberc9410c72016-07-28 12:18:40 -0700407} // namespace android
408