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

Commit 039b9892 authored by Matthew Maurer's avatar Matthew Maurer Committed by Automerger Merge Worker
Browse files

Merge "binder_rust: add async variants of get_interface and...

Merge "binder_rust: add async variants of get_interface and wait_for_interface" am: 1b072863 am: 01f68a18 am: c3b612e6 am: 1a1a5673 am: efcf48a6

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

Change-Id: I1e89d4989f3898599813dfe4c1b1463af3a6d91d
parents 4e2788c7 efcf48a6
Loading
Loading
Loading
Loading
+40 −2
Original line number Diff line number Diff line
@@ -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 {}

+30 −3
Original line number Diff line number Diff line
@@ -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 =
@@ -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");
    }

@@ -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");
    }

@@ -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()