• 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 <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_markSensitive(const AParcel * parcel)229 void AParcel_markSensitive(const AParcel* parcel) {
230     return parcel->get()->markSensitive();
231 }
232 
AParcel_writeStrongBinder(AParcel * parcel,AIBinder * binder)233 binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
234     sp<IBinder> writeBinder = binder != nullptr ? binder->getBinder() : nullptr;
235     return parcel->get()->writeStrongBinder(writeBinder);
236 }
AParcel_readStrongBinder(const AParcel * parcel,AIBinder ** binder)237 binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder) {
238     sp<IBinder> readBinder = nullptr;
239     status_t status = parcel->get()->readNullableStrongBinder(&readBinder);
240     if (status != STATUS_OK) {
241         return PruneStatusT(status);
242     }
243     sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
244     AIBinder_incStrong(ret.get());
245     *binder = ret.get();
246     return PruneStatusT(status);
247 }
248 
AParcel_writeParcelFileDescriptor(AParcel * parcel,int fd)249 binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) {
250     if (fd < 0) {
251         if (fd != -1) {
252             return STATUS_UNKNOWN_ERROR;
253         }
254         return PruneStatusT(parcel->get()->writeInt32(0));  // null
255     }
256     status_t status = parcel->get()->writeInt32(1);  // not-null
257     if (status != STATUS_OK) return PruneStatusT(status);
258 
259     status = parcel->get()->writeDupParcelFileDescriptor(fd);
260     return PruneStatusT(status);
261 }
262 
AParcel_readParcelFileDescriptor(const AParcel * parcel,int * fd)263 binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd) {
264     std::optional<ParcelFileDescriptor> parcelFd;
265 
266     status_t status = parcel->get()->readParcelable(&parcelFd);
267     if (status != STATUS_OK) return PruneStatusT(status);
268 
269     if (parcelFd) {
270         *fd = parcelFd->release().release();
271     } else {
272         *fd = -1;
273     }
274 
275     return STATUS_OK;
276 }
277 
AParcel_writeStatusHeader(AParcel * parcel,const AStatus * status)278 binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status) {
279     return PruneStatusT(status->get().writeToParcel(parcel->get()));
280 }
AParcel_readStatusHeader(const AParcel * parcel,AStatus ** status)281 binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status) {
282     ::android::binder::Status bstatus;
283     binder_status_t ret = PruneStatusT(bstatus.readFromParcel(*parcel->get()));
284     if (ret == STATUS_OK) {
285         *status = new AStatus(std::move(bstatus));
286     }
287     return PruneStatusT(ret);
288 }
289 
AParcel_writeString(AParcel * parcel,const char * string,int32_t length)290 binder_status_t AParcel_writeString(AParcel* parcel, const char* string, int32_t length) {
291     if (string == nullptr) {
292         if (length != -1) {
293             LOG(WARNING) << __func__ << ": null string must be used with length == -1.";
294             return STATUS_BAD_VALUE;
295         }
296 
297         status_t err = parcel->get()->writeInt32(-1);
298         return PruneStatusT(err);
299     }
300 
301     if (length < 0) {
302         LOG(WARNING) << __func__ << ": Negative string length: " << length;
303         return STATUS_BAD_VALUE;
304     }
305 
306     const uint8_t* str8 = (uint8_t*)string;
307     const ssize_t len16 = utf8_to_utf16_length(str8, length);
308 
309     if (len16 < 0 || len16 >= std::numeric_limits<int32_t>::max()) {
310         LOG(WARNING) << __func__ << ": Invalid string length: " << len16;
311         return STATUS_BAD_VALUE;
312     }
313 
314     status_t err = parcel->get()->writeInt32(len16);
315     if (err) {
316         return PruneStatusT(err);
317     }
318 
319     void* str16 = parcel->get()->writeInplace((len16 + 1) * sizeof(char16_t));
320     if (str16 == nullptr) {
321         return STATUS_NO_MEMORY;
322     }
323 
324     utf8_to_utf16(str8, length, (char16_t*)str16, (size_t)len16 + 1);
325 
326     return STATUS_OK;
327 }
328 
AParcel_readString(const AParcel * parcel,void * stringData,AParcel_stringAllocator allocator)329 binder_status_t AParcel_readString(const AParcel* parcel, void* stringData,
330                                    AParcel_stringAllocator allocator) {
331     size_t len16;
332     const char16_t* str16 = parcel->get()->readString16Inplace(&len16);
333 
334     if (str16 == nullptr) {
335         if (allocator(stringData, -1, nullptr)) {
336             return STATUS_OK;
337         }
338 
339         return STATUS_UNEXPECTED_NULL;
340     }
341 
342     ssize_t len8;
343 
344     if (len16 == 0) {
345         len8 = 1;
346     } else {
347         len8 = utf16_to_utf8_length(str16, len16) + 1;
348     }
349 
350     if (len8 <= 0 || len8 > std::numeric_limits<int32_t>::max()) {
351         LOG(WARNING) << __func__ << ": Invalid string length: " << len8;
352         return STATUS_BAD_VALUE;
353     }
354 
355     char* str8;
356     bool success = allocator(stringData, len8, &str8);
357 
358     if (!success || str8 == nullptr) {
359         LOG(WARNING) << __func__ << ": AParcel_stringAllocator failed to allocate.";
360         return STATUS_NO_MEMORY;
361     }
362 
363     utf16_to_utf8(str16, len16, str8, len8);
364 
365     return STATUS_OK;
366 }
367 
AParcel_writeStringArray(AParcel * parcel,const void * arrayData,int32_t length,AParcel_stringArrayElementGetter getter)368 binder_status_t AParcel_writeStringArray(AParcel* parcel, const void* arrayData, int32_t length,
369                                          AParcel_stringArrayElementGetter getter) {
370     // we have no clue if arrayData represents a null object or not, we can only infer from length
371     bool arrayIsNull = length < 0;
372     binder_status_t status = WriteAndValidateArraySize(parcel, arrayIsNull, length);
373     if (status != STATUS_OK) return status;
374     if (length <= 0) return STATUS_OK;
375 
376     for (int32_t i = 0; i < length; i++) {
377         int32_t elementLength = 0;
378         const char* str = getter(arrayData, i, &elementLength);
379         if (str == nullptr && elementLength != -1) return STATUS_BAD_VALUE;
380 
381         binder_status_t status = AParcel_writeString(parcel, str, elementLength);
382         if (status != STATUS_OK) return status;
383     }
384 
385     return STATUS_OK;
386 }
387 
388 // This implements AParcel_stringAllocator for a string using an array, index, and element
389 // allocator.
390 struct StringArrayElementAllocationAdapter {
391     void* arrayData;  // stringData from the NDK
392     int32_t index;    // index into the string array
393     AParcel_stringArrayElementAllocator elementAllocator;
394 
AllocatorStringArrayElementAllocationAdapter395     static bool Allocator(void* stringData, int32_t length, char** buffer) {
396         StringArrayElementAllocationAdapter* adapter =
397                 static_cast<StringArrayElementAllocationAdapter*>(stringData);
398         return adapter->elementAllocator(adapter->arrayData, adapter->index, length, buffer);
399     }
400 };
401 
AParcel_readStringArray(const AParcel * parcel,void * arrayData,AParcel_stringArrayAllocator allocator,AParcel_stringArrayElementAllocator elementAllocator)402 binder_status_t AParcel_readStringArray(const AParcel* parcel, void* arrayData,
403                                         AParcel_stringArrayAllocator allocator,
404                                         AParcel_stringArrayElementAllocator elementAllocator) {
405     const Parcel* rawParcel = parcel->get();
406 
407     int32_t length;
408     status_t status = rawParcel->readInt32(&length);
409 
410     if (status != STATUS_OK) return PruneStatusT(status);
411     if (length < -1) return STATUS_BAD_VALUE;
412 
413     if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
414 
415     if (length == -1) return STATUS_OK;  // null string array
416 
417     StringArrayElementAllocationAdapter adapter{
418             .arrayData = arrayData,
419             .index = 0,
420             .elementAllocator = elementAllocator,
421     };
422 
423     for (; adapter.index < length; adapter.index++) {
424         binder_status_t status = AParcel_readString(parcel, static_cast<void*>(&adapter),
425                                                     StringArrayElementAllocationAdapter::Allocator);
426 
427         if (status != STATUS_OK) return status;
428     }
429 
430     return STATUS_OK;
431 }
432 
AParcel_writeParcelableArray(AParcel * parcel,const void * arrayData,int32_t length,AParcel_writeParcelableElement elementWriter)433 binder_status_t AParcel_writeParcelableArray(AParcel* parcel, const void* arrayData, int32_t length,
434                                              AParcel_writeParcelableElement elementWriter) {
435     // we have no clue if arrayData represents a null object or not, we can only infer from length
436     bool arrayIsNull = length < 0;
437     binder_status_t status = WriteAndValidateArraySize(parcel, arrayIsNull, length);
438     if (status != STATUS_OK) return status;
439     if (length <= 0) return STATUS_OK;
440 
441     for (int32_t i = 0; i < length; i++) {
442         binder_status_t status = elementWriter(parcel, arrayData, i);
443         if (status != STATUS_OK) return status;
444     }
445 
446     return STATUS_OK;
447 }
448 
AParcel_readParcelableArray(const AParcel * parcel,void * arrayData,AParcel_parcelableArrayAllocator allocator,AParcel_readParcelableElement elementReader)449 binder_status_t AParcel_readParcelableArray(const AParcel* parcel, void* arrayData,
450                                             AParcel_parcelableArrayAllocator allocator,
451                                             AParcel_readParcelableElement elementReader) {
452     const Parcel* rawParcel = parcel->get();
453 
454     int32_t length;
455     status_t status = rawParcel->readInt32(&length);
456 
457     if (status != STATUS_OK) return PruneStatusT(status);
458     if (length < -1) return STATUS_BAD_VALUE;
459 
460     if (!allocator(arrayData, length)) return STATUS_NO_MEMORY;
461 
462     if (length == -1) return STATUS_OK;  // null array
463 
464     for (int32_t i = 0; i < length; i++) {
465         binder_status_t status = elementReader(parcel, arrayData, i);
466         if (status != STATUS_OK) return status;
467     }
468 
469     return STATUS_OK;
470 }
471 
472 // See gen_parcel_helper.py. These auto-generated read/write methods use the same types for
473 // libbinder and this library.
474 // @START
AParcel_writeInt32(AParcel * parcel,int32_t value)475 binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) {
476     status_t status = parcel->get()->writeInt32(value);
477     return PruneStatusT(status);
478 }
479 
AParcel_writeUint32(AParcel * parcel,uint32_t value)480 binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value) {
481     status_t status = parcel->get()->writeUint32(value);
482     return PruneStatusT(status);
483 }
484 
AParcel_writeInt64(AParcel * parcel,int64_t value)485 binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) {
486     status_t status = parcel->get()->writeInt64(value);
487     return PruneStatusT(status);
488 }
489 
AParcel_writeUint64(AParcel * parcel,uint64_t value)490 binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value) {
491     status_t status = parcel->get()->writeUint64(value);
492     return PruneStatusT(status);
493 }
494 
AParcel_writeFloat(AParcel * parcel,float value)495 binder_status_t AParcel_writeFloat(AParcel* parcel, float value) {
496     status_t status = parcel->get()->writeFloat(value);
497     return PruneStatusT(status);
498 }
499 
AParcel_writeDouble(AParcel * parcel,double value)500 binder_status_t AParcel_writeDouble(AParcel* parcel, double value) {
501     status_t status = parcel->get()->writeDouble(value);
502     return PruneStatusT(status);
503 }
504 
AParcel_writeBool(AParcel * parcel,bool value)505 binder_status_t AParcel_writeBool(AParcel* parcel, bool value) {
506     status_t status = parcel->get()->writeBool(value);
507     return PruneStatusT(status);
508 }
509 
AParcel_writeChar(AParcel * parcel,char16_t value)510 binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value) {
511     status_t status = parcel->get()->writeChar(value);
512     return PruneStatusT(status);
513 }
514 
AParcel_writeByte(AParcel * parcel,int8_t value)515 binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value) {
516     status_t status = parcel->get()->writeByte(value);
517     return PruneStatusT(status);
518 }
519 
AParcel_readInt32(const AParcel * parcel,int32_t * value)520 binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) {
521     status_t status = parcel->get()->readInt32(value);
522     return PruneStatusT(status);
523 }
524 
AParcel_readUint32(const AParcel * parcel,uint32_t * value)525 binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value) {
526     status_t status = parcel->get()->readUint32(value);
527     return PruneStatusT(status);
528 }
529 
AParcel_readInt64(const AParcel * parcel,int64_t * value)530 binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) {
531     status_t status = parcel->get()->readInt64(value);
532     return PruneStatusT(status);
533 }
534 
AParcel_readUint64(const AParcel * parcel,uint64_t * value)535 binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value) {
536     status_t status = parcel->get()->readUint64(value);
537     return PruneStatusT(status);
538 }
539 
AParcel_readFloat(const AParcel * parcel,float * value)540 binder_status_t AParcel_readFloat(const AParcel* parcel, float* value) {
541     status_t status = parcel->get()->readFloat(value);
542     return PruneStatusT(status);
543 }
544 
AParcel_readDouble(const AParcel * parcel,double * value)545 binder_status_t AParcel_readDouble(const AParcel* parcel, double* value) {
546     status_t status = parcel->get()->readDouble(value);
547     return PruneStatusT(status);
548 }
549 
AParcel_readBool(const AParcel * parcel,bool * value)550 binder_status_t AParcel_readBool(const AParcel* parcel, bool* value) {
551     status_t status = parcel->get()->readBool(value);
552     return PruneStatusT(status);
553 }
554 
AParcel_readChar(const AParcel * parcel,char16_t * value)555 binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value) {
556     status_t status = parcel->get()->readChar(value);
557     return PruneStatusT(status);
558 }
559 
AParcel_readByte(const AParcel * parcel,int8_t * value)560 binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value) {
561     status_t status = parcel->get()->readByte(value);
562     return PruneStatusT(status);
563 }
564 
AParcel_writeInt32Array(AParcel * parcel,const int32_t * arrayData,int32_t length)565 binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* arrayData, int32_t length) {
566     return WriteArray<int32_t>(parcel, arrayData, length);
567 }
568 
AParcel_writeUint32Array(AParcel * parcel,const uint32_t * arrayData,int32_t length)569 binder_status_t AParcel_writeUint32Array(AParcel* parcel, const uint32_t* arrayData,
570                                          int32_t length) {
571     return WriteArray<uint32_t>(parcel, arrayData, length);
572 }
573 
AParcel_writeInt64Array(AParcel * parcel,const int64_t * arrayData,int32_t length)574 binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* arrayData, int32_t length) {
575     return WriteArray<int64_t>(parcel, arrayData, length);
576 }
577 
AParcel_writeUint64Array(AParcel * parcel,const uint64_t * arrayData,int32_t length)578 binder_status_t AParcel_writeUint64Array(AParcel* parcel, const uint64_t* arrayData,
579                                          int32_t length) {
580     return WriteArray<uint64_t>(parcel, arrayData, length);
581 }
582 
AParcel_writeFloatArray(AParcel * parcel,const float * arrayData,int32_t length)583 binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* arrayData, int32_t length) {
584     return WriteArray<float>(parcel, arrayData, length);
585 }
586 
AParcel_writeDoubleArray(AParcel * parcel,const double * arrayData,int32_t length)587 binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* arrayData, int32_t length) {
588     return WriteArray<double>(parcel, arrayData, length);
589 }
590 
AParcel_writeBoolArray(AParcel * parcel,const void * arrayData,int32_t length,AParcel_boolArrayGetter getter)591 binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData, int32_t length,
592                                        AParcel_boolArrayGetter getter) {
593     return WriteArray<bool>(parcel, arrayData, length, getter, &Parcel::writeBool);
594 }
595 
AParcel_writeCharArray(AParcel * parcel,const char16_t * arrayData,int32_t length)596 binder_status_t AParcel_writeCharArray(AParcel* parcel, const char16_t* arrayData, int32_t length) {
597     return WriteArray<char16_t>(parcel, arrayData, length);
598 }
599 
AParcel_writeByteArray(AParcel * parcel,const int8_t * arrayData,int32_t length)600 binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* arrayData, int32_t length) {
601     return WriteArray<int8_t>(parcel, arrayData, length);
602 }
603 
AParcel_readInt32Array(const AParcel * parcel,void * arrayData,AParcel_int32ArrayAllocator allocator)604 binder_status_t AParcel_readInt32Array(const AParcel* parcel, void* arrayData,
605                                        AParcel_int32ArrayAllocator allocator) {
606     return ReadArray<int32_t>(parcel, arrayData, allocator);
607 }
608 
AParcel_readUint32Array(const AParcel * parcel,void * arrayData,AParcel_uint32ArrayAllocator allocator)609 binder_status_t AParcel_readUint32Array(const AParcel* parcel, void* arrayData,
610                                         AParcel_uint32ArrayAllocator allocator) {
611     return ReadArray<uint32_t>(parcel, arrayData, allocator);
612 }
613 
AParcel_readInt64Array(const AParcel * parcel,void * arrayData,AParcel_int64ArrayAllocator allocator)614 binder_status_t AParcel_readInt64Array(const AParcel* parcel, void* arrayData,
615                                        AParcel_int64ArrayAllocator allocator) {
616     return ReadArray<int64_t>(parcel, arrayData, allocator);
617 }
618 
AParcel_readUint64Array(const AParcel * parcel,void * arrayData,AParcel_uint64ArrayAllocator allocator)619 binder_status_t AParcel_readUint64Array(const AParcel* parcel, void* arrayData,
620                                         AParcel_uint64ArrayAllocator allocator) {
621     return ReadArray<uint64_t>(parcel, arrayData, allocator);
622 }
623 
AParcel_readFloatArray(const AParcel * parcel,void * arrayData,AParcel_floatArrayAllocator allocator)624 binder_status_t AParcel_readFloatArray(const AParcel* parcel, void* arrayData,
625                                        AParcel_floatArrayAllocator allocator) {
626     return ReadArray<float>(parcel, arrayData, allocator);
627 }
628 
AParcel_readDoubleArray(const AParcel * parcel,void * arrayData,AParcel_doubleArrayAllocator allocator)629 binder_status_t AParcel_readDoubleArray(const AParcel* parcel, void* arrayData,
630                                         AParcel_doubleArrayAllocator allocator) {
631     return ReadArray<double>(parcel, arrayData, allocator);
632 }
633 
AParcel_readBoolArray(const AParcel * parcel,void * arrayData,AParcel_boolArrayAllocator allocator,AParcel_boolArraySetter setter)634 binder_status_t AParcel_readBoolArray(const AParcel* parcel, void* arrayData,
635                                       AParcel_boolArrayAllocator allocator,
636                                       AParcel_boolArraySetter setter) {
637     return ReadArray<bool>(parcel, arrayData, allocator, setter, &Parcel::readBool);
638 }
639 
AParcel_readCharArray(const AParcel * parcel,void * arrayData,AParcel_charArrayAllocator allocator)640 binder_status_t AParcel_readCharArray(const AParcel* parcel, void* arrayData,
641                                       AParcel_charArrayAllocator allocator) {
642     return ReadArray<char16_t>(parcel, arrayData, allocator);
643 }
644 
AParcel_readByteArray(const AParcel * parcel,void * arrayData,AParcel_byteArrayAllocator allocator)645 binder_status_t AParcel_readByteArray(const AParcel* parcel, void* arrayData,
646                                       AParcel_byteArrayAllocator allocator) {
647     return ReadArray<int8_t>(parcel, arrayData, allocator);
648 }
649 
AParcel_getAllowFds(const AParcel * parcel)650 bool AParcel_getAllowFds(const AParcel* parcel) {
651     return parcel->get()->allowFds();
652 }
653 
AParcel_reset(AParcel * parcel)654 binder_status_t AParcel_reset(AParcel* parcel) {
655     parcel->get()->freeData();
656     return STATUS_OK;
657 }
658 
AParcel_getDataSize(const AParcel * parcel)659 int32_t AParcel_getDataSize(const AParcel* parcel) {
660     return parcel->get()->dataSize();
661 }
662 
AParcel_appendFrom(const AParcel * from,AParcel * to,int32_t start,int32_t size)663 binder_status_t AParcel_appendFrom(const AParcel* from, AParcel* to, int32_t start, int32_t size) {
664     status_t status = to->get()->appendFrom(from->get(), start, size);
665     return PruneStatusT(status);
666 }
667 
AParcel_create()668 AParcel* AParcel_create() {
669     return new AParcel(nullptr);
670 }
671 
672 // @END
673