Skip to content

Commit e200cb1

Browse files
committed
Add methods to get keys.
Bug: 389074518 Test: atest libbinder_rs-internal_test Change-Id: Ifc7cd6cd519cda1ce63d0242df4d56d47ac86bab
1 parent 412d19a commit e200cb1

2 files changed

Lines changed: 233 additions & 6 deletions

File tree

libs/binder/rust/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ pub use binder::{BinderFeatures, FromIBinder, IBinder, Interface, Strong, Weak};
116116
pub use error::{ExceptionCode, IntoBinderResult, Status, StatusCode};
117117
pub use parcel::{ParcelFileDescriptor, Parcelable, ParcelableHolder};
118118
#[cfg(not(trusty))]
119-
pub use persistable_bundle::PersistableBundle;
119+
pub use persistable_bundle::{PersistableBundle, ValueType};
120120
pub use proxy::{DeathRecipient, SpIBinder, WpIBinder};
121121
#[cfg(not(any(trusty, android_ndk)))]
122122
pub use service::{

libs/binder/rust/src/persistable_bundle.rs

Lines changed: 232 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,17 @@ use crate::{
2222
};
2323
use binder_ndk_sys::{
2424
APersistableBundle, APersistableBundle_delete, APersistableBundle_dup,
25-
APersistableBundle_erase, APersistableBundle_getBoolean, APersistableBundle_getBooleanVector,
26-
APersistableBundle_getDouble, APersistableBundle_getDoubleVector, APersistableBundle_getInt,
27-
APersistableBundle_getIntVector, APersistableBundle_getLong, APersistableBundle_getLongVector,
28-
APersistableBundle_getPersistableBundle, APersistableBundle_getString,
29-
APersistableBundle_getStringVector, APersistableBundle_isEqual, APersistableBundle_new,
25+
APersistableBundle_erase, APersistableBundle_getBoolean, APersistableBundle_getBooleanKeys,
26+
APersistableBundle_getBooleanVector, APersistableBundle_getBooleanVectorKeys,
27+
APersistableBundle_getDouble, APersistableBundle_getDoubleKeys,
28+
APersistableBundle_getDoubleVector, APersistableBundle_getDoubleVectorKeys,
29+
APersistableBundle_getInt, APersistableBundle_getIntKeys, APersistableBundle_getIntVector,
30+
APersistableBundle_getIntVectorKeys, APersistableBundle_getLong,
31+
APersistableBundle_getLongKeys, APersistableBundle_getLongVector,
32+
APersistableBundle_getLongVectorKeys, APersistableBundle_getPersistableBundle,
33+
APersistableBundle_getPersistableBundleKeys, APersistableBundle_getString,
34+
APersistableBundle_getStringKeys, APersistableBundle_getStringVector,
35+
APersistableBundle_getStringVectorKeys, APersistableBundle_isEqual, APersistableBundle_new,
3036
APersistableBundle_putBoolean, APersistableBundle_putBooleanVector,
3137
APersistableBundle_putDouble, APersistableBundle_putDoubleVector, APersistableBundle_putInt,
3238
APersistableBundle_putIntVector, APersistableBundle_putLong, APersistableBundle_putLongVector,
@@ -588,6 +594,171 @@ impl PersistableBundle {
588594
Ok(None)
589595
}
590596
}
597+
598+
/// Calls the appropriate `APersistableBundle_get*Keys` function for the given `value_type`,
599+
/// with our `string_allocator` and a null context pointer.
600+
///
601+
/// # Safety
602+
///
603+
/// `out_keys` must either be null or point to a buffer of at least `buffer_size_bytes` bytes,
604+
/// properly aligned for `T`, and not otherwise accessed for the duration of the call.
605+
unsafe fn get_keys_raw(
606+
&self,
607+
value_type: ValueType,
608+
out_keys: *mut *mut c_char,
609+
buffer_size_bytes: i32,
610+
) -> i32 {
611+
// SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for the
612+
// lifetime of the `PersistableBundle`. Our caller guarantees an appropriate value for
613+
// `out_keys` and `buffer_size_bytes`.
614+
unsafe {
615+
match value_type {
616+
ValueType::Boolean => APersistableBundle_getBooleanKeys(
617+
self.0.as_ptr(),
618+
out_keys,
619+
buffer_size_bytes,
620+
Some(string_allocator),
621+
null_mut(),
622+
),
623+
ValueType::Integer => APersistableBundle_getIntKeys(
624+
self.0.as_ptr(),
625+
out_keys,
626+
buffer_size_bytes,
627+
Some(string_allocator),
628+
null_mut(),
629+
),
630+
ValueType::Long => APersistableBundle_getLongKeys(
631+
self.0.as_ptr(),
632+
out_keys,
633+
buffer_size_bytes,
634+
Some(string_allocator),
635+
null_mut(),
636+
),
637+
ValueType::Double => APersistableBundle_getDoubleKeys(
638+
self.0.as_ptr(),
639+
out_keys,
640+
buffer_size_bytes,
641+
Some(string_allocator),
642+
null_mut(),
643+
),
644+
ValueType::String => APersistableBundle_getStringKeys(
645+
self.0.as_ptr(),
646+
out_keys,
647+
buffer_size_bytes,
648+
Some(string_allocator),
649+
null_mut(),
650+
),
651+
ValueType::BooleanVector => APersistableBundle_getBooleanVectorKeys(
652+
self.0.as_ptr(),
653+
out_keys,
654+
buffer_size_bytes,
655+
Some(string_allocator),
656+
null_mut(),
657+
),
658+
ValueType::IntegerVector => APersistableBundle_getIntVectorKeys(
659+
self.0.as_ptr(),
660+
out_keys,
661+
buffer_size_bytes,
662+
Some(string_allocator),
663+
null_mut(),
664+
),
665+
ValueType::LongVector => APersistableBundle_getLongVectorKeys(
666+
self.0.as_ptr(),
667+
out_keys,
668+
buffer_size_bytes,
669+
Some(string_allocator),
670+
null_mut(),
671+
),
672+
ValueType::DoubleVector => APersistableBundle_getDoubleVectorKeys(
673+
self.0.as_ptr(),
674+
out_keys,
675+
buffer_size_bytes,
676+
Some(string_allocator),
677+
null_mut(),
678+
),
679+
ValueType::StringVector => APersistableBundle_getStringVectorKeys(
680+
self.0.as_ptr(),
681+
out_keys,
682+
buffer_size_bytes,
683+
Some(string_allocator),
684+
null_mut(),
685+
),
686+
ValueType::PersistableBundle => APersistableBundle_getPersistableBundleKeys(
687+
self.0.as_ptr(),
688+
out_keys,
689+
buffer_size_bytes,
690+
Some(string_allocator),
691+
null_mut(),
692+
),
693+
}
694+
}
695+
}
696+
697+
/// Gets all the keys associated with values of the given type.
698+
pub fn keys_for_type(&self, value_type: ValueType) -> Vec<String> {
699+
// SAFETY: A null pointer is allowed for the buffer.
700+
match unsafe { self.get_keys_raw(value_type, null_mut(), 0) } {
701+
APERSISTABLEBUNDLE_ALLOCATOR_FAILED => {
702+
panic!("APersistableBundle_get*Keys failed to allocate string");
703+
}
704+
required_buffer_size => {
705+
let required_buffer_size_usize = usize::try_from(required_buffer_size)
706+
.expect("APersistableBundle_get*Keys returned invalid size");
707+
assert_eq!(required_buffer_size_usize % size_of::<*mut c_char>(), 0);
708+
let mut keys =
709+
vec![null_mut(); required_buffer_size_usize / size_of::<*mut c_char>()];
710+
// SAFETY: The wrapped `APersistableBundle` pointer is guaranteed to be valid for
711+
// the lifetime of the `PersistableBundle`. The keys buffer pointer is valid as it
712+
// comes from the Vec we just allocated.
713+
if unsafe { self.get_keys_raw(value_type, keys.as_mut_ptr(), required_buffer_size) }
714+
== APERSISTABLEBUNDLE_ALLOCATOR_FAILED
715+
{
716+
panic!("APersistableBundle_get*Keys failed to allocate string");
717+
}
718+
keys.into_iter()
719+
.map(|key| {
720+
// SAFETY: The pointer was returned from `string_allocator`, which used
721+
// `Box::into_raw`, and `APersistableBundle_getStringVector` should have
722+
// written valid bytes to it including a NUL terminator in the last
723+
// position.
724+
let string_length = unsafe { CStr::from_ptr(key) }.count_bytes();
725+
let raw_slice = slice_from_raw_parts_mut(key.cast(), string_length + 1);
726+
// SAFETY: The pointer was returned from `string_allocator`, which used
727+
// `Box::into_raw`, and we've got the appropriate size back by checking the
728+
// length of the string.
729+
let boxed_slice: Box<[u8]> = unsafe { Box::from_raw(raw_slice) };
730+
let c_string = CString::from_vec_with_nul(boxed_slice.into())
731+
.expect("APersistableBundle_get*Keys returned string missing NUL byte");
732+
c_string
733+
.into_string()
734+
.expect("APersistableBundle_get*Keys returned invalid UTF-8")
735+
})
736+
.collect()
737+
}
738+
}
739+
}
740+
741+
/// Returns an iterator over all keys in the bundle, along with the type of their associated
742+
/// value.
743+
pub fn keys(&self) -> impl Iterator<Item = (String, ValueType)> + use<'_> {
744+
[
745+
ValueType::Boolean,
746+
ValueType::Integer,
747+
ValueType::Long,
748+
ValueType::Double,
749+
ValueType::String,
750+
ValueType::BooleanVector,
751+
ValueType::IntegerVector,
752+
ValueType::LongVector,
753+
ValueType::DoubleVector,
754+
ValueType::StringVector,
755+
ValueType::PersistableBundle,
756+
]
757+
.iter()
758+
.flat_map(|value_type| {
759+
self.keys_for_type(*value_type).into_iter().map(|key| (key, *value_type))
760+
})
761+
}
591762
}
592763

593764
/// Wrapper around `APersistableBundle_getStringVector` to pass `string_allocator` and a null
@@ -709,6 +880,33 @@ unsafe extern "C" fn string_allocator(size: i32, context: *mut c_void) -> *mut c
709880
impl_deserialize_for_unstructured_parcelable!(PersistableBundle);
710881
impl_serialize_for_unstructured_parcelable!(PersistableBundle);
711882

883+
/// The types which may be stored as values in a [`PersistableBundle`].
884+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
885+
pub enum ValueType {
886+
/// A `bool`.
887+
Boolean,
888+
/// An `i32`.
889+
Integer,
890+
/// An `i64`.
891+
Long,
892+
/// An `f64`.
893+
Double,
894+
/// A string.
895+
String,
896+
/// A vector of `bool`s.
897+
BooleanVector,
898+
/// A vector of `i32`s.
899+
IntegerVector,
900+
/// A vector of `i64`s.
901+
LongVector,
902+
/// A vector of `f64`s.
903+
DoubleVector,
904+
/// A vector of strings.
905+
StringVector,
906+
/// A nested `PersistableBundle`.
907+
PersistableBundle,
908+
}
909+
712910
#[cfg(test)]
713911
mod test {
714912
use super::*;
@@ -846,4 +1044,33 @@ mod test {
8461044

8471045
assert_eq!(bundle.get_persistable_bundle("bundle"), Ok(Some(sub_bundle)));
8481046
}
1047+
1048+
#[test]
1049+
fn get_keys() {
1050+
let mut bundle = PersistableBundle::new();
1051+
1052+
assert_eq!(bundle.keys_for_type(ValueType::Boolean), Vec::<String>::new());
1053+
assert_eq!(bundle.keys_for_type(ValueType::Integer), Vec::<String>::new());
1054+
assert_eq!(bundle.keys_for_type(ValueType::StringVector), Vec::<String>::new());
1055+
1056+
assert_eq!(bundle.insert_bool("bool1", false), Ok(()));
1057+
assert_eq!(bundle.insert_bool("bool2", true), Ok(()));
1058+
assert_eq!(bundle.insert_int("int", 42), Ok(()));
1059+
1060+
assert_eq!(
1061+
bundle.keys_for_type(ValueType::Boolean),
1062+
vec!["bool1".to_string(), "bool2".to_string()]
1063+
);
1064+
assert_eq!(bundle.keys_for_type(ValueType::Integer), vec!["int".to_string()]);
1065+
assert_eq!(bundle.keys_for_type(ValueType::StringVector), Vec::<String>::new());
1066+
1067+
assert_eq!(
1068+
bundle.keys().collect::<Vec<_>>(),
1069+
vec![
1070+
("bool1".to_string(), ValueType::Boolean),
1071+
("bool2".to_string(), ValueType::Boolean),
1072+
("int".to_string(), ValueType::Integer),
1073+
]
1074+
);
1075+
}
8491076
}

0 commit comments

Comments
 (0)