Loading libs/binder/rust/src/binder.rs +145 −13 Original line number Diff line number Diff line Loading @@ -16,12 +16,17 @@ //! Trait definitions for binder objects use crate::error::{status_t, Result}; use crate::error::{status_t, Result, StatusCode}; use crate::parcel::Parcel; use crate::proxy::{DeathRecipient, SpIBinder}; use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder}; use crate::sys; use std::borrow::Borrow; use std::cmp::Ordering; use std::ffi::{c_void, CStr, CString}; use std::fmt; use std::marker::PhantomData; use std::ops::Deref; use std::os::raw::c_char; use std::os::unix::io::AsRawFd; use std::ptr; Loading @@ -44,7 +49,7 @@ pub type TransactionFlags = u32; /// interfaces) must implement this trait. /// /// This is equivalent `IInterface` in C++. pub trait Interface { pub trait Interface: Send { /// Convert this binder object into a generic [`SpIBinder`] reference. fn as_binder(&self) -> SpIBinder { panic!("This object was not a Binder object and cannot be converted into an SpIBinder.") Loading Loading @@ -230,6 +235,132 @@ impl From<InterfaceClass> for *const sys::AIBinder_Class { } } /// Strong reference to a binder object pub struct Strong<I: FromIBinder + ?Sized>(Box<I>); impl<I: FromIBinder + ?Sized> Strong<I> { /// Create a new strong reference to the provided binder object pub fn new(binder: Box<I>) -> Self { Self(binder) } /// Construct a new weak reference to this binder pub fn downgrade(this: &Strong<I>) -> Weak<I> { Weak::new(this) } } impl<I: FromIBinder + ?Sized> Clone for Strong<I> { fn clone(&self) -> Self { // Since we hold a strong reference, we should always be able to create // a new strong reference to the same interface type, so try_from() // should never fail here. FromIBinder::try_from(self.0.as_binder()).unwrap() } } impl<I: FromIBinder + ?Sized> Borrow<I> for Strong<I> { fn borrow(&self) -> &I { &self.0 } } impl<I: FromIBinder + ?Sized> AsRef<I> for Strong<I> { fn as_ref(&self) -> &I { &self.0 } } impl<I: FromIBinder + ?Sized> Deref for Strong<I> { type Target = I; fn deref(&self) -> &Self::Target { &self.0 } } impl<I: FromIBinder + fmt::Debug + ?Sized> fmt::Debug for Strong<I> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } impl<I: FromIBinder + ?Sized> Ord for Strong<I> { fn cmp(&self, other: &Self) -> Ordering { self.0.as_binder().cmp(&other.0.as_binder()) } } impl<I: FromIBinder + ?Sized> PartialOrd for Strong<I> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { self.0.as_binder().partial_cmp(&other.0.as_binder()) } } impl<I: FromIBinder + ?Sized> PartialEq for Strong<I> { fn eq(&self, other: &Self) -> bool { self.0.as_binder().eq(&other.0.as_binder()) } } impl<I: FromIBinder + ?Sized> Eq for Strong<I> {} /// Weak reference to a binder object #[derive(Debug)] pub struct Weak<I: FromIBinder + ?Sized> { weak_binder: WpIBinder, interface_type: PhantomData<I>, } impl<I: FromIBinder + ?Sized> Weak<I> { /// Construct a new weak reference from a strong reference fn new(binder: &Strong<I>) -> Self { let weak_binder = binder.as_binder().downgrade(); Weak { weak_binder, interface_type: PhantomData, } } /// Upgrade this weak reference to a strong reference if the binder object /// is still alive pub fn upgrade(&self) -> Result<Strong<I>> { self.weak_binder .promote() .ok_or(StatusCode::DEAD_OBJECT) .and_then(FromIBinder::try_from) } } impl<I: FromIBinder + ?Sized> Clone for Weak<I> { fn clone(&self) -> Self { Self { weak_binder: self.weak_binder.clone(), interface_type: PhantomData, } } } impl<I: FromIBinder + ?Sized> Ord for Weak<I> { fn cmp(&self, other: &Self) -> Ordering { self.weak_binder.cmp(&other.weak_binder) } } impl<I: FromIBinder + ?Sized> PartialOrd for Weak<I> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { self.weak_binder.partial_cmp(&other.weak_binder) } } impl<I: FromIBinder + ?Sized> PartialEq for Weak<I> { fn eq(&self, other: &Self) -> bool { self.weak_binder == other.weak_binder } } impl<I: FromIBinder + ?Sized> Eq for Weak<I> {} /// Create a function implementing a static getter for an interface class. /// /// Each binder interface (i.e. local [`Remotable`] service or remote proxy Loading Loading @@ -354,12 +485,12 @@ pub trait InterfaceClassMethods { /// } /// } /// ``` pub trait FromIBinder { pub trait FromIBinder: Interface { /// Try to interpret a generic Binder object as this interface. /// /// Returns a trait object for the `Self` interface if this object /// implements that interface. fn try_from(ibinder: SpIBinder) -> Result<Box<Self>>; fn try_from(ibinder: SpIBinder) -> Result<Strong<Self>>; } /// Trait for transparent Rust wrappers around android C++ native types. Loading Loading @@ -534,8 +665,9 @@ macro_rules! declare_binder_interface { impl $native { /// Create a new binder service. pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T) -> impl $interface { $crate::Binder::new($native(Box::new(inner))) pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T) -> $crate::Strong<dyn $interface> { let binder = $crate::Binder::new($native(Box::new(inner))); $crate::Strong::new(Box::new(binder)) } } Loading Loading @@ -577,7 +709,7 @@ macro_rules! declare_binder_interface { } impl $crate::FromIBinder for dyn $interface { fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<Box<dyn $interface>> { fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<$crate::Strong<dyn $interface>> { use $crate::AssociateClass; let existing_class = ibinder.get_class(); Loading @@ -590,7 +722,7 @@ macro_rules! declare_binder_interface { // associated object as remote, because we can't cast it // into a Rust service object without a matching class // pointer. return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)); return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?))); } } Loading @@ -600,10 +732,10 @@ macro_rules! declare_binder_interface { if let Ok(service) = service { // We were able to associate with our expected class and // the service is local. return Ok(Box::new(service)); return Ok($crate::Strong::new(Box::new(service))); } else { // Service is remote return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)); return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?))); } } Loading Loading @@ -633,9 +765,9 @@ macro_rules! declare_binder_interface { } } // Convert a &dyn $interface to Box<dyn $interface> /// Convert a &dyn $interface to Strong<dyn $interface> impl std::borrow::ToOwned for dyn $interface { type Owned = Box<dyn $interface>; type Owned = $crate::Strong<dyn $interface>; fn to_owned(&self) -> Self::Owned { self.as_binder().into_interface() .expect(concat!("Error cloning interface ", stringify!($interface))) Loading libs/binder/rust/src/lib.rs +4 −2 Original line number Diff line number Diff line Loading @@ -107,7 +107,8 @@ use binder_ndk_sys as sys; pub mod parcel; pub use crate::binder::{ FromIBinder, IBinder, Interface, InterfaceClass, Remotable, TransactionCode, TransactionFlags, FromIBinder, IBinder, Interface, InterfaceClass, Remotable, Strong, TransactionCode, TransactionFlags, Weak, }; pub use error::{status_t, ExceptionCode, Result, Status, StatusCode}; pub use native::add_service; Loading @@ -122,7 +123,8 @@ pub mod public_api { pub use super::parcel::ParcelFileDescriptor; pub use super::{add_service, get_interface}; pub use super::{ ExceptionCode, Interface, ProcessState, SpIBinder, Status, StatusCode, WpIBinder, ExceptionCode, Interface, ProcessState, SpIBinder, Status, StatusCode, Strong, ThreadState, Weak, WpIBinder, }; /// Binder result containing a [`Status`] on error. Loading libs/binder/rust/src/parcel/parcelable.rs +5 −5 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ * limitations under the License. */ use crate::binder::{AsNative, FromIBinder}; use crate::binder::{AsNative, FromIBinder, Strong}; use crate::error::{status_result, status_t, Result, Status, StatusCode}; use crate::parcel::Parcel; use crate::proxy::SpIBinder; Loading Loading @@ -628,26 +628,26 @@ impl Deserialize for Status { } } impl<T: Serialize + ?Sized> Serialize for Box<T> { impl<T: Serialize + FromIBinder + ?Sized> Serialize for Strong<T> { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { Serialize::serialize(&**self, parcel) } } impl<T: SerializeOption + ?Sized> SerializeOption for Box<T> { impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> { fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { SerializeOption::serialize_option(this.map(|b| &**b), parcel) } } impl<T: FromIBinder + ?Sized> Deserialize for Box<T> { impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> { fn deserialize(parcel: &Parcel) -> Result<Self> { let ibinder: SpIBinder = parcel.read()?; FromIBinder::try_from(ibinder) } } impl<T: FromIBinder + ?Sized> DeserializeOption for Box<T> { impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> { fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> { let ibinder: Option<SpIBinder> = parcel.read()?; ibinder.map(FromIBinder::try_from).transpose() Loading libs/binder/rust/src/proxy.rs +92 −5 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ //! Rust API for interacting with a remote binder service. use crate::binder::{ AsNative, FromIBinder, IBinder, Interface, InterfaceClass, TransactionCode, TransactionFlags, AsNative, FromIBinder, IBinder, Interface, InterfaceClass, Strong, TransactionCode, TransactionFlags, }; use crate::error::{status_result, Result, StatusCode}; use crate::parcel::{ Loading @@ -27,6 +27,7 @@ use crate::parcel::{ use crate::sys; use std::convert::TryInto; use std::cmp::Ordering; use std::ffi::{c_void, CString}; use std::fmt; use std::os::unix::io::AsRawFd; Loading Loading @@ -99,7 +100,7 @@ impl SpIBinder { /// /// If this object does not implement the expected interface, the error /// `StatusCode::BAD_TYPE` is returned. pub fn into_interface<I: FromIBinder + ?Sized>(self) -> Result<Box<I>> { pub fn into_interface<I: FromIBinder + Interface + ?Sized>(self) -> Result<Strong<I>> { FromIBinder::try_from(self) } Loading Loading @@ -148,6 +149,36 @@ impl AssociateClass for SpIBinder { } } impl Ord for SpIBinder { fn cmp(&self, other: &Self) -> Ordering { let less_than = unsafe { // Safety: SpIBinder always holds a valid `AIBinder` pointer, so // this pointer is always safe to pass to `AIBinder_lt` (null is // also safe to pass to this function, but we should never do that). sys::AIBinder_lt(self.0, other.0) }; let greater_than = unsafe { // Safety: SpIBinder always holds a valid `AIBinder` pointer, so // this pointer is always safe to pass to `AIBinder_lt` (null is // also safe to pass to this function, but we should never do that). sys::AIBinder_lt(other.0, self.0) }; if !less_than && !greater_than { Ordering::Equal } else if less_than { Ordering::Less } else { Ordering::Greater } } } impl PartialOrd for SpIBinder { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) } } impl PartialEq for SpIBinder { fn eq(&self, other: &Self) -> bool { ptr::eq(self.0, other.0) Loading Loading @@ -326,7 +357,7 @@ impl<T: AsNative<sys::AIBinder>> IBinder for T { // Safety: `SpIBinder` guarantees that `self` always contains a // valid pointer to an `AIBinder`. `recipient` can always be // converted into a valid pointer to an // `AIBinder_DeatRecipient`. Any value is safe to pass as the // `AIBinder_DeathRecipient`. Any value is safe to pass as the // cookie, although we depend on this value being set by // `get_cookie` when the death recipient callback is called. sys::AIBinder_linkToDeath( Loading @@ -342,7 +373,7 @@ impl<T: AsNative<sys::AIBinder>> IBinder for T { // Safety: `SpIBinder` guarantees that `self` always contains a // valid pointer to an `AIBinder`. `recipient` can always be // converted into a valid pointer to an // `AIBinder_DeatRecipient`. Any value is safe to pass as the // `AIBinder_DeathRecipient`. Any value is safe to pass as the // cookie, although we depend on this value being set by // `get_cookie` when the death recipient callback is called. sys::AIBinder_unlinkToDeath( Loading Loading @@ -430,6 +461,62 @@ impl WpIBinder { } } impl Clone for WpIBinder { fn clone(&self) -> Self { let ptr = unsafe { // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, // so this pointer is always safe to pass to `AIBinder_Weak_clone` // (although null is also a safe value to pass to this API). // // We get ownership of the returned pointer, so can construct a new // WpIBinder object from it. sys::AIBinder_Weak_clone(self.0) }; assert!(!ptr.is_null(), "Unexpected null pointer from AIBinder_Weak_clone"); Self(ptr) } } impl Ord for WpIBinder { fn cmp(&self, other: &Self) -> Ordering { let less_than = unsafe { // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, // so this pointer is always safe to pass to `AIBinder_Weak_lt` // (null is also safe to pass to this function, but we should never // do that). sys::AIBinder_Weak_lt(self.0, other.0) }; let greater_than = unsafe { // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, // so this pointer is always safe to pass to `AIBinder_Weak_lt` // (null is also safe to pass to this function, but we should never // do that). sys::AIBinder_Weak_lt(other.0, self.0) }; if !less_than && !greater_than { Ordering::Equal } else if less_than { Ordering::Less } else { Ordering::Greater } } } impl PartialOrd for WpIBinder { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) } } impl PartialEq for WpIBinder { fn eq(&self, other: &Self) -> bool { self.cmp(other) == Ordering::Equal } } impl Eq for WpIBinder {} impl Drop for WpIBinder { fn drop(&mut self) { unsafe { Loading Loading @@ -564,7 +651,7 @@ pub fn get_service(name: &str) -> Option<SpIBinder> { /// Retrieve an existing service for a particular interface, blocking for a few /// seconds if it doesn't yet exist. pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Box<T>> { pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> { let service = get_service(name); match service { Some(service) => FromIBinder::try_from(service), Loading libs/binder/rust/tests/integration.rs +57 −6 Original line number Diff line number Diff line Loading @@ -209,7 +209,7 @@ mod tests { use std::thread; use std::time::Duration; use binder::{Binder, DeathRecipient, FromIBinder, IBinder, Interface, SpIBinder, StatusCode}; use binder::{Binder, DeathRecipient, FromIBinder, IBinder, Interface, SpIBinder, StatusCode, Strong}; use super::{BnTest, ITest, ITestSameDescriptor, RUST_SERVICE_BINARY, TestService}; Loading Loading @@ -271,7 +271,7 @@ mod tests { fn trivial_client() { let service_name = "trivial_client_test"; let _process = ScopedServiceProcess::new(service_name); let test_client: Box<dyn ITest> = let test_client: Strong<dyn ITest> = binder::get_interface(service_name).expect("Did not get manager binder service"); assert_eq!(test_client.test().unwrap(), "trivial_client_test"); } Loading @@ -280,7 +280,7 @@ mod tests { fn get_selinux_context() { let service_name = "get_selinux_context"; let _process = ScopedServiceProcess::new(service_name); let test_client: Box<dyn ITest> = let test_client: Strong<dyn ITest> = binder::get_interface(service_name).expect("Did not get manager binder service"); let expected_context = unsafe { let mut out_ptr = ptr::null_mut(); Loading Loading @@ -453,7 +453,7 @@ mod tests { let extension = maybe_extension.expect("Remote binder did not have an extension"); let extension: Box<dyn ITest> = FromIBinder::try_from(extension) let extension: Strong<dyn ITest> = FromIBinder::try_from(extension) .expect("Extension could not be converted to the expected interface"); assert_eq!(extension.test().unwrap(), extension_name); Loading @@ -479,7 +479,7 @@ mod tests { // This should succeed although we will have to treat the service as // remote. let _interface: Box<dyn ITestSameDescriptor> = FromIBinder::try_from(service.as_binder()) let _interface: Strong<dyn ITestSameDescriptor> = FromIBinder::try_from(service.as_binder()) .expect("Could not re-interpret service as the ITestSameDescriptor interface"); } Loading @@ -490,9 +490,60 @@ mod tests { let service_ibinder = BnTest::new_binder(TestService { s: service_name.to_string() }) .as_binder(); let service: Box<dyn ITest> = service_ibinder.into_interface() let service: Strong<dyn ITest> = service_ibinder.into_interface() .expect("Could not reassociate the generic ibinder"); assert_eq!(service.test().unwrap(), service_name); } #[test] fn weak_binder_upgrade() { let service_name = "testing_service"; let service = BnTest::new_binder(TestService { s: service_name.to_string() }); let weak = Strong::downgrade(&service); let upgraded = weak.upgrade().expect("Could not upgrade weak binder"); assert_eq!(service, upgraded); } #[test] fn weak_binder_upgrade_dead() { let service_name = "testing_service"; let weak = { let service = BnTest::new_binder(TestService { s: service_name.to_string() }); Strong::downgrade(&service) }; assert_eq!(weak.upgrade(), Err(StatusCode::DEAD_OBJECT)); } #[test] fn weak_binder_clone() { let service_name = "testing_service"; let service = BnTest::new_binder(TestService { s: service_name.to_string() }); let weak = Strong::downgrade(&service); let cloned = weak.clone(); assert_eq!(weak, cloned); let upgraded = weak.upgrade().expect("Could not upgrade weak binder"); let clone_upgraded = cloned.upgrade().expect("Could not upgrade weak binder"); assert_eq!(service, upgraded); assert_eq!(service, clone_upgraded); } #[test] #[allow(clippy::eq_op)] fn binder_ord() { let service1 = BnTest::new_binder(TestService { s: "testing_service1".to_string() }); let service2 = BnTest::new_binder(TestService { s: "testing_service2".to_string() }); assert!(!(service1 < service1)); assert!(!(service1 > service1)); assert_eq!(service1 < service2, !(service2 < service1)); } } Loading
libs/binder/rust/src/binder.rs +145 −13 Original line number Diff line number Diff line Loading @@ -16,12 +16,17 @@ //! Trait definitions for binder objects use crate::error::{status_t, Result}; use crate::error::{status_t, Result, StatusCode}; use crate::parcel::Parcel; use crate::proxy::{DeathRecipient, SpIBinder}; use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder}; use crate::sys; use std::borrow::Borrow; use std::cmp::Ordering; use std::ffi::{c_void, CStr, CString}; use std::fmt; use std::marker::PhantomData; use std::ops::Deref; use std::os::raw::c_char; use std::os::unix::io::AsRawFd; use std::ptr; Loading @@ -44,7 +49,7 @@ pub type TransactionFlags = u32; /// interfaces) must implement this trait. /// /// This is equivalent `IInterface` in C++. pub trait Interface { pub trait Interface: Send { /// Convert this binder object into a generic [`SpIBinder`] reference. fn as_binder(&self) -> SpIBinder { panic!("This object was not a Binder object and cannot be converted into an SpIBinder.") Loading Loading @@ -230,6 +235,132 @@ impl From<InterfaceClass> for *const sys::AIBinder_Class { } } /// Strong reference to a binder object pub struct Strong<I: FromIBinder + ?Sized>(Box<I>); impl<I: FromIBinder + ?Sized> Strong<I> { /// Create a new strong reference to the provided binder object pub fn new(binder: Box<I>) -> Self { Self(binder) } /// Construct a new weak reference to this binder pub fn downgrade(this: &Strong<I>) -> Weak<I> { Weak::new(this) } } impl<I: FromIBinder + ?Sized> Clone for Strong<I> { fn clone(&self) -> Self { // Since we hold a strong reference, we should always be able to create // a new strong reference to the same interface type, so try_from() // should never fail here. FromIBinder::try_from(self.0.as_binder()).unwrap() } } impl<I: FromIBinder + ?Sized> Borrow<I> for Strong<I> { fn borrow(&self) -> &I { &self.0 } } impl<I: FromIBinder + ?Sized> AsRef<I> for Strong<I> { fn as_ref(&self) -> &I { &self.0 } } impl<I: FromIBinder + ?Sized> Deref for Strong<I> { type Target = I; fn deref(&self) -> &Self::Target { &self.0 } } impl<I: FromIBinder + fmt::Debug + ?Sized> fmt::Debug for Strong<I> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } impl<I: FromIBinder + ?Sized> Ord for Strong<I> { fn cmp(&self, other: &Self) -> Ordering { self.0.as_binder().cmp(&other.0.as_binder()) } } impl<I: FromIBinder + ?Sized> PartialOrd for Strong<I> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { self.0.as_binder().partial_cmp(&other.0.as_binder()) } } impl<I: FromIBinder + ?Sized> PartialEq for Strong<I> { fn eq(&self, other: &Self) -> bool { self.0.as_binder().eq(&other.0.as_binder()) } } impl<I: FromIBinder + ?Sized> Eq for Strong<I> {} /// Weak reference to a binder object #[derive(Debug)] pub struct Weak<I: FromIBinder + ?Sized> { weak_binder: WpIBinder, interface_type: PhantomData<I>, } impl<I: FromIBinder + ?Sized> Weak<I> { /// Construct a new weak reference from a strong reference fn new(binder: &Strong<I>) -> Self { let weak_binder = binder.as_binder().downgrade(); Weak { weak_binder, interface_type: PhantomData, } } /// Upgrade this weak reference to a strong reference if the binder object /// is still alive pub fn upgrade(&self) -> Result<Strong<I>> { self.weak_binder .promote() .ok_or(StatusCode::DEAD_OBJECT) .and_then(FromIBinder::try_from) } } impl<I: FromIBinder + ?Sized> Clone for Weak<I> { fn clone(&self) -> Self { Self { weak_binder: self.weak_binder.clone(), interface_type: PhantomData, } } } impl<I: FromIBinder + ?Sized> Ord for Weak<I> { fn cmp(&self, other: &Self) -> Ordering { self.weak_binder.cmp(&other.weak_binder) } } impl<I: FromIBinder + ?Sized> PartialOrd for Weak<I> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { self.weak_binder.partial_cmp(&other.weak_binder) } } impl<I: FromIBinder + ?Sized> PartialEq for Weak<I> { fn eq(&self, other: &Self) -> bool { self.weak_binder == other.weak_binder } } impl<I: FromIBinder + ?Sized> Eq for Weak<I> {} /// Create a function implementing a static getter for an interface class. /// /// Each binder interface (i.e. local [`Remotable`] service or remote proxy Loading Loading @@ -354,12 +485,12 @@ pub trait InterfaceClassMethods { /// } /// } /// ``` pub trait FromIBinder { pub trait FromIBinder: Interface { /// Try to interpret a generic Binder object as this interface. /// /// Returns a trait object for the `Self` interface if this object /// implements that interface. fn try_from(ibinder: SpIBinder) -> Result<Box<Self>>; fn try_from(ibinder: SpIBinder) -> Result<Strong<Self>>; } /// Trait for transparent Rust wrappers around android C++ native types. Loading Loading @@ -534,8 +665,9 @@ macro_rules! declare_binder_interface { impl $native { /// Create a new binder service. pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T) -> impl $interface { $crate::Binder::new($native(Box::new(inner))) pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T) -> $crate::Strong<dyn $interface> { let binder = $crate::Binder::new($native(Box::new(inner))); $crate::Strong::new(Box::new(binder)) } } Loading Loading @@ -577,7 +709,7 @@ macro_rules! declare_binder_interface { } impl $crate::FromIBinder for dyn $interface { fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<Box<dyn $interface>> { fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<$crate::Strong<dyn $interface>> { use $crate::AssociateClass; let existing_class = ibinder.get_class(); Loading @@ -590,7 +722,7 @@ macro_rules! declare_binder_interface { // associated object as remote, because we can't cast it // into a Rust service object without a matching class // pointer. return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)); return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?))); } } Loading @@ -600,10 +732,10 @@ macro_rules! declare_binder_interface { if let Ok(service) = service { // We were able to associate with our expected class and // the service is local. return Ok(Box::new(service)); return Ok($crate::Strong::new(Box::new(service))); } else { // Service is remote return Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)); return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?))); } } Loading Loading @@ -633,9 +765,9 @@ macro_rules! declare_binder_interface { } } // Convert a &dyn $interface to Box<dyn $interface> /// Convert a &dyn $interface to Strong<dyn $interface> impl std::borrow::ToOwned for dyn $interface { type Owned = Box<dyn $interface>; type Owned = $crate::Strong<dyn $interface>; fn to_owned(&self) -> Self::Owned { self.as_binder().into_interface() .expect(concat!("Error cloning interface ", stringify!($interface))) Loading
libs/binder/rust/src/lib.rs +4 −2 Original line number Diff line number Diff line Loading @@ -107,7 +107,8 @@ use binder_ndk_sys as sys; pub mod parcel; pub use crate::binder::{ FromIBinder, IBinder, Interface, InterfaceClass, Remotable, TransactionCode, TransactionFlags, FromIBinder, IBinder, Interface, InterfaceClass, Remotable, Strong, TransactionCode, TransactionFlags, Weak, }; pub use error::{status_t, ExceptionCode, Result, Status, StatusCode}; pub use native::add_service; Loading @@ -122,7 +123,8 @@ pub mod public_api { pub use super::parcel::ParcelFileDescriptor; pub use super::{add_service, get_interface}; pub use super::{ ExceptionCode, Interface, ProcessState, SpIBinder, Status, StatusCode, WpIBinder, ExceptionCode, Interface, ProcessState, SpIBinder, Status, StatusCode, Strong, ThreadState, Weak, WpIBinder, }; /// Binder result containing a [`Status`] on error. Loading
libs/binder/rust/src/parcel/parcelable.rs +5 −5 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ * limitations under the License. */ use crate::binder::{AsNative, FromIBinder}; use crate::binder::{AsNative, FromIBinder, Strong}; use crate::error::{status_result, status_t, Result, Status, StatusCode}; use crate::parcel::Parcel; use crate::proxy::SpIBinder; Loading Loading @@ -628,26 +628,26 @@ impl Deserialize for Status { } } impl<T: Serialize + ?Sized> Serialize for Box<T> { impl<T: Serialize + FromIBinder + ?Sized> Serialize for Strong<T> { fn serialize(&self, parcel: &mut Parcel) -> Result<()> { Serialize::serialize(&**self, parcel) } } impl<T: SerializeOption + ?Sized> SerializeOption for Box<T> { impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> { fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { SerializeOption::serialize_option(this.map(|b| &**b), parcel) } } impl<T: FromIBinder + ?Sized> Deserialize for Box<T> { impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> { fn deserialize(parcel: &Parcel) -> Result<Self> { let ibinder: SpIBinder = parcel.read()?; FromIBinder::try_from(ibinder) } } impl<T: FromIBinder + ?Sized> DeserializeOption for Box<T> { impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> { fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> { let ibinder: Option<SpIBinder> = parcel.read()?; ibinder.map(FromIBinder::try_from).transpose() Loading
libs/binder/rust/src/proxy.rs +92 −5 Original line number Diff line number Diff line Loading @@ -17,7 +17,7 @@ //! Rust API for interacting with a remote binder service. use crate::binder::{ AsNative, FromIBinder, IBinder, Interface, InterfaceClass, TransactionCode, TransactionFlags, AsNative, FromIBinder, IBinder, Interface, InterfaceClass, Strong, TransactionCode, TransactionFlags, }; use crate::error::{status_result, Result, StatusCode}; use crate::parcel::{ Loading @@ -27,6 +27,7 @@ use crate::parcel::{ use crate::sys; use std::convert::TryInto; use std::cmp::Ordering; use std::ffi::{c_void, CString}; use std::fmt; use std::os::unix::io::AsRawFd; Loading Loading @@ -99,7 +100,7 @@ impl SpIBinder { /// /// If this object does not implement the expected interface, the error /// `StatusCode::BAD_TYPE` is returned. pub fn into_interface<I: FromIBinder + ?Sized>(self) -> Result<Box<I>> { pub fn into_interface<I: FromIBinder + Interface + ?Sized>(self) -> Result<Strong<I>> { FromIBinder::try_from(self) } Loading Loading @@ -148,6 +149,36 @@ impl AssociateClass for SpIBinder { } } impl Ord for SpIBinder { fn cmp(&self, other: &Self) -> Ordering { let less_than = unsafe { // Safety: SpIBinder always holds a valid `AIBinder` pointer, so // this pointer is always safe to pass to `AIBinder_lt` (null is // also safe to pass to this function, but we should never do that). sys::AIBinder_lt(self.0, other.0) }; let greater_than = unsafe { // Safety: SpIBinder always holds a valid `AIBinder` pointer, so // this pointer is always safe to pass to `AIBinder_lt` (null is // also safe to pass to this function, but we should never do that). sys::AIBinder_lt(other.0, self.0) }; if !less_than && !greater_than { Ordering::Equal } else if less_than { Ordering::Less } else { Ordering::Greater } } } impl PartialOrd for SpIBinder { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) } } impl PartialEq for SpIBinder { fn eq(&self, other: &Self) -> bool { ptr::eq(self.0, other.0) Loading Loading @@ -326,7 +357,7 @@ impl<T: AsNative<sys::AIBinder>> IBinder for T { // Safety: `SpIBinder` guarantees that `self` always contains a // valid pointer to an `AIBinder`. `recipient` can always be // converted into a valid pointer to an // `AIBinder_DeatRecipient`. Any value is safe to pass as the // `AIBinder_DeathRecipient`. Any value is safe to pass as the // cookie, although we depend on this value being set by // `get_cookie` when the death recipient callback is called. sys::AIBinder_linkToDeath( Loading @@ -342,7 +373,7 @@ impl<T: AsNative<sys::AIBinder>> IBinder for T { // Safety: `SpIBinder` guarantees that `self` always contains a // valid pointer to an `AIBinder`. `recipient` can always be // converted into a valid pointer to an // `AIBinder_DeatRecipient`. Any value is safe to pass as the // `AIBinder_DeathRecipient`. Any value is safe to pass as the // cookie, although we depend on this value being set by // `get_cookie` when the death recipient callback is called. sys::AIBinder_unlinkToDeath( Loading Loading @@ -430,6 +461,62 @@ impl WpIBinder { } } impl Clone for WpIBinder { fn clone(&self) -> Self { let ptr = unsafe { // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, // so this pointer is always safe to pass to `AIBinder_Weak_clone` // (although null is also a safe value to pass to this API). // // We get ownership of the returned pointer, so can construct a new // WpIBinder object from it. sys::AIBinder_Weak_clone(self.0) }; assert!(!ptr.is_null(), "Unexpected null pointer from AIBinder_Weak_clone"); Self(ptr) } } impl Ord for WpIBinder { fn cmp(&self, other: &Self) -> Ordering { let less_than = unsafe { // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, // so this pointer is always safe to pass to `AIBinder_Weak_lt` // (null is also safe to pass to this function, but we should never // do that). sys::AIBinder_Weak_lt(self.0, other.0) }; let greater_than = unsafe { // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, // so this pointer is always safe to pass to `AIBinder_Weak_lt` // (null is also safe to pass to this function, but we should never // do that). sys::AIBinder_Weak_lt(other.0, self.0) }; if !less_than && !greater_than { Ordering::Equal } else if less_than { Ordering::Less } else { Ordering::Greater } } } impl PartialOrd for WpIBinder { fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) } } impl PartialEq for WpIBinder { fn eq(&self, other: &Self) -> bool { self.cmp(other) == Ordering::Equal } } impl Eq for WpIBinder {} impl Drop for WpIBinder { fn drop(&mut self) { unsafe { Loading Loading @@ -564,7 +651,7 @@ pub fn get_service(name: &str) -> Option<SpIBinder> { /// Retrieve an existing service for a particular interface, blocking for a few /// seconds if it doesn't yet exist. pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Box<T>> { pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> { let service = get_service(name); match service { Some(service) => FromIBinder::try_from(service), Loading
libs/binder/rust/tests/integration.rs +57 −6 Original line number Diff line number Diff line Loading @@ -209,7 +209,7 @@ mod tests { use std::thread; use std::time::Duration; use binder::{Binder, DeathRecipient, FromIBinder, IBinder, Interface, SpIBinder, StatusCode}; use binder::{Binder, DeathRecipient, FromIBinder, IBinder, Interface, SpIBinder, StatusCode, Strong}; use super::{BnTest, ITest, ITestSameDescriptor, RUST_SERVICE_BINARY, TestService}; Loading Loading @@ -271,7 +271,7 @@ mod tests { fn trivial_client() { let service_name = "trivial_client_test"; let _process = ScopedServiceProcess::new(service_name); let test_client: Box<dyn ITest> = let test_client: Strong<dyn ITest> = binder::get_interface(service_name).expect("Did not get manager binder service"); assert_eq!(test_client.test().unwrap(), "trivial_client_test"); } Loading @@ -280,7 +280,7 @@ mod tests { fn get_selinux_context() { let service_name = "get_selinux_context"; let _process = ScopedServiceProcess::new(service_name); let test_client: Box<dyn ITest> = let test_client: Strong<dyn ITest> = binder::get_interface(service_name).expect("Did not get manager binder service"); let expected_context = unsafe { let mut out_ptr = ptr::null_mut(); Loading Loading @@ -453,7 +453,7 @@ mod tests { let extension = maybe_extension.expect("Remote binder did not have an extension"); let extension: Box<dyn ITest> = FromIBinder::try_from(extension) let extension: Strong<dyn ITest> = FromIBinder::try_from(extension) .expect("Extension could not be converted to the expected interface"); assert_eq!(extension.test().unwrap(), extension_name); Loading @@ -479,7 +479,7 @@ mod tests { // This should succeed although we will have to treat the service as // remote. let _interface: Box<dyn ITestSameDescriptor> = FromIBinder::try_from(service.as_binder()) let _interface: Strong<dyn ITestSameDescriptor> = FromIBinder::try_from(service.as_binder()) .expect("Could not re-interpret service as the ITestSameDescriptor interface"); } Loading @@ -490,9 +490,60 @@ mod tests { let service_ibinder = BnTest::new_binder(TestService { s: service_name.to_string() }) .as_binder(); let service: Box<dyn ITest> = service_ibinder.into_interface() let service: Strong<dyn ITest> = service_ibinder.into_interface() .expect("Could not reassociate the generic ibinder"); assert_eq!(service.test().unwrap(), service_name); } #[test] fn weak_binder_upgrade() { let service_name = "testing_service"; let service = BnTest::new_binder(TestService { s: service_name.to_string() }); let weak = Strong::downgrade(&service); let upgraded = weak.upgrade().expect("Could not upgrade weak binder"); assert_eq!(service, upgraded); } #[test] fn weak_binder_upgrade_dead() { let service_name = "testing_service"; let weak = { let service = BnTest::new_binder(TestService { s: service_name.to_string() }); Strong::downgrade(&service) }; assert_eq!(weak.upgrade(), Err(StatusCode::DEAD_OBJECT)); } #[test] fn weak_binder_clone() { let service_name = "testing_service"; let service = BnTest::new_binder(TestService { s: service_name.to_string() }); let weak = Strong::downgrade(&service); let cloned = weak.clone(); assert_eq!(weak, cloned); let upgraded = weak.upgrade().expect("Could not upgrade weak binder"); let clone_upgraded = cloned.upgrade().expect("Could not upgrade weak binder"); assert_eq!(service, upgraded); assert_eq!(service, clone_upgraded); } #[test] #[allow(clippy::eq_op)] fn binder_ord() { let service1 = BnTest::new_binder(TestService { s: "testing_service1".to_string() }); let service2 = BnTest::new_binder(TestService { s: "testing_service2".to_string() }); assert!(!(service1 < service1)); assert!(!(service1 > service1)); assert_eq!(service1 < service2, !(service2 < service1)); } }