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::*;