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