Support Rust PersistableBundle in AIDL.

Bug: 389074518
Test: atest libbinder_rs-internal_test
Change-Id: I2ba487b6bd1ea18b2fc3eb331b1376cf20473408

diff --git a/aidl/binder/android/os/PersistableBundle.aidl b/aidl/binder/android/os/PersistableBundle.aidl
index 248e973..9b11109 100644
--- a/aidl/binder/android/os/PersistableBundle.aidl
+++ b/aidl/binder/android/os/PersistableBundle.aidl
@@ -17,4 +17,4 @@
 
 package android.os;
 
-@JavaOnlyStableParcelable @NdkOnlyStableParcelable parcelable PersistableBundle cpp_header "binder/PersistableBundle.h" ndk_header "android/persistable_bundle_aidl.h";
+@JavaOnlyStableParcelable @NdkOnlyStableParcelable @RustOnlyStableParcelable parcelable PersistableBundle cpp_header "binder/PersistableBundle.h" ndk_header "android/persistable_bundle_aidl.h" rust_type "binder::PersistableBundle";
diff --git a/libs/binder/rust/src/persistable_bundle.rs b/libs/binder/rust/src/persistable_bundle.rs
index c62feb0..1323d99 100644
--- a/libs/binder/rust/src/persistable_bundle.rs
+++ b/libs/binder/rust/src/persistable_bundle.rs
@@ -14,11 +14,18 @@
  * limitations under the License.
  */
 
+use crate::{
+    binder::AsNative,
+    error::{status_result, StatusCode},
+    impl_deserialize_for_unstructured_parcelable, impl_serialize_for_unstructured_parcelable,
+    parcel::{BorrowedParcel, UnstructuredParcelable},
+};
 use binder_ndk_sys::{
     APersistableBundle, APersistableBundle_delete, APersistableBundle_dup,
-    APersistableBundle_isEqual, APersistableBundle_new, APersistableBundle_size,
+    APersistableBundle_isEqual, APersistableBundle_new, APersistableBundle_readFromParcel,
+    APersistableBundle_size, APersistableBundle_writeToParcel,
 };
-use std::ptr::NonNull;
+use std::ptr::{null_mut, NonNull};
 
 /// A mapping from string keys to values of various types.
 #[derive(Debug)]
@@ -42,6 +49,13 @@
     }
 }
 
+// SAFETY: The underlying *APersistableBundle can be moved between threads.
+unsafe impl Send for PersistableBundle {}
+
+// SAFETY: The underlying *APersistableBundle can be read from multiple threads, and we require
+// `&mut PersistableBundle` for any operations which mutate it.
+unsafe impl Sync for PersistableBundle {}
+
 impl Default for PersistableBundle {
     fn default() -> Self {
         Self::new()
@@ -73,6 +87,34 @@
     }
 }
 
+impl UnstructuredParcelable for PersistableBundle {
+    fn write_to_parcel(&self, parcel: &mut BorrowedParcel) -> Result<(), StatusCode> {
+        let status =
+        // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+        // lifetime of the `PersistableBundle`. `parcel.as_native_mut()` always returns a valid
+        // parcel pointer.
+            unsafe { APersistableBundle_writeToParcel(self.0.as_ptr(), parcel.as_native_mut()) };
+        status_result(status)
+    }
+
+    fn from_parcel(parcel: &BorrowedParcel) -> Result<Self, StatusCode> {
+        let mut bundle = null_mut();
+
+        // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+        // lifetime of the `PersistableBundle`. `parcel.as_native()` always returns a valid parcel
+        // pointer.
+        let status = unsafe { APersistableBundle_readFromParcel(parcel.as_native(), &mut bundle) };
+        status_result(status)?;
+
+        Ok(Self(NonNull::new(bundle).expect(
+            "APersistableBundle_readFromParcel returned success but didn't allocate bundle",
+        )))
+    }
+}
+
+impl_deserialize_for_unstructured_parcelable!(PersistableBundle);
+impl_serialize_for_unstructured_parcelable!(PersistableBundle);
+
 #[cfg(test)]
 mod test {
     use super::*;