blob: 5279b549ceda075dc3584f7659632a1bd4ef1bfd [file] [log] [blame]
Steven Moreland2e87adc2018-08-20 19:47:00 -07001/*
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>
Steven Moreland4d5ad492018-09-13 12:49:16 -070018#include "parcel_internal.h"
Steven Moreland2e87adc2018-08-20 19:47:00 -070019
Steven Moreland4d5ad492018-09-13 12:49:16 -070020#include "ibinder_internal.h"
Steven Moreland5d62e442018-09-13 15:01:02 -070021#include "status_internal.h"
Steven Moreland2e87adc2018-08-20 19:47:00 -070022
Steven Moreland7b06f592018-10-03 19:25:32 -070023#include <limits>
24
25#include <android-base/logging.h>
Steven Moreland2e87adc2018-08-20 19:47:00 -070026#include <binder/Parcel.h>
Steven Moreland7b06f592018-10-03 19:25:32 -070027#include <utils/Unicode.h>
Steven Moreland2e87adc2018-08-20 19:47:00 -070028
29using ::android::IBinder;
30using ::android::Parcel;
31using ::android::sp;
Steven Moreland5d62e442018-09-13 15:01:02 -070032using ::android::status_t;
Steven Moreland2e87adc2018-08-20 19:47:00 -070033
Steven Morelanda8845662018-10-12 11:53:03 -070034template <typename T>
35using ContiguousArrayGetter = T* (*)(void* arrayData);
36template <typename T>
37using ArrayGetter = T (*)(const void* arrayData, size_t index);
38template <typename T>
39using ArraySetter = void (*)(void* arrayData, size_t index, T value);
40
41template <typename T>
42binder_status_t WriteArray(AParcel* parcel, const T* array, size_t length) {
43 if (length > std::numeric_limits<int32_t>::max()) return STATUS_BAD_VALUE;
44
45 Parcel* rawParcel = parcel->get();
46
47 status_t status = rawParcel->writeInt32(static_cast<int32_t>(length));
48 if (status != STATUS_OK) return PruneStatusT(status);
49
50 int32_t size = 0;
51 if (__builtin_smul_overflow(sizeof(T), length, &size)) return STATUS_NO_MEMORY;
52
53 void* const data = rawParcel->writeInplace(size);
54 if (data == nullptr) return STATUS_NO_MEMORY;
55
56 memcpy(data, array, size);
57
58 return STATUS_OK;
59}
60
61// Each element in a char16_t array is converted to an int32_t (not packed).
62template <>
63binder_status_t WriteArray<char16_t>(AParcel* parcel, const char16_t* array, size_t length) {
64 if (length > std::numeric_limits<int32_t>::max()) return STATUS_BAD_VALUE;
65
66 Parcel* rawParcel = parcel->get();
67
68 status_t status = rawParcel->writeInt32(static_cast<int32_t>(length));
69 if (status != STATUS_OK) return PruneStatusT(status);
70
71 int32_t size = 0;
72 if (__builtin_smul_overflow(sizeof(char16_t), length, &size)) return STATUS_NO_MEMORY;
73
74 for (int32_t i = 0; i < length; i++) {
75 status = rawParcel->writeChar(array[i]);
76
77 if (status != STATUS_OK) return PruneStatusT(status);
78 }
79
80 return STATUS_OK;
81}
82
83template <typename T>
84binder_status_t ReadArray(const AParcel* parcel, void** arrayData,
85 AParcel_arrayReallocator reallocator, ContiguousArrayGetter<T> getter) {
86 const Parcel* rawParcel = parcel->get();
87
88 int32_t length;
89 status_t status = rawParcel->readInt32(&length);
90
91 if (status != STATUS_OK) return PruneStatusT(status);
92 if (length < 0) return STATUS_UNEXPECTED_NULL;
93
94 *arrayData = reallocator(*arrayData, length);
95 if (*arrayData == nullptr) return STATUS_NO_MEMORY;
96
97 if (length == 0) return STATUS_OK;
98
99 T* array = getter(*arrayData);
100 if (array == nullptr) return STATUS_NO_MEMORY;
101
102 int32_t size = 0;
103 if (__builtin_smul_overflow(sizeof(T), length, &size)) return STATUS_NO_MEMORY;
104
105 const void* data = rawParcel->readInplace(size);
106 if (data == nullptr) return STATUS_NO_MEMORY;
107
108 memcpy(array, data, size);
109
110 return STATUS_OK;
111}
112
113// Each element in a char16_t array is converted to an int32_t (not packed)
114template <>
115binder_status_t ReadArray<char16_t>(const AParcel* parcel, void** arrayData,
116 AParcel_arrayReallocator reallocator,
117 ContiguousArrayGetter<char16_t> getter) {
118 const Parcel* rawParcel = parcel->get();
119
120 int32_t length;
121 status_t status = rawParcel->readInt32(&length);
122
123 if (status != STATUS_OK) return PruneStatusT(status);
124 if (length < 0) return STATUS_UNEXPECTED_NULL;
125
126 *arrayData = reallocator(*arrayData, length);
127 if (*arrayData == nullptr) return STATUS_NO_MEMORY;
128
129 if (length == 0) return STATUS_OK;
130
131 char16_t* array = getter(*arrayData);
132 if (array == nullptr) return STATUS_NO_MEMORY;
133
134 int32_t size = 0;
135 if (__builtin_smul_overflow(sizeof(char16_t), length, &size)) return STATUS_NO_MEMORY;
136
137 for (int32_t i = 0; i < length; i++) {
138 status = rawParcel->readChar(array + i);
139
140 if (status != STATUS_OK) return PruneStatusT(status);
141 }
142
143 return STATUS_OK;
144}
145
146template <typename T>
147binder_status_t WriteArray(AParcel* parcel, const void* arrayData, ArrayGetter<T> getter,
148 size_t length, status_t (Parcel::*write)(T)) {
149 if (length > std::numeric_limits<int32_t>::max()) return STATUS_BAD_VALUE;
150
151 Parcel* rawParcel = parcel->get();
152
153 status_t status = rawParcel->writeInt32(static_cast<int32_t>(length));
154 if (status != STATUS_OK) return PruneStatusT(status);
155
156 for (size_t i = 0; i < length; i++) {
157 status = (rawParcel->*write)(getter(arrayData, i));
158
159 if (status != STATUS_OK) return PruneStatusT(status);
160 }
161
162 return STATUS_OK;
163}
164
165template <typename T>
166binder_status_t ReadArray(const AParcel* parcel, void** arrayData,
167 AParcel_arrayReallocator reallocator, ArraySetter<T> setter,
168 status_t (Parcel::*read)(T*) const) {
169 const Parcel* rawParcel = parcel->get();
170
171 int32_t length;
172 status_t status = rawParcel->readInt32(&length);
173
174 if (status != STATUS_OK) return PruneStatusT(status);
175 if (length < 0) return STATUS_UNEXPECTED_NULL;
176
177 *arrayData = reallocator(*arrayData, length);
178 if (*arrayData == nullptr) return STATUS_NO_MEMORY;
179
180 for (size_t i = 0; i < length; i++) {
181 T readTarget;
182 status = (rawParcel->*read)(&readTarget);
183 if (status != STATUS_OK) return PruneStatusT(status);
184
185 setter(*arrayData, i, readTarget);
186 }
187
188 return STATUS_OK;
189}
190
Steven Moreland9b80e282018-09-19 13:57:23 -0700191void AParcel_delete(AParcel* parcel) {
192 delete parcel;
Steven Morelandcaa776c2018-09-04 13:48:11 -0700193}
194
Steven Moreland2e87adc2018-08-20 19:47:00 -0700195binder_status_t AParcel_writeStrongBinder(AParcel* parcel, AIBinder* binder) {
Steven Morelandc0e46d32018-09-12 15:40:49 -0700196 sp<IBinder> writeBinder = binder != nullptr ? binder->getBinder() : nullptr;
Steven Morelandf18615b2018-09-14 11:43:06 -0700197 return parcel->get()->writeStrongBinder(writeBinder);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700198}
199binder_status_t AParcel_readStrongBinder(const AParcel* parcel, AIBinder** binder) {
200 sp<IBinder> readBinder = nullptr;
Steven Morelandf18615b2018-09-14 11:43:06 -0700201 status_t status = parcel->get()->readStrongBinder(&readBinder);
Steven Moreland5d62e442018-09-13 15:01:02 -0700202 if (status != STATUS_OK) {
203 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700204 }
Steven Moreland94968952018-09-05 14:42:59 -0700205 sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
Steven Moreland71cddc32018-08-30 23:39:22 -0700206 AIBinder_incStrong(ret.get());
207 *binder = ret.get();
Steven Moreland5d62e442018-09-13 15:01:02 -0700208 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700209}
210binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, AIBinder** binder) {
211 sp<IBinder> readBinder = nullptr;
Steven Morelandf18615b2018-09-14 11:43:06 -0700212 status_t status = parcel->get()->readNullableStrongBinder(&readBinder);
Steven Moreland5d62e442018-09-13 15:01:02 -0700213 if (status != STATUS_OK) {
214 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700215 }
Steven Moreland94968952018-09-05 14:42:59 -0700216 sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
Steven Moreland71cddc32018-08-30 23:39:22 -0700217 AIBinder_incStrong(ret.get());
218 *binder = ret.get();
Steven Moreland5d62e442018-09-13 15:01:02 -0700219 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700220}
Steven Moreland9a51db82018-09-14 10:59:35 -0700221binder_status_t AParcel_writeStatusHeader(AParcel* parcel, const AStatus* status) {
222 return PruneStatusT(status->get()->writeToParcel(parcel->get()));
223}
224binder_status_t AParcel_readStatusHeader(const AParcel* parcel, AStatus** status) {
225 ::android::binder::Status bstatus;
226 binder_status_t ret = PruneStatusT(bstatus.readFromParcel(*parcel->get()));
227 if (ret == EX_NONE) {
228 *status = new AStatus(std::move(bstatus));
229 }
230 return ret;
231}
Steven Moreland2e87adc2018-08-20 19:47:00 -0700232
Steven Moreland7b06f592018-10-03 19:25:32 -0700233binder_status_t AParcel_writeString(AParcel* parcel, const char* string, size_t length) {
234 const uint8_t* str8 = (uint8_t*)string;
235
236 const ssize_t len16 = utf8_to_utf16_length(str8, length);
237
238 if (len16 < 0 || len16 >= std::numeric_limits<int32_t>::max()) {
239 LOG(WARNING) << __func__ << ": Invalid string length: " << len16;
240 return STATUS_BAD_VALUE;
241 }
242
243 status_t err = parcel->get()->writeInt32(len16);
244 if (err) {
245 return PruneStatusT(err);
246 }
247
248 void* str16 = parcel->get()->writeInplace((len16 + 1) * sizeof(char16_t));
249 if (str16 == nullptr) {
250 return STATUS_NO_MEMORY;
251 }
252
253 utf8_to_utf16(str8, length, (char16_t*)str16, (size_t)len16 + 1);
254
255 return STATUS_OK;
256}
257
258binder_status_t AParcel_readString(const AParcel* parcel, AParcel_string_reallocator reallocator,
259 AParcel_string_getter getter, void** stringData) {
260 size_t len16;
261 const char16_t* str16 = parcel->get()->readString16Inplace(&len16);
262
263 if (str16 == nullptr) {
264 LOG(WARNING) << __func__ << ": Failed to read string in place.";
265 return STATUS_UNEXPECTED_NULL;
266 }
267
268 ssize_t len8;
269
270 if (len16 == 0) {
271 len8 = 1;
272 } else {
273 len8 = utf16_to_utf8_length(str16, len16) + 1;
274 }
275
276 if (len8 <= 0 || len8 >= std::numeric_limits<int32_t>::max()) {
277 LOG(WARNING) << __func__ << ": Invalid string length: " << len8;
278 return STATUS_BAD_VALUE;
279 }
280
281 *stringData = reallocator(*stringData, len8);
Steven Morelanda8845662018-10-12 11:53:03 -0700282
283 if (*stringData == nullptr) {
284 return STATUS_NO_MEMORY;
285 }
286
Steven Moreland7b06f592018-10-03 19:25:32 -0700287 char* str8 = getter(*stringData);
288
289 if (str8 == nullptr) {
290 LOG(WARNING) << __func__ << ": AParcel_string_allocator failed to allocate.";
291 return STATUS_NO_MEMORY;
292 }
293
294 utf16_to_utf8(str16, len16, str8, len8);
295
296 return STATUS_OK;
297}
298
Steven Moreland2e87adc2018-08-20 19:47:00 -0700299// See gen_parcel_helper.py. These auto-generated read/write methods use the same types for
300// libbinder and this library.
301// @START
302binder_status_t AParcel_writeInt32(AParcel* parcel, int32_t value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700303 status_t status = parcel->get()->writeInt32(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700304 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700305}
306
307binder_status_t AParcel_writeUint32(AParcel* parcel, uint32_t value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700308 status_t status = parcel->get()->writeUint32(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700309 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700310}
311
312binder_status_t AParcel_writeInt64(AParcel* parcel, int64_t value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700313 status_t status = parcel->get()->writeInt64(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700314 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700315}
316
317binder_status_t AParcel_writeUint64(AParcel* parcel, uint64_t value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700318 status_t status = parcel->get()->writeUint64(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700319 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700320}
321
322binder_status_t AParcel_writeFloat(AParcel* parcel, float value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700323 status_t status = parcel->get()->writeFloat(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700324 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700325}
326
327binder_status_t AParcel_writeDouble(AParcel* parcel, double value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700328 status_t status = parcel->get()->writeDouble(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700329 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700330}
331
332binder_status_t AParcel_writeBool(AParcel* parcel, bool value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700333 status_t status = parcel->get()->writeBool(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700334 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700335}
336
337binder_status_t AParcel_writeChar(AParcel* parcel, char16_t value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700338 status_t status = parcel->get()->writeChar(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700339 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700340}
341
342binder_status_t AParcel_writeByte(AParcel* parcel, int8_t value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700343 status_t status = parcel->get()->writeByte(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700344 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700345}
346
347binder_status_t AParcel_readInt32(const AParcel* parcel, int32_t* value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700348 status_t status = parcel->get()->readInt32(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700349 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700350}
351
352binder_status_t AParcel_readUint32(const AParcel* parcel, uint32_t* value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700353 status_t status = parcel->get()->readUint32(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700354 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700355}
356
357binder_status_t AParcel_readInt64(const AParcel* parcel, int64_t* value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700358 status_t status = parcel->get()->readInt64(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700359 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700360}
361
362binder_status_t AParcel_readUint64(const AParcel* parcel, uint64_t* value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700363 status_t status = parcel->get()->readUint64(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700364 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700365}
366
367binder_status_t AParcel_readFloat(const AParcel* parcel, float* value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700368 status_t status = parcel->get()->readFloat(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700369 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700370}
371
372binder_status_t AParcel_readDouble(const AParcel* parcel, double* value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700373 status_t status = parcel->get()->readDouble(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700374 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700375}
376
377binder_status_t AParcel_readBool(const AParcel* parcel, bool* value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700378 status_t status = parcel->get()->readBool(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700379 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700380}
381
382binder_status_t AParcel_readChar(const AParcel* parcel, char16_t* value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700383 status_t status = parcel->get()->readChar(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700384 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700385}
386
387binder_status_t AParcel_readByte(const AParcel* parcel, int8_t* value) {
Steven Morelandf18615b2018-09-14 11:43:06 -0700388 status_t status = parcel->get()->readByte(value);
Steven Moreland5d62e442018-09-13 15:01:02 -0700389 return PruneStatusT(status);
Steven Moreland2e87adc2018-08-20 19:47:00 -0700390}
391
Steven Morelanda8845662018-10-12 11:53:03 -0700392binder_status_t AParcel_writeInt32Array(AParcel* parcel, const int32_t* value, size_t length) {
393 return WriteArray<int32_t>(parcel, value, length);
394}
395
396binder_status_t AParcel_writeUint32Array(AParcel* parcel, const uint32_t* value, size_t length) {
397 return WriteArray<uint32_t>(parcel, value, length);
398}
399
400binder_status_t AParcel_writeInt64Array(AParcel* parcel, const int64_t* value, size_t length) {
401 return WriteArray<int64_t>(parcel, value, length);
402}
403
404binder_status_t AParcel_writeUint64Array(AParcel* parcel, const uint64_t* value, size_t length) {
405 return WriteArray<uint64_t>(parcel, value, length);
406}
407
408binder_status_t AParcel_writeFloatArray(AParcel* parcel, const float* value, size_t length) {
409 return WriteArray<float>(parcel, value, length);
410}
411
412binder_status_t AParcel_writeDoubleArray(AParcel* parcel, const double* value, size_t length) {
413 return WriteArray<double>(parcel, value, length);
414}
415
416binder_status_t AParcel_writeBoolArray(AParcel* parcel, const void* arrayData,
417 AParcel_boolArrayGetter getter, size_t length) {
418 return WriteArray<bool>(parcel, arrayData, getter, length, &Parcel::writeBool);
419}
420
421binder_status_t AParcel_writeCharArray(AParcel* parcel, const char16_t* value, size_t length) {
422 return WriteArray<char16_t>(parcel, value, length);
423}
424
425binder_status_t AParcel_writeByteArray(AParcel* parcel, const int8_t* value, size_t length) {
426 return WriteArray<int8_t>(parcel, value, length);
427}
428
429binder_status_t AParcel_readInt32Array(const AParcel* parcel, void** arrayData,
430 AParcel_arrayReallocator reallocator,
431 AParcel_int32ArrayGetter getter) {
432 return ReadArray<int32_t>(parcel, arrayData, reallocator, getter);
433}
434
435binder_status_t AParcel_readUint32Array(const AParcel* parcel, void** arrayData,
436 AParcel_arrayReallocator reallocator,
437 AParcel_uint32ArrayGetter getter) {
438 return ReadArray<uint32_t>(parcel, arrayData, reallocator, getter);
439}
440
441binder_status_t AParcel_readInt64Array(const AParcel* parcel, void** arrayData,
442 AParcel_arrayReallocator reallocator,
443 AParcel_int64ArrayGetter getter) {
444 return ReadArray<int64_t>(parcel, arrayData, reallocator, getter);
445}
446
447binder_status_t AParcel_readUint64Array(const AParcel* parcel, void** arrayData,
448 AParcel_arrayReallocator reallocator,
449 AParcel_uint64ArrayGetter getter) {
450 return ReadArray<uint64_t>(parcel, arrayData, reallocator, getter);
451}
452
453binder_status_t AParcel_readFloatArray(const AParcel* parcel, void** arrayData,
454 AParcel_arrayReallocator reallocator,
455 AParcel_floatArrayGetter getter) {
456 return ReadArray<float>(parcel, arrayData, reallocator, getter);
457}
458
459binder_status_t AParcel_readDoubleArray(const AParcel* parcel, void** arrayData,
460 AParcel_arrayReallocator reallocator,
461 AParcel_doubleArrayGetter getter) {
462 return ReadArray<double>(parcel, arrayData, reallocator, getter);
463}
464
465binder_status_t AParcel_readBoolArray(const AParcel* parcel, void** arrayData,
466 AParcel_arrayReallocator reallocator,
467 AParcel_boolArraySetter setter) {
468 return ReadArray<bool>(parcel, arrayData, reallocator, setter, &Parcel::readBool);
469}
470
471binder_status_t AParcel_readCharArray(const AParcel* parcel, void** arrayData,
472 AParcel_arrayReallocator reallocator,
473 AParcel_charArrayGetter getter) {
474 return ReadArray<char16_t>(parcel, arrayData, reallocator, getter);
475}
476
477binder_status_t AParcel_readByteArray(const AParcel* parcel, void** arrayData,
478 AParcel_arrayReallocator reallocator,
479 AParcel_byteArrayGetter getter) {
480 return ReadArray<int8_t>(parcel, arrayData, reallocator, getter);
481}
482
Steven Moreland2e87adc2018-08-20 19:47:00 -0700483// @END