use crate::error::{Result, StatusCode, status_t};
use crate::parcel::{BorrowedParcel, Parcel};
use crate::proxy::{DeathRecipient, SpIBinder, WpIBinder};
use crate::sys;
use alloc::boxed::Box;
use alloc::ffi::CString;
use alloc::string::String;
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::convert::TryFrom;
use core::ffi::{CStr, c_char, c_void};
use core::fmt;
use core::marker::PhantomData;
use core::ops::Deref;
use core::ptr;
use downcast_rs::{DowncastSync, impl_downcast};
#[cfg(all(feature = "std", not(android_ndk)))]
use std::io::Read;
#[cfg(feature = "std")]
use std::io::Write;
#[cfg(feature = "std")]
use std::os::fd::AsRawFd;
#[cfg(feature = "android_ndk_compat_symbols")]
use binder_rs_ndk_compat::set_transaction_code_to_function_name_map;
pub type TransactionCode = u32;
pub type TransactionFlags = u32;
pub trait Interface: Send + Sync + DowncastSync {
fn as_binder(&self) -> SpIBinder {
panic!("This object was not a Binder object and cannot be converted into an SpIBinder.")
}
#[cfg(feature = "std")]
fn dump(&self, _writer: &mut dyn Write, _args: &[&CStr]) -> Result<()> {
Ok(())
}
#[cfg(all(feature = "std", not(android_ndk)))]
fn shell_command(
&self,
_stdin: &mut dyn Read,
_stdout: &mut dyn Write,
_stderr: &mut dyn Write,
_args: &[&CStr],
) -> Result<()> {
Ok(())
}
}
impl_downcast!(sync Interface);
pub trait ToAsyncInterface<P>
where
Self: Interface,
Self::Target: FromIBinder,
{
type Target: ?Sized;
}
pub trait ToSyncInterface
where
Self: Interface,
Self::Target: FromIBinder,
{
type Target: ?Sized;
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Default)]
pub enum Stability {
#[default]
Local,
Vintf,
}
impl From<Stability> for i32 {
fn from(stability: Stability) -> i32 {
use Stability::*;
match stability {
Local => 0,
Vintf => 1,
}
}
}
impl TryFrom<i32> for Stability {
type Error = StatusCode;
fn try_from(stability: i32) -> Result<Stability> {
use Stability::*;
match stability {
0 => Ok(Local),
1 => Ok(Vintf),
_ => Err(StatusCode::BAD_VALUE),
}
}
}
pub trait StabilityType {
const VALUE: Stability;
}
#[derive(Debug)]
pub enum LocalStabilityType {}
#[derive(Debug)]
pub enum VintfStabilityType {}
impl StabilityType for LocalStabilityType {
const VALUE: Stability = Stability::Local;
}
impl StabilityType for VintfStabilityType {
const VALUE: Stability = Stability::Vintf;
}
pub trait Remotable: Send + Sync + 'static {
fn get_descriptor() -> &'static str;
fn on_transact(
&self,
code: TransactionCode,
data: &BorrowedParcel<'_>,
reply: &mut BorrowedParcel<'_>,
) -> Result<()>;
#[cfg(feature = "std")]
fn on_dump(&self, file: &mut dyn Write, args: &[&CStr]) -> Result<()>;
#[cfg(all(feature = "std", not(android_ndk)))]
fn on_shell_command(
&self,
stdin: &mut dyn Read,
stdout: &mut dyn Write,
stderr: &mut dyn Write,
args: &[&CStr],
) -> Result<()>;
fn get_class() -> InterfaceClass;
}
#[allow(dead_code)]
pub struct FunctionNames<const LEN: usize> {
pub(crate) arr: [*const core::ffi::c_char; LEN],
}
unsafe impl<const LEN: usize> Sync for FunctionNames<LEN> {}
impl<const LEN: usize> FunctionNames<LEN> {
pub const fn new(strs: [&'static core::ffi::CStr; LEN]) -> Self {
let mut arr = [core::ptr::null(); LEN];
let mut i = 0;
while i < LEN {
arr[i] = strs[i].as_ptr();
i += 1;
}
Self { arr }
}
pub const fn len(&self) -> usize {
LEN
}
pub const fn is_empty(&self) -> bool {
LEN == 0
}
}
pub const FIRST_CALL_TRANSACTION: TransactionCode = sys::FIRST_CALL_TRANSACTION;
pub const LAST_CALL_TRANSACTION: TransactionCode = sys::LAST_CALL_TRANSACTION;
pub const FLAG_ONEWAY: TransactionFlags = sys::FLAG_ONEWAY;
#[cfg(not(android_ndk))]
pub const FLAG_CLEAR_BUF: TransactionFlags = sys::FLAG_CLEAR_BUF;
#[cfg(not(android_ndk))]
pub const FLAG_PRIVATE_LOCAL: TransactionFlags = sys::FLAG_PRIVATE_LOCAL;
pub trait IBinderInternal: IBinder {
fn is_binder_alive(&self) -> bool;
#[cfg(not(any(android_vndk, android_ndk)))]
fn set_requesting_sid(&mut self, enable: bool);
#[cfg(not(android_ndk))]
fn set_inherit_rt(&mut self, enable: bool);
#[cfg(feature = "std")]
fn dump<F: AsRawFd>(&mut self, fp: &F, args: &[&str]) -> Result<()>;
fn get_extension(&mut self) -> Result<Option<SpIBinder>>;
fn prepare_transact(&self) -> Result<Parcel>;
fn submit_transact(
&self,
code: TransactionCode,
data: Parcel,
flags: TransactionFlags,
) -> Result<Parcel>;
fn transact<F: FnOnce(BorrowedParcel<'_>) -> Result<()>>(
&self,
code: TransactionCode,
flags: TransactionFlags,
input_callback: F,
) -> Result<Parcel> {
let mut parcel = self.prepare_transact()?;
input_callback(parcel.borrowed())?;
self.submit_transact(code, parcel, flags)
}
}
pub trait IBinder {
fn link_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()>;
fn unlink_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()>;
fn ping_binder(&mut self) -> Result<()>;
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct InterfaceClass(*const sys::AIBinder_Class);
unsafe impl Send for InterfaceClass {}
unsafe impl Sync for InterfaceClass {}
impl InterfaceClass {
pub fn new<I: InterfaceClassMethods>() -> InterfaceClass {
let descriptor = CString::new(I::get_descriptor()).unwrap();
let ptr = unsafe {
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, Some(I::on_dump));
#[cfg(not(android_ndk))]
sys::AIBinder_Class_setHandleShellCommand(class, Some(I::on_shell_command));
class
};
InterfaceClass(ptr)
}
pub fn new_with_function_names<I: InterfaceClassMethods, const LEN: usize>(
_function_names: &'static FunctionNames<LEN>,
) -> InterfaceClass {
let descriptor = CString::new(I::get_descriptor()).unwrap();
let class = unsafe {
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!");
}
if LEN > 0 {
#[cfg(feature = "android_ndk_compat_symbols")]
unsafe {
set_transaction_code_to_function_name_map(class, _function_names.arr.as_ptr(), LEN);
}
}
unsafe {
sys::AIBinder_Class_setOnDump(class, Some(I::on_dump));
#[cfg(not(android_ndk))]
sys::AIBinder_Class_setHandleShellCommand(class, Some(I::on_shell_command));
}
InterfaceClass(class)
}
pub(crate) unsafe fn from_ptr(ptr: *const sys::AIBinder_Class) -> InterfaceClass {
InterfaceClass(ptr)
}
pub fn get_descriptor(&self) -> String {
unsafe {
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
}
}
pub struct Strong<I: FromIBinder + ?Sized>(Box<I>);
impl<I: FromIBinder + ?Sized> Strong<I> {
pub fn new(binder: Box<I>) -> Self {
Self(binder)
}
pub fn downgrade(this: &Strong<I>) -> Weak<I> {
Weak::new(this)
}
pub fn into_async<P>(self) -> Strong<<I as ToAsyncInterface<P>>::Target>
where
I: ToAsyncInterface<P>,
{
FromIBinder::try_from(self.0.as_binder()).unwrap()
}
pub fn into_sync(self) -> Strong<<I as ToSyncInterface>::Target>
where
I: ToSyncInterface,
{
FromIBinder::try_from(self.0.as_binder()).unwrap()
}
}
impl<I: FromIBinder + ?Sized> Clone for Strong<I> {
fn clone(&self) -> Self {
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> {
Some(self.cmp(other))
}
}
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> {}
#[derive(Debug)]
pub struct Weak<I: FromIBinder + ?Sized> {
weak_binder: WpIBinder,
interface_type: PhantomData<I>,
}
impl<I: FromIBinder + ?Sized> Weak<I> {
fn new(binder: &Strong<I>) -> Self {
let weak_binder = binder.as_binder().downgrade();
Weak { weak_binder, interface_type: PhantomData }
}
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> {
Some(self.cmp(other))
}
}
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> {}
macro_rules! binder_fn_get_class {
($class:ty) => {
binder_fn_get_class!($crate::binder_impl::InterfaceClass::new::<$class>());
};
($constructor:expr_2021) => {
fn get_class() -> $crate::binder_impl::InterfaceClass {
static CLASS_INIT: $crate::binder_impl::Once = $crate::binder_impl::Once::new();
static mut CLASS: Option<$crate::binder_impl::InterfaceClass> = None;
CLASS_INIT.call_once(|| unsafe {
CLASS = Some($constructor);
});
unsafe { CLASS.unwrap() }
}
};
}
pub trait InterfaceClassMethods {
fn get_descriptor() -> &'static str
where
Self: Sized;
unsafe extern "C" fn on_create(args: *mut c_void) -> *mut c_void;
unsafe extern "C" fn on_transact(
binder: *mut sys::AIBinder,
code: u32,
data: *const sys::AParcel,
reply: *mut sys::AParcel,
) -> status_t;
unsafe extern "C" fn on_destroy(object: *mut c_void);
unsafe extern "C" fn on_dump(
binder: *mut sys::AIBinder,
fd: i32,
args: *mut *const c_char,
num_args: u32,
) -> status_t;
#[cfg(not(android_ndk))]
unsafe extern "C" fn on_shell_command(
binder: *mut sys::AIBinder,
stdin: i32,
stdout: i32,
stderr: i32,
args: *mut *const c_char,
num_args: u32,
) -> status_t;
}
pub trait FromIBinder: Interface {
fn try_from(ibinder: SpIBinder) -> Result<Strong<Self>>;
}
pub unsafe trait AsNative<T> {
fn as_native(&self) -> *const T;
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())
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct BinderFeatures {
#[cfg(not(any(android_vndk, android_ndk)))]
pub set_requesting_sid: bool,
#[cfg(not(android_ndk))]
pub set_inherit_rt: bool,
#[doc(hidden)]
pub _non_exhaustive: (),
}
#[doc(hidden)]
#[cfg(feature = "std")]
#[macro_export]
macro_rules! on_dump_impl {
() => {
fn on_dump(
&self,
writer: &mut dyn std::io::Write,
args: &[&std::ffi::CStr],
) -> std::result::Result<(), $crate::StatusCode> {
self.0.dump(writer, args)
}
};
}
#[doc(hidden)]
#[cfg(not(feature = "std"))]
#[macro_export]
macro_rules! on_dump_impl {
() => {};
}
#[doc(hidden)]
#[cfg(all(feature = "std", not(android_ndk)))]
#[macro_export]
macro_rules! on_shell_command_impl {
() => {
fn on_shell_command(
&self,
stdin: &mut dyn std::io::Read,
stdout: &mut dyn std::io::Write,
stderr: &mut dyn std::io::Write,
args: &[&std::ffi::CStr],
) -> std::result::Result<(), $crate::StatusCode> {
self.0.shell_command(stdin, stdout, stderr, args)
}
};
}
#[doc(hidden)]
#[cfg(not(all(feature = "std", not(android_ndk))))]
#[macro_export]
macro_rules! on_shell_command_impl {
() => {};
}
#[macro_export]
macro_rules! declare_binder_interface {
{
$interface:path[$descriptor:expr_2021] {
native: $native:ident($on_transact:path),
proxy: $proxy:ident,
$(async: $async_interface:ident $(($try_into_local_async:ident))?,)?
$(functionNames: [$($fn:expr_2021),* $(,)?],)?
}
} => {
$crate::declare_binder_interface! {
$interface[$descriptor] {
native: $native($on_transact),
proxy: $proxy {},
$(async: $async_interface $(($try_into_local_async))?,)?
stability: $crate::binder_impl::Stability::default(),
$(functionNames: [$($fn),*],)?
}
}
};
{
$interface:path[$descriptor:expr_2021] {
native: $native:ident($on_transact:path),
proxy: $proxy:ident,
$(async: $async_interface:ident $(($try_into_local_async:ident))?,)?
stability: $stability:expr_2021,
$(functionNames: [$($fn:expr_2021),* $(,)?],)?
}
} => {
$crate::declare_binder_interface! {
$interface[$descriptor] {
native: $native($on_transact),
proxy: $proxy {},
$(async: $async_interface $(($try_into_local_async))?,)?
stability: $stability,
$(functionNames: [$($fn),*],)?
}
}
};
{
$interface:path[$descriptor:expr_2021] {
native: $native:ident($on_transact:path),
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr_2021),*
},
$(async: $async_interface:ident $(($try_into_local_async:ident))?,)?
$(functionNames: [$($fn:expr_2021),* $(,)?],)?
}
} => {
$crate::declare_binder_interface! {
$interface[$descriptor] {
native: $native($on_transact),
proxy: $proxy {
$($fname: $fty = $finit),*
},
$(async: $async_interface $(($try_into_local_async))?,)?
stability: $crate::binder_impl::Stability::default(),
$(functionNames: [$($fn),*],)?
}
}
};
{
$interface:path[$descriptor:expr_2021] {
native: $native:ident($on_transact:path),
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr_2021),*
},
$(async: $async_interface:ident $(($try_into_local_async:ident))?,)?
stability: $stability:expr_2021,
$(functionNames: [$($fn:expr_2021),* $(,)?],)?
}
} => {
$crate::declare_binder_interface! {
$interface[$descriptor] {
@doc[concat!("A binder [`Remotable`]($crate::binder_impl::Remotable) that holds an [`", stringify!($interface), "`] object.")]
native: $native($on_transact),
@doc[concat!("A binder [`Proxy`]($crate::binder_impl::Proxy) that holds an [`", stringify!($interface), "`] remote interface.")]
proxy: $proxy {
$($fname: $fty = $finit),*
},
$(async: $async_interface $(($try_into_local_async))?,)?
stability: $stability,
$(functionNames: [$($fn),*],)?
}
}
};
{
$interface:path[$descriptor:expr_2021] {
@doc[$native_doc:expr_2021]
native: $native:ident($on_transact:path),
@doc[$proxy_doc:expr_2021]
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr_2021),*
},
$(async: $async_interface:ident $(($try_into_local_async:ident))?,)?
stability: $stability:expr_2021,
$(functionNames: [$($fn:expr_2021),* $(,)?],)?
}
} => {
#[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::binder_impl::Proxy for $proxy
where
$proxy: $interface,
{
fn get_descriptor() -> &'static str {
$descriptor
}
fn from_binder(mut binder: $crate::SpIBinder) -> core::result::Result<Self, $crate::StatusCode> {
Ok(Self { binder, $($fname: $finit),* })
}
}
#[doc = $native_doc]
#[repr(transparent)]
pub struct $native(alloc::boxed::Box<dyn $interface + Sync + Send + 'static>);
impl $native {
pub fn new_binder<T: $interface + Sync + Send + 'static>(inner: T, features: $crate::BinderFeatures) -> $crate::Strong<dyn $interface> {
#[cfg(not(android_ndk))]
let mut binder = $crate::binder_impl::Binder::new_with_stability($native(alloc::boxed::Box::new(inner)), $stability);
#[cfg(android_ndk)]
let mut binder = $crate::binder_impl::Binder::new($native(alloc::boxed::Box::new(inner)));
#[cfg(not(any(android_vndk, android_ndk)))]
$crate::binder_impl::IBinderInternal::set_requesting_sid(&mut binder, features.set_requesting_sid);
#[cfg(not(android_ndk))]
$crate::binder_impl::IBinderInternal::set_inherit_rt(&mut binder, features.set_inherit_rt);
$crate::Strong::new(alloc::boxed::Box::new(binder))
}
pub fn downcast_binder<T: $interface>(&self) -> Option<&T> {
self.0.as_any().downcast_ref::<T>()
}
}
impl $crate::binder_impl::Remotable for $native {
fn get_descriptor() -> &'static str {
$descriptor
}
fn on_transact(&self, code: $crate::binder_impl::TransactionCode, data: &$crate::binder_impl::BorrowedParcel<'_>, reply: &mut $crate::binder_impl::BorrowedParcel<'_>) -> core::result::Result<(), $crate::StatusCode> {
match $on_transact(&*self.0, code, data, reply) {
Err($crate::StatusCode::UNEXPECTED_NULL) => {
let status = $crate::Status::new_exception(
$crate::ExceptionCode::NULL_POINTER,
None,
);
reply.write(&status)
},
result => result
}
}
$crate::on_dump_impl!();
$crate::on_shell_command_impl!();
fn get_class() -> $crate::binder_impl::InterfaceClass {
static CLASS_INIT: $crate::binder_impl::Once = $crate::binder_impl::Once::new();
static mut CLASS: Option<$crate::binder_impl::InterfaceClass> = None;
CLASS_INIT.call_once(|| {
$(
const STRS: [&'static core::ffi::CStr; {[$($fn),*].len()}] = [$($fn),*];
static FUNCTION_NAMES: $crate::binder_impl::FunctionNames<{STRS.len()}> =
$crate::binder_impl::FunctionNames::new(STRS);
unsafe {
CLASS = Some($crate::binder_impl::InterfaceClass::new_with_function_names::<
$crate::binder_impl::Binder<$native>,
{ FUNCTION_NAMES.len() },
>(&FUNCTION_NAMES));
return;
}
)?
unsafe {
CLASS = Some($crate::binder_impl::InterfaceClass::new::<$crate::binder_impl::Binder<$native>>());
}
});
unsafe { CLASS.unwrap() }
}
}
impl $crate::FromIBinder for dyn $interface {
fn try_from(mut ibinder: $crate::SpIBinder) -> core::result::Result<$crate::Strong<dyn $interface>, $crate::StatusCode> {
use $crate::binder_impl::AssociateClass;
let existing_class = ibinder.get_class();
if let Some(class) = existing_class {
if class != <$native as $crate::binder_impl::Remotable>::get_class() &&
class.get_descriptor() == <$native as $crate::binder_impl::Remotable>::get_descriptor()
{
return Ok($crate::Strong::new(alloc::boxed::Box::new(<$proxy as $crate::binder_impl::Proxy>::from_binder(ibinder)?)));
}
}
if ibinder.associate_class(<$native as $crate::binder_impl::Remotable>::get_class()) {
let service: core::result::Result<$crate::binder_impl::Binder<$native>, $crate::StatusCode> =
core::convert::TryFrom::try_from(ibinder.clone());
if let Ok(service) = service {
return Ok($crate::Strong::new(alloc::boxed::Box::new(service)));
} else {
return Ok($crate::Strong::new(alloc::boxed::Box::new(<$proxy as $crate::binder_impl::Proxy>::from_binder(ibinder)?)));
}
}
Err($crate::StatusCode::BAD_TYPE.into())
}
}
impl $crate::binder_impl::Serialize for dyn $interface + '_
where
dyn $interface: $crate::Interface
{
fn serialize(&self, parcel: &mut $crate::binder_impl::BorrowedParcel<'_>) -> core::result::Result<(), $crate::StatusCode> {
let binder = $crate::Interface::as_binder(self);
parcel.write(&binder)
}
}
impl $crate::binder_impl::SerializeOption for dyn $interface + '_ {
fn serialize_option(this: Option<&Self>, parcel: &mut $crate::binder_impl::BorrowedParcel<'_>) -> core::result::Result<(), $crate::StatusCode> {
parcel.write(&this.map($crate::Interface::as_binder))
}
}
impl core::fmt::Debug for dyn $interface + '_ {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.pad(stringify!($interface))
}
}
impl alloc::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)))
}
}
$(
impl<P: $crate::BinderAsyncPool + 'static> $crate::FromIBinder for dyn $async_interface<P> {
fn try_from(mut ibinder: $crate::SpIBinder) -> core::result::Result<$crate::Strong<dyn $async_interface<P>>, $crate::StatusCode> {
use $crate::binder_impl::AssociateClass;
let existing_class = ibinder.get_class();
if let Some(class) = existing_class {
if class != <$native as $crate::binder_impl::Remotable>::get_class() &&
class.get_descriptor() == <$native as $crate::binder_impl::Remotable>::get_descriptor()
{
return Ok($crate::Strong::new(alloc::boxed::Box::new(<$proxy as $crate::binder_impl::Proxy>::from_binder(ibinder)?)));
}
}
if ibinder.associate_class(<$native as $crate::binder_impl::Remotable>::get_class()) {
let service: core::result::Result<$crate::binder_impl::Binder<$native>, $crate::StatusCode> =
core::convert::TryFrom::try_from(ibinder.clone());
$(
if let Ok(service) = service {
if let Some(async_service) = $native::$try_into_local_async(service) {
return Ok(async_service);
}
}
)?
return Ok($crate::Strong::new(alloc::boxed::Box::new(<$proxy as $crate::binder_impl::Proxy>::from_binder(ibinder)?)));
}
Err($crate::StatusCode::BAD_TYPE.into())
}
}
impl<P: $crate::BinderAsyncPool + 'static> $crate::binder_impl::Serialize for dyn $async_interface<P> + '_ {
fn serialize(&self, parcel: &mut $crate::binder_impl::BorrowedParcel<'_>) -> core::result::Result<(), $crate::StatusCode> {
let binder = $crate::Interface::as_binder(self);
parcel.write(&binder)
}
}
impl<P: $crate::BinderAsyncPool + 'static> $crate::binder_impl::SerializeOption for dyn $async_interface<P> + '_ {
fn serialize_option(this: Option<&Self>, parcel: &mut $crate::binder_impl::BorrowedParcel<'_>) -> core::result::Result<(), $crate::StatusCode> {
parcel.write(&this.map($crate::Interface::as_binder))
}
}
impl<P: $crate::BinderAsyncPool + 'static> core::fmt::Debug for dyn $async_interface<P> + '_ {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.pad(stringify!($async_interface))
}
}
impl<P: $crate::BinderAsyncPool + 'static> alloc::borrow::ToOwned for dyn $async_interface<P> {
type Owned = $crate::Strong<dyn $async_interface<P>>;
fn to_owned(&self) -> Self::Owned {
self.as_binder().into_interface()
.expect(concat!("Error cloning interface ", stringify!($async_interface)))
}
}
impl<P: $crate::BinderAsyncPool + 'static> $crate::binder_impl::ToAsyncInterface<P> for dyn $interface {
type Target = dyn $async_interface<P>;
}
impl<P: $crate::BinderAsyncPool + 'static> $crate::binder_impl::ToSyncInterface for dyn $async_interface<P> {
type Target = dyn $interface;
}
)?
};
}
#[macro_export]
macro_rules! declare_binder_enum {
{
$( #[$attr:meta] )*
$enum:ident : [$backing:ty; $size:expr_2021] {
$( $( #[$value_attr:meta] )* $name:ident = $value:expr_2021, )*
}
} => {
$( #[$attr] )*
#[derive(Default, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
#[derive(zerocopy::Immutable, zerocopy::TryFromBytes)]
#[allow(missing_docs)]
#[repr(C)]
pub struct $enum(pub $backing);
impl $enum {
$( $( #[$value_attr] )* #[allow(missing_docs)] pub const $name: Self = Self($value); )*
#[inline(always)]
#[allow(missing_docs)]
pub const fn enum_values() -> [Self; $size] {
[$(Self::$name),*]
}
#[inline(always)]
#[allow(missing_docs)]
pub const fn get(&self) -> $backing {
self.0
}
}
impl core::fmt::Debug for $enum {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self.0 {
$($value => f.write_str(stringify!($name)),)*
_ => f.write_fmt(format_args!("{}", self.0))
}
}
}
impl $crate::binder_impl::Serialize for $enum {
fn serialize(&self, parcel: &mut $crate::binder_impl::BorrowedParcel<'_>) -> core::result::Result<(), $crate::StatusCode> {
parcel.write(&self.0)
}
}
impl $crate::binder_impl::SerializeArray for $enum {
fn serialize_array(slice: &[Self], parcel: &mut $crate::binder_impl::BorrowedParcel<'_>) -> core::result::Result<(), $crate::StatusCode> {
let v: alloc::vec::Vec<$backing> = slice.iter().map(|x| x.0).collect();
<$backing as $crate::binder_impl::SerializeArray>::serialize_array(&v[..], parcel)
}
}
impl $crate::binder_impl::Deserialize for $enum {
type UninitType = Self;
fn uninit() -> Self::UninitType { Self::UninitType::default() }
fn from_init(value: Self) -> Self::UninitType { value }
fn deserialize(parcel: &$crate::binder_impl::BorrowedParcel<'_>) -> core::result::Result<Self, $crate::StatusCode> {
parcel.read().map(Self)
}
}
impl $crate::binder_impl::DeserializeArray for $enum {
fn deserialize_array(parcel: &$crate::binder_impl::BorrowedParcel<'_>) -> core::result::Result<Option<alloc::vec::Vec<Self>>, $crate::StatusCode> {
let v: Option<alloc::vec::Vec<$backing>> =
<$backing as $crate::binder_impl::DeserializeArray>::deserialize_array(parcel)?;
Ok(v.map(|v| v.into_iter().map(Self).collect()))
}
}
impl $crate::WriteTo for $enum {
#[inline]
unsafe fn write_to(&self, target: *mut Self) {
unsafe { self.0.write_to(&raw mut (*target).0); }
}
#[inline]
unsafe fn write_to_volatile(&self, target: *mut Self) {
unsafe { self.0.write_to_volatile(&raw mut (*target).0); }
}
}
impl core::ops::BitOr for $enum {
type Output = Self;
fn bitor(self, rhs: Self) -> Self {
Self(self.0 | rhs.0)
}
}
impl core::ops::BitOrAssign for $enum {
fn bitor_assign(&mut self, rhs: Self) {
self.0 = self.0 | rhs.0;
}
}
impl core::ops::BitAnd for $enum {
type Output = Self;
fn bitand(self, rhs: Self) -> Self {
Self(self.0 & rhs.0)
}
}
impl core::ops::BitAndAssign for $enum {
fn bitand_assign(&mut self, rhs: Self) {
self.0 = self.0 & rhs.0;
}
}
impl core::ops::BitXor for $enum {
type Output = Self;
fn bitxor(self, rhs: Self) -> Self {
Self(self.0 ^ rhs.0)
}
}
impl core::ops::BitXorAssign for $enum {
fn bitxor_assign(&mut self, rhs: Self) {
self.0 = self.0 ^ rhs.0;
}
}
};
}