Initial Binder Rust crate
This crate exposes an idiomatic Binder interface for Rust clients and
services. This interface is primarily designed for use by the
forthcoming Rust backend for the AIDL compiler. The crate links against
the stable NDK version of the libbinder interface and therefore can
be used by APEX packages.
Test: atest rustBinderTest libbinder_rs-internal_test
Bug: 161559357
Change-Id: I2e9b800186f24217edeb1c3778f13902a3cca2fd
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
new file mode 100644
index 0000000..f5e7509
--- /dev/null
+++ b/libs/binder/rust/src/binder.rs
@@ -0,0 +1,585 @@
+/*
+ * 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};
+use crate::parcel::Parcel;
+use crate::proxy::{DeathRecipient, SpIBinder};
+use crate::sys;
+
+use std::ffi::{c_void, CString};
+use std::os::unix::io::AsRawFd;
+use std::ptr;
+
+/// Binder action to perform.
+///
+/// This must be a number between [`IBinder::FIRST_CALL_TRANSACTION`] and
+/// [`IBinder::LAST_CALL_TRANSACTION`].
+pub type TransactionCode = u32;
+
+/// Additional operation flags.
+///
+/// Can be either 0 for a normal RPC, or [`IBinder::FLAG_ONEWAY`] for a
+/// one-way RPC.
+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 {
+ /// 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.")
+ }
+}
+
+/// 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: 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;
+}
+
+/// Interface of binder local or remote objects.
+///
+/// This trait corresponds to the interface of the C++ `IBinder` class.
+pub trait IBinder {
+ /// First transaction code available for user commands (inclusive)
+ const FIRST_CALL_TRANSACTION: TransactionCode = sys::FIRST_CALL_TRANSACTION;
+ /// Last transaction code available for user commands (inclusive)
+ const LAST_CALL_TRANSACTION: TransactionCode = sys::LAST_CALL_TRANSACTION;
+
+ /// Corresponds to TF_ONE_WAY -- an asynchronous call.
+ const FLAG_ONEWAY: TransactionFlags = sys::FLAG_ONEWAY;
+
+ /// Is this object still alive?
+ fn is_binder_alive(&self) -> bool;
+
+ /// Send a ping transaction to this object
+ fn ping_binder(&mut self) -> Result<()>;
+
+ /// 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`](IBinder::FLAG_ONEWAY))
+ fn transact<F: FnOnce(&mut Parcel) -> Result<()>>(
+ &self,
+ code: TransactionCode,
+ flags: TransactionFlags,
+ input_callback: F,
+ ) -> Result<Parcel>;
+
+ /// 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 DeathRecipient::binder_died() will be called with a reference
+ /// to this.
+ ///
+ /// 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.
+ ///
+ /// You will only receive a weak reference to the dead
+ /// binder. You should not try to promote this to a strong reference.
+ /// (Nor should you need to, as there is nothing useful you can
+ /// directly do with it now that it has passed on.)
+ 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)
+ }
+}
+
+impl From<InterfaceClass> for *const sys::AIBinder_Class {
+ fn from(class: InterfaceClass) -> *const sys::AIBinder_Class {
+ class.0
+ }
+}
+
+/// 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 {
+ /// 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<Box<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())
+ }
+}
+
+/// 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 {},
+ }
+ }
+ };
+
+ {
+ $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] {
+ @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),*
+ },
+ }
+ }
+ };
+
+ {
+ $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),*
+ },
+ }
+ } => {
+ #[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> {
+ use $crate::AssociateClass;
+ if binder.associate_class(<$native as $crate::Remotable>::get_class()) {
+ Ok(Self { binder, $($fname: $finit),* })
+ } else {
+ Err($crate::StatusCode::BAD_TYPE)
+ }
+ }
+ }
+
+ #[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) -> impl $interface {
+ $crate::Binder::new($native(Box::new(inner)))
+ }
+ }
+
+ 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<()> {
+ $on_transact(&*self.0, code, data, reply)
+ }
+
+ 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<Box<dyn $interface>> {
+ use $crate::AssociateClass;
+ if !ibinder.associate_class(<$native as $crate::Remotable>::get_class()) {
+ return Err($crate::StatusCode::BAD_TYPE.into());
+ }
+
+ let service: $crate::Result<$crate::Binder<$native>> = std::convert::TryFrom::try_from(ibinder.clone());
+ if let Ok(service) = service {
+ Ok(Box::new(service))
+ } else {
+ Ok(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?))
+ }
+ }
+ }
+
+ impl $crate::parcel::Serialize for dyn $interface + '_
+ where
+ $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))
+ }
+ }
+ };
+}
diff --git a/libs/binder/rust/src/error.rs b/libs/binder/rust/src/error.rs
new file mode 100644
index 0000000..289b157
--- /dev/null
+++ b/libs/binder/rust/src/error.rs
@@ -0,0 +1,373 @@
+/*
+ * 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),
+ }
+}
+
+// impl Display for StatusCode {
+// fn fmt(&self, f: &mut Formatter) -> FmtResult {
+// write!(f, "StatusCode::{:?}", self)
+// }
+// }
+
+// impl error::Error for StatusCode {}
+
+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);
+
+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
new file mode 100644
index 0000000..4b9cccf
--- /dev/null
+++ b/libs/binder/rust/src/lib.rs
@@ -0,0 +1,130 @@
+/*
+ * 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_bindgen as sys;
+
+pub mod parcel;
+
+pub use crate::binder::{
+ FromIBinder, IBinder, Interface, InterfaceClass, Remotable, TransactionCode, TransactionFlags,
+};
+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::{
+ ExceptionCode, Interface, ProcessState, SpIBinder, Status, StatusCode,
+ };
+
+ /// 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
new file mode 100644
index 0000000..798fed8
--- /dev/null
+++ b/libs/binder/rust/src/native.rs
@@ -0,0 +1,358 @@
+/*
+ * 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, 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;
+use std::ptr;
+
+/// 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,
+}
+
+impl<T: Remotable> Binder<T> {
+ /// Create a new Binder remotable object.
+ ///
+ /// This moves the `rust_object` into an owned [`Box`] and Binder will
+ /// manage its lifetime.
+ pub fn new(rust_object: T) -> 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)
+ };
+ Binder {
+ ibinder,
+ rust_object,
+ }
+ }
+
+ /// 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()
+ }
+}
+
+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) {
+ ptr::drop_in_place(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
new file mode 100644
index 0000000..43850fe
--- /dev/null
+++ b/libs/binder/rust/src/parcel.rs
@@ -0,0 +1,447 @@
+/*
+ * 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::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 {
+ /// 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)
+ }
+ }
+
+ /// 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))
+ }
+}
+
+// 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;
+ use std::ffi::CString;
+
+ 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<CString>>(), 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(&["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]);
+}
diff --git a/libs/binder/rust/src/parcel/file_descriptor.rs b/libs/binder/rust/src/parcel/file_descriptor.rs
new file mode 100644
index 0000000..8a89ab0
--- /dev/null
+++ b/libs/binder/rust/src/parcel/file_descriptor.rs
@@ -0,0 +1,126 @@
+/*
+ * 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
+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
new file mode 100644
index 0000000..78b3d2c
--- /dev/null
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -0,0 +1,922 @@
+/*
+ * 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};
+use crate::error::{status_result, Result, Status, StatusCode};
+use crate::parcel::Parcel;
+use crate::proxy::SpIBinder;
+use crate::sys;
+
+use std::convert::TryInto;
+use std::ffi::{c_void, CStr, CString};
+use std::ptr;
+
+/// 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<()> {
+ parcel.write_slice_size(Some(slice))?;
+
+ for item in slice {
+ parcel.write(item)?;
+ }
+
+ Ok(())
+ }
+}
+
+/// 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 len: i32 = parcel.read()?;
+ if len < 0 {
+ return Ok(None);
+ }
+
+ // TODO: Assumes that usize is at least 32 bits
+ let mut vec = Vec::with_capacity(len as usize);
+
+ for _ in 0..len {
+ vec.push(parcel.read()?);
+ }
+
+ Ok(Some(vec))
+ }
+}
+
+/// 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.
+///
+/// # Safety
+///
+/// The opaque data pointer passed to the array read function must be a mutable
+/// pointer to an `Option<Vec<T>>`. `buffer` will be assigned a mutable pointer
+/// to the allocated vector data if this function returns true.
+unsafe extern "C" fn allocate_vec<T: Clone + Default>(
+ data: *mut c_void,
+ len: i32,
+ buffer: *mut *mut T,
+) -> bool {
+ let vec = &mut *(data as *mut Option<Vec<T>>);
+ if len < 0 {
+ *vec = None;
+ return true;
+ }
+ let mut new_vec: Vec<T> = Vec::with_capacity(len as usize);
+ new_vec.resize_with(len as usize, Default::default);
+ *buffer = new_vec.as_mut_ptr();
+ *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<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<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),
+ )
+ };
+ status_result(status)?;
+ 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 CStr {
+ 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
+ // null-terminated C string pointer with no nulls in the middle
+ // of the string. Rust guarantees exactly that for a valid CStr
+ // instance.
+ status_result(sys::AParcel_writeString(
+ parcel.as_native_mut(),
+ s.as_ptr(),
+ s.to_bytes()
+ .len()
+ .try_into()
+ .or(Err(StatusCode::BAD_VALUE))?,
+ ))
+ },
+ }
+ }
+}
+
+impl SerializeArray for Option<&CStr> {}
+
+impl Serialize for CStr {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ Some(self).serialize(parcel)
+ }
+}
+
+impl Serialize for CString {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ Some(self.as_c_str()).serialize(parcel)
+ }
+}
+
+impl SerializeArray for CString {}
+
+impl SerializeOption for CString {
+ fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+ SerializeOption::serialize_option(this.map(CString::as_c_str), parcel)
+ }
+}
+
+impl SerializeArray for Option<CString> {}
+
+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<CString> {
+ 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),
+ )
+ };
+
+ status_result(status)?;
+ vec.map(|mut s| {
+ // The vector includes a null-terminator and CString::new requires
+ // no nulls, including terminating.
+ s.pop();
+ CString::new(s).or(Err(StatusCode::BAD_VALUE))
+ })
+ .transpose()
+ }
+}
+
+impl DeserializeArray for Option<CString> {}
+
+impl DeserializeOption for String {
+ fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
+ let c_str = <Option<CString>>::deserialize(parcel)?;
+ c_str
+ .map(|s| s.into_string().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 SerializeOption for str {
+ fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+ match this {
+ None => parcel.write(&-1i32),
+ Some(s) => {
+ let c_str = CString::new(s).or(Err(StatusCode::BAD_VALUE))?;
+ parcel.write(&c_str)
+ }
+ }
+ }
+}
+
+impl Serialize for str {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ Some(self).serialize(parcel)
+ }
+}
+
+impl SerializeArray for &str {}
+
+impl SerializeArray for Option<&str> {}
+
+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 + ?Sized> Serialize for Box<T> {
+ fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+ Serialize::serialize(&**self, parcel)
+ }
+}
+
+impl<T: SerializeOption + ?Sized> SerializeOption for Box<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 Box<T> {
+ fn deserialize(parcel: &Parcel) -> Result<Self> {
+ let ibinder: SpIBinder = parcel.read()?;
+ FromIBinder::try_from(ibinder)
+ }
+}
+
+impl<T: FromIBinder + ?Sized> DeserializeOption for Box<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 strs = [s1, s2, s3];
+
+ 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
new file mode 100644
index 0000000..f9519b4
--- /dev/null
+++ b/libs/binder/rust/src/proxy.rs
@@ -0,0 +1,512 @@
+/*
+ * 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, Interface, InterfaceClass, TransactionCode, TransactionFlags,
+};
+use crate::error::{status_result, Result, StatusCode};
+use crate::parcel::{
+ Deserialize, DeserializeArray, DeserializeOption, Parcel, Serialize, SerializeArray,
+ SerializeOption,
+};
+use crate::sys;
+
+use std::convert::TryInto;
+use std::ffi::{c_void, CString};
+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);
+
+/// # 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))
+ }
+
+ /// 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 + ?Sized>(self) -> Result<Box<I>> {
+ FromIBinder::try_from(self)
+ }
+
+ /// Return the interface class of this binder object, if associated with
+ /// one.
+ pub(crate) 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))
+ }
+ }
+}
+
+/// 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 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>> IBinder 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 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)
+ }
+
+ 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_DeatRecipient`. 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_DeatRecipient`. 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()
+ }
+}
+
+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 C++ `wp<IBinder>` class. However, this wrapper
+/// is untyped, so properly typed versions implementing a particular binder
+/// interface should be crated with [`declare_binder_interface!`].
+pub struct WpIBinder(*mut sys::AIBinder_Weak);
+
+impl WpIBinder {
+ /// Create a new weak reference from an object that can be converted into a
+ /// raw `AIBinder` pointer.
+ pub 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)
+ }
+}
+
+/// 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<Box<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
new file mode 100644
index 0000000..992f074
--- /dev/null
+++ b/libs/binder/rust/src/state.rs
@@ -0,0 +1,101 @@
+/*
+ * 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()
+ }
+ }
+}