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