File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -91,6 +91,32 @@ impl Accessor {
9191 Accessor { accessor }
9292 }
9393
94+ /// Creates a new Accessor instance based on an existing Accessor's binder.
95+ /// This is useful when the Accessor instance is hosted in another process
96+ /// that has the permissions to create the socket connection FD.
97+ ///
98+ /// The `instance` argument must match the instance that the original Accessor
99+ /// is responsible for.
100+ /// `instance` must not contain null bytes and is used to create a CString to
101+ /// pass through FFI.
102+ /// The `binder` argument must be a valid binder from an Accessor
103+ pub fn from_binder ( instance : & str , binder : SpIBinder ) -> Option < Accessor > {
104+ let inst = CString :: new ( instance) . unwrap ( ) ;
105+
106+ // Safety: All `SpIBinder` objects (the `binder` argument) hold a valid pointer
107+ // to an `AIBinder` that is guaranteed to remain valid for the lifetime of the
108+ // SpIBinder. `ABinderRpc_Accessor_fromBinder` creates a new pointer to that binder
109+ // that it is responsible for.
110+ // The `inst` argument is a new CString that will copied by
111+ // `ABinderRpc_Accessor_fromBinder` and not modified.
112+ let accessor =
113+ unsafe { sys:: ABinderRpc_Accessor_fromBinder ( inst. as_ptr ( ) , binder. as_raw ( ) ) } ;
114+ if accessor. is_null ( ) {
115+ return None ;
116+ }
117+ Some ( Accessor { accessor } )
118+ }
119+
94120 /// Get the underlying binder for this Accessor for when it needs to be either
95121 /// registered with service manager or sent to another process.
96122 pub fn as_binder ( & self ) -> Option < SpIBinder > {
Original file line number Diff line number Diff line change @@ -1038,6 +1038,34 @@ mod tests {
10381038 assert ! ( deleted. load( Ordering :: Relaxed ) ) ;
10391039 }
10401040
1041+ #[ test]
1042+ fn test_accessor_from_accessor_binder ( ) {
1043+ let get_connection_info = move |_instance : & str | None ;
1044+ let accessor = Accessor :: new ( "foo.service" , get_connection_info) ;
1045+ let accessor2 =
1046+ Accessor :: from_binder ( "foo.service" , accessor. as_binder ( ) . unwrap ( ) ) . unwrap ( ) ;
1047+ assert_eq ! ( accessor. as_binder( ) , accessor2. as_binder( ) ) ;
1048+ }
1049+
1050+ #[ test]
1051+ fn test_accessor_from_non_accessor_binder ( ) {
1052+ let service_name = "rust_test_ibinder" ;
1053+ let _process = ScopedServiceProcess :: new ( service_name) ;
1054+ let binder = binder:: get_service ( service_name) . unwrap ( ) ;
1055+ assert ! ( binder. is_binder_alive( ) ) ;
1056+
1057+ let accessor = Accessor :: from_binder ( "rust_test_ibinder" , binder) ;
1058+ assert ! ( accessor. is_none( ) ) ;
1059+ }
1060+
1061+ #[ test]
1062+ fn test_accessor_from_wrong_accessor_binder ( ) {
1063+ let get_connection_info = move |_instance : & str | None ;
1064+ let accessor = Accessor :: new ( "foo.service" , get_connection_info) ;
1065+ let accessor2 = Accessor :: from_binder ( "NOT.foo.service" , accessor. as_binder ( ) . unwrap ( ) ) ;
1066+ assert ! ( accessor2. is_none( ) ) ;
1067+ }
1068+
10411069 #[ tokio:: test]
10421070 async fn reassociate_rust_binder_async ( ) {
10431071 let service_name = "testing_service" ;
You can’t perform that action at this time.
0 commit comments