diff options
| author | 2021-11-17 10:39:07 +0000 | |
|---|---|---|
| committer | 2021-11-17 10:39:07 +0000 | |
| commit | e59fde00320dcb3a8c927eaa84ab5d9fed003164 (patch) | |
| tree | 5c1ddc515805cf6a843451b26758ecefdc46bedd | |
| parent | 488f3d37bb6459f29c579b4a59dacda43b54c79f (diff) | |
| parent | 55f395a6d1d6cda8264a95bfd2325bf9e7a8c6a9 (diff) | |
Merge "binder_tokio: only use threadpool for new transactions" am: 55f395a6d1
Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1892698
Change-Id: I29826df5da76a52d6087c2cfbdcf902b38496fb4
| -rw-r--r-- | libs/binder/rust/binder_tokio/lib.rs | 45 | ||||
| -rw-r--r-- | libs/binder/rust/src/lib.rs | 2 | ||||
| -rw-r--r-- | libs/binder/rust/src/native.rs | 9 |
3 files changed, 42 insertions, 14 deletions
diff --git a/libs/binder/rust/binder_tokio/lib.rs b/libs/binder/rust/binder_tokio/lib.rs index 64833b6d60..91047bea48 100644 --- a/libs/binder/rust/binder_tokio/lib.rs +++ b/libs/binder/rust/binder_tokio/lib.rs @@ -35,6 +35,11 @@ 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> { + if binder::is_handling_transaction() { + // See comment in the BinderAsyncPool impl. + return binder::public_api::get_interface::<T>(name); + } + let name = name.to_string(); let res = tokio::task::spawn_blocking(move || { binder::public_api::get_interface::<T>(&name) @@ -54,6 +59,11 @@ pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(name: &str) -> Res /// 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> { + if binder::is_handling_transaction() { + // See comment in the BinderAsyncPool impl. + return binder::public_api::wait_for_interface::<T>(name); + } + let name = name.to_string(); let res = tokio::task::spawn_blocking(move || { binder::public_api::wait_for_interface::<T>(&name) @@ -86,18 +96,27 @@ impl BinderAsyncPool for Tokio { B: Send + 'a, E: From<crate::StatusCode>, { - let handle = tokio::task::spawn_blocking(spawn_me); - Box::pin(async move { - // The `is_panic` branch is not actually reachable in Android as we compile - // with `panic = abort`. - match handle.await { - Ok(res) => after_spawn(res).await, - Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()), - Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION.into()), - Err(_) => Err(StatusCode::UNKNOWN_ERROR.into()), - } - }) + if binder::is_handling_transaction() { + // We are currently on the thread pool for a binder server, so we should execute the + // transaction on the current thread so that the binder kernel driver is able to apply + // its deadlock prevention strategy to the sub-call. + // + // This shouldn't cause issues with blocking the thread as only one task will run in a + // call to `block_on`, so there aren't other tasks to block. + let result = spawn_me(); + Box::pin(after_spawn(result)) + } else { + let handle = tokio::task::spawn_blocking(spawn_me); + Box::pin(async move { + // The `is_panic` branch is not actually reachable in Android as we compile + // with `panic = abort`. + match handle.await { + Ok(res) => after_spawn(res).await, + Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()), + Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION.into()), + Err(_) => Err(StatusCode::UNKNOWN_ERROR.into()), + } + }) + } } } - - diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs index cce55c0188..b94dfa137e 100644 --- a/libs/binder/rust/src/lib.rs +++ b/libs/binder/rust/src/lib.rs @@ -114,7 +114,7 @@ pub use crate::binder::{ }; pub use crate::binder_async::{BoxFuture, BinderAsyncPool}; pub use error::{status_t, ExceptionCode, Result, Status, StatusCode}; -pub use native::{add_service, force_lazy_services_persist, register_lazy_service, Binder}; +pub use native::{add_service, force_lazy_services_persist, is_handling_transaction, register_lazy_service, Binder}; pub use parcel::{BorrowedParcel, Parcel}; pub use proxy::{get_interface, get_service, wait_for_interface, wait_for_service}; pub use proxy::{AssociateClass, DeathRecipient, Proxy, SpIBinder, WpIBinder}; diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs index e183ea30fc..b7c7ae4b54 100644 --- a/libs/binder/rust/src/native.rs +++ b/libs/binder/rust/src/native.rs @@ -517,3 +517,12 @@ impl Remotable for () { } impl Interface for () {} + +/// Determine whether the current thread is currently executing an incoming +/// transaction. +pub fn is_handling_transaction() -> bool { + unsafe { + // Safety: This method is always safe to call. + sys::AIBinder_isHandlingTransaction() + } +} |