#[cfg(feature = "async")]
#[macro_export]
macro_rules! __declare_binder_interface {
{
$interface:path[$descriptor:expr] {
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr),*
},
$(r#async: $async_interface:ident,)?
stability: $stability:expr,
}
} => {
$(
pub trait $native_adapter {
fn as_sync(&self) -> &dyn $interface;
#[allow(dead_code)]
fn as_async(&self) -> &dyn $native_async;
#[allow(dead_code)]
fn try_as_async(&self) -> ::core::option::Option<&dyn $native_async>;
}
pub struct $native(::std::boxed::Box<dyn $native_adapter + ::core::marker::Send + ::core::marker::Sync + 'static>);
impl $native {
pub fn new_binder<T: $interface + ::core::marker::Sync + ::core::marker::Send + 'static>(inner: T) -> $crate::Strong<dyn $interface> {
Self::new_binder_with_features(inner, $crate::BinderFeatures::default())
}
pub fn new_binder_with_features<T: $interface + ::core::marker::Sync + ::core::marker::Send + 'static>(
inner: T,
features: $crate::BinderFeatures,
) -> $crate::Strong<dyn $interface> {
struct Wrapper<T> {
_inner: T,
}
impl<T> $native_adapter for Wrapper<T>
where
T: $interface + ::core::marker::Sync + ::core::marker::Send + 'static,
{
fn as_sync(&self) -> &dyn $interface { &self._inner }
fn as_async(&self) -> &dyn $native_async {
unreachable!("{} doesn't support async interface.", stringify!($interface))
}
fn try_as_async(&self) -> ::core::option::Option<&dyn $native_async> { ::core::option::Option::None }
}
let binder = $crate::Binder::new_with_stability_and_features(
$native(::std::boxed::Box::new(Wrapper {_inner: inner})),
$stability,
features,
);
$crate::Strong::new(::std::boxed::Box::new(binder))
}
}
impl $crate::Remotable for $native {
fn descriptor() -> &'static str where Self: Sized {
$descriptor
}
fn on_transact(&self, code: $crate::TransactionCode, reader: &mut $crate::Parcel, reply: &mut $crate::Parcel) -> $crate::Result<()> {
$on_transact(self.0.as_sync(), code, reader, reply)
}
fn on_dump(&self, _writer: &mut dyn ::std::io::Write, _args: &[::std::string::String]) -> $crate::Result<()> {
self.0.as_sync().dump(_writer, _args)
}
}
)?
$(
impl<P: $crate::BinderAsyncPool> $crate::FromIBinder for dyn $async_interface<P> {
fn try_from(ibinder: $crate::SIBinder) -> ::std::result::Result<$crate::Strong<dyn $async_interface<P>>, $crate::StatusCode> {
match <$proxy as $crate::Proxy>::from_binder(ibinder.clone()) {
::core::option::Option::Some(proxy) => ::core::result::Result::Ok($crate::Strong::new(::std::boxed::Box::new(proxy))),
::core::option::Option::None => {
match $crate::Binder::<$native>::try_from(ibinder) {
::core::result::Result::Ok(native) => {
if native.0.try_as_async().is_some() {
::core::result::Result::Ok($crate::Strong::new(::std::boxed::Box::new(native)))
} else {
::core::result::Result::Err($crate::StatusCode::BadType)
}
}
::core::result::Result::Err(err) => ::core::result::Result::Err(err),
}
}
}
}
}
impl<P: $crate::BinderAsyncPool> $crate::Serialize for dyn $async_interface<P> + '_ {
fn serialize(&self, parcel: &mut $crate::Parcel) -> ::std::result::Result<(), $crate::StatusCode> {
let binder = $crate::Interface::as_binder(self);
parcel.write(&binder)
}
}
impl<P: $crate::BinderAsyncPool> $crate::SerializeOption for dyn $async_interface<P> + '_ {
fn serialize_option(this: ::core::option::Option<&Self>, parcel: &mut $crate::Parcel) -> ::std::result::Result<(), $crate::StatusCode> {
parcel.write(&this.map($crate::Interface::as_binder))
}
}
impl<P: $crate::BinderAsyncPool> ::std::fmt::Debug for dyn $async_interface<P> + '_ {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
f.pad(stringify!($async_interface))
}
}
impl<P: $crate::BinderAsyncPool> $crate::ToAsyncInterface<P> for dyn $interface {
type Target = dyn $async_interface<P>;
}
impl<P: $crate::BinderAsyncPool> $crate::ToSyncInterface for dyn $async_interface<P> {
type Target = dyn $interface;
}
)?
};
}
#[cfg(not(feature = "async"))]
#[macro_export]
macro_rules! __declare_binder_interface {
{
$interface:path[$descriptor:expr] {
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr),*
},
$(r#async: $async_interface:ident,)?
stability: $stability:expr,
}
} => {
pub struct $native(::std::boxed::Box<dyn $interface + ::core::marker::Send + ::core::marker::Sync + 'static>);
impl $native {
pub fn new_binder<T: $interface + ::core::marker::Sync + ::core::marker::Send + 'static>(inner: T) -> $crate::Strong<dyn $interface> {
Self::new_binder_with_features(inner, $crate::BinderFeatures::default())
}
pub fn new_binder_with_features<T: $interface + ::core::marker::Sync + ::core::marker::Send + 'static>(
inner: T,
features: $crate::BinderFeatures,
) -> $crate::Strong<dyn $interface> {
let binder = $crate::Binder::new_with_stability_and_features(
$native(::std::boxed::Box::new(inner)),
$stability,
features,
);
$crate::Strong::new(::std::boxed::Box::new(binder))
}
}
impl $crate::Remotable for $native {
fn descriptor() -> &'static str where Self: Sized {
$descriptor
}
fn on_transact(&self, code: $crate::TransactionCode, reader: &mut $crate::Parcel, reply: &mut $crate::Parcel) -> $crate::Result<()> {
$on_transact(&*self.0, code, reader, reply)
}
fn on_dump(&self, _writer: &mut dyn ::std::io::Write, _args: &[::std::string::String]) -> $crate::Result<()> {
self.0.dump(_writer, _args)
}
}
};
}
#[macro_export]
macro_rules! declare_binder_interface {
{
$interface:path[$descriptor:expr] {
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
proxy: $proxy:ident,
$(r#async: $async_interface:ident,)?
}
} => {
$crate::declare_binder_interface! {
$interface[$descriptor] {
native: {
$native($on_transact),
$(adapter: $native_adapter,)?
$(r#async: $native_async,)?
},
proxy: $proxy {},
$(r#async: $async_interface,)?
stability: $crate::Stability::default(),
}
}
};
{
$interface:path[$descriptor:expr] {
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
proxy: $proxy:ident,
$(r#async: $async_interface:ident,)?
stability: $stability:expr,
}
} => {
$crate::declare_binder_interface! {
$interface[$descriptor] {
native: {
$native($on_transact),
$(adapter: $native_adapter,)?
$(r#async: $native_async,)?
},
proxy: $proxy {},
$(r#async: $async_interface,)?
stability: $stability,
}
}
};
{
$interface:path[$descriptor:expr] {
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr),*
},
$(r#async: $async_interface:ident,)?
}
} => {
$crate::declare_binder_interface! {
$interface[$descriptor] {
native: {
$native($on_transact),
$(adapter: $native_adapter,)?
$(r#async: $native_async,)?
},
proxy: $proxy {
$($fname: $fty = $finit),*
},
$(r#async: $async_interface,)?
stability: $crate::Stability::default(),
}
}
};
{
$interface:path[$descriptor:expr] {
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr),*
},
$(r#async: $async_interface:ident,)?
stability: $stability:expr,
}
} => {
$crate::declare_binder_interface! {
$interface[$descriptor] {
@doc[concat!("A binder `Remotable` that holds an [`", stringify!($interface), "`] object.")]
native: {
$native($on_transact),
$(adapter: $native_adapter,)?
$(r#async: $native_async,)?
},
@doc[concat!("A binder `Proxy` that holds an [`", stringify!($interface), "`] remote interface.")]
proxy: $proxy {
$($fname: $fty = $finit),*
},
$(r#async: $async_interface,)?
stability: $stability,
}
}
};
{
$interface:path[$descriptor:expr] {
@doc[$native_doc:expr]
native: {
$native:ident($on_transact:path),
$(adapter: $native_adapter:ident,)?
$(r#async: $native_async:ident,)?
},
@doc[$proxy_doc:expr]
proxy: $proxy:ident {
$($fname:ident: $fty:ty = $finit:expr),*
},
$( r#async: $async_interface:ident, )?
stability: $stability:expr,
}
} => {
#[doc = $proxy_doc]
pub struct $proxy {
binder: $crate::SIBinder,
$($fname: $fty,)*
}
impl $crate::Interface for $proxy {
fn as_binder(&self) -> $crate::SIBinder {
self.binder.clone()
}
}
impl $crate::Proxy for $proxy
where
$proxy: $interface,
{
fn descriptor() -> &'static str {
$descriptor
}
fn from_binder(binder: $crate::SIBinder) -> ::core::option::Option<Self> {
$crate::__rpc_stamp_descriptor(&binder, $descriptor);
if binder.descriptor() != $descriptor {
return ::core::option::Option::None
}
if binder.as_remote().is_some() {
::core::option::Option::Some(Self { binder, $($fname: $finit),* })
} else {
::core::option::Option::None
}
}
}
$crate::__declare_binder_interface!{
$interface[$descriptor] {
native: {
$native($on_transact),
$(adapter: $native_adapter,)?
$(r#async: $native_async,)?
},
proxy: $proxy {
$($fname: $fty = $finit),*
},
$(r#async: $async_interface,)?
stability: $stability,
}
}
impl $crate::FromIBinder for dyn $interface {
fn try_from(binder: $crate::SIBinder) -> $crate::Result<$crate::Strong<dyn $interface>> {
match <$proxy as $crate::Proxy>::from_binder(binder.clone()) {
::core::option::Option::Some(proxy) => ::core::result::Result::Ok($crate::Strong::new(::std::boxed::Box::new(proxy))),
::core::option::Option::None => {
match $crate::Binder::<$native>::try_from(binder) {
::core::result::Result::Ok(native) => ::core::result::Result::Ok($crate::Strong::new(::std::boxed::Box::new(native))),
::core::result::Result::Err(err) => ::core::result::Result::Err(err),
}
}
}
}
}
impl $crate::Serialize for dyn $interface + '_
where
dyn $interface: $crate::Interface
{
fn serialize(&self, parcel: &mut $crate::Parcel) -> $crate::Result<()> {
let binder = $crate::Interface::as_binder(self);
parcel.write(&binder)?;
::core::result::Result::Ok(())
}
}
impl $crate::SerializeOption for dyn $interface + '_ {
fn serialize_option(this: ::core::option::Option<&Self>, parcel: &mut $crate::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))
}
}
}
}
#[macro_export]
macro_rules! impl_serialize_for_parcelable {
($parcelable:ident) => {
impl $crate::Serialize for $parcelable {
fn serialize(&self, parcel: &mut $crate::Parcel) -> $crate::Result<()> {
<Self as $crate::SerializeOption>::serialize_option(
::core::option::Option::Some(self),
parcel,
)
}
}
impl $crate::SerializeArray for $parcelable {}
impl $crate::SerializeOption for $parcelable {
fn serialize_option(
this: ::core::option::Option<&Self>,
parcel: &mut $crate::Parcel,
) -> $crate::Result<()> {
if let ::core::option::Option::Some(this) = this {
use $crate::Parcelable;
parcel.write(&$crate::NON_NULL_PARCELABLE_FLAG)?;
this.write_to_parcel(parcel)
} else {
parcel.write(&$crate::NULL_PARCELABLE_FLAG)
}
}
}
};
}
#[macro_export]
macro_rules! impl_deserialize_for_parcelable {
($parcelable:ident) => {
impl $crate::Deserialize for $parcelable {
fn deserialize(parcel: &mut $crate::Parcel) -> $crate::Result<Self> {
$crate::DeserializeOption::deserialize_option(parcel)
.transpose()
.unwrap_or(::core::result::Result::Err(
$crate::StatusCode::UnexpectedNull.into(),
))
}
fn deserialize_from(&mut self, parcel: &mut $crate::Parcel) -> $crate::Result<()> {
let status: i32 = parcel.read()?;
if status == $crate::NULL_PARCELABLE_FLAG {
::core::result::Result::Err($crate::StatusCode::UnexpectedNull.into())
} else if status == $crate::NON_NULL_PARCELABLE_FLAG {
use $crate::Parcelable;
self.read_from_parcel(parcel)
} else {
::core::result::Result::Err($crate::StatusCode::UnexpectedNull.into())
}
}
}
impl $crate::DeserializeArray for $parcelable {}
impl $crate::DeserializeOption for $parcelable {
fn deserialize_option(
parcel: &mut $crate::Parcel,
) -> $crate::Result<::core::option::Option<Self>> {
let mut result = ::core::option::Option::None;
Self::deserialize_option_from(&mut result, parcel)?;
::core::result::Result::Ok(result)
}
fn deserialize_option_from(
this: &mut ::core::option::Option<Self>,
parcel: &mut $crate::Parcel,
) -> $crate::Result<()> {
let status: i32 = parcel.read()?;
if status == $crate::NULL_PARCELABLE_FLAG {
*this = ::core::option::Option::None;
::core::result::Result::Ok(())
} else if status == $crate::NON_NULL_PARCELABLE_FLAG {
use $crate::Parcelable;
this.get_or_insert_with(Self::default)
.read_from_parcel(parcel)
} else {
::core::result::Result::Err($crate::StatusCode::UnexpectedNull.into())
}
}
}
};
}
#[macro_export]
macro_rules! declare_binder_enum {
{
$( #[$attr:meta] )*
$enum:ident : [$backing:ty; $size:expr] {
$( $( #[$value_attr:meta] )* $name:ident = $value:expr, )*
}
} => {
$( #[$attr] )*
#[derive(Debug, Default, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
#[allow(missing_docs)]
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::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 |= 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 &= 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 ^= rhs.0;
}
}
impl $crate::Serialize for $enum {
fn serialize(&self, parcel: &mut $crate::Parcel) -> $crate::Result<()> {
parcel.write(&self.0)
}
}
impl $crate::SerializeArray for $enum {
fn serialize_array(slice: &[Self], parcel: &mut $crate::Parcel) -> $crate::Result<()> {
let v: ::std::vec::Vec<$backing> = slice.iter().map(|x| x.0).collect();
<$backing as $crate::SerializeArray>::serialize_array(&v[..], parcel)
}
}
impl $crate::Deserialize for $enum {
fn deserialize(parcel: &mut $crate::Parcel) -> $crate::Result<Self> {
let res = parcel.read().map(Self);
res
}
}
impl $crate::DeserializeArray for $enum {
fn deserialize_array(parcel: &mut $crate::Parcel) -> $crate::Result<::core::option::Option<::std::vec::Vec<Self>>> {
let v: ::core::option::Option<::std::vec::Vec<$backing>> =
<$backing as $crate::DeserializeArray>::deserialize_array(parcel)?;
::core::result::Result::Ok(v.map(|v| v.into_iter().map(Self).collect()))
}
}
};
}
#[macro_export]
macro_rules! include_aidl {
($file:literal, $($use_path:tt)+) => {
include!(concat!(env!("OUT_DIR"), "/", $file, ".rs"));
pub use $($use_path)+;
};
($file:literal $(,)?) => {
include!(concat!(env!("OUT_DIR"), "/", $file, ".rs"));
};
}
#[cfg(test)]
mod tests {
use crate::{Binder, Interface, Parcel, Result, TransactionCode};
pub trait IEcho: Interface {
fn echo(&self, echo: &str) -> Result<String>;
}
pub trait IEchoAsyncService: Interface {
#[allow(dead_code)]
fn echo(&self, echo: &str) -> Result<String>;
}
declare_binder_interface! {
IEcho["my.echo"] {
native: {
BnEcho(on_transact),
adapter: BnEchoAdapter,
r#async: IEchoAsyncService,
},
proxy: BpEcho{},
}
}
#[allow(dead_code)]
impl IEcho for Binder<BnEcho> {
#[cfg(feature = "async")]
fn echo(&self, echo: &str) -> Result<String> {
self.0.as_sync().echo(echo)
}
#[cfg(not(feature = "async"))]
fn echo(&self, echo: &str) -> Result<String> {
self.0.echo(echo)
}
}
impl IEcho for BpEcho {
fn echo(&self, _echo: &str) -> Result<String> {
unimplemented!("BpEcho::echo")
}
}
fn on_transact(
_service: &dyn IEcho,
_code: TransactionCode,
_data: &mut Parcel,
_reply: &mut Parcel,
) -> Result<()> {
Ok(())
}
struct EchoService {}
impl Interface for EchoService {}
impl IEcho for EchoService {
fn echo(&self, echo: &str) -> Result<String> {
Ok(echo.to_owned())
}
}
pub trait IBye: Interface {
#[allow(dead_code)]
fn bye(&self) -> Result<()>;
}
pub trait IByeAsyncService: Interface {
#[allow(dead_code)]
fn bye(&self) -> Result<()>;
}
declare_binder_interface! {
IBye["my.bye"] {
native: {
BnBye(on_transact_bye),
adapter: BnByeAdapter,
r#async: IByeAsyncService,
},
proxy: BpBye{},
}
}
#[allow(dead_code)]
impl IBye for Binder<BnBye> {
#[cfg(feature = "async")]
fn bye(&self) -> Result<()> {
self.0.as_sync().bye()
}
#[cfg(not(feature = "async"))]
fn bye(&self) -> Result<()> {
self.0.bye()
}
}
impl IBye for BpBye {
fn bye(&self) -> Result<()> {
unimplemented!("BpBye::bye")
}
}
fn on_transact_bye(
_service: &dyn IBye,
_code: TransactionCode,
_data: &mut Parcel,
_reply: &mut Parcel,
) -> Result<()> {
Ok(())
}
struct ByeService {}
impl Interface for ByeService {}
impl IBye for ByeService {
fn bye(&self) -> Result<()> {
Ok(())
}
}
#[test]
fn test_declare_binder_interface() {
let _ = BnEcho::new_binder(EchoService {});
}
#[test]
fn test_cast_mismatch_is_bad_type() {
let echo: crate::SIBinder = BnEcho::new_binder(EchoService {}).into();
let bye: crate::SIBinder = BnBye::new_binder(ByeService {}).into();
assert!(<dyn IEcho as crate::FromIBinder>::try_from(echo.clone()).is_ok());
assert!(<dyn IBye as crate::FromIBinder>::try_from(bye.clone()).is_ok());
assert_eq!(
<dyn IBye as crate::FromIBinder>::try_from(echo).unwrap_err(),
crate::StatusCode::BadType,
);
assert_eq!(
<dyn IEcho as crate::FromIBinder>::try_from(bye).unwrap_err(),
crate::StatusCode::BadType,
);
}
#[test]
fn test_strong_try_from() {
let echo: crate::SIBinder = BnEcho::new_binder(EchoService {}).into();
assert!(crate::Strong::<dyn IEcho>::try_from(echo.clone()).is_ok());
assert_eq!(
crate::Strong::<dyn IBye>::try_from(echo).unwrap_err(),
crate::StatusCode::BadType,
);
}
#[test]
fn test_link_to_death_arc_no_cast() {
struct Rec;
impl crate::DeathRecipient for Rec {
fn binder_died(&self, _who: &crate::WIBinder) {}
}
let recipient = std::sync::Arc::new(Rec);
let strong = BnEcho::new_binder(EchoService {});
assert_eq!(
strong.link_to_death_arc(&recipient).unwrap_err(),
crate::StatusCode::InvalidOperation,
);
let sib: crate::SIBinder = strong.into();
assert_eq!(
sib.link_to_death_arc(&recipient).unwrap_err(),
crate::StatusCode::InvalidOperation,
);
assert_eq!(
sib.unlink_to_death_arc(&recipient).unwrap_err(),
crate::StatusCode::InvalidOperation,
);
}
}