Merge "Add methods to get vectors." into main am: 430db867d4 am: 3d6cfc8cc6
Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/3455342
Change-Id: I7ac4f797d0742c38209f02d05577b5ca5ca6512b
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/libs/binder/rust/src/persistable_bundle.rs b/libs/binder/rust/src/persistable_bundle.rs
index 367f334..d71ed73 100644
--- a/libs/binder/rust/src/persistable_bundle.rs
+++ b/libs/binder/rust/src/persistable_bundle.rs
@@ -22,17 +22,18 @@
};
use binder_ndk_sys::{
APersistableBundle, APersistableBundle_delete, APersistableBundle_dup,
- APersistableBundle_erase, APersistableBundle_getBoolean, APersistableBundle_getDouble,
- APersistableBundle_getInt, APersistableBundle_getLong, APersistableBundle_getPersistableBundle,
- APersistableBundle_isEqual, APersistableBundle_new, APersistableBundle_putBoolean,
- APersistableBundle_putBooleanVector, APersistableBundle_putDouble,
- APersistableBundle_putDoubleVector, APersistableBundle_putInt, APersistableBundle_putIntVector,
- APersistableBundle_putLong, APersistableBundle_putLongVector,
+ APersistableBundle_erase, APersistableBundle_getBoolean, APersistableBundle_getBooleanVector,
+ APersistableBundle_getDouble, APersistableBundle_getDoubleVector, APersistableBundle_getInt,
+ APersistableBundle_getIntVector, APersistableBundle_getLong, APersistableBundle_getLongVector,
+ APersistableBundle_getPersistableBundle, APersistableBundle_isEqual, APersistableBundle_new,
+ APersistableBundle_putBoolean, APersistableBundle_putBooleanVector,
+ APersistableBundle_putDouble, APersistableBundle_putDoubleVector, APersistableBundle_putInt,
+ APersistableBundle_putIntVector, APersistableBundle_putLong, APersistableBundle_putLongVector,
APersistableBundle_putPersistableBundle, APersistableBundle_putString,
APersistableBundle_putStringVector, APersistableBundle_readFromParcel, APersistableBundle_size,
- APersistableBundle_writeToParcel,
+ APersistableBundle_writeToParcel, APERSISTABLEBUNDLE_KEY_NOT_FOUND,
};
-use std::ffi::{CString, NulError};
+use std::ffi::{c_char, CString, NulError};
use std::ptr::{null_mut, NonNull};
/// A mapping from string keys to values of various types.
@@ -373,6 +374,104 @@
}
}
+ /// Gets the vector of `T` associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ ///
+ /// `get_func` should be one of the `APersistableBundle_get*Vector` functions from
+ /// `binder_ndk_sys`.
+ ///
+ /// # Safety
+ ///
+ /// `get_func` must only require that the pointers it takes are valid for the duration of the
+ /// call. It must allow a null pointer for the buffer, and must return the size in bytes of
+ /// buffer it requires. If it is given a non-null buffer pointer it must write that number of
+ /// bytes to the buffer, which must be a whole number of valid `T` values.
+ unsafe fn get_vec<T: Clone + Default>(
+ &self,
+ key: &str,
+ get_func: unsafe extern "C" fn(
+ *const APersistableBundle,
+ *const c_char,
+ *mut T,
+ i32,
+ ) -> i32,
+ ) -> Result<Option<Vec<T>>, NulError> {
+ let key = CString::new(key)?;
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
+ // lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()` is guaranteed
+ // to be valid for the lifetime of `key`. A null pointer is allowed for the buffer.
+ match unsafe { get_func(self.0.as_ptr(), key.as_ptr(), null_mut(), 0) } {
+ APERSISTABLEBUNDLE_KEY_NOT_FOUND => Ok(None),
+ required_buffer_size => {
+ let mut value = vec![
+ T::default();
+ usize::try_from(required_buffer_size).expect(
+ "APersistableBundle_get*Vector returned invalid size"
+ ) / size_of::<T>()
+ ];
+ // SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for
+ // the lifetime of the `PersistableBundle`. The pointer returned by `key.as_ptr()`
+ // is guaranteed to be valid for the lifetime of `key`. The value buffer pointer is
+ // valid as it comes from the Vec we just allocated.
+ match unsafe {
+ get_func(
+ self.0.as_ptr(),
+ key.as_ptr(),
+ value.as_mut_ptr(),
+ (value.len() * size_of::<T>()).try_into().unwrap(),
+ )
+ } {
+ APERSISTABLEBUNDLE_KEY_NOT_FOUND => {
+ panic!("APersistableBundle_get*Vector failed to find key after first finding it");
+ }
+ _ => Ok(Some(value)),
+ }
+ }
+ }
+ }
+
+ /// Gets the boolean vector value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_bool_vec(&self, key: &str) -> Result<Option<Vec<bool>>, NulError> {
+ // SAFETY: APersistableBundle_getBooleanVector fulfils all the safety requirements of
+ // `get_vec`.
+ unsafe { self.get_vec(key, APersistableBundle_getBooleanVector) }
+ }
+
+ /// Gets the i32 vector value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_int_vec(&self, key: &str) -> Result<Option<Vec<i32>>, NulError> {
+ // SAFETY: APersistableBundle_getIntVector fulfils all the safety requirements of
+ // `get_vec`.
+ unsafe { self.get_vec(key, APersistableBundle_getIntVector) }
+ }
+
+ /// Gets the i64 vector value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_long_vec(&self, key: &str) -> Result<Option<Vec<i64>>, NulError> {
+ // SAFETY: APersistableBundle_getLongVector fulfils all the safety requirements of
+ // `get_vec`.
+ unsafe { self.get_vec(key, APersistableBundle_getLongVector) }
+ }
+
+ /// Gets the f64 vector value associated with the given key.
+ ///
+ /// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
+ /// in the bundle.
+ pub fn get_double_vec(&self, key: &str) -> Result<Option<Vec<f64>>, NulError> {
+ // SAFETY: APersistableBundle_getDoubleVector fulfils all the safety requirements of
+ // `get_vec`.
+ unsafe { self.get_vec(key, APersistableBundle_getDoubleVector) }
+ }
+
/// Gets the `PersistableBundle` value associated with the given key.
///
/// Returns an error if the key contains a NUL character, or `Ok(None)` if the key doesn't exist
@@ -486,6 +585,10 @@
assert_eq!(bundle.get_int("foo"), Ok(None));
assert_eq!(bundle.get_long("foo"), Ok(None));
assert_eq!(bundle.get_double("foo"), Ok(None));
+ assert_eq!(bundle.get_bool_vec("foo"), Ok(None));
+ assert_eq!(bundle.get_int_vec("foo"), Ok(None));
+ assert_eq!(bundle.get_long_vec("foo"), Ok(None));
+ assert_eq!(bundle.get_double_vec("foo"), Ok(None));
}
#[test]
@@ -543,7 +646,7 @@
}
#[test]
- fn insert_vec() {
+ fn insert_get_vec() {
let mut bundle = PersistableBundle::new();
assert_eq!(bundle.insert_bool_vec("bool", &[]), Ok(()));
@@ -567,6 +670,11 @@
);
assert_eq!(bundle.size(), 5);
+
+ assert_eq!(bundle.get_bool_vec("bool"), Ok(Some(vec![])));
+ assert_eq!(bundle.get_int_vec("int"), Ok(Some(vec![42])));
+ assert_eq!(bundle.get_long_vec("long"), Ok(Some(vec![66, 67, 68])));
+ assert_eq!(bundle.get_double_vec("double"), Ok(Some(vec![123.4])));
}
#[test]
diff --git a/libs/binder/rust/sys/BinderBindings.hpp b/libs/binder/rust/sys/BinderBindings.hpp
index deeaa37..c19e375 100644
--- a/libs/binder/rust/sys/BinderBindings.hpp
+++ b/libs/binder/rust/sys/BinderBindings.hpp
@@ -92,6 +92,11 @@
#endif
};
+enum {
+ APERSISTABLEBUNDLE_KEY_NOT_FOUND = APERSISTABLEBUNDLE_KEY_NOT_FOUND,
+ APERSISTABLEBUNDLE_ALLOCATOR_FAILED = APERSISTABLEBUNDLE_ALLOCATOR_FAILED,
+};
+
} // namespace consts
} // namespace c_interface