diff options
| author | 2024-11-25 17:21:03 +0000 | |
|---|---|---|
| committer | 2024-11-25 17:21:03 +0000 | |
| commit | a22273415139187a09a41f5f9525aac6be09c5ff (patch) | |
| tree | 5034366fd4748f535dad5c7d16e9a0bfc4f034fe | |
| parent | 2d66014572c6d077540e9ccae26b50890c76068f (diff) | |
| parent | b4eafd35890b1651514feb602aba025e4c869d8d (diff) | |
Merge "Add Accessor::from_binder" into main
| -rw-r--r-- | libs/binder/rust/src/system_only.rs | 26 | ||||
| -rw-r--r-- | libs/binder/rust/tests/integration.rs | 28 |
2 files changed, 54 insertions, 0 deletions
diff --git a/libs/binder/rust/src/system_only.rs b/libs/binder/rust/src/system_only.rs index 3da59ab811..1a58d6b44d 100644 --- a/libs/binder/rust/src/system_only.rs +++ b/libs/binder/rust/src/system_only.rs @@ -91,6 +91,32 @@ impl Accessor { Accessor { accessor } } + /// Creates a new Accessor instance based on an existing Accessor's binder. + /// This is useful when the Accessor instance is hosted in another process + /// that has the permissions to create the socket connection FD. + /// + /// The `instance` argument must match the instance that the original Accessor + /// is responsible for. + /// `instance` must not contain null bytes and is used to create a CString to + /// pass through FFI. + /// The `binder` argument must be a valid binder from an Accessor + pub fn from_binder(instance: &str, binder: SpIBinder) -> Option<Accessor> { + let inst = CString::new(instance).unwrap(); + + // Safety: All `SpIBinder` objects (the `binder` argument) hold a valid pointer + // to an `AIBinder` that is guaranteed to remain valid for the lifetime of the + // SpIBinder. `ABinderRpc_Accessor_fromBinder` creates a new pointer to that binder + // that it is responsible for. + // The `inst` argument is a new CString that will copied by + // `ABinderRpc_Accessor_fromBinder` and not modified. + let accessor = + unsafe { sys::ABinderRpc_Accessor_fromBinder(inst.as_ptr(), binder.as_raw()) }; + if accessor.is_null() { + return None; + } + Some(Accessor { accessor }) + } + /// Get the underlying binder for this Accessor for when it needs to be either /// registered with service manager or sent to another process. pub fn as_binder(&self) -> Option<SpIBinder> { diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs index 0e793e5761..da4f128e67 100644 --- a/libs/binder/rust/tests/integration.rs +++ b/libs/binder/rust/tests/integration.rs @@ -1038,6 +1038,34 @@ mod tests { assert!(deleted.load(Ordering::Relaxed)); } + #[test] + fn test_accessor_from_accessor_binder() { + let get_connection_info = move |_instance: &str| None; + let accessor = Accessor::new("foo.service", get_connection_info); + let accessor2 = + Accessor::from_binder("foo.service", accessor.as_binder().unwrap()).unwrap(); + assert_eq!(accessor.as_binder(), accessor2.as_binder()); + } + + #[test] + fn test_accessor_from_non_accessor_binder() { + let service_name = "rust_test_ibinder"; + let _process = ScopedServiceProcess::new(service_name); + let binder = binder::get_service(service_name).unwrap(); + assert!(binder.is_binder_alive()); + + let accessor = Accessor::from_binder("rust_test_ibinder", binder); + assert!(accessor.is_none()); + } + + #[test] + fn test_accessor_from_wrong_accessor_binder() { + let get_connection_info = move |_instance: &str| None; + let accessor = Accessor::new("foo.service", get_connection_info); + let accessor2 = Accessor::from_binder("NOT.foo.service", accessor.as_binder().unwrap()); + assert!(accessor2.is_none()); + } + #[tokio::test] async fn reassociate_rust_binder_async() { let service_name = "testing_service"; |