• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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