summaryrefslogtreecommitdiff
path: root/libs/binder/rust/src/binder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'libs/binder/rust/src/binder.rs')
-rw-r--r--libs/binder/rust/src/binder.rs910
1 files changed, 910 insertions, 0 deletions
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
new file mode 100644
index 0000000000..695a83e414
--- /dev/null
+++ b/libs/binder/rust/src/binder.rs
@@ -0,0 +1,910 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//! Trait definitions for binder objects
+
+use crate::error::{status_t, Result, StatusCode};
+use crate::parcel::Parcel;
+use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder};
+use crate::sys;
+
+use std::borrow::Borrow;
+use std::cmp::Ordering;
+use std::ffi::{c_void, CStr, CString};
+use std::fmt;
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::os::raw::c_char;
+use std::os::unix::io::AsRawFd;
+use std::ptr;
+
+/// Binder action to perform.
+///
+/// This must be a number between [`FIRST_CALL_TRANSACTION`] and
+/// [`LAST_CALL_TRANSACTION`].
+pub type TransactionCode = u32;
+
+/// Additional operation flags.
+///
+/// `FLAG_*` values.
+pub type TransactionFlags = u32;
+
+/// Super-trait for Binder interfaces.
+///
+/// This trait allows conversion of a Binder interface trait object into an
+/// IBinder object for IPC calls. All Binder remotable interface (i.e. AIDL
+/// interfaces) must implement this trait.
+///
+/// This is equivalent `IInterface` in C++.
+pub trait Interface: Send {
+ /// Convert this binder object into a generic [`SpIBinder`] reference.
+ fn as_binder(&self) -> SpIBinder {
+ panic!("This object was not a Binder object and cannot be converted into an SpIBinder.")
+ }
+}
+
+/// Interface stability promise
+///
+/// An interface can promise to be a stable vendor interface ([`Vintf`]), or
+/// makes no stability guarantees ([`Local`]). [`Local`] is
+/// currently the default stability.
+pub enum Stability {
+ /// Default stability, visible to other modules in the same compilation
+ /// context (e.g. modules on system.img)
+ Local,
+
+ /// A Vendor Interface Object, which promises to be stable
+ Vintf,
+}
+
+impl Default for Stability {
+ fn default() -> Self {
+ Stability::Local
+ }
+}
+
+/// A local service that can be remotable via Binder.
+///
+/// An object that implement this interface made be made into a Binder service
+/// via `Binder::new(object)`.
+///
+/// This is a low-level interface that should normally be automatically
+/// generated from AIDL via the [`declare_binder_interface!`] macro. When using
+/// the AIDL backend, users need only implement the high-level AIDL-defined
+/// interface. The AIDL compiler then generates a container struct that wraps
+/// the user-defined service and implements `Remotable`.
+pub trait Remotable: Send + Sync {
+ /// The Binder interface descriptor string.
+ ///
+ /// This string is a unique identifier for a Binder interface, and should be
+ /// the same between all implementations of that interface.
+ fn get_descriptor() -> &'static str;
+
+ /// Handle and reply to a request to invoke a transaction on this object.
+ ///
+ /// `reply` may be [`None`] if the sender does not expect a reply.
+ fn on_transact(&self, code: TransactionCode, data: &Parcel, reply: &mut Parcel) -> Result<()>;
+
+ /// Retrieve the class of this remote object.
+ ///
+ /// This method should always return the same InterfaceClass for the same
+ /// type.
+ fn get_class() -> InterfaceClass;
+}
+
+/// First transaction code available for user commands (inclusive)
+pub const FIRST_CALL_TRANSACTION: TransactionCode = sys::FIRST_CALL_TRANSACTION;
+/// Last transaction code available for user commands (inclusive)
+pub const LAST_CALL_TRANSACTION: TransactionCode = sys::LAST_CALL_TRANSACTION;
+
+/// Corresponds to TF_ONE_WAY -- an asynchronous call.
+pub const FLAG_ONEWAY: TransactionFlags = sys::FLAG_ONEWAY;
+/// Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call is made.
+pub const FLAG_CLEAR_BUF: TransactionFlags = sys::FLAG_CLEAR_BUF;
+/// Set to the vendor flag if we are building for the VNDK, 0 otherwise
+pub const FLAG_PRIVATE_LOCAL: TransactionFlags = sys::FLAG_PRIVATE_LOCAL;
+
+/// Internal interface of binder local or remote objects for making
+/// transactions.
+///
+/// This trait corresponds to the parts of the interface of the C++ `IBinder`
+/// class which are internal implementation details.
+pub trait IBinderInternal: IBinder {
+ /// Is this object still alive?
+ fn is_binder_alive(&self) -> bool;
+
+ /// Send a ping transaction to this object
+ fn ping_binder(&mut self) -> Result<()>;
+
+ /// Indicate that the service intends to receive caller security contexts.
+ fn set_requesting_sid(&mut self, enable: bool);
+
+ /// Dump this object to the given file handle
+ fn dump<F: AsRawFd>(&mut self, fp: &F, args: &[&str]) -> Result<()>;
+
+ /// Get a new interface that exposes additional extension functionality, if
+ /// available.
+ fn get_extension(&mut self) -> Result<Option<SpIBinder>>;
+
+ /// Perform a generic operation with the object.
+ ///
+ /// # Arguments
+ /// * `code` - Transaction code for the operation
+ /// * `data` - [`Parcel`] with input data
+ /// * `reply` - Optional [`Parcel`] for reply data
+ /// * `flags` - Transaction flags, e.g. marking the transaction as
+ /// asynchronous ([`FLAG_ONEWAY`](FLAG_ONEWAY))
+ fn transact<F: FnOnce(&mut Parcel) -> Result<()>>(
+ &self,
+ code: TransactionCode,
+ flags: TransactionFlags,
+ input_callback: F,
+ ) -> Result<Parcel>;
+}
+
+/// Interface of binder local or remote objects.
+///
+/// This trait corresponds to the parts of the interface of the C++ `IBinder`
+/// class which are public.
+pub trait IBinder {
+ /// Register the recipient for a notification if this binder
+ /// goes away. If this binder object unexpectedly goes away
+ /// (typically because its hosting process has been killed),
+ /// then the `DeathRecipient`'s callback will be called.
+ ///
+ /// You will only receive death notifications for remote binders,
+ /// as local binders by definition can't die without you dying as well.
+ /// Trying to use this function on a local binder will result in an
+ /// INVALID_OPERATION code being returned and nothing happening.
+ ///
+ /// This link always holds a weak reference to its recipient.
+ fn link_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()>;
+
+ /// Remove a previously registered death notification.
+ /// The recipient will no longer be called if this object
+ /// dies.
+ fn unlink_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()>;
+}
+
+/// Opaque reference to the type of a Binder interface.
+///
+/// This object encapsulates the Binder interface descriptor string, along with
+/// the binder transaction callback, if the class describes a local service.
+///
+/// A Binder remotable object may only have a single interface class, and any
+/// given object can only be associated with one class. Two objects with
+/// different classes are incompatible, even if both classes have the same
+/// interface descriptor.
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub struct InterfaceClass(*const sys::AIBinder_Class);
+
+impl InterfaceClass {
+ /// Get a Binder NDK `AIBinder_Class` pointer for this object type.
+ ///
+ /// Note: the returned pointer will not be constant. Calling this method
+ /// multiple times for the same type will result in distinct class
+ /// pointers. A static getter for this value is implemented in
+ /// [`declare_binder_interface!`].
+ pub fn new<I: InterfaceClassMethods>() -> InterfaceClass {
+ let descriptor = CString::new(I::get_descriptor()).unwrap();
+ let ptr = unsafe {
+ // Safety: `AIBinder_Class_define` expects a valid C string, and
+ // three valid callback functions, all non-null pointers. The C
+ // string is copied and need not be valid for longer than the call,
+ // so we can drop it after the call. We can safely assign null to
+ // the onDump and handleShellCommand callbacks as long as the class
+ // pointer was non-null. Rust None for a Option<fn> is guaranteed to
+ // be a NULL pointer. Rust retains ownership of the pointer after it
+ // is defined.
+ let class = sys::AIBinder_Class_define(
+ descriptor.as_ptr(),
+ Some(I::on_create),
+ Some(I::on_destroy),
+ Some(I::on_transact),
+ );
+ if class.is_null() {
+ panic!("Expected non-null class pointer from AIBinder_Class_define!");
+ }
+ sys::AIBinder_Class_setOnDump(class, None);
+ sys::AIBinder_Class_setHandleShellCommand(class, None);
+ class
+ };
+ InterfaceClass(ptr)
+ }
+
+ /// Construct an `InterfaceClass` out of a raw, non-null `AIBinder_Class`
+ /// pointer.
+ ///
+ /// # Safety
+ ///
+ /// This function is safe iff `ptr` is a valid, non-null pointer to an
+ /// `AIBinder_Class`.
+ pub(crate) unsafe fn from_ptr(ptr: *const sys::AIBinder_Class) -> InterfaceClass {
+ InterfaceClass(ptr)
+ }
+
+ /// Get the interface descriptor string of this class.
+ pub fn get_descriptor(&self) -> String {
+ unsafe {
+ // SAFETY: The descriptor returned by AIBinder_Class_getDescriptor
+ // is always a two-byte null terminated sequence of u16s. Thus, we
+ // can continue reading from the pointer until we hit a null value,
+ // and this pointer can be a valid slice if the slice length is <=
+ // the number of u16 elements before the null terminator.
+
+ let raw_descriptor: *const c_char = sys::AIBinder_Class_getDescriptor(self.0);
+ CStr::from_ptr(raw_descriptor)
+ .to_str()
+ .expect("Expected valid UTF-8 string from AIBinder_Class_getDescriptor")
+ .into()
+ }
+ }
+}
+
+impl From<InterfaceClass> for *const sys::AIBinder_Class {
+ fn from(class: InterfaceClass) -> *const sys::AIBinder_Class {
+ class.0
+ }
+}
+
+/// Strong reference to a binder object
+pub struct Strong<I: FromIBinder + ?Sized>(Box<I>);
+
+impl<I: FromIBinder + ?Sized> Strong<I> {
+ /// Create a new strong reference to the provided binder object
+ pub fn new(binder: Box<I>) -> Self {
+ Self(binder)
+ }
+
+ /// Construct a new weak reference to this binder
+ pub fn downgrade(this: &Strong<I>) -> Weak<I> {
+ Weak::new(this)
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Clone for Strong<I> {
+ fn clone(&self) -> Self {
+ // Since we hold a strong reference, we should always be able to create
+ // a new strong reference to the same interface type, so try_from()
+ // should never fail here.
+ FromIBinder::try_from(self.0.as_binder()).unwrap()
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Borrow<I> for Strong<I> {
+ fn borrow(&self) -> &I {
+ &self.0
+ }
+}
+
+impl<I: FromIBinder + ?Sized> AsRef<I> for Strong<I> {
+ fn as_ref(&self) -> &I {
+ &self.0
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Deref for Strong<I> {
+ type Target = I;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl<I: FromIBinder + fmt::Debug + ?Sized> fmt::Debug for Strong<I> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Debug::fmt(&**self, f)
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Ord for Strong<I> {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.0.as_binder().cmp(&other.0.as_binder())
+ }
+}
+
+impl<I: FromIBinder + ?Sized> PartialOrd for Strong<I> {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.0.as_binder().partial_cmp(&other.0.as_binder())
+ }
+}
+
+impl<I: FromIBinder + ?Sized> PartialEq for Strong<I> {
+ fn eq(&self, other: &Self) -> bool {
+ self.0.as_binder().eq(&other.0.as_binder())
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Eq for Strong<I> {}
+
+/// Weak reference to a binder object
+#[derive(Debug)]
+pub struct Weak<I: FromIBinder + ?Sized> {
+ weak_binder: WpIBinder,
+ interface_type: PhantomData<I>,
+}
+
+impl<I: FromIBinder + ?Sized> Weak<I> {
+ /// Construct a new weak reference from a strong reference
+ fn new(binder: &Strong<I>) -> Self {
+ let weak_binder = binder.as_binder().downgrade();
+ Weak {
+ weak_binder,
+ interface_type: PhantomData,
+ }
+ }
+
+ /// Upgrade this weak reference to a strong reference if the binder object
+ /// is still alive
+ pub fn upgrade(&self) -> Result<Strong<I>> {
+ self.weak_binder
+ .promote()
+ .ok_or(StatusCode::DEAD_OBJECT)
+ .and_then(FromIBinder::try_from)
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Clone for Weak<I> {
+ fn clone(&self) -> Self {
+ Self {
+ weak_binder: self.weak_binder.clone(),
+ interface_type: PhantomData,
+ }
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Ord for Weak<I> {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.weak_binder.cmp(&other.weak_binder)
+ }
+}
+
+impl<I: FromIBinder + ?Sized> PartialOrd for Weak<I> {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ self.weak_binder.partial_cmp(&other.weak_binder)
+ }
+}
+
+impl<I: FromIBinder + ?Sized> PartialEq for Weak<I> {
+ fn eq(&self, other: &Self) -> bool {
+ self.weak_binder == other.weak_binder
+ }
+}
+
+impl<I: FromIBinder + ?Sized> Eq for Weak<I> {}
+
+/// Create a function implementing a static getter for an interface class.
+///
+/// Each binder interface (i.e. local [`Remotable`] service or remote proxy
+/// [`Interface`]) must have global, static class that uniquely identifies
+/// it. This macro implements an [`InterfaceClass`] getter to simplify these
+/// implementations.
+///
+/// The type of a structure that implements [`InterfaceClassMethods`] must be
+/// passed to this macro. For local services, this should be `Binder<Self>`
+/// since [`Binder`] implements [`InterfaceClassMethods`].
+///
+/// # Examples
+///
+/// When implementing a local [`Remotable`] service `ExampleService`, the
+/// `get_class` method is required in the [`Remotable`] impl block. This macro
+/// should be used as follows to implement this functionality:
+///
+/// ```rust
+/// impl Remotable for ExampleService {
+/// fn get_descriptor() -> &'static str {
+/// "android.os.IExampleInterface"
+/// }
+///
+/// fn on_transact(
+/// &self,
+/// code: TransactionCode,
+/// data: &Parcel,
+/// reply: &mut Parcel,
+/// ) -> Result<()> {
+/// // ...
+/// }
+///
+/// binder_fn_get_class!(Binder<Self>);
+/// }
+/// ```
+macro_rules! binder_fn_get_class {
+ ($class:ty) => {
+ binder_fn_get_class!($crate::InterfaceClass::new::<$class>());
+ };
+
+ ($constructor:expr) => {
+ fn get_class() -> $crate::InterfaceClass {
+ static CLASS_INIT: std::sync::Once = std::sync::Once::new();
+ static mut CLASS: Option<$crate::InterfaceClass> = None;
+
+ CLASS_INIT.call_once(|| unsafe {
+ // Safety: This assignment is guarded by the `CLASS_INIT` `Once`
+ // variable, and therefore is thread-safe, as it can only occur
+ // once.
+ CLASS = Some($constructor);
+ });
+ unsafe {
+ // Safety: The `CLASS` variable can only be mutated once, above,
+ // and is subsequently safe to read from any thread.
+ CLASS.unwrap()
+ }
+ }
+ };
+}
+
+pub trait InterfaceClassMethods {
+ /// Get the interface descriptor string for this object type.
+ fn get_descriptor() -> &'static str
+ where
+ Self: Sized;
+
+ /// Called during construction of a new `AIBinder` object of this interface
+ /// class.
+ ///
+ /// The opaque pointer parameter will be the parameter provided to
+ /// `AIBinder_new`. Returns an opaque userdata to be associated with the new
+ /// `AIBinder` object.
+ ///
+ /// # Safety
+ ///
+ /// Callback called from C++. The parameter argument provided to
+ /// `AIBinder_new` must match the type expected here. The `AIBinder` object
+ /// will take ownership of the returned pointer, which it will free via
+ /// `on_destroy`.
+ unsafe extern "C" fn on_create(args: *mut c_void) -> *mut c_void;
+
+ /// Called when a transaction needs to be processed by the local service
+ /// implementation.
+ ///
+ /// # Safety
+ ///
+ /// Callback called from C++. The `binder` parameter must be a valid pointer
+ /// to a binder object of this class with userdata initialized via this
+ /// class's `on_create`. The parcel parameters must be valid pointers to
+ /// parcel objects.
+ unsafe extern "C" fn on_transact(
+ binder: *mut sys::AIBinder,
+ code: u32,
+ data: *const sys::AParcel,
+ reply: *mut sys::AParcel,
+ ) -> status_t;
+
+ /// Called whenever an `AIBinder` object is no longer referenced and needs
+ /// to be destroyed.
+ ///
+ /// # Safety
+ ///
+ /// Callback called from C++. The opaque pointer parameter must be the value
+ /// returned by `on_create` for this class. This function takes ownership of
+ /// the provided pointer and destroys it.
+ unsafe extern "C" fn on_destroy(object: *mut c_void);
+}
+
+/// Interface for transforming a generic SpIBinder into a specific remote
+/// interface trait.
+///
+/// # Example
+///
+/// For Binder interface `IFoo`, the following implementation should be made:
+/// ```no_run
+/// # use binder::{FromIBinder, SpIBinder, Result};
+/// # trait IFoo {}
+/// impl FromIBinder for dyn IFoo {
+/// fn try_from(ibinder: SpIBinder) -> Result<Box<Self>> {
+/// // ...
+/// # Err(binder::StatusCode::OK)
+/// }
+/// }
+/// ```
+pub trait FromIBinder: Interface {
+ /// Try to interpret a generic Binder object as this interface.
+ ///
+ /// Returns a trait object for the `Self` interface if this object
+ /// implements that interface.
+ fn try_from(ibinder: SpIBinder) -> Result<Strong<Self>>;
+}
+
+/// Trait for transparent Rust wrappers around android C++ native types.
+///
+/// The pointer return by this trait's methods should be immediately passed to
+/// C++ and not stored by Rust. The pointer is valid only as long as the
+/// underlying C++ object is alive, so users must be careful to take this into
+/// account, as Rust cannot enforce this.
+///
+/// # Safety
+///
+/// For this trait to be a correct implementation, `T` must be a valid android
+/// C++ type. Since we cannot constrain this via the type system, this trait is
+/// marked as unsafe.
+pub unsafe trait AsNative<T> {
+ /// Return a pointer to the native version of `self`
+ fn as_native(&self) -> *const T;
+
+ /// Return a mutable pointer to the native version of `self`
+ fn as_native_mut(&mut self) -> *mut T;
+}
+
+unsafe impl<T, V: AsNative<T>> AsNative<T> for Option<V> {
+ fn as_native(&self) -> *const T {
+ self.as_ref().map_or(ptr::null(), |v| v.as_native())
+ }
+
+ fn as_native_mut(&mut self) -> *mut T {
+ self.as_mut().map_or(ptr::null_mut(), |v| v.as_native_mut())
+ }
+}
+
+/// The features to enable when creating a native Binder.
+///
+/// This should always be initialised with a default value, e.g.:
+/// ```
+/// # use binder::BinderFeatures;
+/// BinderFeatures {
+/// set_requesting_sid: true,
+/// ..BinderFeatures::default(),
+/// }
+/// ```
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+pub struct BinderFeatures {
+ /// Indicates that the service intends to receive caller security contexts. This must be true
+ /// for `ThreadState::with_calling_sid` to work.
+ pub set_requesting_sid: bool,
+ // Ensure that clients include a ..BinderFeatures::default() to preserve backwards compatibility
+ // when new fields are added. #[non_exhaustive] doesn't work because it prevents struct
+ // expressions entirely.
+ #[doc(hidden)]
+ pub _non_exhaustive: (),
+}
+
+/// Declare typed interfaces for a binder object.
+///
+/// Given an interface trait and descriptor string, create a native and remote
+/// proxy wrapper for this interface. The native service object (`$native`)
+/// implements `Remotable` and will dispatch to the function `$on_transact` to
+/// handle transactions. The typed proxy object (`$proxy`) wraps remote binder
+/// objects for this interface and can optionally contain additional fields.
+///
+/// Assuming the interface trait is `Interface`, `$on_transact` function must
+/// have the following type:
+///
+/// ```
+/// # use binder::{Interface, TransactionCode, Parcel};
+/// # trait Placeholder {
+/// fn on_transact(
+/// service: &dyn Interface,
+/// code: TransactionCode,
+/// data: &Parcel,
+/// reply: &mut Parcel,
+/// ) -> binder::Result<()>;
+/// # }
+/// ```
+///
+/// # Examples
+///
+/// The following example declares the local service type `BnServiceManager` and
+/// a remote proxy type `BpServiceManager` (the `n` and `p` stand for native and
+/// proxy respectively) for the `IServiceManager` Binder interface. The
+/// interfaces will be identified by the descriptor string
+/// "android.os.IServiceManager". The local service will dispatch transactions
+/// using the provided function, `on_transact`.
+///
+/// ```
+/// use binder::{declare_binder_interface, Binder, Interface, TransactionCode, Parcel};
+///
+/// pub trait IServiceManager: Interface {
+/// // remote methods...
+/// }
+///
+/// declare_binder_interface! {
+/// IServiceManager["android.os.IServiceManager"] {
+/// native: BnServiceManager(on_transact),
+/// proxy: BpServiceManager,
+/// }
+/// }
+///
+/// fn on_transact(
+/// service: &dyn IServiceManager,
+/// code: TransactionCode,
+/// data: &Parcel,
+/// reply: &mut Parcel,
+/// ) -> binder::Result<()> {
+/// // ...
+/// Ok(())
+/// }
+///
+/// impl IServiceManager for BpServiceManager {
+/// // parceling/unparceling code for the IServiceManager emitted here
+/// }
+///
+/// impl IServiceManager for Binder<BnServiceManager> {
+/// // Forward calls to local implementation
+/// }
+/// ```
+#[macro_export]
+macro_rules! declare_binder_interface {
+ {
+ $interface:path[$descriptor:expr] {
+ native: $native:ident($on_transact:path),
+ proxy: $proxy:ident,
+ }
+ } => {
+ $crate::declare_binder_interface! {
+ $interface[$descriptor] {
+ native: $native($on_transact),
+ proxy: $proxy {},
+ stability: $crate::Stability::default(),
+ }
+ }
+ };
+
+ {
+ $interface:path[$descriptor:expr] {
+ native: $native:ident($on_transact:path),
+ proxy: $proxy:ident,
+ stability: $stability:expr,
+ }
+ } => {
+ $crate::declare_binder_interface! {
+ $interface[$descriptor] {
+ native: $native($on_transact),
+ proxy: $proxy {},
+ stability: $stability,
+ }
+ }
+ };
+
+ {
+ $interface:path[$descriptor:expr] {
+ native: $native:ident($on_transact:path),
+ proxy: $proxy:ident {
+ $($fname:ident: $fty:ty = $finit:expr),*
+ },
+ }
+ } => {
+ $crate::declare_binder_interface! {
+ $interface[$descriptor] {
+ native: $native($on_transact),
+ proxy: $proxy {
+ $($fname: $fty = $finit),*
+ },
+ stability: $crate::Stability::default(),
+ }
+ }
+ };
+
+ {
+ $interface:path[$descriptor:expr] {
+ native: $native:ident($on_transact:path),
+ proxy: $proxy:ident {
+ $($fname:ident: $fty:ty = $finit:expr),*
+ },
+ stability: $stability:expr,
+ }
+ } => {
+ $crate::declare_binder_interface! {
+ $interface[$descriptor] {
+ @doc[concat!("A binder [`Remotable`]($crate::Remotable) that holds an [`", stringify!($interface), "`] object.")]
+ native: $native($on_transact),
+ @doc[concat!("A binder [`Proxy`]($crate::Proxy) that holds an [`", stringify!($interface), "`] remote interface.")]
+ proxy: $proxy {
+ $($fname: $fty = $finit),*
+ },
+ stability: $stability,
+ }
+ }
+ };
+
+ {
+ $interface:path[$descriptor:expr] {
+ @doc[$native_doc:expr]
+ native: $native:ident($on_transact:path),
+
+ @doc[$proxy_doc:expr]
+ proxy: $proxy:ident {
+ $($fname:ident: $fty:ty = $finit:expr),*
+ },
+
+ stability: $stability:expr,
+ }
+ } => {
+ #[doc = $proxy_doc]
+ pub struct $proxy {
+ binder: $crate::SpIBinder,
+ $($fname: $fty,)*
+ }
+
+ impl $crate::Interface for $proxy {
+ fn as_binder(&self) -> $crate::SpIBinder {
+ self.binder.clone()
+ }
+ }
+
+ impl $crate::Proxy for $proxy
+ where
+ $proxy: $interface,
+ {
+ fn get_descriptor() -> &'static str {
+ $descriptor
+ }
+
+ fn from_binder(mut binder: $crate::SpIBinder) -> $crate::Result<Self> {
+ Ok(Self { binder, $($fname: $finit),* })
+ }
+ }
+
+ #[doc = $native_doc]
+ #[repr(transparent)]
+ pub struct $native(Box<dyn $interface + Sync + Send + 'static>);
+
+ impl $native {
+ /// Create a new binder service.
+ pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T, features: $crate::BinderFeatures) -> $crate::Strong<dyn $interface> {
+ let mut binder = $crate::Binder::new_with_stability($native(Box::new(inner)), $stability);
+ $crate::IBinderInternal::set_requesting_sid(&mut binder, features.set_requesting_sid);
+ $crate::Strong::new(Box::new(binder))
+ }
+ }
+
+ impl $crate::Remotable for $native {
+ fn get_descriptor() -> &'static str {
+ $descriptor
+ }
+
+ fn on_transact(&self, code: $crate::TransactionCode, data: &$crate::Parcel, reply: &mut $crate::Parcel) -> $crate::Result<()> {
+ match $on_transact(&*self.0, code, data, reply) {
+ // The C++ backend converts UNEXPECTED_NULL into an exception
+ Err($crate::StatusCode::UNEXPECTED_NULL) => {
+ let status = $crate::Status::new_exception(
+ $crate::ExceptionCode::NULL_POINTER,
+ None,
+ );
+ reply.write(&status)
+ },
+ result => result
+ }
+ }
+
+ fn get_class() -> $crate::InterfaceClass {
+ static CLASS_INIT: std::sync::Once = std::sync::Once::new();
+ static mut CLASS: Option<$crate::InterfaceClass> = None;
+
+ CLASS_INIT.call_once(|| unsafe {
+ // Safety: This assignment is guarded by the `CLASS_INIT` `Once`
+ // variable, and therefore is thread-safe, as it can only occur
+ // once.
+ CLASS = Some($crate::InterfaceClass::new::<$crate::Binder<$native>>());
+ });
+ unsafe {
+ // Safety: The `CLASS` variable can only be mutated once, above,
+ // and is subsequently safe to read from any thread.
+ CLASS.unwrap()
+ }
+ }
+ }
+
+ impl $crate::FromIBinder for dyn $interface {
+ fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<$crate::Strong<dyn $interface>> {
+ use $crate::AssociateClass;
+
+ let existing_class = ibinder.get_class();
+ if let Some(class) = existing_class {
+ if class != <$native as $crate::Remotable>::get_class() &&
+ class.get_descriptor() == <$native as $crate::Remotable>::get_descriptor()
+ {
+ // The binder object's descriptor string matches what we
+ // expect. We still need to treat this local or already
+ // associated object as remote, because we can't cast it
+ // into a Rust service object without a matching class
+ // pointer.
+ return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)));
+ }
+ }
+
+ if ibinder.associate_class(<$native as $crate::Remotable>::get_class()) {
+ let service: $crate::Result<$crate::Binder<$native>> =
+ std::convert::TryFrom::try_from(ibinder.clone());
+ if let Ok(service) = service {
+ // We were able to associate with our expected class and
+ // the service is local.
+ return Ok($crate::Strong::new(Box::new(service)));
+ } else {
+ // Service is remote
+ return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)));
+ }
+ }
+
+ Err($crate::StatusCode::BAD_TYPE.into())
+ }
+ }
+
+ impl $crate::parcel::Serialize for dyn $interface + '_
+ where
+ dyn $interface: $crate::Interface
+ {
+ fn serialize(&self, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> {
+ let binder = $crate::Interface::as_binder(self);
+ parcel.write(&binder)
+ }
+ }
+
+ impl $crate::parcel::SerializeOption for dyn $interface + '_ {
+ fn serialize_option(this: Option<&Self>, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> {
+ parcel.write(&this.map($crate::Interface::as_binder))
+ }
+ }
+
+ impl std::fmt::Debug for dyn $interface {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.pad(stringify!($interface))
+ }
+ }
+
+ /// Convert a &dyn $interface to Strong<dyn $interface>
+ impl std::borrow::ToOwned for dyn $interface {
+ type Owned = $crate::Strong<dyn $interface>;
+ fn to_owned(&self) -> Self::Owned {
+ self.as_binder().into_interface()
+ .expect(concat!("Error cloning interface ", stringify!($interface)))
+ }
+ }
+ };
+}
+
+/// Declare an AIDL enumeration.
+///
+/// This is mainly used internally by the AIDL compiler.
+#[macro_export]
+macro_rules! declare_binder_enum {
+ {
+ $enum:ident : $backing:ty {
+ $( $name:ident = $value:expr, )*
+ }
+ } => {
+ #[derive(Debug, Default, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
+ pub struct $enum(pub $backing);
+ impl $enum {
+ $( pub const $name: Self = Self($value); )*
+ }
+
+ impl $crate::parcel::Serialize for $enum {
+ fn serialize(&self, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> {
+ parcel.write(&self.0)
+ }
+ }
+
+ impl $crate::parcel::SerializeArray for $enum {
+ fn serialize_array(slice: &[Self], parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> {
+ let v: Vec<$backing> = slice.iter().map(|x| x.0).collect();
+ <$backing as binder::parcel::SerializeArray>::serialize_array(&v[..], parcel)
+ }
+ }
+
+ impl $crate::parcel::Deserialize for $enum {
+ fn deserialize(parcel: &$crate::parcel::Parcel) -> $crate::Result<Self> {
+ parcel.read().map(Self)
+ }
+ }
+
+ impl $crate::parcel::DeserializeArray for $enum {
+ fn deserialize_array(parcel: &$crate::parcel::Parcel) -> $crate::Result<Option<Vec<Self>>> {
+ let v: Option<Vec<$backing>> =
+ <$backing as binder::parcel::DeserializeArray>::deserialize_array(parcel)?;
+ Ok(v.map(|v| v.into_iter().map(Self).collect()))
+ }
+ }
+ };
+}