summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreehugger Robot <treehugger-gerrit@google.com>2021-12-11 09:59:55 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2021-12-11 09:59:55 +0000
commitbd26e59d33113487da6d00d9c8f712976f823083 (patch)
tree3dabc5e8c4643bd8e814b66504cadbd8f04ed8d2
parentbab6894a087da1624a4c9bcf1312521920628cb9 (diff)
parent26a735ae0f606db67f1a623cd42a644ea902747b (diff)
downloadnative-temp-sc-sam.tar.gz
Merge "rust: add conversion between sync and async interfaces" am: 26a735ae0ftemp-sc-sam
Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1900390 Change-Id: I4f327c6916d6621bd79dd057331c8a09f2a02884
-rw-r--r--libs/binder/rust/src/binder.rs57
-rw-r--r--libs/binder/rust/src/lib.rs4
-rw-r--r--libs/binder/rust/tests/integration.rs26
3 files changed, 85 insertions, 2 deletions
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index 3d2eddf611..4d6b294000 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -66,6 +66,35 @@ pub trait Interface: Send + Sync {
}
}
+/// Implemented by sync interfaces to specify what the associated async interface is.
+/// Generic to handle the fact that async interfaces are generic over a thread pool.
+///
+/// The binder in any object implementing this trait should be compatible with the
+/// `Target` associated type, and using `FromIBinder` to convert it to the target
+/// should not fail.
+pub trait ToAsyncInterface<P>
+where
+ Self: Interface,
+ Self::Target: FromIBinder,
+{
+ /// The async interface associated with this sync interface.
+ type Target: ?Sized;
+}
+
+/// Implemented by async interfaces to specify what the associated sync interface is.
+///
+/// The binder in any object implementing this trait should be compatible with the
+/// `Target` associated type, and using `FromIBinder` to convert it to the target
+/// should not fail.
+pub trait ToSyncInterface
+where
+ Self: Interface,
+ Self::Target: FromIBinder,
+{
+ /// The sync interface associated with this async interface.
+ type Target: ?Sized;
+}
+
/// Interface stability promise
///
/// An interface can promise to be a stable vendor interface ([`Vintf`]), or
@@ -337,6 +366,26 @@ impl<I: FromIBinder + ?Sized> Strong<I> {
pub fn downgrade(this: &Strong<I>) -> Weak<I> {
Weak::new(this)
}
+
+ /// Convert this synchronous binder handle into an asynchronous one.
+ pub fn into_async<P>(self) -> Strong<<I as ToAsyncInterface<P>>::Target>
+ where
+ I: ToAsyncInterface<P>,
+ {
+ // By implementing the ToAsyncInterface trait, it is guaranteed that the binder
+ // object is also valid for the target type.
+ FromIBinder::try_from(self.0.as_binder()).unwrap()
+ }
+
+ /// Convert this asynchronous binder handle into a synchronous one.
+ pub fn into_sync(self) -> Strong<<I as ToSyncInterface>::Target>
+ where
+ I: ToSyncInterface,
+ {
+ // By implementing the ToSyncInterface trait, it is guaranteed that the binder
+ // object is also valid for the target type.
+ FromIBinder::try_from(self.0.as_binder()).unwrap()
+ }
}
impl<I: FromIBinder + ?Sized> Clone for Strong<I> {
@@ -1017,6 +1066,14 @@ macro_rules! declare_binder_interface {
.expect(concat!("Error cloning interface ", stringify!($async_interface)))
}
}
+
+ impl<P: $crate::BinderAsyncPool> $crate::ToAsyncInterface<P> for dyn $interface {
+ type Target = dyn $async_interface<P>;
+ }
+
+ impl<P: $crate::BinderAsyncPool> $crate::ToSyncInterface for dyn $async_interface<P> {
+ type Target = dyn $interface;
+ }
)?
};
}
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index b94dfa137e..7c04a7207b 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -109,8 +109,8 @@ pub mod parcel;
pub use crate::binder::{
BinderFeatures, FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Remotable,
- Stability, Strong, TransactionCode, TransactionFlags, Weak, FIRST_CALL_TRANSACTION,
- FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION,
+ Stability, Strong, ToAsyncInterface, ToSyncInterface, TransactionCode, TransactionFlags, Weak,
+ FIRST_CALL_TRANSACTION, FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION,
};
pub use crate::binder_async::{BoxFuture, BinderAsyncPool};
pub use error::{status_t, ExceptionCode, Result, Status, StatusCode};
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index 09a956d2e9..80dc47682c 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -549,6 +549,32 @@ mod tests {
);
}
+ #[tokio::test]
+ async fn get_selinux_context_sync_to_async() {
+ let service_name = "get_selinux_context";
+ let _process = ScopedServiceProcess::new(service_name);
+ let test_client: Strong<dyn ITest> =
+ binder::get_interface(service_name).expect("Did not get manager binder service");
+ let test_client = test_client.into_async::<Tokio>();
+ assert_eq!(
+ test_client.get_selinux_context().await.unwrap(),
+ get_expected_selinux_context()
+ );
+ }
+
+ #[tokio::test]
+ async fn get_selinux_context_async_to_sync() {
+ let service_name = "get_selinux_context";
+ let _process = ScopedServiceProcess::new(service_name);
+ let test_client: Strong<dyn IATest<Tokio>> =
+ binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
+ let test_client = test_client.into_sync();
+ assert_eq!(
+ test_client.get_selinux_context().unwrap(),
+ get_expected_selinux_context()
+ );
+ }
+
struct Bools {
binder_died: Arc<AtomicBool>,
binder_dealloc: Arc<AtomicBool>,