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