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