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