• 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 #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