diff options
| -rw-r--r-- | libs/binder/rust/src/lib.rs | 4 | ||||
| -rw-r--r-- | libs/binder/rust/src/proxy.rs | 22 | ||||
| -rw-r--r-- | libs/binder/rust/tests/integration.rs | 23 |
3 files changed, 47 insertions, 2 deletions
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs index 2694cba870..7c0584bade 100644 --- a/libs/binder/rust/src/lib.rs +++ b/libs/binder/rust/src/lib.rs @@ -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, diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs index 52036f5312..4a6d118f07 100644 --- a/libs/binder/rust/src/proxy.rs +++ b/libs/binder/rust/src/proxy.rs @@ -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>> { @@ -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 diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs index 03320076cb..10b77f4840 100644 --- a/libs/binder/rust/tests/integration.rs +++ b/libs/binder/rust/tests/integration.rs @@ -274,6 +274,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"; let _process = ScopedServiceProcess::new(service_name); @@ -283,6 +297,15 @@ mod tests { } #[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"; let _process = ScopedServiceProcess::new(service_name); |