summaryrefslogtreecommitdiff
path: root/libs/binder/rust/src
diff options
context:
space:
mode:
Diffstat (limited to 'libs/binder/rust/src')
-rw-r--r--libs/binder/rust/src/binder.rs910
-rw-r--r--libs/binder/rust/src/error.rs373
-rw-r--r--libs/binder/rust/src/lib.rs133
-rw-r--r--libs/binder/rust/src/native.rs415
-rw-r--r--libs/binder/rust/src/parcel.rs562
-rw-r--r--libs/binder/rust/src/parcel/file_descriptor.rs127
-rw-r--r--libs/binder/rust/src/parcel/parcelable.rs989
-rw-r--r--libs/binder/rust/src/proxy.rs678
-rw-r--r--libs/binder/rust/src/state.rs133
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))
- }
- })
- }
-}