use crate::binder::{
AsNative, FromIBinder, IBinder, IBinderInternal, Interface, InterfaceClass, Strong,
TransactionCode, TransactionFlags,
};
use crate::error::{Result, StatusCode, status_result};
use crate::parcel::{
BorrowedParcel, Deserialize, DeserializeArray, DeserializeOption, Parcel, Serialize,
SerializeArray, SerializeOption,
};
use crate::sys;
use alloc::sync::Arc;
use core::cmp::Ordering;
use core::ffi::c_void;
use core::fmt;
use core::mem;
use core::ptr;
#[cfg(feature = "std")]
use std::ffi::CString;
#[cfg(feature = "std")]
use std::os::fd::AsRawFd;
pub struct SpIBinder(ptr::NonNull<sys::AIBinder>);
impl fmt::Debug for SpIBinder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("SpIBinder")
}
}
unsafe impl Send for SpIBinder {}
unsafe impl Sync for SpIBinder {}
impl SpIBinder {
pub(crate) unsafe fn from_raw(ptr: *mut sys::AIBinder) -> Option<Self> {
ptr::NonNull::new(ptr).map(Self)
}
pub unsafe fn as_raw(&self) -> *mut sys::AIBinder {
self.0.as_ptr()
}
pub fn is_remote(&self) -> bool {
unsafe { sys::AIBinder_isRemote(self.as_native()) }
}
pub fn into_interface<I: FromIBinder + Interface + ?Sized>(self) -> Result<Strong<I>> {
FromIBinder::try_from(self)
}
pub fn get_class(&mut self) -> Option<InterfaceClass> {
unsafe {
let class = sys::AIBinder_getClass(self.as_native_mut());
class.as_ref().map(|p| InterfaceClass::from_ptr(p))
}
}
pub fn downgrade(&mut self) -> WpIBinder {
WpIBinder::new(self)
}
#[cfg(not(android_ndk))]
pub fn requires_vintf_declaration(&self) -> bool {
#[cfg(feature = "android_ndk_compat_symbols")]
unsafe {
binder_rs_ndk_compat::requires_vintf_declaration(self.as_raw())
}
#[cfg(not(feature = "android_ndk_compat_symbols"))]
unsafe {
sys::AIBinder_requiresVintfDeclaration(self.as_raw())
}
}
#[cfg(not(android_ndk))]
pub fn is_vendor_stable(&self) -> bool {
#[cfg(feature = "android_ndk_compat_symbols")]
unsafe {
binder_rs_ndk_compat::is_vendor_stable(self.as_raw())
}
#[cfg(not(feature = "android_ndk_compat_symbols"))]
unsafe {
sys::AIBinder_isVendorStable(self.as_raw())
}
}
#[cfg(not(android_ndk))]
pub fn is_system_stable(&self) -> bool {
#[cfg(feature = "android_ndk_compat_symbols")]
unsafe {
binder_rs_ndk_compat::is_system_stable(self.as_raw())
}
#[cfg(not(feature = "android_ndk_compat_symbols"))]
unsafe {
sys::AIBinder_isSystemStable(self.as_raw())
}
}
}
pub mod unstable_api {
use super::{SpIBinder, sys};
pub unsafe fn new_spibinder(ptr: *mut sys::AIBinder) -> Option<SpIBinder> {
unsafe { SpIBinder::from_raw(ptr) }
}
}
pub trait AssociateClass {
fn associate_class(&mut self, class: InterfaceClass) -> bool;
}
impl AssociateClass for SpIBinder {
fn associate_class(&mut self, class: InterfaceClass) -> bool {
unsafe { sys::AIBinder_associateClass(self.as_native_mut(), class.into()) }
}
}
impl Ord for SpIBinder {
fn cmp(&self, other: &Self) -> Ordering {
let less_than = unsafe { sys::AIBinder_lt(self.0.as_ptr(), other.0.as_ptr()) };
let greater_than = unsafe { sys::AIBinder_lt(other.0.as_ptr(), self.0.as_ptr()) };
if !less_than && !greater_than {
Ordering::Equal
} else if less_than {
Ordering::Less
} else {
Ordering::Greater
}
}
}
impl PartialOrd for SpIBinder {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for SpIBinder {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == Ordering::Equal
}
}
impl Eq for SpIBinder {}
impl Clone for SpIBinder {
fn clone(&self) -> Self {
unsafe {
sys::AIBinder_incStrong(self.0.as_ptr());
}
Self(self.0)
}
}
impl Drop for SpIBinder {
fn drop(&mut self) {
unsafe {
sys::AIBinder_decStrong(self.as_native_mut());
}
}
}
impl<T: AsNative<sys::AIBinder>> IBinderInternal for T {
fn prepare_transact(&self) -> Result<Parcel> {
let mut input = ptr::null_mut();
let status = unsafe {
sys::AIBinder_prepareTransaction(self.as_native() as *mut sys::AIBinder, &mut input)
};
status_result(status)?;
unsafe { Parcel::from_raw(input).ok_or(StatusCode::UNEXPECTED_NULL) }
}
fn submit_transact(
&self,
code: TransactionCode,
data: Parcel,
flags: TransactionFlags,
) -> Result<Parcel> {
let mut reply = ptr::null_mut();
let status = unsafe {
sys::AIBinder_transact(
self.as_native() as *mut sys::AIBinder,
code,
&mut data.into_raw(),
&mut reply,
flags,
)
};
status_result(status)?;
unsafe { Parcel::from_raw(reply).ok_or(StatusCode::UNEXPECTED_NULL) }
}
fn is_binder_alive(&self) -> bool {
unsafe { sys::AIBinder_isAlive(self.as_native()) }
}
#[cfg(not(any(android_vndk, android_ndk)))]
fn set_requesting_sid(&mut self, enable: bool) {
unsafe { sys::AIBinder_setRequestingSid(self.as_native_mut(), enable) };
}
#[cfg(not(any(android_vndk, android_ndk)))]
fn set_inherit_rt(&mut self, enable: bool) {
unsafe { sys::AIBinder_setInheritRt(self.as_native_mut(), enable) };
}
#[cfg(feature = "std")]
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 {
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 { sys::AIBinder_getExtension(self.as_native_mut(), &mut out) };
let ibinder = unsafe { SpIBinder::from_raw(out) };
status_result(status)?;
Ok(ibinder)
}
}
impl<T: AsNative<sys::AIBinder>> IBinder for T {
fn link_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> {
status_result(unsafe {
sys::AIBinder_linkToDeath(
self.as_native_mut(),
recipient.as_native_mut(),
recipient.new_cookie(),
)
})
}
fn unlink_to_death(&mut self, recipient: &mut DeathRecipient) -> Result<()> {
status_result(unsafe {
sys::AIBinder_unlinkToDeath(
self.as_native_mut(),
recipient.as_native_mut(),
recipient.get_cookie(),
)
})
}
fn ping_binder(&mut self) -> Result<()> {
let status = unsafe { sys::AIBinder_ping(self.as_native_mut()) };
status_result(status)
}
}
impl Serialize for SpIBinder {
fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
parcel.write_binder(Some(self))
}
}
impl SerializeOption for SpIBinder {
fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
parcel.write_binder(this)
}
}
impl SerializeArray for SpIBinder {}
impl Deserialize for SpIBinder {
type UninitType = Option<Self>;
fn uninit() -> Self::UninitType {
Self::UninitType::default()
}
fn from_init(value: Self) -> Self::UninitType {
Some(value)
}
fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<SpIBinder> {
parcel.read_binder().transpose().unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
}
}
impl DeserializeOption for SpIBinder {
fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<SpIBinder>> {
parcel.read_binder()
}
}
impl DeserializeArray for SpIBinder {}
pub struct WpIBinder(ptr::NonNull<sys::AIBinder_Weak>);
impl fmt::Debug for WpIBinder {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad("WpIBinder")
}
}
unsafe impl Send for WpIBinder {}
unsafe impl Sync for WpIBinder {}
impl WpIBinder {
fn new<B: AsNative<sys::AIBinder>>(binder: &mut B) -> WpIBinder {
let ptr = unsafe { sys::AIBinder_Weak_new(binder.as_native_mut()) };
Self(ptr::NonNull::new(ptr).expect("Unexpected null pointer from AIBinder_Weak_new"))
}
pub fn promote(&self) -> Option<SpIBinder> {
unsafe {
let ptr = sys::AIBinder_Weak_promote(self.0.as_ptr());
SpIBinder::from_raw(ptr)
}
}
}
impl Clone for WpIBinder {
fn clone(&self) -> Self {
let ptr = unsafe { sys::AIBinder_Weak_clone(self.0.as_ptr()) };
Self(ptr::NonNull::new(ptr).expect("Unexpected null pointer from AIBinder_Weak_clone"))
}
}
impl Ord for WpIBinder {
fn cmp(&self, other: &Self) -> Ordering {
let less_than = unsafe { sys::AIBinder_Weak_lt(self.0.as_ptr(), other.0.as_ptr()) };
let greater_than = unsafe { sys::AIBinder_Weak_lt(other.0.as_ptr(), self.0.as_ptr()) };
if !less_than && !greater_than {
Ordering::Equal
} else if less_than {
Ordering::Less
} else {
Ordering::Greater
}
}
}
impl PartialOrd for WpIBinder {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for WpIBinder {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == Ordering::Equal
}
}
impl Eq for WpIBinder {}
impl Drop for WpIBinder {
fn drop(&mut self) {
unsafe {
sys::AIBinder_Weak_delete(self.0.as_ptr());
}
}
}
#[repr(C)]
pub struct DeathRecipient {
recipient: *mut sys::AIBinder_DeathRecipient,
cookie: *mut c_void,
vtable: &'static DeathRecipientVtable,
}
struct DeathRecipientVtable {
cookie_incr_refcount: unsafe extern "C" fn(*mut c_void),
cookie_decr_refcount: unsafe extern "C" fn(*mut c_void),
}
unsafe impl Send for DeathRecipient {}
unsafe impl Sync for DeathRecipient {}
impl DeathRecipient {
pub fn new<F>(callback: F) -> DeathRecipient
where
F: Fn() + Send + Sync + 'static,
{
let callback: *const F = Arc::into_raw(Arc::new(callback));
let recipient = unsafe { sys::AIBinder_DeathRecipient_new(Some(Self::binder_died::<F>)) };
unsafe {
sys::AIBinder_DeathRecipient_setOnUnlinked(
recipient,
Some(Self::cookie_decr_refcount::<F>),
);
}
DeathRecipient {
recipient,
cookie: callback as *mut c_void,
vtable: &DeathRecipientVtable {
cookie_incr_refcount: Self::cookie_incr_refcount::<F>,
cookie_decr_refcount: Self::cookie_decr_refcount::<F>,
},
}
}
unsafe fn new_cookie(&self) -> *mut c_void {
unsafe {
(self.vtable.cookie_incr_refcount)(self.cookie);
}
self.cookie
}
fn get_cookie(&self) -> *mut c_void {
self.cookie
}
unsafe extern "C" fn binder_died<F>(cookie: *mut c_void)
where
F: Fn() + Send + Sync + 'static,
{
let callback = unsafe { (cookie as *const F).as_ref().unwrap() };
callback();
}
unsafe extern "C" fn cookie_decr_refcount<F>(cookie: *mut c_void)
where
F: Fn() + Send + Sync + 'static,
{
drop(unsafe { Arc::from_raw(cookie as *const F) });
}
unsafe extern "C" fn cookie_incr_refcount<F>(cookie: *mut c_void)
where
F: Fn() + Send + Sync + 'static,
{
let arc = mem::ManuallyDrop::new(unsafe { Arc::from_raw(cookie as *const F) });
mem::forget(Arc::clone(&arc));
}
}
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 {
sys::AIBinder_DeathRecipient_delete(self.recipient);
}
unsafe {
(self.vtable.cookie_decr_refcount)(self.cookie);
}
}
}
pub trait Proxy: Sized + Interface {
fn get_descriptor() -> &'static str;
fn from_binder(binder: SpIBinder) -> Result<Self>;
}
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()
}
}
unsafe impl AsNative<sys::AIBinder> for SpIBinder {
fn as_native(&self) -> *const sys::AIBinder {
self.0.as_ptr()
}
fn as_native_mut(&mut self) -> *mut sys::AIBinder {
self.0.as_ptr()
}
}