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