Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bd26e59d authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "rust: add conversion between sync and async interfaces" am: 26a735ae

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1900390

Change-Id: I4f327c6916d6621bd79dd057331c8a09f2a02884
parents bab6894a 26a735ae
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -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;
        }
        )?
    };
}
+2 −2
Original line number Diff line number Diff line
@@ -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};
+26 −0
Original line number Diff line number Diff line
@@ -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>,