• 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 /**
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