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*);
+}