@@ -100,17 +100,36 @@ impl Accessor {
100100 unsafe { SpIBinder :: from_raw ( sys:: ABinderRpc_Accessor_asBinder ( self . accessor ) ) }
101101 }
102102
103+ /// Release the underlying ABinderRpc_Accessor pointer for use with the ndk API
104+ /// This gives up ownership of the ABinderRpc_Accessor and it is the responsibility of
105+ /// the caller to delete it with ABinderRpc_Accessor_delete
106+ ///
107+ /// # Safety
108+ ///
109+ /// - The returned `ABinderRpc_Accessor` pointer is now owned by the caller, who must
110+ /// call `ABinderRpc_Accessor_delete` to delete the object.
111+ /// - This `Accessor` object is now useless after `release` so it can be dropped.
112+ unsafe fn release ( mut self ) -> * mut sys:: ABinderRpc_Accessor {
113+ if self . accessor . is_null ( ) {
114+ log:: error!( "Attempting to release an Accessor that was already released" ) ;
115+ return ptr:: null_mut ( ) ;
116+ }
117+ let ptr = self . accessor ;
118+ self . accessor = ptr:: null_mut ( ) ;
119+ ptr
120+ }
121+
103122 /// Callback invoked from C++ when the connection info is needed.
104123 ///
105124 /// # Safety
106125 ///
107- /// The `instance` parameter must be a non-null pointer to a valid C string for
108- /// CStr::from_ptr. The memory must contain a valid null terminator at the end of
109- /// the string within isize::MAX from the pointer. The memory must not be mutated for
110- /// the duration of this function call and must be valid for reads from the pointer
111- /// to the null terminator.
112- /// The `cookie` parameter must be the cookie for an `Arc<F>` and
113- /// the caller must hold a ref-count to it.
126+ /// - The `instance` parameter must be a non-null pointer to a valid C string for
127+ /// CStr::from_ptr. The memory must contain a valid null terminator at the end of
128+ /// the string within isize::MAX from the pointer. The memory must not be mutated for
129+ /// the duration of this function call and must be valid for reads from the pointer
130+ /// to the null terminator.
131+ /// - The `cookie` parameter must be the cookie for an `Arc<F>` and
132+ /// the caller must hold a ref-count to it.
114133 unsafe extern "C" fn connection_info < F > (
115134 instance : * const c_char ,
116135 cookie : * mut c_void ,
@@ -172,8 +191,8 @@ impl Accessor {
172191 ///
173192 /// # Safety
174193 ///
175- /// The `cookie` parameter must be the cookie for an `Arc<F>` and
176- /// the owner must give up a ref-count to it.
194+ /// - The `cookie` parameter must be the cookie for an `Arc<F>` and
195+ /// the owner must give up a ref-count to it.
177196 unsafe extern "C" fn cookie_decr_refcount < F > ( cookie : * mut c_void )
178197 where
179198 F : Fn ( & str ) -> Option < ConnectionInfo > + Send + Sync + ' static ,
@@ -185,6 +204,10 @@ impl Accessor {
185204
186205impl Drop for Accessor {
187206 fn drop ( & mut self ) {
207+ if self . accessor . is_null ( ) {
208+ // This Accessor was already released.
209+ return ;
210+ }
188211 // Safety: `self.accessor` is always a valid, owned
189212 // `ABinderRpc_Accessor` pointer returned by
190213 // `ABinderRpc_Accessor_new` when `self` was created. This delete
@@ -218,3 +241,140 @@ pub fn delegate_accessor(name: &str, mut binder: SpIBinder) -> Result<SpIBinder>
218241 // point, so can be safely passed to `SpIBinder::from_raw`.
219242 Ok ( unsafe { SpIBinder :: from_raw ( delegator) . expect ( "Expected valid binder at this point" ) } )
220243}
244+
245+ /// Rust wrapper around ABinderRpc_AccessorProvider objects for RPC binder service management.
246+ ///
247+ /// Dropping the `AccessorProvider` will drop/unregister the underlying object.
248+ #[ derive( Debug ) ]
249+ pub struct AccessorProvider {
250+ accessor_provider : * mut sys:: ABinderRpc_AccessorProvider ,
251+ }
252+
253+ /// Safety: A `AccessorProvider` is a wrapper around `ABinderRpc_AccessorProvider` which is
254+ /// `Sync` and `Send`. As
255+ /// `ABinderRpc_AccessorProvider` is threadsafe, this structure is too.
256+ /// The Fn owned the AccessorProvider has `Sync` and `Send` properties
257+ unsafe impl Send for AccessorProvider { }
258+
259+ /// Safety: A `AccessorProvider` is a wrapper around `ABinderRpc_AccessorProvider` which is
260+ /// `Sync` and `Send`. As `ABinderRpc_AccessorProvider` is threadsafe, this structure is too.
261+ /// The Fn owned the AccessorProvider has `Sync` and `Send` properties
262+ unsafe impl Sync for AccessorProvider { }
263+
264+ impl AccessorProvider {
265+ /// Create a new `AccessorProvider` that will give libbinder `Accessors` in order to
266+ /// connect to binder services over sockets.
267+ ///
268+ /// `instances` is a list of all instances that this `AccessorProvider` is responsible for.
269+ /// It is declaring these instances as available to this process and will return
270+ /// `Accessor` objects for them when libbinder calls the `provider` callback.
271+ /// `provider` is the callback that libbinder will call when a service is being requested.
272+ /// The callback takes a `&str` argument representing the service that is being requested.
273+ /// See the `ABinderRpc_AccessorProvider_getAccessorCallback` for the C++ equivalent.
274+ pub fn new < F > ( instances : & [ String ] , provider : F ) -> Option < AccessorProvider >
275+ where
276+ F : Fn ( & str ) -> Option < Accessor > + Send + Sync + ' static ,
277+ {
278+ let callback: * mut c_void = Arc :: into_raw ( Arc :: new ( provider) ) as * mut c_void ;
279+ let c_str_instances: Vec < CString > =
280+ instances. iter ( ) . map ( |s| CString :: new ( s. as_bytes ( ) ) . unwrap ( ) ) . collect ( ) ;
281+ let mut c_instances: Vec < * const c_char > =
282+ c_str_instances. iter ( ) . map ( |s| s. as_ptr ( ) ) . collect ( ) ;
283+ let num_instances: usize = c_instances. len ( ) ;
284+ // Safety:
285+ // - The function pointer for the first argument is a valid `get_accessor` callback.
286+ // - This call returns an owned `ABinderRpc_AccessorProvider` pointer which
287+ // must be destroyed via `ABinderRpc_unregisterAccessorProvider` when no longer
288+ // needed.
289+ // - When the underlying ABinderRpc_AccessorProvider is deleted, it will call
290+ // the `cookie_decr_refcount` callback on the `callback` pointer to release its
291+ // strong ref.
292+ // - The `c_instances` vector is not modified by the function
293+ let accessor_provider = unsafe {
294+ sys:: ABinderRpc_registerAccessorProvider (
295+ Some ( Self :: get_accessor :: < F > ) ,
296+ c_instances. as_mut_ptr ( ) ,
297+ num_instances,
298+ callback,
299+ Some ( Self :: accessor_cookie_decr_refcount :: < F > ) ,
300+ )
301+ } ;
302+
303+ if accessor_provider. is_null ( ) {
304+ return None ;
305+ }
306+ Some ( AccessorProvider { accessor_provider } )
307+ }
308+
309+ /// Callback invoked from C++ when an Accessor is needed.
310+ ///
311+ /// # Safety
312+ ///
313+ /// - libbinder guarantees the `instance` argument is a valid C string if it's not null.
314+ /// - The `cookie` pointer is same pointer that we pass to ABinderRpc_registerAccessorProvider
315+ /// in AccessorProvider.new() which is the closure that we will delete with
316+ /// self.accessor_cookie_decr_refcount when unregistering the AccessorProvider.
317+ unsafe extern "C" fn get_accessor < F > (
318+ instance : * const c_char ,
319+ cookie : * mut c_void ,
320+ ) -> * mut binder_ndk_sys:: ABinderRpc_Accessor
321+ where
322+ F : Fn ( & str ) -> Option < Accessor > + Send + Sync + ' static ,
323+ {
324+ if cookie. is_null ( ) || instance. is_null ( ) {
325+ log:: error!( "Cookie({cookie:p}) or instance({instance:p}) is null!" ) ;
326+ return ptr:: null_mut ( ) ;
327+ }
328+ // Safety: The caller promises that `cookie` is for an Arc<F>.
329+ let callback = unsafe { ( cookie as * const F ) . as_ref ( ) . unwrap ( ) } ;
330+
331+ let inst = {
332+ // Safety: The caller in libbinder_ndk will have already verified this is a valid
333+ // C string
334+ match unsafe { CStr :: from_ptr ( instance) } . to_str ( ) {
335+ Ok ( s) => s,
336+ Err ( err) => {
337+ log:: error!( "Failed to get a valid C string! {err:?}" ) ;
338+ return ptr:: null_mut ( ) ;
339+ }
340+ }
341+ } ;
342+
343+ match callback ( inst) {
344+ Some ( a) => {
345+ // Safety: This is giving up ownership of this ABinderRpc_Accessor
346+ // to the caller of this function (libbinder) and it is responsible
347+ // for deleting it.
348+ unsafe { a. release ( ) }
349+ }
350+ None => ptr:: null_mut ( ) ,
351+ }
352+ }
353+
354+ /// Callback that decrements the ref-count.
355+ /// This is invoked from C++ when the provider is unregistered.
356+ ///
357+ /// # Safety
358+ ///
359+ /// - The `cookie` parameter must be the cookie for an `Arc<F>` and
360+ /// the owner must give up a ref-count to it.
361+ unsafe extern "C" fn accessor_cookie_decr_refcount < F > ( cookie : * mut c_void )
362+ where
363+ F : Fn ( & str ) -> Option < Accessor > + Send + Sync + ' static ,
364+ {
365+ // Safety: The caller promises that `cookie` is for an Arc<F>.
366+ unsafe { Arc :: decrement_strong_count ( cookie as * const F ) } ;
367+ }
368+ }
369+
370+ impl Drop for AccessorProvider {
371+ fn drop ( & mut self ) {
372+ // Safety: `self.accessor_provider` is always a valid, owned
373+ // `ABinderRpc_AccessorProvider` pointer returned by
374+ // `ABinderRpc_registerAccessorProvider` when `self` was created. This delete
375+ // method can only be called once when `self` is dropped.
376+ unsafe {
377+ sys:: ABinderRpc_unregisterAccessorProvider ( self . accessor_provider ) ;
378+ }
379+ }
380+ }
0 commit comments