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