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
diff --git a/Android.bp b/Android.bp
index 3992f82..81d0615 100644
--- a/Android.bp
+++ b/Android.bp
@@ -89,6 +89,12 @@
],
}
+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 493ecb4..248e973 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 58ed418..47b9f58 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -60,6 +60,7 @@
"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 0000000..f178027
--- /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 0000000..eff8104
--- /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 1c5f79f..0843a8e 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -161,6 +161,51 @@
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 0000000..404611c
--- /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 0000000..279c66f
--- /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*);
+}