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