diff options
Diffstat (limited to 'libs/binder/rust/src')
-rw-r--r-- | libs/binder/rust/src/binder.rs | 910 | ||||
-rw-r--r-- | libs/binder/rust/src/error.rs | 373 | ||||
-rw-r--r-- | libs/binder/rust/src/lib.rs | 133 | ||||
-rw-r--r-- | libs/binder/rust/src/native.rs | 415 | ||||
-rw-r--r-- | libs/binder/rust/src/parcel.rs | 562 | ||||
-rw-r--r-- | libs/binder/rust/src/parcel/file_descriptor.rs | 127 | ||||
-rw-r--r-- | libs/binder/rust/src/parcel/parcelable.rs | 989 | ||||
-rw-r--r-- | libs/binder/rust/src/proxy.rs | 678 | ||||
-rw-r--r-- | libs/binder/rust/src/state.rs | 133 |
9 files changed, 0 insertions, 4320 deletions
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs deleted file mode 100644 index 695a83e414..0000000000 --- a/libs/binder/rust/src/binder.rs +++ /dev/null @@ -1,910 +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. - */ - -//! Trait definitions for binder objects - -use crate::error::{status_t, Result, StatusCode}; -use crate::parcel::Parcel; -use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder}; -use crate::sys; - -use std::borrow::Borrow; -use std::cmp::Ordering; -use std::ffi::{c_void, CStr, CString}; -use std::fmt; -use std::marker::PhantomData; -use std::ops::Deref; -use std::os::raw::c_char; -use std::os::unix::io::AsRawFd; -use std::ptr; - -/// Binder action to perform. -/// -/// This must be a number between [`FIRST_CALL_TRANSACTION`] and -/// [`LAST_CALL_TRANSACTION`]. -pub type TransactionCode = u32; - -/// Additional operation flags. -/// -/// `FLAG_*` values. -pub type TransactionFlags = u32; - -/// Super-trait for Binder interfaces. -/// -/// This trait allows conversion of a Binder interface trait object into an -/// IBinder object for IPC calls. All Binder remotable interface (i.e. AIDL -/// interfaces) must implement this trait. -/// -/// This is equivalent `IInterface` in C++. -pub trait Interface: Send { - /// Convert this binder object into a generic [`SpIBinder`] reference. - fn as_binder(&self) -> SpIBinder { - panic!("This object was not a Binder object and cannot be converted into an SpIBinder.") - } -} - -/// Interface stability promise -/// -/// An interface can promise to be a stable vendor interface ([`Vintf`]), or -/// makes no stability guarantees ([`Local`]). [`Local`] is -/// currently the default stability. -pub enum Stability { - /// Default stability, visible to other modules in the same compilation - /// context (e.g. modules on system.img) - Local, - - /// A Vendor Interface Object, which promises to be stable - Vintf, -} - -impl Default for Stability { - fn default() -> Self { - Stability::Local - } -} - -/// A local service that can be remotable via Binder. -/// -/// An object that implement this interface made be made into a Binder service -/// via `Binder::new(object)`. -/// -/// This is a low-level interface that should normally be automatically -/// generated from AIDL via the [`declare_binder_interface!`] macro. When using -/// the AIDL backend, users need only implement the high-level AIDL-defined -/// interface. The AIDL compiler then generates a container struct that wraps -/// the user-defined service and implements `Remotable`. -pub trait Remotable: Send + Sync { - /// The Binder interface descriptor string. - /// - /// This string is a unique identifier for a Binder interface, and should be - /// the same between all implementations of that interface. - fn get_descriptor() -> &'static str; - - /// Handle and reply to a request to invoke a transaction on this object. - /// - /// `reply` may be [`None`] if the sender does not expect a reply. - fn on_transact(&self, code: TransactionCode, data: &Parcel, reply: &mut Parcel) -> Result<()>; - - /// Retrieve the class of this remote object. - /// - /// This method should always return the same InterfaceClass for the same - /// type. - fn get_class() -> InterfaceClass; -} - -/// First transaction code available for user commands (inclusive) -pub const FIRST_CALL_TRANSACTION: TransactionCode = sys::FIRST_CALL_TRANSACTION; -/// Last transaction code available for user commands (inclusive) -pub const LAST_CALL_TRANSACTION: TransactionCode = sys::LAST_CALL_TRANSACTION; - -/// Corresponds to TF_ONE_WAY -- an asynchronous call. -pub const FLAG_ONEWAY: TransactionFlags = sys::FLAG_ONEWAY; -/// Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call is made. -pub const FLAG_CLEAR_BUF: TransactionFlags = sys::FLAG_CLEAR_BUF; -/// Set to the vendor flag if we are building for the VNDK, 0 otherwise -pub const FLAG_PRIVATE_LOCAL: TransactionFlags = sys::FLAG_PRIVATE_LOCAL; - -/// Internal interface of binder local or remote objects for making -/// transactions. -/// -/// This trait corresponds to the parts of the interface of the C++ `IBinder` -/// class which are internal implementation details. -pub trait IBinderInternal: IBinder { - /// Is this object still alive? - fn is_binder_alive(&self) -> bool; - - /// Send a ping transaction to this object - fn ping_binder(&mut self) -> Result<()>; - - /// Indicate that the service intends to receive caller security contexts. - fn set_requesting_sid(&mut self, enable: bool); - - /// Dump this object to the given file handle - fn dump<F: AsRawFd>(&mut self, fp: &F, args: &[&str]) -> Result<()>; - - /// Get a new interface that exposes additional extension functionality, if - /// available. - fn get_extension(&mut self) -> Result<Option<SpIBinder>>; - - /// Perform a generic operation with the object. - /// - /// # Arguments - /// * `code` - Transaction code for the operation - /// * `data` - [`Parcel`] with input data - /// * `reply` - Optional [`Parcel`] for reply data - /// * `flags` - Transaction flags, e.g. marking the transaction as - /// asynchronous ([`FLAG_ONEWAY`](FLAG_ONEWAY)) - fn transact<F: FnOnce(&mut Parcel) -> Result<()>>( - &self, - code: TransactionCode, - flags: TransactionFlags, - input_callback: F, - ) -> Result<Parcel>; -} - -/// Interface of binder local or remote objects. -/// -/// This trait corresponds to the parts of the interface of the C++ `IBinder` -/// class which are public. -pub trait IBinder { - /// Register the recipient for a notification if this binder - /// goes away. If this binder object unexpectedly goes away - /// (typically because its hosting process has been killed), - /// then the `DeathRecipient`'s callback will be called. - /// - /// You will only receive death notifications for remote binders, - /// as local binders by definition can't die without you dying as well. - /// Trying to use this function on a local binder will result in an - /// INVALID_OPERATION code being returned and nothing happening. - /// - /// This link always holds a weak reference to its recipient. - fn link_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()>; - - /// Remove a previously registered death notification. - /// The recipient will no longer be called if this object - /// dies. - fn unlink_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()>; -} - -/// Opaque reference to the type of a Binder interface. -/// -/// This object encapsulates the Binder interface descriptor string, along with -/// the binder transaction callback, if the class describes a local service. -/// -/// A Binder remotable object may only have a single interface class, and any -/// given object can only be associated with one class. Two objects with -/// different classes are incompatible, even if both classes have the same -/// interface descriptor. -#[derive(Copy, Clone, PartialEq, Eq)] -pub struct InterfaceClass(*const sys::AIBinder_Class); - -impl InterfaceClass { - /// Get a Binder NDK `AIBinder_Class` pointer for this object type. - /// - /// Note: the returned pointer will not be constant. Calling this method - /// multiple times for the same type will result in distinct class - /// pointers. A static getter for this value is implemented in - /// [`declare_binder_interface!`]. - pub fn new<I: InterfaceClassMethods>() -> InterfaceClass { - let descriptor = CString::new(I::get_descriptor()).unwrap(); - let ptr = unsafe { - // Safety: `AIBinder_Class_define` expects a valid C string, and - // three valid callback functions, all non-null pointers. The C - // string is copied and need not be valid for longer than the call, - // so we can drop it after the call. We can safely assign null to - // the onDump and handleShellCommand callbacks as long as the class - // pointer was non-null. Rust None for a Option<fn> is guaranteed to - // be a NULL pointer. Rust retains ownership of the pointer after it - // is defined. - let class = sys::AIBinder_Class_define( - descriptor.as_ptr(), - Some(I::on_create), - Some(I::on_destroy), - Some(I::on_transact), - ); - if class.is_null() { - panic!("Expected non-null class pointer from AIBinder_Class_define!"); - } - sys::AIBinder_Class_setOnDump(class, None); - sys::AIBinder_Class_setHandleShellCommand(class, None); - class - }; - InterfaceClass(ptr) - } - - /// Construct an `InterfaceClass` out of a raw, non-null `AIBinder_Class` - /// pointer. - /// - /// # Safety - /// - /// This function is safe iff `ptr` is a valid, non-null pointer to an - /// `AIBinder_Class`. - pub(crate) unsafe fn from_ptr(ptr: *const sys::AIBinder_Class) -> InterfaceClass { - InterfaceClass(ptr) - } - - /// Get the interface descriptor string of this class. - pub fn get_descriptor(&self) -> String { - unsafe { - // SAFETY: The descriptor returned by AIBinder_Class_getDescriptor - // is always a two-byte null terminated sequence of u16s. Thus, we - // can continue reading from the pointer until we hit a null value, - // and this pointer can be a valid slice if the slice length is <= - // the number of u16 elements before the null terminator. - - let raw_descriptor: *const c_char = sys::AIBinder_Class_getDescriptor(self.0); - CStr::from_ptr(raw_descriptor) - .to_str() - .expect("Expected valid UTF-8 string from AIBinder_Class_getDescriptor") - .into() - } - } -} - -impl From<InterfaceClass> for *const sys::AIBinder_Class { - fn from(class: InterfaceClass) -> *const sys::AIBinder_Class { - class.0 - } -} - -/// Strong reference to a binder object -pub struct Strong<I: FromIBinder + ?Sized>(Box<I>); - -impl<I: FromIBinder + ?Sized> Strong<I> { - /// Create a new strong reference to the provided binder object - pub fn new(binder: Box<I>) -> Self { - Self(binder) - } - - /// Construct a new weak reference to this binder - pub fn downgrade(this: &Strong<I>) -> Weak<I> { - Weak::new(this) - } -} - -impl<I: FromIBinder + ?Sized> Clone for Strong<I> { - fn clone(&self) -> Self { - // Since we hold a strong reference, we should always be able to create - // a new strong reference to the same interface type, so try_from() - // should never fail here. - FromIBinder::try_from(self.0.as_binder()).unwrap() - } -} - -impl<I: FromIBinder + ?Sized> Borrow<I> for Strong<I> { - fn borrow(&self) -> &I { - &self.0 - } -} - -impl<I: FromIBinder + ?Sized> AsRef<I> for Strong<I> { - fn as_ref(&self) -> &I { - &self.0 - } -} - -impl<I: FromIBinder + ?Sized> Deref for Strong<I> { - type Target = I; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl<I: FromIBinder + fmt::Debug + ?Sized> fmt::Debug for Strong<I> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&**self, f) - } -} - -impl<I: FromIBinder + ?Sized> Ord for Strong<I> { - fn cmp(&self, other: &Self) -> Ordering { - self.0.as_binder().cmp(&other.0.as_binder()) - } -} - -impl<I: FromIBinder + ?Sized> PartialOrd for Strong<I> { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - self.0.as_binder().partial_cmp(&other.0.as_binder()) - } -} - -impl<I: FromIBinder + ?Sized> PartialEq for Strong<I> { - fn eq(&self, other: &Self) -> bool { - self.0.as_binder().eq(&other.0.as_binder()) - } -} - -impl<I: FromIBinder + ?Sized> Eq for Strong<I> {} - -/// Weak reference to a binder object -#[derive(Debug)] -pub struct Weak<I: FromIBinder + ?Sized> { - weak_binder: WpIBinder, - interface_type: PhantomData<I>, -} - -impl<I: FromIBinder + ?Sized> Weak<I> { - /// Construct a new weak reference from a strong reference - fn new(binder: &Strong<I>) -> Self { - let weak_binder = binder.as_binder().downgrade(); - Weak { - weak_binder, - interface_type: PhantomData, - } - } - - /// Upgrade this weak reference to a strong reference if the binder object - /// is still alive - pub fn upgrade(&self) -> Result<Strong<I>> { - self.weak_binder - .promote() - .ok_or(StatusCode::DEAD_OBJECT) - .and_then(FromIBinder::try_from) - } -} - -impl<I: FromIBinder + ?Sized> Clone for Weak<I> { - fn clone(&self) -> Self { - Self { - weak_binder: self.weak_binder.clone(), - interface_type: PhantomData, - } - } -} - -impl<I: FromIBinder + ?Sized> Ord for Weak<I> { - fn cmp(&self, other: &Self) -> Ordering { - self.weak_binder.cmp(&other.weak_binder) - } -} - -impl<I: FromIBinder + ?Sized> PartialOrd for Weak<I> { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - self.weak_binder.partial_cmp(&other.weak_binder) - } -} - -impl<I: FromIBinder + ?Sized> PartialEq for Weak<I> { - fn eq(&self, other: &Self) -> bool { - self.weak_binder == other.weak_binder - } -} - -impl<I: FromIBinder + ?Sized> Eq for Weak<I> {} - -/// Create a function implementing a static getter for an interface class. -/// -/// Each binder interface (i.e. local [`Remotable`] service or remote proxy -/// [`Interface`]) must have global, static class that uniquely identifies -/// it. This macro implements an [`InterfaceClass`] getter to simplify these -/// implementations. -/// -/// The type of a structure that implements [`InterfaceClassMethods`] must be -/// passed to this macro. For local services, this should be `Binder<Self>` -/// since [`Binder`] implements [`InterfaceClassMethods`]. -/// -/// # Examples -/// -/// When implementing a local [`Remotable`] service `ExampleService`, the -/// `get_class` method is required in the [`Remotable`] impl block. This macro -/// should be used as follows to implement this functionality: -/// -/// ```rust -/// impl Remotable for ExampleService { -/// fn get_descriptor() -> &'static str { -/// "android.os.IExampleInterface" -/// } -/// -/// fn on_transact( -/// &self, -/// code: TransactionCode, -/// data: &Parcel, -/// reply: &mut Parcel, -/// ) -> Result<()> { -/// // ... -/// } -/// -/// binder_fn_get_class!(Binder<Self>); -/// } -/// ``` -macro_rules! binder_fn_get_class { - ($class:ty) => { - binder_fn_get_class!($crate::InterfaceClass::new::<$class>()); - }; - - ($constructor:expr) => { - fn get_class() -> $crate::InterfaceClass { - static CLASS_INIT: std::sync::Once = std::sync::Once::new(); - static mut CLASS: Option<$crate::InterfaceClass> = None; - - CLASS_INIT.call_once(|| unsafe { - // Safety: This assignment is guarded by the `CLASS_INIT` `Once` - // variable, and therefore is thread-safe, as it can only occur - // once. - CLASS = Some($constructor); - }); - unsafe { - // Safety: The `CLASS` variable can only be mutated once, above, - // and is subsequently safe to read from any thread. - CLASS.unwrap() - } - } - }; -} - -pub trait InterfaceClassMethods { - /// Get the interface descriptor string for this object type. - fn get_descriptor() -> &'static str - where - Self: Sized; - - /// Called during construction of a new `AIBinder` object of this interface - /// class. - /// - /// The opaque pointer parameter will be the parameter provided to - /// `AIBinder_new`. Returns an opaque userdata to be associated with the new - /// `AIBinder` object. - /// - /// # Safety - /// - /// Callback called from C++. The parameter argument provided to - /// `AIBinder_new` must match the type expected here. The `AIBinder` object - /// will take ownership of the returned pointer, which it will free via - /// `on_destroy`. - unsafe extern "C" fn on_create(args: *mut c_void) -> *mut c_void; - - /// Called when a transaction needs to be processed by the local service - /// implementation. - /// - /// # Safety - /// - /// Callback called from C++. The `binder` parameter must be a valid pointer - /// to a binder object of this class with userdata initialized via this - /// class's `on_create`. The parcel parameters must be valid pointers to - /// parcel objects. - unsafe extern "C" fn on_transact( - binder: *mut sys::AIBinder, - code: u32, - data: *const sys::AParcel, - reply: *mut sys::AParcel, - ) -> status_t; - - /// Called whenever an `AIBinder` object is no longer referenced and needs - /// to be destroyed. - /// - /// # Safety - /// - /// Callback called from C++. The opaque pointer parameter must be the value - /// returned by `on_create` for this class. This function takes ownership of - /// the provided pointer and destroys it. - unsafe extern "C" fn on_destroy(object: *mut c_void); -} - -/// Interface for transforming a generic SpIBinder into a specific remote -/// interface trait. -/// -/// # Example -/// -/// For Binder interface `IFoo`, the following implementation should be made: -/// ```no_run -/// # use binder::{FromIBinder, SpIBinder, Result}; -/// # trait IFoo {} -/// impl FromIBinder for dyn IFoo { -/// fn try_from(ibinder: SpIBinder) -> Result<Box<Self>> { -/// // ... -/// # Err(binder::StatusCode::OK) -/// } -/// } -/// ``` -pub trait FromIBinder: Interface { - /// Try to interpret a generic Binder object as this interface. - /// - /// Returns a trait object for the `Self` interface if this object - /// implements that interface. - fn try_from(ibinder: SpIBinder) -> Result<Strong<Self>>; -} - -/// Trait for transparent Rust wrappers around android C++ native types. -/// -/// The pointer return by this trait's methods should be immediately passed to -/// C++ and not stored by Rust. The pointer is valid only as long as the -/// underlying C++ object is alive, so users must be careful to take this into -/// account, as Rust cannot enforce this. -/// -/// # Safety -/// -/// For this trait to be a correct implementation, `T` must be a valid android -/// C++ type. Since we cannot constrain this via the type system, this trait is -/// marked as unsafe. -pub unsafe trait AsNative<T> { - /// Return a pointer to the native version of `self` - fn as_native(&self) -> *const T; - - /// Return a mutable pointer to the native version of `self` - fn as_native_mut(&mut self) -> *mut T; -} - -unsafe impl<T, V: AsNative<T>> AsNative<T> for Option<V> { - fn as_native(&self) -> *const T { - self.as_ref().map_or(ptr::null(), |v| v.as_native()) - } - - fn as_native_mut(&mut self) -> *mut T { - self.as_mut().map_or(ptr::null_mut(), |v| v.as_native_mut()) - } -} - -/// The features to enable when creating a native Binder. -/// -/// This should always be initialised with a default value, e.g.: -/// ``` -/// # use binder::BinderFeatures; -/// BinderFeatures { -/// set_requesting_sid: true, -/// ..BinderFeatures::default(), -/// } -/// ``` -#[derive(Clone, Debug, Default, Eq, PartialEq)] -pub struct BinderFeatures { - /// Indicates that the service intends to receive caller security contexts. This must be true - /// for `ThreadState::with_calling_sid` to work. - pub set_requesting_sid: bool, - // Ensure that clients include a ..BinderFeatures::default() to preserve backwards compatibility - // when new fields are added. #[non_exhaustive] doesn't work because it prevents struct - // expressions entirely. - #[doc(hidden)] - pub _non_exhaustive: (), -} - -/// Declare typed interfaces for a binder object. -/// -/// Given an interface trait and descriptor string, create a native and remote -/// proxy wrapper for this interface. The native service object (`$native`) -/// implements `Remotable` and will dispatch to the function `$on_transact` to -/// handle transactions. The typed proxy object (`$proxy`) wraps remote binder -/// objects for this interface and can optionally contain additional fields. -/// -/// Assuming the interface trait is `Interface`, `$on_transact` function must -/// have the following type: -/// -/// ``` -/// # use binder::{Interface, TransactionCode, Parcel}; -/// # trait Placeholder { -/// fn on_transact( -/// service: &dyn Interface, -/// code: TransactionCode, -/// data: &Parcel, -/// reply: &mut Parcel, -/// ) -> binder::Result<()>; -/// # } -/// ``` -/// -/// # Examples -/// -/// The following example declares the local service type `BnServiceManager` and -/// a remote proxy type `BpServiceManager` (the `n` and `p` stand for native and -/// proxy respectively) for the `IServiceManager` Binder interface. The -/// interfaces will be identified by the descriptor string -/// "android.os.IServiceManager". The local service will dispatch transactions -/// using the provided function, `on_transact`. -/// -/// ``` -/// use binder::{declare_binder_interface, Binder, Interface, TransactionCode, Parcel}; -/// -/// pub trait IServiceManager: Interface { -/// // remote methods... -/// } -/// -/// declare_binder_interface! { -/// IServiceManager["android.os.IServiceManager"] { -/// native: BnServiceManager(on_transact), -/// proxy: BpServiceManager, -/// } -/// } -/// -/// fn on_transact( -/// service: &dyn IServiceManager, -/// code: TransactionCode, -/// data: &Parcel, -/// reply: &mut Parcel, -/// ) -> binder::Result<()> { -/// // ... -/// Ok(()) -/// } -/// -/// impl IServiceManager for BpServiceManager { -/// // parceling/unparceling code for the IServiceManager emitted here -/// } -/// -/// impl IServiceManager for Binder<BnServiceManager> { -/// // Forward calls to local implementation -/// } -/// ``` -#[macro_export] -macro_rules! declare_binder_interface { - { - $interface:path[$descriptor:expr] { - native: $native:ident($on_transact:path), - proxy: $proxy:ident, - } - } => { - $crate::declare_binder_interface! { - $interface[$descriptor] { - native: $native($on_transact), - proxy: $proxy {}, - stability: $crate::Stability::default(), - } - } - }; - - { - $interface:path[$descriptor:expr] { - native: $native:ident($on_transact:path), - proxy: $proxy:ident, - stability: $stability:expr, - } - } => { - $crate::declare_binder_interface! { - $interface[$descriptor] { - native: $native($on_transact), - proxy: $proxy {}, - stability: $stability, - } - } - }; - - { - $interface:path[$descriptor:expr] { - native: $native:ident($on_transact:path), - proxy: $proxy:ident { - $($fname:ident: $fty:ty = $finit:expr),* - }, - } - } => { - $crate::declare_binder_interface! { - $interface[$descriptor] { - native: $native($on_transact), - proxy: $proxy { - $($fname: $fty = $finit),* - }, - stability: $crate::Stability::default(), - } - } - }; - - { - $interface:path[$descriptor:expr] { - native: $native:ident($on_transact:path), - proxy: $proxy:ident { - $($fname:ident: $fty:ty = $finit:expr),* - }, - stability: $stability:expr, - } - } => { - $crate::declare_binder_interface! { - $interface[$descriptor] { - @doc[concat!("A binder [`Remotable`]($crate::Remotable) that holds an [`", stringify!($interface), "`] object.")] - native: $native($on_transact), - @doc[concat!("A binder [`Proxy`]($crate::Proxy) that holds an [`", stringify!($interface), "`] remote interface.")] - proxy: $proxy { - $($fname: $fty = $finit),* - }, - stability: $stability, - } - } - }; - - { - $interface:path[$descriptor:expr] { - @doc[$native_doc:expr] - native: $native:ident($on_transact:path), - - @doc[$proxy_doc:expr] - proxy: $proxy:ident { - $($fname:ident: $fty:ty = $finit:expr),* - }, - - stability: $stability:expr, - } - } => { - #[doc = $proxy_doc] - pub struct $proxy { - binder: $crate::SpIBinder, - $($fname: $fty,)* - } - - impl $crate::Interface for $proxy { - fn as_binder(&self) -> $crate::SpIBinder { - self.binder.clone() - } - } - - impl $crate::Proxy for $proxy - where - $proxy: $interface, - { - fn get_descriptor() -> &'static str { - $descriptor - } - - fn from_binder(mut binder: $crate::SpIBinder) -> $crate::Result<Self> { - Ok(Self { binder, $($fname: $finit),* }) - } - } - - #[doc = $native_doc] - #[repr(transparent)] - pub struct $native(Box<dyn $interface + Sync + Send + 'static>); - - impl $native { - /// Create a new binder service. - pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T, features: $crate::BinderFeatures) -> $crate::Strong<dyn $interface> { - let mut binder = $crate::Binder::new_with_stability($native(Box::new(inner)), $stability); - $crate::IBinderInternal::set_requesting_sid(&mut binder, features.set_requesting_sid); - $crate::Strong::new(Box::new(binder)) - } - } - - impl $crate::Remotable for $native { - fn get_descriptor() -> &'static str { - $descriptor - } - - fn on_transact(&self, code: $crate::TransactionCode, data: &$crate::Parcel, reply: &mut $crate::Parcel) -> $crate::Result<()> { - match $on_transact(&*self.0, code, data, reply) { - // The C++ backend converts UNEXPECTED_NULL into an exception - Err($crate::StatusCode::UNEXPECTED_NULL) => { - let status = $crate::Status::new_exception( - $crate::ExceptionCode::NULL_POINTER, - None, - ); - reply.write(&status) - }, - result => result - } - } - - fn get_class() -> $crate::InterfaceClass { - static CLASS_INIT: std::sync::Once = std::sync::Once::new(); - static mut CLASS: Option<$crate::InterfaceClass> = None; - - CLASS_INIT.call_once(|| unsafe { - // Safety: This assignment is guarded by the `CLASS_INIT` `Once` - // variable, and therefore is thread-safe, as it can only occur - // once. - CLASS = Some($crate::InterfaceClass::new::<$crate::Binder<$native>>()); - }); - unsafe { - // Safety: The `CLASS` variable can only be mutated once, above, - // and is subsequently safe to read from any thread. - CLASS.unwrap() - } - } - } - - impl $crate::FromIBinder for dyn $interface { - fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<$crate::Strong<dyn $interface>> { - use $crate::AssociateClass; - - let existing_class = ibinder.get_class(); - if let Some(class) = existing_class { - if class != <$native as $crate::Remotable>::get_class() && - class.get_descriptor() == <$native as $crate::Remotable>::get_descriptor() - { - // The binder object's descriptor string matches what we - // expect. We still need to treat this local or already - // associated object as remote, because we can't cast it - // into a Rust service object without a matching class - // pointer. - return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?))); - } - } - - if ibinder.associate_class(<$native as $crate::Remotable>::get_class()) { - let service: $crate::Result<$crate::Binder<$native>> = - std::convert::TryFrom::try_from(ibinder.clone()); - if let Ok(service) = service { - // We were able to associate with our expected class and - // the service is local. - return Ok($crate::Strong::new(Box::new(service))); - } else { - // Service is remote - return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?))); - } - } - - Err($crate::StatusCode::BAD_TYPE.into()) - } - } - - impl $crate::parcel::Serialize for dyn $interface + '_ - where - dyn $interface: $crate::Interface - { - fn serialize(&self, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> { - let binder = $crate::Interface::as_binder(self); - parcel.write(&binder) - } - } - - impl $crate::parcel::SerializeOption for dyn $interface + '_ { - fn serialize_option(this: Option<&Self>, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> { - parcel.write(&this.map($crate::Interface::as_binder)) - } - } - - impl std::fmt::Debug for dyn $interface { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.pad(stringify!($interface)) - } - } - - /// Convert a &dyn $interface to Strong<dyn $interface> - impl std::borrow::ToOwned for dyn $interface { - type Owned = $crate::Strong<dyn $interface>; - fn to_owned(&self) -> Self::Owned { - self.as_binder().into_interface() - .expect(concat!("Error cloning interface ", stringify!($interface))) - } - } - }; -} - -/// Declare an AIDL enumeration. -/// -/// This is mainly used internally by the AIDL compiler. -#[macro_export] -macro_rules! declare_binder_enum { - { - $enum:ident : $backing:ty { - $( $name:ident = $value:expr, )* - } - } => { - #[derive(Debug, Default, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)] - pub struct $enum(pub $backing); - impl $enum { - $( pub const $name: Self = Self($value); )* - } - - impl $crate::parcel::Serialize for $enum { - fn serialize(&self, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> { - parcel.write(&self.0) - } - } - - impl $crate::parcel::SerializeArray for $enum { - fn serialize_array(slice: &[Self], parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> { - let v: Vec<$backing> = slice.iter().map(|x| x.0).collect(); - <$backing as binder::parcel::SerializeArray>::serialize_array(&v[..], parcel) - } - } - - impl $crate::parcel::Deserialize for $enum { - fn deserialize(parcel: &$crate::parcel::Parcel) -> $crate::Result<Self> { - parcel.read().map(Self) - } - } - - impl $crate::parcel::DeserializeArray for $enum { - fn deserialize_array(parcel: &$crate::parcel::Parcel) -> $crate::Result<Option<Vec<Self>>> { - let v: Option<Vec<$backing>> = - <$backing as binder::parcel::DeserializeArray>::deserialize_array(parcel)?; - Ok(v.map(|v| v.into_iter().map(Self).collect())) - } - } - }; -} diff --git a/libs/binder/rust/src/error.rs b/libs/binder/rust/src/error.rs deleted file mode 100644 index 2598ebc804..0000000000 --- a/libs/binder/rust/src/error.rs +++ /dev/null @@ -1,373 +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; -use crate::sys; - -use std::error; -use std::ffi::CStr; -use std::fmt::{Debug, Display, Formatter, Result as FmtResult}; -use std::result; - -pub use sys::binder_status_t as status_t; - -/// Low-level status codes from Android `libutils`. -// All error codes are negative integer values. Derived from the anonymous enum -// in utils/Errors.h -pub use sys::android_c_interface_StatusCode as StatusCode; - -/// A specialized [`Result`](result::Result) for binder operations. -pub type Result<T> = result::Result<T, StatusCode>; - -/// Convert a low-level status code into an empty result. -/// -/// An OK status is converted into an `Ok` result, any other status is converted -/// into an `Err` result holding the status code. -pub fn status_result(status: status_t) -> Result<()> { - match parse_status_code(status) { - StatusCode::OK => Ok(()), - e => Err(e), - } -} - -fn parse_status_code(code: i32) -> StatusCode { - match code { - e if e == StatusCode::OK as i32 => StatusCode::OK, - e if e == StatusCode::NO_MEMORY as i32 => StatusCode::NO_MEMORY, - e if e == StatusCode::INVALID_OPERATION as i32 => StatusCode::INVALID_OPERATION, - e if e == StatusCode::BAD_VALUE as i32 => StatusCode::BAD_VALUE, - e if e == StatusCode::BAD_TYPE as i32 => StatusCode::BAD_TYPE, - e if e == StatusCode::NAME_NOT_FOUND as i32 => StatusCode::NAME_NOT_FOUND, - e if e == StatusCode::PERMISSION_DENIED as i32 => StatusCode::PERMISSION_DENIED, - e if e == StatusCode::NO_INIT as i32 => StatusCode::NO_INIT, - e if e == StatusCode::ALREADY_EXISTS as i32 => StatusCode::ALREADY_EXISTS, - e if e == StatusCode::DEAD_OBJECT as i32 => StatusCode::DEAD_OBJECT, - e if e == StatusCode::FAILED_TRANSACTION as i32 => StatusCode::FAILED_TRANSACTION, - e if e == StatusCode::BAD_INDEX as i32 => StatusCode::BAD_INDEX, - e if e == StatusCode::NOT_ENOUGH_DATA as i32 => StatusCode::NOT_ENOUGH_DATA, - e if e == StatusCode::WOULD_BLOCK as i32 => StatusCode::WOULD_BLOCK, - e if e == StatusCode::TIMED_OUT as i32 => StatusCode::TIMED_OUT, - e if e == StatusCode::UNKNOWN_TRANSACTION as i32 => StatusCode::UNKNOWN_TRANSACTION, - e if e == StatusCode::FDS_NOT_ALLOWED as i32 => StatusCode::FDS_NOT_ALLOWED, - e if e == StatusCode::UNEXPECTED_NULL as i32 => StatusCode::UNEXPECTED_NULL, - _ => StatusCode::UNKNOWN_ERROR, - } -} - -pub use sys::android_c_interface_ExceptionCode as ExceptionCode; - -fn parse_exception_code(code: i32) -> ExceptionCode { - match code { - e if e == ExceptionCode::NONE as i32 => ExceptionCode::NONE, - e if e == ExceptionCode::SECURITY as i32 => ExceptionCode::SECURITY, - e if e == ExceptionCode::BAD_PARCELABLE as i32 => ExceptionCode::BAD_PARCELABLE, - e if e == ExceptionCode::ILLEGAL_ARGUMENT as i32 => ExceptionCode::ILLEGAL_ARGUMENT, - e if e == ExceptionCode::NULL_POINTER as i32 => ExceptionCode::NULL_POINTER, - e if e == ExceptionCode::ILLEGAL_STATE as i32 => ExceptionCode::ILLEGAL_STATE, - e if e == ExceptionCode::NETWORK_MAIN_THREAD as i32 => ExceptionCode::NETWORK_MAIN_THREAD, - e if e == ExceptionCode::UNSUPPORTED_OPERATION as i32 => { - ExceptionCode::UNSUPPORTED_OPERATION - } - e if e == ExceptionCode::SERVICE_SPECIFIC as i32 => ExceptionCode::SERVICE_SPECIFIC, - _ => ExceptionCode::TRANSACTION_FAILED, - } -} - -// Safety: `Status` always contains a owning pointer to a valid `AStatus`. The -// lifetime of the contained pointer is the same as the `Status` object. -/// High-level binder status object that encapsulates a standard way to keep -/// track of and chain binder errors along with service specific errors. -/// -/// Used in AIDL transactions to represent failed transactions. -pub struct Status(*mut sys::AStatus); - -// Safety: The `AStatus` that the `Status` points to must have an entirely thread-safe API for the -// duration of the `Status` object's lifetime. We ensure this by not allowing mutation of a `Status` -// in Rust, and the NDK API says we're the owner of our `AStatus` objects so outside code should not -// be mutating them underneath us. -unsafe impl Sync for Status {} - -// Safety: `Status` always contains an owning pointer to a global, immutable, interned `AStatus`. -// A thread-local `AStatus` would not be valid. -unsafe impl Send for Status {} - -impl Status { - /// Create a status object representing a successful transaction. - pub fn ok() -> Self { - let ptr = unsafe { - // Safety: `AStatus_newOk` always returns a new, heap allocated - // pointer to an `ASTatus` object, so we know this pointer will be - // valid. - // - // Rust takes ownership of the returned pointer. - sys::AStatus_newOk() - }; - Self(ptr) - } - - /// Create a status object from a service specific error - pub fn new_service_specific_error(err: i32, message: Option<&CStr>) -> Status { - let ptr = if let Some(message) = message { - unsafe { - // Safety: Any i32 is a valid service specific error for the - // error code parameter. We construct a valid, null-terminated - // `CString` from the message, which must be a valid C-style - // string to pass as the message. This function always returns a - // new, heap allocated pointer to an `AStatus` object, so we - // know the returned pointer will be valid. - // - // Rust takes ownership of the returned pointer. - sys::AStatus_fromServiceSpecificErrorWithMessage(err, message.as_ptr()) - } - } else { - unsafe { - // Safety: Any i32 is a valid service specific error for the - // error code parameter. This function always returns a new, - // heap allocated pointer to an `AStatus` object, so we know the - // returned pointer will be valid. - // - // Rust takes ownership of the returned pointer. - sys::AStatus_fromServiceSpecificError(err) - } - }; - Self(ptr) - } - - /// Create a status object from an exception code - pub fn new_exception(exception: ExceptionCode, message: Option<&CStr>) -> Status { - if let Some(message) = message { - let ptr = unsafe { - sys::AStatus_fromExceptionCodeWithMessage(exception as i32, message.as_ptr()) - }; - Self(ptr) - } else { - exception.into() - } - } - - /// Create a status object from a raw `AStatus` pointer. - /// - /// # Safety - /// - /// This constructor is safe iff `ptr` is a valid pointer to an `AStatus`. - pub(crate) unsafe fn from_ptr(ptr: *mut sys::AStatus) -> Self { - Self(ptr) - } - - /// Returns `true` if this status represents a successful transaction. - pub fn is_ok(&self) -> bool { - unsafe { - // Safety: `Status` always contains a valid `AStatus` pointer, so we - // are always passing a valid pointer to `AStatus_isOk` here. - sys::AStatus_isOk(self.as_native()) - } - } - - /// Returns a description of the status. - pub fn get_description(&self) -> String { - let description_ptr = unsafe { - // Safety: `Status` always contains a valid `AStatus` pointer, so we - // are always passing a valid pointer to `AStatus_getDescription` - // here. - // - // `AStatus_getDescription` always returns a valid pointer to a null - // terminated C string. Rust is responsible for freeing this pointer - // via `AStatus_deleteDescription`. - sys::AStatus_getDescription(self.as_native()) - }; - let description = unsafe { - // Safety: `AStatus_getDescription` always returns a valid C string, - // which can be safely converted to a `CStr`. - CStr::from_ptr(description_ptr) - }; - let description = description.to_string_lossy().to_string(); - unsafe { - // Safety: `description_ptr` was returned from - // `AStatus_getDescription` above, and must be freed via - // `AStatus_deleteDescription`. We must not access the pointer after - // this call, so we copy it into an owned string above and return - // that string. - sys::AStatus_deleteDescription(description_ptr); - } - description - } - - /// Returns the exception code of the status. - pub fn exception_code(&self) -> ExceptionCode { - let code = unsafe { - // Safety: `Status` always contains a valid `AStatus` pointer, so we - // are always passing a valid pointer to `AStatus_getExceptionCode` - // here. - sys::AStatus_getExceptionCode(self.as_native()) - }; - parse_exception_code(code) - } - - /// Return a status code representing a transaction failure, or - /// `StatusCode::OK` if there was no transaction failure. - /// - /// If this method returns `OK`, the status may still represent a different - /// exception or a service specific error. To find out if this transaction - /// as a whole is okay, use [`is_ok`](Self::is_ok) instead. - pub fn transaction_error(&self) -> StatusCode { - let code = unsafe { - // Safety: `Status` always contains a valid `AStatus` pointer, so we - // are always passing a valid pointer to `AStatus_getStatus` here. - sys::AStatus_getStatus(self.as_native()) - }; - parse_status_code(code) - } - - /// Return a service specific error if this status represents one. - /// - /// This function will only ever return a non-zero result if - /// [`exception_code`](Self::exception_code) returns - /// `ExceptionCode::SERVICE_SPECIFIC`. If this function returns 0, the - /// status object may still represent a different exception or status. To - /// find out if this transaction as a whole is okay, use - /// [`is_ok`](Self::is_ok) instead. - pub fn service_specific_error(&self) -> i32 { - unsafe { - // Safety: `Status` always contains a valid `AStatus` pointer, so we - // are always passing a valid pointer to - // `AStatus_getServiceSpecificError` here. - sys::AStatus_getServiceSpecificError(self.as_native()) - } - } - - /// Calls `op` if the status was ok, otherwise returns an `Err` value of - /// `self`. - pub fn and_then<T, F>(self, op: F) -> result::Result<T, Status> - where - F: FnOnce() -> result::Result<T, Status>, - { - <result::Result<(), Status>>::from(self)?; - op() - } -} - -impl error::Error for Status {} - -impl Display for Status { - fn fmt(&self, f: &mut Formatter) -> FmtResult { - f.write_str(&self.get_description()) - } -} - -impl Debug for Status { - fn fmt(&self, f: &mut Formatter) -> FmtResult { - f.write_str(&self.get_description()) - } -} - -impl PartialEq for Status { - fn eq(&self, other: &Status) -> bool { - let self_code = self.exception_code(); - let other_code = other.exception_code(); - - match (self_code, other_code) { - (ExceptionCode::NONE, ExceptionCode::NONE) => true, - (ExceptionCode::TRANSACTION_FAILED, ExceptionCode::TRANSACTION_FAILED) => { - self.transaction_error() == other.transaction_error() - && self.get_description() == other.get_description() - } - (ExceptionCode::SERVICE_SPECIFIC, ExceptionCode::SERVICE_SPECIFIC) => { - self.service_specific_error() == other.service_specific_error() - && self.get_description() == other.get_description() - } - (e1, e2) => e1 == e2 && self.get_description() == other.get_description(), - } - } -} - -impl Eq for Status {} - -impl From<StatusCode> for Status { - fn from(status: StatusCode) -> Status { - (status as status_t).into() - } -} - -impl From<status_t> for Status { - fn from(status: status_t) -> Status { - let ptr = unsafe { - // Safety: `AStatus_fromStatus` expects any `status_t` integer, so - // this is a safe FFI call. Unknown values will be coerced into - // UNKNOWN_ERROR. - sys::AStatus_fromStatus(status) - }; - Self(ptr) - } -} - -impl From<ExceptionCode> for Status { - fn from(code: ExceptionCode) -> Status { - let ptr = unsafe { - // Safety: `AStatus_fromExceptionCode` expects any - // `binder_exception_t` (i32) integer, so this is a safe FFI call. - // Unknown values will be coerced into EX_TRANSACTION_FAILED. - sys::AStatus_fromExceptionCode(code as i32) - }; - Self(ptr) - } -} - -// TODO: impl Try for Status when try_trait is stabilized -// https://github.com/rust-lang/rust/issues/42327 -impl From<Status> for result::Result<(), Status> { - fn from(status: Status) -> result::Result<(), Status> { - if status.is_ok() { - Ok(()) - } else { - Err(status) - } - } -} - -impl From<Status> for status_t { - fn from(status: Status) -> status_t { - status.transaction_error() as status_t - } -} - -impl Drop for Status { - fn drop(&mut self) { - unsafe { - // Safety: `Status` manages the lifetime of its inner `AStatus` - // pointee, so we need to delete it here. We know that the pointer - // will be valid here since `Status` always contains a valid pointer - // while it is alive. - sys::AStatus_delete(self.0); - } - } -} - -/// # Safety -/// -/// `Status` always contains a valid pointer to an `AStatus` object, so we can -/// trivially convert it to a correctly-typed raw pointer. -/// -/// Care must be taken that the returned pointer is only dereferenced while the -/// `Status` object is still alive. -unsafe impl AsNative<sys::AStatus> for Status { - fn as_native(&self) -> *const sys::AStatus { - self.0 - } - - fn as_native_mut(&mut self) -> *mut sys::AStatus { - self.0 - } -} diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs deleted file mode 100644 index 2694cba870..0000000000 --- a/libs/binder/rust/src/lib.rs +++ /dev/null @@ -1,133 +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. - */ - -//! Safe Rust interface to Android `libbinder`. -//! -//! This crate is primarily designed as an target for a Rust AIDL compiler -//! backend, and should generally not be used directly by users. It is built on -//! top of the binder NDK library to be usable by APEX modules, and therefore -//! only exposes functionality available in the NDK interface. -//! -//! # Example -//! -//! The following example illustrates how the AIDL backend will use this crate. -//! -//! ``` -//! use binder::{ -//! declare_binder_interface, Binder, IBinder, Interface, Remotable, Parcel, SpIBinder, -//! StatusCode, TransactionCode, -//! }; -//! -//! // Generated by AIDL compiler -//! pub trait ITest: Interface { -//! fn test(&self) -> binder::Result<String>; -//! } -//! -//! // Creates a new local (native) service object, BnTest, and a remote proxy -//! // object, BpTest, that are the typed interfaces for their respective ends -//! // of the binder transaction. Generated by AIDL compiler. -//! declare_binder_interface! { -//! ITest["android.os.ITest"] { -//! native: BnTest(on_transact), -//! proxy: BpTest, -//! } -//! } -//! -//! // Generated by AIDL compiler -//! fn on_transact( -//! service: &dyn ITest, -//! code: TransactionCode, -//! _data: &Parcel, -//! reply: &mut Parcel, -//! ) -> binder::Result<()> { -//! match code { -//! SpIBinder::FIRST_CALL_TRANSACTION => { -//! reply.write(&service.test()?)?; -//! Ok(()) -//! } -//! _ => Err(StatusCode::UNKNOWN_TRANSACTION), -//! } -//! } -//! -//! // Generated by AIDL compiler -//! impl ITest for Binder<BnTest> { -//! fn test(&self) -> binder::Result<String> { -//! self.0.test() -//! } -//! } -//! -//! // Generated by AIDL compiler -//! impl ITest for BpTest { -//! fn test(&self) -> binder::Result<String> { -//! let reply = self -//! .as_binder() -//! .transact(SpIBinder::FIRST_CALL_TRANSACTION, 0, |_| Ok(()))?; -//! reply.read() -//! } -//! } -//! -//! // User implemented: -//! -//! // Local implementation of the ITest remotable interface. -//! struct TestService; -//! -//! impl Interface for TestService {} -//! -//! impl ITest for TestService { -//! fn test(&self) -> binder::Result<String> { -//! Ok("testing service".to_string()) -//! } -//! } -//! ``` - -#[macro_use] -mod proxy; - -#[macro_use] -mod binder; -mod error; -mod native; -mod state; - -use binder_ndk_sys as sys; - -pub mod parcel; - -pub use crate::binder::{ - BinderFeatures, FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Remotable, - Stability, Strong, TransactionCode, TransactionFlags, Weak, FIRST_CALL_TRANSACTION, - FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION, -}; -pub use error::{status_t, ExceptionCode, Result, Status, StatusCode}; -pub use native::add_service; -pub use native::Binder; -pub use parcel::Parcel; -pub use proxy::{get_interface, get_service}; -pub use proxy::{AssociateClass, DeathRecipient, Proxy, SpIBinder, WpIBinder}; -pub use state::{ProcessState, ThreadState}; - -/// The public API usable outside AIDL-generated interface crates. -pub mod public_api { - pub use super::parcel::ParcelFileDescriptor; - pub use super::{add_service, get_interface}; - pub use super::{ - BinderFeatures, DeathRecipient, ExceptionCode, IBinder, Interface, ProcessState, SpIBinder, - Status, StatusCode, Strong, ThreadState, Weak, WpIBinder, - }; - - /// Binder result containing a [`Status`] on error. - pub type Result<T> = std::result::Result<T, Status>; -} 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 () {} diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs deleted file mode 100644 index 6c34824a5e..0000000000 --- a/libs/binder/rust/src/parcel.rs +++ /dev/null @@ -1,562 +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. - */ - -//! Container for messages that are sent via binder. - -use crate::binder::AsNative; -use crate::error::{status_result, Result, StatusCode}; -use crate::proxy::SpIBinder; -use crate::sys; - -use std::cell::RefCell; -use std::convert::TryInto; -use std::mem::ManuallyDrop; -use std::ptr; - -mod file_descriptor; -mod parcelable; - -pub use self::file_descriptor::ParcelFileDescriptor; -pub use self::parcelable::{ - Deserialize, DeserializeArray, DeserializeOption, Serialize, SerializeArray, SerializeOption, -}; - -/// Container for a message (data and object references) that can be sent -/// through Binder. -/// -/// A Parcel can contain both serialized data that will be deserialized on the -/// other side of the IPC, and references to live Binder objects that will -/// result in the other side receiving a proxy Binder connected with the -/// original Binder in the Parcel. -pub enum Parcel { - /// Owned parcel pointer - Owned(*mut sys::AParcel), - /// Borrowed parcel pointer (will not be destroyed on drop) - Borrowed(*mut sys::AParcel), -} - -/// # Safety -/// -/// The `Parcel` constructors guarantee that a `Parcel` object will always -/// contain a valid pointer to an `AParcel`. -unsafe impl AsNative<sys::AParcel> for Parcel { - fn as_native(&self) -> *const sys::AParcel { - match *self { - Self::Owned(x) | Self::Borrowed(x) => x, - } - } - - fn as_native_mut(&mut self) -> *mut sys::AParcel { - match *self { - Self::Owned(x) | Self::Borrowed(x) => x, - } - } -} - -impl Parcel { - /// Create a borrowed reference to a parcel object from a raw pointer. - /// - /// # Safety - /// - /// This constructor is safe if the raw pointer parameter is either null - /// (resulting in `None`), or a valid pointer to an `AParcel` object. - pub(crate) unsafe fn borrowed(ptr: *mut sys::AParcel) -> Option<Parcel> { - ptr.as_mut().map(|ptr| Self::Borrowed(ptr)) - } - - /// Create an owned reference to a parcel object from a raw pointer. - /// - /// # Safety - /// - /// This constructor is safe if the raw pointer parameter is either null - /// (resulting in `None`), or a valid pointer to an `AParcel` object. The - /// parcel object must be owned by the caller prior to this call, as this - /// constructor takes ownership of the parcel and will destroy it on drop. - pub(crate) unsafe fn owned(ptr: *mut sys::AParcel) -> Option<Parcel> { - ptr.as_mut().map(|ptr| Self::Owned(ptr)) - } - - /// Consume the parcel, transferring ownership to the caller if the parcel - /// was owned. - pub(crate) fn into_raw(mut self) -> *mut sys::AParcel { - let ptr = self.as_native_mut(); - let _ = ManuallyDrop::new(self); - ptr - } -} - -// Data serialization methods -impl Parcel { - /// Data written to parcelable is zero'd before being deleted or reallocated. - pub fn mark_sensitive(&mut self) { - unsafe { - // Safety: guaranteed to have a parcel object, and this method never fails - sys::AParcel_markSensitive(self.as_native()) - } - } - - /// Write a type that implements [`Serialize`] to the `Parcel`. - pub fn write<S: Serialize + ?Sized>(&mut self, parcelable: &S) -> Result<()> { - parcelable.serialize(self) - } - - /// Writes the length of a slice to the `Parcel`. - /// - /// This is used in AIDL-generated client side code to indicate the - /// allocated space for an output array parameter. - pub fn write_slice_size<T>(&mut self, slice: Option<&[T]>) -> Result<()> { - if let Some(slice) = slice { - let len: i32 = slice.len().try_into().or(Err(StatusCode::BAD_VALUE))?; - self.write(&len) - } else { - self.write(&-1i32) - } - } - - /// Perform a series of writes to the `Parcel`, prepended with the length - /// (in bytes) of the written data. - /// - /// The length `0i32` will be written to the parcel first, followed by the - /// writes performed by the callback. The initial length will then be - /// updated to the length of all data written by the callback, plus the - /// size of the length elemement itself (4 bytes). - /// - /// # Examples - /// - /// After the following call: - /// - /// ``` - /// # use binder::{Binder, Interface, Parcel}; - /// # let mut parcel = Parcel::Owned(std::ptr::null_mut()); - /// parcel.sized_write(|subparcel| { - /// subparcel.write(&1u32)?; - /// subparcel.write(&2u32)?; - /// subparcel.write(&3u32) - /// }); - /// ``` - /// - /// `parcel` will contain the following: - /// - /// ```ignore - /// [16i32, 1u32, 2u32, 3u32] - /// ``` - pub fn sized_write<F>(&mut self, f: F) -> Result<()> - where for<'a> - F: Fn(&'a WritableSubParcel<'a>) -> Result<()> - { - let start = self.get_data_position(); - self.write(&0i32)?; - { - let subparcel = WritableSubParcel(RefCell::new(self)); - f(&subparcel)?; - } - let end = self.get_data_position(); - unsafe { - self.set_data_position(start)?; - } - assert!(end >= start); - self.write(&(end - start))?; - unsafe { - self.set_data_position(end)?; - } - Ok(()) - } - - /// Returns the current position in the parcel data. - pub fn get_data_position(&self) -> i32 { - unsafe { - // Safety: `Parcel` always contains a valid pointer to an `AParcel`, - // and this call is otherwise safe. - sys::AParcel_getDataPosition(self.as_native()) - } - } - - /// Move the current read/write position in the parcel. - /// - /// The new position must be a position previously returned by - /// `self.get_data_position()`. - /// - /// # Safety - /// - /// This method is safe if `pos` is less than the current size of the parcel - /// data buffer. Otherwise, we are relying on correct bounds checking in the - /// Parcel C++ code on every subsequent read or write to this parcel. If all - /// accesses are bounds checked, this call is still safe, but we can't rely - /// on that. - pub unsafe fn set_data_position(&self, pos: i32) -> Result<()> { - status_result(sys::AParcel_setDataPosition(self.as_native(), pos)) - } -} - -/// A segment of a writable parcel, used for [`Parcel::sized_write`]. -pub struct WritableSubParcel<'a>(RefCell<&'a mut Parcel>); - -impl<'a> WritableSubParcel<'a> { - /// Write a type that implements [`Serialize`] to the sub-parcel. - pub fn write<S: Serialize + ?Sized>(&self, parcelable: &S) -> Result<()> { - parcelable.serialize(&mut *self.0.borrow_mut()) - } -} - -// Data deserialization methods -impl Parcel { - /// Attempt to read a type that implements [`Deserialize`] from this - /// `Parcel`. - pub fn read<D: Deserialize>(&self) -> Result<D> { - D::deserialize(self) - } - - /// Read a vector size from the `Parcel` and resize the given output vector - /// to be correctly sized for that amount of data. - /// - /// This method is used in AIDL-generated server side code for methods that - /// take a mutable slice reference parameter. - pub fn resize_out_vec<D: Default + Deserialize>(&self, out_vec: &mut Vec<D>) -> Result<()> { - let len: i32 = self.read()?; - - if len < 0 { - return Err(StatusCode::UNEXPECTED_NULL); - } - - // usize in Rust may be 16-bit, so i32 may not fit - let len = len.try_into().unwrap(); - out_vec.resize_with(len, Default::default); - - Ok(()) - } - - /// Read a vector size from the `Parcel` and either create a correctly sized - /// vector for that amount of data or set the output parameter to None if - /// the vector should be null. - /// - /// This method is used in AIDL-generated server side code for methods that - /// take a mutable slice reference parameter. - pub fn resize_nullable_out_vec<D: Default + Deserialize>( - &self, - out_vec: &mut Option<Vec<D>>, - ) -> Result<()> { - let len: i32 = self.read()?; - - if len < 0 { - *out_vec = None; - } else { - // usize in Rust may be 16-bit, so i32 may not fit - let len = len.try_into().unwrap(); - let mut vec = Vec::with_capacity(len); - vec.resize_with(len, Default::default); - *out_vec = Some(vec); - } - - Ok(()) - } -} - -// Internal APIs -impl Parcel { - pub(crate) fn write_binder(&mut self, binder: Option<&SpIBinder>) -> Result<()> { - unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. `AsNative` for `Option<SpIBinder`> will either return - // null or a valid pointer to an `AIBinder`, both of which are - // valid, safe inputs to `AParcel_writeStrongBinder`. - // - // This call does not take ownership of the binder. However, it does - // require a mutable pointer, which we cannot extract from an - // immutable reference, so we clone the binder, incrementing the - // refcount before the call. The refcount will be immediately - // decremented when this temporary is dropped. - status_result(sys::AParcel_writeStrongBinder( - self.as_native_mut(), - binder.cloned().as_native_mut(), - )) - } - } - - pub(crate) fn read_binder(&self) -> Result<Option<SpIBinder>> { - let mut binder = ptr::null_mut(); - let status = unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. We pass a valid, mutable out pointer to the `binder` - // parameter. After this call, `binder` will be either null or a - // valid pointer to an `AIBinder` owned by the caller. - sys::AParcel_readStrongBinder(self.as_native(), &mut binder) - }; - - status_result(status)?; - - Ok(unsafe { - // Safety: `binder` is either null or a valid, owned pointer at this - // point, so can be safely passed to `SpIBinder::from_raw`. - SpIBinder::from_raw(binder) - }) - } -} - -impl Drop for Parcel { - fn drop(&mut self) { - // Run the C++ Parcel complete object destructor - if let Self::Owned(ptr) = *self { - unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. If we own the parcel, we can safely delete it - // here. - sys::AParcel_delete(ptr) - } - } - } -} - -#[cfg(test)] -impl Parcel { - /// Create a new parcel tied to a bogus binder. TESTING ONLY! - /// - /// This can only be used for testing! All real parcel operations must be - /// done in the callback to [`IBinder::transact`] or in - /// [`Remotable::on_transact`] using the parcels provided to these methods. - pub(crate) fn new_for_test(binder: &mut SpIBinder) -> Result<Self> { - let mut input = ptr::null_mut(); - let status = unsafe { - // Safety: `SpIBinder` guarantees that `binder` always contains a - // valid pointer to an `AIBinder`. We pass a valid, mutable out - // pointer to receive a newly constructed parcel. When successful - // this function assigns a new pointer to an `AParcel` to `input` - // and transfers ownership of this pointer to the caller. Thus, - // after this call, `input` will either be null or point to a valid, - // owned `AParcel`. - sys::AIBinder_prepareTransaction(binder.as_native_mut(), &mut input) - }; - status_result(status)?; - unsafe { - // Safety: `input` is either null or a valid, owned pointer to an - // `AParcel`, so is valid to safe to - // `Parcel::owned`. `Parcel::owned` takes ownership of the parcel - // pointer. - Parcel::owned(input).ok_or(StatusCode::UNEXPECTED_NULL) - } - } -} - -#[test] -fn test_read_write() { - use crate::binder::Interface; - use crate::native::Binder; - - let mut service = Binder::new(()).as_binder(); - let mut parcel = Parcel::new_for_test(&mut service).unwrap(); - let start = parcel.get_data_position(); - - assert_eq!(parcel.read::<bool>(), Err(StatusCode::NOT_ENOUGH_DATA)); - assert_eq!(parcel.read::<i8>(), Err(StatusCode::NOT_ENOUGH_DATA)); - assert_eq!(parcel.read::<u16>(), Err(StatusCode::NOT_ENOUGH_DATA)); - assert_eq!(parcel.read::<i32>(), Err(StatusCode::NOT_ENOUGH_DATA)); - assert_eq!(parcel.read::<u32>(), Err(StatusCode::NOT_ENOUGH_DATA)); - assert_eq!(parcel.read::<i64>(), Err(StatusCode::NOT_ENOUGH_DATA)); - assert_eq!(parcel.read::<u64>(), Err(StatusCode::NOT_ENOUGH_DATA)); - assert_eq!(parcel.read::<f32>(), Err(StatusCode::NOT_ENOUGH_DATA)); - assert_eq!(parcel.read::<f64>(), Err(StatusCode::NOT_ENOUGH_DATA)); - assert_eq!(parcel.read::<Option<String>>(), Ok(None)); - assert_eq!(parcel.read::<String>(), Err(StatusCode::UNEXPECTED_NULL)); - - assert_eq!(parcel.read_binder().err(), Some(StatusCode::BAD_TYPE)); - - parcel.write(&1i32).unwrap(); - - unsafe { - parcel.set_data_position(start).unwrap(); - } - - let i: i32 = parcel.read().unwrap(); - assert_eq!(i, 1i32); -} - -#[test] -#[allow(clippy::float_cmp)] -fn test_read_data() { - use crate::binder::Interface; - use crate::native::Binder; - - let mut service = Binder::new(()).as_binder(); - let mut parcel = Parcel::new_for_test(&mut service).unwrap(); - let str_start = parcel.get_data_position(); - - parcel.write(&b"Hello, Binder!\0"[..]).unwrap(); - // Skip over string length - unsafe { - assert!(parcel.set_data_position(str_start).is_ok()); - } - assert_eq!(parcel.read::<i32>().unwrap(), 15); - let start = parcel.get_data_position(); - - assert_eq!(parcel.read::<bool>().unwrap(), true); - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<i8>().unwrap(), 72i8); - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<u16>().unwrap(), 25928); - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<i32>().unwrap(), 1819043144); - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<u32>().unwrap(), 1819043144); - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<i64>().unwrap(), 4764857262830019912); - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<u64>().unwrap(), 4764857262830019912); - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!( - parcel.read::<f32>().unwrap(), - 1143139100000000000000000000.0 - ); - assert_eq!(parcel.read::<f32>().unwrap(), 40.043392); - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<f64>().unwrap(), 34732488246.197815); - - // Skip back to before the string length - unsafe { - assert!(parcel.set_data_position(str_start).is_ok()); - } - - assert_eq!(parcel.read::<Vec<u8>>().unwrap(), b"Hello, Binder!\0"); -} - -#[test] -fn test_utf8_utf16_conversions() { - use crate::binder::Interface; - use crate::native::Binder; - - let mut service = Binder::new(()).as_binder(); - let mut parcel = Parcel::new_for_test(&mut service).unwrap(); - let start = parcel.get_data_position(); - - assert!(parcel.write("Hello, Binder!").is_ok()); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - assert_eq!( - parcel.read::<Option<String>>().unwrap().unwrap(), - "Hello, Binder!", - ); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert!(parcel.write("Embedded null \0 inside a string").is_ok()); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - assert_eq!( - parcel.read::<Option<String>>().unwrap().unwrap(), - "Embedded null \0 inside a string", - ); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert!(parcel.write(&["str1", "str2", "str3"][..]).is_ok()); - assert!(parcel - .write( - &[ - String::from("str4"), - String::from("str5"), - String::from("str6"), - ][..] - ) - .is_ok()); - - let s1 = "Hello, Binder!"; - let s2 = "This is a utf8 string."; - let s3 = "Some more text here."; - - assert!(parcel.write(&[s1, s2, s3][..]).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!( - parcel.read::<Vec<String>>().unwrap(), - ["str1", "str2", "str3"] - ); - assert_eq!( - parcel.read::<Vec<String>>().unwrap(), - ["str4", "str5", "str6"] - ); - assert_eq!(parcel.read::<Vec<String>>().unwrap(), [s1, s2, s3]); -} - -#[test] -fn test_sized_write() { - use crate::binder::Interface; - use crate::native::Binder; - - let mut service = Binder::new(()).as_binder(); - let mut parcel = Parcel::new_for_test(&mut service).unwrap(); - let start = parcel.get_data_position(); - - let arr = [1i32, 2i32, 3i32]; - - parcel.sized_write(|subparcel| { - subparcel.write(&arr[..]) - }).expect("Could not perform sized write"); - - // i32 sub-parcel length + i32 array length + 3 i32 elements - let expected_len = 20i32; - - assert_eq!(parcel.get_data_position(), start + expected_len); - - unsafe { - parcel.set_data_position(start).unwrap(); - } - - assert_eq!( - expected_len, - parcel.read().unwrap(), - ); - - assert_eq!( - parcel.read::<Vec<i32>>().unwrap(), - &arr, - ); -} diff --git a/libs/binder/rust/src/parcel/file_descriptor.rs b/libs/binder/rust/src/parcel/file_descriptor.rs deleted file mode 100644 index 20e91785d3..0000000000 --- a/libs/binder/rust/src/parcel/file_descriptor.rs +++ /dev/null @@ -1,127 +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 super::{ - Deserialize, DeserializeArray, DeserializeOption, Parcel, Serialize, SerializeArray, - SerializeOption, -}; -use crate::binder::AsNative; -use crate::error::{status_result, Result, StatusCode}; -use crate::sys; - -use std::fs::File; -use std::os::unix::io::{AsRawFd, FromRawFd}; - -/// Rust version of the Java class android.os.ParcelFileDescriptor -#[derive(Debug)] -pub struct ParcelFileDescriptor(File); - -impl ParcelFileDescriptor { - /// Create a new `ParcelFileDescriptor` - pub fn new(file: File) -> Self { - Self(file) - } -} - -impl AsRef<File> for ParcelFileDescriptor { - fn as_ref(&self) -> &File { - &self.0 - } -} - -impl From<ParcelFileDescriptor> for File { - fn from(file: ParcelFileDescriptor) -> File { - file.0 - } -} - -impl Serialize for ParcelFileDescriptor { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - let fd = self.0.as_raw_fd(); - let status = unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. Likewise, `ParcelFileDescriptor` always contains a - // valid file, so we can borrow a valid file - // descriptor. `AParcel_writeParcelFileDescriptor` does NOT take - // ownership of the fd, so we need not duplicate it first. - sys::AParcel_writeParcelFileDescriptor(parcel.as_native_mut(), fd) - }; - status_result(status) - } -} - -impl SerializeArray for ParcelFileDescriptor {} - -impl SerializeOption for ParcelFileDescriptor { - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { - if let Some(f) = this { - f.serialize(parcel) - } else { - let status = unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. `AParcel_writeParcelFileDescriptor` accepts the - // value `-1` as the file descriptor to signify serializing a - // null file descriptor. - sys::AParcel_writeParcelFileDescriptor(parcel.as_native_mut(), -1i32) - }; - status_result(status) - } - } -} - -impl SerializeArray for Option<ParcelFileDescriptor> {} - -impl DeserializeOption for ParcelFileDescriptor { - fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> { - let mut fd = -1i32; - unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. We pass a valid mutable pointer to an i32, which - // `AParcel_readParcelFileDescriptor` assigns the valid file - // descriptor into, or `-1` if deserializing a null file - // descriptor. The read function passes ownership of the file - // descriptor to its caller if it was non-null, so we must take - // ownership of the file and ensure that it is eventually closed. - status_result(sys::AParcel_readParcelFileDescriptor( - parcel.as_native(), - &mut fd, - ))?; - } - if fd < 0 { - Ok(None) - } else { - let file = unsafe { - // Safety: At this point, we know that the file descriptor was - // not -1, so must be a valid, owned file descriptor which we - // can safely turn into a `File`. - File::from_raw_fd(fd) - }; - Ok(Some(ParcelFileDescriptor::new(file))) - } - } -} - -impl DeserializeArray for Option<ParcelFileDescriptor> {} - -impl Deserialize for ParcelFileDescriptor { - fn deserialize(parcel: &Parcel) -> Result<Self> { - Deserialize::deserialize(parcel) - .transpose() - .unwrap_or(Err(StatusCode::UNEXPECTED_NULL)) - } -} - -impl DeserializeArray for ParcelFileDescriptor {} diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs deleted file mode 100644 index f57788b87e..0000000000 --- a/libs/binder/rust/src/parcel/parcelable.rs +++ /dev/null @@ -1,989 +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, FromIBinder, Strong}; -use crate::error::{status_result, status_t, Result, Status, StatusCode}; -use crate::parcel::Parcel; -use crate::proxy::SpIBinder; -use crate::sys; - -use std::convert::TryInto; -use std::ffi::c_void; -use std::os::raw::{c_char, c_ulong}; -use std::mem::{self, MaybeUninit}; -use std::ptr; -use std::slice; - -/// A struct whose instances can be written to a [`Parcel`]. -// Might be able to hook this up as a serde backend in the future? -pub trait Serialize { - /// Serialize this instance into the given [`Parcel`]. - fn serialize(&self, parcel: &mut Parcel) -> Result<()>; -} - -/// A struct whose instances can be restored from a [`Parcel`]. -// Might be able to hook this up as a serde backend in the future? -pub trait Deserialize: Sized { - /// Deserialize an instance from the given [`Parcel`]. - fn deserialize(parcel: &Parcel) -> Result<Self>; -} - -/// Helper trait for types that can be serialized as arrays. -/// Defaults to calling Serialize::serialize() manually for every element, -/// but can be overridden for custom implementations like `writeByteArray`. -// Until specialization is stabilized in Rust, we need this to be a separate -// trait because it's the only way to have a default implementation for a method. -// We want the default implementation for most types, but an override for -// a few special ones like `readByteArray` for `u8`. -pub trait SerializeArray: Serialize + Sized { - /// Serialize an array of this type into the given [`Parcel`]. - fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> { - let res = unsafe { - // Safety: Safe FFI, slice will always be a safe pointer to pass. - sys::AParcel_writeParcelableArray( - parcel.as_native_mut(), - slice.as_ptr() as *const c_void, - slice.len().try_into().or(Err(StatusCode::BAD_VALUE))?, - Some(serialize_element::<Self>), - ) - }; - status_result(res) - } -} - -/// Callback to serialize an element of a generic parcelable array. -/// -/// Safety: We are relying on binder_ndk to not overrun our slice. As long as it -/// doesn't provide an index larger than the length of the original slice in -/// serialize_array, this operation is safe. The index provided is zero-based. -unsafe extern "C" fn serialize_element<T: Serialize>( - parcel: *mut sys::AParcel, - array: *const c_void, - index: c_ulong, -) -> status_t { - // c_ulong and usize are the same, but we need the explicitly sized version - // so the function signature matches what bindgen generates. - let index = index as usize; - - let slice: &[T] = slice::from_raw_parts(array.cast(), index+1); - - let mut parcel = match Parcel::borrowed(parcel) { - None => return StatusCode::UNEXPECTED_NULL as status_t, - Some(p) => p, - }; - - slice[index].serialize(&mut parcel) - .err() - .unwrap_or(StatusCode::OK) - as status_t -} - -/// Helper trait for types that can be deserialized as arrays. -/// Defaults to calling Deserialize::deserialize() manually for every element, -/// but can be overridden for custom implementations like `readByteArray`. -pub trait DeserializeArray: Deserialize { - /// Deserialize an array of type from the given [`Parcel`]. - fn deserialize_array(parcel: &Parcel) -> Result<Option<Vec<Self>>> { - let mut vec: Option<Vec<MaybeUninit<Self>>> = None; - let res = unsafe { - // Safety: Safe FFI, vec is the correct opaque type expected by - // allocate_vec and deserialize_element. - sys::AParcel_readParcelableArray( - parcel.as_native(), - &mut vec as *mut _ as *mut c_void, - Some(allocate_vec::<Self>), - Some(deserialize_element::<Self>), - ) - }; - status_result(res)?; - let vec: Option<Vec<Self>> = unsafe { - // Safety: We are assuming that the NDK correctly initialized every - // element of the vector by now, so we know that all the - // MaybeUninits are now properly initialized. We can transmute from - // Vec<MaybeUninit<T>> to Vec<T> because MaybeUninit<T> has the same - // alignment and size as T, so the pointer to the vector allocation - // will be compatible. - mem::transmute(vec) - }; - Ok(vec) - } -} - -/// Callback to deserialize a parcelable element. -/// -/// The opaque array data pointer must be a mutable pointer to an -/// `Option<Vec<MaybeUninit<T>>>` with at least enough elements for `index` to be valid -/// (zero-based). -unsafe extern "C" fn deserialize_element<T: Deserialize>( - parcel: *const sys::AParcel, - array: *mut c_void, - index: c_ulong, -) -> status_t { - // c_ulong and usize are the same, but we need the explicitly sized version - // so the function signature matches what bindgen generates. - let index = index as usize; - - let vec = &mut *(array as *mut Option<Vec<MaybeUninit<T>>>); - let vec = match vec { - Some(v) => v, - None => return StatusCode::BAD_INDEX as status_t, - }; - - let parcel = match Parcel::borrowed(parcel as *mut _) { - None => return StatusCode::UNEXPECTED_NULL as status_t, - Some(p) => p, - }; - let element = match parcel.read() { - Ok(e) => e, - Err(code) => return code as status_t, - }; - ptr::write(vec[index].as_mut_ptr(), element); - StatusCode::OK as status_t -} - -/// Helper trait for types that can be nullable when serialized. -// We really need this trait instead of implementing `Serialize for Option<T>` -// because of the Rust orphan rule which prevents us from doing -// `impl Serialize for Option<&dyn IFoo>` for AIDL interfaces. -// Instead we emit `impl SerializeOption for dyn IFoo` which is allowed. -// We also use it to provide a default implementation for AIDL-generated -// parcelables. -pub trait SerializeOption: Serialize { - /// Serialize an Option of this type into the given [`Parcel`]. - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { - if let Some(inner) = this { - parcel.write(&1i32)?; - parcel.write(inner) - } else { - parcel.write(&0i32) - } - } -} - -/// Helper trait for types that can be nullable when deserialized. -pub trait DeserializeOption: Deserialize { - /// Deserialize an Option of this type from the given [`Parcel`]. - fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> { - let null: i32 = parcel.read()?; - if null == 0 { - Ok(None) - } else { - parcel.read().map(Some) - } - } -} - -/// Callback to allocate a vector for parcel array read functions. -/// -/// This variant is for APIs which use an out buffer pointer. -/// -/// # Safety -/// -/// The opaque data pointer passed to the array read function must be a mutable -/// pointer to an `Option<Vec<MaybeUninit<T>>>`. `buffer` will be assigned a mutable pointer -/// to the allocated vector data if this function returns true. -unsafe extern "C" fn allocate_vec_with_buffer<T>( - data: *mut c_void, - len: i32, - buffer: *mut *mut T, -) -> bool { - let res = allocate_vec::<T>(data, len); - let vec = &mut *(data as *mut Option<Vec<MaybeUninit<T>>>); - if let Some(new_vec) = vec { - *buffer = new_vec.as_mut_ptr() as *mut T; - } - res -} - -/// Callback to allocate a vector for parcel array read functions. -/// -/// # Safety -/// -/// The opaque data pointer passed to the array read function must be a mutable -/// pointer to an `Option<Vec<MaybeUninit<T>>>`. -unsafe extern "C" fn allocate_vec<T>( - data: *mut c_void, - len: i32, -) -> bool { - let vec = &mut *(data as *mut Option<Vec<MaybeUninit<T>>>); - if len < 0 { - *vec = None; - return true; - } - let mut new_vec: Vec<MaybeUninit<T>> = Vec::with_capacity(len as usize); - - // Safety: We are filling the vector with uninitialized data here, but this - // is safe because the vector contains MaybeUninit elements which can be - // uninitialized. We're putting off the actual unsafe bit, transmuting the - // vector to a Vec<T> until the contents are initialized. - new_vec.set_len(len as usize); - - ptr::write(vec, Some(new_vec)); - true -} - - -macro_rules! parcelable_primitives { - { - $( - impl $trait:ident for $ty:ty = $fn:path; - )* - } => { - $(impl_parcelable!{$trait, $ty, $fn})* - }; -} - -macro_rules! impl_parcelable { - {Serialize, $ty:ty, $write_fn:path} => { - impl Serialize for $ty { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`, and any `$ty` literal value is safe to pass to - // `$write_fn`. - status_result($write_fn(parcel.as_native_mut(), *self)) - } - } - } - }; - - {Deserialize, $ty:ty, $read_fn:path} => { - impl Deserialize for $ty { - fn deserialize(parcel: &Parcel) -> Result<Self> { - let mut val = Self::default(); - unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. We pass a valid, mutable pointer to `val`, a - // literal of type `$ty`, and `$read_fn` will write the - // value read into `val` if successful - status_result($read_fn(parcel.as_native(), &mut val))? - }; - Ok(val) - } - } - }; - - {SerializeArray, $ty:ty, $write_array_fn:path} => { - impl SerializeArray for $ty { - fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> { - let status = unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. If the slice is > 0 length, `slice.as_ptr()` - // will be a valid pointer to an array of elements of type - // `$ty`. If the slice length is 0, `slice.as_ptr()` may be - // dangling, but this is safe since the pointer is not - // dereferenced if the length parameter is 0. - $write_array_fn( - parcel.as_native_mut(), - slice.as_ptr(), - slice - .len() - .try_into() - .or(Err(StatusCode::BAD_VALUE))?, - ) - }; - status_result(status) - } - } - }; - - {DeserializeArray, $ty:ty, $read_array_fn:path} => { - impl DeserializeArray for $ty { - fn deserialize_array(parcel: &Parcel) -> Result<Option<Vec<Self>>> { - let mut vec: Option<Vec<MaybeUninit<Self>>> = None; - let status = unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. `allocate_vec<T>` expects the opaque pointer to - // be of type `*mut Option<Vec<MaybeUninit<T>>>`, so `&mut vec` is - // correct for it. - $read_array_fn( - parcel.as_native(), - &mut vec as *mut _ as *mut c_void, - Some(allocate_vec_with_buffer), - ) - }; - status_result(status)?; - let vec: Option<Vec<Self>> = unsafe { - // Safety: We are assuming that the NDK correctly - // initialized every element of the vector by now, so we - // know that all the MaybeUninits are now properly - // initialized. We can transmute from Vec<MaybeUninit<T>> to - // Vec<T> because MaybeUninit<T> has the same alignment and - // size as T, so the pointer to the vector allocation will - // be compatible. - mem::transmute(vec) - }; - Ok(vec) - } - } - }; -} - -parcelable_primitives! { - impl Serialize for bool = sys::AParcel_writeBool; - impl Deserialize for bool = sys::AParcel_readBool; - - // This is only safe because `Option<Vec<u8>>` is interchangeable with - // `Option<Vec<i8>>` (what the allocator function actually allocates. - impl DeserializeArray for u8 = sys::AParcel_readByteArray; - - impl Serialize for i8 = sys::AParcel_writeByte; - impl Deserialize for i8 = sys::AParcel_readByte; - impl SerializeArray for i8 = sys::AParcel_writeByteArray; - impl DeserializeArray for i8 = sys::AParcel_readByteArray; - - impl Serialize for u16 = sys::AParcel_writeChar; - impl Deserialize for u16 = sys::AParcel_readChar; - impl SerializeArray for u16 = sys::AParcel_writeCharArray; - impl DeserializeArray for u16 = sys::AParcel_readCharArray; - - // This is only safe because `Option<Vec<i16>>` is interchangeable with - // `Option<Vec<u16>>` (what the allocator function actually allocates. - impl DeserializeArray for i16 = sys::AParcel_readCharArray; - - impl Serialize for u32 = sys::AParcel_writeUint32; - impl Deserialize for u32 = sys::AParcel_readUint32; - impl SerializeArray for u32 = sys::AParcel_writeUint32Array; - impl DeserializeArray for u32 = sys::AParcel_readUint32Array; - - impl Serialize for i32 = sys::AParcel_writeInt32; - impl Deserialize for i32 = sys::AParcel_readInt32; - impl SerializeArray for i32 = sys::AParcel_writeInt32Array; - impl DeserializeArray for i32 = sys::AParcel_readInt32Array; - - impl Serialize for u64 = sys::AParcel_writeUint64; - impl Deserialize for u64 = sys::AParcel_readUint64; - impl SerializeArray for u64 = sys::AParcel_writeUint64Array; - impl DeserializeArray for u64 = sys::AParcel_readUint64Array; - - impl Serialize for i64 = sys::AParcel_writeInt64; - impl Deserialize for i64 = sys::AParcel_readInt64; - impl SerializeArray for i64 = sys::AParcel_writeInt64Array; - impl DeserializeArray for i64 = sys::AParcel_readInt64Array; - - impl Serialize for f32 = sys::AParcel_writeFloat; - impl Deserialize for f32 = sys::AParcel_readFloat; - impl SerializeArray for f32 = sys::AParcel_writeFloatArray; - impl DeserializeArray for f32 = sys::AParcel_readFloatArray; - - impl Serialize for f64 = sys::AParcel_writeDouble; - impl Deserialize for f64 = sys::AParcel_readDouble; - impl SerializeArray for f64 = sys::AParcel_writeDoubleArray; - impl DeserializeArray for f64 = sys::AParcel_readDoubleArray; -} - -impl SerializeArray for bool {} -impl DeserializeArray for bool {} - -impl Serialize for u8 { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - (*self as i8).serialize(parcel) - } -} - -impl Deserialize for u8 { - fn deserialize(parcel: &Parcel) -> Result<Self> { - i8::deserialize(parcel).map(|v| v as u8) - } -} - -impl SerializeArray for u8 { - fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> { - let status = unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. If the slice is > 0 length, `slice.as_ptr()` will be a - // valid pointer to an array of elements of type `$ty`. If the slice - // length is 0, `slice.as_ptr()` may be dangling, but this is safe - // since the pointer is not dereferenced if the length parameter is - // 0. - sys::AParcel_writeByteArray( - parcel.as_native_mut(), - slice.as_ptr() as *const i8, - slice.len().try_into().or(Err(StatusCode::BAD_VALUE))?, - ) - }; - status_result(status) - } -} - -impl Serialize for i16 { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - (*self as u16).serialize(parcel) - } -} - -impl Deserialize for i16 { - fn deserialize(parcel: &Parcel) -> Result<Self> { - u16::deserialize(parcel).map(|v| v as i16) - } -} - -impl SerializeArray for i16 { - fn serialize_array(slice: &[Self], parcel: &mut Parcel) -> Result<()> { - let status = unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. If the slice is > 0 length, `slice.as_ptr()` will be a - // valid pointer to an array of elements of type `$ty`. If the slice - // length is 0, `slice.as_ptr()` may be dangling, but this is safe - // since the pointer is not dereferenced if the length parameter is - // 0. - sys::AParcel_writeCharArray( - parcel.as_native_mut(), - slice.as_ptr() as *const u16, - slice.len().try_into().or(Err(StatusCode::BAD_VALUE))?, - ) - }; - status_result(status) - } -} - -impl SerializeOption for str { - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { - match this { - None => unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. If the string pointer is null, - // `AParcel_writeString` requires that the length is -1 to - // indicate that we want to serialize a null string. - status_result(sys::AParcel_writeString( - parcel.as_native_mut(), - ptr::null(), - -1, - )) - }, - Some(s) => unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. `AParcel_writeString` assumes that we pass a utf-8 - // string pointer of `length` bytes, which is what str in Rust - // is. The docstring for `AParcel_writeString` says that the - // string input should be null-terminated, but it doesn't - // actually rely on that fact in the code. If this ever becomes - // necessary, we will need to null-terminate the str buffer - // before sending it. - status_result(sys::AParcel_writeString( - parcel.as_native_mut(), - s.as_ptr() as *const c_char, - s.as_bytes() - .len() - .try_into() - .or(Err(StatusCode::BAD_VALUE))?, - )) - }, - } - } -} - -impl SerializeArray for Option<&str> {} - -impl Serialize for str { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - Some(self).serialize(parcel) - } -} - -impl SerializeArray for &str {} - -impl Serialize for String { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - Some(self.as_str()).serialize(parcel) - } -} - -impl SerializeArray for String {} - -impl SerializeOption for String { - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { - SerializeOption::serialize_option(this.map(String::as_str), parcel) - } -} - -impl SerializeArray for Option<String> {} - -impl Deserialize for Option<String> { - fn deserialize(parcel: &Parcel) -> Result<Self> { - let mut vec: Option<Vec<u8>> = None; - let status = unsafe { - // Safety: `Parcel` always contains a valid pointer to an `AParcel`. - // `Option<Vec<u8>>` is equivalent to the expected `Option<Vec<i8>>` - // for `allocate_vec`, so `vec` is safe to pass as the opaque data - // pointer on platforms where char is signed. - sys::AParcel_readString( - parcel.as_native(), - &mut vec as *mut _ as *mut c_void, - Some(allocate_vec_with_buffer), - ) - }; - - status_result(status)?; - vec.map(|mut s| { - // The vector includes a null-terminator and we don't want the - // string to be null-terminated for Rust. - s.pop(); - String::from_utf8(s).or(Err(StatusCode::BAD_VALUE)) - }) - .transpose() - } -} - -impl DeserializeArray for Option<String> {} - -impl Deserialize for String { - fn deserialize(parcel: &Parcel) -> Result<Self> { - Deserialize::deserialize(parcel) - .transpose() - .unwrap_or(Err(StatusCode::UNEXPECTED_NULL)) - } -} - -impl DeserializeArray for String {} - -impl<T: SerializeArray> Serialize for [T] { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - SerializeArray::serialize_array(self, parcel) - } -} - -impl<T: SerializeArray> Serialize for Vec<T> { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - SerializeArray::serialize_array(&self[..], parcel) - } -} - -impl<T: SerializeArray> SerializeOption for [T] { - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { - if let Some(v) = this { - SerializeArray::serialize_array(v, parcel) - } else { - parcel.write(&-1i32) - } - } -} - -impl<T: SerializeArray> SerializeOption for Vec<T> { - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { - SerializeOption::serialize_option(this.map(Vec::as_slice), parcel) - } -} - -impl<T: DeserializeArray> Deserialize for Vec<T> { - fn deserialize(parcel: &Parcel) -> Result<Self> { - DeserializeArray::deserialize_array(parcel) - .transpose() - .unwrap_or(Err(StatusCode::UNEXPECTED_NULL)) - } -} - -impl<T: DeserializeArray> DeserializeOption for Vec<T> { - fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> { - DeserializeArray::deserialize_array(parcel) - } -} - -impl Serialize for Status { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - unsafe { - // Safety: `Parcel` always contains a valid pointer to an `AParcel` - // and `Status` always contains a valid pointer to an `AStatus`, so - // both parameters are valid and safe. This call does not take - // ownership of either of its parameters. - status_result(sys::AParcel_writeStatusHeader( - parcel.as_native_mut(), - self.as_native(), - )) - } - } -} - -impl Deserialize for Status { - fn deserialize(parcel: &Parcel) -> Result<Self> { - let mut status_ptr = ptr::null_mut(); - let ret_status = unsafe { - // Safety: `Parcel` always contains a valid pointer to an - // `AParcel`. We pass a mutable out pointer which will be - // assigned a valid `AStatus` pointer if the function returns - // status OK. This function passes ownership of the status - // pointer to the caller, if it was assigned. - sys::AParcel_readStatusHeader(parcel.as_native(), &mut status_ptr) - }; - status_result(ret_status)?; - Ok(unsafe { - // Safety: At this point, the return status of the read call was ok, - // so we know that `status_ptr` is a valid, owned pointer to an - // `AStatus`, from which we can safely construct a `Status` object. - Status::from_ptr(status_ptr) - }) - } -} - -impl<T: Serialize + FromIBinder + ?Sized> Serialize for Strong<T> { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - Serialize::serialize(&**self, parcel) - } -} - -impl<T: SerializeOption + FromIBinder + ?Sized> SerializeOption for Strong<T> { - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { - SerializeOption::serialize_option(this.map(|b| &**b), parcel) - } -} - -impl<T: FromIBinder + ?Sized> Deserialize for Strong<T> { - fn deserialize(parcel: &Parcel) -> Result<Self> { - let ibinder: SpIBinder = parcel.read()?; - FromIBinder::try_from(ibinder) - } -} - -impl<T: FromIBinder + ?Sized> DeserializeOption for Strong<T> { - fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> { - let ibinder: Option<SpIBinder> = parcel.read()?; - ibinder.map(FromIBinder::try_from).transpose() - } -} - -// We need these to support Option<&T> for all T -impl<T: Serialize + ?Sized> Serialize for &T { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - Serialize::serialize(*self, parcel) - } -} - -impl<T: SerializeOption + ?Sized> SerializeOption for &T { - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { - SerializeOption::serialize_option(this.copied(), parcel) - } -} - -impl<T: SerializeOption> Serialize for Option<T> { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - SerializeOption::serialize_option(self.as_ref(), parcel) - } -} - -impl<T: DeserializeOption> Deserialize for Option<T> { - fn deserialize(parcel: &Parcel) -> Result<Self> { - DeserializeOption::deserialize_option(parcel) - } -} - -#[test] -fn test_custom_parcelable() { - use crate::binder::Interface; - use crate::native::Binder; - let mut service = Binder::new(()).as_binder(); - - struct Custom(u32, bool, String, Vec<String>); - - impl Serialize for Custom { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - self.0.serialize(parcel)?; - self.1.serialize(parcel)?; - self.2.serialize(parcel)?; - self.3.serialize(parcel) - } - } - - impl Deserialize for Custom { - fn deserialize(parcel: &Parcel) -> Result<Self> { - Ok(Custom( - parcel.read()?, - parcel.read()?, - parcel.read()?, - parcel.read::<Option<Vec<String>>>()?.unwrap(), - )) - } - } - - let string8 = "Custom Parcelable".to_string(); - - let s1 = "str1".to_string(); - let s2 = "str2".to_string(); - let s3 = "str3".to_string(); - - let strs = vec![s1, s2, s3]; - - let custom = Custom(123_456_789, true, string8, strs); - - let mut parcel = Parcel::new_for_test(&mut service).unwrap(); - let start = parcel.get_data_position(); - - assert!(custom.serialize(&mut parcel).is_ok()); - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - let custom2 = Custom::deserialize(&parcel).unwrap(); - - assert_eq!(custom2.0, 123_456_789); - assert!(custom2.1); - assert_eq!(custom2.2, custom.2); - assert_eq!(custom2.3, custom.3); -} - -#[test] -#[allow(clippy::excessive_precision)] -fn test_slice_parcelables() { - use crate::binder::Interface; - use crate::native::Binder; - let mut service = Binder::new(()).as_binder(); - - let bools = [true, false, false, true]; - - let mut parcel = Parcel::new_for_test(&mut service).unwrap(); - let start = parcel.get_data_position(); - - assert!(bools.serialize(&mut parcel).is_ok()); - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<u32>().unwrap(), 4); - assert_eq!(parcel.read::<u32>().unwrap(), 1); - assert_eq!(parcel.read::<u32>().unwrap(), 0); - assert_eq!(parcel.read::<u32>().unwrap(), 0); - assert_eq!(parcel.read::<u32>().unwrap(), 1); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - let vec = Vec::<bool>::deserialize(&parcel).unwrap(); - - assert_eq!(vec, [true, false, false, true]); - - let u8s = [101u8, 255, 42, 117]; - - let mut parcel = Parcel::new_for_test(&mut service).unwrap(); - let start = parcel.get_data_position(); - - assert!(parcel.write(&u8s[..]).is_ok()); - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items - assert_eq!(parcel.read::<u32>().unwrap(), 0x752aff65); // bytes - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - let vec = Vec::<u8>::deserialize(&parcel).unwrap(); - assert_eq!(vec, [101, 255, 42, 117]); - - let i8s = [-128i8, 127, 42, -117]; - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert!(parcel.write(&i8s[..]).is_ok()); - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items - assert_eq!(parcel.read::<u32>().unwrap(), 0x8b2a7f80); // bytes - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - let vec = Vec::<u8>::deserialize(&parcel).unwrap(); - assert_eq!(vec, [-128i8 as u8, 127, 42, -117i8 as u8]); - - let u16s = [u16::max_value(), 12_345, 42, 117]; - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - assert!(u16s.serialize(&mut parcel).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items - assert_eq!(parcel.read::<u32>().unwrap(), 0xffff); // u16::max_value() - assert_eq!(parcel.read::<u32>().unwrap(), 12345); // 12,345 - assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42 - assert_eq!(parcel.read::<u32>().unwrap(), 117); // 117 - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - let vec = Vec::<u16>::deserialize(&parcel).unwrap(); - - assert_eq!(vec, [u16::max_value(), 12_345, 42, 117]); - - let i16s = [i16::max_value(), i16::min_value(), 42, -117]; - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - assert!(i16s.serialize(&mut parcel).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items - assert_eq!(parcel.read::<u32>().unwrap(), 0x7fff); // i16::max_value() - assert_eq!(parcel.read::<u32>().unwrap(), 0x8000); // i16::min_value() - assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42 - assert_eq!(parcel.read::<u32>().unwrap(), 0xff8b); // -117 - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - let vec = Vec::<i16>::deserialize(&parcel).unwrap(); - - assert_eq!(vec, [i16::max_value(), i16::min_value(), 42, -117]); - - let u32s = [u32::max_value(), 12_345, 42, 117]; - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - assert!(u32s.serialize(&mut parcel).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items - assert_eq!(parcel.read::<u32>().unwrap(), 0xffffffff); // u32::max_value() - assert_eq!(parcel.read::<u32>().unwrap(), 12345); // 12,345 - assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42 - assert_eq!(parcel.read::<u32>().unwrap(), 117); // 117 - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - let vec = Vec::<u32>::deserialize(&parcel).unwrap(); - - assert_eq!(vec, [u32::max_value(), 12_345, 42, 117]); - - let i32s = [i32::max_value(), i32::min_value(), 42, -117]; - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - assert!(i32s.serialize(&mut parcel).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - assert_eq!(parcel.read::<u32>().unwrap(), 4); // 4 items - assert_eq!(parcel.read::<u32>().unwrap(), 0x7fffffff); // i32::max_value() - assert_eq!(parcel.read::<u32>().unwrap(), 0x80000000); // i32::min_value() - assert_eq!(parcel.read::<u32>().unwrap(), 42); // 42 - assert_eq!(parcel.read::<u32>().unwrap(), 0xffffff8b); // -117 - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - let vec = Vec::<i32>::deserialize(&parcel).unwrap(); - - assert_eq!(vec, [i32::max_value(), i32::min_value(), 42, -117]); - - let u64s = [u64::max_value(), 12_345, 42, 117]; - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - assert!(u64s.serialize(&mut parcel).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - let vec = Vec::<u64>::deserialize(&parcel).unwrap(); - - assert_eq!(vec, [u64::max_value(), 12_345, 42, 117]); - - let i64s = [i64::max_value(), i64::min_value(), 42, -117]; - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - assert!(i64s.serialize(&mut parcel).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - let vec = Vec::<i64>::deserialize(&parcel).unwrap(); - - assert_eq!(vec, [i64::max_value(), i64::min_value(), 42, -117]); - - let f32s = [ - std::f32::NAN, - std::f32::INFINITY, - 1.23456789, - std::f32::EPSILON, - ]; - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - assert!(f32s.serialize(&mut parcel).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - let vec = Vec::<f32>::deserialize(&parcel).unwrap(); - - // NAN != NAN so we can't use it in the assert_eq: - assert!(vec[0].is_nan()); - assert_eq!(vec[1..], f32s[1..]); - - let f64s = [ - std::f64::NAN, - std::f64::INFINITY, - 1.234567890123456789, - std::f64::EPSILON, - ]; - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - assert!(f64s.serialize(&mut parcel).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - let vec = Vec::<f64>::deserialize(&parcel).unwrap(); - - // NAN != NAN so we can't use it in the assert_eq: - assert!(vec[0].is_nan()); - assert_eq!(vec[1..], f64s[1..]); - - let s1 = "Hello, Binder!"; - let s2 = "This is a utf8 string."; - let s3 = "Some more text here."; - let s4 = "Embedded nulls \0 \0"; - - let strs = [s1, s2, s3, s4]; - - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - assert!(strs.serialize(&mut parcel).is_ok()); - unsafe { - assert!(parcel.set_data_position(start).is_ok()); - } - - let vec = Vec::<String>::deserialize(&parcel).unwrap(); - - assert_eq!(vec, strs); -} diff --git a/libs/binder/rust/src/proxy.rs b/libs/binder/rust/src/proxy.rs deleted file mode 100644 index 52036f5312..0000000000 --- a/libs/binder/rust/src/proxy.rs +++ /dev/null @@ -1,678 +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. - */ - -//! Rust API for interacting with a remote binder service. - -use crate::binder::{ - AsNative, FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Strong, - TransactionCode, TransactionFlags, -}; -use crate::error::{status_result, Result, StatusCode}; -use crate::parcel::{ - Deserialize, DeserializeArray, DeserializeOption, Parcel, Serialize, SerializeArray, - SerializeOption, -}; -use crate::sys; - -use std::cmp::Ordering; -use std::convert::TryInto; -use std::ffi::{c_void, CString}; -use std::fmt; -use std::os::unix::io::AsRawFd; -use std::ptr; - -/// A strong reference to a Binder remote object. -/// -/// This struct encapsulates the generic C++ `sp<IBinder>` class. This wrapper -/// is untyped; typed interface access is implemented by the AIDL compiler. -pub struct SpIBinder(*mut sys::AIBinder); - -impl fmt::Debug for SpIBinder { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("SpIBinder") - } -} - -/// # Safety -/// -/// An `SpIBinder` is a handle to a C++ IBinder, which is thread-safe -unsafe impl Send for SpIBinder {} - -impl SpIBinder { - /// Create an `SpIBinder` wrapper object from a raw `AIBinder` pointer. - /// - /// # Safety - /// - /// This constructor is safe iff `ptr` is a null pointer or a valid pointer - /// to an `AIBinder`. - /// - /// In the non-null case, this method conceptually takes ownership of a strong - /// reference to the object, so `AIBinder_incStrong` must have been called - /// on the pointer before passing it to this constructor. This is generally - /// done by Binder NDK methods that return an `AIBinder`, but care should be - /// taken to ensure this invariant. - /// - /// All `SpIBinder` objects that are constructed will hold a valid pointer - /// to an `AIBinder`, which will remain valid for the entire lifetime of the - /// `SpIBinder` (we keep a strong reference, and only decrement on drop). - pub(crate) unsafe fn from_raw(ptr: *mut sys::AIBinder) -> Option<Self> { - ptr.as_mut().map(|p| Self(p)) - } - - /// Extract a raw `AIBinder` pointer from this wrapper. - /// - /// This method should _only_ be used for testing. Do not try to use the NDK - /// interface directly for anything else. - /// - /// # Safety - /// - /// The resulting pointer is valid only as long as the SpIBinder is alive. - /// The SpIBinder object retains ownership of the AIBinder and the caller - /// should not attempt to free the returned pointer. - pub unsafe fn as_raw(&self) -> *mut sys::AIBinder { - self.0 - } - - /// Return true if this binder object is hosted in a different process than - /// the current one. - pub fn is_remote(&self) -> bool { - unsafe { - // Safety: `SpIBinder` guarantees that it always contains a valid - // `AIBinder` pointer. - sys::AIBinder_isRemote(self.as_native()) - } - } - - /// Try to convert this Binder object into a trait object for the given - /// Binder interface. - /// - /// If this object does not implement the expected interface, the error - /// `StatusCode::BAD_TYPE` is returned. - pub fn into_interface<I: FromIBinder + Interface + ?Sized>(self) -> Result<Strong<I>> { - FromIBinder::try_from(self) - } - - /// Return the interface class of this binder object, if associated with - /// one. - pub fn get_class(&mut self) -> Option<InterfaceClass> { - unsafe { - // Safety: `SpIBinder` guarantees that it always contains a valid - // `AIBinder` pointer. `AIBinder_getClass` returns either a null - // pointer or a valid pointer to an `AIBinder_Class`. After mapping - // null to None, we can safely construct an `InterfaceClass` if the - // pointer was non-null. - let class = sys::AIBinder_getClass(self.as_native_mut()); - class.as_ref().map(|p| InterfaceClass::from_ptr(p)) - } - } - - /// Creates a new weak reference to this binder object. - pub fn downgrade(&mut self) -> WpIBinder { - WpIBinder::new(self) - } -} - -/// An object that can be associate with an [`InterfaceClass`]. -pub trait AssociateClass { - /// Check if this object is a valid object for the given interface class - /// `I`. - /// - /// Returns `Some(self)` if this is a valid instance of the interface, and - /// `None` otherwise. - /// - /// Classes constructed by `InterfaceClass` are unique per type, so - /// repeatedly calling this method for the same `InterfaceClass` is allowed. - fn associate_class(&mut self, class: InterfaceClass) -> bool; -} - -impl AssociateClass for SpIBinder { - fn associate_class(&mut self, class: InterfaceClass) -> bool { - unsafe { - // Safety: `SpIBinder` guarantees that it always contains a valid - // `AIBinder` pointer. An `InterfaceClass` can always be converted - // into a valid `AIBinder_Class` pointer, so these parameters are - // always safe. - sys::AIBinder_associateClass(self.as_native_mut(), class.into()) - } - } -} - -impl Ord for SpIBinder { - fn cmp(&self, other: &Self) -> Ordering { - let less_than = unsafe { - // Safety: SpIBinder always holds a valid `AIBinder` pointer, so - // this pointer is always safe to pass to `AIBinder_lt` (null is - // also safe to pass to this function, but we should never do that). - sys::AIBinder_lt(self.0, other.0) - }; - let greater_than = unsafe { - // Safety: SpIBinder always holds a valid `AIBinder` pointer, so - // this pointer is always safe to pass to `AIBinder_lt` (null is - // also safe to pass to this function, but we should never do that). - sys::AIBinder_lt(other.0, self.0) - }; - if !less_than && !greater_than { - Ordering::Equal - } else if less_than { - Ordering::Less - } else { - Ordering::Greater - } - } -} - -impl PartialOrd for SpIBinder { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -impl PartialEq for SpIBinder { - fn eq(&self, other: &Self) -> bool { - ptr::eq(self.0, other.0) - } -} - -impl Eq for SpIBinder {} - -impl Clone for SpIBinder { - fn clone(&self) -> Self { - unsafe { - // Safety: Cloning a strong reference must increment the reference - // count. We are guaranteed by the `SpIBinder` constructor - // invariants that `self.0` is always a valid `AIBinder` pointer. - sys::AIBinder_incStrong(self.0); - } - Self(self.0) - } -} - -impl Drop for SpIBinder { - // We hold a strong reference to the IBinder in SpIBinder and need to give up - // this reference on drop. - fn drop(&mut self) { - unsafe { - // Safety: SpIBinder always holds a valid `AIBinder` pointer, so we - // know this pointer is safe to pass to `AIBinder_decStrong` here. - sys::AIBinder_decStrong(self.as_native_mut()); - } - } -} - -impl<T: AsNative<sys::AIBinder>> IBinderInternal for T { - /// Perform a binder transaction - fn transact<F: FnOnce(&mut Parcel) -> Result<()>>( - &self, - code: TransactionCode, - flags: TransactionFlags, - input_callback: F, - ) -> Result<Parcel> { - let mut input = ptr::null_mut(); - let status = unsafe { - // Safety: `SpIBinder` guarantees that `self` always contains a - // valid pointer to an `AIBinder`. It is safe to cast from an - // immutable pointer to a mutable pointer here, because - // `AIBinder_prepareTransaction` only calls immutable `AIBinder` - // methods but the parameter is unfortunately not marked as const. - // - // After the call, input will be either a valid, owned `AParcel` - // pointer, or null. - sys::AIBinder_prepareTransaction(self.as_native() as *mut sys::AIBinder, &mut input) - }; - status_result(status)?; - let mut input = unsafe { - // Safety: At this point, `input` is either a valid, owned `AParcel` - // pointer, or null. `Parcel::owned` safely handles both cases, - // taking ownership of the parcel. - Parcel::owned(input).ok_or(StatusCode::UNEXPECTED_NULL)? - }; - input_callback(&mut input)?; - let mut reply = ptr::null_mut(); - let status = unsafe { - // Safety: `SpIBinder` guarantees that `self` always contains a - // valid pointer to an `AIBinder`. Although `IBinder::transact` is - // not a const method, it is still safe to cast our immutable - // pointer to mutable for the call. First, `IBinder::transact` is - // thread-safe, so concurrency is not an issue. The only way that - // `transact` can affect any visible, mutable state in the current - // process is by calling `onTransact` for a local service. However, - // in order for transactions to be thread-safe, this method must - // dynamically lock its data before modifying it. We enforce this - // property in Rust by requiring `Sync` for remotable objects and - // only providing `on_transact` with an immutable reference to - // `self`. - // - // This call takes ownership of the `input` parcel pointer, and - // passes ownership of the `reply` out parameter to its caller. It - // does not affect ownership of the `binder` parameter. - sys::AIBinder_transact( - self.as_native() as *mut sys::AIBinder, - code, - &mut input.into_raw(), - &mut reply, - flags, - ) - }; - status_result(status)?; - - unsafe { - // Safety: `reply` is either a valid `AParcel` pointer or null - // after the call to `AIBinder_transact` above, so we can - // construct a `Parcel` out of it. `AIBinder_transact` passes - // ownership of the `reply` parcel to Rust, so we need to - // construct an owned variant. `Parcel::owned` takes ownership - // of the parcel pointer. - Parcel::owned(reply).ok_or(StatusCode::UNEXPECTED_NULL) - } - } - - fn is_binder_alive(&self) -> bool { - unsafe { - // Safety: `SpIBinder` guarantees that `self` always contains a - // valid pointer to an `AIBinder`. - // - // This call does not affect ownership of its pointer parameter. - sys::AIBinder_isAlive(self.as_native()) - } - } - - fn ping_binder(&mut self) -> Result<()> { - let status = unsafe { - // Safety: `SpIBinder` guarantees that `self` always contains a - // valid pointer to an `AIBinder`. - // - // This call does not affect ownership of its pointer parameter. - sys::AIBinder_ping(self.as_native_mut()) - }; - status_result(status) - } - - fn set_requesting_sid(&mut self, enable: bool) { - unsafe { sys::AIBinder_setRequestingSid(self.as_native_mut(), enable) }; - } - - fn dump<F: AsRawFd>(&mut self, fp: &F, args: &[&str]) -> Result<()> { - let args: Vec<_> = args.iter().map(|a| CString::new(*a).unwrap()).collect(); - let mut arg_ptrs: Vec<_> = args.iter().map(|a| a.as_ptr()).collect(); - let status = unsafe { - // Safety: `SpIBinder` guarantees that `self` always contains a - // valid pointer to an `AIBinder`. `AsRawFd` guarantees that the - // file descriptor parameter is always be a valid open file. The - // `args` pointer parameter is a valid pointer to an array of C - // strings that will outlive the call since `args` lives for the - // whole function scope. - // - // This call does not affect ownership of its binder pointer - // parameter and does not take ownership of the file or args array - // parameters. - sys::AIBinder_dump( - self.as_native_mut(), - fp.as_raw_fd(), - arg_ptrs.as_mut_ptr(), - arg_ptrs.len().try_into().unwrap(), - ) - }; - status_result(status) - } - - fn get_extension(&mut self) -> Result<Option<SpIBinder>> { - let mut out = ptr::null_mut(); - let status = unsafe { - // Safety: `SpIBinder` guarantees that `self` always contains a - // valid pointer to an `AIBinder`. After this call, the `out` - // parameter will be either null, or a valid pointer to an - // `AIBinder`. - // - // This call passes ownership of the out pointer to its caller - // (assuming it is set to a non-null value). - sys::AIBinder_getExtension(self.as_native_mut(), &mut out) - }; - let ibinder = unsafe { - // Safety: The call above guarantees that `out` is either null or a - // valid, owned pointer to an `AIBinder`, both of which are safe to - // pass to `SpIBinder::from_raw`. - SpIBinder::from_raw(out) - }; - - status_result(status)?; - Ok(ibinder) - } -} - -impl<T: AsNative<sys::AIBinder>> IBinder for T { - fn link_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> { - status_result(unsafe { - // Safety: `SpIBinder` guarantees that `self` always contains a - // valid pointer to an `AIBinder`. `recipient` can always be - // converted into a valid pointer to an - // `AIBinder_DeathRecipient`. Any value is safe to pass as the - // cookie, although we depend on this value being set by - // `get_cookie` when the death recipient callback is called. - sys::AIBinder_linkToDeath( - self.as_native_mut(), - recipient.as_native_mut(), - recipient.get_cookie(), - ) - }) - } - - fn unlink_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> { - status_result(unsafe { - // Safety: `SpIBinder` guarantees that `self` always contains a - // valid pointer to an `AIBinder`. `recipient` can always be - // converted into a valid pointer to an - // `AIBinder_DeathRecipient`. Any value is safe to pass as the - // cookie, although we depend on this value being set by - // `get_cookie` when the death recipient callback is called. - sys::AIBinder_unlinkToDeath( - self.as_native_mut(), - recipient.as_native_mut(), - recipient.get_cookie(), - ) - }) - } -} - -impl Serialize for SpIBinder { - fn serialize(&self, parcel: &mut Parcel) -> Result<()> { - parcel.write_binder(Some(self)) - } -} - -impl SerializeOption for SpIBinder { - fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { - parcel.write_binder(this) - } -} - -impl SerializeArray for SpIBinder {} -impl SerializeArray for Option<&SpIBinder> {} - -impl Deserialize for SpIBinder { - fn deserialize(parcel: &Parcel) -> Result<SpIBinder> { - parcel - .read_binder() - .transpose() - .unwrap_or(Err(StatusCode::UNEXPECTED_NULL)) - } -} - -impl DeserializeOption for SpIBinder { - fn deserialize_option(parcel: &Parcel) -> Result<Option<SpIBinder>> { - parcel.read_binder() - } -} - -impl DeserializeArray for SpIBinder {} -impl DeserializeArray for Option<SpIBinder> {} - -/// A weak reference to a Binder remote object. -/// -/// This struct encapsulates the generic C++ `wp<IBinder>` class. This wrapper -/// is untyped; typed interface access is implemented by the AIDL compiler. -pub struct WpIBinder(*mut sys::AIBinder_Weak); - -impl fmt::Debug for WpIBinder { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("WpIBinder") - } -} - -/// # Safety -/// -/// A `WpIBinder` is a handle to a C++ IBinder, which is thread-safe. -unsafe impl Send for WpIBinder {} - -impl WpIBinder { - /// Create a new weak reference from an object that can be converted into a - /// raw `AIBinder` pointer. - fn new<B: AsNative<sys::AIBinder>>(binder: &mut B) -> WpIBinder { - let ptr = unsafe { - // Safety: `SpIBinder` guarantees that `binder` always contains a - // valid pointer to an `AIBinder`. - sys::AIBinder_Weak_new(binder.as_native_mut()) - }; - assert!(!ptr.is_null()); - Self(ptr) - } - - /// Promote this weak reference to a strong reference to the binder object. - pub fn promote(&self) -> Option<SpIBinder> { - unsafe { - // Safety: `WpIBinder` always contains a valid weak reference, so we - // can pass this pointer to `AIBinder_Weak_promote`. Returns either - // null or an AIBinder owned by the caller, both of which are valid - // to pass to `SpIBinder::from_raw`. - let ptr = sys::AIBinder_Weak_promote(self.0); - SpIBinder::from_raw(ptr) - } - } -} - -impl Clone for WpIBinder { - fn clone(&self) -> Self { - let ptr = unsafe { - // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, - // so this pointer is always safe to pass to `AIBinder_Weak_clone` - // (although null is also a safe value to pass to this API). - // - // We get ownership of the returned pointer, so can construct a new - // WpIBinder object from it. - sys::AIBinder_Weak_clone(self.0) - }; - assert!( - !ptr.is_null(), - "Unexpected null pointer from AIBinder_Weak_clone" - ); - Self(ptr) - } -} - -impl Ord for WpIBinder { - fn cmp(&self, other: &Self) -> Ordering { - let less_than = unsafe { - // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, - // so this pointer is always safe to pass to `AIBinder_Weak_lt` - // (null is also safe to pass to this function, but we should never - // do that). - sys::AIBinder_Weak_lt(self.0, other.0) - }; - let greater_than = unsafe { - // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, - // so this pointer is always safe to pass to `AIBinder_Weak_lt` - // (null is also safe to pass to this function, but we should never - // do that). - sys::AIBinder_Weak_lt(other.0, self.0) - }; - if !less_than && !greater_than { - Ordering::Equal - } else if less_than { - Ordering::Less - } else { - Ordering::Greater - } - } -} - -impl PartialOrd for WpIBinder { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -impl PartialEq for WpIBinder { - fn eq(&self, other: &Self) -> bool { - self.cmp(other) == Ordering::Equal - } -} - -impl Eq for WpIBinder {} - -impl Drop for WpIBinder { - fn drop(&mut self) { - unsafe { - // Safety: WpIBinder always holds a valid `AIBinder_Weak` pointer, so we - // know this pointer is safe to pass to `AIBinder_Weak_delete` here. - sys::AIBinder_Weak_delete(self.0); - } - } -} - -/// Rust wrapper around DeathRecipient objects. -#[repr(C)] -pub struct DeathRecipient { - recipient: *mut sys::AIBinder_DeathRecipient, - callback: Box<dyn Fn() + Send + 'static>, -} - -impl DeathRecipient { - /// Create a new death recipient that will call the given callback when its - /// associated object dies. - pub fn new<F>(callback: F) -> DeathRecipient - where - F: Fn() + Send + 'static, - { - let callback = Box::new(callback); - let recipient = unsafe { - // Safety: The function pointer is a valid death recipient callback. - // - // This call returns an owned `AIBinder_DeathRecipient` pointer - // which must be destroyed via `AIBinder_DeathRecipient_delete` when - // no longer needed. - sys::AIBinder_DeathRecipient_new(Some(Self::binder_died::<F>)) - }; - DeathRecipient { - recipient, - callback, - } - } - - /// Get the opaque cookie that identifies this death recipient. - /// - /// This cookie will be used to link and unlink this death recipient to a - /// binder object and will be passed to the `binder_died` callback as an - /// opaque userdata pointer. - fn get_cookie(&self) -> *mut c_void { - &*self.callback as *const _ as *mut c_void - } - - /// Callback invoked from C++ when the binder object dies. - /// - /// # Safety - /// - /// The `cookie` parameter must have been created with the `get_cookie` - /// method of this object. - unsafe extern "C" fn binder_died<F>(cookie: *mut c_void) - where - F: Fn() + Send + 'static, - { - let callback = (cookie as *mut F).as_ref().unwrap(); - callback(); - } -} - -/// # Safety -/// -/// A `DeathRecipient` is always constructed with a valid raw pointer to an -/// `AIBinder_DeathRecipient`, so it is always type-safe to extract this -/// pointer. -unsafe impl AsNative<sys::AIBinder_DeathRecipient> for DeathRecipient { - fn as_native(&self) -> *const sys::AIBinder_DeathRecipient { - self.recipient - } - - fn as_native_mut(&mut self) -> *mut sys::AIBinder_DeathRecipient { - self.recipient - } -} - -impl Drop for DeathRecipient { - fn drop(&mut self) { - unsafe { - // Safety: `self.recipient` is always a valid, owned - // `AIBinder_DeathRecipient` pointer returned by - // `AIBinder_DeathRecipient_new` when `self` was created. This - // delete method can only be called once when `self` is dropped. - sys::AIBinder_DeathRecipient_delete(self.recipient); - } - } -} - -/// Generic interface to remote binder objects. -/// -/// Corresponds to the C++ `BpInterface` class. -pub trait Proxy: Sized + Interface { - /// The Binder interface descriptor string. - /// - /// This string is a unique identifier for a Binder interface, and should be - /// the same between all implementations of that interface. - fn get_descriptor() -> &'static str; - - /// Create a new interface from the given proxy, if it matches the expected - /// type of this interface. - fn from_binder(binder: SpIBinder) -> Result<Self>; -} - -/// # Safety -/// -/// This is a convenience method that wraps `AsNative` for `SpIBinder` to allow -/// invocation of `IBinder` methods directly from `Interface` objects. It shares -/// the same safety as the implementation for `SpIBinder`. -unsafe impl<T: Proxy> AsNative<sys::AIBinder> for T { - fn as_native(&self) -> *const sys::AIBinder { - self.as_binder().as_native() - } - - fn as_native_mut(&mut self) -> *mut sys::AIBinder { - self.as_binder().as_native_mut() - } -} - -/// Retrieve an existing service, blocking for a few seconds if it doesn't yet -/// exist. -pub fn get_service(name: &str) -> Option<SpIBinder> { - let name = CString::new(name).ok()?; - unsafe { - // Safety: `AServiceManager_getService` returns either a null pointer or - // a valid pointer to an owned `AIBinder`. Either of these values is - // safe to pass to `SpIBinder::from_raw`. - SpIBinder::from_raw(sys::AServiceManager_getService(name.as_ptr())) - } -} - -/// Retrieve an existing service for a particular interface, blocking for a few -/// seconds if it doesn't yet exist. -pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> { - let service = get_service(name); - match service { - Some(service) => FromIBinder::try_from(service), - None => Err(StatusCode::NAME_NOT_FOUND), - } -} - -/// # Safety -/// -/// `SpIBinder` guarantees that `binder` always contains a valid pointer to an -/// `AIBinder`, so we can trivially extract this pointer here. -unsafe impl AsNative<sys::AIBinder> for SpIBinder { - fn as_native(&self) -> *const sys::AIBinder { - self.0 - } - - fn as_native_mut(&mut self) -> *mut sys::AIBinder { - self.0 - } -} diff --git a/libs/binder/rust/src/state.rs b/libs/binder/rust/src/state.rs deleted file mode 100644 index 0e05f10dfe..0000000000 --- a/libs/binder/rust/src/state.rs +++ /dev/null @@ -1,133 +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::sys; - -use libc::{pid_t, uid_t}; - -/// Static utility functions to manage Binder process state. -pub struct ProcessState; - -impl ProcessState { - /// Start the Binder IPC thread pool - pub fn start_thread_pool() { - unsafe { - // Safety: Safe FFI - sys::ABinderProcess_startThreadPool(); - } - } - - /// Set the maximum number of threads that can be started in the threadpool. - /// - /// By default, after startThreadPool is called, this is 15. If it is called - /// additional times, it will only prevent the kernel from starting new - /// threads and will not delete already existing threads. - pub fn set_thread_pool_max_thread_count(num_threads: u32) { - unsafe { - // Safety: Safe FFI - sys::ABinderProcess_setThreadPoolMaxThreadCount(num_threads); - } - } - - /// Block on the Binder IPC thread pool - pub fn join_thread_pool() { - unsafe { - // Safety: Safe FFI - sys::ABinderProcess_joinThreadPool(); - } - } -} - -/// Static utility functions to manage Binder thread state. -pub struct ThreadState; - -impl ThreadState { - /// This returns the calling UID assuming that this thread is called from a - /// thread that is processing a binder transaction (for instance, in the - /// implementation of - /// [`Remotable::on_transact`](crate::Remotable::on_transact)). - /// - /// This can be used with higher-level system services to determine the - /// caller's identity and check permissions. - /// - /// Available since API level 29. - /// - /// \return calling uid or the current process's UID if this thread isn't - /// processing a transaction. - pub fn get_calling_uid() -> uid_t { - unsafe { - // Safety: Safe FFI - sys::AIBinder_getCallingUid() - } - } - - /// This returns the calling PID assuming that this thread is called from a - /// thread that is processing a binder transaction (for instance, in the - /// implementation of - /// [`Remotable::on_transact`](crate::Remotable::on_transact)). - /// - /// This can be used with higher-level system services to determine the - /// caller's identity and check permissions. However, when doing this, one - /// should be aware of possible TOCTOU problems when the calling process - /// dies and is replaced with another process with elevated permissions and - /// the same PID. - /// - /// Available since API level 29. - /// - /// \return calling pid or the current process's PID if this thread isn't - /// processing a transaction. - /// - /// If the transaction being processed is a oneway transaction, then this - /// method will return 0. - pub fn get_calling_pid() -> pid_t { - unsafe { - // Safety: Safe FFI - sys::AIBinder_getCallingPid() - } - } - - /// This function makes the client's security context available to the - /// service calling this function. This can be used for access control. - /// It does not suffer from the TOCTOU issues of get_calling_pid. - /// - /// Implementations of `check_permission` should use the given CStr - /// argument as context for selinux permission checks. If `None` is - /// given, the implementation should fall back to using the PID - /// instead. - /// - /// Note: `None` may be passed to the callback if the caller did not - /// `set_requesting_sid` on the serviced binder, or if the underlying - /// kernel is too old to support this feature. - pub fn with_calling_sid<T, F>(check_permission: F) -> T - where - for<'a> F: FnOnce(Option<&'a std::ffi::CStr>) -> T { - // Safety: AIBinder_getCallingSid returns a c-string pointer - // that is valid for a transaction. Also, the string returned - // is thread local. By restricting the lifetime of the CStr - // reference to the scope of the callback, we prevent it being - // used beyond the guaranteed lifetime. - check_permission(unsafe { - let sid = sys::AIBinder_getCallingSid(); - // AIBinder_getCallingSid() returns a '\0' terminated string - // or NULL. - if sid.is_null() { - None - } else { - Some(std::ffi::CStr::from_ptr(sid)) - } - }) - } -} |