diff options
author | 2023-10-20 16:53:08 +0000 | |
---|---|---|
committer | 2023-10-31 20:01:06 +0000 | |
commit | 33ce330de12e3ed3ae9cb1311aed72c6f8611a47 (patch) | |
tree | 773a1a4c97ac576ae75fd6667f8ef0b0d2326f47 | |
parent | 49753ae00a00641382c426e9b8fa775f1a364e7e (diff) |
Add PersistableBundle ndk and AIDL type
Add the new APersistableBundle NDK type for the new AIDL
PersistableBundle.
Test: atest CtsNdkBinderTestCases
Bug: 306401400
Change-Id: I6b9204d8b36f224de610338d2184e73f16ca56d0
-rw-r--r-- | Android.bp | 6 | ||||
-rw-r--r-- | aidl/binder/android/os/PersistableBundle.aidl | 2 | ||||
-rw-r--r-- | libs/binder/ndk/Android.bp | 1 | ||||
-rw-r--r-- | libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h | 497 | ||||
-rw-r--r-- | libs/binder/ndk/include_ndk/android/persistable_bundle.h | 905 | ||||
-rw-r--r-- | libs/binder/ndk/libbinder_ndk.map.txt | 45 | ||||
-rw-r--r-- | libs/binder/ndk/persistable_bundle.cpp | 313 | ||||
-rw-r--r-- | libs/binder/ndk/persistable_bundle_internal.h | 85 |
8 files changed, 1853 insertions, 1 deletions
diff --git a/Android.bp b/Android.bp index 3992f82c3d..81d0615e64 100644 --- a/Android.bp +++ b/Android.bp @@ -89,6 +89,12 @@ filegroup { ], } +aidl_library { + name: "PersistableBundle_aidl", + hdrs: ["aidl/binder/android/os/PersistableBundle.aidl"], + strip_import_prefix: "aidl/binder", +} + cc_library_headers { name: "libandroid_headers_private", export_include_dirs: ["include/private"], diff --git a/aidl/binder/android/os/PersistableBundle.aidl b/aidl/binder/android/os/PersistableBundle.aidl index 493ecb414c..248e9738df 100644 --- a/aidl/binder/android/os/PersistableBundle.aidl +++ b/aidl/binder/android/os/PersistableBundle.aidl @@ -17,4 +17,4 @@ package android.os; -@JavaOnlyStableParcelable parcelable PersistableBundle cpp_header "binder/PersistableBundle.h"; +@JavaOnlyStableParcelable @NdkOnlyStableParcelable parcelable PersistableBundle cpp_header "binder/PersistableBundle.h" ndk_header "android/persistable_bundle_aidl.h"; diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp index 58ed4188e2..47b9f5868d 100644 --- a/libs/binder/ndk/Android.bp +++ b/libs/binder/ndk/Android.bp @@ -60,6 +60,7 @@ cc_library { "libbinder.cpp", "parcel.cpp", "parcel_jni.cpp", + "persistable_bundle.cpp", "process.cpp", "stability.cpp", "status.cpp", diff --git a/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h b/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h new file mode 100644 index 0000000000..f178027b35 --- /dev/null +++ b/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h @@ -0,0 +1,497 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <android/binder_parcel.h> +#include <android/persistable_bundle.h> +#include <sys/cdefs.h> + +#include <set> +#include <sstream> + +namespace aidl::android::os { + +/** + * Wrapper class that enables interop with AIDL NDK generation + * Takes ownership of the APersistableBundle* given to it in reset() and will automatically + * destroy it in the destructor, similar to a smart pointer container + */ +class PersistableBundle { + public: + PersistableBundle() noexcept : mPBundle(APersistableBundle_new()) {} + // takes ownership of the APersistableBundle* + PersistableBundle(APersistableBundle* _Nonnull bundle) noexcept : mPBundle(bundle) {} + // takes ownership of the APersistableBundle* + PersistableBundle(PersistableBundle&& other) noexcept : mPBundle(other.release()) {} + // duplicates, does not take ownership of the APersistableBundle* + PersistableBundle(const PersistableBundle& other) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + mPBundle = APersistableBundle_dup(other.mPBundle); + } + } + // duplicates, does not take ownership of the APersistableBundle* + PersistableBundle& operator=(const PersistableBundle& other) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + mPBundle = APersistableBundle_dup(other.mPBundle); + } + return *this; + } + + ~PersistableBundle() { reset(); } + + binder_status_t readFromParcel(const AParcel* _Nonnull parcel) { + reset(); + if (__builtin_available(android __ANDROID_API_V__, *)) { + return APersistableBundle_readFromParcel(parcel, &mPBundle); + } else { + return STATUS_FAILED_TRANSACTION; + } + } + + binder_status_t writeToParcel(AParcel* _Nonnull parcel) const { + if (!mPBundle) { + return STATUS_BAD_VALUE; + } + if (__builtin_available(android __ANDROID_API_V__, *)) { + return APersistableBundle_writeToParcel(mPBundle, parcel); + } else { + return STATUS_FAILED_TRANSACTION; + } + } + + /** + * Destroys any currently owned APersistableBundle* and takes ownership of the given + * APersistableBundle* + * + * @param pBundle The APersistableBundle to take ownership of + */ + void reset(APersistableBundle* _Nullable pBundle = nullptr) noexcept { + if (mPBundle) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + APersistableBundle_delete(mPBundle); + } + mPBundle = nullptr; + } + mPBundle = pBundle; + } + + /** + * Check the actual contents of the bundle for equality. This is typically + * what should be used to check for equality. + */ + bool deepEquals(const PersistableBundle& rhs) const { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return APersistableBundle_isEqual(get(), rhs.get()); + } else { + return false; + } + } + + /** + * NOTE: This does NOT check the contents of the PersistableBundle. This is + * implemented for ordering. Use deepEquals() to check for equality between + * two different PersistableBundle objects. + */ + inline bool operator==(const PersistableBundle& rhs) const { return get() == rhs.get(); } + inline bool operator!=(const PersistableBundle& rhs) const { return get() != rhs.get(); } + + inline bool operator<(const PersistableBundle& rhs) const { return get() < rhs.get(); } + inline bool operator>(const PersistableBundle& rhs) const { return get() > rhs.get(); } + inline bool operator>=(const PersistableBundle& rhs) const { return !(*this < rhs); } + inline bool operator<=(const PersistableBundle& rhs) const { return !(*this > rhs); } + + PersistableBundle& operator=(PersistableBundle&& other) noexcept { + reset(other.release()); + return *this; + } + + /** + * Stops managing any contained APersistableBundle*, returning it to the caller. Ownership + * is released. + * @return APersistableBundle* or null if this was empty + */ + [[nodiscard]] APersistableBundle* _Nullable release() noexcept { + APersistableBundle* _Nullable ret = mPBundle; + mPBundle = nullptr; + return ret; + } + + inline std::string toString() const { + if (!mPBundle) { + return "<PersistableBundle: null>"; + } else if (__builtin_available(android __ANDROID_API_V__, *)) { + std::ostringstream os; + os << "<PersistableBundle: "; + os << "size: " << std::to_string(APersistableBundle_size(mPBundle)); + os << " >"; + return os.str(); + } + return "<PersistableBundle (unknown)>"; + } + + int32_t size() const { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return APersistableBundle_size(mPBundle); + } else { + return 0; + } + } + + int32_t erase(const std::string& key) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return APersistableBundle_erase(mPBundle, key.c_str()); + } else { + return 0; + } + } + + void putBoolean(const std::string& key, bool val) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + APersistableBundle_putBoolean(mPBundle, key.c_str(), val); + } + } + + void putInt(const std::string& key, int32_t val) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + APersistableBundle_putInt(mPBundle, key.c_str(), val); + } + } + + void putLong(const std::string& key, int64_t val) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + APersistableBundle_putLong(mPBundle, key.c_str(), val); + } + } + + void putDouble(const std::string& key, double val) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + APersistableBundle_putDouble(mPBundle, key.c_str(), val); + } + } + + void putString(const std::string& key, const std::string& val) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + APersistableBundle_putString(mPBundle, key.c_str(), val.c_str()); + } + } + + void putBooleanVector(const std::string& key, const std::vector<bool>& vec) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + // std::vector<bool> has no ::data(). + int32_t num = vec.size(); + if (num > 0) { + bool* newVec = (bool*)malloc(num * sizeof(bool)); + if (newVec) { + for (int32_t i = 0; i < num; i++) { + newVec[i] = vec[i]; + } + APersistableBundle_putBooleanVector(mPBundle, key.c_str(), newVec, num); + free(newVec); + } + } + } + } + + void putIntVector(const std::string& key, const std::vector<int32_t>& vec) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + int32_t num = vec.size(); + if (num > 0) { + APersistableBundle_putIntVector(mPBundle, key.c_str(), vec.data(), num); + } + } + } + void putLongVector(const std::string& key, const std::vector<int64_t>& vec) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + int32_t num = vec.size(); + if (num > 0) { + APersistableBundle_putLongVector(mPBundle, key.c_str(), vec.data(), num); + } + } + } + void putDoubleVector(const std::string& key, const std::vector<double>& vec) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + int32_t num = vec.size(); + if (num > 0) { + APersistableBundle_putDoubleVector(mPBundle, key.c_str(), vec.data(), num); + } + } + } + void putStringVector(const std::string& key, const std::vector<std::string>& vec) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + int32_t num = vec.size(); + if (num > 0) { + char** inVec = (char**)malloc(num * sizeof(char*)); + if (inVec) { + for (int32_t i = 0; i < num; i++) { + inVec[i] = strdup(vec[i].c_str()); + } + APersistableBundle_putStringVector(mPBundle, key.c_str(), inVec, num); + free(inVec); + } + } + } + } + void putPersistableBundle(const std::string& key, const PersistableBundle& pBundle) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + APersistableBundle_putPersistableBundle(mPBundle, key.c_str(), pBundle.mPBundle); + } + } + + bool getBoolean(const std::string& key, bool* _Nonnull val) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return APersistableBundle_getBoolean(mPBundle, key.c_str(), val); + } else { + return false; + } + } + + bool getInt(const std::string& key, int32_t* _Nonnull val) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return APersistableBundle_getInt(mPBundle, key.c_str(), val); + } else { + return false; + } + } + + bool getLong(const std::string& key, int64_t* _Nonnull val) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return APersistableBundle_getLong(mPBundle, key.c_str(), val); + } else { + return false; + } + } + + bool getDouble(const std::string& key, double* _Nonnull val) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return APersistableBundle_getDouble(mPBundle, key.c_str(), val); + } else { + return false; + } + } + + static char* _Nullable stringAllocator(int32_t bufferSizeBytes, void* _Nullable) { + return (char*)malloc(bufferSizeBytes); + } + + bool getString(const std::string& key, std::string* _Nonnull val) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + char* outString = nullptr; + bool ret = APersistableBundle_getString(mPBundle, key.c_str(), &outString, + &stringAllocator, nullptr); + if (ret && outString) { + *val = std::string(outString); + } + return ret; + } else { + return false; + } + } + + template <typename T> + bool 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) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + int32_t bytes = 0; + // call first with nullptr to get required size in bytes + bytes = getVec(pBundle, key, nullptr, 0); + if (bytes > 0) { + T* newVec = (T*)malloc(bytes); + if (newVec) { + bytes = getVec(pBundle, key, newVec, bytes); + int32_t elements = bytes / sizeof(T); + vec->clear(); + for (int32_t i = 0; i < elements; i++) { + vec->push_back(newVec[i]); + } + free(newVec); + return true; + } + } + } + return false; + } + + bool getBooleanVector(const std::string& key, std::vector<bool>* _Nonnull vec) { + return getVecInternal<bool>(&APersistableBundle_getBooleanVector, mPBundle, key.c_str(), + vec); + } + bool getIntVector(const std::string& key, std::vector<int32_t>* _Nonnull vec) { + return getVecInternal<int32_t>(&APersistableBundle_getIntVector, mPBundle, key.c_str(), + vec); + } + bool getLongVector(const std::string& key, std::vector<int64_t>* _Nonnull vec) { + return getVecInternal<int64_t>(&APersistableBundle_getLongVector, mPBundle, key.c_str(), + vec); + } + bool getDoubleVector(const std::string& key, std::vector<double>* _Nonnull vec) { + return getVecInternal<double>(&APersistableBundle_getDoubleVector, mPBundle, key.c_str(), + vec); + } + + // Takes ownership of and frees the char** and its elements. + // Creates a new set or vector based on the array of char*. + template <typename T> + T moveStringsInternal(char* _Nullable* _Nonnull strings, int32_t bufferSizeBytes) { + if (strings && bufferSizeBytes > 0) { + int32_t num = bufferSizeBytes / sizeof(char*); + T ret; + for (int32_t i = 0; i < num; i++) { + ret.insert(ret.end(), std::string(strings[i])); + free(strings[i]); + } + free(strings); + return ret; + } + return T(); + } + + bool getStringVector(const std::string& key, std::vector<std::string>* _Nonnull vec) { + int32_t bytes = APersistableBundle_getStringVector(mPBundle, key.c_str(), nullptr, 0, + &stringAllocator, nullptr); + if (bytes > 0) { + char** strings = (char**)malloc(bytes); + if (strings) { + bytes = APersistableBundle_getStringVector(mPBundle, key.c_str(), strings, bytes, + &stringAllocator, nullptr); + *vec = moveStringsInternal<std::vector<std::string>>(strings, bytes); + return true; + } + } + return false; + } + + bool getPersistableBundle(const std::string& key, PersistableBundle* _Nonnull val) { + if (__builtin_available(android __ANDROID_API_V__, *)) { + APersistableBundle* bundle = nullptr; + bool ret = APersistableBundle_getPersistableBundle(mPBundle, key.c_str(), &bundle); + if (ret) { + *val = PersistableBundle(bundle); + } + return ret; + } else { + return false; + } + } + + std::set<std::string> 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) { + // call first with nullptr to get required size in bytes + int32_t bytes = getTypedKeys(pBundle, nullptr, 0, &stringAllocator, nullptr); + if (bytes > 0) { + char** keys = (char**)malloc(bytes); + if (keys) { + bytes = getTypedKeys(pBundle, keys, bytes, &stringAllocator, nullptr); + return moveStringsInternal<std::set<std::string>>(keys, bytes); + } + } + return {}; + } + + std::set<std::string> getBooleanKeys() { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return getKeys(&APersistableBundle_getBooleanKeys, mPBundle); + } else { + return {}; + } + } + std::set<std::string> getIntKeys() { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return getKeys(&APersistableBundle_getIntKeys, mPBundle); + } else { + return {}; + } + } + std::set<std::string> getLongKeys() { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return getKeys(&APersistableBundle_getLongKeys, mPBundle); + } else { + return {}; + } + } + std::set<std::string> getDoubleKeys() { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return getKeys(&APersistableBundle_getDoubleKeys, mPBundle); + } else { + return {}; + } + } + std::set<std::string> getStringKeys() { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return getKeys(&APersistableBundle_getStringKeys, mPBundle); + } else { + return {}; + } + } + std::set<std::string> getBooleanVectorKeys() { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return getKeys(&APersistableBundle_getBooleanVectorKeys, mPBundle); + } else { + return {}; + } + } + std::set<std::string> getIntVectorKeys() { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return getKeys(&APersistableBundle_getIntVectorKeys, mPBundle); + } else { + return {}; + } + } + std::set<std::string> getLongVectorKeys() { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return getKeys(&APersistableBundle_getLongVectorKeys, mPBundle); + } else { + return {}; + } + } + std::set<std::string> getDoubleVectorKeys() { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return getKeys(&APersistableBundle_getDoubleVectorKeys, mPBundle); + } else { + return {}; + } + } + std::set<std::string> getStringVectorKeys() { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return getKeys(&APersistableBundle_getStringVectorKeys, mPBundle); + } else { + return {}; + } + } + std::set<std::string> getPersistableBundleKeys() { + if (__builtin_available(android __ANDROID_API_V__, *)) { + return getKeys(&APersistableBundle_getPersistableBundleKeys, mPBundle); + } else { + return {}; + } + } + std::set<std::string> getMonKeys() { + // :P + return {"c(o,o)b", "c(o,o)b"}; + } + + private: + inline APersistableBundle* _Nullable get() const { return mPBundle; } + APersistableBundle* _Nullable mPBundle = nullptr; +}; + +} // namespace aidl::android::os diff --git a/libs/binder/ndk/include_ndk/android/persistable_bundle.h b/libs/binder/ndk/include_ndk/android/persistable_bundle.h new file mode 100644 index 0000000000..eff81045b0 --- /dev/null +++ b/libs/binder/ndk/include_ndk/android/persistable_bundle.h @@ -0,0 +1,905 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <android/binder_parcel.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +__BEGIN_DECLS + +/* + * A mapping from string keys to values of various types. + * See frameworks/base/core/java/android/os/PersistableBundle.java + * for the Java type than can be used in SDK APIs. + * APersistableBundle exists to be used in AIDL interfaces and seamlessly + * interact with framework services. + * frameworks/native/libs/binder/ndk/include_cpp/android/persistable_bundle_aidl.h + * contains the AIDL type used in the ndk backend of AIDL interfaces. + */ +struct APersistableBundle; +typedef struct APersistableBundle APersistableBundle; + +/** + * This is a user supplied allocator that allocates a buffer for the + * APersistableBundle APIs to fill in with a string. + * + * \param the required size in bytes for the allocated buffer + * \param void* _Nullable context if needed by the callback + * + * \return allocated buffer of sizeBytes. Null if allocation failed. + */ +typedef char* _Nullable (*_Nonnull APersistableBundle_stringAllocator)(int32_t sizeBytes, + void* _Nullable context); + +/** + * Create a new APersistableBundle. + * + * Available since API level __ANDROID_API_V__. + * + * \return Pointer to a new APersistableBundle + */ +APersistableBundle* _Nullable APersistableBundle_new() __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Create a new APersistableBundle based off an existing APersistableBundle. + * + * Available since API level __ANDROID_API_V__. + * + * \param bundle to duplicate + * + * \return Pointer to a new APersistableBundle + */ +APersistableBundle* _Nullable APersistableBundle_dup(const APersistableBundle* _Nonnull pBundle) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Delete an APersistableBundle. This must always be called when finished using + * the object. + * + * \param bundle to delete + * + * Available since API level __ANDROID_API_V__. + */ +void APersistableBundle_delete(APersistableBundle* _Nonnull pBundle) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Check for equality of APersistableBundles. + * + * Available since API level __ANDROID_API_V__. + * + * \param lhs bundle to compare agains the other param + * \param rhs bundle to compare agains the other param + * + * \return true when equal, false when not + */ +bool APersistableBundle_isEqual(const APersistableBundle* _Nonnull lhs, + const APersistableBundle* _Nonnull rhs) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Read an APersistableBundle from an AParcel. + * + * Available since API level __ANDROID_API_V__. + * + * \param parcel to read from + * \param outPBundle bundle to write to + * + * \return STATUS_OK on success + * STATUS_BAD_VALUE if the parcel or outBuffer is null, or if there's an + * issue deserializing (eg, corrupted parcel) + * STATUS_BAD_TYPE if the parcel's current data position is not that of + * an APersistableBundle type + * STATUS_NO_MEMORY if an allocation fails + */ +binder_status_t APersistableBundle_readFromParcel( + const AParcel* _Nonnull parcel, APersistableBundle* _Nullable* _Nonnull outPBundle) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Write an APersistableBundle to an AParcel. + * + * Available since API level __ANDROID_API_V__. + * + * \param pBundle bundle to write to the parcel + * \param parcel to write to + * + * \return STATUS_OK on success. + * STATUS_BAD_VALUE if either pBundle or parcel is null, or if the + * APersistableBundle* + * fails to serialize (eg, internally corrupted) + * STATUS_NO_MEMORY if the parcel runs out of space to store the pBundle & is + * unable to allocate more + * STATUS_FDS_NOT_ALLOWED if the parcel does not allow storing FDs + */ +binder_status_t APersistableBundle_writeToParcel(const APersistableBundle* _Nonnull pBundle, + AParcel* _Nonnull parcel) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get the size of an APersistableBundle. This is the number of mappings in the + * object. + * + * Available since API level __ANDROID_API_V__. + * + * \param bundle to get the size of (number of mappings) + * + * \return number of mappings in the object + */ +int32_t APersistableBundle_size(APersistableBundle* _Nonnull pBundle) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Erase any entries added with the provided key. + * + * Available since API level __ANDROID_API_V__. + * + * \param bundle to operate on + * \param key for the mapping to erase + * + * \return number of entries erased. Either 0 or 1. + */ +int32_t APersistableBundle_erase(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Put a boolean associated with the provided key. + * New values with the same key will overwrite existing values. + * + * \param bundle to operate on + * \param key for the mapping + * \param value to put for the mapping + * + * Available since API level __ANDROID_API_V__. + */ +void APersistableBundle_putBoolean(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key, + bool val) __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Put an int32_t associated with the provided key. + * New values with the same key will overwrite existing values. + * + * \param bundle to operate on + * \param key for the mapping + * \param value to put for the mapping + * + * Available since API level __ANDROID_API_V__. + */ +void APersistableBundle_putInt(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key, + int32_t val) __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Put an int64_t associated with the provided key. + * New values with the same key will overwrite existing values. + * + * \param bundle to operate on + * \param key for the mapping + * \param value to put for the mapping + * + * Available since API level __ANDROID_API_V__. + */ +void APersistableBundle_putLong(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key, + int64_t val) __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Put a double associated with the provided key. + * New values with the same key will overwrite existing values. + * + * \param bundle to operate on + * \param key for the mapping + * \param value to put for the mapping + * + * Available since API level __ANDROID_API_V__. + */ +void APersistableBundle_putDouble(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key, + double val) __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Put a string associated with the provided key. + * New values with the same key will overwrite existing values. + * + * \param bundle to operate on + * \param key for the mapping + * \param value to put for the mapping + * + * Available since API level __ANDROID_API_V__. + */ +void APersistableBundle_putString(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key, + const char* _Nonnull val) __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Put a boolean vector associated with the provided key. + * New values with the same key will overwrite existing values. + * + * \param bundle to operate on + * \param key for the mapping + * \param value to put for the mapping + * \param size in number of elements in the vector + * + * Available since API level __ANDROID_API_V__. + */ +void APersistableBundle_putBooleanVector(APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, const bool* _Nonnull vec, + int32_t num) __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Put an int32_t vector associated with the provided key. + * New values with the same key will overwrite existing values. + * + * \param bundle to operate on + * \param key for the mapping + * \param value to put for the mapping + * \param size in number of elements in the vector + * + * Available since API level __ANDROID_API_V__. + */ +void APersistableBundle_putIntVector(APersistableBundle* _Nonnull pBundle, const char* _Nonnull key, + const int32_t* _Nonnull vec, int32_t num) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Put an int64_t vector associated with the provided key. + * New values with the same key will overwrite existing values. + * + * \param bundle to operate on + * \param key for the mapping + * \param value to put for the mapping + * \param size in number of elements in the vector + * + * Available since API level __ANDROID_API_V__. + */ +void APersistableBundle_putLongVector(APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, const int64_t* _Nonnull vec, + int32_t num) __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Put a double vector associated with the provided key. + * New values with the same key will overwrite existing values. + * + * \param bundle to operate on + * \param key for the mapping + * \param value to put for the mapping + * \param size in number of elements in the vector + * + * Available since API level __ANDROID_API_V__. + */ +void APersistableBundle_putDoubleVector(APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, const double* _Nonnull vec, + int32_t num) __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Put a string vector associated with the provided key. + * New values with the same key will overwrite existing values. + * + * \param bundle to operate on + * \param key for the mapping + * \param value to put for the mapping + * \param size in number of elements in the vector + * + * Available since API level __ANDROID_API_V__. + */ +void APersistableBundle_putStringVector(APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, + const char* _Nullable const* _Nullable vec, int32_t num) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Put an APersistableBundle associated with the provided key. + * New values with the same key will overwrite existing values. + * + * \param bundle to operate on + * \param key for the mapping + * \param value to put for the mapping + * + * Available since API level __ANDROID_API_V__. + */ +void APersistableBundle_putPersistableBundle(APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, + const APersistableBundle* _Nonnull val) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get a boolean associated with the provided key. + * + * Available since API level __ANDROID_API_V__. + * + * \param bundle to operate on + * \param key for the mapping + * \param nonnull pointer to write the value to + * + * \return true if a value exists for the provided key + */ +bool APersistableBundle_getBoolean(const APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, bool* _Nonnull val) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get an int32_t associated with the provided key. + * + * Available since API level __ANDROID_API_V__. + * + * \param bundle to operate on + * \param key for the mapping + * \param nonnull pointer to write the value to + * + * \return true if a value exists for the provided key + */ +bool APersistableBundle_getInt(const APersistableBundle* _Nonnull pBundle, const char* _Nonnull key, + int32_t* _Nonnull val) __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get an int64_t associated with the provided key. + * + * Available since API level __ANDROID_API_V__. + * + * \param bundle to operate on + * \param key for the mapping + * \param nonnull pointer to write the value to + * + * \return true if a value exists for the provided key + */ +bool APersistableBundle_getLong(const APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, int64_t* _Nonnull val) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get a double associated with the provided key. + * + * Available since API level __ANDROID_API_V__. + * + * \param bundle to operate on + * \param key for the mapping + * \param nonnull pointer to write the value to + * + * \return true if a value exists for the provided key + */ +bool APersistableBundle_getDouble(const APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, double* _Nonnull val) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get a string associated with the provided key. + * + * Available since API level __ANDROID_API_V__. + * + * \param bundle to operate on + * \param key for the mapping + * \param nonnull pointer to write the value to + * \param function pointer to the string dup allocator + * + * \return size of string associated with the provided key on success + * 0 if no string exists for the provided key + * -1 if the provided allocator fails and returns false + */ +int32_t APersistableBundle_getString(const APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, char* _Nullable* _Nonnull val, + APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get a boolean vector associated with the provided key and place it in the + * provided pre-allocated buffer from the user. + * + * This function returns the size in bytes of stored vector. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param key for the mapping + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * + * \return size of the stored vector in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + */ +int32_t APersistableBundle_getBooleanVector(const APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, bool* _Nullable buffer, + int32_t bufferSizeBytes) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get an int32_t vector associated with the provided key and place it in the + * provided pre-allocated buffer from the user. + * + * This function returns the size in bytes of stored vector. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param key for the mapping + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * + * \return size of the stored vector in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + */ +int32_t APersistableBundle_getIntVector(const APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, int32_t* _Nullable buffer, + int32_t bufferSizeBytes) __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get an int64_t vector associated with the provided key and place it in the + * provided pre-allocated buffer from the user. + * + * This function returns the size in bytes of stored vector. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param key for the mapping + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * + * \return size of the stored vector in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + */ +int32_t APersistableBundle_getLongVector(const APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, int64_t* _Nullable buffer, + int32_t bufferSizeBytes) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get a double vector associated with the provided key and place it in the + * provided pre-allocated buffer from the user. + * + * This function returns the size in bytes of stored vector. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param key for the mapping + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * + * \return size of the stored vector in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + */ +int32_t APersistableBundle_getDoubleVector(const APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, double* _Nullable buffer, + int32_t bufferSizeBytes) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get a string vector associated with the provided key and place it in the + * provided pre-allocated buffer from the user. The user must provide an + * APersistableBundle_stringAllocator for the individual strings to be + * allocated. + * + * This function returns the size in bytes of stored vector. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param key for the mapping + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * \param function pointer to the string dup allocator + * + * \return size of the stored vector in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + * 0 if no string vector exists for the provided key + * -1 if the user supplied APersistableBundle_stringAllocator returns + * false + */ +int32_t APersistableBundle_getStringVector(const APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, + char* _Nullable* _Nullable buffer, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get an APersistableBundle* associated with the provided key. + * + * Available since API level __ANDROID_API_V__. + * + * \param bundle to operate on + * \param key for the mapping + * \param nonnull pointer to an APersistableBundle pointer to write to point to + * a new copy of the stored APersistableBundle. The caller takes ownership of + * the new APersistableBundle and must be deleted with + * APersistableBundle_delete. + * + * \return true if a value exists for the provided key + */ +bool APersistableBundle_getPersistableBundle(const APersistableBundle* _Nonnull pBundle, + const char* _Nonnull key, + APersistableBundle* _Nullable* _Nonnull outBundle) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get all of the keys associated with this specific type and place it in the + * provided pre-allocated buffer from the user. The user must provide an + * APersistableBundle_stringAllocator for the individual strings to be + * allocated. + * + * This function returns the size in bytes required to fit the fill list of keys. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * \param function pointer to the string dup allocator + * + * \return size of the buffer of keys in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + * 0 if no string vector exists for the provided key + * -1 if the user supplied APersistableBundle_stringAllocator returns + * false + */ +int32_t APersistableBundle_getBooleanKeys(const APersistableBundle* _Nonnull pBundle, + char* _Nullable* _Nullable outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get all of the keys associated with this specific type and place it in the + * provided pre-allocated buffer from the user. The user must provide an + * APersistableBundle_stringAllocator for the individual strings to be + * allocated. + * + * This function returns the size in bytes required to fit the fill list of keys. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * \param function pointer to the string dup allocator + * + * \return size of the buffer of keys in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + * 0 if no string vector exists for the provided key + * -1 if the user supplied APersistableBundle_stringAllocator returns + * false + */ +int32_t APersistableBundle_getIntKeys(const APersistableBundle* _Nonnull pBundle, + char* _Nullable* _Nullable outKeys, int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get all of the keys associated with this specific type and place it in the + * provided pre-allocated buffer from the user. The user must provide an + * APersistableBundle_stringAllocator for the individual strings to be + * allocated. + * + * This function returns the size in bytes required to fit the fill list of keys. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * \param function pointer to the string dup allocator + * + * \return size of the buffer of keys in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + * 0 if no string vector exists for the provided key + * -1 if the user supplied APersistableBundle_stringAllocator returns + * false + */ +int32_t APersistableBundle_getLongKeys(const APersistableBundle* _Nonnull pBundle, + char* _Nullable* _Nullable outKeys, int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get all of the keys associated with this specific type and place it in the + * provided pre-allocated buffer from the user. The user must provide an + * APersistableBundle_stringAllocator for the individual strings to be + * allocated. + * + * This function returns the size in bytes required to fit the fill list of keys. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * \param function pointer to the string dup allocator + * + * \return size of the buffer of keys in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + * 0 if no string vector exists for the provided key + * -1 if the user supplied APersistableBundle_stringAllocator returns + * false + */ +int32_t APersistableBundle_getDoubleKeys(const APersistableBundle* _Nonnull pBundle, + char* _Nullable* _Nullable outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get all of the keys associated with this specific type and place it in the + * provided pre-allocated buffer from the user. The user must provide an + * APersistableBundle_stringAllocator for the individual strings to be + * allocated. + * + * This function returns the size in bytes required to fit the fill list of keys. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * \param function pointer to the string dup allocator + * + * \return size of the buffer of keys in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + * 0 if no string vector exists for the provided key + * -1 if the user supplied APersistableBundle_stringAllocator returns + * false + */ +int32_t APersistableBundle_getStringKeys(const APersistableBundle* _Nonnull pBundle, + char* _Nullable* _Nullable outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get all of the keys associated with this specific type and place it in the + * provided pre-allocated buffer from the user. The user must provide an + * APersistableBundle_stringAllocator for the individual strings to be + * allocated. + * + * This function returns the size in bytes required to fit the fill list of keys. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * \param function pointer to the string dup allocator + * + * \return size of the buffer of keys in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + * 0 if no string vector exists for the provided key + * -1 if the user supplied APersistableBundle_stringAllocator returns + * false + */ +int32_t APersistableBundle_getBooleanVectorKeys(const APersistableBundle* _Nonnull pBundle, + char* _Nullable* _Nullable outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get all of the keys associated with this specific type and place it in the + * provided pre-allocated buffer from the user. The user must provide an + * APersistableBundle_stringAllocator for the individual strings to be + * allocated. + * + * This function returns the size in bytes required to fit the fill list of keys. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * \param function pointer to the string dup allocator + * + * \return size of the buffer of keys in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + * 0 if no string vector exists for the provided key + * -1 if the user supplied APersistableBundle_stringAllocator returns + * false + */ +int32_t APersistableBundle_getIntVectorKeys(const APersistableBundle* _Nonnull pBundle, + char* _Nullable* _Nullable outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get all of the keys associated with this specific type and place it in the + * provided pre-allocated buffer from the user. The user must provide an + * APersistableBundle_stringAllocator for the individual strings to be + * allocated. + * + * This function returns the size in bytes required to fit the fill list of keys. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * \param function pointer to the string dup allocator + * + * \return size of the buffer of keys in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + * 0 if no string vector exists for the provided key + * -1 if the user supplied APersistableBundle_stringAllocator returns + * false + */ +int32_t APersistableBundle_getLongVectorKeys(const APersistableBundle* _Nonnull pBundle, + char* _Nullable* _Nullable outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get all of the keys associated with this specific type and place it in the + * provided pre-allocated buffer from the user. The user must provide an + * APersistableBundle_stringAllocator for the individual strings to be + * allocated. + * + * This function returns the size in bytes required to fit the fill list of keys. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * \param function pointer to the string dup allocator + * + * \return size of the buffer of keys in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + * 0 if no string vector exists for the provided key + * -1 if the user supplied APersistableBundle_stringAllocator returns + * false + */ +int32_t APersistableBundle_getDoubleVectorKeys(const APersistableBundle* _Nonnull pBundle, + char* _Nullable* _Nullable outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get all of the keys associated with this specific type and place it in the + * provided pre-allocated buffer from the user. The user must provide an + * APersistableBundle_stringAllocator for the individual strings to be + * allocated. + * + * This function returns the size in bytes required to fit the fill list of keys. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * \param function pointer to the string dup allocator + * + * \return size of the buffer of keys in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + * 0 if no string vector exists for the provided key + * -1 if the user supplied APersistableBundle_stringAllocator returns + * false + */ +int32_t APersistableBundle_getStringVectorKeys(const APersistableBundle* _Nonnull pBundle, + char* _Nullable* _Nullable outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) + __INTRODUCED_IN(__ANDROID_API_V__); + +/** + * Get all of the keys associated with this specific type and place it in the + * provided pre-allocated buffer from the user. The user must provide an + * APersistableBundle_stringAllocator for the individual strings to be + * allocated. + * + * This function returns the size in bytes required to fit the fill list of keys. + * The supplied buffer will be filled in based on the smaller of the suplied + * bufferSizeBytes or the actual size of the stored data. + * If the buffer is null or if the supplied bufferSizeBytes is smaller than the + * actual stored data, then not all of the stored data will be returned. + * + * Users can call this function with null buffer and 0 bufferSizeBytes to get + * the required size of the buffer to use on a subsequent call. + * + * \param bundle to operate on + * \param nonnull pointer to a pre-allocated buffer to write the values to + * \param size of the pre-allocated buffer + * \param function pointer to the string dup allocator + * + * \return size of the buffer of keys in bytes. This is the required size of the + * pre-allocated user supplied buffer if all of the stored contents are desired. + * 0 if no string vector exists for the provided key + * -1 if the user supplied APersistableBundle_stringAllocator returns + * false + */ +int32_t APersistableBundle_getPersistableBundleKeys( + const APersistableBundle* _Nonnull pBundle, char* _Nullable* _Nullable outKeys, + int32_t bufferSizeBytes, APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) __INTRODUCED_IN(__ANDROID_API_V__); + +__END_DECLS diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt index 1c5f79f791..0843a8e648 100644 --- a/libs/binder/ndk/libbinder_ndk.map.txt +++ b/libs/binder/ndk/libbinder_ndk.map.txt @@ -161,6 +161,51 @@ LIBBINDER_NDK34 { # introduced=UpsideDownCake AServiceManager_addServiceWithFlags; # systemapi llndk }; +LIBBINDER_NDK35 { # introduced=VanillaIceCream + global: + APersistableBundle_readFromParcel; + APersistableBundle_writeToParcel; + APersistableBundle_new; + APersistableBundle_dup; + APersistableBundle_delete; + APersistableBundle_isEqual; + APersistableBundle_size; + APersistableBundle_erase; + APersistableBundle_putBoolean; + APersistableBundle_putInt; + APersistableBundle_putLong; + APersistableBundle_putDouble; + APersistableBundle_putString; + APersistableBundle_putBooleanVector; + APersistableBundle_putIntVector; + APersistableBundle_putLongVector; + APersistableBundle_putDoubleVector; + APersistableBundle_putStringVector; + APersistableBundle_putPersistableBundle; + APersistableBundle_getBoolean; + APersistableBundle_getInt; + APersistableBundle_getLong; + APersistableBundle_getDouble; + APersistableBundle_getString; + APersistableBundle_getBooleanVector; + APersistableBundle_getIntVector; + APersistableBundle_getLongVector; + APersistableBundle_getDoubleVector; + APersistableBundle_getStringVector; + APersistableBundle_getPersistableBundle; + APersistableBundle_getBooleanKeys; + APersistableBundle_getIntKeys; + APersistableBundle_getLongKeys; + APersistableBundle_getDoubleKeys; + APersistableBundle_getStringKeys; + APersistableBundle_getBooleanVectorKeys; + APersistableBundle_getIntVectorKeys; + APersistableBundle_getLongVectorKeys; + APersistableBundle_getDoubleVectorKeys; + APersistableBundle_getStringVectorKeys; + APersistableBundle_getPersistableBundleKeys; +}; + LIBBINDER_NDK_PLATFORM { global: AParcel_getAllowFds; diff --git a/libs/binder/ndk/persistable_bundle.cpp b/libs/binder/ndk/persistable_bundle.cpp new file mode 100644 index 0000000000..404611cbba --- /dev/null +++ b/libs/binder/ndk/persistable_bundle.cpp @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <android/binder_libbinder.h> +#include <android/persistable_bundle.h> +#include <binder/PersistableBundle.h> +#include <log/log.h> +#include <persistable_bundle_internal.h> +#include <string.h> + +#include <set> + +__BEGIN_DECLS + +struct APersistableBundle { + APersistableBundle(const APersistableBundle& pBundle) : mPBundle(pBundle.mPBundle) {} + APersistableBundle(const android::os::PersistableBundle& pBundle) : mPBundle(pBundle) {} + APersistableBundle() = default; + android::os::PersistableBundle mPBundle; +}; + +APersistableBundle* _Nullable APersistableBundle_new() { + return new (std::nothrow) APersistableBundle(); +} + +APersistableBundle* _Nullable APersistableBundle_dup(const APersistableBundle* pBundle) { + if (pBundle) { + return new APersistableBundle(*pBundle); + } else { + return new APersistableBundle(); + } +} + +void APersistableBundle_delete(APersistableBundle* pBundle) { + free(pBundle); +} + +bool APersistableBundle_isEqual(const APersistableBundle* lhs, const APersistableBundle* rhs) { + if (lhs && rhs) { + return lhs->mPBundle == rhs->mPBundle; + } else if (lhs == rhs) { + return true; + } else { + return false; + } +} + +binder_status_t APersistableBundle_readFromParcel(const AParcel* parcel, + APersistableBundle* _Nullable* outPBundle) { + if (!parcel || !outPBundle) return STATUS_BAD_VALUE; + APersistableBundle* newPBundle = APersistableBundle_new(); + if (newPBundle == nullptr) return STATUS_NO_MEMORY; + binder_status_t status = + newPBundle->mPBundle.readFromParcel(AParcel_viewPlatformParcel(parcel)); + if (status == STATUS_OK) { + *outPBundle = newPBundle; + } + return status; +} + +binder_status_t APersistableBundle_writeToParcel(const APersistableBundle* pBundle, + AParcel* parcel) { + if (!parcel || !pBundle) return STATUS_BAD_VALUE; + return pBundle->mPBundle.writeToParcel(AParcel_viewPlatformParcel(parcel)); +} + +int32_t APersistableBundle_size(APersistableBundle* pBundle) { + size_t size = pBundle->mPBundle.size(); + LOG_ALWAYS_FATAL_IF(size > INT32_MAX, + "The APersistableBundle has gotten too large! There will be an overflow in " + "the reported size."); + return pBundle->mPBundle.size(); +} +int32_t APersistableBundle_erase(APersistableBundle* pBundle, const char* key) { + return pBundle->mPBundle.erase(android::String16(key)); +} +void APersistableBundle_putBoolean(APersistableBundle* pBundle, const char* key, bool val) { + pBundle->mPBundle.putBoolean(android::String16(key), val); +} +void APersistableBundle_putInt(APersistableBundle* pBundle, const char* key, int32_t val) { + pBundle->mPBundle.putInt(android::String16(key), val); +} +void APersistableBundle_putLong(APersistableBundle* pBundle, const char* key, int64_t val) { + pBundle->mPBundle.putLong(android::String16(key), val); +} +void APersistableBundle_putDouble(APersistableBundle* pBundle, const char* key, double val) { + pBundle->mPBundle.putDouble(android::String16(key), val); +} +void APersistableBundle_putString(APersistableBundle* pBundle, const char* key, const char* val) { + pBundle->mPBundle.putString(android::String16(key), android::String16(val)); +} +void APersistableBundle_putBooleanVector(APersistableBundle* pBundle, const char* key, + const bool* vec, int32_t num) { + LOG_ALWAYS_FATAL_IF(num < 0, "Negative number of elements is invalid."); + std::vector<bool> newVec(num); + for (int32_t i = 0; i < num; i++) { + newVec[i] = vec[i]; + } + pBundle->mPBundle.putBooleanVector(android::String16(key), newVec); +} +void APersistableBundle_putIntVector(APersistableBundle* pBundle, const char* key, + const int32_t* vec, int32_t num) { + LOG_ALWAYS_FATAL_IF(num < 0, "Negative number of elements is invalid."); + std::vector<int32_t> newVec(num); + for (int32_t i = 0; i < num; i++) { + newVec[i] = vec[i]; + } + pBundle->mPBundle.putIntVector(android::String16(key), newVec); +} +void APersistableBundle_putLongVector(APersistableBundle* pBundle, const char* key, + const int64_t* vec, int32_t num) { + LOG_ALWAYS_FATAL_IF(num < 0, "Negative number of elements is invalid."); + std::vector<int64_t> newVec(num); + for (int32_t i = 0; i < num; i++) { + newVec[i] = vec[i]; + } + pBundle->mPBundle.putLongVector(android::String16(key), newVec); +} +void APersistableBundle_putDoubleVector(APersistableBundle* pBundle, const char* key, + const double* vec, int32_t num) { + LOG_ALWAYS_FATAL_IF(num < 0, "Negative number of elements is invalid."); + std::vector<double> newVec(num); + for (int32_t i = 0; i < num; i++) { + newVec[i] = vec[i]; + } + pBundle->mPBundle.putDoubleVector(android::String16(key), newVec); +} +void APersistableBundle_putStringVector(APersistableBundle* pBundle, const char* key, + const char* const* vec, int32_t num) { + LOG_ALWAYS_FATAL_IF(num < 0, "Negative number of elements is invalid."); + std::vector<android::String16> newVec(num); + for (int32_t i = 0; i < num; i++) { + newVec[i] = android::String16(vec[i]); + } + pBundle->mPBundle.putStringVector(android::String16(key), newVec); +} +void APersistableBundle_putPersistableBundle(APersistableBundle* pBundle, const char* key, + const APersistableBundle* val) { + pBundle->mPBundle.putPersistableBundle(android::String16(key), val->mPBundle); +} +bool APersistableBundle_getBoolean(const APersistableBundle* pBundle, const char* key, bool* val) { + return pBundle->mPBundle.getBoolean(android::String16(key), val); +} +bool APersistableBundle_getInt(const APersistableBundle* pBundle, const char* key, int32_t* val) { + return pBundle->mPBundle.getInt(android::String16(key), val); +} +bool APersistableBundle_getLong(const APersistableBundle* pBundle, const char* key, int64_t* val) { + return pBundle->mPBundle.getLong(android::String16(key), val); +} +bool APersistableBundle_getDouble(const APersistableBundle* pBundle, const char* key, double* val) { + return pBundle->mPBundle.getDouble(android::String16(key), val); +} +int32_t APersistableBundle_getString(const APersistableBundle* pBundle, const char* key, char** val, + APersistableBundle_stringAllocator stringAllocator, + void* context) { + android::String16 outVal; + bool ret = pBundle->mPBundle.getString(android::String16(key), &outVal); + if (ret) { + android::String8 tmp8(outVal); + *val = stringAllocator(tmp8.bytes() + 1, context); + if (*val) { + strncpy(*val, tmp8.c_str(), tmp8.bytes() + 1); + return tmp8.bytes(); + } else { + return -1; + } + } + return 0; +} +int32_t APersistableBundle_getBooleanVector(const APersistableBundle* pBundle, const char* key, + bool* buffer, int32_t bufferSizeBytes) { + std::vector<bool> newVec; + pBundle->mPBundle.getBooleanVector(android::String16(key), &newVec); + return getVecInternal<bool>(newVec, buffer, bufferSizeBytes); +} +int32_t APersistableBundle_getIntVector(const APersistableBundle* pBundle, const char* key, + int32_t* buffer, int32_t bufferSizeBytes) { + std::vector<int32_t> newVec; + pBundle->mPBundle.getIntVector(android::String16(key), &newVec); + return getVecInternal<int32_t>(newVec, buffer, bufferSizeBytes); +} +int32_t APersistableBundle_getLongVector(const APersistableBundle* pBundle, const char* key, + int64_t* buffer, int32_t bufferSizeBytes) { + std::vector<int64_t> newVec; + pBundle->mPBundle.getLongVector(android::String16(key), &newVec); + return getVecInternal<int64_t>(newVec, buffer, bufferSizeBytes); +} +int32_t APersistableBundle_getDoubleVector(const APersistableBundle* pBundle, const char* key, + double* buffer, int32_t bufferSizeBytes) { + std::vector<double> newVec; + pBundle->mPBundle.getDoubleVector(android::String16(key), &newVec); + return getVecInternal<double>(newVec, buffer, bufferSizeBytes); +} +int32_t APersistableBundle_getStringVector(const APersistableBundle* pBundle, const char* key, + char** vec, int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* context) { + std::vector<android::String16> newVec; + pBundle->mPBundle.getStringVector(android::String16(key), &newVec); + return getStringsInternal<std::vector<android::String16>>(newVec, vec, bufferSizeBytes, + stringAllocator, context); +} +bool APersistableBundle_getPersistableBundle(const APersistableBundle* pBundle, const char* key, + APersistableBundle** outBundle) { + APersistableBundle* bundle = APersistableBundle_new(); + bool ret = pBundle->mPBundle.getPersistableBundle(android::String16(key), &bundle->mPBundle); + if (ret) { + *outBundle = bundle; + return true; + } + return false; +} +int32_t APersistableBundle_getBooleanKeys(const APersistableBundle* pBundle, char** outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* context) { + std::set<android::String16> ret = pBundle->mPBundle.getBooleanKeys(); + return getStringsInternal<std::set<android::String16>>(ret, outKeys, bufferSizeBytes, + stringAllocator, context); +} +int32_t APersistableBundle_getIntKeys(const APersistableBundle* pBundle, char** outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* context) { + std::set<android::String16> ret = pBundle->mPBundle.getIntKeys(); + return getStringsInternal<std::set<android::String16>>(ret, outKeys, bufferSizeBytes, + stringAllocator, context); +} +int32_t APersistableBundle_getLongKeys(const APersistableBundle* pBundle, char** outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* context) { + std::set<android::String16> ret = pBundle->mPBundle.getLongKeys(); + return getStringsInternal<std::set<android::String16>>(ret, outKeys, bufferSizeBytes, + stringAllocator, context); +} +int32_t APersistableBundle_getDoubleKeys(const APersistableBundle* pBundle, char** outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* context) { + std::set<android::String16> ret = pBundle->mPBundle.getDoubleKeys(); + return getStringsInternal<std::set<android::String16>>(ret, outKeys, bufferSizeBytes, + stringAllocator, context); +} +int32_t APersistableBundle_getStringKeys(const APersistableBundle* pBundle, char** outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* context) { + std::set<android::String16> ret = pBundle->mPBundle.getStringKeys(); + return getStringsInternal<std::set<android::String16>>(ret, outKeys, bufferSizeBytes, + stringAllocator, context); +} +int32_t APersistableBundle_getBooleanVectorKeys(const APersistableBundle* pBundle, char** outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* context) { + std::set<android::String16> ret = pBundle->mPBundle.getBooleanVectorKeys(); + return getStringsInternal<std::set<android::String16>>(ret, outKeys, bufferSizeBytes, + stringAllocator, context); +} +int32_t APersistableBundle_getIntVectorKeys(const APersistableBundle* pBundle, char** outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* context) { + std::set<android::String16> ret = pBundle->mPBundle.getIntVectorKeys(); + return getStringsInternal<std::set<android::String16>>(ret, outKeys, bufferSizeBytes, + stringAllocator, context); +} +int32_t APersistableBundle_getLongVectorKeys(const APersistableBundle* pBundle, char** outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* context) { + std::set<android::String16> ret = pBundle->mPBundle.getLongVectorKeys(); + return getStringsInternal<std::set<android::String16>>(ret, outKeys, bufferSizeBytes, + stringAllocator, context); +} +int32_t APersistableBundle_getDoubleVectorKeys(const APersistableBundle* pBundle, char** outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* context) { + std::set<android::String16> ret = pBundle->mPBundle.getDoubleVectorKeys(); + return getStringsInternal<std::set<android::String16>>(ret, outKeys, bufferSizeBytes, + stringAllocator, context); +} +int32_t APersistableBundle_getStringVectorKeys(const APersistableBundle* pBundle, char** outKeys, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* context) { + std::set<android::String16> ret = pBundle->mPBundle.getStringVectorKeys(); + return getStringsInternal<std::set<android::String16>>(ret, outKeys, bufferSizeBytes, + stringAllocator, context); +} +int32_t APersistableBundle_getPersistableBundleKeys( + const APersistableBundle* pBundle, char** outKeys, int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, void* context) { + std::set<android::String16> ret = pBundle->mPBundle.getPersistableBundleKeys(); + return getStringsInternal<std::set<android::String16>>(ret, outKeys, bufferSizeBytes, + stringAllocator, context); +} + +__END_DECLS diff --git a/libs/binder/ndk/persistable_bundle_internal.h b/libs/binder/ndk/persistable_bundle_internal.h new file mode 100644 index 0000000000..279c66fdcc --- /dev/null +++ b/libs/binder/ndk/persistable_bundle_internal.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include <android/persistable_bundle.h> +#include <log/log.h> +#include <utils/String8.h> + +// take a vector and put the contents into a buffer. +// return the size of the contents. +// This may not put all of the contents into the buffer if the buffer is not +// large enough. +template <typename T> +int32_t getVecInternal(const std::vector<T>& inVec, T* _Nullable buffer, int32_t bufferSizeBytes) { + LOG_ALWAYS_FATAL_IF(inVec.size() > INT32_MAX, + "The size of the APersistableBundle has gotten too large!"); + LOG_ALWAYS_FATAL_IF( + bufferSizeBytes < 0, + "The buffer size in bytes can not be larger than INT32_MAX and can not be negative."); + int32_t num = inVec.size(); + int32_t numAvailable = bufferSizeBytes / sizeof(T); + int32_t numFill = numAvailable < num ? numAvailable : num; + + if (numFill > 0 && buffer) { + for (int32_t i = 0; i < numFill; i++) { + buffer[i] = inVec[i]; + } + } + return num * sizeof(T); +} + +// take a vector or a set of String16 and put the contents into a char** buffer. +// return the size of the contents. +// This may not put all of the contents into the buffer if the buffer is not +// large enough. +// The strings are duped with a user supplied callback +template <typename T> +int32_t getStringsInternal(const T& strings, char* _Nullable* _Nullable buffer, + int32_t bufferSizeBytes, + APersistableBundle_stringAllocator stringAllocator, + void* _Nullable context) { + LOG_ALWAYS_FATAL_IF(strings.size() > INT32_MAX, + "The size of the APersistableBundle has gotten too large!"); + LOG_ALWAYS_FATAL_IF( + bufferSizeBytes < 0, + "The buffer size in bytes can not be larger than INT32_MAX and can not be negative."); + int32_t num = strings.size(); + int32_t numAvailable = bufferSizeBytes / sizeof(char*); + int32_t numFill = numAvailable < num ? numAvailable : num; + if (!stringAllocator) { + return -1; + } + + if (numFill > 0 && buffer) { + int32_t i = 0; + for (const auto& val : strings) { + android::String8 tmp8 = android::String8(val); + buffer[i] = stringAllocator(tmp8.bytes() + 1, context); + if (buffer[i] == nullptr) { + return -1; + } + strncpy(buffer[i], tmp8.c_str(), tmp8.bytes() + 1); + i++; + if (i > numFill - 1) { + // buffer is too small to keep going or this is the end of the + // set + break; + } + } + } + return num * sizeof(char*); +} |