diff options
-rw-r--r-- | libs/binder/rust/src/binder.rs | 36 | ||||
-rw-r--r-- | libs/binder/rust/tests/integration.rs | 23 |
2 files changed, 49 insertions, 10 deletions
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs index e34d31e58f..9a252b853b 100644 --- a/libs/binder/rust/src/binder.rs +++ b/libs/binder/rust/src/binder.rs @@ -768,14 +768,14 @@ macro_rules! declare_binder_interface { $interface:path[$descriptor:expr] { native: $native:ident($on_transact:path), proxy: $proxy:ident, - $(async: $async_interface:ident,)? + $(async: $async_interface:ident $(($try_into_local_async:ident))?,)? } } => { $crate::declare_binder_interface! { $interface[$descriptor] { native: $native($on_transact), proxy: $proxy {}, - $(async: $async_interface,)? + $(async: $async_interface $(($try_into_local_async))?,)? stability: $crate::binder_impl::Stability::default(), } } @@ -785,7 +785,7 @@ macro_rules! declare_binder_interface { $interface:path[$descriptor:expr] { native: $native:ident($on_transact:path), proxy: $proxy:ident, - $(async: $async_interface:ident,)? + $(async: $async_interface:ident $(($try_into_local_async:ident))?,)? stability: $stability:expr, } } => { @@ -793,7 +793,7 @@ macro_rules! declare_binder_interface { $interface[$descriptor] { native: $native($on_transact), proxy: $proxy {}, - $(async: $async_interface,)? + $(async: $async_interface $(($try_into_local_async))?,)? stability: $stability, } } @@ -805,7 +805,7 @@ macro_rules! declare_binder_interface { proxy: $proxy:ident { $($fname:ident: $fty:ty = $finit:expr),* }, - $(async: $async_interface:ident,)? + $(async: $async_interface:ident $(($try_into_local_async:ident))?,)? } } => { $crate::declare_binder_interface! { @@ -814,7 +814,7 @@ macro_rules! declare_binder_interface { proxy: $proxy { $($fname: $fty = $finit),* }, - $(async: $async_interface,)? + $(async: $async_interface $(($try_into_local_async))?,)? stability: $crate::binder_impl::Stability::default(), } } @@ -826,7 +826,7 @@ macro_rules! declare_binder_interface { proxy: $proxy:ident { $($fname:ident: $fty:ty = $finit:expr),* }, - $(async: $async_interface:ident,)? + $(async: $async_interface:ident $(($try_into_local_async:ident))?,)? stability: $stability:expr, } } => { @@ -838,7 +838,7 @@ macro_rules! declare_binder_interface { proxy: $proxy { $($fname: $fty = $finit),* }, - $(async: $async_interface,)? + $(async: $async_interface $(($try_into_local_async))?,)? stability: $stability, } } @@ -854,7 +854,7 @@ macro_rules! declare_binder_interface { $($fname:ident: $fty:ty = $finit:expr),* }, - $( async: $async_interface:ident, )? + $(async: $async_interface:ident $(($try_into_local_async:ident))?,)? stability: $stability:expr, } @@ -1043,6 +1043,24 @@ macro_rules! declare_binder_interface { } if ibinder.associate_class(<$native as $crate::binder_impl::Remotable>::get_class()) { + let service: std::result::Result<$crate::binder_impl::Binder<$native>, $crate::StatusCode> = + std::convert::TryFrom::try_from(ibinder.clone()); + $( + // This part is only generated if the user of the macro specifies that the + // trait has an `try_into_local_async` implementation. + if let Ok(service) = service { + if let Some(async_service) = $native::$try_into_local_async(service) { + // We were able to associate with our expected class, + // the service is local, and the local service is async. + return Ok(async_service); + } + // The service is local but not async. Fall back to treating it as a + // remote service. This means that calls to this local service have an + // extra performance cost due to serialization, but async handle to + // non-async server is considered a rare case, so this is okay. + } + )? + // Treat service as remote. return Ok($crate::Strong::new(Box::new(<$proxy as $crate::binder_impl::Proxy>::from_binder(ibinder)?))); } diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs index 15ae56fdd7..5359832da1 100644 --- a/libs/binder/rust/tests/integration.rs +++ b/libs/binder/rust/tests/integration.rs @@ -182,7 +182,7 @@ declare_binder_interface! { proxy: BpTest { x: i32 = 100 }, - async: IATest, + async: IATest(try_into_local_async), } } @@ -323,6 +323,14 @@ impl<P: binder::BinderAsyncPool> IATest<P> for Binder<BnTest> { } } +impl BnTest { + fn try_into_local_async<P: binder::BinderAsyncPool + 'static>( + me: Binder<BnTest>, + ) -> Option<binder::Strong<dyn IATest<P>>> { + Some(binder::Strong::new(Box::new(me) as _)) + } +} + /// Trivial testing binder interface pub trait ITestSameDescriptor: Interface {} @@ -900,6 +908,19 @@ mod tests { assert_eq!(service.test().unwrap(), service_name); } + #[tokio::test] + async fn reassociate_rust_binder_async() { + let service_name = "testing_service"; + let service_ibinder = + BnTest::new_binder(TestService::new(service_name), BinderFeatures::default()) + .as_binder(); + + let service: Strong<dyn IATest<Tokio>> = + service_ibinder.into_interface().expect("Could not reassociate the generic ibinder"); + + assert_eq!(service.test().await.unwrap(), service_name); + } + #[test] fn weak_binder_upgrade() { let service_name = "testing_service"; |