blob: ec849bc58904dc48278b20d9683dc2e9c788ed20 [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 "ArrayType.h"
18
Andreas Huber881227d2016-08-02 14:20:21 -070019#include <android-base/logging.h>
Timur Iskhakove8ee6a02017-09-06 11:42:10 -070020#include <hidl-util/Formatter.h>
21#include <iostream>
Andreas Huber881227d2016-08-02 14:20:21 -070022
Yifan Hongf24fa852016-09-23 11:03:15 -070023#include "ConstantExpression.h"
24
Andreas Huberc9410c72016-07-28 12:18:40 -070025namespace android {
26
Timur Iskhakov63f39902017-08-29 15:47:29 -070027ArrayType::ArrayType(const Reference<Type>& elementType, ConstantExpression* size, Scope* parent)
Timur Iskhakov0737c2a2017-08-31 10:57:28 -070028 : Type(parent), mElementType(elementType), mSizes{size} {
Timur Iskhakov505316c2017-08-05 03:38:59 +000029 CHECK(!elementType.isEmptyReference());
Andreas Huberc9410c72016-07-28 12:18:40 -070030}
31
Yifan Hongbd33e382016-11-02 13:30:17 -070032void ArrayType::appendDimension(ConstantExpression *size) {
Yifan Hong5706a432016-11-02 09:44:18 -070033 mSizes.push_back(size);
Yifan Hongbd33e382016-11-02 13:30:17 -070034}
35
Andreas Huberf03332a2016-09-22 15:35:43 -070036size_t ArrayType::countDimensions() const {
37 return mSizes.size();
38}
39
Andreas Huber709b62d2016-09-19 11:21:18 -070040bool ArrayType::isArray() const {
41 return true;
42}
43
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -070044bool ArrayType::deepCanCheckEquality(std::unordered_set<const Type*>* visited) const {
45 return mElementType->canCheckEquality(visited);
Yifan Hongc6752dc2016-12-20 14:00:14 -080046}
47
Timur Iskhakov24e605b2017-08-30 14:02:55 -070048const Type* ArrayType::getElementType() const {
Timur Iskhakovb3f8bcb2017-08-30 15:33:29 -070049 return mElementType.get();
Andreas Huberf03332a2016-09-22 15:35:43 -070050}
51
Steven Moreland0ecc7b82017-07-19 12:59:23 -070052std::string ArrayType::typeName() const {
53 if (dimension() == 1) {
54 return "array of " + mElementType->typeName();
55 }
56
57 return std::to_string(dimension()) + "d array of " + mElementType->typeName();
58}
59
Timur Iskhakovb58f4182017-08-29 15:19:24 -070060std::vector<const Reference<Type>*> ArrayType::getReferences() const {
61 return {&mElementType};
Timur Iskhakov33431e62017-08-21 17:31:23 -070062}
63
Timur Iskhakovb58f4182017-08-29 15:19:24 -070064std::vector<const ConstantExpression*> ArrayType::getConstantExpressions() const {
65 std::vector<const ConstantExpression*> ret;
66 ret.insert(ret.end(), mSizes.begin(), mSizes.end());
67 return ret;
Timur Iskhakovcec46c42017-08-09 00:22:02 -070068}
69
Timur Iskhakov0737c2a2017-08-31 10:57:28 -070070status_t ArrayType::resolveInheritance() {
71 // Resolve for typedefs
72 while (mElementType->isArray()) {
73 ArrayType* innerArray = static_cast<ArrayType*>(mElementType.get());
74 mSizes.insert(mSizes.end(), innerArray->mSizes.begin(), innerArray->mSizes.end());
75 mElementType = innerArray->mElementType;
76 }
77 return Type::resolveInheritance();
78}
79
Timur Iskhakovcec46c42017-08-09 00:22:02 -070080status_t ArrayType::validate() const {
Timur Iskhakov0737c2a2017-08-31 10:57:28 -070081 CHECK(!mElementType->isArray());
82
Steven Moreland7df0f392018-10-31 13:23:22 -070083 if (mElementType->isInterface()) {
Timur Iskhakovcec46c42017-08-09 00:22:02 -070084 std::cerr << "ERROR: Arrays of interface types are not supported"
85 << " at " << mElementType.location() << "\n";
86
87 return UNKNOWN_ERROR;
88 }
89 return Type::validate();
90}
91
Steven Moreland979e0992016-09-07 09:18:08 -070092std::string ArrayType::getCppType(StorageMode mode,
Steven Moreland979e0992016-09-07 09:18:08 -070093 bool specifyNamespaces) const {
Yifan Hong3b320f82016-11-01 15:15:54 -070094 const std::string base = mElementType->getCppStackType(specifyNamespaces);
Andreas Huber881227d2016-08-02 14:20:21 -070095
Steven Morelandc46e9842016-11-02 13:21:26 -070096 std::string space = specifyNamespaces ? "::android::hardware::" : "";
97 std::string arrayType = space + "hidl_array<" + base;
Andreas Huberf03332a2016-09-22 15:35:43 -070098
99 for (size_t i = 0; i < mSizes.size(); ++i) {
Steven Morelandf21962d2018-08-09 12:44:40 -0700100 arrayType += ", " + mSizes[i]->cppValue();
Andreas Huber709b62d2016-09-19 11:21:18 -0700101 }
102
Andreas Huberf03332a2016-09-22 15:35:43 -0700103 arrayType += ">";
Andreas Huber881227d2016-08-02 14:20:21 -0700104
105 switch (mode) {
106 case StorageMode_Stack:
Andreas Huberf03332a2016-09-22 15:35:43 -0700107 return arrayType;
Andreas Huber881227d2016-08-02 14:20:21 -0700108
109 case StorageMode_Argument:
Andreas Huberf03332a2016-09-22 15:35:43 -0700110 return "const " + arrayType + "&";
111
Andreas Huber881227d2016-08-02 14:20:21 -0700112 case StorageMode_Result:
Andreas Huberf03332a2016-09-22 15:35:43 -0700113 return "const " + arrayType + "*";
Andreas Huber881227d2016-08-02 14:20:21 -0700114 }
Andreas Huberf03332a2016-09-22 15:35:43 -0700115
116 CHECK(!"Should not be here");
Andreas Huber881227d2016-08-02 14:20:21 -0700117}
118
Yifan Hong30b5d1f2017-04-03 12:19:25 -0700119std::string ArrayType::getInternalDataCppType() const {
120 std::string result = mElementType->getCppStackType();
121 for (size_t i = 0; i < mSizes.size(); ++i) {
122 result += "[";
123 result += mSizes[i]->cppValue();
124 result += "]";
125 }
126 return result;
127}
128
Yifan Hong4ed13472016-11-02 10:44:11 -0700129std::string ArrayType::getJavaType(bool forInitializer) const {
130 std::string base =
131 mElementType->getJavaType(forInitializer);
Andreas Huber709b62d2016-09-19 11:21:18 -0700132
Yifan Hongf24fa852016-09-23 11:03:15 -0700133 for (size_t i = 0; i < mSizes.size(); ++i) {
Yifan Hong4ed13472016-11-02 10:44:11 -0700134 base += "[";
Andreas Huber709b62d2016-09-19 11:21:18 -0700135
136 if (forInitializer) {
Yifan Hong4ed13472016-11-02 10:44:11 -0700137 base += mSizes[i]->javaValue();
Steven Morelandf21962d2018-08-09 12:44:40 -0700138 } else {
139 base += "/* " + mSizes[i]->expression() + " */";
Yifan Hong5706a432016-11-02 09:44:18 -0700140 }
Yifan Hongf24fa852016-09-23 11:03:15 -0700141
Yifan Hong4ed13472016-11-02 10:44:11 -0700142 base += "]";
Andreas Huber4c865b72016-09-14 15:26:27 -0700143 }
Andreas Huber4c865b72016-09-14 15:26:27 -0700144
145 return base;
Andreas Huber2831d512016-08-15 09:33:47 -0700146}
147
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700148std::string ArrayType::getVtsType() const {
149 return "TYPE_ARRAY";
150}
151
Andreas Huber881227d2016-08-02 14:20:21 -0700152void ArrayType::emitReaderWriter(
153 Formatter &out,
154 const std::string &name,
155 const std::string &parcelObj,
156 bool parcelObjIsPointer,
157 bool isReader,
158 ErrorMode mode) const {
Yifan Hong3b320f82016-11-01 15:15:54 -0700159 std::string baseType = mElementType->getCppStackType();
Andreas Huber881227d2016-08-02 14:20:21 -0700160
Iliyan Malchev549e2592016-08-10 08:59:12 -0700161 const std::string parentName = "_hidl_" + name + "_parent";
Andreas Huber881227d2016-08-02 14:20:21 -0700162
163 out << "size_t " << parentName << ";\n\n";
164
165 const std::string parcelObjDeref =
166 parcelObj + (parcelObjIsPointer ? "->" : ".");
167
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700168 size_t numArrayElements = 1;
169 for (auto size : mSizes) {
170 numArrayElements *= size->castSizeT();
171 }
Andreas Huber881227d2016-08-02 14:20:21 -0700172 if (isReader) {
Martijn Coenen6a082c62017-01-11 12:47:02 +0100173 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700174 << parcelObjDeref
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700175 << "readBuffer("
176 << numArrayElements
177 << " * sizeof("
178 << baseType
179 << "), &"
Andreas Huber881227d2016-08-02 14:20:21 -0700180 << parentName
Martijn Coenen6a082c62017-01-11 12:47:02 +0100181 << ", "
182 << " reinterpret_cast<const void **>("
183 << "&" << name
184 << "));\n\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700185
Martijn Coenen6a082c62017-01-11 12:47:02 +0100186 handleError(out, mode);
Andreas Huber881227d2016-08-02 14:20:21 -0700187 } else {
Andreas Huberf03332a2016-09-22 15:35:43 -0700188
Iliyan Malchev549e2592016-08-10 08:59:12 -0700189 out << "_hidl_err = "
Andreas Huber881227d2016-08-02 14:20:21 -0700190 << parcelObjDeref
191 << "writeBuffer("
192 << name
Andreas Huberf03332a2016-09-22 15:35:43 -0700193 << ".data(), "
194 << numArrayElements
195 << " * sizeof("
Andreas Huber881227d2016-08-02 14:20:21 -0700196 << baseType
197 << "), &"
198 << parentName
199 << ");\n";
200
201 handleError(out, mode);
202 }
203
204 emitReaderWriterEmbedded(
205 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700206 0 /* depth */,
Andreas Huber881227d2016-08-02 14:20:21 -0700207 name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700208 name /* sanitizedName */,
Andreas Huber881227d2016-08-02 14:20:21 -0700209 isReader /* nameIsPointer */,
210 parcelObj,
211 parcelObjIsPointer,
212 isReader,
213 mode,
214 parentName,
215 "0 /* parentOffset */");
216}
217
218void ArrayType::emitReaderWriterEmbedded(
219 Formatter &out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700220 size_t depth,
Andreas Huber881227d2016-08-02 14:20:21 -0700221 const std::string &name,
Yifan Hongbe2a3732016-10-05 13:33:41 -0700222 const std::string &sanitizedName,
Andreas Huber881227d2016-08-02 14:20:21 -0700223 bool nameIsPointer,
224 const std::string &parcelObj,
225 bool parcelObjIsPointer,
226 bool isReader,
227 ErrorMode mode,
228 const std::string &parentName,
229 const std::string &offsetText) const {
230 if (!mElementType->needsEmbeddedReadWrite()) {
231 return;
232 }
233
234 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
235
Yifan Hong3b320f82016-11-01 15:15:54 -0700236 std::string baseType = mElementType->getCppStackType();
Andreas Huber881227d2016-08-02 14:20:21 -0700237
Andreas Huberf9d49f12016-09-12 14:58:36 -0700238 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
239
240 out << "for (size_t "
241 << iteratorName
242 << " = 0; "
243 << iteratorName
244 << " < "
Yifan Hongbf459bc2016-08-23 16:50:37 -0700245 << dimension()
Andreas Huberf9d49f12016-09-12 14:58:36 -0700246 << "; ++"
247 << iteratorName
248 << ") {\n";
Andreas Huber881227d2016-08-02 14:20:21 -0700249
250 out.indent();
251
252 mElementType->emitReaderWriterEmbedded(
253 out,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700254 depth + 1,
Andreas Huberf03332a2016-09-22 15:35:43 -0700255 nameDeref + "data()[" + iteratorName + "]",
Yifan Hongbe2a3732016-10-05 13:33:41 -0700256 sanitizedName + "_indexed",
Andreas Huber881227d2016-08-02 14:20:21 -0700257 false /* nameIsPointer */,
258 parcelObj,
259 parcelObjIsPointer,
260 isReader,
261 mode,
262 parentName,
Andreas Huberf9d49f12016-09-12 14:58:36 -0700263 offsetText
264 + " + " + iteratorName + " * sizeof("
265 + baseType
Andreas Huberf9d49f12016-09-12 14:58:36 -0700266 + ")");
Andreas Huber881227d2016-08-02 14:20:21 -0700267
268 out.unindent();
269
270 out << "}\n\n";
271}
272
Yifan Hongbf459bc2016-08-23 16:50:37 -0700273void ArrayType::emitResolveReferences(
274 Formatter &out,
275 const std::string &name,
276 bool nameIsPointer,
277 const std::string &parcelObj,
278 bool parcelObjIsPointer,
279 bool isReader,
280 ErrorMode mode) const {
281 emitResolveReferencesEmbedded(
282 out,
283 0 /* depth */,
284 name,
285 name /* sanitizedName */,
286 nameIsPointer,
287 parcelObj,
288 parcelObjIsPointer,
289 isReader,
290 mode,
291 "_hidl_" + name + "_parent",
292 "0 /* parentOffset */");
293}
294
295void ArrayType::emitResolveReferencesEmbedded(
296 Formatter &out,
297 size_t depth,
298 const std::string &name,
299 const std::string &sanitizedName,
300 bool nameIsPointer,
301 const std::string &parcelObj,
302 bool parcelObjIsPointer,
303 bool isReader,
304 ErrorMode mode,
305 const std::string &parentName,
306 const std::string &offsetText) const {
307 CHECK(needsResolveReferences() && mElementType->needsResolveReferences());
308
309 const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
310
Yifan Hong3b320f82016-11-01 15:15:54 -0700311 std::string baseType = mElementType->getCppStackType();
Yifan Hongbf459bc2016-08-23 16:50:37 -0700312
313 std::string iteratorName = "_hidl_index_" + std::to_string(depth);
314
315 out << "for (size_t "
316 << iteratorName
317 << " = 0; "
318 << iteratorName
319 << " < "
320 << dimension()
321 << "; ++"
322 << iteratorName
323 << ") {\n";
324
325 out.indent();
326
327 mElementType->emitResolveReferencesEmbedded(
328 out,
329 depth + 1,
330 nameDeref + "data()[" + iteratorName + "]",
331 sanitizedName + "_indexed",
332 false /* nameIsPointer */,
333 parcelObj,
334 parcelObjIsPointer,
335 isReader,
336 mode,
337 parentName,
338 offsetText + " + " + iteratorName + " * sizeof("
339 + baseType
340 + ")");
341
342 out.unindent();
343
344 out << "}\n\n";
345}
346
Yifan Honge45b5302017-02-22 10:49:07 -0800347void ArrayType::emitJavaDump(
348 Formatter &out,
349 const std::string &streamName,
350 const std::string &name) const {
351 out << streamName << ".append(java.util.Arrays."
352 << (countDimensions() > 1 ? "deepToString" : "toString")
353 << "("
Nirav Atre66842a92018-06-28 18:14:13 -0700354 << name
355 << "));\n";
Yifan Honge45b5302017-02-22 10:49:07 -0800356}
357
358
Andreas Huber881227d2016-08-02 14:20:21 -0700359bool ArrayType::needsEmbeddedReadWrite() const {
360 return mElementType->needsEmbeddedReadWrite();
361}
362
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700363bool ArrayType::deepNeedsResolveReferences(std::unordered_set<const Type*>* visited) const {
364 if (mElementType->needsResolveReferences(visited)) {
365 return true;
366 }
367 return Type::deepNeedsResolveReferences(visited);
Yifan Hongbf459bc2016-08-23 16:50:37 -0700368}
369
Andreas Huberf03332a2016-09-22 15:35:43 -0700370bool ArrayType::resultNeedsDeref() const {
371 return true;
372}
373
Andreas Huber2831d512016-08-15 09:33:47 -0700374void ArrayType::emitJavaReaderWriter(
375 Formatter &out,
376 const std::string &parcelObj,
377 const std::string &argName,
378 bool isReader) const {
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700379 size_t align, size;
380 getAlignmentAndSize(&align, &size);
381
Andreas Huber709b62d2016-09-19 11:21:18 -0700382 if (isReader) {
Andreas Huber709b62d2016-09-19 11:21:18 -0700383 out << "new "
Yifan Hong4ed13472016-11-02 10:44:11 -0700384 << getJavaType(true /* forInitializer */)
Andreas Huber709b62d2016-09-19 11:21:18 -0700385 << ";\n";
Andreas Huberf630bc82016-09-09 14:52:25 -0700386 }
387
Andreas Huber709b62d2016-09-19 11:21:18 -0700388 out << "{\n";
389 out.indent();
390
Yifan Hong1af73532016-11-09 14:32:58 -0800391 out << "android.os.HwBlob _hidl_blob = ";
Andreas Huber709b62d2016-09-19 11:21:18 -0700392
393 if (isReader) {
394 out << parcelObj
Martijn Coenenb2a861c2017-04-18 15:54:25 -0700395 << ".readBuffer("
396 << size
397 << " /* size */);\n";
Andreas Huber709b62d2016-09-19 11:21:18 -0700398 } else {
Yifan Hong1af73532016-11-09 14:32:58 -0800399 out << "new android.os.HwBlob("
Andreas Huber709b62d2016-09-19 11:21:18 -0700400 << size
401 << " /* size */);\n";
402 }
403
404 emitJavaFieldReaderWriter(
Andreas Huber2831d512016-08-15 09:33:47 -0700405 out,
Andreas Huber709b62d2016-09-19 11:21:18 -0700406 0 /* depth */,
Andreas Huber2831d512016-08-15 09:33:47 -0700407 parcelObj,
Andreas Huber709b62d2016-09-19 11:21:18 -0700408 "_hidl_blob",
Andreas Huber2831d512016-08-15 09:33:47 -0700409 argName,
Andreas Huber709b62d2016-09-19 11:21:18 -0700410 "0 /* offset */",
411 isReader);
412
413 if (!isReader) {
414 out << parcelObj << ".writeBuffer(_hidl_blob);\n";
415 }
416
417 out.unindent();
418 out << "}\n";
Andreas Huber2831d512016-08-15 09:33:47 -0700419}
420
Andreas Huber85eabdb2016-08-25 11:24:49 -0700421void ArrayType::emitJavaFieldInitializer(
422 Formatter &out, const std::string &fieldName) const {
Nirav Atre66842a92018-06-28 18:14:13 -0700423 const std::string typeName = getJavaType(false /* forInitializer */);
Nirav Atre1d565622018-07-13 15:41:21 -0700424 const std::string fieldDeclaration = typeName + " " + fieldName;
Andreas Huber4c865b72016-09-14 15:26:27 -0700425
Nirav Atre66842a92018-06-28 18:14:13 -0700426 emitJavaFieldDefaultInitialValue(out, fieldDeclaration);
427}
428
429void ArrayType::emitJavaFieldDefaultInitialValue(
430 Formatter &out, const std::string &declaredFieldName) const {
431 out << declaredFieldName
Andreas Huber85eabdb2016-08-25 11:24:49 -0700432 << " = new "
Nirav Atre66842a92018-06-28 18:14:13 -0700433 << getJavaType(true /* forInitializer */)
Andreas Huber4c865b72016-09-14 15:26:27 -0700434 << ";\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700435}
436
437void ArrayType::emitJavaFieldReaderWriter(
438 Formatter &out,
Andreas Huber4c865b72016-09-14 15:26:27 -0700439 size_t depth,
Andreas Huber709b62d2016-09-19 11:21:18 -0700440 const std::string &parcelName,
Andreas Huber85eabdb2016-08-25 11:24:49 -0700441 const std::string &blobName,
442 const std::string &fieldName,
443 const std::string &offset,
444 bool isReader) const {
Andreas Huber90e8fc22016-09-21 16:36:15 -0700445 out << "{\n";
446 out.indent();
447
Andreas Huber709b62d2016-09-19 11:21:18 -0700448 std::string offsetName = "_hidl_array_offset_" + std::to_string(depth);
449 out << "long " << offsetName << " = " << offset << ";\n";
Andreas Huber4c865b72016-09-14 15:26:27 -0700450
Andreas Hubera23f1ae2017-10-31 11:50:18 -0700451 const bool isPrimitiveArray = mElementType->isScalar();
452
453 /* If the element type corresponds to a Java primitive type we can optimize
454 the innermost loop by copying a linear range of memory instead of doing
455 a per-element copy. As a result the outer nested loop does not include
456 the final dimension. */
457 const size_t loopDimensions = mSizes.size() - (isPrimitiveArray ? 1 : 0);
458
Andreas Huber709b62d2016-09-19 11:21:18 -0700459 std::string indexString;
Andreas Hubera23f1ae2017-10-31 11:50:18 -0700460 for (size_t dim = 0; dim < loopDimensions; ++dim) {
Andreas Huber709b62d2016-09-19 11:21:18 -0700461 std::string iteratorName =
462 "_hidl_index_" + std::to_string(depth) + "_" + std::to_string(dim);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700463
Andreas Huber709b62d2016-09-19 11:21:18 -0700464 out << "for (int "
465 << iteratorName
466 << " = 0; "
467 << iteratorName
468 << " < "
Yifan Hong5706a432016-11-02 09:44:18 -0700469 << mSizes[dim]->javaValue()
Andreas Huber709b62d2016-09-19 11:21:18 -0700470 << "; ++"
471 << iteratorName
472 << ") {\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700473
Andreas Huber709b62d2016-09-19 11:21:18 -0700474 out.indent();
475
476 indexString += "[" + iteratorName + "]";
477 }
478
Nirav Atre66842a92018-06-28 18:14:13 -0700479 const bool isIndexed = (loopDimensions > 0);
480 const std::string fieldNameWithCast = isIndexed
481 ? "(" + getJavaTypeCast(fieldName) + ")" + indexString
482 : getJavaTypeCast(fieldName);
Andreas Huber709b62d2016-09-19 11:21:18 -0700483
Nirav Atre66842a92018-06-28 18:14:13 -0700484 if (isReader && mElementType->isCompoundType()) {
485 mElementType->emitJavaFieldDefaultInitialValue(out, fieldNameWithCast);
Andreas Huber709b62d2016-09-19 11:21:18 -0700486 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700487
Andreas Hubera23f1ae2017-10-31 11:50:18 -0700488 if (!isPrimitiveArray) {
489 mElementType->emitJavaFieldReaderWriter(
490 out,
491 depth + 1,
492 parcelName,
493 blobName,
Nirav Atre66842a92018-06-28 18:14:13 -0700494 fieldNameWithCast,
Andreas Hubera23f1ae2017-10-31 11:50:18 -0700495 offsetName,
496 isReader);
Andreas Huber85eabdb2016-08-25 11:24:49 -0700497
Andreas Hubera23f1ae2017-10-31 11:50:18 -0700498 size_t elementAlign, elementSize;
499 mElementType->getAlignmentAndSize(&elementAlign, &elementSize);
Andreas Huber709b62d2016-09-19 11:21:18 -0700500
Andreas Hubera23f1ae2017-10-31 11:50:18 -0700501 out << offsetName << " += " << std::to_string(elementSize) << ";\n";
502 } else {
503 if (isReader) {
504 out << blobName
505 << ".copyTo"
506 << mElementType->getJavaSuffix()
507 << "Array("
508 << offsetName
509 << ", "
Nirav Atre66842a92018-06-28 18:14:13 -0700510 << fieldNameWithCast
Andreas Hubera23f1ae2017-10-31 11:50:18 -0700511 << ", "
512 << mSizes.back()->javaValue()
513 << " /* size */);\n";
514 } else {
Andreas Huber2dafb922018-08-03 13:54:41 -0700515 std::string elemName = "_hidl_array_item_" + std::to_string(depth);
516
517 out << mElementType->getJavaType(false /* forInitializer */)
518 << "[] "
519 << elemName
520 << " = "
521 << fieldNameWithCast
522 << ";\n\n";
523
524 out << "if ("
525 << elemName
526 << " == null || "
527 << elemName
528 << ".length != "
529 << mSizes.back()->javaValue()
530 << ") {\n";
531
532 out.indent();
533
534 out << "throw new IllegalArgumentException("
535 << "\"Array element is not of the expected length\");\n";
536
537 out.unindent();
538 out << "}\n\n";
539
Andreas Hubera23f1ae2017-10-31 11:50:18 -0700540 out << blobName
541 << ".put"
542 << mElementType->getJavaSuffix()
543 << "Array("
544 << offsetName
545 << ", "
Andreas Huber2dafb922018-08-03 13:54:41 -0700546 << elemName
Andreas Hubera23f1ae2017-10-31 11:50:18 -0700547 << ");\n";
548 }
Andreas Huber709b62d2016-09-19 11:21:18 -0700549
Andreas Hubera23f1ae2017-10-31 11:50:18 -0700550 size_t elementAlign, elementSize;
551 mElementType->getAlignmentAndSize(&elementAlign, &elementSize);
552
553 out << offsetName
554 << " += "
555 << mSizes.back()->javaValue()
556 << " * "
557 << elementSize
558 << ";\n";
559 }
560
561 for (size_t dim = 0; dim < loopDimensions; ++dim) {
Andreas Huber709b62d2016-09-19 11:21:18 -0700562 out.unindent();
563 out << "}\n";
564 }
Andreas Huber90e8fc22016-09-21 16:36:15 -0700565
566 out.unindent();
567 out << "}\n";
Andreas Huber85eabdb2016-08-25 11:24:49 -0700568}
569
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800570void ArrayType::emitVtsTypeDeclarations(Formatter& out) const {
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700571 out << "type: " << getVtsType() << "\n";
Steven Morelandf21962d2018-08-09 12:44:40 -0700572 out << "vector_size: " << mSizes[0]->rawValue() << "\n";
Zhuoyao Zhangc5ea9f52016-10-06 15:05:39 -0700573 out << "vector_value: {\n";
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700574 out.indent();
Zhuoyao Zhangeb355ee2016-10-20 16:00:40 -0700575 // Simple array case.
576 if (mSizes.size() == 1) {
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800577 mElementType->emitVtsTypeDeclarations(out);
Zhuoyao Zhangeb355ee2016-10-20 16:00:40 -0700578 } else { // Multi-dimension array case.
579 for (size_t index = 1; index < mSizes.size(); index++) {
580 out << "type: " << getVtsType() << "\n";
Steven Morelandf21962d2018-08-09 12:44:40 -0700581 out << "vector_size: " << mSizes[index]->rawValue() << "\n";
Zhuoyao Zhangeb355ee2016-10-20 16:00:40 -0700582 out << "vector_value: {\n";
583 out.indent();
Zhuoyao Zhangeb355ee2016-10-20 16:00:40 -0700584 if (index == mSizes.size() - 1) {
Steven Moreland6ec9eb92018-02-16 14:21:49 -0800585 mElementType->emitVtsTypeDeclarations(out);
Zhuoyao Zhangeb355ee2016-10-20 16:00:40 -0700586 }
587 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700588 }
Zhuoyao Zhangeb355ee2016-10-20 16:00:40 -0700589 for (size_t index = 0; index < mSizes.size(); index++) {
590 out.unindent();
591 out << "}\n";
592 }
Zhuoyao Zhang5158db42016-08-10 10:25:20 -0700593}
594
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700595bool ArrayType::deepIsJavaCompatible(std::unordered_set<const Type*>* visited) const {
596 if (!mElementType->isJavaCompatible(visited)) {
597 return false;
598 }
599 return Type::deepIsJavaCompatible(visited);
Andreas Huber70a59e12016-08-16 12:57:01 -0700600}
601
Timur Iskhakov5dc72fe2017-09-07 23:13:44 -0700602bool ArrayType::deepContainsPointer(std::unordered_set<const Type*>* visited) const {
603 if (mElementType->containsPointer(visited)) {
604 return true;
605 }
606 return Type::deepContainsPointer(visited);
Andreas Huber60d3b222017-03-30 09:10:56 -0700607}
608
Andreas Huber85eabdb2016-08-25 11:24:49 -0700609void ArrayType::getAlignmentAndSize(size_t *align, size_t *size) const {
610 mElementType->getAlignmentAndSize(align, size);
611
Andreas Huber709b62d2016-09-19 11:21:18 -0700612 for (auto sizeInDimension : mSizes) {
Yifan Hong5706a432016-11-02 09:44:18 -0700613 (*size) *= sizeInDimension->castSizeT();
Andreas Huber709b62d2016-09-19 11:21:18 -0700614 }
Andreas Huber85eabdb2016-08-25 11:24:49 -0700615}
616
Yifan Hongbf459bc2016-08-23 16:50:37 -0700617size_t ArrayType::dimension() const {
618 size_t numArrayElements = 1;
619 for (auto size : mSizes) {
Yifan Hong5706a432016-11-02 09:44:18 -0700620 numArrayElements *= size->castSizeT();
Yifan Hongbf459bc2016-08-23 16:50:37 -0700621 }
622 return numArrayElements;
623}
624
Andreas Huberc9410c72016-07-28 12:18:40 -0700625} // namespace android
626