blob: e299963c9dece66131089a35792b7a3054c753b8 [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
Victor Hsiehd35d31d2021-06-03 11:24:31 -0700128pub mod unstable_api {
129 use super::{sys, SpIBinder};
130
131 /// A temporary API to allow the client to create a `SpIBinder` from a `sys::AIBinder`. This is
132 /// needed to bridge RPC binder, which doesn't have Rust API yet.
133 /// TODO(b/184872979): remove once the Rust API is created.
134 ///
135 /// # Safety
136 ///
137 /// See `SpIBinder::from_raw`.
138 pub unsafe fn new_spibinder(ptr: *mut sys::AIBinder) -> Option<SpIBinder> {
139 SpIBinder::from_raw(ptr)
140 }
141}
142
Stephen Crane2a3c2502020-06-16 17:48:35 -0700143/// An object that can be associate with an [`InterfaceClass`].
144pub trait AssociateClass {
145 /// Check if this object is a valid object for the given interface class
146 /// `I`.
147 ///
148 /// Returns `Some(self)` if this is a valid instance of the interface, and
149 /// `None` otherwise.
150 ///
151 /// Classes constructed by `InterfaceClass` are unique per type, so
152 /// repeatedly calling this method for the same `InterfaceClass` is allowed.
153 fn associate_class(&mut self, class: InterfaceClass) -> bool;
154}
155
156impl AssociateClass for SpIBinder {
157 fn associate_class(&mut self, class: InterfaceClass) -> bool {
158 unsafe {
159 // Safety: `SpIBinder` guarantees that it always contains a valid
160 // `AIBinder` pointer. An `InterfaceClass` can always be converted
161 // into a valid `AIBinder_Class` pointer, so these parameters are
162 // always safe.
163 sys::AIBinder_associateClass(self.as_native_mut(), class.into())
164 }
165 }
166}
167
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800168impl Ord for SpIBinder {
169 fn cmp(&self, other: &Self) -> Ordering {
170 let less_than = unsafe {
171 // Safety: SpIBinder always holds a valid `AIBinder` pointer, so
172 // this pointer is always safe to pass to `AIBinder_lt` (null is
173 // also safe to pass to this function, but we should never do that).
174 sys::AIBinder_lt(self.0, other.0)
175 };
176 let greater_than = unsafe {
177 // Safety: SpIBinder always holds a valid `AIBinder` pointer, so
178 // this pointer is always safe to pass to `AIBinder_lt` (null is
179 // also safe to pass to this function, but we should never do that).
180 sys::AIBinder_lt(other.0, self.0)
181 };
182 if !less_than && !greater_than {
183 Ordering::Equal
184 } else if less_than {
185 Ordering::Less
186 } else {
187 Ordering::Greater
188 }
189 }
190}
191
192impl PartialOrd for SpIBinder {
193 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
194 Some(self.cmp(other))
195 }
196}
197
Stephen Crane994a0f02020-08-11 14:47:29 -0700198impl PartialEq for SpIBinder {
199 fn eq(&self, other: &Self) -> bool {
200 ptr::eq(self.0, other.0)
201 }
202}
203
204impl Eq for SpIBinder {}
205
Stephen Crane2a3c2502020-06-16 17:48:35 -0700206impl Clone for SpIBinder {
207 fn clone(&self) -> Self {
208 unsafe {
209 // Safety: Cloning a strong reference must increment the reference
210 // count. We are guaranteed by the `SpIBinder` constructor
211 // invariants that `self.0` is always a valid `AIBinder` pointer.
212 sys::AIBinder_incStrong(self.0);
213 }
214 Self(self.0)
215 }
216}
217
218impl Drop for SpIBinder {
219 // We hold a strong reference to the IBinder in SpIBinder and need to give up
220 // this reference on drop.
221 fn drop(&mut self) {
222 unsafe {
223 // Safety: SpIBinder always holds a valid `AIBinder` pointer, so we
224 // know this pointer is safe to pass to `AIBinder_decStrong` here.
225 sys::AIBinder_decStrong(self.as_native_mut());
226 }
227 }
228}
229
Andrew Walbran12400d82021-03-04 17:04:34 +0000230impl<T: AsNative<sys::AIBinder>> IBinderInternal for T {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700231 /// Perform a binder transaction
232 fn transact<F: FnOnce(&mut Parcel) -> Result<()>>(
233 &self,
234 code: TransactionCode,
235 flags: TransactionFlags,
236 input_callback: F,
237 ) -> Result<Parcel> {
238 let mut input = ptr::null_mut();
239 let status = unsafe {
240 // Safety: `SpIBinder` guarantees that `self` always contains a
241 // valid pointer to an `AIBinder`. It is safe to cast from an
242 // immutable pointer to a mutable pointer here, because
243 // `AIBinder_prepareTransaction` only calls immutable `AIBinder`
244 // methods but the parameter is unfortunately not marked as const.
245 //
246 // After the call, input will be either a valid, owned `AParcel`
247 // pointer, or null.
248 sys::AIBinder_prepareTransaction(self.as_native() as *mut sys::AIBinder, &mut input)
249 };
250 status_result(status)?;
251 let mut input = unsafe {
252 // Safety: At this point, `input` is either a valid, owned `AParcel`
253 // pointer, or null. `Parcel::owned` safely handles both cases,
254 // taking ownership of the parcel.
255 Parcel::owned(input).ok_or(StatusCode::UNEXPECTED_NULL)?
256 };
257 input_callback(&mut input)?;
258 let mut reply = ptr::null_mut();
259 let status = unsafe {
260 // Safety: `SpIBinder` guarantees that `self` always contains a
261 // valid pointer to an `AIBinder`. Although `IBinder::transact` is
262 // not a const method, it is still safe to cast our immutable
263 // pointer to mutable for the call. First, `IBinder::transact` is
264 // thread-safe, so concurrency is not an issue. The only way that
265 // `transact` can affect any visible, mutable state in the current
266 // process is by calling `onTransact` for a local service. However,
267 // in order for transactions to be thread-safe, this method must
268 // dynamically lock its data before modifying it. We enforce this
269 // property in Rust by requiring `Sync` for remotable objects and
270 // only providing `on_transact` with an immutable reference to
271 // `self`.
272 //
273 // This call takes ownership of the `input` parcel pointer, and
274 // passes ownership of the `reply` out parameter to its caller. It
275 // does not affect ownership of the `binder` parameter.
276 sys::AIBinder_transact(
277 self.as_native() as *mut sys::AIBinder,
278 code,
279 &mut input.into_raw(),
280 &mut reply,
281 flags,
282 )
283 };
284 status_result(status)?;
285
286 unsafe {
287 // Safety: `reply` is either a valid `AParcel` pointer or null
288 // after the call to `AIBinder_transact` above, so we can
289 // construct a `Parcel` out of it. `AIBinder_transact` passes
290 // ownership of the `reply` parcel to Rust, so we need to
291 // construct an owned variant. `Parcel::owned` takes ownership
292 // of the parcel pointer.
293 Parcel::owned(reply).ok_or(StatusCode::UNEXPECTED_NULL)
294 }
295 }
296
297 fn is_binder_alive(&self) -> bool {
298 unsafe {
299 // Safety: `SpIBinder` guarantees that `self` always contains a
300 // valid pointer to an `AIBinder`.
301 //
302 // This call does not affect ownership of its pointer parameter.
303 sys::AIBinder_isAlive(self.as_native())
304 }
305 }
306
307 fn ping_binder(&mut self) -> Result<()> {
308 let status = unsafe {
309 // Safety: `SpIBinder` guarantees that `self` always contains a
310 // valid pointer to an `AIBinder`.
311 //
312 // This call does not affect ownership of its pointer parameter.
313 sys::AIBinder_ping(self.as_native_mut())
314 };
315 status_result(status)
316 }
317
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700318 fn set_requesting_sid(&mut self, enable: bool) {
Andrew Walbran12400d82021-03-04 17:04:34 +0000319 unsafe { sys::AIBinder_setRequestingSid(self.as_native_mut(), enable) };
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700320 }
321
Stephen Crane2a3c2502020-06-16 17:48:35 -0700322 fn dump<F: AsRawFd>(&mut self, fp: &F, args: &[&str]) -> Result<()> {
323 let args: Vec<_> = args.iter().map(|a| CString::new(*a).unwrap()).collect();
324 let mut arg_ptrs: Vec<_> = args.iter().map(|a| a.as_ptr()).collect();
325 let status = unsafe {
326 // Safety: `SpIBinder` guarantees that `self` always contains a
327 // valid pointer to an `AIBinder`. `AsRawFd` guarantees that the
328 // file descriptor parameter is always be a valid open file. The
329 // `args` pointer parameter is a valid pointer to an array of C
330 // strings that will outlive the call since `args` lives for the
331 // whole function scope.
332 //
333 // This call does not affect ownership of its binder pointer
334 // parameter and does not take ownership of the file or args array
335 // parameters.
336 sys::AIBinder_dump(
337 self.as_native_mut(),
338 fp.as_raw_fd(),
339 arg_ptrs.as_mut_ptr(),
340 arg_ptrs.len().try_into().unwrap(),
341 )
342 };
343 status_result(status)
344 }
345
346 fn get_extension(&mut self) -> Result<Option<SpIBinder>> {
347 let mut out = ptr::null_mut();
348 let status = unsafe {
349 // Safety: `SpIBinder` guarantees that `self` always contains a
350 // valid pointer to an `AIBinder`. After this call, the `out`
351 // parameter will be either null, or a valid pointer to an
352 // `AIBinder`.
353 //
354 // This call passes ownership of the out pointer to its caller
355 // (assuming it is set to a non-null value).
356 sys::AIBinder_getExtension(self.as_native_mut(), &mut out)
357 };
358 let ibinder = unsafe {
359 // Safety: The call above guarantees that `out` is either null or a
360 // valid, owned pointer to an `AIBinder`, both of which are safe to
361 // pass to `SpIBinder::from_raw`.
362 SpIBinder::from_raw(out)
363 };
364
365 status_result(status)?;
366 Ok(ibinder)
367 }
Andrew Walbran12400d82021-03-04 17:04:34 +0000368}
Stephen Crane2a3c2502020-06-16 17:48:35 -0700369
Andrew Walbran12400d82021-03-04 17:04:34 +0000370impl<T: AsNative<sys::AIBinder>> IBinder for T {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700371 fn link_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> {
372 status_result(unsafe {
373 // Safety: `SpIBinder` guarantees that `self` always contains a
374 // valid pointer to an `AIBinder`. `recipient` can always be
375 // converted into a valid pointer to an
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800376 // `AIBinder_DeathRecipient`. Any value is safe to pass as the
Stephen Crane2a3c2502020-06-16 17:48:35 -0700377 // cookie, although we depend on this value being set by
378 // `get_cookie` when the death recipient callback is called.
379 sys::AIBinder_linkToDeath(
380 self.as_native_mut(),
381 recipient.as_native_mut(),
382 recipient.get_cookie(),
383 )
384 })
385 }
386
387 fn unlink_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> {
388 status_result(unsafe {
389 // Safety: `SpIBinder` guarantees that `self` always contains a
390 // valid pointer to an `AIBinder`. `recipient` can always be
391 // converted into a valid pointer to an
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800392 // `AIBinder_DeathRecipient`. Any value is safe to pass as the
Stephen Crane2a3c2502020-06-16 17:48:35 -0700393 // cookie, although we depend on this value being set by
394 // `get_cookie` when the death recipient callback is called.
395 sys::AIBinder_unlinkToDeath(
396 self.as_native_mut(),
397 recipient.as_native_mut(),
398 recipient.get_cookie(),
399 )
400 })
401 }
402}
403
404impl Serialize for SpIBinder {
405 fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
406 parcel.write_binder(Some(self))
407 }
408}
409
410impl SerializeOption for SpIBinder {
411 fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
412 parcel.write_binder(this)
413 }
414}
415
416impl SerializeArray for SpIBinder {}
417impl SerializeArray for Option<&SpIBinder> {}
418
419impl Deserialize for SpIBinder {
420 fn deserialize(parcel: &Parcel) -> Result<SpIBinder> {
Andrei Homescu32814372020-08-20 15:36:08 -0700421 parcel
422 .read_binder()
423 .transpose()
424 .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
Stephen Crane2a3c2502020-06-16 17:48:35 -0700425 }
426}
427
428impl DeserializeOption for SpIBinder {
429 fn deserialize_option(parcel: &Parcel) -> Result<Option<SpIBinder>> {
430 parcel.read_binder()
431 }
432}
433
434impl DeserializeArray for SpIBinder {}
435impl DeserializeArray for Option<SpIBinder> {}
436
437/// A weak reference to a Binder remote object.
438///
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000439/// This struct encapsulates the generic C++ `wp<IBinder>` class. This wrapper
440/// is untyped; typed interface access is implemented by the AIDL compiler.
Stephen Crane2a3c2502020-06-16 17:48:35 -0700441pub struct WpIBinder(*mut sys::AIBinder_Weak);
442
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000443impl fmt::Debug for WpIBinder {
444 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
445 f.pad("WpIBinder")
446 }
447}
448
449/// # Safety
450///
451/// A `WpIBinder` is a handle to a C++ IBinder, which is thread-safe.
452unsafe impl Send for WpIBinder {}
453
Stephen Crane2a3c2502020-06-16 17:48:35 -0700454impl WpIBinder {
455 /// Create a new weak reference from an object that can be converted into a
456 /// raw `AIBinder` pointer.
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000457 fn new<B: AsNative<sys::AIBinder>>(binder: &mut B) -> WpIBinder {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700458 let ptr = unsafe {
459 // Safety: `SpIBinder` guarantees that `binder` always contains a
460 // valid pointer to an `AIBinder`.
461 sys::AIBinder_Weak_new(binder.as_native_mut())
462 };
463 assert!(!ptr.is_null());
464 Self(ptr)
465 }
Stephen Crane994a0f02020-08-11 14:47:29 -0700466
467 /// Promote this weak reference to a strong reference to the binder object.
468 pub fn promote(&self) -> Option<SpIBinder> {
469 unsafe {
470 // Safety: `WpIBinder` always contains a valid weak reference, so we
471 // can pass this pointer to `AIBinder_Weak_promote`. Returns either
472 // null or an AIBinder owned by the caller, both of which are valid
473 // to pass to `SpIBinder::from_raw`.
474 let ptr = sys::AIBinder_Weak_promote(self.0);
475 SpIBinder::from_raw(ptr)
476 }
477 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700478}
479
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800480impl Clone for WpIBinder {
481 fn clone(&self) -> Self {
482 let ptr = unsafe {
483 // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
484 // so this pointer is always safe to pass to `AIBinder_Weak_clone`
485 // (although null is also a safe value to pass to this API).
486 //
487 // We get ownership of the returned pointer, so can construct a new
488 // WpIBinder object from it.
489 sys::AIBinder_Weak_clone(self.0)
490 };
Andrew Walbran12400d82021-03-04 17:04:34 +0000491 assert!(
492 !ptr.is_null(),
493 "Unexpected null pointer from AIBinder_Weak_clone"
494 );
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800495 Self(ptr)
496 }
497}
498
499impl Ord for WpIBinder {
500 fn cmp(&self, other: &Self) -> Ordering {
501 let less_than = unsafe {
502 // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
503 // so this pointer is always safe to pass to `AIBinder_Weak_lt`
504 // (null is also safe to pass to this function, but we should never
505 // do that).
506 sys::AIBinder_Weak_lt(self.0, other.0)
507 };
508 let greater_than = unsafe {
509 // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
510 // so this pointer is always safe to pass to `AIBinder_Weak_lt`
511 // (null is also safe to pass to this function, but we should never
512 // do that).
513 sys::AIBinder_Weak_lt(other.0, self.0)
514 };
515 if !less_than && !greater_than {
516 Ordering::Equal
517 } else if less_than {
518 Ordering::Less
519 } else {
520 Ordering::Greater
521 }
522 }
523}
524
525impl PartialOrd for WpIBinder {
526 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
527 Some(self.cmp(other))
528 }
529}
530
531impl PartialEq for WpIBinder {
532 fn eq(&self, other: &Self) -> bool {
533 self.cmp(other) == Ordering::Equal
534 }
535}
536
537impl Eq for WpIBinder {}
538
Andrew Walbran5e8dfa32020-12-16 12:50:06 +0000539impl Drop for WpIBinder {
540 fn drop(&mut self) {
541 unsafe {
542 // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, so we
543 // know this pointer is safe to pass to `AIBinder_Weak_delete` here.
544 sys::AIBinder_Weak_delete(self.0);
545 }
546 }
547}
548
Stephen Crane2a3c2502020-06-16 17:48:35 -0700549/// Rust wrapper around DeathRecipient objects.
550#[repr(C)]
551pub struct DeathRecipient {
552 recipient: *mut sys::AIBinder_DeathRecipient,
553 callback: Box<dyn Fn() + Send + 'static>,
554}
555
556impl DeathRecipient {
557 /// Create a new death recipient that will call the given callback when its
558 /// associated object dies.
559 pub fn new<F>(callback: F) -> DeathRecipient
560 where
561 F: Fn() + Send + 'static,
562 {
563 let callback = Box::new(callback);
564 let recipient = unsafe {
565 // Safety: The function pointer is a valid death recipient callback.
566 //
567 // This call returns an owned `AIBinder_DeathRecipient` pointer
568 // which must be destroyed via `AIBinder_DeathRecipient_delete` when
569 // no longer needed.
570 sys::AIBinder_DeathRecipient_new(Some(Self::binder_died::<F>))
571 };
572 DeathRecipient {
573 recipient,
574 callback,
575 }
576 }
577
578 /// Get the opaque cookie that identifies this death recipient.
579 ///
580 /// This cookie will be used to link and unlink this death recipient to a
581 /// binder object and will be passed to the `binder_died` callback as an
582 /// opaque userdata pointer.
583 fn get_cookie(&self) -> *mut c_void {
584 &*self.callback as *const _ as *mut c_void
585 }
586
587 /// Callback invoked from C++ when the binder object dies.
588 ///
589 /// # Safety
590 ///
591 /// The `cookie` parameter must have been created with the `get_cookie`
592 /// method of this object.
593 unsafe extern "C" fn binder_died<F>(cookie: *mut c_void)
594 where
595 F: Fn() + Send + 'static,
596 {
597 let callback = (cookie as *mut F).as_ref().unwrap();
598 callback();
599 }
600}
601
602/// # Safety
603///
604/// A `DeathRecipient` is always constructed with a valid raw pointer to an
605/// `AIBinder_DeathRecipient`, so it is always type-safe to extract this
606/// pointer.
607unsafe impl AsNative<sys::AIBinder_DeathRecipient> for DeathRecipient {
608 fn as_native(&self) -> *const sys::AIBinder_DeathRecipient {
609 self.recipient
610 }
611
612 fn as_native_mut(&mut self) -> *mut sys::AIBinder_DeathRecipient {
613 self.recipient
614 }
615}
616
617impl Drop for DeathRecipient {
618 fn drop(&mut self) {
619 unsafe {
620 // Safety: `self.recipient` is always a valid, owned
621 // `AIBinder_DeathRecipient` pointer returned by
622 // `AIBinder_DeathRecipient_new` when `self` was created. This
623 // delete method can only be called once when `self` is dropped.
624 sys::AIBinder_DeathRecipient_delete(self.recipient);
625 }
626 }
627}
628
629/// Generic interface to remote binder objects.
630///
631/// Corresponds to the C++ `BpInterface` class.
632pub trait Proxy: Sized + Interface {
633 /// The Binder interface descriptor string.
634 ///
635 /// This string is a unique identifier for a Binder interface, and should be
636 /// the same between all implementations of that interface.
637 fn get_descriptor() -> &'static str;
638
639 /// Create a new interface from the given proxy, if it matches the expected
640 /// type of this interface.
641 fn from_binder(binder: SpIBinder) -> Result<Self>;
642}
643
644/// # Safety
645///
646/// This is a convenience method that wraps `AsNative` for `SpIBinder` to allow
647/// invocation of `IBinder` methods directly from `Interface` objects. It shares
648/// the same safety as the implementation for `SpIBinder`.
649unsafe impl<T: Proxy> AsNative<sys::AIBinder> for T {
650 fn as_native(&self) -> *const sys::AIBinder {
651 self.as_binder().as_native()
652 }
653
654 fn as_native_mut(&mut self) -> *mut sys::AIBinder {
655 self.as_binder().as_native_mut()
656 }
657}
658
659/// Retrieve an existing service, blocking for a few seconds if it doesn't yet
660/// exist.
661pub fn get_service(name: &str) -> Option<SpIBinder> {
662 let name = CString::new(name).ok()?;
663 unsafe {
664 // Safety: `AServiceManager_getService` returns either a null pointer or
665 // a valid pointer to an owned `AIBinder`. Either of these values is
666 // safe to pass to `SpIBinder::from_raw`.
667 SpIBinder::from_raw(sys::AServiceManager_getService(name.as_ptr()))
668 }
669}
670
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000671/// Retrieve an existing service, or start it if it is configured as a dynamic
672/// service and isn't yet started.
673pub fn wait_for_service(name: &str) -> Option<SpIBinder> {
674 let name = CString::new(name).ok()?;
675 unsafe {
676 // Safety: `AServiceManager_waitforService` returns either a null
677 // pointer or a valid pointer to an owned `AIBinder`. Either of these
678 // values is safe to pass to `SpIBinder::from_raw`.
679 SpIBinder::from_raw(sys::AServiceManager_waitForService(name.as_ptr()))
680 }
681}
682
Stephen Crane2a3c2502020-06-16 17:48:35 -0700683/// Retrieve an existing service for a particular interface, blocking for a few
684/// seconds if it doesn't yet exist.
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800685pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700686 let service = get_service(name);
687 match service {
688 Some(service) => FromIBinder::try_from(service),
689 None => Err(StatusCode::NAME_NOT_FOUND),
690 }
691}
692
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000693/// Retrieve an existing service for a particular interface, or start it if it
694/// is configured as a dynamic service and isn't yet started.
695pub fn wait_for_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
696 let service = wait_for_service(name);
697 match service {
698 Some(service) => FromIBinder::try_from(service),
699 None => Err(StatusCode::NAME_NOT_FOUND),
700 }
701}
702
Stephen Crane2a3c2502020-06-16 17:48:35 -0700703/// # Safety
704///
705/// `SpIBinder` guarantees that `binder` always contains a valid pointer to an
706/// `AIBinder`, so we can trivially extract this pointer here.
707unsafe impl AsNative<sys::AIBinder> for SpIBinder {
708 fn as_native(&self) -> *const sys::AIBinder {
709 self.0
710 }
711
712 fn as_native_mut(&mut self) -> *mut sys::AIBinder {
713 self.0
714 }
715}