1 /*
2 * Copyright (C) 2018 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
17 #include <android/binder_parcel.h>
18 #include <android/binder_parcel_platform.h>
19 #include "parcel_internal.h"
20
21 #include "ibinder_internal.h"
22 #include "status_internal.h"
23
24 #include <limits>
25
26 #include <android-base/logging.h>
27 #include <android-base/unique_fd.h>
28 #include <binder/Parcel.h>
29 #include <binder/ParcelFileDescriptor.h>
30 #include <utils/Unicode.h>
31
32 using ::android::IBinder;
33 using ::android::Parcel;
34 using ::android::sp;
35 using ::android::status_t;
36 using ::android::base::unique_fd;
37 using ::android::os::ParcelFileDescriptor;
38
39 template <typename T>
40 using ContiguousArrayAllocator = bool (*)(void* arrayData, int32_t length, T** outBuffer);
41
42 template <typename T>
43 using ArrayAllocator = bool (*)(void* arrayData, int32_t length);
44 template <typename T>
45 using ArrayGetter = T (*)(const void* arrayData, size_t index);
46 template <typename T>
47 using ArraySetter = void (*)(void* arrayData, size_t index, T value);
48
WriteAndValidateArraySize(AParcel * parcel,bool isNullArray,int32_t length)49 binder_status_t WriteAndValidateArraySize(AParcel* parcel, bool isNullArray, int32_t length) {
50 // only -1 can be used to represent a null array
51 if (length < -1) return STATUS_BAD_VALUE;
52
53 if (!isNullArray && length < 0) {
54 LOG(ERROR) << __func__ << ": non-null array but length is " << length;
55 return STATUS_BAD_VALUE;
56 }
57 if (isNullArray && length > 0) {
58 LOG(ERROR) << __func__ << ": null buffer cannot be for size " << length << " array.";
59 return STATUS_BAD_VALUE;
60 }
61
62 Parcel* rawParcel = parcel->get();
63
64 status_t status = rawParcel->writeInt32(static_cast<int32_t>(length));
65 if (status != STATUS_OK) return PruneStatusT(status);
66
67 return STATUS_OK;
68 }
69
70 template <typename T>
WriteArray(AParcel * parcel,const T * array,int32_t length)71 binder_status_t WriteArray(AParcel* parcel, const T* array, int32_t length) {
72 binder_status_t status = WriteAndValidateArraySize(parcel, array == nullptr, length);
73 if (status != STATUS_OK) return status;
74 if (length <= 0) return STATUS_OK;
75
76 int32_t size = 0;
77 if (__builtin_smul_overflow(sizeof(T), length, &size)) return STATUS_NO_MEMORY;
78
79 void* const data = parcel->get()->writeInplace(size);
80 if (data == nullptr) return STATUS_NO_MEMORY;
81
82 memcpy(data, array, size);
83
84 return STATUS_OK;
85 }
86
87 // Each element in a char16_t array is converted to an int32_t (not packed).
88 template <>
WriteArray(AParcel * parcel,const char16_t * array,int32_t length)89 binder_status_t WriteArray<char16_t>(AParcel* parcel, const char16_t* array, int32_t length) {
90 binder_status_t status = WriteAndValidateArraySize(parcel, array == nullptr, length);
91 if (status != STATUS_OK) return status;
92 if (length <= 0) return STATUS_OK;
93
94 int32_t size = 0;
95 if (__builtin_smul_overflow(sizeof(char16_t), length, &size)) return STATUS_NO_MEMORY;
96
97 Parcel* rawParcel = parcel->get();
98
99 for (int32_t i = 0; i < length; i++) {
100 status = rawParcel->writeChar(array[i]);
101
102 if (status != STATUS_OK) return PruneStatusT(status);
103 }
104
105 return STATUS_OK;
106 }
107
108 template <typename T>
ReadArray(const AParcel * parcel,void * arrayData,ContiguousArrayAllocator<T> allocator)109 binder_status_t ReadArray(const AParcel* parcel, void* arrayData,
110 ContiguousArrayAllocator<T> allocator) {
111 const Parcel* rawParcel = parcel->get();
112
113 int32_t length;
114 status_t status = rawParcel->readInt32(&length);
115
116 if (status != STATUS_OK) return PruneStatusT(status);
117 if (length < -1) return STATUS_BAD_VALUE;
118
119 T* array;
120 if (!allocator(arrayData, length, &array)) return STATUS_NO_MEMORY;
121
122 if (length <= 0) return STATUS_OK;
123 if (array == nullptr) return STATUS_NO_MEMORY;
124
125 int32_t size = 0;
126 if (__builtin_smul_overflow(sizeof(T), length, &size)) return STATUS_NO_MEMORY;
127
128 const void* data = rawParcel->readInplace(size);
129 if (data == nullptr) return STATUS_NO_MEMORY;
130
131 memcpy(array, data, size);
132
133 return STATUS_OK;
134 }
135
136 // Each element in a char16_t array is converted to an int32_t (not packed)
137 template <>
ReadArray(const AParcel * parcel,void * arrayData,ContiguousArrayAllocator<char16_t> allocator)138 binder_status_t ReadArray<char16_t>(const AParcel* parcel, void* arrayData,
139 ContiguousArrayAllocator<char16_t> allocator) {
140 const Parcel* rawParcel = parcel->get();
141
142 int32_t length;
143 status_t status = rawParcel->readInt32(&length);
144
145 if (status != STATUS_OK) return PruneStatusT(status);
146 if (length < -1) return STATUS_BAD_VALUE;
147
148 char16_t* array;
149 if (!allocator(arrayData, length, &array)) return STATUS_NO_MEMORY;
150
151 if (length <= 0) return STATUS_OK;
152 if (array == nullptr) return STATUS_NO_MEMORY;
153
154 int32_t size = 0;
155 if (__builtin_smul_overflow(sizeof(char16_t), length, &size)) return STATUS_NO_MEMORY;
156
157 for (int32_t i = 0; i < length; i++) {
158 status = rawParcel->readChar(array + i);
159
160 if (status != STATUS_OK) return PruneStatusT(status);
161 }
162
163 return STATUS_OK;
164 }
165
166 template <typename T>
WriteArray(AParcel * parcel,const void * arrayData,int32_t length,ArrayGetter<T> getter,status_t (Parcel::* write)(T))167 binder_status_t WriteArray(AParcel* parcel, const void* arrayData, int32_t length,
168 ArrayGetter<T> getter, status_t (Parcel::*write)(T)) {
169 // we have no clue if arrayData represents a null object or not, we can only infer from length
170 bool arrayIsNull = length < 0;
171 binder_status_t status = WriteAndValidateArraySize(parcel, arrayIsNull, length);
172 if (status != STATUS_OK) return status;
173 if (length <= 0) return STATUS_OK;
174
175 Parcel* rawParcel = parcel->get();
176
177 for (int32_t i = 0; i < length; i++) {
178 status = (rawParcel->*write)(getter(arrayData, i));
179
180 if (status != STATUS_OK) return PruneStatusT(status);
181 }
182
183 return STATUS_OK;
184 }
185
186 template <typename T>
ReadArray(const AParcel * parcel,void * arrayData,ArrayAllocator<T> allocator,ArraySetter<T> setter,status_t (Parcel::* read)(T *)const)187 binder_status_t ReadArray(const AParcel* parcel, void* arrayData, ArrayAllocator<T> allocator,
188 ArraySetter<T> setter, status_t (Parcel::*read)(T*) const) {
189 const Parcel* rawParcel = parcel->get();
190
191 int32_t length;
192 status_t status = rawParcel->readInt32(&length);
193
194 if (status != STATUS_OK) return PruneStatusT(status);
195 if (length < -1) return STATUS_BAD_VALUE;
196
197 if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
198
199 if (length <= 0) return STATUS_OK;
200
201 for (int32_t i = 0; i < length; i++) {
202 T readTarget;
203 status = (rawParcel->*read)(&readTarget);
204 if (status != STATUS_OK) return PruneStatusT(status);
205
206 setter(arrayData, i, readTarget);
207 }
208
209 return STATUS_OK;
210 }
211
AParcel_delete(AParcel * parcel)212 void AParcel_delete(AParcel* parcel) {
213 delete parcel;
214 }
215
AParcel_setDataPosition(const AParcel * parcel,int32_t position)216 binder_status_t AParcel_setDataPosition(const AParcel* parcel, int32_t position) {
217 if (position < 0) {
218 return STATUS_BAD_VALUE;
219 }
220
221 parcel->get()->setDataPosition(position);
222 return STATUS_OK;
223 }
224
AParcel_getDataPosition(const AParcel * parcel)225 int32_t AParcel_getDataPosition(const AParcel* parcel) {
226 return parcel->get()->dataPosition();
227 }
228
AParcel_writeStrongBinder(AParcel * parcel,AIBinder * binder)229 binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
230 sp<IBinder> writeBinder = binder != nullptr ? binder->getBinder() : nullptr;
231 return parcel->get()->writeStrongBinder(writeBinder);
232 }
AParcel_readStrongBinder(const AParcel * parcel,AIBinder ** binder)233 binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder) {
234 sp<IBinder> readBinder = nullptr;
235 status_t status = parcel->get()->readNullableStrongBinder(&readBinder);
236 if (status != STATUS_OK) {
237 return PruneStatusT(status);
238 }
239 sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
240 AIBinder_incStrong(ret.get());
241 *binder = ret.get();
242 return PruneStatusT(status);
243 }
244
AParcel_writeParcelFileDescriptor(AParcel * parcel,int fd)245 binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) {
246 if (fd < 0) {
247 if (fd != -1) {
248 return STATUS_UNKNOWN_ERROR;
249 }
250 return PruneStatusT(parcel->get()->writeInt32(0)); // null
251 }
252 status_t status = parcel->get()->writeInt32(1); // not-null
253 if (status != STATUS_OK) return PruneStatusT(status);
254
255 status = parcel->get()->writeDupParcelFileDescriptor(fd);
256 return PruneStatusT(status);
257 }
258
AParcel_readParcelFileDescriptor(const AParcel * parcel,int * fd)259 binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd) {
260 std::unique_ptr<ParcelFileDescriptor> parcelFd;
261
262 status_t status = parcel->get()->readParcelable(&parcelFd);
263 if (status != STATUS_OK) return PruneStatusT(status);
264
265 if (parcelFd) {
266 *fd = parcelFd->release().release();
267 } else {
268 *fd = -1;
269 }
270
271 return STATUS_OK;
272 }
273
AParcel_writeStatusHeader(AParcel * parcel,const AStatus * status)274 binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status) {
275 return PruneStatusT(status->get()->writeToParcel(parcel->get()));
276 }
AParcel_readStatusHeader(const AParcel * parcel,AStatus ** status)277 binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status) {
278 ::android::binder::Status bstatus;
279 binder_status_t ret = PruneStatusT(bstatus.readFromParcel(*parcel->get()));
280 if (ret == STATUS_OK) {
281 *status = new AStatus(std::move(bstatus));
282 }
283 return PruneStatusT(ret);
284 }
285
AParcel_writeString(AParcel * parcel,const char * string,int32_t length)286 binder_status_t AParcel_writeString(AParcel* parcel, const char* string, int32_t length) {
287 if (string == nullptr) {
288 if (length != -1) {
289 LOG(WARNING) << __func__ << ": null string must be used with length == -1.";
290 return STATUS_BAD_VALUE;
291 }
292
293 status_t err = parcel->get()->writeInt32(-1);
294 return PruneStatusT(err);
295 }
296
297 if (length < 0) {
298 LOG(WARNING) << __func__ << ": Negative string length: " << length;
299 return STATUS_BAD_VALUE;
300 }
301
302 const uint8_t* str8 = (uint8_t*)string;
303 const ssize_t len16 = utf8_to_utf16_length(str8, length);
304
305 if (len16 < 0 || len16 >= std::numeric_limits<int32_t>::max()) {
306 LOG(WARNING) << __func__ << ": Invalid string length: " << len16;
307 return STATUS_BAD_VALUE;
308 }
309
310 status_t err = parcel->get()->writeInt32(len16);
311 if (err) {
312 return PruneStatusT(err);
313 }
314
315 void* str16 = parcel->get()->writeInplace((len16 + 1) * sizeof(char16_t));
316 if (str16 == nullptr) {
317 return STATUS_NO_MEMORY;
318 }
319
320 utf8_to_utf16(str8, length, (char16_t*)str16, (size_t)len16 + 1);
321
322 return STATUS_OK;
323 }
324
AParcel_readString(const AParcel * parcel,void * stringData,AParcel_stringAllocator allocator)325 binder_status_t AParcel_readString(const AParcel* parcel, void* stringData,
326 AParcel_stringAllocator allocator) {
327 size_t len16;
328 const char16_t* str16 = parcel->get()->readString16Inplace(&len16);
329
330 if (str16 == nullptr) {
331 if (allocator(stringData, -1, nullptr)) {
332 return STATUS_OK;
333 }
334
335 return STATUS_UNEXPECTED_NULL;
336 }
337
338 ssize_t len8;
339
340 if (len16 == 0) {
341 len8 = 1;
342 } else {
343 len8 = utf16_to_utf8_length(str16, len16) + 1;
344 }
345
346 if (len8 <= 0 || len8 > std::numeric_limits<int32_t>::max()) {
347 LOG(WARNING) << __func__ << ": Invalid string length: " << len8;
348 return STATUS_BAD_VALUE;
349 }
350
351 char* str8;
352 bool success = allocator(stringData, len8, &str8);
353
354 if (!success || str8 == nullptr) {
355 LOG(WARNING) << __func__ << ": AParcel_stringAllocator failed to allocate.";
356 return STATUS_NO_MEMORY;
357 }
358
359 utf16_to_utf8(str16, len16, str8, len8);
360
361 return STATUS_OK;
362 }
363
AParcel_writeStringArray(AParcel * parcel,const void * arrayData,int32_t length,AParcel_stringArrayElementGetter getter)364 binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, int32_t length,
365 AParcel_stringArrayElementGetter getter) {
366 // we have no clue if arrayData represents a null object or not, we can only infer from length
367 bool arrayIsNull = length < 0;
368 binder_status_t status = WriteAndValidateArraySize(parcel, arrayIsNull, length);
369 if (status != STATUS_OK) return status;
370 if (length <= 0) return STATUS_OK;
371
372 for (int32_t i = 0; i < length; i++) {
373 int32_t elementLength = 0;
374 const char* str = getter(arrayData, i, &elementLength);
375 if (str == nullptr && elementLength != -1) return STATUS_BAD_VALUE;
376
377 binder_status_t status = AParcel_writeString(parcel, str, elementLength);
378 if (status != STATUS_OK) return status;
379 }
380
381 return STATUS_OK;
382 }
383
384 // This implements AParcel_stringAllocator for a string using an array, index, and element
385 // allocator.
386 struct StringArrayElementAllocationAdapter {
387 void* arrayData; // stringData from the NDK
388 int32_t index; // index into the string array
389 AParcel_stringArrayElementAllocator elementAllocator;
390
AllocatorStringArrayElementAllocationAdapter391 static bool Allocator(void* stringData, int32_t length, char** buffer) {
392 StringArrayElementAllocationAdapter* adapter =
393 static_cast<StringArrayElementAllocationAdapter*>(stringData);
394 return adapter->elementAllocator(adapter->arrayData, adapter->index, length, buffer);
395 }
396 };
397
AParcel_readStringArray(const AParcel * parcel,void * arrayData,AParcel_stringArrayAllocator allocator,AParcel_stringArrayElementAllocator elementAllocator)398 binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData,
399 AParcel_stringArrayAllocator allocator,
400 AParcel_stringArrayElementAllocator elementAllocator) {
401 const Parcel* rawParcel = parcel->get();
402
403 int32_t length;
404 status_t status = rawParcel->readInt32(&length);
405
406 if (status != STATUS_OK) return PruneStatusT(status);
407 if (length < -1) return STATUS_BAD_VALUE;
408
409 if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
410
411 if (length == -1) return STATUS_OK; // null string array
412
413 StringArrayElementAllocationAdapter adapter{
414 .arrayData = arrayData,
415 .index = 0,
416 .elementAllocator = elementAllocator,
417 };
418
419 for (; adapter.index < length; adapter.index++) {
420 binder_status_t status = AParcel_readString(parcel, static_cast<void*>(&adapter),
421 StringArrayElementAllocationAdapter::Allocator);
422
423 if (status != STATUS_OK) return status;
424 }
425
426 return STATUS_OK;
427 }
428
AParcel_writeParcelableArray(AParcel * parcel,const void * arrayData,int32_t length,AParcel_writeParcelableElement elementWriter)429 binder_status_t AParcel_writeParcelableArray(AParcel* parcel, const void* arrayData, int32_t length,
430 AParcel_writeParcelableElement elementWriter) {
431 // we have no clue if arrayData represents a null object or not, we can only infer from length
432 bool arrayIsNull = length < 0;
433 binder_status_t status = WriteAndValidateArraySize(parcel, arrayIsNull, length);
434 if (status != STATUS_OK) return status;
435 if (length <= 0) return STATUS_OK;
436
437 for (int32_t i = 0; i < length; i++) {
438 binder_status_t status = elementWriter(parcel, arrayData, i);
439 if (status != STATUS_OK) return status;
440 }
441
442 return STATUS_OK;
443 }
444
AParcel_readParcelableArray(const AParcel * parcel,void * arrayData,AParcel_parcelableArrayAllocator allocator,AParcel_readParcelableElement elementReader)445 binder_status_t AParcel_readParcelableArray(const AParcel* parcel, void* arrayData,
446 AParcel_parcelableArrayAllocator allocator,
447 AParcel_readParcelableElement elementReader) {
448 const Parcel* rawParcel = parcel->get();
449
450 int32_t length;
451 status_t status = rawParcel->readInt32(&length);
452
453 if (status != STATUS_OK) return PruneStatusT(status);
454 if (length < -1) return STATUS_BAD_VALUE;
455
456 if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
457
458 if (length == -1) return STATUS_OK; // null array
459
460 for (int32_t i = 0; i < length; i++) {
461 binder_status_t status = elementReader(parcel, arrayData, i);
462 if (status != STATUS_OK) return status;
463 }
464
465 return STATUS_OK;
466 }
467
468 // See gen_parcel_helper.py. These auto-generated read/write methods use the same types for
469 // libbinder and this library.
470 // @START
AParcel_writeInt32(AParcel * parcel,int32_t value)471 binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) {
472 status_t status = parcel->get()->writeInt32(value);
473 return PruneStatusT(status);
474 }
475
AParcel_writeUint32(AParcel * parcel,uint32_t value)476 binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value) {
477 status_t status = parcel->get()->writeUint32(value);
478 return PruneStatusT(status);
479 }
480
AParcel_writeInt64(AParcel * parcel,int64_t value)481 binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) {
482 status_t status = parcel->get()->writeInt64(value);
483 return PruneStatusT(status);
484 }
485
AParcel_writeUint64(AParcel * parcel,uint64_t value)486 binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value) {
487 status_t status = parcel->get()->writeUint64(value);
488 return PruneStatusT(status);
489 }
490
AParcel_writeFloat(AParcel * parcel,float value)491 binder_status_t AParcel_writeFloat(AParcel* parcel, float value) {
492 status_t status = parcel->get()->writeFloat(value);
493 return PruneStatusT(status);
494 }
495
AParcel_writeDouble(AParcel * parcel,double value)496 binder_status_t AParcel_writeDouble(AParcel* parcel, double value) {
497 status_t status = parcel->get()->writeDouble(value);
498 return PruneStatusT(status);
499 }
500
AParcel_writeBool(AParcel * parcel,bool value)501 binder_status_t AParcel_writeBool(AParcel* parcel, bool value) {
502 status_t status = parcel->get()->writeBool(value);
503 return PruneStatusT(status);
504 }
505
AParcel_writeChar(AParcel * parcel,char16_t value)506 binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value) {
507 status_t status = parcel->get()->writeChar(value);
508 return PruneStatusT(status);
509 }
510
AParcel_writeByte(AParcel * parcel,int8_t value)511 binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value) {
512 status_t status = parcel->get()->writeByte(value);
513 return PruneStatusT(status);
514 }
515
AParcel_readInt32(const AParcel * parcel,int32_t * value)516 binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) {
517 status_t status = parcel->get()->readInt32(value);
518 return PruneStatusT(status);
519 }
520
AParcel_readUint32(const AParcel * parcel,uint32_t * value)521 binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value) {
522 status_t status = parcel->get()->readUint32(value);
523 return PruneStatusT(status);
524 }
525
AParcel_readInt64(const AParcel * parcel,int64_t * value)526 binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) {
527 status_t status = parcel->get()->readInt64(value);
528 return PruneStatusT(status);
529 }
530
AParcel_readUint64(const AParcel * parcel,uint64_t * value)531 binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value) {
532 status_t status = parcel->get()->readUint64(value);
533 return PruneStatusT(status);
534 }
535
AParcel_readFloat(const AParcel * parcel,float * value)536 binder_status_t AParcel_readFloat(const AParcel* parcel, float* value) {
537 status_t status = parcel->get()->readFloat(value);
538 return PruneStatusT(status);
539 }
540
AParcel_readDouble(const AParcel * parcel,double * value)541 binder_status_t AParcel_readDouble(const AParcel* parcel, double* value) {
542 status_t status = parcel->get()->readDouble(value);
543 return PruneStatusT(status);
544 }
545
AParcel_readBool(const AParcel * parcel,bool * value)546 binder_status_t AParcel_readBool(const AParcel* parcel, bool* value) {
547 status_t status = parcel->get()->readBool(value);
548 return PruneStatusT(status);
549 }
550
AParcel_readChar(const AParcel * parcel,char16_t * value)551 binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value) {
552 status_t status = parcel->get()->readChar(value);
553 return PruneStatusT(status);
554 }
555
AParcel_readByte(const AParcel * parcel,int8_t * value)556 binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value) {
557 status_t status = parcel->get()->readByte(value);
558 return PruneStatusT(status);
559 }
560
AParcel_writeInt32Array(AParcel * parcel,const int32_t * arrayData,int32_t length)561 binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* arrayData, int32_t length) {
562 return WriteArray<int32_t>(parcel, arrayData, length);
563 }
564
AParcel_writeUint32Array(AParcel * parcel,const uint32_t * arrayData,int32_t length)565 binder_status_t AParcel_writeUint32Array(AParcel* parcel, const uint32_t* arrayData,
566 int32_t length) {
567 return WriteArray<uint32_t>(parcel, arrayData, length);
568 }
569
AParcel_writeInt64Array(AParcel * parcel,const int64_t * arrayData,int32_t length)570 binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* arrayData, int32_t length) {
571 return WriteArray<int64_t>(parcel, arrayData, length);
572 }
573
AParcel_writeUint64Array(AParcel * parcel,const uint64_t * arrayData,int32_t length)574 binder_status_t AParcel_writeUint64Array(AParcel* parcel, const uint64_t* arrayData,
575 int32_t length) {
576 return WriteArray<uint64_t>(parcel, arrayData, length);
577 }
578
AParcel_writeFloatArray(AParcel * parcel,const float * arrayData,int32_t length)579 binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* arrayData, int32_t length) {
580 return WriteArray<float>(parcel, arrayData, length);
581 }
582
AParcel_writeDoubleArray(AParcel * parcel,const double * arrayData,int32_t length)583 binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* arrayData, int32_t length) {
584 return WriteArray<double>(parcel, arrayData, length);
585 }
586
AParcel_writeBoolArray(AParcel * parcel,const void * arrayData,int32_t length,AParcel_boolArrayGetter getter)587 binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData, int32_t length,
588 AParcel_boolArrayGetter getter) {
589 return WriteArray<bool>(parcel, arrayData, length, getter, &Parcel::writeBool);
590 }
591
AParcel_writeCharArray(AParcel * parcel,const char16_t * arrayData,int32_t length)592 binder_status_t AParcel_writeCharArray(AParcel* parcel, const char16_t* arrayData, int32_t length) {
593 return WriteArray<char16_t>(parcel, arrayData, length);
594 }
595
AParcel_writeByteArray(AParcel * parcel,const int8_t * arrayData,int32_t length)596 binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData, int32_t length) {
597 return WriteArray<int8_t>(parcel, arrayData, length);
598 }
599
AParcel_readInt32Array(const AParcel * parcel,void * arrayData,AParcel_int32ArrayAllocator allocator)600 binder_status_t AParcel_readInt32Array(const AParcel* parcel, void* arrayData,
601 AParcel_int32ArrayAllocator allocator) {
602 return ReadArray<int32_t>(parcel, arrayData, allocator);
603 }
604
AParcel_readUint32Array(const AParcel * parcel,void * arrayData,AParcel_uint32ArrayAllocator allocator)605 binder_status_t AParcel_readUint32Array(const AParcel* parcel, void* arrayData,
606 AParcel_uint32ArrayAllocator allocator) {
607 return ReadArray<uint32_t>(parcel, arrayData, allocator);
608 }
609
AParcel_readInt64Array(const AParcel * parcel,void * arrayData,AParcel_int64ArrayAllocator allocator)610 binder_status_t AParcel_readInt64Array(const AParcel* parcel, void* arrayData,
611 AParcel_int64ArrayAllocator allocator) {
612 return ReadArray<int64_t>(parcel, arrayData, allocator);
613 }
614
AParcel_readUint64Array(const AParcel * parcel,void * arrayData,AParcel_uint64ArrayAllocator allocator)615 binder_status_t AParcel_readUint64Array(const AParcel* parcel, void* arrayData,
616 AParcel_uint64ArrayAllocator allocator) {
617 return ReadArray<uint64_t>(parcel, arrayData, allocator);
618 }
619
AParcel_readFloatArray(const AParcel * parcel,void * arrayData,AParcel_floatArrayAllocator allocator)620 binder_status_t AParcel_readFloatArray(const AParcel* parcel, void* arrayData,
621 AParcel_floatArrayAllocator allocator) {
622 return ReadArray<float>(parcel, arrayData, allocator);
623 }
624
AParcel_readDoubleArray(const AParcel * parcel,void * arrayData,AParcel_doubleArrayAllocator allocator)625 binder_status_t AParcel_readDoubleArray(const AParcel* parcel, void* arrayData,
626 AParcel_doubleArrayAllocator allocator) {
627 return ReadArray<double>(parcel, arrayData, allocator);
628 }
629
AParcel_readBoolArray(const AParcel * parcel,void * arrayData,AParcel_boolArrayAllocator allocator,AParcel_boolArraySetter setter)630 binder_status_t AParcel_readBoolArray(const AParcel* parcel, void* arrayData,
631 AParcel_boolArrayAllocator allocator,
632 AParcel_boolArraySetter setter) {
633 return ReadArray<bool>(parcel, arrayData, allocator, setter, &Parcel::readBool);
634 }
635
AParcel_readCharArray(const AParcel * parcel,void * arrayData,AParcel_charArrayAllocator allocator)636 binder_status_t AParcel_readCharArray(const AParcel* parcel, void* arrayData,
637 AParcel_charArrayAllocator allocator) {
638 return ReadArray<char16_t>(parcel, arrayData, allocator);
639 }
640
AParcel_readByteArray(const AParcel * parcel,void * arrayData,AParcel_byteArrayAllocator allocator)641 binder_status_t AParcel_readByteArray(const AParcel* parcel, void* arrayData,
642 AParcel_byteArrayAllocator allocator) {
643 return ReadArray<int8_t>(parcel, arrayData, allocator);
644 }
645
AParcel_getAllowFds(const AParcel * parcel)646 bool AParcel_getAllowFds(const AParcel* parcel) {
647 return parcel->get()->allowFds();
648 }
649
650 // @END
651