• 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_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  * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'.
425  */
426 template <typename P>
AParcel_writeStdVectorParcelableElement(AParcel * parcel,const void * vectorData,size_t index)427 binder_status_t AParcel_writeStdVectorParcelableElement(AParcel* parcel, const void* vectorData,
428                                                         size_t index) {
429     const std::vector<P>* vector = static_cast<const std::vector<P>*>(vectorData);
430     return vector->at(index).writeToParcel(parcel);
431 }
432 
433 /**
434  * Reads a parcelable object of type P inside a std::vector<P> at index 'index' from 'parcel'.
435  */
436 template <typename P>
AParcel_readStdVectorParcelableElement(const AParcel * parcel,void * vectorData,size_t index)437 binder_status_t AParcel_readStdVectorParcelableElement(const AParcel* parcel, void* vectorData,
438                                                        size_t index) {
439     std::vector<P>* vector = static_cast<std::vector<P>*>(vectorData);
440     return vector->at(index).readFromParcel(parcel);
441 }
442 
443 /**
444  * Convenience API for writing a std::vector<P>
445  */
446 template <typename P>
AParcel_writeVector(AParcel * parcel,const std::vector<P> & vec)447 static inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<P>& vec) {
448     const void* vectorData = static_cast<const void*>(&vec);
449     return AParcel_writeParcelableArray(parcel, vectorData, vec.size(),
450                                         AParcel_writeStdVectorParcelableElement<P>);
451 }
452 
453 /**
454  * Convenience API for reading a std::vector<P>
455  */
456 template <typename P>
AParcel_readVector(const AParcel * parcel,std::vector<P> * vec)457 static inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<P>* vec) {
458     void* vectorData = static_cast<void*>(vec);
459     return AParcel_readParcelableArray(parcel, vectorData, AParcel_stdVectorExternalAllocator<P>,
460                                        AParcel_readStdVectorParcelableElement<P>);
461 }
462 
463 // @START
464 /**
465  * Writes a vector of int32_t to the next location in a non-null parcel.
466  */
AParcel_writeVector(AParcel * parcel,const std::vector<int32_t> & vec)467 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int32_t>& vec) {
468     return AParcel_writeInt32Array(parcel, vec.data(), vec.size());
469 }
470 
471 /**
472  * Writes an optional vector of int32_t to the next location in a non-null parcel.
473  */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<int32_t>> & vec)474 inline binder_status_t AParcel_writeVector(AParcel* parcel,
475                                            const std::optional<std::vector<int32_t>>& vec) {
476     if (!vec) return AParcel_writeInt32Array(parcel, nullptr, -1);
477     return AParcel_writeVector(parcel, *vec);
478 }
479 
480 /**
481  * Reads a vector of int32_t from the next location in a non-null parcel.
482  */
AParcel_readVector(const AParcel * parcel,std::vector<int32_t> * vec)483 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int32_t>* vec) {
484     void* vectorData = static_cast<void*>(vec);
485     return AParcel_readInt32Array(parcel, vectorData, AParcel_stdVectorAllocator<int32_t>);
486 }
487 
488 /**
489  * Reads an optional vector of int32_t from the next location in a non-null parcel.
490  */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<int32_t>> * vec)491 inline binder_status_t AParcel_readVector(const AParcel* parcel,
492                                           std::optional<std::vector<int32_t>>* vec) {
493     void* vectorData = static_cast<void*>(vec);
494     return AParcel_readInt32Array(parcel, vectorData, AParcel_nullableStdVectorAllocator<int32_t>);
495 }
496 
497 /**
498  * Writes a vector of uint32_t to the next location in a non-null parcel.
499  */
AParcel_writeVector(AParcel * parcel,const std::vector<uint32_t> & vec)500 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint32_t>& vec) {
501     return AParcel_writeUint32Array(parcel, vec.data(), vec.size());
502 }
503 
504 /**
505  * Writes an optional vector of uint32_t to the next location in a non-null parcel.
506  */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<uint32_t>> & vec)507 inline binder_status_t AParcel_writeVector(AParcel* parcel,
508                                            const std::optional<std::vector<uint32_t>>& vec) {
509     if (!vec) return AParcel_writeUint32Array(parcel, nullptr, -1);
510     return AParcel_writeVector(parcel, *vec);
511 }
512 
513 /**
514  * Reads a vector of uint32_t from the next location in a non-null parcel.
515  */
AParcel_readVector(const AParcel * parcel,std::vector<uint32_t> * vec)516 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint32_t>* vec) {
517     void* vectorData = static_cast<void*>(vec);
518     return AParcel_readUint32Array(parcel, vectorData, AParcel_stdVectorAllocator<uint32_t>);
519 }
520 
521 /**
522  * Reads an optional vector of uint32_t from the next location in a non-null parcel.
523  */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<uint32_t>> * vec)524 inline binder_status_t AParcel_readVector(const AParcel* parcel,
525                                           std::optional<std::vector<uint32_t>>* vec) {
526     void* vectorData = static_cast<void*>(vec);
527     return AParcel_readUint32Array(parcel, vectorData,
528                                    AParcel_nullableStdVectorAllocator<uint32_t>);
529 }
530 
531 /**
532  * Writes a vector of int64_t to the next location in a non-null parcel.
533  */
AParcel_writeVector(AParcel * parcel,const std::vector<int64_t> & vec)534 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int64_t>& vec) {
535     return AParcel_writeInt64Array(parcel, vec.data(), vec.size());
536 }
537 
538 /**
539  * Writes an optional vector of int64_t to the next location in a non-null parcel.
540  */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<int64_t>> & vec)541 inline binder_status_t AParcel_writeVector(AParcel* parcel,
542                                            const std::optional<std::vector<int64_t>>& vec) {
543     if (!vec) return AParcel_writeInt64Array(parcel, nullptr, -1);
544     return AParcel_writeVector(parcel, *vec);
545 }
546 
547 /**
548  * Reads a vector of int64_t from the next location in a non-null parcel.
549  */
AParcel_readVector(const AParcel * parcel,std::vector<int64_t> * vec)550 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int64_t>* vec) {
551     void* vectorData = static_cast<void*>(vec);
552     return AParcel_readInt64Array(parcel, vectorData, AParcel_stdVectorAllocator<int64_t>);
553 }
554 
555 /**
556  * Reads an optional vector of int64_t from the next location in a non-null parcel.
557  */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<int64_t>> * vec)558 inline binder_status_t AParcel_readVector(const AParcel* parcel,
559                                           std::optional<std::vector<int64_t>>* vec) {
560     void* vectorData = static_cast<void*>(vec);
561     return AParcel_readInt64Array(parcel, vectorData, AParcel_nullableStdVectorAllocator<int64_t>);
562 }
563 
564 /**
565  * Writes a vector of uint64_t to the next location in a non-null parcel.
566  */
AParcel_writeVector(AParcel * parcel,const std::vector<uint64_t> & vec)567 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint64_t>& vec) {
568     return AParcel_writeUint64Array(parcel, vec.data(), vec.size());
569 }
570 
571 /**
572  * Writes an optional vector of uint64_t to the next location in a non-null parcel.
573  */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<uint64_t>> & vec)574 inline binder_status_t AParcel_writeVector(AParcel* parcel,
575                                            const std::optional<std::vector<uint64_t>>& vec) {
576     if (!vec) return AParcel_writeUint64Array(parcel, nullptr, -1);
577     return AParcel_writeVector(parcel, *vec);
578 }
579 
580 /**
581  * Reads a vector of uint64_t from the next location in a non-null parcel.
582  */
AParcel_readVector(const AParcel * parcel,std::vector<uint64_t> * vec)583 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint64_t>* vec) {
584     void* vectorData = static_cast<void*>(vec);
585     return AParcel_readUint64Array(parcel, vectorData, AParcel_stdVectorAllocator<uint64_t>);
586 }
587 
588 /**
589  * Reads an optional vector of uint64_t from the next location in a non-null parcel.
590  */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<uint64_t>> * vec)591 inline binder_status_t AParcel_readVector(const AParcel* parcel,
592                                           std::optional<std::vector<uint64_t>>* vec) {
593     void* vectorData = static_cast<void*>(vec);
594     return AParcel_readUint64Array(parcel, vectorData,
595                                    AParcel_nullableStdVectorAllocator<uint64_t>);
596 }
597 
598 /**
599  * Writes a vector of float to the next location in a non-null parcel.
600  */
AParcel_writeVector(AParcel * parcel,const std::vector<float> & vec)601 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<float>& vec) {
602     return AParcel_writeFloatArray(parcel, vec.data(), vec.size());
603 }
604 
605 /**
606  * Writes an optional vector of float to the next location in a non-null parcel.
607  */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<float>> & vec)608 inline binder_status_t AParcel_writeVector(AParcel* parcel,
609                                            const std::optional<std::vector<float>>& vec) {
610     if (!vec) return AParcel_writeFloatArray(parcel, nullptr, -1);
611     return AParcel_writeVector(parcel, *vec);
612 }
613 
614 /**
615  * Reads a vector of float from the next location in a non-null parcel.
616  */
AParcel_readVector(const AParcel * parcel,std::vector<float> * vec)617 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<float>* vec) {
618     void* vectorData = static_cast<void*>(vec);
619     return AParcel_readFloatArray(parcel, vectorData, AParcel_stdVectorAllocator<float>);
620 }
621 
622 /**
623  * Reads an optional vector of float from the next location in a non-null parcel.
624  */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<float>> * vec)625 inline binder_status_t AParcel_readVector(const AParcel* parcel,
626                                           std::optional<std::vector<float>>* vec) {
627     void* vectorData = static_cast<void*>(vec);
628     return AParcel_readFloatArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<float>);
629 }
630 
631 /**
632  * Writes a vector of double to the next location in a non-null parcel.
633  */
AParcel_writeVector(AParcel * parcel,const std::vector<double> & vec)634 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<double>& vec) {
635     return AParcel_writeDoubleArray(parcel, vec.data(), vec.size());
636 }
637 
638 /**
639  * Writes an optional vector of double to the next location in a non-null parcel.
640  */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<double>> & vec)641 inline binder_status_t AParcel_writeVector(AParcel* parcel,
642                                            const std::optional<std::vector<double>>& vec) {
643     if (!vec) return AParcel_writeDoubleArray(parcel, nullptr, -1);
644     return AParcel_writeVector(parcel, *vec);
645 }
646 
647 /**
648  * Reads a vector of double from the next location in a non-null parcel.
649  */
AParcel_readVector(const AParcel * parcel,std::vector<double> * vec)650 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<double>* vec) {
651     void* vectorData = static_cast<void*>(vec);
652     return AParcel_readDoubleArray(parcel, vectorData, AParcel_stdVectorAllocator<double>);
653 }
654 
655 /**
656  * Reads an optional vector of double from the next location in a non-null parcel.
657  */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<double>> * vec)658 inline binder_status_t AParcel_readVector(const AParcel* parcel,
659                                           std::optional<std::vector<double>>* vec) {
660     void* vectorData = static_cast<void*>(vec);
661     return AParcel_readDoubleArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<double>);
662 }
663 
664 /**
665  * Writes a vector of bool to the next location in a non-null parcel.
666  */
AParcel_writeVector(AParcel * parcel,const std::vector<bool> & vec)667 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<bool>& vec) {
668     return AParcel_writeBoolArray(parcel, static_cast<const void*>(&vec), vec.size(),
669                                   AParcel_stdVectorGetter<bool>);
670 }
671 
672 /**
673  * Writes an optional vector of bool to the next location in a non-null parcel.
674  */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<bool>> & vec)675 inline binder_status_t AParcel_writeVector(AParcel* parcel,
676                                            const std::optional<std::vector<bool>>& vec) {
677     if (!vec) return AParcel_writeBoolArray(parcel, nullptr, -1, AParcel_stdVectorGetter<bool>);
678     return AParcel_writeVector(parcel, *vec);
679 }
680 
681 /**
682  * Reads a vector of bool from the next location in a non-null parcel.
683  */
AParcel_readVector(const AParcel * parcel,std::vector<bool> * vec)684 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<bool>* vec) {
685     void* vectorData = static_cast<void*>(vec);
686     return AParcel_readBoolArray(parcel, vectorData, AParcel_stdVectorExternalAllocator<bool>,
687                                  AParcel_stdVectorSetter<bool>);
688 }
689 
690 /**
691  * Reads an optional vector of bool from the next location in a non-null parcel.
692  */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<bool>> * vec)693 inline binder_status_t AParcel_readVector(const AParcel* parcel,
694                                           std::optional<std::vector<bool>>* vec) {
695     void* vectorData = static_cast<void*>(vec);
696     return AParcel_readBoolArray(parcel, vectorData,
697                                  AParcel_nullableStdVectorExternalAllocator<bool>,
698                                  AParcel_nullableStdVectorSetter<bool>);
699 }
700 
701 /**
702  * Writes a vector of char16_t to the next location in a non-null parcel.
703  */
AParcel_writeVector(AParcel * parcel,const std::vector<char16_t> & vec)704 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<char16_t>& vec) {
705     return AParcel_writeCharArray(parcel, vec.data(), vec.size());
706 }
707 
708 /**
709  * Writes an optional vector of char16_t to the next location in a non-null parcel.
710  */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<char16_t>> & vec)711 inline binder_status_t AParcel_writeVector(AParcel* parcel,
712                                            const std::optional<std::vector<char16_t>>& vec) {
713     if (!vec) return AParcel_writeCharArray(parcel, nullptr, -1);
714     return AParcel_writeVector(parcel, *vec);
715 }
716 
717 /**
718  * Reads a vector of char16_t from the next location in a non-null parcel.
719  */
AParcel_readVector(const AParcel * parcel,std::vector<char16_t> * vec)720 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<char16_t>* vec) {
721     void* vectorData = static_cast<void*>(vec);
722     return AParcel_readCharArray(parcel, vectorData, AParcel_stdVectorAllocator<char16_t>);
723 }
724 
725 /**
726  * Reads an optional vector of char16_t from the next location in a non-null parcel.
727  */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<char16_t>> * vec)728 inline binder_status_t AParcel_readVector(const AParcel* parcel,
729                                           std::optional<std::vector<char16_t>>* vec) {
730     void* vectorData = static_cast<void*>(vec);
731     return AParcel_readCharArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<char16_t>);
732 }
733 
734 /**
735  * Writes a vector of int8_t to the next location in a non-null parcel.
736  */
AParcel_writeVector(AParcel * parcel,const std::vector<int8_t> & vec)737 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int8_t>& vec) {
738     return AParcel_writeByteArray(parcel, vec.data(), vec.size());
739 }
740 
741 /**
742  * Writes an optional vector of int8_t to the next location in a non-null parcel.
743  */
AParcel_writeVector(AParcel * parcel,const std::optional<std::vector<int8_t>> & vec)744 inline binder_status_t AParcel_writeVector(AParcel* parcel,
745                                            const std::optional<std::vector<int8_t>>& vec) {
746     if (!vec) return AParcel_writeByteArray(parcel, nullptr, -1);
747     return AParcel_writeVector(parcel, *vec);
748 }
749 
750 /**
751  * Reads a vector of int8_t from the next location in a non-null parcel.
752  */
AParcel_readVector(const AParcel * parcel,std::vector<int8_t> * vec)753 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int8_t>* vec) {
754     void* vectorData = static_cast<void*>(vec);
755     return AParcel_readByteArray(parcel, vectorData, AParcel_stdVectorAllocator<int8_t>);
756 }
757 
758 /**
759  * Reads an optional vector of int8_t from the next location in a non-null parcel.
760  */
AParcel_readVector(const AParcel * parcel,std::optional<std::vector<int8_t>> * vec)761 inline binder_status_t AParcel_readVector(const AParcel* parcel,
762                                           std::optional<std::vector<int8_t>>* vec) {
763     void* vectorData = static_cast<void*>(vec);
764     return AParcel_readByteArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<int8_t>);
765 }
766 
767 // @END
768 
769 /**
770  * Convenience API for writing the size of a vector.
771  */
772 template <typename T>
AParcel_writeVectorSize(AParcel * parcel,const std::vector<T> & vec)773 static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel, const std::vector<T>& vec) {
774     if (vec.size() > INT32_MAX) {
775         return STATUS_BAD_VALUE;
776     }
777 
778     return AParcel_writeInt32(parcel, static_cast<int32_t>(vec.size()));
779 }
780 
781 /**
782  * Convenience API for writing the size of a vector.
783  */
784 template <typename T>
AParcel_writeVectorSize(AParcel * parcel,const std::optional<std::vector<T>> & vec)785 static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel,
786                                                       const std::optional<std::vector<T>>& vec) {
787     if (!vec) {
788         return AParcel_writeInt32(parcel, -1);
789     }
790 
791     if (vec->size() > INT32_MAX) {
792         return STATUS_BAD_VALUE;
793     }
794 
795     return AParcel_writeInt32(parcel, static_cast<int32_t>(vec->size()));
796 }
797 
798 /**
799  * Convenience API for resizing a vector.
800  */
801 template <typename T>
AParcel_resizeVector(const AParcel * parcel,std::vector<T> * vec)802 static inline binder_status_t AParcel_resizeVector(const AParcel* parcel, std::vector<T>* vec) {
803     int32_t size;
804     binder_status_t err = AParcel_readInt32(parcel, &size);
805 
806     if (err != STATUS_OK) return err;
807     if (size < 0) return STATUS_UNEXPECTED_NULL;
808 
809     vec->resize(static_cast<size_t>(size));
810     return STATUS_OK;
811 }
812 
813 /**
814  * Convenience API for resizing a vector.
815  */
816 template <typename T>
AParcel_resizeVector(const AParcel * parcel,std::optional<std::vector<T>> * vec)817 static inline binder_status_t AParcel_resizeVector(const AParcel* parcel,
818                                                    std::optional<std::vector<T>>* vec) {
819     int32_t size;
820     binder_status_t err = AParcel_readInt32(parcel, &size);
821 
822     if (err != STATUS_OK) return err;
823     if (size < -1) return STATUS_UNEXPECTED_NULL;
824 
825     if (size == -1) {
826         *vec = std::nullopt;
827         return STATUS_OK;
828     }
829 
830     *vec = std::optional<std::vector<T>>(std::vector<T>{});
831     (*vec)->resize(static_cast<size_t>(size));
832     return STATUS_OK;
833 }
834 
835 }  // namespace ndk
836 
837 /** @} */
838