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 /**
18 * @addtogroup NdkBinder
19 * @{
20 */
21
22 /**
23 * @file binder_parcel_utils.h
24 * @brief A collection of helper wrappers for AParcel.
25 */
26
27 #pragma once
28
29 #include <android/binder_auto_utils.h>
30 #include <android/binder_internal_logging.h>
31 #include <android/binder_parcel.h>
32
33 #include <optional>
34 #include <string>
35 #include <vector>
36
37 namespace ndk {
38
39 /**
40 * This retrieves and allocates a vector to size 'length' and returns the underlying buffer.
41 */
42 template <typename T>
AParcel_stdVectorAllocator(void * vectorData,int32_t length,T ** outBuffer)43 static inline bool AParcel_stdVectorAllocator(void* vectorData, int32_t length, T** outBuffer) {
44 if (length < 0) return false;
45
46 std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
47 if (static_cast<size_t>(length) > vec->max_size()) return false;
48
49 vec->resize(static_cast<size_t>(length));
50 *outBuffer = vec->data();
51 return true;
52 }
53
54 /**
55 * This retrieves and allocates a vector to size 'length' and returns the underlying buffer.
56 */
57 template <typename T>
AParcel_nullableStdVectorAllocator(void * vectorData,int32_t length,T ** outBuffer)58 static inline bool AParcel_nullableStdVectorAllocator(void* vectorData, int32_t length,
59 T** outBuffer) {
60 std::optional<std::vector<T>>* vec = static_cast<std::optional<std::vector<T>>*>(vectorData);
61
62 if (length < 0) {
63 *vec = std::nullopt;
64 return true;
65 }
66
67 *vec = std::optional<std::vector<T>>(std::vector<T>{});
68
69 if (static_cast<size_t>(length) > (*vec)->max_size()) return false;
70 (*vec)->resize(static_cast<size_t>(length));
71
72 *outBuffer = (*vec)->data();
73 return true;
74 }
75
76 /**
77 * This allocates a vector to size 'length' and returns whether the allocation is successful.
78 *
79 * See also AParcel_stdVectorAllocator. Types used with this allocator have their sizes defined
80 * externally with respect to the NDK, and that size information is not passed into the NDK.
81 * Instead, it is used in cases where callbacks are used. Note that when this allocator is used,
82 * null arrays are not supported.
83 *
84 * See AParcel_readVector(const AParcel* parcel, std::vector<bool>)
85 * See AParcel_readVector(const AParcel* parcel, std::vector<std::string>)
86 */
87 template <typename T>
AParcel_stdVectorExternalAllocator(void * vectorData,int32_t length)88 static inline bool AParcel_stdVectorExternalAllocator(void* vectorData, int32_t length) {
89 if (length < 0) return false;
90
91 std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
92 if (static_cast<size_t>(length) > vec->max_size()) return false;
93
94 vec->resize(static_cast<size_t>(length));
95 return true;
96 }
97
98 /**
99 * This allocates a vector to size 'length' and returns whether the allocation is successful.
100 *
101 * See also AParcel_stdVectorAllocator. Types used with this allocator have their sizes defined
102 * externally with respect to the NDK, and that size information is not passed into the NDK.
103 * Instead, it is used in cases where callbacks are used. Note, when this allocator is used,
104 * the vector itself can be nullable.
105 *
106 * See AParcel_readVector(const AParcel* parcel,
107 * std::optional<std::vector<std::optional<std::string>>>)
108 */
109 template <typename T>
AParcel_nullableStdVectorExternalAllocator(void * vectorData,int32_t length)110 static inline bool AParcel_nullableStdVectorExternalAllocator(void* vectorData, int32_t length) {
111 std::optional<std::vector<T>>* vec = static_cast<std::optional<std::vector<T>>*>(vectorData);
112
113 if (length < 0) {
114 *vec = std::nullopt;
115 return true;
116 }
117
118 *vec = std::optional<std::vector<T>>(std::vector<T>{});
119
120 if (static_cast<size_t>(length) > (*vec)->max_size()) return false;
121 (*vec)->resize(static_cast<size_t>(length));
122
123 return true;
124 }
125
126 /**
127 * This retrieves the underlying value in a vector which may not be contiguous at index from a
128 * corresponding vectorData.
129 */
130 template <typename T>
AParcel_stdVectorGetter(const void * vectorData,size_t index)131 static inline T AParcel_stdVectorGetter(const void* vectorData, size_t index) {
132 const std::vector<T>* vec = static_cast<const std::vector<T>*>(vectorData);
133 return (*vec)[index];
134 }
135
136 /**
137 * This sets the underlying value in a corresponding vectorData which may not be contiguous at
138 * index.
139 */
140 template <typename T>
AParcel_stdVectorSetter(void * vectorData,size_t index,T value)141 static inline void AParcel_stdVectorSetter(void* vectorData, size_t index, T value) {
142 std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData);
143 (*vec)[index] = value;
144 }
145
146 /**
147 * This sets the underlying value in a corresponding vectorData which may not be contiguous at
148 * index.
149 */
150 template <typename T>
AParcel_nullableStdVectorSetter(void * vectorData,size_t index,T value)151 static inline void AParcel_nullableStdVectorSetter(void* vectorData, size_t index, T value) {
152 std::optional<std::vector<T>>* vec = static_cast<std::optional<std::vector<T>>*>(vectorData);
153 vec->value()[index] = value;
154 }
155
156 /**
157 * Convenience method to write a nullable strong binder.
158 */
AParcel_writeNullableStrongBinder(AParcel * parcel,const SpAIBinder & binder)159 static inline binder_status_t AParcel_writeNullableStrongBinder(AParcel* parcel,
160 const SpAIBinder& binder) {
161 return AParcel_writeStrongBinder(parcel, binder.get());
162 }
163
164 /**
165 * Convenience method to read a nullable strong binder.
166 */
AParcel_readNullableStrongBinder(const AParcel * parcel,SpAIBinder * binder)167 static inline binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel,
168 SpAIBinder* binder) {
169 AIBinder* readBinder;
170 binder_status_t status = AParcel_readStrongBinder(parcel, &readBinder);
171 if (status == STATUS_OK) {
172 binder->set(readBinder);
173 }
174 return status;
175 }
176
177 /**
178 * Convenience method to write a strong binder but return an error if it is null.
179 */
AParcel_writeRequiredStrongBinder(AParcel * parcel,const SpAIBinder & binder)180 static inline binder_status_t AParcel_writeRequiredStrongBinder(AParcel* parcel,
181 const SpAIBinder& binder) {
182 if (binder.get() == nullptr) {
183 syslog(LOG_ERR, "Passing null binder object as non-@nullable AIDL IBinder");
184 return STATUS_UNEXPECTED_NULL;
185 }
186 return AParcel_writeStrongBinder(parcel, binder.get());
187 }
188
189 /**
190 * Convenience method to read a strong binder but return an error if it is null.
191 */
AParcel_readRequiredStrongBinder(const AParcel * parcel,SpAIBinder * binder)192 static inline binder_status_t AParcel_readRequiredStrongBinder(const AParcel* parcel,
193 SpAIBinder* binder) {
194 AIBinder* readBinder;
195 binder_status_t ret = AParcel_readStrongBinder(parcel, &readBinder);
196 if (ret == STATUS_OK) {
197 if (readBinder == nullptr) {
198 return STATUS_UNEXPECTED_NULL;
199 }
200
201 binder->set(readBinder);
202 }
203 return ret;
204 }
205
206 /**
207 * Convenience method to write a ParcelFileDescriptor where -1 represents a null value.
208 */
AParcel_writeNullableParcelFileDescriptor(AParcel * parcel,const ScopedFileDescriptor & fd)209 static inline binder_status_t AParcel_writeNullableParcelFileDescriptor(
210 AParcel* parcel, const ScopedFileDescriptor& fd) {
211 return AParcel_writeParcelFileDescriptor(parcel, fd.get());
212 }
213
214 /**
215 * Convenience method to read a ParcelFileDescriptor where -1 represents a null value.
216 */
AParcel_readNullableParcelFileDescriptor(const AParcel * parcel,ScopedFileDescriptor * fd)217 static inline binder_status_t AParcel_readNullableParcelFileDescriptor(const AParcel* parcel,
218 ScopedFileDescriptor* fd) {
219 int readFd;
220 binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
221 if (status == STATUS_OK) {
222 fd->set(readFd);
223 }
224 return status;
225 }
226
227 /**
228 * Convenience method to write a valid ParcelFileDescriptor.
229 */
AParcel_writeRequiredParcelFileDescriptor(AParcel * parcel,const ScopedFileDescriptor & fd)230 static inline binder_status_t AParcel_writeRequiredParcelFileDescriptor(
231 AParcel* parcel, const ScopedFileDescriptor& fd) {
232 if (fd.get() < 0) {
233 syslog(LOG_ERR, "Passing -1 file descriptor as non-@nullable AIDL ParcelFileDescriptor");
234 return STATUS_UNEXPECTED_NULL;
235 }
236 return AParcel_writeParcelFileDescriptor(parcel, fd.get());
237 }
238
239 /**
240 * Convenience method to read a valid ParcelFileDescriptor.
241 */
AParcel_readRequiredParcelFileDescriptor(const AParcel * parcel,ScopedFileDescriptor * fd)242 static inline binder_status_t AParcel_readRequiredParcelFileDescriptor(const AParcel* parcel,
243 ScopedFileDescriptor* fd) {
244 int readFd;
245 binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
246 if (status == STATUS_OK) {
247 if (readFd < 0) {
248 return STATUS_UNEXPECTED_NULL;
249 }
250 fd->set(readFd);
251 }
252 return status;
253 }
254
255 /**
256 * Allocates a std::string to length and returns the underlying buffer. For use with
257 * AParcel_readString. See use below in AParcel_readString(const AParcel*, std::string*).
258 */
AParcel_stdStringAllocator(void * stringData,int32_t length,char ** buffer)259 static inline bool AParcel_stdStringAllocator(void* stringData, int32_t length, char** buffer) {
260 if (length <= 0) return false;
261
262 std::string* str = static_cast<std::string*>(stringData);
263 str->resize(static_cast<size_t>(length) - 1);
264 *buffer = &(*str)[0];
265 return true;
266 }
267
268 /**
269 * Allocates a string in a std::optional<std::string> to size 'length' (or to std::nullopt when
270 * length is -1) and returns the underlying buffer. For use with AParcel_readString. See use below
271 * in AParcel_readString(const AParcel*, std::optional<std::string>*).
272 */
AParcel_nullableStdStringAllocator(void * stringData,int32_t length,char ** buffer)273 static inline bool AParcel_nullableStdStringAllocator(void* stringData, int32_t length,
274 char** buffer) {
275 if (length == 0) return false;
276
277 std::optional<std::string>* str = static_cast<std::optional<std::string>*>(stringData);
278
279 if (length < 0) {
280 *str = std::nullopt;
281 return true;
282 }
283
284 *str = std::optional<std::string>(std::string{});
285 (*str)->resize(static_cast<size_t>(length) - 1);
286 *buffer = &(**str)[0];
287 return true;
288 }
289
290 /**
291 * Allocates a std::string inside of a std::vector<std::string> at index 'index' to size 'length'.
292 */
AParcel_stdVectorStringElementAllocator(void * vectorData,size_t index,int32_t length,char ** buffer)293 static inline bool AParcel_stdVectorStringElementAllocator(void* vectorData, size_t index,
294 int32_t length, char** buffer) {
295 std::vector<std::string>* vec = static_cast<std::vector<std::string>*>(vectorData);
296 std::string& element = vec->at(index);
297 return AParcel_stdStringAllocator(static_cast<void*>(&element), length, buffer);
298 }
299
300 /**
301 * This gets the length and buffer of a std::string inside of a std::vector<std::string> at index
302 * index.
303 */
AParcel_stdVectorStringElementGetter(const void * vectorData,size_t index,int32_t * outLength)304 static inline const char* AParcel_stdVectorStringElementGetter(const void* vectorData, size_t index,
305 int32_t* outLength) {
306 const std::vector<std::string>* vec = static_cast<const std::vector<std::string>*>(vectorData);
307 const std::string& element = vec->at(index);
308
309 *outLength = static_cast<int32_t>(element.size());
310 return element.c_str();
311 }
312
313 /**
314 * Allocates a string in a std::optional<std::string> inside of a
315 * std::optional<std::vector<std::optional<std::string>>> at index 'index' to size 'length' (or to
316 * std::nullopt when length is -1).
317 */
AParcel_nullableStdVectorStringElementAllocator(void * vectorData,size_t index,int32_t length,char ** buffer)318 static inline bool AParcel_nullableStdVectorStringElementAllocator(void* vectorData, size_t index,
319 int32_t length, char** buffer) {
320 std::optional<std::vector<std::optional<std::string>>>* vec =
321 static_cast<std::optional<std::vector<std::optional<std::string>>>*>(vectorData);
322 std::optional<std::string>& element = vec->value().at(index);
323 return AParcel_nullableStdStringAllocator(static_cast<void*>(&element), length, buffer);
324 }
325
326 /**
327 * This gets the length and buffer of a std::optional<std::string> inside of a
328 * std::vector<std::string> at index index. If the string is null, then it returns null and a length
329 * of -1.
330 */
AParcel_nullableStdVectorStringElementGetter(const void * vectorData,size_t index,int32_t * outLength)331 static inline const char* AParcel_nullableStdVectorStringElementGetter(const void* vectorData,
332 size_t index,
333 int32_t* outLength) {
334 const std::optional<std::vector<std::optional<std::string>>>* vec =
335 static_cast<const std::optional<std::vector<std::optional<std::string>>>*>(vectorData);
336 const std::optional<std::string>& element = vec->value().at(index);
337
338 if (!element) {
339 *outLength = -1;
340 return nullptr;
341 }
342
343 *outLength = static_cast<int32_t>(element->size());
344 return element->c_str();
345 }
346
347 /**
348 * Convenience API for writing a std::string.
349 */
AParcel_writeString(AParcel * parcel,const std::string & str)350 static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) {
351 return AParcel_writeString(parcel, str.c_str(), static_cast<int32_t>(str.size()));
352 }
353
354 /**
355 * Convenience API for reading a std::string.
356 */
AParcel_readString(const AParcel * parcel,std::string * str)357 static inline binder_status_t AParcel_readString(const AParcel* parcel, std::string* str) {
358 void* stringData = static_cast<void*>(str);
359 return AParcel_readString(parcel, stringData, AParcel_stdStringAllocator);
360 }
361
362 /**
363 * Convenience API for writing a std::optional<std::string>.
364 */
AParcel_writeString(AParcel * parcel,const std::optional<std::string> & str)365 static inline binder_status_t AParcel_writeString(AParcel* parcel,
366 const std::optional<std::string>& str) {
367 if (!str) {
368 return AParcel_writeString(parcel, nullptr, -1);
369 }
370
371 return AParcel_writeString(parcel, str->c_str(), static_cast<int32_t>(str->size()));
372 }
373
374 /**
375 * Convenience API for reading a std::optional<std::string>.
376 */
AParcel_readString(const AParcel * parcel,std::optional<std::string> * str)377 static inline binder_status_t AParcel_readString(const AParcel* parcel,
378 std::optional<std::string>* str) {
379 void* stringData = static_cast<void*>(str);
380 return AParcel_readString(parcel, stringData, AParcel_nullableStdStringAllocator);
381 }
382
383 /**
384 * Convenience API for writing a std::vector<std::string>
385 */
AParcel_writeVector(AParcel * parcel,const std::vector<std::string> & vec)386 static inline binder_status_t AParcel_writeVector(AParcel* parcel,
387 const std::vector<std::string>& vec) {
388 const void* vectorData = static_cast<const void*>(&vec);
389 return AParcel_writeStringArray(parcel, vectorData, static_cast<int32_t>(vec.size()),
390 AParcel_stdVectorStringElementGetter);
391 }
392
393 /**
394 * Convenience API for reading a std::vector<std::string>
395 */
AParcel_readVector(const AParcel * parcel,std::vector<std::string> * vec)396 static inline binder_status_t AParcel_readVector(const AParcel* parcel,
397 std::vector<std::string>* vec) {
398 void* vectorData = static_cast<void*>(vec);
399 return AParcel_readStringArray(parcel, vectorData,
400 AParcel_stdVectorExternalAllocator<std::string>,
401 AParcel_stdVectorStringElementAllocator);
402 }
403
404 /**
405 * Convenience API for writing a std::optional<std::vector<std::optional<std::string>>>
406 */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<std::optional<std::string>>> & vec)407 static inline binder_status_t AParcel_writeVector(
408 AParcel* parcel, const std::optional<std::vector<std::optional<std::string>>>& vec) {
409 const void* vectorData = static_cast<const void*>(&vec);
410 return AParcel_writeStringArray(parcel, vectorData,
411 (vec ? static_cast<int32_t>(vec->size()) : -1),
412 AParcel_nullableStdVectorStringElementGetter);
413 }
414
415 /**
416 * Convenience API for reading a std::optional<std::vector<std::optional<std::string>>>
417 */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<std::optional<std::string>>> * vec)418 static inline binder_status_t AParcel_readVector(
419 const AParcel* parcel, std::optional<std::vector<std::optional<std::string>>>* vec) {
420 void* vectorData = static_cast<void*>(vec);
421 return AParcel_readStringArray(
422 parcel, vectorData,
423 AParcel_nullableStdVectorExternalAllocator<std::optional<std::string>>,
424 AParcel_nullableStdVectorStringElementAllocator);
425 }
426
427 /**
428 * Convenience API for writing a non-null parcelable.
429 */
430 template <typename P>
AParcel_writeParcelable(AParcel * parcel,const P & p)431 static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) {
432 binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null
433 if (status != STATUS_OK) {
434 return status;
435 }
436 return p.writeToParcel(parcel);
437 }
438
439 /**
440 * Convenience API for reading a non-null parcelable.
441 */
442 template <typename P>
AParcel_readParcelable(const AParcel * parcel,P * p)443 static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) {
444 int32_t null;
445 binder_status_t status = AParcel_readInt32(parcel, &null);
446 if (status != STATUS_OK) {
447 return status;
448 }
449 if (null == 0) {
450 return STATUS_UNEXPECTED_NULL;
451 }
452 return p->readFromParcel(parcel);
453 }
454
455 /**
456 * Convenience API for writing a nullable parcelable.
457 */
458 template <typename P>
AParcel_writeNullableParcelable(AParcel * parcel,const std::optional<P> & p)459 static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel,
460 const std::optional<P>& p) {
461 if (p == std::nullopt) {
462 return AParcel_writeInt32(parcel, 0); // null
463 }
464 binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null
465 if (status != STATUS_OK) {
466 return status;
467 }
468 return p->writeToParcel(parcel);
469 }
470
471 /**
472 * Convenience API for reading a nullable parcelable.
473 */
474 template <typename P>
AParcel_readNullableParcelable(const AParcel * parcel,std::optional<P> * p)475 static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel,
476 std::optional<P>* p) {
477 int32_t null;
478 binder_status_t status = AParcel_readInt32(parcel, &null);
479 if (status != STATUS_OK) {
480 return status;
481 }
482 if (null == 0) {
483 *p = std::nullopt;
484 return STATUS_OK;
485 }
486 *p = std::optional<P>(P{});
487 return (*p)->readFromParcel(parcel);
488 }
489
490 /**
491 * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'.
492 */
493 template <typename P>
AParcel_writeStdVectorParcelableElement(AParcel * parcel,const void * vectorData,size_t index)494 binder_status_t AParcel_writeStdVectorParcelableElement(AParcel* parcel, const void* vectorData,
495 size_t index) {
496 const std::vector<P>* vector = static_cast<const std::vector<P>*>(vectorData);
497 return AParcel_writeParcelable(parcel, vector->at(index));
498 }
499
500 /**
501 * Reads a parcelable object of type P inside a std::vector<P> at index 'index' from 'parcel'.
502 */
503 template <typename P>
AParcel_readStdVectorParcelableElement(const AParcel * parcel,void * vectorData,size_t index)504 binder_status_t AParcel_readStdVectorParcelableElement(const AParcel* parcel, void* vectorData,
505 size_t index) {
506 std::vector<P>* vector = static_cast<std::vector<P>*>(vectorData);
507 return AParcel_readParcelable(parcel, &vector->at(index));
508 }
509
510 /**
511 * Writes a ScopedFileDescriptor object inside a std::vector<ScopedFileDescriptor> at index 'index'
512 * to 'parcel'.
513 */
514 template <>
515 inline binder_status_t AParcel_writeStdVectorParcelableElement<ScopedFileDescriptor>(
516 AParcel* parcel, const void* vectorData, size_t index) {
517 const std::vector<ScopedFileDescriptor>* vector =
518 static_cast<const std::vector<ScopedFileDescriptor>*>(vectorData);
519 int writeFd = vector->at(index).get();
520 if (writeFd < 0) {
521 return STATUS_UNEXPECTED_NULL;
522 }
523 return AParcel_writeParcelFileDescriptor(parcel, writeFd);
524 }
525
526 /**
527 * Reads a ScopedFileDescriptor object inside a std::vector<ScopedFileDescriptor> at index 'index'
528 * from 'parcel'.
529 */
530 template <>
531 inline binder_status_t AParcel_readStdVectorParcelableElement<ScopedFileDescriptor>(
532 const AParcel* parcel, void* vectorData, size_t index) {
533 std::vector<ScopedFileDescriptor>* vector =
534 static_cast<std::vector<ScopedFileDescriptor>*>(vectorData);
535 int readFd;
536 binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
537 if (status == STATUS_OK) {
538 if (readFd < 0) {
539 return STATUS_UNEXPECTED_NULL;
540 }
541 vector->at(index).set(readFd);
542 }
543 return status;
544 }
545
546 /**
547 * Convenience API for writing a std::vector<P>
548 */
549 template <typename P>
AParcel_writeVector(AParcel * parcel,const std::vector<P> & vec)550 static inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<P>& vec) {
551 const void* vectorData = static_cast<const void*>(&vec);
552 return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec.size()),
553 AParcel_writeStdVectorParcelableElement<P>);
554 }
555
556 /**
557 * Convenience API for reading a std::vector<P>
558 */
559 template <typename P>
AParcel_readVector(const AParcel * parcel,std::vector<P> * vec)560 static inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<P>* vec) {
561 void* vectorData = static_cast<void*>(vec);
562 return AParcel_readParcelableArray(parcel, vectorData, AParcel_stdVectorExternalAllocator<P>,
563 AParcel_readStdVectorParcelableElement<P>);
564 }
565
566 // @START
567 /**
568 * Writes a vector of int32_t to the next location in a non-null parcel.
569 */
AParcel_writeVector(AParcel * parcel,const std::vector<int32_t> & vec)570 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int32_t>& vec) {
571 return AParcel_writeInt32Array(parcel, vec.data(), static_cast<int32_t>(vec.size()));
572 }
573
574 /**
575 * Writes an optional vector of int32_t to the next location in a non-null parcel.
576 */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<int32_t>> & vec)577 inline binder_status_t AParcel_writeVector(AParcel* parcel,
578 const std::optional<std::vector<int32_t>>& vec) {
579 if (!vec) return AParcel_writeInt32Array(parcel, nullptr, -1);
580 return AParcel_writeVector(parcel, *vec);
581 }
582
583 /**
584 * Reads a vector of int32_t from the next location in a non-null parcel.
585 */
AParcel_readVector(const AParcel * parcel,std::vector<int32_t> * vec)586 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int32_t>* vec) {
587 void* vectorData = static_cast<void*>(vec);
588 return AParcel_readInt32Array(parcel, vectorData, AParcel_stdVectorAllocator<int32_t>);
589 }
590
591 /**
592 * Reads an optional vector of int32_t from the next location in a non-null parcel.
593 */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<int32_t>> * vec)594 inline binder_status_t AParcel_readVector(const AParcel* parcel,
595 std::optional<std::vector<int32_t>>* vec) {
596 void* vectorData = static_cast<void*>(vec);
597 return AParcel_readInt32Array(parcel, vectorData, AParcel_nullableStdVectorAllocator<int32_t>);
598 }
599
600 /**
601 * Writes a vector of uint32_t to the next location in a non-null parcel.
602 */
AParcel_writeVector(AParcel * parcel,const std::vector<uint32_t> & vec)603 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint32_t>& vec) {
604 return AParcel_writeUint32Array(parcel, vec.data(), static_cast<int32_t>(vec.size()));
605 }
606
607 /**
608 * Writes an optional vector of uint32_t to the next location in a non-null parcel.
609 */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<uint32_t>> & vec)610 inline binder_status_t AParcel_writeVector(AParcel* parcel,
611 const std::optional<std::vector<uint32_t>>& vec) {
612 if (!vec) return AParcel_writeUint32Array(parcel, nullptr, -1);
613 return AParcel_writeVector(parcel, *vec);
614 }
615
616 /**
617 * Reads a vector of uint32_t from the next location in a non-null parcel.
618 */
AParcel_readVector(const AParcel * parcel,std::vector<uint32_t> * vec)619 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint32_t>* vec) {
620 void* vectorData = static_cast<void*>(vec);
621 return AParcel_readUint32Array(parcel, vectorData, AParcel_stdVectorAllocator<uint32_t>);
622 }
623
624 /**
625 * Reads an optional vector of uint32_t from the next location in a non-null parcel.
626 */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<uint32_t>> * vec)627 inline binder_status_t AParcel_readVector(const AParcel* parcel,
628 std::optional<std::vector<uint32_t>>* vec) {
629 void* vectorData = static_cast<void*>(vec);
630 return AParcel_readUint32Array(parcel, vectorData,
631 AParcel_nullableStdVectorAllocator<uint32_t>);
632 }
633
634 /**
635 * Writes a vector of int64_t to the next location in a non-null parcel.
636 */
AParcel_writeVector(AParcel * parcel,const std::vector<int64_t> & vec)637 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int64_t>& vec) {
638 return AParcel_writeInt64Array(parcel, vec.data(), static_cast<int32_t>(vec.size()));
639 }
640
641 /**
642 * Writes an optional vector of int64_t to the next location in a non-null parcel.
643 */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<int64_t>> & vec)644 inline binder_status_t AParcel_writeVector(AParcel* parcel,
645 const std::optional<std::vector<int64_t>>& vec) {
646 if (!vec) return AParcel_writeInt64Array(parcel, nullptr, -1);
647 return AParcel_writeVector(parcel, *vec);
648 }
649
650 /**
651 * Reads a vector of int64_t from the next location in a non-null parcel.
652 */
AParcel_readVector(const AParcel * parcel,std::vector<int64_t> * vec)653 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int64_t>* vec) {
654 void* vectorData = static_cast<void*>(vec);
655 return AParcel_readInt64Array(parcel, vectorData, AParcel_stdVectorAllocator<int64_t>);
656 }
657
658 /**
659 * Reads an optional vector of int64_t from the next location in a non-null parcel.
660 */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<int64_t>> * vec)661 inline binder_status_t AParcel_readVector(const AParcel* parcel,
662 std::optional<std::vector<int64_t>>* vec) {
663 void* vectorData = static_cast<void*>(vec);
664 return AParcel_readInt64Array(parcel, vectorData, AParcel_nullableStdVectorAllocator<int64_t>);
665 }
666
667 /**
668 * Writes a vector of uint64_t to the next location in a non-null parcel.
669 */
AParcel_writeVector(AParcel * parcel,const std::vector<uint64_t> & vec)670 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint64_t>& vec) {
671 return AParcel_writeUint64Array(parcel, vec.data(), static_cast<int32_t>(vec.size()));
672 }
673
674 /**
675 * Writes an optional vector of uint64_t to the next location in a non-null parcel.
676 */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<uint64_t>> & vec)677 inline binder_status_t AParcel_writeVector(AParcel* parcel,
678 const std::optional<std::vector<uint64_t>>& vec) {
679 if (!vec) return AParcel_writeUint64Array(parcel, nullptr, -1);
680 return AParcel_writeVector(parcel, *vec);
681 }
682
683 /**
684 * Reads a vector of uint64_t from the next location in a non-null parcel.
685 */
AParcel_readVector(const AParcel * parcel,std::vector<uint64_t> * vec)686 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint64_t>* vec) {
687 void* vectorData = static_cast<void*>(vec);
688 return AParcel_readUint64Array(parcel, vectorData, AParcel_stdVectorAllocator<uint64_t>);
689 }
690
691 /**
692 * Reads an optional vector of uint64_t from the next location in a non-null parcel.
693 */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<uint64_t>> * vec)694 inline binder_status_t AParcel_readVector(const AParcel* parcel,
695 std::optional<std::vector<uint64_t>>* vec) {
696 void* vectorData = static_cast<void*>(vec);
697 return AParcel_readUint64Array(parcel, vectorData,
698 AParcel_nullableStdVectorAllocator<uint64_t>);
699 }
700
701 /**
702 * Writes a vector of float to the next location in a non-null parcel.
703 */
AParcel_writeVector(AParcel * parcel,const std::vector<float> & vec)704 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<float>& vec) {
705 return AParcel_writeFloatArray(parcel, vec.data(), static_cast<int32_t>(vec.size()));
706 }
707
708 /**
709 * Writes an optional vector of float to the next location in a non-null parcel.
710 */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<float>> & vec)711 inline binder_status_t AParcel_writeVector(AParcel* parcel,
712 const std::optional<std::vector<float>>& vec) {
713 if (!vec) return AParcel_writeFloatArray(parcel, nullptr, -1);
714 return AParcel_writeVector(parcel, *vec);
715 }
716
717 /**
718 * Reads a vector of float from the next location in a non-null parcel.
719 */
AParcel_readVector(const AParcel * parcel,std::vector<float> * vec)720 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<float>* vec) {
721 void* vectorData = static_cast<void*>(vec);
722 return AParcel_readFloatArray(parcel, vectorData, AParcel_stdVectorAllocator<float>);
723 }
724
725 /**
726 * Reads an optional vector of float from the next location in a non-null parcel.
727 */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<float>> * vec)728 inline binder_status_t AParcel_readVector(const AParcel* parcel,
729 std::optional<std::vector<float>>* vec) {
730 void* vectorData = static_cast<void*>(vec);
731 return AParcel_readFloatArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<float>);
732 }
733
734 /**
735 * Writes a vector of double to the next location in a non-null parcel.
736 */
AParcel_writeVector(AParcel * parcel,const std::vector<double> & vec)737 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<double>& vec) {
738 return AParcel_writeDoubleArray(parcel, vec.data(), static_cast<int32_t>(vec.size()));
739 }
740
741 /**
742 * Writes an optional vector of double to the next location in a non-null parcel.
743 */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<double>> & vec)744 inline binder_status_t AParcel_writeVector(AParcel* parcel,
745 const std::optional<std::vector<double>>& vec) {
746 if (!vec) return AParcel_writeDoubleArray(parcel, nullptr, -1);
747 return AParcel_writeVector(parcel, *vec);
748 }
749
750 /**
751 * Reads a vector of double from the next location in a non-null parcel.
752 */
AParcel_readVector(const AParcel * parcel,std::vector<double> * vec)753 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<double>* vec) {
754 void* vectorData = static_cast<void*>(vec);
755 return AParcel_readDoubleArray(parcel, vectorData, AParcel_stdVectorAllocator<double>);
756 }
757
758 /**
759 * Reads an optional vector of double from the next location in a non-null parcel.
760 */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<double>> * vec)761 inline binder_status_t AParcel_readVector(const AParcel* parcel,
762 std::optional<std::vector<double>>* vec) {
763 void* vectorData = static_cast<void*>(vec);
764 return AParcel_readDoubleArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<double>);
765 }
766
767 /**
768 * Writes a vector of bool to the next location in a non-null parcel.
769 */
AParcel_writeVector(AParcel * parcel,const std::vector<bool> & vec)770 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<bool>& vec) {
771 return AParcel_writeBoolArray(parcel, static_cast<const void*>(&vec),
772 static_cast<int32_t>(vec.size()), AParcel_stdVectorGetter<bool>);
773 }
774
775 /**
776 * Writes an optional vector of bool to the next location in a non-null parcel.
777 */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<bool>> & vec)778 inline binder_status_t AParcel_writeVector(AParcel* parcel,
779 const std::optional<std::vector<bool>>& vec) {
780 if (!vec) return AParcel_writeBoolArray(parcel, nullptr, -1, AParcel_stdVectorGetter<bool>);
781 return AParcel_writeVector(parcel, *vec);
782 }
783
784 /**
785 * Reads a vector of bool from the next location in a non-null parcel.
786 */
AParcel_readVector(const AParcel * parcel,std::vector<bool> * vec)787 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<bool>* vec) {
788 void* vectorData = static_cast<void*>(vec);
789 return AParcel_readBoolArray(parcel, vectorData, AParcel_stdVectorExternalAllocator<bool>,
790 AParcel_stdVectorSetter<bool>);
791 }
792
793 /**
794 * Reads an optional vector of bool from the next location in a non-null parcel.
795 */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<bool>> * vec)796 inline binder_status_t AParcel_readVector(const AParcel* parcel,
797 std::optional<std::vector<bool>>* vec) {
798 void* vectorData = static_cast<void*>(vec);
799 return AParcel_readBoolArray(parcel, vectorData,
800 AParcel_nullableStdVectorExternalAllocator<bool>,
801 AParcel_nullableStdVectorSetter<bool>);
802 }
803
804 /**
805 * Writes a vector of char16_t to the next location in a non-null parcel.
806 */
AParcel_writeVector(AParcel * parcel,const std::vector<char16_t> & vec)807 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<char16_t>& vec) {
808 return AParcel_writeCharArray(parcel, vec.data(), static_cast<int32_t>(vec.size()));
809 }
810
811 /**
812 * Writes an optional vector of char16_t to the next location in a non-null parcel.
813 */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<char16_t>> & vec)814 inline binder_status_t AParcel_writeVector(AParcel* parcel,
815 const std::optional<std::vector<char16_t>>& vec) {
816 if (!vec) return AParcel_writeCharArray(parcel, nullptr, -1);
817 return AParcel_writeVector(parcel, *vec);
818 }
819
820 /**
821 * Reads a vector of char16_t from the next location in a non-null parcel.
822 */
AParcel_readVector(const AParcel * parcel,std::vector<char16_t> * vec)823 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<char16_t>* vec) {
824 void* vectorData = static_cast<void*>(vec);
825 return AParcel_readCharArray(parcel, vectorData, AParcel_stdVectorAllocator<char16_t>);
826 }
827
828 /**
829 * Reads an optional vector of char16_t from the next location in a non-null parcel.
830 */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<char16_t>> * vec)831 inline binder_status_t AParcel_readVector(const AParcel* parcel,
832 std::optional<std::vector<char16_t>>* vec) {
833 void* vectorData = static_cast<void*>(vec);
834 return AParcel_readCharArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<char16_t>);
835 }
836
837 /**
838 * Writes a vector of uint8_t to the next location in a non-null parcel.
839 */
AParcel_writeVector(AParcel * parcel,const std::vector<uint8_t> & vec)840 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint8_t>& vec) {
841 return AParcel_writeByteArray(parcel, reinterpret_cast<const int8_t*>(vec.data()),
842 static_cast<int32_t>(vec.size()));
843 }
844
845 /**
846 * Writes an optional vector of uint8_t to the next location in a non-null parcel.
847 */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<uint8_t>> & vec)848 inline binder_status_t AParcel_writeVector(AParcel* parcel,
849 const std::optional<std::vector<uint8_t>>& vec) {
850 if (!vec) return AParcel_writeByteArray(parcel, nullptr, -1);
851 return AParcel_writeVector(parcel, *vec);
852 }
853
854 /**
855 * Reads a vector of uint8_t from the next location in a non-null parcel.
856 */
AParcel_readVector(const AParcel * parcel,std::vector<uint8_t> * vec)857 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint8_t>* vec) {
858 void* vectorData = static_cast<void*>(vec);
859 return AParcel_readByteArray(parcel, vectorData, AParcel_stdVectorAllocator<int8_t>);
860 }
861
862 /**
863 * Reads an optional vector of uint8_t from the next location in a non-null parcel.
864 */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<uint8_t>> * vec)865 inline binder_status_t AParcel_readVector(const AParcel* parcel,
866 std::optional<std::vector<uint8_t>>* vec) {
867 void* vectorData = static_cast<void*>(vec);
868 return AParcel_readByteArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<int8_t>);
869 }
870
871 // @END
872
873 /**
874 * Convenience API for writing the size of a vector.
875 */
876 template <typename T>
AParcel_writeVectorSize(AParcel * parcel,const std::vector<T> & vec)877 static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel, const std::vector<T>& vec) {
878 if (vec.size() > INT32_MAX) {
879 return STATUS_BAD_VALUE;
880 }
881
882 return AParcel_writeInt32(parcel, static_cast<int32_t>(vec.size()));
883 }
884
885 /**
886 * Convenience API for writing the size of a vector.
887 */
888 template <typename T>
AParcel_writeVectorSize(AParcel * parcel,const std::optional<std::vector<T>> & vec)889 static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel,
890 const std::optional<std::vector<T>>& vec) {
891 if (!vec) {
892 return AParcel_writeInt32(parcel, -1);
893 }
894
895 if (vec->size() > INT32_MAX) {
896 return STATUS_BAD_VALUE;
897 }
898
899 return AParcel_writeInt32(parcel, static_cast<int32_t>(vec->size()));
900 }
901
902 /**
903 * Convenience API for resizing a vector.
904 */
905 template <typename T>
AParcel_resizeVector(const AParcel * parcel,std::vector<T> * vec)906 static inline binder_status_t AParcel_resizeVector(const AParcel* parcel, std::vector<T>* vec) {
907 int32_t size;
908 binder_status_t err = AParcel_readInt32(parcel, &size);
909
910 if (err != STATUS_OK) return err;
911 if (size < 0) return STATUS_UNEXPECTED_NULL;
912
913 vec->resize(static_cast<size_t>(size));
914 return STATUS_OK;
915 }
916
917 /**
918 * Convenience API for resizing a vector.
919 */
920 template <typename T>
AParcel_resizeVector(const AParcel * parcel,std::optional<std::vector<T>> * vec)921 static inline binder_status_t AParcel_resizeVector(const AParcel* parcel,
922 std::optional<std::vector<T>>* vec) {
923 int32_t size;
924 binder_status_t err = AParcel_readInt32(parcel, &size);
925
926 if (err != STATUS_OK) return err;
927 if (size < -1) return STATUS_UNEXPECTED_NULL;
928
929 if (size == -1) {
930 *vec = std::nullopt;
931 return STATUS_OK;
932 }
933
934 *vec = std::optional<std::vector<T>>(std::vector<T>{});
935 (*vec)->resize(static_cast<size_t>(size));
936 return STATUS_OK;
937 }
938
939 } // namespace ndk
940
941 /** @} */
942