blob: 4a6d118f07200af8027bb96769c3a3a3cf9d67a5 [file] [log] [blame]
Stephen Crane2a3c2502020-06-16 17:48:35 -07001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//! Rust API for interacting with a remote binder service.
18
19use crate::binder::{
Andrew Walbran12400d82021-03-04 17:04:34 +000020 AsNative, FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Strong,
21 TransactionCode, TransactionFlags,
Stephen Crane2a3c2502020-06-16 17:48:35 -070022};
23use crate::error::{status_result, Result, StatusCode};
24use crate::parcel::{
25 Deserialize, DeserializeArray, DeserializeOption, Parcel, Serialize, SerializeArray,
26 SerializeOption,
27};
28use crate::sys;
29
Stephen Craneddb3e6d2020-12-18 13:27:22 -080030use std::cmp::Ordering;
Andrew Walbran12400d82021-03-04 17:04:34 +000031use std::convert::TryInto;
Stephen Crane2a3c2502020-06-16 17:48:35 -070032use std::ffi::{c_void, CString};
Andrei Homescu2e3c1472020-08-11 16:35:40 -070033use std::fmt;
Stephen Crane2a3c2502020-06-16 17:48:35 -070034use std::os::unix::io::AsRawFd;
35use std::ptr;
36
37/// A strong reference to a Binder remote object.
38///
39/// This struct encapsulates the generic C++ `sp<IBinder>` class. This wrapper
40/// is untyped; typed interface access is implemented by the AIDL compiler.
41pub struct SpIBinder(*mut sys::AIBinder);
42
Andrei Homescu2e3c1472020-08-11 16:35:40 -070043impl fmt::Debug for SpIBinder {
44 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
45 f.pad("SpIBinder")
46 }
47}
48
Stephen Crane2a3c2502020-06-16 17:48:35 -070049/// # Safety
50///
51/// An `SpIBinder` is a handle to a C++ IBinder, which is thread-safe
52unsafe impl Send for SpIBinder {}
53
54impl SpIBinder {
55 /// Create an `SpIBinder` wrapper object from a raw `AIBinder` pointer.
56 ///
57 /// # Safety
58 ///
59 /// This constructor is safe iff `ptr` is a null pointer or a valid pointer
60 /// to an `AIBinder`.
61 ///
62 /// In the non-null case, this method conceptually takes ownership of a strong
63 /// reference to the object, so `AIBinder_incStrong` must have been called
64 /// on the pointer before passing it to this constructor. This is generally
65 /// done by Binder NDK methods that return an `AIBinder`, but care should be
66 /// taken to ensure this invariant.
67 ///
68 /// All `SpIBinder` objects that are constructed will hold a valid pointer
69 /// to an `AIBinder`, which will remain valid for the entire lifetime of the
70 /// `SpIBinder` (we keep a strong reference, and only decrement on drop).
71 pub(crate) unsafe fn from_raw(ptr: *mut sys::AIBinder) -> Option<Self> {
72 ptr.as_mut().map(|p| Self(p))
73 }
74
Stephen Craned58bce02020-07-07 12:26:02 -070075 /// Extract a raw `AIBinder` pointer from this wrapper.
76 ///
77 /// This method should _only_ be used for testing. Do not try to use the NDK
78 /// interface directly for anything else.
79 ///
80 /// # Safety
81 ///
82 /// The resulting pointer is valid only as long as the SpIBinder is alive.
83 /// The SpIBinder object retains ownership of the AIBinder and the caller
84 /// should not attempt to free the returned pointer.
85 pub unsafe fn as_raw(&self) -> *mut sys::AIBinder {
86 self.0
87 }
88
Stephen Crane2a3c2502020-06-16 17:48:35 -070089 /// Return true if this binder object is hosted in a different process than
90 /// the current one.
91 pub fn is_remote(&self) -> bool {
92 unsafe {
93 // Safety: `SpIBinder` guarantees that it always contains a valid
94 // `AIBinder` pointer.
95 sys::AIBinder_isRemote(self.as_native())
96 }
97 }
98
99 /// Try to convert this Binder object into a trait object for the given
100 /// Binder interface.
101 ///
102 /// If this object does not implement the expected interface, the error
103 /// `StatusCode::BAD_TYPE` is returned.
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800104 pub fn into_interface<I: FromIBinder + Interface + ?Sized>(self) -> Result<Strong<I>> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700105 FromIBinder::try_from(self)
106 }
107
108 /// Return the interface class of this binder object, if associated with
109 /// one.
Stephen Crane669deb62020-09-10 17:31:39 -0700110 pub fn get_class(&mut self) -> Option<InterfaceClass> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700111 unsafe {
112 // Safety: `SpIBinder` guarantees that it always contains a valid
113 // `AIBinder` pointer. `AIBinder_getClass` returns either a null
114 // pointer or a valid pointer to an `AIBinder_Class`. After mapping
115 // null to None, we can safely construct an `InterfaceClass` if the
116 // pointer was non-null.
117 let class = sys::AIBinder_getClass(self.as_native_mut());
118 class.as_ref().map(|p| InterfaceClass::from_ptr(p))
119 }
120 }
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000121
122 /// Creates a new weak reference to this binder object.
123 pub fn downgrade(&mut self) -> WpIBinder {
124 WpIBinder::new(self)
125 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700126}
127
128/// An object that can be associate with an [`InterfaceClass`].
129pub trait AssociateClass {
130 /// Check if this object is a valid object for the given interface class
131 /// `I`.
132 ///
133 /// Returns `Some(self)` if this is a valid instance of the interface, and
134 /// `None` otherwise.
135 ///
136 /// Classes constructed by `InterfaceClass` are unique per type, so
137 /// repeatedly calling this method for the same `InterfaceClass` is allowed.
138 fn associate_class(&mut self, class: InterfaceClass) -> bool;
139}
140
141impl AssociateClass for SpIBinder {
142 fn associate_class(&mut self, class: InterfaceClass) -> bool {
143 unsafe {
144 // Safety: `SpIBinder` guarantees that it always contains a valid
145 // `AIBinder` pointer. An `InterfaceClass` can always be converted
146 // into a valid `AIBinder_Class` pointer, so these parameters are
147 // always safe.
148 sys::AIBinder_associateClass(self.as_native_mut(), class.into())
149 }
150 }
151}
152
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800153impl Ord for SpIBinder {
154 fn cmp(&self, other: &Self) -> Ordering {
155 let less_than = unsafe {
156 // Safety: SpIBinder always holds a valid `AIBinder` pointer, so
157 // this pointer is always safe to pass to `AIBinder_lt` (null is
158 // also safe to pass to this function, but we should never do that).
159 sys::AIBinder_lt(self.0, other.0)
160 };
161 let greater_than = unsafe {
162 // Safety: SpIBinder always holds a valid `AIBinder` pointer, so
163 // this pointer is always safe to pass to `AIBinder_lt` (null is
164 // also safe to pass to this function, but we should never do that).
165 sys::AIBinder_lt(other.0, self.0)
166 };
167 if !less_than && !greater_than {
168 Ordering::Equal
169 } else if less_than {
170 Ordering::Less
171 } else {
172 Ordering::Greater
173 }
174 }
175}
176
177impl PartialOrd for SpIBinder {
178 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
179 Some(self.cmp(other))
180 }
181}
182
Stephen Crane994a0f02020-08-11 14:47:29 -0700183impl PartialEq for SpIBinder {
184 fn eq(&self, other: &Self) -> bool {
185 ptr::eq(self.0, other.0)
186 }
187}
188
189impl Eq for SpIBinder {}
190
Stephen Crane2a3c2502020-06-16 17:48:35 -0700191impl Clone for SpIBinder {
192 fn clone(&self) -> Self {
193 unsafe {
194 // Safety: Cloning a strong reference must increment the reference
195 // count. We are guaranteed by the `SpIBinder` constructor
196 // invariants that `self.0` is always a valid `AIBinder` pointer.
197 sys::AIBinder_incStrong(self.0);
198 }
199 Self(self.0)
200 }
201}
202
203impl Drop for SpIBinder {
204 // We hold a strong reference to the IBinder in SpIBinder and need to give up
205 // this reference on drop.
206 fn drop(&mut self) {
207 unsafe {
208 // Safety: SpIBinder always holds a valid `AIBinder` pointer, so we
209 // know this pointer is safe to pass to `AIBinder_decStrong` here.
210 sys::AIBinder_decStrong(self.as_native_mut());
211 }
212 }
213}
214
Andrew Walbran12400d82021-03-04 17:04:34 +0000215impl<T: AsNative<sys::AIBinder>> IBinderInternal for T {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700216 /// Perform a binder transaction
217 fn transact<F: FnOnce(&mut Parcel) -> Result<()>>(
218 &self,
219 code: TransactionCode,
220 flags: TransactionFlags,
221 input_callback: F,
222 ) -> Result<Parcel> {
223 let mut input = ptr::null_mut();
224 let status = unsafe {
225 // Safety: `SpIBinder` guarantees that `self` always contains a
226 // valid pointer to an `AIBinder`. It is safe to cast from an
227 // immutable pointer to a mutable pointer here, because
228 // `AIBinder_prepareTransaction` only calls immutable `AIBinder`
229 // methods but the parameter is unfortunately not marked as const.
230 //
231 // After the call, input will be either a valid, owned `AParcel`
232 // pointer, or null.
233 sys::AIBinder_prepareTransaction(self.as_native() as *mut sys::AIBinder, &mut input)
234 };
235 status_result(status)?;
236 let mut input = unsafe {
237 // Safety: At this point, `input` is either a valid, owned `AParcel`
238 // pointer, or null. `Parcel::owned` safely handles both cases,
239 // taking ownership of the parcel.
240 Parcel::owned(input).ok_or(StatusCode::UNEXPECTED_NULL)?
241 };
242 input_callback(&mut input)?;
243 let mut reply = ptr::null_mut();
244 let status = unsafe {
245 // Safety: `SpIBinder` guarantees that `self` always contains a
246 // valid pointer to an `AIBinder`. Although `IBinder::transact` is
247 // not a const method, it is still safe to cast our immutable
248 // pointer to mutable for the call. First, `IBinder::transact` is
249 // thread-safe, so concurrency is not an issue. The only way that
250 // `transact` can affect any visible, mutable state in the current
251 // process is by calling `onTransact` for a local service. However,
252 // in order for transactions to be thread-safe, this method must
253 // dynamically lock its data before modifying it. We enforce this
254 // property in Rust by requiring `Sync` for remotable objects and
255 // only providing `on_transact` with an immutable reference to
256 // `self`.
257 //
258 // This call takes ownership of the `input` parcel pointer, and
259 // passes ownership of the `reply` out parameter to its caller. It
260 // does not affect ownership of the `binder` parameter.
261 sys::AIBinder_transact(
262 self.as_native() as *mut sys::AIBinder,
263 code,
264 &mut input.into_raw(),
265 &mut reply,
266 flags,
267 )
268 };
269 status_result(status)?;
270
271 unsafe {
272 // Safety: `reply` is either a valid `AParcel` pointer or null
273 // after the call to `AIBinder_transact` above, so we can
274 // construct a `Parcel` out of it. `AIBinder_transact` passes
275 // ownership of the `reply` parcel to Rust, so we need to
276 // construct an owned variant. `Parcel::owned` takes ownership
277 // of the parcel pointer.
278 Parcel::owned(reply).ok_or(StatusCode::UNEXPECTED_NULL)
279 }
280 }
281
282 fn is_binder_alive(&self) -> bool {
283 unsafe {
284 // Safety: `SpIBinder` guarantees that `self` always contains a
285 // valid pointer to an `AIBinder`.
286 //
287 // This call does not affect ownership of its pointer parameter.
288 sys::AIBinder_isAlive(self.as_native())
289 }
290 }
291
292 fn ping_binder(&mut self) -> Result<()> {
293 let status = unsafe {
294 // Safety: `SpIBinder` guarantees that `self` always contains a
295 // valid pointer to an `AIBinder`.
296 //
297 // This call does not affect ownership of its pointer parameter.
298 sys::AIBinder_ping(self.as_native_mut())
299 };
300 status_result(status)
301 }
302
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700303 fn set_requesting_sid(&mut self, enable: bool) {
Andrew Walbran12400d82021-03-04 17:04:34 +0000304 unsafe { sys::AIBinder_setRequestingSid(self.as_native_mut(), enable) };
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700305 }
306
Stephen Crane2a3c2502020-06-16 17:48:35 -0700307 fn dump<F: AsRawFd>(&mut self, fp: &F, args: &[&str]) -> Result<()> {
308 let args: Vec<_> = args.iter().map(|a| CString::new(*a).unwrap()).collect();
309 let mut arg_ptrs: Vec<_> = args.iter().map(|a| a.as_ptr()).collect();
310 let status = unsafe {
311 // Safety: `SpIBinder` guarantees that `self` always contains a
312 // valid pointer to an `AIBinder`. `AsRawFd` guarantees that the
313 // file descriptor parameter is always be a valid open file. The
314 // `args` pointer parameter is a valid pointer to an array of C
315 // strings that will outlive the call since `args` lives for the
316 // whole function scope.
317 //
318 // This call does not affect ownership of its binder pointer
319 // parameter and does not take ownership of the file or args array
320 // parameters.
321 sys::AIBinder_dump(
322 self.as_native_mut(),
323 fp.as_raw_fd(),
324 arg_ptrs.as_mut_ptr(),
325 arg_ptrs.len().try_into().unwrap(),
326 )
327 };
328 status_result(status)
329 }
330
331 fn get_extension(&mut self) -> Result<Option<SpIBinder>> {
332 let mut out = ptr::null_mut();
333 let status = unsafe {
334 // Safety: `SpIBinder` guarantees that `self` always contains a
335 // valid pointer to an `AIBinder`. After this call, the `out`
336 // parameter will be either null, or a valid pointer to an
337 // `AIBinder`.
338 //
339 // This call passes ownership of the out pointer to its caller
340 // (assuming it is set to a non-null value).
341 sys::AIBinder_getExtension(self.as_native_mut(), &mut out)
342 };
343 let ibinder = unsafe {
344 // Safety: The call above guarantees that `out` is either null or a
345 // valid, owned pointer to an `AIBinder`, both of which are safe to
346 // pass to `SpIBinder::from_raw`.
347 SpIBinder::from_raw(out)
348 };
349
350 status_result(status)?;
351 Ok(ibinder)
352 }
Andrew Walbran12400d82021-03-04 17:04:34 +0000353}
Stephen Crane2a3c2502020-06-16 17:48:35 -0700354
Andrew Walbran12400d82021-03-04 17:04:34 +0000355impl<T: AsNative<sys::AIBinder>> IBinder for T {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700356 fn link_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> {
357 status_result(unsafe {
358 // Safety: `SpIBinder` guarantees that `self` always contains a
359 // valid pointer to an `AIBinder`. `recipient` can always be
360 // converted into a valid pointer to an
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800361 // `AIBinder_DeathRecipient`. Any value is safe to pass as the
Stephen Crane2a3c2502020-06-16 17:48:35 -0700362 // cookie, although we depend on this value being set by
363 // `get_cookie` when the death recipient callback is called.
364 sys::AIBinder_linkToDeath(
365 self.as_native_mut(),
366 recipient.as_native_mut(),
367 recipient.get_cookie(),
368 )
369 })
370 }
371
372 fn unlink_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> {
373 status_result(unsafe {
374 // Safety: `SpIBinder` guarantees that `self` always contains a
375 // valid pointer to an `AIBinder`. `recipient` can always be
376 // converted into a valid pointer to an
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800377 // `AIBinder_DeathRecipient`. Any value is safe to pass as the
Stephen Crane2a3c2502020-06-16 17:48:35 -0700378 // cookie, although we depend on this value being set by
379 // `get_cookie` when the death recipient callback is called.
380 sys::AIBinder_unlinkToDeath(
381 self.as_native_mut(),
382 recipient.as_native_mut(),
383 recipient.get_cookie(),
384 )
385 })
386 }
387}
388
389impl Serialize for SpIBinder {
390 fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
391 parcel.write_binder(Some(self))
392 }
393}
394
395impl SerializeOption for SpIBinder {
396 fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
397 parcel.write_binder(this)
398 }
399}
400
401impl SerializeArray for SpIBinder {}
402impl SerializeArray for Option<&SpIBinder> {}
403
404impl Deserialize for SpIBinder {
405 fn deserialize(parcel: &Parcel) -> Result<SpIBinder> {
Andrei Homescu32814372020-08-20 15:36:08 -0700406 parcel
407 .read_binder()
408 .transpose()
409 .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
Stephen Crane2a3c2502020-06-16 17:48:35 -0700410 }
411}
412
413impl DeserializeOption for SpIBinder {
414 fn deserialize_option(parcel: &Parcel) -> Result<Option<SpIBinder>> {
415 parcel.read_binder()
416 }
417}
418
419impl DeserializeArray for SpIBinder {}
420impl DeserializeArray for Option<SpIBinder> {}
421
422/// A weak reference to a Binder remote object.
423///
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000424/// This struct encapsulates the generic C++ `wp<IBinder>` class. This wrapper
425/// is untyped; typed interface access is implemented by the AIDL compiler.
Stephen Crane2a3c2502020-06-16 17:48:35 -0700426pub struct WpIBinder(*mut sys::AIBinder_Weak);
427
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000428impl fmt::Debug for WpIBinder {
429 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
430 f.pad("WpIBinder")
431 }
432}
433
434/// # Safety
435///
436/// A `WpIBinder` is a handle to a C++ IBinder, which is thread-safe.
437unsafe impl Send for WpIBinder {}
438
Stephen Crane2a3c2502020-06-16 17:48:35 -0700439impl WpIBinder {
440 /// Create a new weak reference from an object that can be converted into a
441 /// raw `AIBinder` pointer.
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000442 fn new<B: AsNative<sys::AIBinder>>(binder: &mut B) -> WpIBinder {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700443 let ptr = unsafe {
444 // Safety: `SpIBinder` guarantees that `binder` always contains a
445 // valid pointer to an `AIBinder`.
446 sys::AIBinder_Weak_new(binder.as_native_mut())
447 };
448 assert!(!ptr.is_null());
449 Self(ptr)
450 }
Stephen Crane994a0f02020-08-11 14:47:29 -0700451
452 /// Promote this weak reference to a strong reference to the binder object.
453 pub fn promote(&self) -> Option<SpIBinder> {
454 unsafe {
455 // Safety: `WpIBinder` always contains a valid weak reference, so we
456 // can pass this pointer to `AIBinder_Weak_promote`. Returns either
457 // null or an AIBinder owned by the caller, both of which are valid
458 // to pass to `SpIBinder::from_raw`.
459 let ptr = sys::AIBinder_Weak_promote(self.0);
460 SpIBinder::from_raw(ptr)
461 }
462 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700463}
464
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800465impl Clone for WpIBinder {
466 fn clone(&self) -> Self {
467 let ptr = unsafe {
468 // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
469 // so this pointer is always safe to pass to `AIBinder_Weak_clone`
470 // (although null is also a safe value to pass to this API).
471 //
472 // We get ownership of the returned pointer, so can construct a new
473 // WpIBinder object from it.
474 sys::AIBinder_Weak_clone(self.0)
475 };
Andrew Walbran12400d82021-03-04 17:04:34 +0000476 assert!(
477 !ptr.is_null(),
478 "Unexpected null pointer from AIBinder_Weak_clone"
479 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800480 Self(ptr)
481 }
482}
483
484impl Ord for WpIBinder {
485 fn cmp(&self, other: &Self) -> Ordering {
486 let less_than = unsafe {
487 // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
488 // so this pointer is always safe to pass to `AIBinder_Weak_lt`
489 // (null is also safe to pass to this function, but we should never
490 // do that).
491 sys::AIBinder_Weak_lt(self.0, other.0)
492 };
493 let greater_than = unsafe {
494 // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
495 // so this pointer is always safe to pass to `AIBinder_Weak_lt`
496 // (null is also safe to pass to this function, but we should never
497 // do that).
498 sys::AIBinder_Weak_lt(other.0, self.0)
499 };
500 if !less_than && !greater_than {
501 Ordering::Equal
502 } else if less_than {
503 Ordering::Less
504 } else {
505 Ordering::Greater
506 }
507 }
508}
509
510impl PartialOrd for WpIBinder {
511 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
512 Some(self.cmp(other))
513 }
514}
515
516impl PartialEq for WpIBinder {
517 fn eq(&self, other: &Self) -> bool {
518 self.cmp(other) == Ordering::Equal
519 }
520}
521
522impl Eq for WpIBinder {}
523
Andrew Walbran5e8dfa32020-12-16 12:50:06 +0000524impl Drop for WpIBinder {
525 fn drop(&mut self) {
526 unsafe {
527 // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, so we
528 // know this pointer is safe to pass to `AIBinder_Weak_delete` here.
529 sys::AIBinder_Weak_delete(self.0);
530 }
531 }
532}
533
Stephen Crane2a3c2502020-06-16 17:48:35 -0700534/// Rust wrapper around DeathRecipient objects.
535#[repr(C)]
536pub struct DeathRecipient {
537 recipient: *mut sys::AIBinder_DeathRecipient,
538 callback: Box<dyn Fn() + Send + 'static>,
539}
540
541impl DeathRecipient {
542 /// Create a new death recipient that will call the given callback when its
543 /// associated object dies.
544 pub fn new<F>(callback: F) -> DeathRecipient
545 where
546 F: Fn() + Send + 'static,
547 {
548 let callback = Box::new(callback);
549 let recipient = unsafe {
550 // Safety: The function pointer is a valid death recipient callback.
551 //
552 // This call returns an owned `AIBinder_DeathRecipient` pointer
553 // which must be destroyed via `AIBinder_DeathRecipient_delete` when
554 // no longer needed.
555 sys::AIBinder_DeathRecipient_new(Some(Self::binder_died::<F>))
556 };
557 DeathRecipient {
558 recipient,
559 callback,
560 }
561 }
562
563 /// Get the opaque cookie that identifies this death recipient.
564 ///
565 /// This cookie will be used to link and unlink this death recipient to a
566 /// binder object and will be passed to the `binder_died` callback as an
567 /// opaque userdata pointer.
568 fn get_cookie(&self) -> *mut c_void {
569 &*self.callback as *const _ as *mut c_void
570 }
571
572 /// Callback invoked from C++ when the binder object dies.
573 ///
574 /// # Safety
575 ///
576 /// The `cookie` parameter must have been created with the `get_cookie`
577 /// method of this object.
578 unsafe extern "C" fn binder_died<F>(cookie: *mut c_void)
579 where
580 F: Fn() + Send + 'static,
581 {
582 let callback = (cookie as *mut F).as_ref().unwrap();
583 callback();
584 }
585}
586
587/// # Safety
588///
589/// A `DeathRecipient` is always constructed with a valid raw pointer to an
590/// `AIBinder_DeathRecipient`, so it is always type-safe to extract this
591/// pointer.
592unsafe impl AsNative<sys::AIBinder_DeathRecipient> for DeathRecipient {
593 fn as_native(&self) -> *const sys::AIBinder_DeathRecipient {
594 self.recipient
595 }
596
597 fn as_native_mut(&mut self) -> *mut sys::AIBinder_DeathRecipient {
598 self.recipient
599 }
600}
601
602impl Drop for DeathRecipient {
603 fn drop(&mut self) {
604 unsafe {
605 // Safety: `self.recipient` is always a valid, owned
606 // `AIBinder_DeathRecipient` pointer returned by
607 // `AIBinder_DeathRecipient_new` when `self` was created. This
608 // delete method can only be called once when `self` is dropped.
609 sys::AIBinder_DeathRecipient_delete(self.recipient);
610 }
611 }
612}
613
614/// Generic interface to remote binder objects.
615///
616/// Corresponds to the C++ `BpInterface` class.
617pub trait Proxy: Sized + Interface {
618 /// The Binder interface descriptor string.
619 ///
620 /// This string is a unique identifier for a Binder interface, and should be
621 /// the same between all implementations of that interface.
622 fn get_descriptor() -> &'static str;
623
624 /// Create a new interface from the given proxy, if it matches the expected
625 /// type of this interface.
626 fn from_binder(binder: SpIBinder) -> Result<Self>;
627}
628
629/// # Safety
630///
631/// This is a convenience method that wraps `AsNative` for `SpIBinder` to allow
632/// invocation of `IBinder` methods directly from `Interface` objects. It shares
633/// the same safety as the implementation for `SpIBinder`.
634unsafe impl<T: Proxy> AsNative<sys::AIBinder> for T {
635 fn as_native(&self) -> *const sys::AIBinder {
636 self.as_binder().as_native()
637 }
638
639 fn as_native_mut(&mut self) -> *mut sys::AIBinder {
640 self.as_binder().as_native_mut()
641 }
642}
643
644/// Retrieve an existing service, blocking for a few seconds if it doesn't yet
645/// exist.
646pub fn get_service(name: &str) -> Option<SpIBinder> {
647 let name = CString::new(name).ok()?;
648 unsafe {
649 // Safety: `AServiceManager_getService` returns either a null pointer or
650 // a valid pointer to an owned `AIBinder`. Either of these values is
651 // safe to pass to `SpIBinder::from_raw`.
652 SpIBinder::from_raw(sys::AServiceManager_getService(name.as_ptr()))
653 }
654}
655
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000656/// Retrieve an existing service, or start it if it is configured as a dynamic
657/// service and isn't yet started.
658pub fn wait_for_service(name: &str) -> Option<SpIBinder> {
659 let name = CString::new(name).ok()?;
660 unsafe {
661 // Safety: `AServiceManager_waitforService` returns either a null
662 // pointer or a valid pointer to an owned `AIBinder`. Either of these
663 // values is safe to pass to `SpIBinder::from_raw`.
664 SpIBinder::from_raw(sys::AServiceManager_waitForService(name.as_ptr()))
665 }
666}
667
Stephen Crane2a3c2502020-06-16 17:48:35 -0700668/// Retrieve an existing service for a particular interface, blocking for a few
669/// seconds if it doesn't yet exist.
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800670pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700671 let service = get_service(name);
672 match service {
673 Some(service) => FromIBinder::try_from(service),
674 None => Err(StatusCode::NAME_NOT_FOUND),
675 }
676}
677
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000678/// Retrieve an existing service for a particular interface, or start it if it
679/// is configured as a dynamic service and isn't yet started.
680pub fn wait_for_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
681 let service = wait_for_service(name);
682 match service {
683 Some(service) => FromIBinder::try_from(service),
684 None => Err(StatusCode::NAME_NOT_FOUND),
685 }
686}
687
Stephen Crane2a3c2502020-06-16 17:48:35 -0700688/// # Safety
689///
690/// `SpIBinder` guarantees that `binder` always contains a valid pointer to an
691/// `AIBinder`, so we can trivially extract this pointer here.
692unsafe impl AsNative<sys::AIBinder> for SpIBinder {
693 fn as_native(&self) -> *const sys::AIBinder {
694 self.0
695 }
696
697 fn as_native_mut(&mut self) -> *mut sys::AIBinder {
698 self.0
699 }
700}