Loading libs/binder/rust/binder_tokio/lib.rs +40 −2 Original line number Diff line number Diff line Loading @@ -28,10 +28,48 @@ //! //! [`Tokio`]: crate::Tokio use binder::public_api::{BinderAsyncPool, BoxFuture}; use binder::StatusCode; use binder::public_api::{BinderAsyncPool, BoxFuture, Strong}; use binder::{FromIBinder, StatusCode}; use std::future::Future; /// Retrieve an existing service for a particular interface, sleeping for a few /// seconds if it doesn't yet exist. pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(name: &str) -> Result<Strong<T>, StatusCode> { let name = name.to_string(); let res = tokio::task::spawn_blocking(move || { binder::public_api::get_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>(name: &str) -> Result<Strong<T>, StatusCode> { let name = name.to_string(); let res = tokio::task::spawn_blocking(move || { binder::public_api::wait_for_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), } } /// Use the Tokio `spawn_blocking` pool with AIDL. pub enum Tokio {} Loading libs/binder/rust/tests/integration.rs +30 −3 Original line number Diff line number Diff line Loading @@ -377,6 +377,33 @@ mod tests { ); } #[tokio::test] async fn check_services_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()); assert!(binder::get_service("this_service_does_not_exist").is_none()); assert_eq!( binder_tokio::get_interface::<dyn ITest>("this_service_does_not_exist").await.err(), Some(StatusCode::NAME_NOT_FOUND) ); assert_eq!( binder_tokio::get_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::get_interface::<dyn ITest>("manager").await.err(), Some(StatusCode::BAD_TYPE) ); assert_eq!( binder_tokio::get_interface::<dyn IATest<Tokio>>("manager").await.err(), Some(StatusCode::BAD_TYPE) ); } #[test] fn check_wait_for_service() { let mut sm = Loading Loading @@ -409,7 +436,7 @@ mod tests { let service_name = "trivial_client_test"; let _process = ScopedServiceProcess::new(service_name); let test_client: Strong<dyn IATest<Tokio>> = binder::get_interface(service_name).expect("Did not get manager binder service"); binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service"); assert_eq!(test_client.test().await.unwrap(), "trivial_client_test"); } Loading @@ -427,7 +454,7 @@ mod tests { let service_name = "wait_for_trivial_client_test"; let _process = ScopedServiceProcess::new(service_name); let test_client: Strong<dyn IATest<Tokio>> = binder::wait_for_interface(service_name).expect("Did not get manager binder service"); binder_tokio::wait_for_interface(service_name).await.expect("Did not get manager binder service"); assert_eq!(test_client.test().await.unwrap(), "wait_for_trivial_client_test"); } Loading Loading @@ -459,7 +486,7 @@ mod tests { let service_name = "get_selinux_context"; let _process = ScopedServiceProcess::new(service_name); let test_client: Strong<dyn IATest<Tokio>> = binder::get_interface(service_name).expect("Did not get manager binder service"); binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service"); assert_eq!( test_client.get_selinux_context().await.unwrap(), get_expected_selinux_context() Loading Loading
libs/binder/rust/binder_tokio/lib.rs +40 −2 Original line number Diff line number Diff line Loading @@ -28,10 +28,48 @@ //! //! [`Tokio`]: crate::Tokio use binder::public_api::{BinderAsyncPool, BoxFuture}; use binder::StatusCode; use binder::public_api::{BinderAsyncPool, BoxFuture, Strong}; use binder::{FromIBinder, StatusCode}; use std::future::Future; /// Retrieve an existing service for a particular interface, sleeping for a few /// seconds if it doesn't yet exist. pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(name: &str) -> Result<Strong<T>, StatusCode> { let name = name.to_string(); let res = tokio::task::spawn_blocking(move || { binder::public_api::get_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>(name: &str) -> Result<Strong<T>, StatusCode> { let name = name.to_string(); let res = tokio::task::spawn_blocking(move || { binder::public_api::wait_for_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), } } /// Use the Tokio `spawn_blocking` pool with AIDL. pub enum Tokio {} Loading
libs/binder/rust/tests/integration.rs +30 −3 Original line number Diff line number Diff line Loading @@ -377,6 +377,33 @@ mod tests { ); } #[tokio::test] async fn check_services_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()); assert!(binder::get_service("this_service_does_not_exist").is_none()); assert_eq!( binder_tokio::get_interface::<dyn ITest>("this_service_does_not_exist").await.err(), Some(StatusCode::NAME_NOT_FOUND) ); assert_eq!( binder_tokio::get_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::get_interface::<dyn ITest>("manager").await.err(), Some(StatusCode::BAD_TYPE) ); assert_eq!( binder_tokio::get_interface::<dyn IATest<Tokio>>("manager").await.err(), Some(StatusCode::BAD_TYPE) ); } #[test] fn check_wait_for_service() { let mut sm = Loading Loading @@ -409,7 +436,7 @@ mod tests { let service_name = "trivial_client_test"; let _process = ScopedServiceProcess::new(service_name); let test_client: Strong<dyn IATest<Tokio>> = binder::get_interface(service_name).expect("Did not get manager binder service"); binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service"); assert_eq!(test_client.test().await.unwrap(), "trivial_client_test"); } Loading @@ -427,7 +454,7 @@ mod tests { let service_name = "wait_for_trivial_client_test"; let _process = ScopedServiceProcess::new(service_name); let test_client: Strong<dyn IATest<Tokio>> = binder::wait_for_interface(service_name).expect("Did not get manager binder service"); binder_tokio::wait_for_interface(service_name).await.expect("Did not get manager binder service"); assert_eq!(test_client.test().await.unwrap(), "wait_for_trivial_client_test"); } Loading Loading @@ -459,7 +486,7 @@ mod tests { let service_name = "get_selinux_context"; let _process = ScopedServiceProcess::new(service_name); let test_client: Strong<dyn IATest<Tokio>> = binder::get_interface(service_name).expect("Did not get manager binder service"); binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service"); assert_eq!( test_client.get_selinux_context().await.unwrap(), get_expected_selinux_context() Loading