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