1 /* 2 * Copyright (C) 2023 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 #pragma once 17 18 #include <android/binder_parcel.h> 19 #include <android/persistable_bundle.h> 20 #include <sys/cdefs.h> 21 22 #include <set> 23 #include <sstream> 24 25 // Include llndk-versioning.h only for vendor build as it is not available for NDK headers. 26 #if defined(__ANDROID_VENDOR__) 27 #include <android/llndk-versioning.h> 28 #elif !defined(API_LEVEL_AT_LEAST) 29 #if defined(__BIONIC__) 30 #define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) \ 31 (__builtin_available(android sdk_api_level, *)) 32 #else 33 #define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) (true) 34 #endif // __BIONIC__ 35 #endif // __ANDROID_VENDOR__ 36 37 namespace aidl::android::os { 38 39 /** 40 * Wrapper class that enables interop with AIDL NDK generation 41 * Takes ownership of the APersistableBundle* given to it in reset() and will automatically 42 * destroy it in the destructor, similar to a smart pointer container 43 */ 44 class PersistableBundle { 45 public: PersistableBundle()46 PersistableBundle() noexcept { 47 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 48 mPBundle = APersistableBundle_new(); 49 } 50 } 51 // takes ownership of the APersistableBundle* PersistableBundle(APersistableBundle * _Nonnull bundle)52 PersistableBundle(APersistableBundle* _Nonnull bundle) noexcept : mPBundle(bundle) {} 53 // takes ownership of the APersistableBundle* PersistableBundle(PersistableBundle && other)54 PersistableBundle(PersistableBundle&& other) noexcept : mPBundle(other.release()) {} 55 // duplicates, does not take ownership of the APersistableBundle* PersistableBundle(const PersistableBundle & other)56 PersistableBundle(const PersistableBundle& other) { 57 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 58 mPBundle = APersistableBundle_dup(other.mPBundle); 59 } 60 } 61 // duplicates, does not take ownership of the APersistableBundle* 62 PersistableBundle& operator=(const PersistableBundle& other) { 63 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 64 mPBundle = APersistableBundle_dup(other.mPBundle); 65 } 66 return *this; 67 } 68 ~PersistableBundle()69 ~PersistableBundle() { reset(); } 70 readFromParcel(const AParcel * _Nonnull parcel)71 binder_status_t readFromParcel(const AParcel* _Nonnull parcel) { 72 reset(); 73 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 74 return APersistableBundle_readFromParcel(parcel, &mPBundle); 75 } else { 76 return STATUS_INVALID_OPERATION; 77 } 78 } 79 writeToParcel(AParcel * _Nonnull parcel)80 binder_status_t writeToParcel(AParcel* _Nonnull parcel) const { 81 if (!mPBundle) { 82 return STATUS_BAD_VALUE; 83 } 84 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 85 return APersistableBundle_writeToParcel(mPBundle, parcel); 86 } else { 87 return STATUS_INVALID_OPERATION; 88 } 89 } 90 91 /** 92 * Destroys any currently owned APersistableBundle* and takes ownership of the given 93 * APersistableBundle* 94 * 95 * @param pBundle The APersistableBundle to take ownership of 96 */ 97 void reset(APersistableBundle* _Nullable pBundle = nullptr) noexcept { 98 if (mPBundle) { 99 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 100 APersistableBundle_delete(mPBundle); 101 } 102 mPBundle = nullptr; 103 } 104 mPBundle = pBundle; 105 } 106 107 /** 108 * Check the actual contents of the bundle for equality. This is typically 109 * what should be used to check for equality. 110 */ deepEquals(const PersistableBundle & rhs)111 bool deepEquals(const PersistableBundle& rhs) const { 112 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 113 return APersistableBundle_isEqual(get(), rhs.get()); 114 } else { 115 return false; 116 } 117 } 118 119 /** 120 * NOTE: This does NOT check the contents of the PersistableBundle. This is 121 * implemented for ordering. Use deepEquals() to check for equality between 122 * two different PersistableBundle objects. 123 */ 124 inline bool operator==(const PersistableBundle& rhs) const { return get() == rhs.get(); } 125 inline bool operator!=(const PersistableBundle& rhs) const { return get() != rhs.get(); } 126 127 inline bool operator<(const PersistableBundle& rhs) const { return get() < rhs.get(); } 128 inline bool operator>(const PersistableBundle& rhs) const { return get() > rhs.get(); } 129 inline bool operator>=(const PersistableBundle& rhs) const { return !(*this < rhs); } 130 inline bool operator<=(const PersistableBundle& rhs) const { return !(*this > rhs); } 131 132 PersistableBundle& operator=(PersistableBundle&& other) noexcept { 133 reset(other.release()); 134 return *this; 135 } 136 137 /** 138 * Stops managing any contained APersistableBundle*, returning it to the caller. Ownership 139 * is released. 140 * @return APersistableBundle* or null if this was empty 141 */ release()142 [[nodiscard]] APersistableBundle* _Nullable release() noexcept { 143 APersistableBundle* _Nullable ret = mPBundle; 144 mPBundle = nullptr; 145 return ret; 146 } 147 toString()148 inline std::string toString() const { 149 if (!mPBundle) { 150 return "<PersistableBundle: null>"; 151 } else if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 152 std::ostringstream os; 153 os << "<PersistableBundle: "; 154 os << "size: " << std::to_string(APersistableBundle_size(mPBundle)); 155 os << " >"; 156 return os.str(); 157 } 158 return "<PersistableBundle (unknown)>"; 159 } 160 size()161 int32_t size() const { 162 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 163 return APersistableBundle_size(mPBundle); 164 } else { 165 return 0; 166 } 167 } 168 erase(const std::string & key)169 int32_t erase(const std::string& key) { 170 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 171 return APersistableBundle_erase(mPBundle, key.c_str()); 172 } else { 173 return 0; 174 } 175 } 176 putBoolean(const std::string & key,bool val)177 void putBoolean(const std::string& key, bool val) { 178 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 179 APersistableBundle_putBoolean(mPBundle, key.c_str(), val); 180 } 181 } 182 putInt(const std::string & key,int32_t val)183 void putInt(const std::string& key, int32_t val) { 184 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 185 APersistableBundle_putInt(mPBundle, key.c_str(), val); 186 } 187 } 188 putLong(const std::string & key,int64_t val)189 void putLong(const std::string& key, int64_t val) { 190 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 191 APersistableBundle_putLong(mPBundle, key.c_str(), val); 192 } 193 } 194 putDouble(const std::string & key,double val)195 void putDouble(const std::string& key, double val) { 196 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 197 APersistableBundle_putDouble(mPBundle, key.c_str(), val); 198 } 199 } 200 putString(const std::string & key,const std::string & val)201 void putString(const std::string& key, const std::string& val) { 202 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 203 APersistableBundle_putString(mPBundle, key.c_str(), val.c_str()); 204 } 205 } 206 putBooleanVector(const std::string & key,const std::vector<bool> & vec)207 void putBooleanVector(const std::string& key, const std::vector<bool>& vec) { 208 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 209 // std::vector<bool> has no ::data(). 210 int32_t num = vec.size(); 211 if (num > 0) { 212 bool* newVec = (bool*)malloc(num * sizeof(bool)); 213 if (newVec) { 214 for (int32_t i = 0; i < num; i++) { 215 newVec[i] = vec[i]; 216 } 217 APersistableBundle_putBooleanVector(mPBundle, key.c_str(), newVec, num); 218 free(newVec); 219 } 220 } 221 } 222 } 223 putIntVector(const std::string & key,const std::vector<int32_t> & vec)224 void putIntVector(const std::string& key, const std::vector<int32_t>& vec) { 225 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 226 int32_t num = vec.size(); 227 if (num > 0) { 228 APersistableBundle_putIntVector(mPBundle, key.c_str(), vec.data(), num); 229 } 230 } 231 } putLongVector(const std::string & key,const std::vector<int64_t> & vec)232 void putLongVector(const std::string& key, const std::vector<int64_t>& vec) { 233 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 234 int32_t num = vec.size(); 235 if (num > 0) { 236 APersistableBundle_putLongVector(mPBundle, key.c_str(), vec.data(), num); 237 } 238 } 239 } putDoubleVector(const std::string & key,const std::vector<double> & vec)240 void putDoubleVector(const std::string& key, const std::vector<double>& vec) { 241 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 242 int32_t num = vec.size(); 243 if (num > 0) { 244 APersistableBundle_putDoubleVector(mPBundle, key.c_str(), vec.data(), num); 245 } 246 } 247 } putStringVector(const std::string & key,const std::vector<std::string> & vec)248 void putStringVector(const std::string& key, const std::vector<std::string>& vec) { 249 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 250 int32_t num = vec.size(); 251 if (num > 0) { 252 char** inVec = (char**)malloc(num * sizeof(char*)); 253 if (inVec) { 254 for (int32_t i = 0; i < num; i++) { 255 inVec[i] = strdup(vec[i].c_str()); 256 } 257 APersistableBundle_putStringVector(mPBundle, key.c_str(), inVec, num); 258 free(inVec); 259 } 260 } 261 } 262 } putPersistableBundle(const std::string & key,const PersistableBundle & pBundle)263 void putPersistableBundle(const std::string& key, const PersistableBundle& pBundle) { 264 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 265 APersistableBundle_putPersistableBundle(mPBundle, key.c_str(), pBundle.mPBundle); 266 } 267 } 268 getBoolean(const std::string & key,bool * _Nonnull val)269 bool getBoolean(const std::string& key, bool* _Nonnull val) const { 270 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 271 return APersistableBundle_getBoolean(mPBundle, key.c_str(), val); 272 } else { 273 return false; 274 } 275 } 276 getInt(const std::string & key,int32_t * _Nonnull val)277 bool getInt(const std::string& key, int32_t* _Nonnull val) const { 278 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 279 return APersistableBundle_getInt(mPBundle, key.c_str(), val); 280 } else { 281 return false; 282 } 283 } 284 getLong(const std::string & key,int64_t * _Nonnull val)285 bool getLong(const std::string& key, int64_t* _Nonnull val) const { 286 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 287 return APersistableBundle_getLong(mPBundle, key.c_str(), val); 288 } else { 289 return false; 290 } 291 } 292 getDouble(const std::string & key,double * _Nonnull val)293 bool getDouble(const std::string& key, double* _Nonnull val) const { 294 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 295 return APersistableBundle_getDouble(mPBundle, key.c_str(), val); 296 } else { 297 return false; 298 } 299 } 300 stringAllocator(int32_t bufferSizeBytes,void * _Nullable)301 static char* _Nullable stringAllocator(int32_t bufferSizeBytes, void* _Nullable) { 302 return (char*)malloc(bufferSizeBytes); 303 } 304 getString(const std::string & key,std::string * _Nonnull val)305 bool getString(const std::string& key, std::string* _Nonnull val) const { 306 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 307 char* outString = nullptr; 308 bool ret = APersistableBundle_getString(mPBundle, key.c_str(), &outString, 309 &stringAllocator, nullptr); 310 if (ret && outString) { 311 *val = std::string(outString); 312 } 313 return ret; 314 } else { 315 return false; 316 } 317 } 318 319 template <typename T> getVecInternal(int32_t (* _Nonnull getVec)(const APersistableBundle * _Nonnull,const char * _Nonnull,T * _Nullable,int32_t),const APersistableBundle * _Nonnull pBundle,const char * _Nonnull key,std::vector<T> * _Nonnull vec)320 bool getVecInternal(int32_t (*_Nonnull getVec)(const APersistableBundle* _Nonnull, 321 const char* _Nonnull, T* _Nullable, int32_t), 322 const APersistableBundle* _Nonnull pBundle, const char* _Nonnull key, 323 std::vector<T>* _Nonnull vec) const { 324 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 325 int32_t bytes = 0; 326 // call first with nullptr to get required size in bytes 327 bytes = getVec(pBundle, key, nullptr, 0); 328 if (bytes > 0) { 329 T* newVec = (T*)malloc(bytes); 330 if (newVec) { 331 bytes = getVec(pBundle, key, newVec, bytes); 332 int32_t elements = bytes / sizeof(T); 333 vec->clear(); 334 for (int32_t i = 0; i < elements; i++) { 335 vec->push_back(newVec[i]); 336 } 337 free(newVec); 338 return true; 339 } 340 } 341 } 342 return false; 343 } 344 getBooleanVector(const std::string & key,std::vector<bool> * _Nonnull vec)345 bool getBooleanVector(const std::string& key, std::vector<bool>* _Nonnull vec) const { 346 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 347 return getVecInternal<bool>(&APersistableBundle_getBooleanVector, mPBundle, key.c_str(), 348 vec); 349 } 350 return false; 351 } getIntVector(const std::string & key,std::vector<int32_t> * _Nonnull vec)352 bool getIntVector(const std::string& key, std::vector<int32_t>* _Nonnull vec) const { 353 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 354 return getVecInternal<int32_t>(&APersistableBundle_getIntVector, mPBundle, key.c_str(), 355 vec); 356 } 357 return false; 358 } getLongVector(const std::string & key,std::vector<int64_t> * _Nonnull vec)359 bool getLongVector(const std::string& key, std::vector<int64_t>* _Nonnull vec) const { 360 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 361 return getVecInternal<int64_t>(&APersistableBundle_getLongVector, mPBundle, key.c_str(), 362 vec); 363 } 364 return false; 365 } getDoubleVector(const std::string & key,std::vector<double> * _Nonnull vec)366 bool getDoubleVector(const std::string& key, std::vector<double>* _Nonnull vec) const { 367 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 368 return getVecInternal<double>(&APersistableBundle_getDoubleVector, mPBundle, 369 key.c_str(), vec); 370 } 371 return false; 372 } 373 374 // Takes ownership of and frees the char** and its elements. 375 // Creates a new set or vector based on the array of char*. 376 template <typename T> moveStringsInternal(char * _Nullable * _Nonnull strings,int32_t bufferSizeBytes)377 T moveStringsInternal(char* _Nullable* _Nonnull strings, int32_t bufferSizeBytes) const { 378 if (strings && bufferSizeBytes > 0) { 379 int32_t num = bufferSizeBytes / sizeof(char*); 380 T ret; 381 for (int32_t i = 0; i < num; i++) { 382 ret.insert(ret.end(), std::string(strings[i])); 383 free(strings[i]); 384 } 385 free(strings); 386 return ret; 387 } 388 return T(); 389 } 390 getStringVector(const std::string & key,std::vector<std::string> * _Nonnull vec)391 bool getStringVector(const std::string& key, std::vector<std::string>* _Nonnull vec) const { 392 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 393 int32_t bytes = APersistableBundle_getStringVector(mPBundle, key.c_str(), nullptr, 0, 394 &stringAllocator, nullptr); 395 if (bytes > 0) { 396 char** strings = (char**)malloc(bytes); 397 if (strings) { 398 bytes = APersistableBundle_getStringVector(mPBundle, key.c_str(), strings, 399 bytes, &stringAllocator, nullptr); 400 *vec = moveStringsInternal<std::vector<std::string>>(strings, bytes); 401 return true; 402 } 403 } 404 } 405 return false; 406 } 407 getPersistableBundle(const std::string & key,PersistableBundle * _Nonnull val)408 bool getPersistableBundle(const std::string& key, PersistableBundle* _Nonnull val) const { 409 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 410 APersistableBundle* bundle = nullptr; 411 bool ret = APersistableBundle_getPersistableBundle(mPBundle, key.c_str(), &bundle); 412 if (ret) { 413 *val = PersistableBundle(bundle); 414 } 415 return ret; 416 } else { 417 return false; 418 } 419 } 420 getKeys(int32_t (* _Nonnull getTypedKeys)(const APersistableBundle * _Nonnull pBundle,char * _Nullable * _Nullable outKeys,int32_t bufferSizeBytes,APersistableBundle_stringAllocator stringAllocator,void * _Nullable),const APersistableBundle * _Nonnull pBundle)421 std::set<std::string> getKeys( 422 int32_t (*_Nonnull getTypedKeys)(const APersistableBundle* _Nonnull pBundle, 423 char* _Nullable* _Nullable outKeys, 424 int32_t bufferSizeBytes, 425 APersistableBundle_stringAllocator stringAllocator, 426 void* _Nullable), 427 const APersistableBundle* _Nonnull pBundle) const { 428 // call first with nullptr to get required size in bytes 429 int32_t bytes = getTypedKeys(pBundle, nullptr, 0, &stringAllocator, nullptr); 430 if (bytes > 0) { 431 char** keys = (char**)malloc(bytes); 432 if (keys) { 433 bytes = getTypedKeys(pBundle, keys, bytes, &stringAllocator, nullptr); 434 return moveStringsInternal<std::set<std::string>>(keys, bytes); 435 } 436 } 437 return {}; 438 } 439 getBooleanKeys()440 std::set<std::string> getBooleanKeys() const { 441 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 442 return getKeys(&APersistableBundle_getBooleanKeys, mPBundle); 443 } else { 444 return {}; 445 } 446 } getIntKeys()447 std::set<std::string> getIntKeys() const { 448 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 449 return getKeys(&APersistableBundle_getIntKeys, mPBundle); 450 } else { 451 return {}; 452 } 453 } getLongKeys()454 std::set<std::string> getLongKeys() const { 455 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 456 return getKeys(&APersistableBundle_getLongKeys, mPBundle); 457 } else { 458 return {}; 459 } 460 } getDoubleKeys()461 std::set<std::string> getDoubleKeys() const { 462 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 463 return getKeys(&APersistableBundle_getDoubleKeys, mPBundle); 464 } else { 465 return {}; 466 } 467 } getStringKeys()468 std::set<std::string> getStringKeys() const { 469 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 470 return getKeys(&APersistableBundle_getStringKeys, mPBundle); 471 } else { 472 return {}; 473 } 474 } getBooleanVectorKeys()475 std::set<std::string> getBooleanVectorKeys() const { 476 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 477 return getKeys(&APersistableBundle_getBooleanVectorKeys, mPBundle); 478 } else { 479 return {}; 480 } 481 } getIntVectorKeys()482 std::set<std::string> getIntVectorKeys() const { 483 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 484 return getKeys(&APersistableBundle_getIntVectorKeys, mPBundle); 485 } else { 486 return {}; 487 } 488 } getLongVectorKeys()489 std::set<std::string> getLongVectorKeys() const { 490 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 491 return getKeys(&APersistableBundle_getLongVectorKeys, mPBundle); 492 } else { 493 return {}; 494 } 495 } getDoubleVectorKeys()496 std::set<std::string> getDoubleVectorKeys() const { 497 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 498 return getKeys(&APersistableBundle_getDoubleVectorKeys, mPBundle); 499 } else { 500 return {}; 501 } 502 } getStringVectorKeys()503 std::set<std::string> getStringVectorKeys() const { 504 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 505 return getKeys(&APersistableBundle_getStringVectorKeys, mPBundle); 506 } else { 507 return {}; 508 } 509 } getPersistableBundleKeys()510 std::set<std::string> getPersistableBundleKeys() const { 511 if API_LEVEL_AT_LEAST(__ANDROID_API_V__, 202404) { 512 return getKeys(&APersistableBundle_getPersistableBundleKeys, mPBundle); 513 } else { 514 return {}; 515 } 516 } getMonKeys()517 std::set<std::string> getMonKeys() const { 518 // :P 519 return {"c(o,o)b", "c(o,o)b"}; 520 } 521 522 private: get()523 inline APersistableBundle* _Nullable get() const { return mPBundle; } 524 APersistableBundle* _Nullable mPBundle = nullptr; 525 }; 526 527 } // namespace aidl::android::os 528