diff options
Diffstat (limited to 'libs/binder/rust/src/native.rs')
-rw-r--r-- | libs/binder/rust/src/native.rs | 415 |
1 files changed, 0 insertions, 415 deletions
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs deleted file mode 100644 index 39201298c3..0000000000 --- a/libs/binder/rust/src/native.rs +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -use crate::binder::{AsNative, Interface, InterfaceClassMethods, Remotable, Stability, TransactionCode}; -use crate::error::{status_result, status_t, Result, StatusCode}; -use crate::parcel::{Parcel, Serialize}; -use crate::proxy::SpIBinder; -use crate::sys; - -use std::convert::TryFrom; -use std::ffi::{c_void, CString}; -use std::mem::ManuallyDrop; -use std::ops::Deref; - -/// Rust wrapper around Binder remotable objects. -/// -/// Implements the C++ `BBinder` class, and therefore implements the C++ -/// `IBinder` interface. -#[repr(C)] -pub struct Binder<T: Remotable> { - ibinder: *mut sys::AIBinder, - rust_object: *mut T, -} - -/// # Safety -/// -/// A `Binder<T>` is a pair of unique owning pointers to two values: -/// * a C++ ABBinder which the C++ API guarantees can be passed between threads -/// * a Rust object which implements `Remotable`; this trait requires `Send + Sync` -/// -/// Both pointers are unique (never escape the `Binder<T>` object and are not copied) -/// so we can essentially treat `Binder<T>` as a box-like containing the two objects; -/// the box-like object inherits `Send` from the two inner values, similarly -/// to how `Box<T>` is `Send` if `T` is `Send`. -unsafe impl<T: Remotable> Send for Binder<T> {} - -impl<T: Remotable> Binder<T> { - /// Create a new Binder remotable object with default stability - /// - /// This moves the `rust_object` into an owned [`Box`] and Binder will - /// manage its lifetime. - pub fn new(rust_object: T) -> Binder<T> { - Self::new_with_stability(rust_object, Stability::default()) - } - - /// Create a new Binder remotable object with the given stability - /// - /// This moves the `rust_object` into an owned [`Box`] and Binder will - /// manage its lifetime. - pub fn new_with_stability(rust_object: T, stability: Stability) -> Binder<T> { - let class = T::get_class(); - let rust_object = Box::into_raw(Box::new(rust_object)); - let ibinder = unsafe { - // Safety: `AIBinder_new` expects a valid class pointer (which we - // initialize via `get_class`), and an arbitrary pointer - // argument. The caller owns the returned `AIBinder` pointer, which - // is a strong reference to a `BBinder`. This reference should be - // decremented via `AIBinder_decStrong` when the reference lifetime - // ends. - sys::AIBinder_new(class.into(), rust_object as *mut c_void) - }; - let mut binder = Binder { - ibinder, - rust_object, - }; - binder.mark_stability(stability); - binder - } - - /// Set the extension of a binder interface. This allows a downstream - /// developer to add an extension to an interface without modifying its - /// interface file. This should be called immediately when the object is - /// created before it is passed to another thread. - /// - /// # Examples - /// - /// For instance, imagine if we have this Binder AIDL interface definition: - /// interface IFoo { void doFoo(); } - /// - /// If an unrelated owner (perhaps in a downstream codebase) wants to make a - /// change to the interface, they have two options: - /// - /// 1) Historical option that has proven to be BAD! Only the original - /// author of an interface should change an interface. If someone - /// downstream wants additional functionality, they should not ever - /// change the interface or use this method. - /// ```AIDL - /// BAD TO DO: interface IFoo { BAD TO DO - /// BAD TO DO: void doFoo(); BAD TO DO - /// BAD TO DO: + void doBar(); // adding a method BAD TO DO - /// BAD TO DO: } BAD TO DO - /// ``` - /// - /// 2) Option that this method enables! - /// Leave the original interface unchanged (do not change IFoo!). - /// Instead, create a new AIDL interface in a downstream package: - /// ```AIDL - /// package com.<name>; // new functionality in a new package - /// interface IBar { void doBar(); } - /// ``` - /// - /// When registering the interface, add: - /// - /// # use binder::{Binder, Interface}; - /// # type MyFoo = (); - /// # type MyBar = (); - /// # let my_foo = (); - /// # let my_bar = (); - /// let mut foo: Binder<MyFoo> = Binder::new(my_foo); // class in AOSP codebase - /// let bar: Binder<MyBar> = Binder::new(my_bar); // custom extension class - /// foo.set_extension(&mut bar.as_binder()); // use method in Binder - /// - /// Then, clients of `IFoo` can get this extension: - /// - /// # use binder::{declare_binder_interface, Binder, TransactionCode, Parcel}; - /// # trait IBar {} - /// # declare_binder_interface! { - /// # IBar["test"] { - /// # native: BnBar(on_transact), - /// # proxy: BpBar, - /// # } - /// # } - /// # fn on_transact( - /// # service: &dyn IBar, - /// # code: TransactionCode, - /// # data: &Parcel, - /// # reply: &mut Parcel, - /// # ) -> binder::Result<()> { - /// # Ok(()) - /// # } - /// # impl IBar for BpBar {} - /// # impl IBar for Binder<BnBar> {} - /// # fn main() -> binder::Result<()> { - /// # let binder = Binder::new(()); - /// if let Some(barBinder) = binder.get_extension()? { - /// let bar = BpBar::new(barBinder) - /// .expect("Extension was not of type IBar"); - /// } else { - /// // There was no extension - /// } - /// # } - pub fn set_extension(&mut self, extension: &mut SpIBinder) -> Result<()> { - let status = unsafe { - // Safety: `AIBinder_setExtension` expects two valid, mutable - // `AIBinder` pointers. We are guaranteed that both `self` and - // `extension` contain valid `AIBinder` pointers, because they - // cannot be initialized without a valid - // pointer. `AIBinder_setExtension` does not take ownership of - // either parameter. - sys::AIBinder_setExtension(self.as_native_mut(), extension.as_native_mut()) - }; - status_result(status) - } - - /// Retrieve the interface descriptor string for this object's Binder - /// interface. - pub fn get_descriptor() -> &'static str { - T::get_descriptor() - } - - /// Mark this binder object with the given stability guarantee - fn mark_stability(&mut self, stability: Stability) { - match stability { - Stability::Local => self.mark_local_stability(), - Stability::Vintf => { - unsafe { - // Safety: Self always contains a valid `AIBinder` pointer, so - // we can always call this C API safely. - sys::AIBinder_markVintfStability(self.as_native_mut()); - } - } - } - } - - /// Mark this binder object with local stability, which is vendor if we are - /// building for the VNDK and system otherwise. - #[cfg(vendor_ndk)] - fn mark_local_stability(&mut self) { - unsafe { - // Safety: Self always contains a valid `AIBinder` pointer, so - // we can always call this C API safely. - sys::AIBinder_markVendorStability(self.as_native_mut()); - } - } - - /// Mark this binder object with local stability, which is vendor if we are - /// building for the VNDK and system otherwise. - #[cfg(not(vendor_ndk))] - fn mark_local_stability(&mut self) { - unsafe { - // Safety: Self always contains a valid `AIBinder` pointer, so - // we can always call this C API safely. - sys::AIBinder_markSystemStability(self.as_native_mut()); - } - } -} - -impl<T: Remotable> Interface for Binder<T> { - /// Converts the local remotable object into a generic `SpIBinder` - /// reference. - /// - /// The resulting `SpIBinder` will hold its own strong reference to this - /// remotable object, which will prevent the object from being dropped while - /// the `SpIBinder` is alive. - fn as_binder(&self) -> SpIBinder { - unsafe { - // Safety: `self.ibinder` is guaranteed to always be a valid pointer - // to an `AIBinder` by the `Binder` constructor. We are creating a - // copy of the `self.ibinder` strong reference, but - // `SpIBinder::from_raw` assumes it receives an owned pointer with - // its own strong reference. We first increment the reference count, - // so that the new `SpIBinder` will be tracked as a new reference. - sys::AIBinder_incStrong(self.ibinder); - SpIBinder::from_raw(self.ibinder).unwrap() - } - } -} - -impl<T: Remotable> InterfaceClassMethods for Binder<T> { - fn get_descriptor() -> &'static str { - <T as Remotable>::get_descriptor() - } - - /// Called whenever a transaction needs to be processed by a local - /// implementation. - /// - /// # Safety - /// - /// Must be called with a non-null, valid pointer to a local `AIBinder` that - /// contains a `T` pointer in its user data. The `data` and `reply` parcel - /// parameters must be valid pointers to `AParcel` objects. This method does - /// not take ownership of any of its parameters. - /// - /// These conditions hold when invoked by `ABBinder::onTransact`. - unsafe extern "C" fn on_transact( - binder: *mut sys::AIBinder, - code: u32, - data: *const sys::AParcel, - reply: *mut sys::AParcel, - ) -> status_t { - let res = { - let mut reply = Parcel::borrowed(reply).unwrap(); - let data = Parcel::borrowed(data as *mut sys::AParcel).unwrap(); - let object = sys::AIBinder_getUserData(binder); - let binder: &T = &*(object as *const T); - binder.on_transact(code, &data, &mut reply) - }; - match res { - Ok(()) => 0i32, - Err(e) => e as i32, - } - } - - /// Called whenever an `AIBinder` object is no longer referenced and needs - /// destroyed. - /// - /// # Safety - /// - /// Must be called with a valid pointer to a `T` object. After this call, - /// the pointer will be invalid and should not be dereferenced. - unsafe extern "C" fn on_destroy(object: *mut c_void) { - Box::from_raw(object as *mut T); - } - - /// Called whenever a new, local `AIBinder` object is needed of a specific - /// class. - /// - /// Constructs the user data pointer that will be stored in the object, - /// which will be a heap-allocated `T` object. - /// - /// # Safety - /// - /// Must be called with a valid pointer to a `T` object allocated via `Box`. - unsafe extern "C" fn on_create(args: *mut c_void) -> *mut c_void { - // We just return the argument, as it is already a pointer to the rust - // object created by Box. - args - } -} - -impl<T: Remotable> Drop for Binder<T> { - // This causes C++ to decrease the strong ref count of the `AIBinder` - // object. We specifically do not drop the `rust_object` here. When C++ - // actually destroys the object, it calls `on_destroy` and we can drop the - // `rust_object` then. - fn drop(&mut self) { - unsafe { - // Safety: When `self` is dropped, we can no longer access the - // reference, so can decrement the reference count. `self.ibinder` - // is always a valid `AIBinder` pointer, so is valid to pass to - // `AIBinder_decStrong`. - sys::AIBinder_decStrong(self.ibinder); - } - } -} - -impl<T: Remotable> Deref for Binder<T> { - type Target = T; - - fn deref(&self) -> &Self::Target { - unsafe { - // Safety: While `self` is alive, the reference count of the - // underlying object is > 0 and therefore `on_destroy` cannot be - // called. Therefore while `self` is alive, we know that - // `rust_object` is still a valid pointer to a heap allocated object - // of type `T`. - &*self.rust_object - } - } -} - -impl<B: Remotable> Serialize for Binder<B> { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - parcel.write_binder(Some(&self.as_binder())) - } -} - -// This implementation is an idiomatic implementation of the C++ -// `IBinder::localBinder` interface if the binder object is a Rust binder -// service. -impl<B: Remotable> TryFrom<SpIBinder> for Binder<B> { - type Error = StatusCode; - - fn try_from(mut ibinder: SpIBinder) -> Result<Self> { - let class = B::get_class(); - if Some(class) != ibinder.get_class() { - return Err(StatusCode::BAD_TYPE); - } - let userdata = unsafe { - // Safety: `SpIBinder` always holds a valid pointer pointer to an - // `AIBinder`, which we can safely pass to - // `AIBinder_getUserData`. `ibinder` retains ownership of the - // returned pointer. - sys::AIBinder_getUserData(ibinder.as_native_mut()) - }; - if userdata.is_null() { - return Err(StatusCode::UNEXPECTED_NULL); - } - // We are transferring the ownership of the AIBinder into the new Binder - // object. - let mut ibinder = ManuallyDrop::new(ibinder); - Ok(Binder { - ibinder: ibinder.as_native_mut(), - rust_object: userdata as *mut B, - }) - } -} - -/// # Safety -/// -/// The constructor for `Binder` guarantees that `self.ibinder` will contain a -/// valid, non-null pointer to an `AIBinder`, so this implementation is type -/// safe. `self.ibinder` will remain valid for the entire lifetime of `self` -/// because we hold a strong reference to the `AIBinder` until `self` is -/// dropped. -unsafe impl<B: Remotable> AsNative<sys::AIBinder> for Binder<B> { - fn as_native(&self) -> *const sys::AIBinder { - self.ibinder - } - - fn as_native_mut(&mut self) -> *mut sys::AIBinder { - self.ibinder - } -} - -/// Register a new service with the default service manager. -/// -/// Registers the given binder object with the given identifier. If successful, -/// this service can then be retrieved using that identifier. -pub fn add_service(identifier: &str, mut binder: SpIBinder) -> Result<()> { - let instance = CString::new(identifier).unwrap(); - let status = unsafe { - // Safety: `AServiceManager_addService` expects valid `AIBinder` and C - // string pointers. Caller retains ownership of both - // pointers. `AServiceManager_addService` creates a new strong reference - // and copies the string, so both pointers need only be valid until the - // call returns. - sys::AServiceManager_addService(binder.as_native_mut(), instance.as_ptr()) - }; - status_result(status) -} - -/// Tests often create a base BBinder instance; so allowing the unit -/// type to be remotable translates nicely to Binder::new(()). -impl Remotable for () { - fn get_descriptor() -> &'static str { - "" - } - - fn on_transact( - &self, - _code: TransactionCode, - _data: &Parcel, - _reply: &mut Parcel, - ) -> Result<()> { - Ok(()) - } - - binder_fn_get_class!(Binder::<Self>); -} - -impl Interface for () {} |