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_interface_utils.h> 31 #include <android/binder_internal_logging.h> 32 #include <android/binder_parcel.h> 33 34 #include <array> 35 #include <optional> 36 #include <string> 37 #include <type_traits> 38 #include <vector> 39 40 namespace ndk { 41 42 namespace { 43 template <typename Test, template <typename...> class Ref> 44 struct is_specialization : std::false_type {}; 45 46 template <template <typename...> class Ref, typename... Args> 47 struct is_specialization<Ref<Args...>, Ref> : std::true_type {}; 48 49 template <typename Test, template <typename...> class Ref> 50 static inline constexpr bool is_specialization_v = is_specialization<Test, Ref>::value; 51 52 // Get the first template type from a container, the T from MyClass<T, ...>. 53 template <typename T> 54 struct first_template_type { 55 using type = void; 56 }; 57 58 template <template <typename...> class V, typename T, typename... Args> 59 struct first_template_type<V<T, Args...>> { 60 using type = T; 61 }; 62 63 template <typename T> 64 using first_template_type_t = typename first_template_type<T>::type; 65 66 // Tells if T represents NDK interface (shared_ptr<ICInterface-derived>) 67 template <typename T> 68 static inline constexpr bool is_interface_v = is_specialization_v<T, std::shared_ptr>&& 69 std::is_base_of_v<::ndk::ICInterface, first_template_type_t<T>>; 70 71 // Tells if T represents NDK parcelable with readFromParcel/writeToParcel methods defined 72 template <typename T, typename = void> 73 struct is_parcelable : std::false_type {}; 74 75 template <typename T> 76 struct is_parcelable< 77 T, std::void_t<decltype(std::declval<T>().readFromParcel(std::declval<const AParcel*>())), 78 decltype(std::declval<T>().writeToParcel(std::declval<AParcel*>()))>> 79 : std::true_type {}; 80 81 template <typename T> 82 static inline constexpr bool is_parcelable_v = is_parcelable<T>::value; 83 84 // Tells if T represents nullable NDK parcelable (optional<parcelable> or unique_ptr<parcelable>) 85 template <typename T> 86 static inline constexpr bool is_nullable_parcelable_v = is_parcelable_v<first_template_type_t<T>> && 87 (is_specialization_v<T, std::optional> || 88 is_specialization_v<T, std::unique_ptr>); 89 90 // Tells if T is a fixed-size array. 91 template <typename T> 92 struct is_fixed_array : std::false_type {}; 93 94 template <typename T, size_t N> 95 struct is_fixed_array<std::array<T, N>> : std::true_type {}; 96 97 template <typename T> 98 static inline constexpr bool is_fixed_array_v = is_fixed_array<T>::value; 99 100 template <typename T> 101 static inline constexpr bool dependent_false_v = false; 102 } // namespace 103 104 /** 105 * This checks the length against the array size and retrieves the buffer. No allocation required. 106 */ 107 template <typename T, size_t N> 108 static inline bool AParcel_stdArrayAllocator(void* arrayData, int32_t length, T** outBuffer) { 109 if (length < 0) return false; 110 111 if (length != static_cast<int32_t>(N)) { 112 return false; 113 } 114 115 std::array<T, N>* arr = static_cast<std::array<T, N>*>(arrayData); 116 *outBuffer = arr->data(); 117 return true; 118 } 119 120 /** 121 * This checks the length against the array size and retrieves the buffer. No allocation required. 122 */ 123 template <typename T, size_t N> 124 static inline bool AParcel_nullableStdArrayAllocator(void* arrayData, int32_t length, 125 T** outBuffer) { 126 std::optional<std::array<T, N>>* arr = static_cast<std::optional<std::array<T, N>>*>(arrayData); 127 if (length < 0) { 128 *arr = std::nullopt; 129 return true; 130 } 131 132 if (length != static_cast<int32_t>(N)) { 133 return false; 134 } 135 136 arr->emplace(); 137 *outBuffer = (*arr)->data(); 138 return true; 139 } 140 141 /** 142 * This checks the length against the array size. No allocation required. 143 */ 144 template <size_t N> 145 static inline bool AParcel_stdArrayExternalAllocator(void* arrayData, int32_t length) { 146 (void)arrayData; 147 return length == static_cast<int32_t>(N); 148 } 149 150 /** 151 * This checks the length against the array size. No allocation required. 152 */ 153 template <typename T, size_t N> 154 static inline bool AParcel_nullableStdArrayExternalAllocator(void* arrayData, int32_t length) { 155 std::optional<std::array<T, N>>* arr = static_cast<std::optional<std::array<T, N>>*>(arrayData); 156 157 if (length < 0) { 158 *arr = std::nullopt; 159 return true; 160 } 161 162 if (length != static_cast<int32_t>(N)) { 163 return false; 164 } 165 166 arr->emplace(); 167 return true; 168 } 169 170 /** 171 * This retrieves and allocates a vector to size 'length' and returns the underlying buffer. 172 */ 173 template <typename T> 174 static inline bool AParcel_stdVectorAllocator(void* vectorData, int32_t length, T** outBuffer) { 175 if (length < 0) return false; 176 177 std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData); 178 if (static_cast<size_t>(length) > vec->max_size()) return false; 179 180 vec->resize(static_cast<size_t>(length)); 181 *outBuffer = vec->data(); 182 return true; 183 } 184 185 /** 186 * This retrieves and allocates a vector to size 'length' and returns the underlying buffer. 187 */ 188 template <typename T> 189 static inline bool AParcel_nullableStdVectorAllocator(void* vectorData, int32_t length, 190 T** outBuffer) { 191 std::optional<std::vector<T>>* vec = static_cast<std::optional<std::vector<T>>*>(vectorData); 192 193 if (length < 0) { 194 *vec = std::nullopt; 195 return true; 196 } 197 198 *vec = std::optional<std::vector<T>>(std::vector<T>{}); 199 200 if (static_cast<size_t>(length) > (*vec)->max_size()) return false; 201 (*vec)->resize(static_cast<size_t>(length)); 202 203 *outBuffer = (*vec)->data(); 204 return true; 205 } 206 207 /** 208 * This allocates a vector to size 'length' and returns whether the allocation is successful. 209 * 210 * See also AParcel_stdVectorAllocator. Types used with this allocator have their sizes defined 211 * externally with respect to the NDK, and that size information is not passed into the NDK. 212 * Instead, it is used in cases where callbacks are used. Note that when this allocator is used, 213 * null arrays are not supported. 214 * 215 * See AParcel_readVector(const AParcel* parcel, std::vector<bool>) 216 * See AParcel_readVector(const AParcel* parcel, std::vector<std::string>) 217 */ 218 template <typename T> 219 static inline bool AParcel_stdVectorExternalAllocator(void* vectorData, int32_t length) { 220 if (length < 0) return false; 221 222 std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData); 223 if (static_cast<size_t>(length) > vec->max_size()) return false; 224 225 vec->resize(static_cast<size_t>(length)); 226 return true; 227 } 228 229 /** 230 * This allocates a vector to size 'length' and returns whether the allocation is successful. 231 * 232 * See also AParcel_stdVectorAllocator. Types used with this allocator have their sizes defined 233 * externally with respect to the NDK, and that size information is not passed into the NDK. 234 * Instead, it is used in cases where callbacks are used. Note, when this allocator is used, 235 * the vector itself can be nullable. 236 * 237 * See AParcel_readVector(const AParcel* parcel, 238 * std::optional<std::vector<std::optional<std::string>>>) 239 */ 240 template <typename T> 241 static inline bool AParcel_nullableStdVectorExternalAllocator(void* vectorData, int32_t length) { 242 std::optional<std::vector<T>>* vec = static_cast<std::optional<std::vector<T>>*>(vectorData); 243 244 if (length < 0) { 245 *vec = std::nullopt; 246 return true; 247 } 248 249 *vec = std::optional<std::vector<T>>(std::vector<T>{}); 250 251 if (static_cast<size_t>(length) > (*vec)->max_size()) return false; 252 (*vec)->resize(static_cast<size_t>(length)); 253 254 return true; 255 } 256 257 /** 258 * This retrieves the underlying value in a vector which may not be contiguous at index from a 259 * corresponding vectorData. 260 */ 261 template <typename T> 262 static inline T AParcel_stdVectorGetter(const void* vectorData, size_t index) { 263 const std::vector<T>* vec = static_cast<const std::vector<T>*>(vectorData); 264 return (*vec)[index]; 265 } 266 267 /** 268 * This sets the underlying value in a corresponding vectorData which may not be contiguous at 269 * index. 270 */ 271 template <typename T> 272 static inline void AParcel_stdVectorSetter(void* vectorData, size_t index, T value) { 273 std::vector<T>* vec = static_cast<std::vector<T>*>(vectorData); 274 (*vec)[index] = value; 275 } 276 277 /** 278 * This sets the underlying value in a corresponding vectorData which may not be contiguous at 279 * index. 280 */ 281 template <typename T> 282 static inline void AParcel_nullableStdVectorSetter(void* vectorData, size_t index, T value) { 283 std::optional<std::vector<T>>* vec = static_cast<std::optional<std::vector<T>>*>(vectorData); 284 vec->value()[index] = value; 285 } 286 287 /** 288 * Convenience method to write a nullable strong binder. 289 */ 290 static inline binder_status_t AParcel_writeNullableStrongBinder(AParcel* parcel, 291 const SpAIBinder& binder) { 292 return AParcel_writeStrongBinder(parcel, binder.get()); 293 } 294 295 /** 296 * Convenience method to read a nullable strong binder. 297 */ 298 static inline binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel, 299 SpAIBinder* binder) { 300 AIBinder* readBinder; 301 binder_status_t status = AParcel_readStrongBinder(parcel, &readBinder); 302 if (status == STATUS_OK) { 303 binder->set(readBinder); 304 } 305 return status; 306 } 307 308 /** 309 * Convenience method to write a strong binder but return an error if it is null. 310 */ 311 static inline binder_status_t AParcel_writeRequiredStrongBinder(AParcel* parcel, 312 const SpAIBinder& binder) { 313 if (binder.get() == nullptr) { 314 syslog(LOG_ERR, "Passing null binder object as non-@nullable AIDL IBinder"); 315 return STATUS_UNEXPECTED_NULL; 316 } 317 return AParcel_writeStrongBinder(parcel, binder.get()); 318 } 319 320 /** 321 * Convenience method to read a strong binder but return an error if it is null. 322 */ 323 static inline binder_status_t AParcel_readRequiredStrongBinder(const AParcel* parcel, 324 SpAIBinder* binder) { 325 AIBinder* readBinder; 326 binder_status_t ret = AParcel_readStrongBinder(parcel, &readBinder); 327 if (ret == STATUS_OK) { 328 if (readBinder == nullptr) { 329 return STATUS_UNEXPECTED_NULL; 330 } 331 332 binder->set(readBinder); 333 } 334 return ret; 335 } 336 337 /** 338 * Convenience method to write a ParcelFileDescriptor where -1 represents a null value. 339 */ 340 static inline binder_status_t AParcel_writeNullableParcelFileDescriptor( 341 AParcel* parcel, const ScopedFileDescriptor& fd) { 342 return AParcel_writeParcelFileDescriptor(parcel, fd.get()); 343 } 344 345 /** 346 * Convenience method to read a ParcelFileDescriptor where -1 represents a null value. 347 */ 348 static inline binder_status_t AParcel_readNullableParcelFileDescriptor(const AParcel* parcel, 349 ScopedFileDescriptor* fd) { 350 int readFd; 351 binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd); 352 if (status == STATUS_OK) { 353 fd->set(readFd); 354 } 355 return status; 356 } 357 358 /** 359 * Convenience method to write a valid ParcelFileDescriptor. 360 */ 361 static inline binder_status_t AParcel_writeRequiredParcelFileDescriptor( 362 AParcel* parcel, const ScopedFileDescriptor& fd) { 363 if (fd.get() < 0) { 364 syslog(LOG_ERR, "Passing -1 file descriptor as non-@nullable AIDL ParcelFileDescriptor"); 365 return STATUS_UNEXPECTED_NULL; 366 } 367 return AParcel_writeParcelFileDescriptor(parcel, fd.get()); 368 } 369 370 /** 371 * Convenience method to read a valid ParcelFileDescriptor. 372 */ 373 static inline binder_status_t AParcel_readRequiredParcelFileDescriptor(const AParcel* parcel, 374 ScopedFileDescriptor* fd) { 375 int readFd; 376 binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd); 377 if (status == STATUS_OK) { 378 if (readFd < 0) { 379 return STATUS_UNEXPECTED_NULL; 380 } 381 fd->set(readFd); 382 } 383 return status; 384 } 385 386 /** 387 * Allocates a std::string to length and returns the underlying buffer. For use with 388 * AParcel_readString. See use below in AParcel_readString(const AParcel*, std::string*). 389 */ 390 static inline bool AParcel_stdStringAllocator(void* stringData, int32_t length, char** buffer) { 391 if (length <= 0) return false; 392 393 std::string* str = static_cast<std::string*>(stringData); 394 str->resize(static_cast<size_t>(length) - 1); 395 *buffer = &(*str)[0]; 396 return true; 397 } 398 399 /** 400 * Allocates a string in a std::optional<std::string> to size 'length' (or to std::nullopt when 401 * length is -1) and returns the underlying buffer. For use with AParcel_readString. See use below 402 * in AParcel_readString(const AParcel*, std::optional<std::string>*). 403 */ 404 static inline bool AParcel_nullableStdStringAllocator(void* stringData, int32_t length, 405 char** buffer) { 406 if (length == 0) return false; 407 408 std::optional<std::string>* str = static_cast<std::optional<std::string>*>(stringData); 409 410 if (length < 0) { 411 *str = std::nullopt; 412 return true; 413 } 414 415 *str = std::optional<std::string>(std::string{}); 416 (*str)->resize(static_cast<size_t>(length) - 1); 417 *buffer = &(**str)[0]; 418 return true; 419 } 420 421 /** 422 * Allocates a std::string inside of a std::vector<std::string> at index 'index' to size 'length'. 423 */ 424 static inline bool AParcel_stdVectorStringElementAllocator(void* vectorData, size_t index, 425 int32_t length, char** buffer) { 426 std::vector<std::string>* vec = static_cast<std::vector<std::string>*>(vectorData); 427 std::string& element = vec->at(index); 428 return AParcel_stdStringAllocator(static_cast<void*>(&element), length, buffer); 429 } 430 431 /** 432 * This gets the length and buffer of a std::string inside of a std::vector<std::string> at index 433 * index. 434 */ 435 static inline const char* AParcel_stdVectorStringElementGetter(const void* vectorData, size_t index, 436 int32_t* outLength) { 437 const std::vector<std::string>* vec = static_cast<const std::vector<std::string>*>(vectorData); 438 const std::string& element = vec->at(index); 439 440 *outLength = static_cast<int32_t>(element.size()); 441 return element.c_str(); 442 } 443 444 /** 445 * Allocates a string in a std::optional<std::string> inside of a 446 * std::optional<std::vector<std::optional<std::string>>> at index 'index' to size 'length' (or to 447 * std::nullopt when length is -1). 448 */ 449 static inline bool AParcel_nullableStdVectorStringElementAllocator(void* vectorData, size_t index, 450 int32_t length, char** buffer) { 451 std::optional<std::vector<std::optional<std::string>>>* vec = 452 static_cast<std::optional<std::vector<std::optional<std::string>>>*>(vectorData); 453 std::optional<std::string>& element = vec->value().at(index); 454 return AParcel_nullableStdStringAllocator(static_cast<void*>(&element), length, buffer); 455 } 456 457 /** 458 * This gets the length and buffer of a std::optional<std::string> inside of a 459 * std::vector<std::string> at index index. If the string is null, then it returns null and a length 460 * of -1. 461 */ 462 static inline const char* AParcel_nullableStdVectorStringElementGetter(const void* vectorData, 463 size_t index, 464 int32_t* outLength) { 465 const std::optional<std::vector<std::optional<std::string>>>* vec = 466 static_cast<const std::optional<std::vector<std::optional<std::string>>>*>(vectorData); 467 const std::optional<std::string>& element = vec->value().at(index); 468 469 if (!element) { 470 *outLength = -1; 471 return nullptr; 472 } 473 474 *outLength = static_cast<int32_t>(element->size()); 475 return element->c_str(); 476 } 477 478 /** 479 * This retrieves the underlying value in a std::array which may not be contiguous at index from a 480 * corresponding arrData. 481 */ 482 template <typename T, size_t N> 483 static inline T AParcel_stdArrayGetter(const void* arrData, size_t index) { 484 const std::array<T, N>* arr = static_cast<const std::array<T, N>*>(arrData); 485 return (*arr)[index]; 486 } 487 488 /** 489 * This sets the underlying value in a corresponding arrData which may not be contiguous at 490 * index. 491 */ 492 template <typename T, size_t N> 493 static inline void AParcel_stdArraySetter(void* arrData, size_t index, T value) { 494 std::array<T, N>* arr = static_cast<std::array<T, N>*>(arrData); 495 (*arr)[index] = value; 496 } 497 498 /** 499 * This retrieves the underlying value in a std::array which may not be contiguous at index from a 500 * corresponding arrData. 501 */ 502 template <typename T, size_t N> 503 static inline T AParcel_nullableStdArrayGetter(const void* arrData, size_t index) { 504 const std::optional<std::array<T, N>>* arr = 505 static_cast<const std::optional<std::array<T, N>>*>(arrData); 506 return (*arr)[index]; 507 } 508 509 /** 510 * This sets the underlying value in a corresponding arrData which may not be contiguous at 511 * index. 512 */ 513 template <typename T, size_t N> 514 static inline void AParcel_nullableStdArraySetter(void* arrData, size_t index, T value) { 515 std::optional<std::array<T, N>>* arr = static_cast<std::optional<std::array<T, N>>*>(arrData); 516 (*arr)->at(index) = value; 517 } 518 519 /** 520 * Allocates a std::string inside of std::array<std::string, N> at index 'index' to size 'length'. 521 */ 522 template <size_t N> 523 static inline bool AParcel_stdArrayStringElementAllocator(void* arrData, size_t index, 524 int32_t length, char** buffer) { 525 std::array<std::string, N>* arr = static_cast<std::array<std::string, N>*>(arrData); 526 std::string& element = arr->at(index); 527 return AParcel_stdStringAllocator(static_cast<void*>(&element), length, buffer); 528 } 529 530 /** 531 * This gets the length and buffer of a std::string inside of a std::array<std::string, N> at index 532 * 'index'. 533 */ 534 template <size_t N> 535 static const char* AParcel_stdArrayStringElementGetter(const void* arrData, size_t index, 536 int32_t* outLength) { 537 const std::array<std::string, N>* arr = static_cast<const std::array<std::string, N>*>(arrData); 538 const std::string& element = arr->at(index); 539 540 *outLength = static_cast<int32_t>(element.size()); 541 return element.c_str(); 542 } 543 544 /** 545 * Allocates a std::string inside of std::array<std::optional<std::string>, N> at index 'index' to 546 * size 'length'. 547 */ 548 template <size_t N> 549 static inline bool AParcel_stdArrayNullableStringElementAllocator(void* arrData, size_t index, 550 int32_t length, char** buffer) { 551 std::array<std::optional<std::string>, N>* arr = 552 static_cast<std::array<std::optional<std::string>, N>*>(arrData); 553 std::optional<std::string>& element = arr->at(index); 554 return AParcel_nullableStdStringAllocator(static_cast<void*>(&element), length, buffer); 555 } 556 557 /** 558 * This gets the length and buffer of a std::string inside of a 559 * std::array<std::optional<std::string>, N> at index 'index'. 560 */ 561 template <size_t N> 562 static const char* AParcel_stdArrayNullableStringElementGetter(const void* arrData, size_t index, 563 int32_t* outLength) { 564 const std::array<std::optional<std::string>, N>* arr = 565 static_cast<const std::array<std::optional<std::string>, N>*>(arrData); 566 const std::optional<std::string>& element = arr->at(index); 567 568 if (!element) { 569 *outLength = -1; 570 return nullptr; 571 } 572 573 *outLength = static_cast<int32_t>(element->size()); 574 return element->c_str(); 575 } 576 577 /** 578 * Allocates a std::string inside of std::optional<std::array<std::optional<std::string>, N>> at 579 * index 'index' to size 'length'. 580 */ 581 template <size_t N> 582 static inline bool AParcel_nullableStdArrayStringElementAllocator(void* arrData, size_t index, 583 int32_t length, char** buffer) { 584 std::optional<std::array<std::optional<std::string>, N>>* arr = 585 static_cast<std::optional<std::array<std::optional<std::string>, N>>*>(arrData); 586 std::optional<std::string>& element = (*arr)->at(index); 587 return AParcel_nullableStdStringAllocator(static_cast<void*>(&element), length, buffer); 588 } 589 590 /** 591 * Convenience API for writing a std::string. 592 */ 593 static inline binder_status_t AParcel_writeString(AParcel* parcel, const std::string& str) { 594 return AParcel_writeString(parcel, str.c_str(), static_cast<int32_t>(str.size())); 595 } 596 597 /** 598 * Convenience API for reading a std::string. 599 */ 600 static inline binder_status_t AParcel_readString(const AParcel* parcel, std::string* str) { 601 void* stringData = static_cast<void*>(str); 602 return AParcel_readString(parcel, stringData, AParcel_stdStringAllocator); 603 } 604 605 /** 606 * Convenience API for writing a std::optional<std::string>. 607 */ 608 static inline binder_status_t AParcel_writeString(AParcel* parcel, 609 const std::optional<std::string>& str) { 610 if (!str) { 611 return AParcel_writeString(parcel, nullptr, -1); 612 } 613 614 return AParcel_writeString(parcel, str->c_str(), static_cast<int32_t>(str->size())); 615 } 616 617 /** 618 * Convenience API for reading a std::optional<std::string>. 619 */ 620 static inline binder_status_t AParcel_readString(const AParcel* parcel, 621 std::optional<std::string>* str) { 622 void* stringData = static_cast<void*>(str); 623 return AParcel_readString(parcel, stringData, AParcel_nullableStdStringAllocator); 624 } 625 626 /** 627 * Convenience API for writing a std::vector<std::string> 628 */ 629 static inline binder_status_t AParcel_writeVector(AParcel* parcel, 630 const std::vector<std::string>& vec) { 631 const void* vectorData = static_cast<const void*>(&vec); 632 return AParcel_writeStringArray(parcel, vectorData, static_cast<int32_t>(vec.size()), 633 AParcel_stdVectorStringElementGetter); 634 } 635 636 /** 637 * Convenience API for reading a std::vector<std::string> 638 */ 639 static inline binder_status_t AParcel_readVector(const AParcel* parcel, 640 std::vector<std::string>* vec) { 641 void* vectorData = static_cast<void*>(vec); 642 return AParcel_readStringArray(parcel, vectorData, 643 AParcel_stdVectorExternalAllocator<std::string>, 644 AParcel_stdVectorStringElementAllocator); 645 } 646 647 /** 648 * Convenience API for writing a std::optional<std::vector<std::optional<std::string>>> 649 */ 650 static inline binder_status_t AParcel_writeVector( 651 AParcel* parcel, const std::optional<std::vector<std::optional<std::string>>>& vec) { 652 const void* vectorData = static_cast<const void*>(&vec); 653 return AParcel_writeStringArray(parcel, vectorData, 654 (vec ? static_cast<int32_t>(vec->size()) : -1), 655 AParcel_nullableStdVectorStringElementGetter); 656 } 657 658 /** 659 * Convenience API for reading a std::optional<std::vector<std::optional<std::string>>> 660 */ 661 static inline binder_status_t AParcel_readVector( 662 const AParcel* parcel, std::optional<std::vector<std::optional<std::string>>>* vec) { 663 void* vectorData = static_cast<void*>(vec); 664 return AParcel_readStringArray( 665 parcel, vectorData, 666 AParcel_nullableStdVectorExternalAllocator<std::optional<std::string>>, 667 AParcel_nullableStdVectorStringElementAllocator); 668 } 669 670 /** 671 * Convenience API for writing a non-null parcelable. 672 */ 673 template <typename P> 674 static inline binder_status_t AParcel_writeParcelable(AParcel* parcel, const P& p) { 675 if constexpr (is_interface_v<P>) { 676 // Legacy behavior: allow null 677 return first_template_type_t<P>::writeToParcel(parcel, p); 678 } else { 679 static_assert(is_parcelable_v<P>); 680 binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null 681 if (status != STATUS_OK) { 682 return status; 683 } 684 return p.writeToParcel(parcel); 685 } 686 } 687 688 /** 689 * Convenience API for reading a non-null parcelable. 690 */ 691 template <typename P> 692 static inline binder_status_t AParcel_readParcelable(const AParcel* parcel, P* p) { 693 if constexpr (is_interface_v<P>) { 694 // Legacy behavior: allow null 695 return first_template_type_t<P>::readFromParcel(parcel, p); 696 } else { 697 static_assert(is_parcelable_v<P>); 698 int32_t null; 699 binder_status_t status = AParcel_readInt32(parcel, &null); 700 if (status != STATUS_OK) { 701 return status; 702 } 703 if (null == 0) { 704 return STATUS_UNEXPECTED_NULL; 705 } 706 return p->readFromParcel(parcel); 707 } 708 } 709 710 /** 711 * Convenience API for writing a nullable parcelable. 712 */ 713 template <typename P> 714 static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel, const P& p) { 715 if constexpr (is_interface_v<P>) { 716 return first_template_type_t<P>::writeToParcel(parcel, p); 717 } else { 718 static_assert(is_nullable_parcelable_v<P>); 719 if (!p) { 720 return AParcel_writeInt32(parcel, 0); // null 721 } 722 binder_status_t status = AParcel_writeInt32(parcel, 1); // non-null 723 if (status != STATUS_OK) { 724 return status; 725 } 726 return p->writeToParcel(parcel); 727 } 728 } 729 730 /** 731 * Convenience API for reading a nullable parcelable. 732 */ 733 template <typename P> 734 static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel, P* p) { 735 if constexpr (is_interface_v<P>) { 736 return first_template_type_t<P>::readFromParcel(parcel, p); 737 } else if constexpr (is_specialization_v<P, std::optional>) { 738 int32_t null; 739 binder_status_t status = AParcel_readInt32(parcel, &null); 740 if (status != STATUS_OK) { 741 return status; 742 } 743 if (null == 0) { 744 *p = std::nullopt; 745 return STATUS_OK; 746 } 747 p->emplace(first_template_type_t<P>()); 748 return (*p)->readFromParcel(parcel); 749 } else { 750 static_assert(is_specialization_v<P, std::unique_ptr>); 751 int32_t null; 752 binder_status_t status = AParcel_readInt32(parcel, &null); 753 if (status != STATUS_OK) { 754 return status; 755 } 756 if (null == 0) { 757 p->reset(); 758 return STATUS_OK; 759 } 760 *p = std::make_unique<first_template_type_t<P>>(); 761 return (*p)->readFromParcel(parcel); 762 } 763 } 764 765 // Forward decls 766 template <typename T> 767 static inline binder_status_t AParcel_writeData(AParcel* parcel, const T& value); 768 template <typename T> 769 static inline binder_status_t AParcel_writeNullableData(AParcel* parcel, const T& value); 770 template <typename T> 771 static inline binder_status_t AParcel_readData(const AParcel* parcel, T* value); 772 template <typename T> 773 static inline binder_status_t AParcel_readNullableData(const AParcel* parcel, T* value); 774 775 /** 776 * Reads an object of type T inside a std::array<T, N> at index 'index' from 'parcel'. 777 */ 778 template <typename T, size_t N> 779 binder_status_t AParcel_readStdArrayData(const AParcel* parcel, void* arrayData, size_t index) { 780 std::array<T, N>* arr = static_cast<std::array<T, N>*>(arrayData); 781 return AParcel_readData(parcel, &arr->at(index)); 782 } 783 784 /** 785 * Reads a nullable object of type T inside a std::array<T, N> at index 'index' from 'parcel'. 786 */ 787 template <typename T, size_t N> 788 binder_status_t AParcel_readStdArrayNullableData(const AParcel* parcel, void* arrayData, 789 size_t index) { 790 std::array<T, N>* arr = static_cast<std::array<T, N>*>(arrayData); 791 return AParcel_readNullableData(parcel, &arr->at(index)); 792 } 793 794 /** 795 * Reads a nullable object of type T inside a std::array<T, N> at index 'index' from 'parcel'. 796 */ 797 template <typename T, size_t N> 798 binder_status_t AParcel_readNullableStdArrayNullableData(const AParcel* parcel, void* arrayData, 799 size_t index) { 800 std::optional<std::array<T, N>>* arr = static_cast<std::optional<std::array<T, N>>*>(arrayData); 801 return AParcel_readNullableData(parcel, &(*arr)->at(index)); 802 } 803 804 /** 805 * Writes an object of type T inside a std::array<T, N> at index 'index' to 'parcel'. 806 */ 807 template <typename T, size_t N> 808 binder_status_t AParcel_writeStdArrayData(AParcel* parcel, const void* arrayData, size_t index) { 809 const std::array<T, N>* arr = static_cast<const std::array<T, N>*>(arrayData); 810 return AParcel_writeData(parcel, arr->at(index)); 811 } 812 813 /** 814 * Writes a nullable object of type T inside a std::array<T, N> at index 'index' to 'parcel'. 815 */ 816 template <typename T, size_t N> 817 binder_status_t AParcel_writeStdArrayNullableData(AParcel* parcel, const void* arrayData, 818 size_t index) { 819 const std::array<T, N>* arr = static_cast<const std::array<T, N>*>(arrayData); 820 return AParcel_writeNullableData(parcel, arr->at(index)); 821 } 822 823 /** 824 * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'. 825 */ 826 template <typename P> 827 binder_status_t AParcel_writeStdVectorParcelableElement(AParcel* parcel, const void* vectorData, 828 size_t index) { 829 const std::vector<P>* vector = static_cast<const std::vector<P>*>(vectorData); 830 return AParcel_writeParcelable(parcel, vector->at(index)); 831 } 832 833 /** 834 * Reads a parcelable object of type P inside a std::vector<P> at index 'index' from 'parcel'. 835 */ 836 template <typename P> 837 binder_status_t AParcel_readStdVectorParcelableElement(const AParcel* parcel, void* vectorData, 838 size_t index) { 839 std::vector<P>* vector = static_cast<std::vector<P>*>(vectorData); 840 return AParcel_readParcelable(parcel, &vector->at(index)); 841 } 842 843 /** 844 * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'. 845 */ 846 template <typename P> 847 binder_status_t AParcel_writeNullableStdVectorParcelableElement(AParcel* parcel, 848 const void* vectorData, 849 size_t index) { 850 const std::optional<std::vector<P>>* vector = 851 static_cast<const std::optional<std::vector<P>>*>(vectorData); 852 return AParcel_writeNullableParcelable(parcel, (*vector)->at(index)); 853 } 854 855 /** 856 * Reads a parcelable object of type P inside a std::vector<P> at index 'index' from 'parcel'. 857 */ 858 template <typename P> 859 binder_status_t AParcel_readNullableStdVectorParcelableElement(const AParcel* parcel, 860 void* vectorData, size_t index) { 861 std::optional<std::vector<P>>* vector = static_cast<std::optional<std::vector<P>>*>(vectorData); 862 return AParcel_readNullableParcelable(parcel, &(*vector)->at(index)); 863 } 864 865 /** 866 * Writes a ScopedFileDescriptor object inside a std::vector<ScopedFileDescriptor> at index 'index' 867 * to 'parcel'. 868 */ 869 template <> 870 inline binder_status_t AParcel_writeStdVectorParcelableElement<ScopedFileDescriptor>( 871 AParcel* parcel, const void* vectorData, size_t index) { 872 const std::vector<ScopedFileDescriptor>* vector = 873 static_cast<const std::vector<ScopedFileDescriptor>*>(vectorData); 874 return AParcel_writeRequiredParcelFileDescriptor(parcel, vector->at(index)); 875 } 876 877 /** 878 * Reads a ScopedFileDescriptor object inside a std::vector<ScopedFileDescriptor> at index 'index' 879 * from 'parcel'. 880 */ 881 template <> 882 inline binder_status_t AParcel_readStdVectorParcelableElement<ScopedFileDescriptor>( 883 const AParcel* parcel, void* vectorData, size_t index) { 884 std::vector<ScopedFileDescriptor>* vector = 885 static_cast<std::vector<ScopedFileDescriptor>*>(vectorData); 886 return AParcel_readRequiredParcelFileDescriptor(parcel, &vector->at(index)); 887 } 888 889 /** 890 * Writes a ScopedFileDescriptor object inside a std::optional<std::vector<ScopedFileDescriptor>> at 891 * index 'index' to 'parcel'. 892 */ 893 template <> 894 inline binder_status_t AParcel_writeNullableStdVectorParcelableElement<ScopedFileDescriptor>( 895 AParcel* parcel, const void* vectorData, size_t index) { 896 const std::optional<std::vector<ScopedFileDescriptor>>* vector = 897 static_cast<const std::optional<std::vector<ScopedFileDescriptor>>*>(vectorData); 898 return AParcel_writeNullableParcelFileDescriptor(parcel, (*vector)->at(index)); 899 } 900 901 /** 902 * Reads a ScopedFileDescriptor object inside a std::optional<std::vector<ScopedFileDescriptor>> at 903 * index 'index' from 'parcel'. 904 */ 905 template <> 906 inline binder_status_t AParcel_readNullableStdVectorParcelableElement<ScopedFileDescriptor>( 907 const AParcel* parcel, void* vectorData, size_t index) { 908 std::optional<std::vector<ScopedFileDescriptor>>* vector = 909 static_cast<std::optional<std::vector<ScopedFileDescriptor>>*>(vectorData); 910 return AParcel_readNullableParcelFileDescriptor(parcel, &(*vector)->at(index)); 911 } 912 913 /** 914 * Writes an SpAIBinder object inside a std::vector<SpAIBinder> at index 'index' 915 * to 'parcel'. 916 */ 917 template <> 918 inline binder_status_t AParcel_writeStdVectorParcelableElement<SpAIBinder>(AParcel* parcel, 919 const void* vectorData, 920 size_t index) { 921 const std::vector<SpAIBinder>* vector = static_cast<const std::vector<SpAIBinder>*>(vectorData); 922 return AParcel_writeRequiredStrongBinder(parcel, vector->at(index)); 923 } 924 925 /** 926 * Reads an SpAIBinder object inside a std::vector<SpAIBinder> at index 'index' 927 * from 'parcel'. 928 */ 929 template <> 930 inline binder_status_t AParcel_readStdVectorParcelableElement<SpAIBinder>(const AParcel* parcel, 931 void* vectorData, 932 size_t index) { 933 std::vector<SpAIBinder>* vector = static_cast<std::vector<SpAIBinder>*>(vectorData); 934 return AParcel_readRequiredStrongBinder(parcel, &vector->at(index)); 935 } 936 937 /** 938 * Writes an SpAIBinder object inside a std::optional<std::vector<SpAIBinder>> at index 'index' 939 * to 'parcel'. 940 */ 941 template <> 942 inline binder_status_t AParcel_writeNullableStdVectorParcelableElement<SpAIBinder>( 943 AParcel* parcel, const void* vectorData, size_t index) { 944 const std::optional<std::vector<SpAIBinder>>* vector = 945 static_cast<const std::optional<std::vector<SpAIBinder>>*>(vectorData); 946 return AParcel_writeNullableStrongBinder(parcel, (*vector)->at(index)); 947 } 948 949 /** 950 * Reads an SpAIBinder object inside a std::optional<std::vector<SpAIBinder>> at index 'index' 951 * from 'parcel'. 952 */ 953 template <> 954 inline binder_status_t AParcel_readNullableStdVectorParcelableElement<SpAIBinder>( 955 const AParcel* parcel, void* vectorData, size_t index) { 956 std::optional<std::vector<SpAIBinder>>* vector = 957 static_cast<std::optional<std::vector<SpAIBinder>>*>(vectorData); 958 return AParcel_readNullableStrongBinder(parcel, &(*vector)->at(index)); 959 } 960 961 /** 962 * Convenience API for writing a std::vector<P> 963 */ 964 template <typename P> 965 static inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<P>& vec) { 966 if constexpr (std::is_enum_v<P>) { 967 if constexpr (std::is_same_v<std::underlying_type_t<P>, int8_t>) { 968 return AParcel_writeByteArray(parcel, reinterpret_cast<const int8_t*>(vec.data()), 969 static_cast<int32_t>(vec.size())); 970 } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int32_t>) { 971 return AParcel_writeInt32Array(parcel, reinterpret_cast<const int32_t*>(vec.data()), 972 static_cast<int32_t>(vec.size())); 973 } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int64_t>) { 974 return AParcel_writeInt64Array(parcel, reinterpret_cast<const int64_t*>(vec.data()), 975 static_cast<int32_t>(vec.size())); 976 } else { 977 static_assert(dependent_false_v<P>, "unrecognized type"); 978 } 979 } else { 980 static_assert(!std::is_same_v<P, std::string>, "specialization should be used"); 981 const void* vectorData = static_cast<const void*>(&vec); 982 return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec.size()), 983 AParcel_writeStdVectorParcelableElement<P>); 984 } 985 } 986 987 /** 988 * Convenience API for reading a std::vector<P> 989 */ 990 template <typename P> 991 static inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<P>* vec) { 992 if constexpr (std::is_enum_v<P>) { 993 void* vectorData = static_cast<void*>(vec); 994 if constexpr (std::is_same_v<std::underlying_type_t<P>, int8_t>) { 995 return AParcel_readByteArray(parcel, vectorData, AParcel_stdVectorAllocator<int8_t>); 996 } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int32_t>) { 997 return AParcel_readInt32Array(parcel, vectorData, AParcel_stdVectorAllocator<int32_t>); 998 } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int64_t>) { 999 return AParcel_readInt64Array(parcel, vectorData, AParcel_stdVectorAllocator<int64_t>); 1000 } else { 1001 static_assert(dependent_false_v<P>, "unrecognized type"); 1002 } 1003 } else { 1004 static_assert(!std::is_same_v<P, std::string>, "specialization should be used"); 1005 void* vectorData = static_cast<void*>(vec); 1006 return AParcel_readParcelableArray(parcel, vectorData, 1007 AParcel_stdVectorExternalAllocator<P>, 1008 AParcel_readStdVectorParcelableElement<P>); 1009 } 1010 } 1011 1012 /** 1013 * Convenience API for writing a std::optional<std::vector<P>> 1014 */ 1015 template <typename P> 1016 static inline binder_status_t AParcel_writeVector(AParcel* parcel, 1017 const std::optional<std::vector<P>>& vec) { 1018 if constexpr (std::is_enum_v<P>) { 1019 if constexpr (std::is_same_v<std::underlying_type_t<P>, int8_t>) { 1020 return AParcel_writeByteArray( 1021 parcel, vec ? reinterpret_cast<const int8_t*>(vec->data()) : nullptr, 1022 vec ? static_cast<int32_t>(vec->size()) : -1); 1023 } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int32_t>) { 1024 return AParcel_writeInt32Array( 1025 parcel, vec ? reinterpret_cast<const int32_t*>(vec->data()) : nullptr, 1026 vec ? static_cast<int32_t>(vec->size()) : -1); 1027 } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int64_t>) { 1028 return AParcel_writeInt64Array( 1029 parcel, vec ? reinterpret_cast<const int64_t*>(vec->data()) : nullptr, 1030 vec ? static_cast<int32_t>(vec->size()) : -1); 1031 } else { 1032 static_assert(dependent_false_v<P>, "unrecognized type"); 1033 } 1034 } else { 1035 static_assert(!std::is_same_v<P, std::optional<std::string>>, 1036 "specialization should be used"); 1037 if (!vec) return AParcel_writeInt32(parcel, -1); 1038 const void* vectorData = static_cast<const void*>(&vec); 1039 return AParcel_writeParcelableArray(parcel, vectorData, static_cast<int32_t>(vec->size()), 1040 AParcel_writeNullableStdVectorParcelableElement<P>); 1041 } 1042 } 1043 1044 /** 1045 * Convenience API for reading a std::optional<std::vector<P>> 1046 */ 1047 template <typename P> 1048 static inline binder_status_t AParcel_readVector(const AParcel* parcel, 1049 std::optional<std::vector<P>>* vec) { 1050 if constexpr (std::is_enum_v<P>) { 1051 void* vectorData = static_cast<void*>(vec); 1052 if constexpr (std::is_same_v<std::underlying_type_t<P>, int8_t>) { 1053 return AParcel_readByteArray(parcel, vectorData, 1054 AParcel_nullableStdVectorAllocator<int8_t>); 1055 } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int32_t>) { 1056 return AParcel_readInt32Array(parcel, vectorData, 1057 AParcel_nullableStdVectorAllocator<int32_t>); 1058 } else if constexpr (std::is_same_v<std::underlying_type_t<P>, int64_t>) { 1059 return AParcel_readInt64Array(parcel, vectorData, 1060 AParcel_nullableStdVectorAllocator<int64_t>); 1061 } else { 1062 static_assert(dependent_false_v<P>, "unrecognized type"); 1063 } 1064 } else { 1065 static_assert(!std::is_same_v<P, std::optional<std::string>>, 1066 "specialization should be used"); 1067 void* vectorData = static_cast<void*>(vec); 1068 return AParcel_readParcelableArray(parcel, vectorData, 1069 AParcel_nullableStdVectorExternalAllocator<P>, 1070 AParcel_readNullableStdVectorParcelableElement<P>); 1071 } 1072 } 1073 1074 // @START 1075 /** 1076 * Writes a vector of int32_t to the next location in a non-null parcel. 1077 */ 1078 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int32_t>& vec) { 1079 return AParcel_writeInt32Array(parcel, vec.data(), static_cast<int32_t>(vec.size())); 1080 } 1081 1082 /** 1083 * Writes an optional vector of int32_t to the next location in a non-null parcel. 1084 */ 1085 inline binder_status_t AParcel_writeVector(AParcel* parcel, 1086 const std::optional<std::vector<int32_t>>& vec) { 1087 if (!vec) return AParcel_writeInt32Array(parcel, nullptr, -1); 1088 return AParcel_writeVector(parcel, *vec); 1089 } 1090 1091 /** 1092 * Reads a vector of int32_t from the next location in a non-null parcel. 1093 */ 1094 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int32_t>* vec) { 1095 void* vectorData = static_cast<void*>(vec); 1096 return AParcel_readInt32Array(parcel, vectorData, AParcel_stdVectorAllocator<int32_t>); 1097 } 1098 1099 /** 1100 * Reads an optional vector of int32_t from the next location in a non-null parcel. 1101 */ 1102 inline binder_status_t AParcel_readVector(const AParcel* parcel, 1103 std::optional<std::vector<int32_t>>* vec) { 1104 void* vectorData = static_cast<void*>(vec); 1105 return AParcel_readInt32Array(parcel, vectorData, AParcel_nullableStdVectorAllocator<int32_t>); 1106 } 1107 1108 /** 1109 * Writes a vector of uint32_t to the next location in a non-null parcel. 1110 */ 1111 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint32_t>& vec) { 1112 return AParcel_writeUint32Array(parcel, vec.data(), static_cast<int32_t>(vec.size())); 1113 } 1114 1115 /** 1116 * Writes an optional vector of uint32_t to the next location in a non-null parcel. 1117 */ 1118 inline binder_status_t AParcel_writeVector(AParcel* parcel, 1119 const std::optional<std::vector<uint32_t>>& vec) { 1120 if (!vec) return AParcel_writeUint32Array(parcel, nullptr, -1); 1121 return AParcel_writeVector(parcel, *vec); 1122 } 1123 1124 /** 1125 * Reads a vector of uint32_t from the next location in a non-null parcel. 1126 */ 1127 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint32_t>* vec) { 1128 void* vectorData = static_cast<void*>(vec); 1129 return AParcel_readUint32Array(parcel, vectorData, AParcel_stdVectorAllocator<uint32_t>); 1130 } 1131 1132 /** 1133 * Reads an optional vector of uint32_t from the next location in a non-null parcel. 1134 */ 1135 inline binder_status_t AParcel_readVector(const AParcel* parcel, 1136 std::optional<std::vector<uint32_t>>* vec) { 1137 void* vectorData = static_cast<void*>(vec); 1138 return AParcel_readUint32Array(parcel, vectorData, 1139 AParcel_nullableStdVectorAllocator<uint32_t>); 1140 } 1141 1142 /** 1143 * Writes a vector of int64_t to the next location in a non-null parcel. 1144 */ 1145 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<int64_t>& vec) { 1146 return AParcel_writeInt64Array(parcel, vec.data(), static_cast<int32_t>(vec.size())); 1147 } 1148 1149 /** 1150 * Writes an optional vector of int64_t to the next location in a non-null parcel. 1151 */ 1152 inline binder_status_t AParcel_writeVector(AParcel* parcel, 1153 const std::optional<std::vector<int64_t>>& vec) { 1154 if (!vec) return AParcel_writeInt64Array(parcel, nullptr, -1); 1155 return AParcel_writeVector(parcel, *vec); 1156 } 1157 1158 /** 1159 * Reads a vector of int64_t from the next location in a non-null parcel. 1160 */ 1161 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<int64_t>* vec) { 1162 void* vectorData = static_cast<void*>(vec); 1163 return AParcel_readInt64Array(parcel, vectorData, AParcel_stdVectorAllocator<int64_t>); 1164 } 1165 1166 /** 1167 * Reads an optional vector of int64_t from the next location in a non-null parcel. 1168 */ 1169 inline binder_status_t AParcel_readVector(const AParcel* parcel, 1170 std::optional<std::vector<int64_t>>* vec) { 1171 void* vectorData = static_cast<void*>(vec); 1172 return AParcel_readInt64Array(parcel, vectorData, AParcel_nullableStdVectorAllocator<int64_t>); 1173 } 1174 1175 /** 1176 * Writes a vector of uint64_t to the next location in a non-null parcel. 1177 */ 1178 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint64_t>& vec) { 1179 return AParcel_writeUint64Array(parcel, vec.data(), static_cast<int32_t>(vec.size())); 1180 } 1181 1182 /** 1183 * Writes an optional vector of uint64_t to the next location in a non-null parcel. 1184 */ 1185 inline binder_status_t AParcel_writeVector(AParcel* parcel, 1186 const std::optional<std::vector<uint64_t>>& vec) { 1187 if (!vec) return AParcel_writeUint64Array(parcel, nullptr, -1); 1188 return AParcel_writeVector(parcel, *vec); 1189 } 1190 1191 /** 1192 * Reads a vector of uint64_t from the next location in a non-null parcel. 1193 */ 1194 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint64_t>* vec) { 1195 void* vectorData = static_cast<void*>(vec); 1196 return AParcel_readUint64Array(parcel, vectorData, AParcel_stdVectorAllocator<uint64_t>); 1197 } 1198 1199 /** 1200 * Reads an optional vector of uint64_t from the next location in a non-null parcel. 1201 */ 1202 inline binder_status_t AParcel_readVector(const AParcel* parcel, 1203 std::optional<std::vector<uint64_t>>* vec) { 1204 void* vectorData = static_cast<void*>(vec); 1205 return AParcel_readUint64Array(parcel, vectorData, 1206 AParcel_nullableStdVectorAllocator<uint64_t>); 1207 } 1208 1209 /** 1210 * Writes a vector of float to the next location in a non-null parcel. 1211 */ 1212 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<float>& vec) { 1213 return AParcel_writeFloatArray(parcel, vec.data(), static_cast<int32_t>(vec.size())); 1214 } 1215 1216 /** 1217 * Writes an optional vector of float to the next location in a non-null parcel. 1218 */ 1219 inline binder_status_t AParcel_writeVector(AParcel* parcel, 1220 const std::optional<std::vector<float>>& vec) { 1221 if (!vec) return AParcel_writeFloatArray(parcel, nullptr, -1); 1222 return AParcel_writeVector(parcel, *vec); 1223 } 1224 1225 /** 1226 * Reads a vector of float from the next location in a non-null parcel. 1227 */ 1228 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<float>* vec) { 1229 void* vectorData = static_cast<void*>(vec); 1230 return AParcel_readFloatArray(parcel, vectorData, AParcel_stdVectorAllocator<float>); 1231 } 1232 1233 /** 1234 * Reads an optional vector of float from the next location in a non-null parcel. 1235 */ 1236 inline binder_status_t AParcel_readVector(const AParcel* parcel, 1237 std::optional<std::vector<float>>* vec) { 1238 void* vectorData = static_cast<void*>(vec); 1239 return AParcel_readFloatArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<float>); 1240 } 1241 1242 /** 1243 * Writes a vector of double to the next location in a non-null parcel. 1244 */ 1245 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<double>& vec) { 1246 return AParcel_writeDoubleArray(parcel, vec.data(), static_cast<int32_t>(vec.size())); 1247 } 1248 1249 /** 1250 * Writes an optional vector of double to the next location in a non-null parcel. 1251 */ 1252 inline binder_status_t AParcel_writeVector(AParcel* parcel, 1253 const std::optional<std::vector<double>>& vec) { 1254 if (!vec) return AParcel_writeDoubleArray(parcel, nullptr, -1); 1255 return AParcel_writeVector(parcel, *vec); 1256 } 1257 1258 /** 1259 * Reads a vector of double from the next location in a non-null parcel. 1260 */ 1261 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<double>* vec) { 1262 void* vectorData = static_cast<void*>(vec); 1263 return AParcel_readDoubleArray(parcel, vectorData, AParcel_stdVectorAllocator<double>); 1264 } 1265 1266 /** 1267 * Reads an optional vector of double from the next location in a non-null parcel. 1268 */ 1269 inline binder_status_t AParcel_readVector(const AParcel* parcel, 1270 std::optional<std::vector<double>>* vec) { 1271 void* vectorData = static_cast<void*>(vec); 1272 return AParcel_readDoubleArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<double>); 1273 } 1274 1275 /** 1276 * Writes a vector of bool to the next location in a non-null parcel. 1277 */ 1278 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<bool>& vec) { 1279 return AParcel_writeBoolArray(parcel, static_cast<const void*>(&vec), 1280 static_cast<int32_t>(vec.size()), AParcel_stdVectorGetter<bool>); 1281 } 1282 1283 /** 1284 * Writes an optional vector of bool to the next location in a non-null parcel. 1285 */ 1286 inline binder_status_t AParcel_writeVector(AParcel* parcel, 1287 const std::optional<std::vector<bool>>& vec) { 1288 if (!vec) return AParcel_writeBoolArray(parcel, nullptr, -1, AParcel_stdVectorGetter<bool>); 1289 return AParcel_writeVector(parcel, *vec); 1290 } 1291 1292 /** 1293 * Reads a vector of bool from the next location in a non-null parcel. 1294 */ 1295 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<bool>* vec) { 1296 void* vectorData = static_cast<void*>(vec); 1297 return AParcel_readBoolArray(parcel, vectorData, AParcel_stdVectorExternalAllocator<bool>, 1298 AParcel_stdVectorSetter<bool>); 1299 } 1300 1301 /** 1302 * Reads an optional vector of bool from the next location in a non-null parcel. 1303 */ 1304 inline binder_status_t AParcel_readVector(const AParcel* parcel, 1305 std::optional<std::vector<bool>>* vec) { 1306 void* vectorData = static_cast<void*>(vec); 1307 return AParcel_readBoolArray(parcel, vectorData, 1308 AParcel_nullableStdVectorExternalAllocator<bool>, 1309 AParcel_nullableStdVectorSetter<bool>); 1310 } 1311 1312 /** 1313 * Writes a vector of char16_t to the next location in a non-null parcel. 1314 */ 1315 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<char16_t>& vec) { 1316 return AParcel_writeCharArray(parcel, vec.data(), static_cast<int32_t>(vec.size())); 1317 } 1318 1319 /** 1320 * Writes an optional vector of char16_t to the next location in a non-null parcel. 1321 */ 1322 inline binder_status_t AParcel_writeVector(AParcel* parcel, 1323 const std::optional<std::vector<char16_t>>& vec) { 1324 if (!vec) return AParcel_writeCharArray(parcel, nullptr, -1); 1325 return AParcel_writeVector(parcel, *vec); 1326 } 1327 1328 /** 1329 * Reads a vector of char16_t from the next location in a non-null parcel. 1330 */ 1331 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<char16_t>* vec) { 1332 void* vectorData = static_cast<void*>(vec); 1333 return AParcel_readCharArray(parcel, vectorData, AParcel_stdVectorAllocator<char16_t>); 1334 } 1335 1336 /** 1337 * Reads an optional vector of char16_t from the next location in a non-null parcel. 1338 */ 1339 inline binder_status_t AParcel_readVector(const AParcel* parcel, 1340 std::optional<std::vector<char16_t>>* vec) { 1341 void* vectorData = static_cast<void*>(vec); 1342 return AParcel_readCharArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<char16_t>); 1343 } 1344 1345 /** 1346 * Writes a vector of uint8_t to the next location in a non-null parcel. 1347 */ 1348 inline binder_status_t AParcel_writeVector(AParcel* parcel, const std::vector<uint8_t>& vec) { 1349 return AParcel_writeByteArray(parcel, reinterpret_cast<const int8_t*>(vec.data()), 1350 static_cast<int32_t>(vec.size())); 1351 } 1352 1353 /** 1354 * Writes an optional vector of uint8_t to the next location in a non-null parcel. 1355 */ 1356 inline binder_status_t AParcel_writeVector(AParcel* parcel, 1357 const std::optional<std::vector<uint8_t>>& vec) { 1358 if (!vec) return AParcel_writeByteArray(parcel, nullptr, -1); 1359 return AParcel_writeVector(parcel, *vec); 1360 } 1361 1362 /** 1363 * Reads a vector of uint8_t from the next location in a non-null parcel. 1364 */ 1365 inline binder_status_t AParcel_readVector(const AParcel* parcel, std::vector<uint8_t>* vec) { 1366 void* vectorData = static_cast<void*>(vec); 1367 return AParcel_readByteArray(parcel, vectorData, AParcel_stdVectorAllocator<int8_t>); 1368 } 1369 1370 /** 1371 * Reads an optional vector of uint8_t from the next location in a non-null parcel. 1372 */ 1373 inline binder_status_t AParcel_readVector(const AParcel* parcel, 1374 std::optional<std::vector<uint8_t>>* vec) { 1375 void* vectorData = static_cast<void*>(vec); 1376 return AParcel_readByteArray(parcel, vectorData, AParcel_nullableStdVectorAllocator<int8_t>); 1377 } 1378 1379 // @END 1380 1381 /** 1382 * Convenience API for writing the size of a vector. 1383 */ 1384 template <typename T> 1385 static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel, const std::vector<T>& vec) { 1386 if (vec.size() > INT32_MAX) { 1387 return STATUS_BAD_VALUE; 1388 } 1389 1390 return AParcel_writeInt32(parcel, static_cast<int32_t>(vec.size())); 1391 } 1392 1393 /** 1394 * Convenience API for writing the size of a vector. 1395 */ 1396 template <typename T> 1397 static inline binder_status_t AParcel_writeVectorSize(AParcel* parcel, 1398 const std::optional<std::vector<T>>& vec) { 1399 if (!vec) { 1400 return AParcel_writeInt32(parcel, -1); 1401 } 1402 1403 if (vec->size() > INT32_MAX) { 1404 return STATUS_BAD_VALUE; 1405 } 1406 1407 return AParcel_writeInt32(parcel, static_cast<int32_t>(vec->size())); 1408 } 1409 1410 /** 1411 * Convenience API for resizing a vector. 1412 */ 1413 template <typename T> 1414 static inline binder_status_t AParcel_resizeVector(const AParcel* parcel, std::vector<T>* vec) { 1415 int32_t size; 1416 binder_status_t err = AParcel_readInt32(parcel, &size); 1417 1418 if (err != STATUS_OK) return err; 1419 if (size < 0) return STATUS_UNEXPECTED_NULL; 1420 1421 // TODO(b/188215728): delegate to libbinder_ndk 1422 if (size > 1000000) return STATUS_NO_MEMORY; 1423 1424 vec->resize(static_cast<size_t>(size)); 1425 return STATUS_OK; 1426 } 1427 1428 /** 1429 * Convenience API for resizing a vector. 1430 */ 1431 template <typename T> 1432 static inline binder_status_t AParcel_resizeVector(const AParcel* parcel, 1433 std::optional<std::vector<T>>* vec) { 1434 int32_t size; 1435 binder_status_t err = AParcel_readInt32(parcel, &size); 1436 1437 if (err != STATUS_OK) return err; 1438 if (size < -1) return STATUS_UNEXPECTED_NULL; 1439 1440 if (size == -1) { 1441 *vec = std::nullopt; 1442 return STATUS_OK; 1443 } 1444 1445 // TODO(b/188215728): delegate to libbinder_ndk 1446 if (size > 1000000) return STATUS_NO_MEMORY; 1447 1448 *vec = std::optional<std::vector<T>>(std::vector<T>{}); 1449 (*vec)->resize(static_cast<size_t>(size)); 1450 return STATUS_OK; 1451 } 1452 1453 /** 1454 * Writes a fixed-size array of T. 1455 */ 1456 template <typename T, size_t N> 1457 static inline binder_status_t AParcel_writeFixedArray(AParcel* parcel, 1458 const std::array<T, N>& arr) { 1459 if constexpr (std::is_same_v<T, bool>) { 1460 const void* arrayData = static_cast<const void*>(&arr); 1461 return AParcel_writeBoolArray(parcel, arrayData, static_cast<int32_t>(N), 1462 &AParcel_stdArrayGetter<T, N>); 1463 } else if constexpr (std::is_same_v<T, uint8_t>) { 1464 return AParcel_writeByteArray(parcel, reinterpret_cast<const int8_t*>(arr.data()), 1465 static_cast<int32_t>(arr.size())); 1466 } else if constexpr (std::is_same_v<T, char16_t>) { 1467 return AParcel_writeCharArray(parcel, arr.data(), static_cast<int32_t>(arr.size())); 1468 } else if constexpr (std::is_same_v<T, int32_t>) { 1469 return AParcel_writeInt32Array(parcel, arr.data(), static_cast<int32_t>(arr.size())); 1470 } else if constexpr (std::is_same_v<T, int64_t>) { 1471 return AParcel_writeInt64Array(parcel, arr.data(), static_cast<int32_t>(arr.size())); 1472 } else if constexpr (std::is_same_v<T, float>) { 1473 return AParcel_writeFloatArray(parcel, arr.data(), static_cast<int32_t>(arr.size())); 1474 } else if constexpr (std::is_same_v<T, double>) { 1475 return AParcel_writeDoubleArray(parcel, arr.data(), static_cast<int32_t>(arr.size())); 1476 } else if constexpr (std::is_same_v<T, std::string>) { 1477 const void* arrayData = static_cast<const void*>(&arr); 1478 return AParcel_writeStringArray(parcel, arrayData, static_cast<int32_t>(N), 1479 &AParcel_stdArrayStringElementGetter<N>); 1480 } else { 1481 const void* arrayData = static_cast<const void*>(&arr); 1482 return AParcel_writeParcelableArray(parcel, arrayData, static_cast<int32_t>(N), 1483 &AParcel_writeStdArrayData<T, N>); 1484 } 1485 } 1486 1487 /** 1488 * Writes a fixed-size array of T. 1489 */ 1490 template <typename T, size_t N> 1491 static inline binder_status_t AParcel_writeFixedArrayWithNullableData(AParcel* parcel, 1492 const std::array<T, N>& arr) { 1493 if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, uint8_t> || 1494 std::is_same_v<T, char16_t> || std::is_same_v<T, int32_t> || 1495 std::is_same_v<T, int64_t> || std::is_same_v<T, float> || 1496 std::is_same_v<T, double> || std::is_same_v<T, std::string>) { 1497 return AParcel_writeFixedArray(parcel, arr); 1498 } else if constexpr (std::is_same_v<T, std::optional<std::string>>) { 1499 const void* arrayData = static_cast<const void*>(&arr); 1500 return AParcel_writeStringArray(parcel, arrayData, static_cast<int32_t>(N), 1501 &AParcel_stdArrayNullableStringElementGetter<N>); 1502 } else { 1503 const void* arrayData = static_cast<const void*>(&arr); 1504 return AParcel_writeParcelableArray(parcel, arrayData, static_cast<int32_t>(N), 1505 &AParcel_writeStdArrayNullableData<T, N>); 1506 } 1507 } 1508 1509 /** 1510 * Writes a fixed-size array of T. 1511 */ 1512 template <typename T, size_t N> 1513 static inline binder_status_t AParcel_writeNullableFixedArrayWithNullableData( 1514 AParcel* parcel, const std::optional<std::array<T, N>>& arr) { 1515 if (!arr) return AParcel_writeInt32(parcel, -1); 1516 return AParcel_writeFixedArrayWithNullableData(parcel, arr.value()); 1517 } 1518 1519 /** 1520 * Reads a fixed-size array of T. 1521 */ 1522 template <typename T, size_t N> 1523 static inline binder_status_t AParcel_readFixedArray(const AParcel* parcel, std::array<T, N>* arr) { 1524 void* arrayData = static_cast<void*>(arr); 1525 if constexpr (std::is_same_v<T, bool>) { 1526 return AParcel_readBoolArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>, 1527 &AParcel_stdArraySetter<T, N>); 1528 } else if constexpr (std::is_same_v<T, uint8_t>) { 1529 return AParcel_readByteArray(parcel, arrayData, &AParcel_stdArrayAllocator<int8_t, N>); 1530 } else if constexpr (std::is_same_v<T, char16_t>) { 1531 return AParcel_readCharArray(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>); 1532 } else if constexpr (std::is_same_v<T, int32_t>) { 1533 return AParcel_readInt32Array(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>); 1534 } else if constexpr (std::is_same_v<T, int64_t>) { 1535 return AParcel_readInt64Array(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>); 1536 } else if constexpr (std::is_same_v<T, float>) { 1537 return AParcel_readFloatArray(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>); 1538 } else if constexpr (std::is_same_v<T, double>) { 1539 return AParcel_readDoubleArray(parcel, arrayData, &AParcel_stdArrayAllocator<T, N>); 1540 } else if constexpr (std::is_same_v<T, std::string>) { 1541 return AParcel_readStringArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>, 1542 &AParcel_stdArrayStringElementAllocator<N>); 1543 } else { 1544 return AParcel_readParcelableArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>, 1545 &AParcel_readStdArrayData<T, N>); 1546 } 1547 } 1548 1549 /** 1550 * Reads a fixed-size array of T. 1551 */ 1552 template <typename T, size_t N> 1553 static inline binder_status_t AParcel_readFixedArrayWithNullableData(const AParcel* parcel, 1554 std::array<T, N>* arr) { 1555 void* arrayData = static_cast<void*>(arr); 1556 if constexpr (std::is_same_v<T, bool> || std::is_same_v<T, uint8_t> || 1557 std::is_same_v<T, char16_t> || std::is_same_v<T, int32_t> || 1558 std::is_same_v<T, int64_t> || std::is_same_v<T, float> || 1559 std::is_same_v<T, double> || std::is_same_v<T, std::string>) { 1560 return AParcel_readFixedArray(parcel, arr); 1561 } else if constexpr (std::is_same_v<T, std::optional<std::string>>) { 1562 return AParcel_readStringArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>, 1563 &AParcel_stdArrayNullableStringElementAllocator<N>); 1564 } else { 1565 return AParcel_readParcelableArray(parcel, arrayData, &AParcel_stdArrayExternalAllocator<N>, 1566 &AParcel_readStdArrayNullableData<T, N>); 1567 } 1568 } 1569 1570 /** 1571 * Reads a fixed-size array of T. 1572 */ 1573 template <typename T, size_t N> 1574 static inline binder_status_t AParcel_readNullableFixedArrayWithNullableData( 1575 const AParcel* parcel, std::optional<std::array<T, N>>* arr) { 1576 void* arrayData = static_cast<void*>(arr); 1577 if constexpr (std::is_same_v<T, bool>) { 1578 return AParcel_readBoolArray(parcel, arrayData, 1579 &AParcel_nullableStdArrayExternalAllocator<T, N>, 1580 &AParcel_nullableStdArraySetter<T, N>); 1581 } else if constexpr (std::is_same_v<T, uint8_t>) { 1582 return AParcel_readByteArray(parcel, arrayData, 1583 &AParcel_nullableStdArrayAllocator<int8_t, N>); 1584 } else if constexpr (std::is_same_v<T, char16_t>) { 1585 return AParcel_readCharArray(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>); 1586 } else if constexpr (std::is_same_v<T, int32_t>) { 1587 return AParcel_readInt32Array(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>); 1588 } else if constexpr (std::is_same_v<T, int64_t>) { 1589 return AParcel_readInt64Array(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>); 1590 } else if constexpr (std::is_same_v<T, float>) { 1591 return AParcel_readFloatArray(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>); 1592 } else if constexpr (std::is_same_v<T, double>) { 1593 return AParcel_readDoubleArray(parcel, arrayData, &AParcel_nullableStdArrayAllocator<T, N>); 1594 } else if constexpr (std::is_same_v<T, std::string>) { 1595 return AParcel_readStringArray(parcel, arrayData, 1596 &AParcel_nullableStdArrayExternalAllocator<N>, 1597 &AParcel_nullableStdArrayStringElementAllocator<N>); 1598 } else { 1599 return AParcel_readParcelableArray(parcel, arrayData, 1600 &AParcel_nullableStdArrayExternalAllocator<T, N>, 1601 &AParcel_readStdArrayNullableData<T, N>); 1602 } 1603 } 1604 1605 /** 1606 * Convenience API for writing a value of any type. 1607 */ 1608 template <typename T> 1609 static inline binder_status_t AParcel_writeData(AParcel* parcel, const T& value) { 1610 if constexpr (is_specialization_v<T, std::vector>) { 1611 return AParcel_writeVector(parcel, value); 1612 } else if constexpr (is_fixed_array_v<T>) { 1613 return AParcel_writeFixedArray(parcel, value); 1614 } else if constexpr (std::is_same_v<std::string, T>) { 1615 return AParcel_writeString(parcel, value); 1616 } else if constexpr (std::is_same_v<bool, T>) { 1617 return AParcel_writeBool(parcel, value); 1618 } else if constexpr (std::is_same_v<int8_t, T> || std::is_same_v<uint8_t, T>) { 1619 return AParcel_writeByte(parcel, value); 1620 } else if constexpr (std::is_same_v<char16_t, T>) { 1621 return AParcel_writeChar(parcel, value); 1622 } else if constexpr (std::is_same_v<int32_t, T>) { 1623 return AParcel_writeInt32(parcel, value); 1624 } else if constexpr (std::is_same_v<int64_t, T>) { 1625 return AParcel_writeInt64(parcel, value); 1626 } else if constexpr (std::is_same_v<float, T>) { 1627 return AParcel_writeFloat(parcel, value); 1628 } else if constexpr (std::is_same_v<double, T>) { 1629 return AParcel_writeDouble(parcel, value); 1630 } else if constexpr (std::is_same_v<ScopedFileDescriptor, T>) { 1631 return AParcel_writeRequiredParcelFileDescriptor(parcel, value); 1632 } else if constexpr (std::is_same_v<SpAIBinder, T>) { 1633 return AParcel_writeRequiredStrongBinder(parcel, value); 1634 } else if constexpr (std::is_enum_v<T>) { 1635 return AParcel_writeData(parcel, static_cast<std::underlying_type_t<T>>(value)); 1636 } else if constexpr (is_interface_v<T>) { 1637 return AParcel_writeParcelable(parcel, value); 1638 } else if constexpr (is_parcelable_v<T>) { 1639 return AParcel_writeParcelable(parcel, value); 1640 } else { 1641 static_assert(dependent_false_v<T>, "unrecognized type"); 1642 } 1643 } 1644 1645 /** 1646 * Convenience API for writing a nullable value of any type. 1647 */ 1648 template <typename T> 1649 static inline binder_status_t AParcel_writeNullableData(AParcel* parcel, const T& value) { 1650 if constexpr (is_specialization_v<T, std::optional> && 1651 is_specialization_v<first_template_type_t<T>, std::vector>) { 1652 return AParcel_writeVector(parcel, value); 1653 } else if constexpr (is_specialization_v<T, std::optional> && 1654 is_fixed_array_v<first_template_type_t<T>>) { 1655 return AParcel_writeNullableFixedArrayWithNullableData(parcel, value); 1656 } else if constexpr (is_fixed_array_v<T>) { // happens with a nullable multi-dimensional array. 1657 return AParcel_writeFixedArrayWithNullableData(parcel, value); 1658 } else if constexpr (is_specialization_v<T, std::optional> && 1659 std::is_same_v<first_template_type_t<T>, std::string>) { 1660 return AParcel_writeString(parcel, value); 1661 } else if constexpr (is_nullable_parcelable_v<T> || is_interface_v<T>) { 1662 return AParcel_writeNullableParcelable(parcel, value); 1663 } else if constexpr (std::is_same_v<ScopedFileDescriptor, T>) { 1664 return AParcel_writeNullableParcelFileDescriptor(parcel, value); 1665 } else if constexpr (std::is_same_v<SpAIBinder, T>) { 1666 return AParcel_writeNullableStrongBinder(parcel, value); 1667 } else { 1668 return AParcel_writeData(parcel, value); 1669 } 1670 } 1671 1672 /** 1673 * Convenience API for reading a value of any type. 1674 */ 1675 template <typename T> 1676 static inline binder_status_t AParcel_readData(const AParcel* parcel, T* value) { 1677 if constexpr (is_specialization_v<T, std::vector>) { 1678 return AParcel_readVector(parcel, value); 1679 } else if constexpr (is_fixed_array_v<T>) { 1680 return AParcel_readFixedArray(parcel, value); 1681 } else if constexpr (std::is_same_v<std::string, T>) { 1682 return AParcel_readString(parcel, value); 1683 } else if constexpr (std::is_same_v<bool, T>) { 1684 return AParcel_readBool(parcel, value); 1685 } else if constexpr (std::is_same_v<int8_t, T> || std::is_same_v<uint8_t, T>) { 1686 return AParcel_readByte(parcel, value); 1687 } else if constexpr (std::is_same_v<char16_t, T>) { 1688 return AParcel_readChar(parcel, value); 1689 } else if constexpr (std::is_same_v<int32_t, T>) { 1690 return AParcel_readInt32(parcel, value); 1691 } else if constexpr (std::is_same_v<int64_t, T>) { 1692 return AParcel_readInt64(parcel, value); 1693 } else if constexpr (std::is_same_v<float, T>) { 1694 return AParcel_readFloat(parcel, value); 1695 } else if constexpr (std::is_same_v<double, T>) { 1696 return AParcel_readDouble(parcel, value); 1697 } else if constexpr (std::is_same_v<ScopedFileDescriptor, T>) { 1698 return AParcel_readRequiredParcelFileDescriptor(parcel, value); 1699 } else if constexpr (std::is_same_v<SpAIBinder, T>) { 1700 return AParcel_readRequiredStrongBinder(parcel, value); 1701 } else if constexpr (std::is_enum_v<T>) { 1702 return AParcel_readData(parcel, reinterpret_cast<std::underlying_type_t<T>*>(value)); 1703 } else if constexpr (is_interface_v<T>) { 1704 return AParcel_readParcelable(parcel, value); 1705 } else if constexpr (is_parcelable_v<T>) { 1706 return AParcel_readParcelable(parcel, value); 1707 } else { 1708 static_assert(dependent_false_v<T>, "unrecognized type"); 1709 } 1710 } 1711 1712 /** 1713 * Convenience API for reading a nullable value of any type. 1714 */ 1715 template <typename T> 1716 static inline binder_status_t AParcel_readNullableData(const AParcel* parcel, T* value) { 1717 if constexpr (is_specialization_v<T, std::optional> && 1718 is_specialization_v<first_template_type_t<T>, std::vector>) { 1719 return AParcel_readVector(parcel, value); 1720 } else if constexpr (is_specialization_v<T, std::optional> && 1721 is_fixed_array_v<first_template_type_t<T>>) { 1722 return AParcel_readNullableFixedArrayWithNullableData(parcel, value); 1723 } else if constexpr (is_fixed_array_v<T>) { // happens with a nullable multi-dimensional array. 1724 return AParcel_readFixedArrayWithNullableData(parcel, value); 1725 } else if constexpr (is_specialization_v<T, std::optional> && 1726 std::is_same_v<first_template_type_t<T>, std::string>) { 1727 return AParcel_readString(parcel, value); 1728 } else if constexpr (is_nullable_parcelable_v<T> || is_interface_v<T>) { 1729 return AParcel_readNullableParcelable(parcel, value); 1730 } else if constexpr (std::is_same_v<ScopedFileDescriptor, T>) { 1731 return AParcel_readNullableParcelFileDescriptor(parcel, value); 1732 } else if constexpr (std::is_same_v<SpAIBinder, T>) { 1733 return AParcel_readNullableStrongBinder(parcel, value); 1734 } else { 1735 return AParcel_readData(parcel, value); 1736 } 1737 } 1738 1739 } // namespace ndk 1740 1741 /** @} */ 1742