Loading libs/binder/rust/binder_tokio/lib.rs +27 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ use std::future::Future; /// Retrieve an existing service for a particular interface, sleeping for a few /// seconds if it doesn't yet exist. #[deprecated = "this polls 5s, use wait_for_interface or check_interface"] pub async fn get_interface<T: FromIBinder + ?Sized + 'static>( name: &str, ) -> Result<Strong<T>, StatusCode> { Loading @@ -56,6 +57,32 @@ pub async fn get_interface<T: FromIBinder + ?Sized + 'static>( } } /// Retrieve an existing service for a particular interface. Returns /// `Err(StatusCode::NAME_NOT_FOUND)` immediately if the service is not available. /// /// NOTE: "immediately" above does not mean the future will complete the first time it is polled. pub async fn check_interface<T: FromIBinder + ?Sized + 'static>( name: &str, ) -> Result<Strong<T>, StatusCode> { if binder::is_handling_transaction() { // See comment in the BinderAsyncPool impl. return binder::check_interface::<T>(name); } let name = name.to_string(); let res = tokio::task::spawn_blocking(move || binder::check_interface::<T>(&name)).await; // The `is_panic` branch is not actually reachable in Android as we compile // with `panic = abort`. match res { Ok(Ok(service)) => Ok(service), Ok(Err(err)) => Err(err), Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()), Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION), Err(_) => Err(StatusCode::UNKNOWN_ERROR), } } /// 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 async fn wait_for_interface<T: FromIBinder + ?Sized + 'static>( Loading libs/binder/rust/src/lib.rs +3 −3 Original line number Diff line number Diff line Loading @@ -114,9 +114,9 @@ pub use parcel::{ParcelFileDescriptor, Parcelable, ParcelableHolder}; pub use proxy::{DeathRecipient, SpIBinder, WpIBinder}; #[cfg(not(trusty))] pub use service::{ add_service, force_lazy_services_persist, get_declared_instances, get_interface, get_service, is_declared, is_handling_transaction, register_lazy_service, wait_for_interface, wait_for_service, LazyServiceGuard, add_service, check_interface, check_service, force_lazy_services_persist, get_declared_instances, get_interface, get_service, is_declared, is_handling_transaction, register_lazy_service, wait_for_interface, wait_for_service, LazyServiceGuard, }; #[cfg(not(trusty))] pub use state::{ProcessState, ThreadState}; Loading libs/binder/rust/src/service.rs +17 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,7 @@ fn interface_cast<T: FromIBinder + ?Sized>(service: Option<SpIBinder>) -> Result /// Retrieve an existing service, blocking for a few seconds if it doesn't yet /// exist. #[deprecated = "this polls 5s, use wait_for_service or check_service"] pub fn get_service(name: &str) -> Option<SpIBinder> { let name = CString::new(name).ok()?; // Safety: `AServiceManager_getService` returns either a null pointer or a Loading @@ -152,6 +153,15 @@ pub fn get_service(name: &str) -> Option<SpIBinder> { unsafe { SpIBinder::from_raw(sys::AServiceManager_getService(name.as_ptr())) } } /// Retrieve an existing service. Returns `None` immediately if the service is not available. pub fn check_service(name: &str) -> Option<SpIBinder> { let name = CString::new(name).ok()?; // Safety: `AServiceManager_checkService` 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`. unsafe { SpIBinder::from_raw(sys::AServiceManager_checkService(name.as_ptr())) } } /// 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> { Loading @@ -164,10 +174,17 @@ pub fn wait_for_service(name: &str) -> Option<SpIBinder> { /// Retrieve an existing service for a particular interface, blocking for a few /// seconds if it doesn't yet exist. #[deprecated = "this polls 5s, use wait_for_interface or check_interface"] pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> { interface_cast(get_service(name)) } /// Retrieve an existing service for a particular interface. Returns /// `Err(StatusCode::NAME_NOT_FOUND)` immediately if the service is not available. pub fn check_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> { interface_cast(check_service(name)) } /// 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>> { Loading libs/binder/rust/tests/integration.rs +58 −2 Original line number Diff line number Diff line Loading @@ -421,7 +421,7 @@ mod tests { } #[test] fn check_services() { fn check_get_service() { let mut sm = binder::get_service("manager").expect("Did not get manager binder service"); assert!(sm.is_binder_alive()); assert!(sm.ping_binder().is_ok()); Loading @@ -445,7 +445,7 @@ mod tests { } #[tokio::test] async fn check_services_async() { async fn check_get_service_async() { let mut sm = binder::get_service("manager").expect("Did not get manager binder service"); assert!(sm.is_binder_alive()); assert!(sm.ping_binder().is_ok()); Loading Loading @@ -473,6 +473,62 @@ mod tests { ); } #[test] fn check_check_service() { let mut sm = binder::check_service("manager").expect("Did not find manager binder service"); assert!(sm.is_binder_alive()); assert!(sm.ping_binder().is_ok()); assert!(binder::check_service("this_service_does_not_exist").is_none()); assert_eq!( binder::check_interface::<dyn ITest>("this_service_does_not_exist").err(), Some(StatusCode::NAME_NOT_FOUND) ); assert_eq!( binder::check_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").err(), Some(StatusCode::NAME_NOT_FOUND) ); // The service manager service isn't an ITest, so this must fail. assert_eq!( binder::check_interface::<dyn ITest>("manager").err(), Some(StatusCode::BAD_TYPE) ); assert_eq!( binder::check_interface::<dyn IATest<Tokio>>("manager").err(), Some(StatusCode::BAD_TYPE) ); } #[tokio::test] async fn check_check_service_async() { let mut sm = binder::check_service("manager").expect("Did not find manager binder service"); assert!(sm.is_binder_alive()); assert!(sm.ping_binder().is_ok()); assert!(binder::check_service("this_service_does_not_exist").is_none()); assert_eq!( binder_tokio::check_interface::<dyn ITest>("this_service_does_not_exist").await.err(), Some(StatusCode::NAME_NOT_FOUND) ); assert_eq!( binder_tokio::check_interface::<dyn IATest<Tokio>>("this_service_does_not_exist") .await .err(), Some(StatusCode::NAME_NOT_FOUND) ); // The service manager service isn't an ITest, so this must fail. assert_eq!( binder_tokio::check_interface::<dyn ITest>("manager").await.err(), Some(StatusCode::BAD_TYPE) ); assert_eq!( binder_tokio::check_interface::<dyn IATest<Tokio>>("manager").await.err(), Some(StatusCode::BAD_TYPE) ); } #[test] fn check_wait_for_service() { let mut sm = Loading Loading
libs/binder/rust/binder_tokio/lib.rs +27 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ use std::future::Future; /// Retrieve an existing service for a particular interface, sleeping for a few /// seconds if it doesn't yet exist. #[deprecated = "this polls 5s, use wait_for_interface or check_interface"] pub async fn get_interface<T: FromIBinder + ?Sized + 'static>( name: &str, ) -> Result<Strong<T>, StatusCode> { Loading @@ -56,6 +57,32 @@ pub async fn get_interface<T: FromIBinder + ?Sized + 'static>( } } /// Retrieve an existing service for a particular interface. Returns /// `Err(StatusCode::NAME_NOT_FOUND)` immediately if the service is not available. /// /// NOTE: "immediately" above does not mean the future will complete the first time it is polled. pub async fn check_interface<T: FromIBinder + ?Sized + 'static>( name: &str, ) -> Result<Strong<T>, StatusCode> { if binder::is_handling_transaction() { // See comment in the BinderAsyncPool impl. return binder::check_interface::<T>(name); } let name = name.to_string(); let res = tokio::task::spawn_blocking(move || binder::check_interface::<T>(&name)).await; // The `is_panic` branch is not actually reachable in Android as we compile // with `panic = abort`. match res { Ok(Ok(service)) => Ok(service), Ok(Err(err)) => Err(err), Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()), Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION), Err(_) => Err(StatusCode::UNKNOWN_ERROR), } } /// 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 async fn wait_for_interface<T: FromIBinder + ?Sized + 'static>( Loading
libs/binder/rust/src/lib.rs +3 −3 Original line number Diff line number Diff line Loading @@ -114,9 +114,9 @@ pub use parcel::{ParcelFileDescriptor, Parcelable, ParcelableHolder}; pub use proxy::{DeathRecipient, SpIBinder, WpIBinder}; #[cfg(not(trusty))] pub use service::{ add_service, force_lazy_services_persist, get_declared_instances, get_interface, get_service, is_declared, is_handling_transaction, register_lazy_service, wait_for_interface, wait_for_service, LazyServiceGuard, add_service, check_interface, check_service, force_lazy_services_persist, get_declared_instances, get_interface, get_service, is_declared, is_handling_transaction, register_lazy_service, wait_for_interface, wait_for_service, LazyServiceGuard, }; #[cfg(not(trusty))] pub use state::{ProcessState, ThreadState}; Loading
libs/binder/rust/src/service.rs +17 −0 Original line number Diff line number Diff line Loading @@ -144,6 +144,7 @@ fn interface_cast<T: FromIBinder + ?Sized>(service: Option<SpIBinder>) -> Result /// Retrieve an existing service, blocking for a few seconds if it doesn't yet /// exist. #[deprecated = "this polls 5s, use wait_for_service or check_service"] pub fn get_service(name: &str) -> Option<SpIBinder> { let name = CString::new(name).ok()?; // Safety: `AServiceManager_getService` returns either a null pointer or a Loading @@ -152,6 +153,15 @@ pub fn get_service(name: &str) -> Option<SpIBinder> { unsafe { SpIBinder::from_raw(sys::AServiceManager_getService(name.as_ptr())) } } /// Retrieve an existing service. Returns `None` immediately if the service is not available. pub fn check_service(name: &str) -> Option<SpIBinder> { let name = CString::new(name).ok()?; // Safety: `AServiceManager_checkService` 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`. unsafe { SpIBinder::from_raw(sys::AServiceManager_checkService(name.as_ptr())) } } /// 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> { Loading @@ -164,10 +174,17 @@ pub fn wait_for_service(name: &str) -> Option<SpIBinder> { /// Retrieve an existing service for a particular interface, blocking for a few /// seconds if it doesn't yet exist. #[deprecated = "this polls 5s, use wait_for_interface or check_interface"] pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> { interface_cast(get_service(name)) } /// Retrieve an existing service for a particular interface. Returns /// `Err(StatusCode::NAME_NOT_FOUND)` immediately if the service is not available. pub fn check_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> { interface_cast(check_service(name)) } /// 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>> { Loading
libs/binder/rust/tests/integration.rs +58 −2 Original line number Diff line number Diff line Loading @@ -421,7 +421,7 @@ mod tests { } #[test] fn check_services() { fn check_get_service() { let mut sm = binder::get_service("manager").expect("Did not get manager binder service"); assert!(sm.is_binder_alive()); assert!(sm.ping_binder().is_ok()); Loading @@ -445,7 +445,7 @@ mod tests { } #[tokio::test] async fn check_services_async() { async fn check_get_service_async() { let mut sm = binder::get_service("manager").expect("Did not get manager binder service"); assert!(sm.is_binder_alive()); assert!(sm.ping_binder().is_ok()); Loading Loading @@ -473,6 +473,62 @@ mod tests { ); } #[test] fn check_check_service() { let mut sm = binder::check_service("manager").expect("Did not find manager binder service"); assert!(sm.is_binder_alive()); assert!(sm.ping_binder().is_ok()); assert!(binder::check_service("this_service_does_not_exist").is_none()); assert_eq!( binder::check_interface::<dyn ITest>("this_service_does_not_exist").err(), Some(StatusCode::NAME_NOT_FOUND) ); assert_eq!( binder::check_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").err(), Some(StatusCode::NAME_NOT_FOUND) ); // The service manager service isn't an ITest, so this must fail. assert_eq!( binder::check_interface::<dyn ITest>("manager").err(), Some(StatusCode::BAD_TYPE) ); assert_eq!( binder::check_interface::<dyn IATest<Tokio>>("manager").err(), Some(StatusCode::BAD_TYPE) ); } #[tokio::test] async fn check_check_service_async() { let mut sm = binder::check_service("manager").expect("Did not find manager binder service"); assert!(sm.is_binder_alive()); assert!(sm.ping_binder().is_ok()); assert!(binder::check_service("this_service_does_not_exist").is_none()); assert_eq!( binder_tokio::check_interface::<dyn ITest>("this_service_does_not_exist").await.err(), Some(StatusCode::NAME_NOT_FOUND) ); assert_eq!( binder_tokio::check_interface::<dyn IATest<Tokio>>("this_service_does_not_exist") .await .err(), Some(StatusCode::NAME_NOT_FOUND) ); // The service manager service isn't an ITest, so this must fail. assert_eq!( binder_tokio::check_interface::<dyn ITest>("manager").await.err(), Some(StatusCode::BAD_TYPE) ); assert_eq!( binder_tokio::check_interface::<dyn IATest<Tokio>>("manager").await.err(), Some(StatusCode::BAD_TYPE) ); } #[test] fn check_wait_for_service() { let mut sm = Loading