Loading libs/binder/rust/src/lib.rs +2 −2 Original line number Diff line number Diff line Loading @@ -115,14 +115,14 @@ pub use error::{status_t, ExceptionCode, Result, Status, StatusCode}; pub use native::add_service; pub use native::Binder; pub use parcel::Parcel; pub use proxy::{get_interface, get_service}; pub use proxy::{get_interface, get_service, wait_for_interface, wait_for_service}; pub use proxy::{AssociateClass, DeathRecipient, Proxy, SpIBinder, WpIBinder}; pub use state::{ProcessState, ThreadState}; /// The public API usable outside AIDL-generated interface crates. pub mod public_api { pub use super::parcel::ParcelFileDescriptor; pub use super::{add_service, get_interface}; pub use super::{add_service, get_interface, wait_for_interface}; pub use super::{ BinderFeatures, DeathRecipient, ExceptionCode, IBinder, Interface, ProcessState, SpIBinder, Status, StatusCode, Strong, ThreadState, Weak, WpIBinder, Loading libs/binder/rust/src/proxy.rs +22 −0 Original line number Diff line number Diff line Loading @@ -653,6 +653,18 @@ pub fn get_service(name: &str) -> Option<SpIBinder> { } } /// Retrieve an existing service, or start it if it is configured as a dynamic /// service and isn't yet started. pub fn wait_for_service(name: &str) -> Option<SpIBinder> { let name = CString::new(name).ok()?; unsafe { // Safety: `AServiceManager_waitforService` returns either a null // pointer or a valid pointer to an owned `AIBinder`. Either of these // values is safe to pass to `SpIBinder::from_raw`. SpIBinder::from_raw(sys::AServiceManager_waitForService(name.as_ptr())) } } /// 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<Strong<T>> { Loading @@ -663,6 +675,16 @@ pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> { } } /// Retrieve an existing service for a particular interface, or start it if it /// is configured as a dynamic service and isn't yet started. pub fn wait_for_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> { let service = wait_for_service(name); match service { Some(service) => FromIBinder::try_from(service), None => Err(StatusCode::NAME_NOT_FOUND), } } /// # Safety /// /// `SpIBinder` guarantees that `binder` always contains a valid pointer to an Loading libs/binder/rust/tests/integration.rs +23 −0 Original line number Diff line number Diff line Loading @@ -273,6 +273,20 @@ mod tests { ); } #[test] fn check_wait_for_service() { let mut sm = binder::wait_for_service("manager").expect("Did not get manager binder service"); assert!(sm.is_binder_alive()); assert!(sm.ping_binder().is_ok()); // The service manager service isn't an ITest, so this must fail. assert_eq!( binder::wait_for_interface::<dyn ITest>("manager").err(), Some(StatusCode::BAD_TYPE) ); } #[test] fn trivial_client() { let service_name = "trivial_client_test"; Loading @@ -282,6 +296,15 @@ mod tests { assert_eq!(test_client.test().unwrap(), "trivial_client_test"); } #[test] fn wait_for_trivial_client() { let service_name = "wait_for_trivial_client_test"; let _process = ScopedServiceProcess::new(service_name); let test_client: Strong<dyn ITest> = binder::wait_for_interface(service_name).expect("Did not get manager binder service"); assert_eq!(test_client.test().unwrap(), "wait_for_trivial_client_test"); } #[test] fn get_selinux_context() { let service_name = "get_selinux_context"; Loading Loading
libs/binder/rust/src/lib.rs +2 −2 Original line number Diff line number Diff line Loading @@ -115,14 +115,14 @@ pub use error::{status_t, ExceptionCode, Result, Status, StatusCode}; pub use native::add_service; pub use native::Binder; pub use parcel::Parcel; pub use proxy::{get_interface, get_service}; pub use proxy::{get_interface, get_service, wait_for_interface, wait_for_service}; pub use proxy::{AssociateClass, DeathRecipient, Proxy, SpIBinder, WpIBinder}; pub use state::{ProcessState, ThreadState}; /// The public API usable outside AIDL-generated interface crates. pub mod public_api { pub use super::parcel::ParcelFileDescriptor; pub use super::{add_service, get_interface}; pub use super::{add_service, get_interface, wait_for_interface}; pub use super::{ BinderFeatures, DeathRecipient, ExceptionCode, IBinder, Interface, ProcessState, SpIBinder, Status, StatusCode, Strong, ThreadState, Weak, WpIBinder, Loading
libs/binder/rust/src/proxy.rs +22 −0 Original line number Diff line number Diff line Loading @@ -653,6 +653,18 @@ pub fn get_service(name: &str) -> Option<SpIBinder> { } } /// Retrieve an existing service, or start it if it is configured as a dynamic /// service and isn't yet started. pub fn wait_for_service(name: &str) -> Option<SpIBinder> { let name = CString::new(name).ok()?; unsafe { // Safety: `AServiceManager_waitforService` returns either a null // pointer or a valid pointer to an owned `AIBinder`. Either of these // values is safe to pass to `SpIBinder::from_raw`. SpIBinder::from_raw(sys::AServiceManager_waitForService(name.as_ptr())) } } /// 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<Strong<T>> { Loading @@ -663,6 +675,16 @@ pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> { } } /// Retrieve an existing service for a particular interface, or start it if it /// is configured as a dynamic service and isn't yet started. pub fn wait_for_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> { let service = wait_for_service(name); match service { Some(service) => FromIBinder::try_from(service), None => Err(StatusCode::NAME_NOT_FOUND), } } /// # Safety /// /// `SpIBinder` guarantees that `binder` always contains a valid pointer to an Loading
libs/binder/rust/tests/integration.rs +23 −0 Original line number Diff line number Diff line Loading @@ -273,6 +273,20 @@ mod tests { ); } #[test] fn check_wait_for_service() { let mut sm = binder::wait_for_service("manager").expect("Did not get manager binder service"); assert!(sm.is_binder_alive()); assert!(sm.ping_binder().is_ok()); // The service manager service isn't an ITest, so this must fail. assert_eq!( binder::wait_for_interface::<dyn ITest>("manager").err(), Some(StatusCode::BAD_TYPE) ); } #[test] fn trivial_client() { let service_name = "trivial_client_test"; Loading @@ -282,6 +296,15 @@ mod tests { assert_eq!(test_client.test().unwrap(), "trivial_client_test"); } #[test] fn wait_for_trivial_client() { let service_name = "wait_for_trivial_client_test"; let _process = ScopedServiceProcess::new(service_name); let test_client: Strong<dyn ITest> = binder::wait_for_interface(service_name).expect("Did not get manager binder service"); assert_eq!(test_client.test().unwrap(), "wait_for_trivial_client_test"); } #[test] fn get_selinux_context() { let service_name = "get_selinux_context"; Loading