blob: 17af0992e2eeb16934723ddbdd4bd5cd8249ee2d [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::{
20 AsNative, FromIBinder, IBinder, Interface, InterfaceClass, TransactionCode, TransactionFlags,
21};
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;
30use std::ffi::{c_void, CString};
Andrei Homescu2e3c1472020-08-11 16:35:40 -070031use std::fmt;
Stephen Crane2a3c2502020-06-16 17:48:35 -070032use std::os::unix::io::AsRawFd;
33use std::ptr;
34
35/// A strong reference to a Binder remote object.
36///
37/// This struct encapsulates the generic C++ `sp<IBinder>` class. This wrapper
38/// is untyped; typed interface access is implemented by the AIDL compiler.
39pub struct SpIBinder(*mut sys::AIBinder);
40
Andrei Homescu2e3c1472020-08-11 16:35:40 -070041impl fmt::Debug for SpIBinder {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 f.pad("SpIBinder")
44 }
45}
46
Stephen Crane2a3c2502020-06-16 17:48:35 -070047/// # Safety
48///
49/// An `SpIBinder` is a handle to a C++ IBinder, which is thread-safe
50unsafe impl Send for SpIBinder {}
51
52impl SpIBinder {
53 /// Create an `SpIBinder` wrapper object from a raw `AIBinder` pointer.
54 ///
55 /// # Safety
56 ///
57 /// This constructor is safe iff `ptr` is a null pointer or a valid pointer
58 /// to an `AIBinder`.
59 ///
60 /// In the non-null case, this method conceptually takes ownership of a strong
61 /// reference to the object, so `AIBinder_incStrong` must have been called
62 /// on the pointer before passing it to this constructor. This is generally
63 /// done by Binder NDK methods that return an `AIBinder`, but care should be
64 /// taken to ensure this invariant.
65 ///
66 /// All `SpIBinder` objects that are constructed will hold a valid pointer
67 /// to an `AIBinder`, which will remain valid for the entire lifetime of the
68 /// `SpIBinder` (we keep a strong reference, and only decrement on drop).
69 pub(crate) unsafe fn from_raw(ptr: *mut sys::AIBinder) -> Option<Self> {
70 ptr.as_mut().map(|p| Self(p))
71 }
72
73 /// Return true if this binder object is hosted in a different process than
74 /// the current one.
75 pub fn is_remote(&self) -> bool {
76 unsafe {
77 // Safety: `SpIBinder` guarantees that it always contains a valid
78 // `AIBinder` pointer.
79 sys::AIBinder_isRemote(self.as_native())
80 }
81 }
82
83 /// Try to convert this Binder object into a trait object for the given
84 /// Binder interface.
85 ///
86 /// If this object does not implement the expected interface, the error
87 /// `StatusCode::BAD_TYPE` is returned.
88 pub fn into_interface<I: FromIBinder + ?Sized>(self) -> Result<Box<I>> {
89 FromIBinder::try_from(self)
90 }
91
92 /// Return the interface class of this binder object, if associated with
93 /// one.
Stephen Crane669deb62020-09-10 17:31:39 -070094 pub fn get_class(&mut self) -> Option<InterfaceClass> {
Stephen Crane2a3c2502020-06-16 17:48:35 -070095 unsafe {
96 // Safety: `SpIBinder` guarantees that it always contains a valid
97 // `AIBinder` pointer. `AIBinder_getClass` returns either a null
98 // pointer or a valid pointer to an `AIBinder_Class`. After mapping
99 // null to None, we can safely construct an `InterfaceClass` if the
100 // pointer was non-null.
101 let class = sys::AIBinder_getClass(self.as_native_mut());
102 class.as_ref().map(|p| InterfaceClass::from_ptr(p))
103 }
104 }
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000105
106 /// Creates a new weak reference to this binder object.
107 pub fn downgrade(&mut self) -> WpIBinder {
108 WpIBinder::new(self)
109 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700110}
111
112/// An object that can be associate with an [`InterfaceClass`].
113pub trait AssociateClass {
114 /// Check if this object is a valid object for the given interface class
115 /// `I`.
116 ///
117 /// Returns `Some(self)` if this is a valid instance of the interface, and
118 /// `None` otherwise.
119 ///
120 /// Classes constructed by `InterfaceClass` are unique per type, so
121 /// repeatedly calling this method for the same `InterfaceClass` is allowed.
122 fn associate_class(&mut self, class: InterfaceClass) -> bool;
123}
124
125impl AssociateClass for SpIBinder {
126 fn associate_class(&mut self, class: InterfaceClass) -> bool {
127 unsafe {
128 // Safety: `SpIBinder` guarantees that it always contains a valid
129 // `AIBinder` pointer. An `InterfaceClass` can always be converted
130 // into a valid `AIBinder_Class` pointer, so these parameters are
131 // always safe.
132 sys::AIBinder_associateClass(self.as_native_mut(), class.into())
133 }
134 }
135}
136
Stephen Crane994a0f02020-08-11 14:47:29 -0700137impl PartialEq for SpIBinder {
138 fn eq(&self, other: &Self) -> bool {
139 ptr::eq(self.0, other.0)
140 }
141}
142
143impl Eq for SpIBinder {}
144
Stephen Crane2a3c2502020-06-16 17:48:35 -0700145impl Clone for SpIBinder {
146 fn clone(&self) -> Self {
147 unsafe {
148 // Safety: Cloning a strong reference must increment the reference
149 // count. We are guaranteed by the `SpIBinder` constructor
150 // invariants that `self.0` is always a valid `AIBinder` pointer.
151 sys::AIBinder_incStrong(self.0);
152 }
153 Self(self.0)
154 }
155}
156
157impl Drop for SpIBinder {
158 // We hold a strong reference to the IBinder in SpIBinder and need to give up
159 // this reference on drop.
160 fn drop(&mut self) {
161 unsafe {
162 // Safety: SpIBinder always holds a valid `AIBinder` pointer, so we
163 // know this pointer is safe to pass to `AIBinder_decStrong` here.
164 sys::AIBinder_decStrong(self.as_native_mut());
165 }
166 }
167}
168
169impl<T: AsNative<sys::AIBinder>> IBinder for T {
170 /// Perform a binder transaction
171 fn transact<F: FnOnce(&mut Parcel) -> Result<()>>(
172 &self,
173 code: TransactionCode,
174 flags: TransactionFlags,
175 input_callback: F,
176 ) -> Result<Parcel> {
177 let mut input = ptr::null_mut();
178 let status = unsafe {
179 // Safety: `SpIBinder` guarantees that `self` always contains a
180 // valid pointer to an `AIBinder`. It is safe to cast from an
181 // immutable pointer to a mutable pointer here, because
182 // `AIBinder_prepareTransaction` only calls immutable `AIBinder`
183 // methods but the parameter is unfortunately not marked as const.
184 //
185 // After the call, input will be either a valid, owned `AParcel`
186 // pointer, or null.
187 sys::AIBinder_prepareTransaction(self.as_native() as *mut sys::AIBinder, &mut input)
188 };
189 status_result(status)?;
190 let mut input = unsafe {
191 // Safety: At this point, `input` is either a valid, owned `AParcel`
192 // pointer, or null. `Parcel::owned` safely handles both cases,
193 // taking ownership of the parcel.
194 Parcel::owned(input).ok_or(StatusCode::UNEXPECTED_NULL)?
195 };
196 input_callback(&mut input)?;
197 let mut reply = ptr::null_mut();
198 let status = unsafe {
199 // Safety: `SpIBinder` guarantees that `self` always contains a
200 // valid pointer to an `AIBinder`. Although `IBinder::transact` is
201 // not a const method, it is still safe to cast our immutable
202 // pointer to mutable for the call. First, `IBinder::transact` is
203 // thread-safe, so concurrency is not an issue. The only way that
204 // `transact` can affect any visible, mutable state in the current
205 // process is by calling `onTransact` for a local service. However,
206 // in order for transactions to be thread-safe, this method must
207 // dynamically lock its data before modifying it. We enforce this
208 // property in Rust by requiring `Sync` for remotable objects and
209 // only providing `on_transact` with an immutable reference to
210 // `self`.
211 //
212 // This call takes ownership of the `input` parcel pointer, and
213 // passes ownership of the `reply` out parameter to its caller. It
214 // does not affect ownership of the `binder` parameter.
215 sys::AIBinder_transact(
216 self.as_native() as *mut sys::AIBinder,
217 code,
218 &mut input.into_raw(),
219 &mut reply,
220 flags,
221 )
222 };
223 status_result(status)?;
224
225 unsafe {
226 // Safety: `reply` is either a valid `AParcel` pointer or null
227 // after the call to `AIBinder_transact` above, so we can
228 // construct a `Parcel` out of it. `AIBinder_transact` passes
229 // ownership of the `reply` parcel to Rust, so we need to
230 // construct an owned variant. `Parcel::owned` takes ownership
231 // of the parcel pointer.
232 Parcel::owned(reply).ok_or(StatusCode::UNEXPECTED_NULL)
233 }
234 }
235
236 fn is_binder_alive(&self) -> bool {
237 unsafe {
238 // Safety: `SpIBinder` guarantees that `self` always contains a
239 // valid pointer to an `AIBinder`.
240 //
241 // This call does not affect ownership of its pointer parameter.
242 sys::AIBinder_isAlive(self.as_native())
243 }
244 }
245
246 fn ping_binder(&mut self) -> Result<()> {
247 let status = unsafe {
248 // Safety: `SpIBinder` guarantees that `self` always contains a
249 // valid pointer to an `AIBinder`.
250 //
251 // This call does not affect ownership of its pointer parameter.
252 sys::AIBinder_ping(self.as_native_mut())
253 };
254 status_result(status)
255 }
256
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700257 fn set_requesting_sid(&mut self, enable: bool) {
258 unsafe {
259 sys::AIBinder_setRequestingSid(self.as_native_mut(), enable)
260 };
261 }
262
Stephen Crane2a3c2502020-06-16 17:48:35 -0700263 fn dump<F: AsRawFd>(&mut self, fp: &F, args: &[&str]) -> Result<()> {
264 let args: Vec<_> = args.iter().map(|a| CString::new(*a).unwrap()).collect();
265 let mut arg_ptrs: Vec<_> = args.iter().map(|a| a.as_ptr()).collect();
266 let status = unsafe {
267 // Safety: `SpIBinder` guarantees that `self` always contains a
268 // valid pointer to an `AIBinder`. `AsRawFd` guarantees that the
269 // file descriptor parameter is always be a valid open file. The
270 // `args` pointer parameter is a valid pointer to an array of C
271 // strings that will outlive the call since `args` lives for the
272 // whole function scope.
273 //
274 // This call does not affect ownership of its binder pointer
275 // parameter and does not take ownership of the file or args array
276 // parameters.
277 sys::AIBinder_dump(
278 self.as_native_mut(),
279 fp.as_raw_fd(),
280 arg_ptrs.as_mut_ptr(),
281 arg_ptrs.len().try_into().unwrap(),
282 )
283 };
284 status_result(status)
285 }
286
287 fn get_extension(&mut self) -> Result<Option<SpIBinder>> {
288 let mut out = ptr::null_mut();
289 let status = unsafe {
290 // Safety: `SpIBinder` guarantees that `self` always contains a
291 // valid pointer to an `AIBinder`. After this call, the `out`
292 // parameter will be either null, or a valid pointer to an
293 // `AIBinder`.
294 //
295 // This call passes ownership of the out pointer to its caller
296 // (assuming it is set to a non-null value).
297 sys::AIBinder_getExtension(self.as_native_mut(), &mut out)
298 };
299 let ibinder = unsafe {
300 // Safety: The call above guarantees that `out` is either null or a
301 // valid, owned pointer to an `AIBinder`, both of which are safe to
302 // pass to `SpIBinder::from_raw`.
303 SpIBinder::from_raw(out)
304 };
305
306 status_result(status)?;
307 Ok(ibinder)
308 }
309
310 fn link_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> {
311 status_result(unsafe {
312 // Safety: `SpIBinder` guarantees that `self` always contains a
313 // valid pointer to an `AIBinder`. `recipient` can always be
314 // converted into a valid pointer to an
315 // `AIBinder_DeatRecipient`. Any value is safe to pass as the
316 // cookie, although we depend on this value being set by
317 // `get_cookie` when the death recipient callback is called.
318 sys::AIBinder_linkToDeath(
319 self.as_native_mut(),
320 recipient.as_native_mut(),
321 recipient.get_cookie(),
322 )
323 })
324 }
325
326 fn unlink_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> {
327 status_result(unsafe {
328 // Safety: `SpIBinder` guarantees that `self` always contains a
329 // valid pointer to an `AIBinder`. `recipient` can always be
330 // converted into a valid pointer to an
331 // `AIBinder_DeatRecipient`. Any value is safe to pass as the
332 // cookie, although we depend on this value being set by
333 // `get_cookie` when the death recipient callback is called.
334 sys::AIBinder_unlinkToDeath(
335 self.as_native_mut(),
336 recipient.as_native_mut(),
337 recipient.get_cookie(),
338 )
339 })
340 }
341}
342
343impl Serialize for SpIBinder {
344 fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
345 parcel.write_binder(Some(self))
346 }
347}
348
349impl SerializeOption for SpIBinder {
350 fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
351 parcel.write_binder(this)
352 }
353}
354
355impl SerializeArray for SpIBinder {}
356impl SerializeArray for Option<&SpIBinder> {}
357
358impl Deserialize for SpIBinder {
359 fn deserialize(parcel: &Parcel) -> Result<SpIBinder> {
Andrei Homescu32814372020-08-20 15:36:08 -0700360 parcel
361 .read_binder()
362 .transpose()
363 .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
Stephen Crane2a3c2502020-06-16 17:48:35 -0700364 }
365}
366
367impl DeserializeOption for SpIBinder {
368 fn deserialize_option(parcel: &Parcel) -> Result<Option<SpIBinder>> {
369 parcel.read_binder()
370 }
371}
372
373impl DeserializeArray for SpIBinder {}
374impl DeserializeArray for Option<SpIBinder> {}
375
376/// A weak reference to a Binder remote object.
377///
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000378/// This struct encapsulates the generic C++ `wp<IBinder>` class. This wrapper
379/// is untyped; typed interface access is implemented by the AIDL compiler.
Stephen Crane2a3c2502020-06-16 17:48:35 -0700380pub struct WpIBinder(*mut sys::AIBinder_Weak);
381
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000382impl fmt::Debug for WpIBinder {
383 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
384 f.pad("WpIBinder")
385 }
386}
387
388/// # Safety
389///
390/// A `WpIBinder` is a handle to a C++ IBinder, which is thread-safe.
391unsafe impl Send for WpIBinder {}
392
Stephen Crane2a3c2502020-06-16 17:48:35 -0700393impl WpIBinder {
394 /// Create a new weak reference from an object that can be converted into a
395 /// raw `AIBinder` pointer.
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000396 fn new<B: AsNative<sys::AIBinder>>(binder: &mut B) -> WpIBinder {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700397 let ptr = unsafe {
398 // Safety: `SpIBinder` guarantees that `binder` always contains a
399 // valid pointer to an `AIBinder`.
400 sys::AIBinder_Weak_new(binder.as_native_mut())
401 };
402 assert!(!ptr.is_null());
403 Self(ptr)
404 }
Stephen Crane994a0f02020-08-11 14:47:29 -0700405
406 /// Promote this weak reference to a strong reference to the binder object.
407 pub fn promote(&self) -> Option<SpIBinder> {
408 unsafe {
409 // Safety: `WpIBinder` always contains a valid weak reference, so we
410 // can pass this pointer to `AIBinder_Weak_promote`. Returns either
411 // null or an AIBinder owned by the caller, both of which are valid
412 // to pass to `SpIBinder::from_raw`.
413 let ptr = sys::AIBinder_Weak_promote(self.0);
414 SpIBinder::from_raw(ptr)
415 }
416 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700417}
418
Andrew Walbran5e8dfa32020-12-16 12:50:06 +0000419impl Drop for WpIBinder {
420 fn drop(&mut self) {
421 unsafe {
422 // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, so we
423 // know this pointer is safe to pass to `AIBinder_Weak_delete` here.
424 sys::AIBinder_Weak_delete(self.0);
425 }
426 }
427}
428
Stephen Crane2a3c2502020-06-16 17:48:35 -0700429/// Rust wrapper around DeathRecipient objects.
430#[repr(C)]
431pub struct DeathRecipient {
432 recipient: *mut sys::AIBinder_DeathRecipient,
433 callback: Box<dyn Fn() + Send + 'static>,
434}
435
436impl DeathRecipient {
437 /// Create a new death recipient that will call the given callback when its
438 /// associated object dies.
439 pub fn new<F>(callback: F) -> DeathRecipient
440 where
441 F: Fn() + Send + 'static,
442 {
443 let callback = Box::new(callback);
444 let recipient = unsafe {
445 // Safety: The function pointer is a valid death recipient callback.
446 //
447 // This call returns an owned `AIBinder_DeathRecipient` pointer
448 // which must be destroyed via `AIBinder_DeathRecipient_delete` when
449 // no longer needed.
450 sys::AIBinder_DeathRecipient_new(Some(Self::binder_died::<F>))
451 };
452 DeathRecipient {
453 recipient,
454 callback,
455 }
456 }
457
458 /// Get the opaque cookie that identifies this death recipient.
459 ///
460 /// This cookie will be used to link and unlink this death recipient to a
461 /// binder object and will be passed to the `binder_died` callback as an
462 /// opaque userdata pointer.
463 fn get_cookie(&self) -> *mut c_void {
464 &*self.callback as *const _ as *mut c_void
465 }
466
467 /// Callback invoked from C++ when the binder object dies.
468 ///
469 /// # Safety
470 ///
471 /// The `cookie` parameter must have been created with the `get_cookie`
472 /// method of this object.
473 unsafe extern "C" fn binder_died<F>(cookie: *mut c_void)
474 where
475 F: Fn() + Send + 'static,
476 {
477 let callback = (cookie as *mut F).as_ref().unwrap();
478 callback();
479 }
480}
481
482/// # Safety
483///
484/// A `DeathRecipient` is always constructed with a valid raw pointer to an
485/// `AIBinder_DeathRecipient`, so it is always type-safe to extract this
486/// pointer.
487unsafe impl AsNative<sys::AIBinder_DeathRecipient> for DeathRecipient {
488 fn as_native(&self) -> *const sys::AIBinder_DeathRecipient {
489 self.recipient
490 }
491
492 fn as_native_mut(&mut self) -> *mut sys::AIBinder_DeathRecipient {
493 self.recipient
494 }
495}
496
497impl Drop for DeathRecipient {
498 fn drop(&mut self) {
499 unsafe {
500 // Safety: `self.recipient` is always a valid, owned
501 // `AIBinder_DeathRecipient` pointer returned by
502 // `AIBinder_DeathRecipient_new` when `self` was created. This
503 // delete method can only be called once when `self` is dropped.
504 sys::AIBinder_DeathRecipient_delete(self.recipient);
505 }
506 }
507}
508
509/// Generic interface to remote binder objects.
510///
511/// Corresponds to the C++ `BpInterface` class.
512pub trait Proxy: Sized + Interface {
513 /// The Binder interface descriptor string.
514 ///
515 /// This string is a unique identifier for a Binder interface, and should be
516 /// the same between all implementations of that interface.
517 fn get_descriptor() -> &'static str;
518
519 /// Create a new interface from the given proxy, if it matches the expected
520 /// type of this interface.
521 fn from_binder(binder: SpIBinder) -> Result<Self>;
522}
523
524/// # Safety
525///
526/// This is a convenience method that wraps `AsNative` for `SpIBinder` to allow
527/// invocation of `IBinder` methods directly from `Interface` objects. It shares
528/// the same safety as the implementation for `SpIBinder`.
529unsafe impl<T: Proxy> AsNative<sys::AIBinder> for T {
530 fn as_native(&self) -> *const sys::AIBinder {
531 self.as_binder().as_native()
532 }
533
534 fn as_native_mut(&mut self) -> *mut sys::AIBinder {
535 self.as_binder().as_native_mut()
536 }
537}
538
539/// Retrieve an existing service, blocking for a few seconds if it doesn't yet
540/// exist.
541pub fn get_service(name: &str) -> Option<SpIBinder> {
542 let name = CString::new(name).ok()?;
543 unsafe {
544 // Safety: `AServiceManager_getService` returns either a null pointer or
545 // a valid pointer to an owned `AIBinder`. Either of these values is
546 // safe to pass to `SpIBinder::from_raw`.
547 SpIBinder::from_raw(sys::AServiceManager_getService(name.as_ptr()))
548 }
549}
550
551/// Retrieve an existing service for a particular interface, blocking for a few
552/// seconds if it doesn't yet exist.
553pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Box<T>> {
554 let service = get_service(name);
555 match service {
556 Some(service) => FromIBinder::try_from(service),
557 None => Err(StatusCode::NAME_NOT_FOUND),
558 }
559}
560
561/// # Safety
562///
563/// `SpIBinder` guarantees that `binder` always contains a valid pointer to an
564/// `AIBinder`, so we can trivially extract this pointer here.
565unsafe impl AsNative<sys::AIBinder> for SpIBinder {
566 fn as_native(&self) -> *const sys::AIBinder {
567 self.0
568 }
569
570 fn as_native_mut(&mut self) -> *mut sys::AIBinder {
571 self.0
572 }
573}