blob: 12bfde755ef61e13149fc5573766fa68c6f94b62 [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::{
Alice Ryhl8618c482021-11-09 15:35:35 +000025 Parcel, BorrowedParcel, Deserialize, DeserializeArray, DeserializeOption, Serialize, SerializeArray, SerializeOption,
Stephen Crane2a3c2502020-06-16 17:48:35 -070026};
27use crate::sys;
28
Stephen Craneddb3e6d2020-12-18 13:27:22 -080029use std::cmp::Ordering;
Andrew Walbran12400d82021-03-04 17:04:34 +000030use std::convert::TryInto;
Stephen Crane2a3c2502020-06-16 17:48:35 -070031use std::ffi::{c_void, CString};
Andrei Homescu2e3c1472020-08-11 16:35:40 -070032use std::fmt;
Alice Ryhlea9d9d22021-08-27 07:51:30 +000033use std::mem;
Stephen Crane2a3c2502020-06-16 17:48:35 -070034use std::os::unix::io::AsRawFd;
35use std::ptr;
Alice Ryhlea9d9d22021-08-27 07:51:30 +000036use std::sync::Arc;
Stephen Crane2a3c2502020-06-16 17:48:35 -070037
38/// A strong reference to a Binder remote object.
39///
40/// This struct encapsulates the generic C++ `sp<IBinder>` class. This wrapper
41/// is untyped; typed interface access is implemented by the AIDL compiler.
Alice Ryhl8dde9bc2021-08-16 16:57:10 +000042pub struct SpIBinder(ptr::NonNull<sys::AIBinder>);
Stephen Crane2a3c2502020-06-16 17:48:35 -070043
Andrei Homescu2e3c1472020-08-11 16:35:40 -070044impl fmt::Debug for SpIBinder {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 f.pad("SpIBinder")
47 }
48}
49
Stephen Crane2a3c2502020-06-16 17:48:35 -070050/// # Safety
51///
Stephen Cranef03fe3d2021-06-25 15:05:00 -070052/// An `SpIBinder` is an immutable handle to a C++ IBinder, which is thread-safe
Stephen Crane2a3c2502020-06-16 17:48:35 -070053unsafe impl Send for SpIBinder {}
54
Stephen Cranef03fe3d2021-06-25 15:05:00 -070055/// # Safety
56///
57/// An `SpIBinder` is an immutable handle to a C++ IBinder, which is thread-safe
58unsafe impl Sync for SpIBinder {}
59
Stephen Crane2a3c2502020-06-16 17:48:35 -070060impl SpIBinder {
61 /// Create an `SpIBinder` wrapper object from a raw `AIBinder` pointer.
62 ///
63 /// # Safety
64 ///
65 /// This constructor is safe iff `ptr` is a null pointer or a valid pointer
66 /// to an `AIBinder`.
67 ///
68 /// In the non-null case, this method conceptually takes ownership of a strong
69 /// reference to the object, so `AIBinder_incStrong` must have been called
70 /// on the pointer before passing it to this constructor. This is generally
71 /// done by Binder NDK methods that return an `AIBinder`, but care should be
72 /// taken to ensure this invariant.
73 ///
74 /// All `SpIBinder` objects that are constructed will hold a valid pointer
75 /// to an `AIBinder`, which will remain valid for the entire lifetime of the
76 /// `SpIBinder` (we keep a strong reference, and only decrement on drop).
77 pub(crate) unsafe fn from_raw(ptr: *mut sys::AIBinder) -> Option<Self> {
Alice Ryhl8dde9bc2021-08-16 16:57:10 +000078 ptr::NonNull::new(ptr).map(Self)
Stephen Crane2a3c2502020-06-16 17:48:35 -070079 }
80
Stephen Craned58bce02020-07-07 12:26:02 -070081 /// Extract a raw `AIBinder` pointer from this wrapper.
82 ///
83 /// This method should _only_ be used for testing. Do not try to use the NDK
84 /// interface directly for anything else.
85 ///
86 /// # Safety
87 ///
88 /// The resulting pointer is valid only as long as the SpIBinder is alive.
89 /// The SpIBinder object retains ownership of the AIBinder and the caller
90 /// should not attempt to free the returned pointer.
91 pub unsafe fn as_raw(&self) -> *mut sys::AIBinder {
Alice Ryhl8dde9bc2021-08-16 16:57:10 +000092 self.0.as_ptr()
Stephen Craned58bce02020-07-07 12:26:02 -070093 }
94
Stephen Crane2a3c2502020-06-16 17:48:35 -070095 /// Return true if this binder object is hosted in a different process than
96 /// the current one.
97 pub fn is_remote(&self) -> bool {
98 unsafe {
99 // Safety: `SpIBinder` guarantees that it always contains a valid
100 // `AIBinder` pointer.
101 sys::AIBinder_isRemote(self.as_native())
102 }
103 }
104
105 /// Try to convert this Binder object into a trait object for the given
106 /// Binder interface.
107 ///
108 /// If this object does not implement the expected interface, the error
109 /// `StatusCode::BAD_TYPE` is returned.
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800110 pub fn into_interface<I: FromIBinder + Interface + ?Sized>(self) -> Result<Strong<I>> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700111 FromIBinder::try_from(self)
112 }
113
114 /// Return the interface class of this binder object, if associated with
115 /// one.
Stephen Crane669deb62020-09-10 17:31:39 -0700116 pub fn get_class(&mut self) -> Option<InterfaceClass> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700117 unsafe {
118 // Safety: `SpIBinder` guarantees that it always contains a valid
119 // `AIBinder` pointer. `AIBinder_getClass` returns either a null
120 // pointer or a valid pointer to an `AIBinder_Class`. After mapping
121 // null to None, we can safely construct an `InterfaceClass` if the
122 // pointer was non-null.
123 let class = sys::AIBinder_getClass(self.as_native_mut());
124 class.as_ref().map(|p| InterfaceClass::from_ptr(p))
125 }
126 }
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000127
128 /// Creates a new weak reference to this binder object.
129 pub fn downgrade(&mut self) -> WpIBinder {
130 WpIBinder::new(self)
131 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700132}
133
Victor Hsiehd35d31d2021-06-03 11:24:31 -0700134pub mod unstable_api {
135 use super::{sys, SpIBinder};
136
137 /// A temporary API to allow the client to create a `SpIBinder` from a `sys::AIBinder`. This is
138 /// needed to bridge RPC binder, which doesn't have Rust API yet.
139 /// TODO(b/184872979): remove once the Rust API is created.
140 ///
141 /// # Safety
142 ///
143 /// See `SpIBinder::from_raw`.
144 pub unsafe fn new_spibinder(ptr: *mut sys::AIBinder) -> Option<SpIBinder> {
145 SpIBinder::from_raw(ptr)
146 }
147}
148
Stephen Crane2a3c2502020-06-16 17:48:35 -0700149/// An object that can be associate with an [`InterfaceClass`].
150pub trait AssociateClass {
151 /// Check if this object is a valid object for the given interface class
152 /// `I`.
153 ///
154 /// Returns `Some(self)` if this is a valid instance of the interface, and
155 /// `None` otherwise.
156 ///
157 /// Classes constructed by `InterfaceClass` are unique per type, so
158 /// repeatedly calling this method for the same `InterfaceClass` is allowed.
159 fn associate_class(&mut self, class: InterfaceClass) -> bool;
160}
161
162impl AssociateClass for SpIBinder {
163 fn associate_class(&mut self, class: InterfaceClass) -> bool {
164 unsafe {
165 // Safety: `SpIBinder` guarantees that it always contains a valid
166 // `AIBinder` pointer. An `InterfaceClass` can always be converted
167 // into a valid `AIBinder_Class` pointer, so these parameters are
168 // always safe.
169 sys::AIBinder_associateClass(self.as_native_mut(), class.into())
170 }
171 }
172}
173
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800174impl Ord for SpIBinder {
175 fn cmp(&self, other: &Self) -> Ordering {
176 let less_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).
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000180 sys::AIBinder_lt(self.0.as_ptr(), other.0.as_ptr())
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800181 };
182 let greater_than = unsafe {
183 // Safety: SpIBinder always holds a valid `AIBinder` pointer, so
184 // this pointer is always safe to pass to `AIBinder_lt` (null is
185 // also safe to pass to this function, but we should never do that).
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000186 sys::AIBinder_lt(other.0.as_ptr(), self.0.as_ptr())
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800187 };
188 if !less_than && !greater_than {
189 Ordering::Equal
190 } else if less_than {
191 Ordering::Less
192 } else {
193 Ordering::Greater
194 }
195 }
196}
197
198impl PartialOrd for SpIBinder {
199 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
200 Some(self.cmp(other))
201 }
202}
203
Stephen Crane994a0f02020-08-11 14:47:29 -0700204impl PartialEq for SpIBinder {
205 fn eq(&self, other: &Self) -> bool {
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000206 ptr::eq(self.0.as_ptr(), other.0.as_ptr())
Stephen Crane994a0f02020-08-11 14:47:29 -0700207 }
208}
209
210impl Eq for SpIBinder {}
211
Stephen Crane2a3c2502020-06-16 17:48:35 -0700212impl Clone for SpIBinder {
213 fn clone(&self) -> Self {
214 unsafe {
215 // Safety: Cloning a strong reference must increment the reference
216 // count. We are guaranteed by the `SpIBinder` constructor
217 // invariants that `self.0` is always a valid `AIBinder` pointer.
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000218 sys::AIBinder_incStrong(self.0.as_ptr());
Stephen Crane2a3c2502020-06-16 17:48:35 -0700219 }
220 Self(self.0)
221 }
222}
223
224impl Drop for SpIBinder {
225 // We hold a strong reference to the IBinder in SpIBinder and need to give up
226 // this reference on drop.
227 fn drop(&mut self) {
228 unsafe {
229 // Safety: SpIBinder always holds a valid `AIBinder` pointer, so we
230 // know this pointer is safe to pass to `AIBinder_decStrong` here.
231 sys::AIBinder_decStrong(self.as_native_mut());
232 }
233 }
234}
235
Andrew Walbran12400d82021-03-04 17:04:34 +0000236impl<T: AsNative<sys::AIBinder>> IBinderInternal for T {
Alice Ryhl8618c482021-11-09 15:35:35 +0000237 fn prepare_transact(&self) -> Result<Parcel> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700238 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 };
Alice Ryhlfeba6ca2021-08-19 10:47:04 +0000250
Stephen Crane2a3c2502020-06-16 17:48:35 -0700251 status_result(status)?;
Alice Ryhlfeba6ca2021-08-19 10:47:04 +0000252
253 unsafe {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700254 // Safety: At this point, `input` is either a valid, owned `AParcel`
Alice Ryhl268458c2021-09-15 12:56:10 +0000255 // pointer, or null. `OwnedParcel::from_raw` safely handles both cases,
Stephen Crane2a3c2502020-06-16 17:48:35 -0700256 // taking ownership of the parcel.
Alice Ryhl8618c482021-11-09 15:35:35 +0000257 Parcel::from_raw(input).ok_or(StatusCode::UNEXPECTED_NULL)
Alice Ryhlfeba6ca2021-08-19 10:47:04 +0000258 }
259 }
260
261 fn submit_transact(
262 &self,
263 code: TransactionCode,
Alice Ryhl8618c482021-11-09 15:35:35 +0000264 data: Parcel,
Alice Ryhlfeba6ca2021-08-19 10:47:04 +0000265 flags: TransactionFlags,
Alice Ryhl8618c482021-11-09 15:35:35 +0000266 ) -> Result<Parcel> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700267 let mut reply = ptr::null_mut();
268 let status = unsafe {
269 // Safety: `SpIBinder` guarantees that `self` always contains a
270 // valid pointer to an `AIBinder`. Although `IBinder::transact` is
271 // not a const method, it is still safe to cast our immutable
272 // pointer to mutable for the call. First, `IBinder::transact` is
273 // thread-safe, so concurrency is not an issue. The only way that
274 // `transact` can affect any visible, mutable state in the current
275 // process is by calling `onTransact` for a local service. However,
276 // in order for transactions to be thread-safe, this method must
277 // dynamically lock its data before modifying it. We enforce this
278 // property in Rust by requiring `Sync` for remotable objects and
279 // only providing `on_transact` with an immutable reference to
280 // `self`.
281 //
Alice Ryhlfeba6ca2021-08-19 10:47:04 +0000282 // This call takes ownership of the `data` parcel pointer, and
Stephen Crane2a3c2502020-06-16 17:48:35 -0700283 // passes ownership of the `reply` out parameter to its caller. It
284 // does not affect ownership of the `binder` parameter.
285 sys::AIBinder_transact(
286 self.as_native() as *mut sys::AIBinder,
287 code,
Alice Ryhlfeba6ca2021-08-19 10:47:04 +0000288 &mut data.into_raw(),
Stephen Crane2a3c2502020-06-16 17:48:35 -0700289 &mut reply,
290 flags,
291 )
292 };
293 status_result(status)?;
294
295 unsafe {
296 // Safety: `reply` is either a valid `AParcel` pointer or null
297 // after the call to `AIBinder_transact` above, so we can
298 // construct a `Parcel` out of it. `AIBinder_transact` passes
299 // ownership of the `reply` parcel to Rust, so we need to
Alice Ryhl268458c2021-09-15 12:56:10 +0000300 // construct an owned variant.
Alice Ryhl8618c482021-11-09 15:35:35 +0000301 Parcel::from_raw(reply).ok_or(StatusCode::UNEXPECTED_NULL)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700302 }
303 }
304
305 fn is_binder_alive(&self) -> bool {
306 unsafe {
307 // Safety: `SpIBinder` guarantees that `self` always contains a
308 // valid pointer to an `AIBinder`.
309 //
310 // This call does not affect ownership of its pointer parameter.
311 sys::AIBinder_isAlive(self.as_native())
312 }
313 }
314
Janis Danisevskis1323d512021-11-09 07:48:08 -0800315 #[cfg(not(android_vndk))]
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700316 fn set_requesting_sid(&mut self, enable: bool) {
Andrew Walbran12400d82021-03-04 17:04:34 +0000317 unsafe { sys::AIBinder_setRequestingSid(self.as_native_mut(), enable) };
Janis Danisevskis798a09a2020-08-18 08:35:38 -0700318 }
319
Stephen Crane2a3c2502020-06-16 17:48:35 -0700320 fn dump<F: AsRawFd>(&mut self, fp: &F, args: &[&str]) -> Result<()> {
321 let args: Vec<_> = args.iter().map(|a| CString::new(*a).unwrap()).collect();
322 let mut arg_ptrs: Vec<_> = args.iter().map(|a| a.as_ptr()).collect();
323 let status = unsafe {
324 // Safety: `SpIBinder` guarantees that `self` always contains a
325 // valid pointer to an `AIBinder`. `AsRawFd` guarantees that the
326 // file descriptor parameter is always be a valid open file. The
327 // `args` pointer parameter is a valid pointer to an array of C
328 // strings that will outlive the call since `args` lives for the
329 // whole function scope.
330 //
331 // This call does not affect ownership of its binder pointer
332 // parameter and does not take ownership of the file or args array
333 // parameters.
334 sys::AIBinder_dump(
335 self.as_native_mut(),
336 fp.as_raw_fd(),
337 arg_ptrs.as_mut_ptr(),
338 arg_ptrs.len().try_into().unwrap(),
339 )
340 };
341 status_result(status)
342 }
343
344 fn get_extension(&mut self) -> Result<Option<SpIBinder>> {
345 let mut out = ptr::null_mut();
346 let status = unsafe {
347 // Safety: `SpIBinder` guarantees that `self` always contains a
348 // valid pointer to an `AIBinder`. After this call, the `out`
349 // parameter will be either null, or a valid pointer to an
350 // `AIBinder`.
351 //
352 // This call passes ownership of the out pointer to its caller
353 // (assuming it is set to a non-null value).
354 sys::AIBinder_getExtension(self.as_native_mut(), &mut out)
355 };
356 let ibinder = unsafe {
357 // Safety: The call above guarantees that `out` is either null or a
358 // valid, owned pointer to an `AIBinder`, both of which are safe to
359 // pass to `SpIBinder::from_raw`.
360 SpIBinder::from_raw(out)
361 };
362
363 status_result(status)?;
364 Ok(ibinder)
365 }
Andrew Walbran12400d82021-03-04 17:04:34 +0000366}
Stephen Crane2a3c2502020-06-16 17:48:35 -0700367
Andrew Walbran12400d82021-03-04 17:04:34 +0000368impl<T: AsNative<sys::AIBinder>> IBinder for T {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700369 fn link_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> {
370 status_result(unsafe {
371 // Safety: `SpIBinder` guarantees that `self` always contains a
372 // valid pointer to an `AIBinder`. `recipient` can always be
373 // converted into a valid pointer to an
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000374 // `AIBinder_DeathRecipient`.
375 //
376 // The cookie is also the correct pointer, and by calling new_cookie,
377 // we have created a new ref-count to the cookie, which linkToDeath
378 // takes ownership of. Once the DeathRecipient is unlinked for any
379 // reason (including if this call fails), the onUnlinked callback
380 // will consume that ref-count.
Stephen Crane2a3c2502020-06-16 17:48:35 -0700381 sys::AIBinder_linkToDeath(
382 self.as_native_mut(),
383 recipient.as_native_mut(),
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000384 recipient.new_cookie(),
Stephen Crane2a3c2502020-06-16 17:48:35 -0700385 )
386 })
387 }
388
389 fn unlink_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> {
390 status_result(unsafe {
391 // Safety: `SpIBinder` guarantees that `self` always contains a
392 // valid pointer to an `AIBinder`. `recipient` can always be
393 // converted into a valid pointer to an
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800394 // `AIBinder_DeathRecipient`. Any value is safe to pass as the
Stephen Crane2a3c2502020-06-16 17:48:35 -0700395 // cookie, although we depend on this value being set by
396 // `get_cookie` when the death recipient callback is called.
397 sys::AIBinder_unlinkToDeath(
398 self.as_native_mut(),
399 recipient.as_native_mut(),
400 recipient.get_cookie(),
401 )
402 })
403 }
Stephen Crane61366d42022-01-20 17:45:34 -0800404
405 fn ping_binder(&mut self) -> Result<()> {
406 let status = unsafe {
407 // Safety: `SpIBinder` guarantees that `self` always contains a
408 // valid pointer to an `AIBinder`.
409 //
410 // This call does not affect ownership of its pointer parameter.
411 sys::AIBinder_ping(self.as_native_mut())
412 };
413 status_result(status)
414 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700415}
416
417impl Serialize for SpIBinder {
Alice Ryhl8618c482021-11-09 15:35:35 +0000418 fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700419 parcel.write_binder(Some(self))
420 }
421}
422
423impl SerializeOption for SpIBinder {
Alice Ryhl8618c482021-11-09 15:35:35 +0000424 fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700425 parcel.write_binder(this)
426 }
427}
428
429impl SerializeArray for SpIBinder {}
Stephen Crane2a3c2502020-06-16 17:48:35 -0700430
431impl Deserialize for SpIBinder {
Alice Ryhl8618c482021-11-09 15:35:35 +0000432 fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<SpIBinder> {
Andrei Homescu32814372020-08-20 15:36:08 -0700433 parcel
434 .read_binder()
435 .transpose()
436 .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
Stephen Crane2a3c2502020-06-16 17:48:35 -0700437 }
438}
439
440impl DeserializeOption for SpIBinder {
Alice Ryhl8618c482021-11-09 15:35:35 +0000441 fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<SpIBinder>> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700442 parcel.read_binder()
443 }
444}
445
446impl DeserializeArray for SpIBinder {}
Stephen Crane2a3c2502020-06-16 17:48:35 -0700447
448/// A weak reference to a Binder remote object.
449///
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000450/// This struct encapsulates the generic C++ `wp<IBinder>` class. This wrapper
451/// is untyped; typed interface access is implemented by the AIDL compiler.
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000452pub struct WpIBinder(ptr::NonNull<sys::AIBinder_Weak>);
Stephen Crane2a3c2502020-06-16 17:48:35 -0700453
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000454impl fmt::Debug for WpIBinder {
455 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
456 f.pad("WpIBinder")
457 }
458}
459
460/// # Safety
461///
Stephen Cranef03fe3d2021-06-25 15:05:00 -0700462/// A `WpIBinder` is an immutable handle to a C++ IBinder, which is thread-safe.
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000463unsafe impl Send for WpIBinder {}
464
Stephen Cranef03fe3d2021-06-25 15:05:00 -0700465/// # Safety
466///
467/// A `WpIBinder` is an immutable handle to a C++ IBinder, which is thread-safe.
468unsafe impl Sync for WpIBinder {}
469
Stephen Crane2a3c2502020-06-16 17:48:35 -0700470impl WpIBinder {
471 /// Create a new weak reference from an object that can be converted into a
472 /// raw `AIBinder` pointer.
Andrew Walbran8fe3ecc2020-12-15 11:29:58 +0000473 fn new<B: AsNative<sys::AIBinder>>(binder: &mut B) -> WpIBinder {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700474 let ptr = unsafe {
475 // Safety: `SpIBinder` guarantees that `binder` always contains a
476 // valid pointer to an `AIBinder`.
477 sys::AIBinder_Weak_new(binder.as_native_mut())
478 };
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000479 Self(ptr::NonNull::new(ptr).expect("Unexpected null pointer from AIBinder_Weak_new"))
Stephen Crane2a3c2502020-06-16 17:48:35 -0700480 }
Stephen Crane994a0f02020-08-11 14:47:29 -0700481
482 /// Promote this weak reference to a strong reference to the binder object.
483 pub fn promote(&self) -> Option<SpIBinder> {
484 unsafe {
485 // Safety: `WpIBinder` always contains a valid weak reference, so we
486 // can pass this pointer to `AIBinder_Weak_promote`. Returns either
487 // null or an AIBinder owned by the caller, both of which are valid
488 // to pass to `SpIBinder::from_raw`.
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000489 let ptr = sys::AIBinder_Weak_promote(self.0.as_ptr());
Stephen Crane994a0f02020-08-11 14:47:29 -0700490 SpIBinder::from_raw(ptr)
491 }
492 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700493}
494
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800495impl Clone for WpIBinder {
496 fn clone(&self) -> Self {
497 let ptr = unsafe {
498 // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
499 // so this pointer is always safe to pass to `AIBinder_Weak_clone`
500 // (although null is also a safe value to pass to this API).
501 //
502 // We get ownership of the returned pointer, so can construct a new
503 // WpIBinder object from it.
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000504 sys::AIBinder_Weak_clone(self.0.as_ptr())
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800505 };
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000506 Self(ptr::NonNull::new(ptr).expect("Unexpected null pointer from AIBinder_Weak_clone"))
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800507 }
508}
509
510impl Ord for WpIBinder {
511 fn cmp(&self, other: &Self) -> Ordering {
512 let less_than = unsafe {
513 // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
514 // so this pointer is always safe to pass to `AIBinder_Weak_lt`
515 // (null is also safe to pass to this function, but we should never
516 // do that).
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000517 sys::AIBinder_Weak_lt(self.0.as_ptr(), other.0.as_ptr())
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800518 };
519 let greater_than = unsafe {
520 // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer,
521 // so this pointer is always safe to pass to `AIBinder_Weak_lt`
522 // (null is also safe to pass to this function, but we should never
523 // do that).
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000524 sys::AIBinder_Weak_lt(other.0.as_ptr(), self.0.as_ptr())
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800525 };
526 if !less_than && !greater_than {
527 Ordering::Equal
528 } else if less_than {
529 Ordering::Less
530 } else {
531 Ordering::Greater
532 }
533 }
534}
535
536impl PartialOrd for WpIBinder {
537 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
538 Some(self.cmp(other))
539 }
540}
541
542impl PartialEq for WpIBinder {
543 fn eq(&self, other: &Self) -> bool {
544 self.cmp(other) == Ordering::Equal
545 }
546}
547
548impl Eq for WpIBinder {}
549
Andrew Walbran5e8dfa32020-12-16 12:50:06 +0000550impl Drop for WpIBinder {
551 fn drop(&mut self) {
552 unsafe {
553 // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, so we
554 // know this pointer is safe to pass to `AIBinder_Weak_delete` here.
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000555 sys::AIBinder_Weak_delete(self.0.as_ptr());
Andrew Walbran5e8dfa32020-12-16 12:50:06 +0000556 }
557 }
558}
559
Stephen Crane2a3c2502020-06-16 17:48:35 -0700560/// Rust wrapper around DeathRecipient objects.
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000561///
562/// The cookie in this struct represents an Arc<F> for the owned callback.
563/// This struct owns a ref-count of it, and so does every binder that we
564/// have been linked with.
Stephen Crane2a3c2502020-06-16 17:48:35 -0700565#[repr(C)]
566pub struct DeathRecipient {
567 recipient: *mut sys::AIBinder_DeathRecipient,
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000568 cookie: *mut c_void,
569 vtable: &'static DeathRecipientVtable,
570}
571
572struct DeathRecipientVtable {
573 cookie_incr_refcount: unsafe extern "C" fn(*mut c_void),
574 cookie_decr_refcount: unsafe extern "C" fn(*mut c_void),
Stephen Crane2a3c2502020-06-16 17:48:35 -0700575}
576
577impl DeathRecipient {
578 /// Create a new death recipient that will call the given callback when its
579 /// associated object dies.
580 pub fn new<F>(callback: F) -> DeathRecipient
581 where
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000582 F: Fn() + Send + Sync + 'static,
Stephen Crane2a3c2502020-06-16 17:48:35 -0700583 {
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000584 let callback: *const F = Arc::into_raw(Arc::new(callback));
Stephen Crane2a3c2502020-06-16 17:48:35 -0700585 let recipient = unsafe {
586 // Safety: The function pointer is a valid death recipient callback.
587 //
588 // This call returns an owned `AIBinder_DeathRecipient` pointer
589 // which must be destroyed via `AIBinder_DeathRecipient_delete` when
590 // no longer needed.
591 sys::AIBinder_DeathRecipient_new(Some(Self::binder_died::<F>))
592 };
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000593 unsafe {
594 // Safety: The function pointer is a valid onUnlinked callback.
595 //
596 // All uses of linkToDeath in this file correctly increment the
597 // ref-count that this onUnlinked callback will decrement.
598 sys::AIBinder_DeathRecipient_setOnUnlinked(recipient, Some(Self::cookie_decr_refcount::<F>));
599 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700600 DeathRecipient {
601 recipient,
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000602 cookie: callback as *mut c_void,
603 vtable: &DeathRecipientVtable {
604 cookie_incr_refcount: Self::cookie_incr_refcount::<F>,
605 cookie_decr_refcount: Self::cookie_decr_refcount::<F>,
606 },
Stephen Crane2a3c2502020-06-16 17:48:35 -0700607 }
608 }
609
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000610 /// Increment the ref-count for the cookie and return it.
611 ///
612 /// # Safety
613 ///
614 /// The caller must handle the returned ref-count correctly.
615 unsafe fn new_cookie(&self) -> *mut c_void {
616 (self.vtable.cookie_incr_refcount)(self.cookie);
617
618 // Return a raw pointer with ownership of a ref-count
619 self.cookie
620 }
621
Stephen Crane2a3c2502020-06-16 17:48:35 -0700622 /// Get the opaque cookie that identifies this death recipient.
623 ///
624 /// This cookie will be used to link and unlink this death recipient to a
625 /// binder object and will be passed to the `binder_died` callback as an
626 /// opaque userdata pointer.
627 fn get_cookie(&self) -> *mut c_void {
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000628 self.cookie
Stephen Crane2a3c2502020-06-16 17:48:35 -0700629 }
630
631 /// Callback invoked from C++ when the binder object dies.
632 ///
633 /// # Safety
634 ///
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000635 /// The `cookie` parameter must be the cookie for an Arc<F> and
636 /// the caller must hold a ref-count to it.
Stephen Crane2a3c2502020-06-16 17:48:35 -0700637 unsafe extern "C" fn binder_died<F>(cookie: *mut c_void)
638 where
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000639 F: Fn() + Send + Sync + 'static,
Stephen Crane2a3c2502020-06-16 17:48:35 -0700640 {
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000641 let callback = (cookie as *const F).as_ref().unwrap();
Stephen Crane2a3c2502020-06-16 17:48:35 -0700642 callback();
643 }
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000644
645 /// Callback that decrements the ref-count.
646 /// This is invoked from C++ when a binder is unlinked.
647 ///
648 /// # Safety
649 ///
650 /// The `cookie` parameter must be the cookie for an Arc<F> and
651 /// the owner must give up a ref-count to it.
652 unsafe extern "C" fn cookie_decr_refcount<F>(cookie: *mut c_void)
653 where
654 F: Fn() + Send + Sync + 'static,
655 {
656 drop(Arc::from_raw(cookie as *const F));
657 }
658
659 /// Callback that increments the ref-count.
660 ///
661 /// # Safety
662 ///
663 /// The `cookie` parameter must be the cookie for an Arc<F> and
664 /// the owner must handle the created ref-count properly.
665 unsafe extern "C" fn cookie_incr_refcount<F>(cookie: *mut c_void)
666 where
667 F: Fn() + Send + Sync + 'static,
668 {
669 let arc = mem::ManuallyDrop::new(Arc::from_raw(cookie as *const F));
670 mem::forget(Arc::clone(&arc));
671 }
Stephen Crane2a3c2502020-06-16 17:48:35 -0700672}
673
674/// # Safety
675///
676/// A `DeathRecipient` is always constructed with a valid raw pointer to an
677/// `AIBinder_DeathRecipient`, so it is always type-safe to extract this
678/// pointer.
679unsafe impl AsNative<sys::AIBinder_DeathRecipient> for DeathRecipient {
680 fn as_native(&self) -> *const sys::AIBinder_DeathRecipient {
681 self.recipient
682 }
683
684 fn as_native_mut(&mut self) -> *mut sys::AIBinder_DeathRecipient {
685 self.recipient
686 }
687}
688
689impl Drop for DeathRecipient {
690 fn drop(&mut self) {
691 unsafe {
692 // Safety: `self.recipient` is always a valid, owned
693 // `AIBinder_DeathRecipient` pointer returned by
694 // `AIBinder_DeathRecipient_new` when `self` was created. This
695 // delete method can only be called once when `self` is dropped.
696 sys::AIBinder_DeathRecipient_delete(self.recipient);
Alice Ryhlea9d9d22021-08-27 07:51:30 +0000697
698 // Safety: We own a ref-count to the cookie, and so does every
699 // linked binder. This call gives up our ref-count. The linked
700 // binders should already have given up their ref-count, or should
701 // do so shortly.
702 (self.vtable.cookie_decr_refcount)(self.cookie)
Stephen Crane2a3c2502020-06-16 17:48:35 -0700703 }
704 }
705}
706
707/// Generic interface to remote binder objects.
708///
709/// Corresponds to the C++ `BpInterface` class.
710pub trait Proxy: Sized + Interface {
711 /// The Binder interface descriptor string.
712 ///
713 /// This string is a unique identifier for a Binder interface, and should be
714 /// the same between all implementations of that interface.
715 fn get_descriptor() -> &'static str;
716
717 /// Create a new interface from the given proxy, if it matches the expected
718 /// type of this interface.
719 fn from_binder(binder: SpIBinder) -> Result<Self>;
720}
721
722/// # Safety
723///
724/// This is a convenience method that wraps `AsNative` for `SpIBinder` to allow
725/// invocation of `IBinder` methods directly from `Interface` objects. It shares
726/// the same safety as the implementation for `SpIBinder`.
727unsafe impl<T: Proxy> AsNative<sys::AIBinder> for T {
728 fn as_native(&self) -> *const sys::AIBinder {
729 self.as_binder().as_native()
730 }
731
732 fn as_native_mut(&mut self) -> *mut sys::AIBinder {
733 self.as_binder().as_native_mut()
734 }
735}
736
737/// Retrieve an existing service, blocking for a few seconds if it doesn't yet
738/// exist.
739pub fn get_service(name: &str) -> Option<SpIBinder> {
740 let name = CString::new(name).ok()?;
741 unsafe {
742 // Safety: `AServiceManager_getService` returns either a null pointer or
743 // a valid pointer to an owned `AIBinder`. Either of these values is
744 // safe to pass to `SpIBinder::from_raw`.
745 SpIBinder::from_raw(sys::AServiceManager_getService(name.as_ptr()))
746 }
747}
748
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000749/// Retrieve an existing service, or start it if it is configured as a dynamic
750/// service and isn't yet started.
751pub fn wait_for_service(name: &str) -> Option<SpIBinder> {
752 let name = CString::new(name).ok()?;
753 unsafe {
754 // Safety: `AServiceManager_waitforService` returns either a null
755 // pointer or a valid pointer to an owned `AIBinder`. Either of these
756 // values is safe to pass to `SpIBinder::from_raw`.
757 SpIBinder::from_raw(sys::AServiceManager_waitForService(name.as_ptr()))
758 }
759}
760
Stephen Crane2a3c2502020-06-16 17:48:35 -0700761/// Retrieve an existing service for a particular interface, blocking for a few
762/// seconds if it doesn't yet exist.
Stephen Craneddb3e6d2020-12-18 13:27:22 -0800763pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
Stephen Crane2a3c2502020-06-16 17:48:35 -0700764 let service = get_service(name);
765 match service {
766 Some(service) => FromIBinder::try_from(service),
767 None => Err(StatusCode::NAME_NOT_FOUND),
768 }
769}
770
Andrew Walbranc3ce5c32021-06-03 16:15:56 +0000771/// Retrieve an existing service for a particular interface, or start it if it
772/// is configured as a dynamic service and isn't yet started.
773pub fn wait_for_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
774 let service = wait_for_service(name);
775 match service {
776 Some(service) => FromIBinder::try_from(service),
777 None => Err(StatusCode::NAME_NOT_FOUND),
778 }
779}
780
Stephen Crane2a3c2502020-06-16 17:48:35 -0700781/// # Safety
782///
783/// `SpIBinder` guarantees that `binder` always contains a valid pointer to an
784/// `AIBinder`, so we can trivially extract this pointer here.
785unsafe impl AsNative<sys::AIBinder> for SpIBinder {
786 fn as_native(&self) -> *const sys::AIBinder {
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000787 self.0.as_ptr()
Stephen Crane2a3c2502020-06-16 17:48:35 -0700788 }
789
790 fn as_native_mut(&mut self) -> *mut sys::AIBinder {
Alice Ryhl8dde9bc2021-08-16 16:57:10 +0000791 self.0.as_ptr()
Stephen Crane2a3c2502020-06-16 17:48:35 -0700792 }
793}