use std::any::Any;
use std::borrow::Borrow;
use std::fmt::{Debug, Formatter};
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::Deref;
use std::sync::{self, Arc};
use crate::{error::*, parcel::*, proxy, sys};
pub type TransactionCode = u32;
pub type TransactionFlags = u32;
pub const FLAG_ONEWAY: TransactionFlags = sys::transaction_flags_TF_ONE_WAY;
pub const FLAG_CLEAR_BUF: TransactionFlags = sys::transaction_flags_TF_CLEAR_BUF;
pub const FLAG_PRIVATE_LOCAL: TransactionFlags = 0;
pub const FLAG_PRIVATE_VENDOR: TransactionFlags = FLAG_PRIVATE_LOCAL;
const fn b_pack_chars(c1: char, c2: char, c3: char, c4: char) -> u32 {
((c1 as u32) << 24) | ((c2 as u32) << 16) | ((c3 as u32) << 8) | (c4 as u32)
}
pub const FIRST_CALL_TRANSACTION: u32 = 0x00000001;
pub const LAST_CALL_TRANSACTION: u32 = 0x00ffffff;
pub const PING_TRANSACTION: u32 = b_pack_chars('_', 'P', 'N', 'G');
pub const DUMP_TRANSACTION: u32 = b_pack_chars('_', 'D', 'M', 'P');
pub const SHELL_COMMAND_TRANSACTION: u32 = b_pack_chars('_', 'C', 'M', 'D');
pub const INTERFACE_TRANSACTION: u32 = b_pack_chars('_', 'N', 'T', 'F');
pub const SYSPROPS_TRANSACTION: u32 = b_pack_chars('_', 'S', 'P', 'R');
pub const EXTENSION_TRANSACTION: u32 = b_pack_chars('_', 'E', 'X', 'T');
pub const DEBUG_PID_TRANSACTION: u32 = b_pack_chars('_', 'P', 'I', 'D');
pub const SET_RPC_CLIENT_TRANSACTION: u32 = b_pack_chars('_', 'R', 'P', 'C');
pub const START_RECORDING_TRANSACTION: u32 = b_pack_chars('_', 'S', 'R', 'D');
pub const STOP_RECORDING_TRANSACTION: u32 = b_pack_chars('_', 'E', 'R', 'D');
pub const TWEET_TRANSACTION: u32 = b_pack_chars('_', 'T', 'W', 'T');
pub const LIKE_TRANSACTION: u32 = b_pack_chars('_', 'L', 'I', 'K');
pub const INTERFACE_HEADER: u32 = b_pack_chars('S', 'Y', 'S', 'T');
pub trait Interface: Send + Sync {
fn as_binder(&self) -> SIBinder {
log::error!(
"as_binder() called on non-Binder object of type {}. \
This is a programmer error - only Binder objects should implement Interface.",
std::any::type_name::<Self>()
);
unreachable!(
"as_binder() must be overridden by types that can be converted to SIBinder. \
Type: {}",
std::any::type_name::<Self>()
)
}
fn dump(&self, _writer: &mut dyn std::io::Write, _args: &[String]) -> Result<()> {
Ok(())
}
}
pub trait FromIBinder: Interface {
fn try_from(ibinder: SIBinder) -> Result<Strong<Self>>;
}
pub trait DeathRecipient: Send + Sync {
fn binder_died(&self, who: &WIBinder);
}
pub trait IBinder: Any + Send + Sync {
fn link_to_death(&self, recipient: sync::Weak<dyn DeathRecipient>) -> Result<()>;
fn unlink_to_death(&self, recipient: sync::Weak<dyn DeathRecipient>) -> Result<()>;
fn ping_binder(&self) -> Result<()>;
fn as_any(&self) -> &dyn Any;
fn as_transactable(&self) -> Option<&dyn Transactable>;
fn descriptor(&self) -> &str;
fn is_remote(&self) -> bool;
fn stability(&self) -> Stability {
Stability::default()
}
fn get_extension(&self) -> Result<Option<SIBinder>> {
Ok(None)
}
fn set_extension(&self, _extension: &SIBinder) -> Result<()> {
Err(StatusCode::InvalidOperation)
}
fn local_binder_flags(&self) -> u32 {
0
}
fn inc_strong(&self, strong: &SIBinder) -> Result<()>;
fn attempt_inc_strong(&self) -> bool;
fn dec_strong(&self, strong: Option<ManuallyDrop<SIBinder>>) -> Result<()>;
fn inc_weak(&self, weak: &WIBinder) -> Result<()>;
fn dec_weak(&self) -> Result<()>;
}
impl dyn IBinder {
pub fn as_proxy(&self) -> Option<&proxy::ProxyHandle> {
self.as_any().downcast_ref::<proxy::ProxyHandle>()
}
}
impl std::fmt::Debug for dyn IBinder {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self.as_any())
}
}
pub trait Remotable: Send + Sync {
fn descriptor() -> &'static str
where
Self: Sized;
fn on_transact(
&self,
code: TransactionCode,
reader: &mut Parcel,
reply: &mut Parcel,
) -> Result<()>;
fn on_dump(&self, writer: &mut dyn std::io::Write, args: &[String]) -> Result<()>;
}
pub trait Transactable: Send + Sync {
fn transact(
&self,
code: TransactionCode,
reader: &mut Parcel,
reply: &mut Parcel,
) -> Result<()>;
}
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(Default, Debug, Copy, Clone, PartialEq, Eq)]
pub enum Stability {
Local,
Vendor,
#[default]
System,
Vintf,
}
impl Stability {
pub fn includes(&self, required: Stability) -> bool {
let provided: i32 = (*self).into();
let required: i32 = required.into();
(provided & required) == required
}
}
impl From<Stability> for i32 {
fn from(stability: Stability) -> i32 {
use Stability::*;
let stability = match stability {
Local => 0,
Vendor => 0b000011,
System => 0b001100,
Vintf => 0b111111,
};
#[cfg(target_os = "android")]
{
let android_sdk_version = crate::get_android_sdk_version();
if android_sdk_version == 31 || android_sdk_version == 32 {
stability | 0x0c000000
} else {
stability
}
}
#[cfg(not(target_os = "android"))]
stability
}
}
impl TryFrom<i32> for Stability {
type Error = StatusCode;
fn try_from(stability: i32) -> Result<Stability> {
use Stability::*;
let level = if stability <= 0xFF {
stability
} else {
(stability >> 24) & 0xFF
};
match level {
0 => Ok(Local),
0b000011 => Ok(Vendor),
0b001100 => Ok(System),
0b111111 => Ok(Vintf),
_ => {
log::error!("Stability value is invalid: {stability:#X}");
Err(StatusCode::BadValue)
}
}
}
}
pub struct SIBinder {
inner: Arc<dyn IBinder>,
}
impl SIBinder {
pub fn new(data: Arc<dyn IBinder>) -> Result<Self> {
let this = Self { inner: data };
this.increase()?;
Ok(this)
}
pub(crate) fn from_arc(inner: Arc<dyn IBinder>) -> Self {
let this = Self { inner };
this.increase()
.expect("inc_strong on existing Arc<dyn IBinder> must not fail");
this
}
pub(crate) fn as_arc(&self) -> &Arc<dyn IBinder> {
&self.inner
}
pub fn downgrade(this: &Self) -> WIBinder {
let weak = Arc::downgrade(&this.inner);
if let Some(proxy_handle) = this.inner.as_any().downcast_ref::<proxy::ProxyHandle>() {
let handle = proxy_handle.handle();
let stability = proxy_handle.stability();
let generation =
crate::process_state::ProcessState::as_self().cache_generation_for(handle);
match generation {
Some(generation) => WIBinder {
inner: WIBinderInner::Proxy {
handle,
stability,
generation,
weak,
},
},
None => WIBinder {
inner: WIBinderInner::Native(weak),
},
}
} else {
WIBinder {
inner: WIBinderInner::Native(weak),
}
}
}
pub fn stability(&self) -> Stability {
self.inner.stability()
}
pub(crate) fn increase(&self) -> Result<()> {
self.inner.inc_strong(self)
}
pub(crate) fn attempt_increase(&self) -> bool {
self.inner.attempt_inc_strong()
}
pub(crate) fn decrease(&self) -> Result<()> {
self.inner.dec_strong(None)
}
pub fn into_interface<I: FromIBinder + Interface + ?Sized>(self) -> Result<Strong<I>> {
FromIBinder::try_from(self)
}
}
impl Debug for SIBinder {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
f.debug_struct("SIBinder")
.field("descriptor", &self.descriptor())
.field("ptr", &Arc::as_ptr(&self.inner))
.finish()
}
}
impl Clone for SIBinder {
fn clone(&self) -> Self {
Self::from_arc(Arc::clone(&self.inner))
}
}
impl Drop for SIBinder {
fn drop(&mut self) {
self.decrease()
.map_err(|err| {
log::error!("Error in SIBinder::drop() is {err:?}");
})
.ok();
}
}
impl Deref for SIBinder {
type Target = dyn IBinder;
fn deref(&self) -> &Self::Target {
self.inner.deref()
}
}
impl PartialEq for SIBinder {
fn eq(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.inner, &other.inner)
}
}
impl Eq for SIBinder {}
pub struct WIBinder {
inner: WIBinderInner,
}
pub(crate) enum WIBinderInner {
Proxy {
handle: u32,
stability: Stability,
generation: u64,
weak: sync::Weak<dyn IBinder>,
},
Native(sync::Weak<dyn IBinder>),
}
impl WIBinder {
pub fn upgrade(&self) -> Result<SIBinder> {
match &self.inner {
WIBinderInner::Native(weak) => weak
.upgrade()
.map(SIBinder::from_arc)
.ok_or(StatusCode::DeadObject),
WIBinderInner::Proxy {
handle,
stability,
generation,
weak,
} => {
if let Some(arc) = weak.upgrade() {
return Ok(SIBinder::from_arc(arc));
}
crate::process_state::ProcessState::as_self().resurrect_proxy_for_handle_stability(
*handle,
*stability,
*generation,
)
}
}
}
}
impl Debug for WIBinder {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
match &self.inner {
WIBinderInner::Native(weak) => f
.debug_struct("WIBinder::Native")
.field("strong_count", &weak.strong_count())
.field("weak_count", &weak.weak_count())
.finish(),
WIBinderInner::Proxy {
handle,
stability,
generation,
weak,
} => f
.debug_struct("WIBinder::Proxy")
.field("handle", handle)
.field("stability", stability)
.field("generation", generation)
.field("strong_count", &weak.strong_count())
.finish(),
}
}
}
impl Clone for WIBinder {
fn clone(&self) -> Self {
let inner = match &self.inner {
WIBinderInner::Native(weak) => WIBinderInner::Native(sync::Weak::clone(weak)),
WIBinderInner::Proxy {
handle,
stability,
generation,
weak,
} => WIBinderInner::Proxy {
handle: *handle,
stability: *stability,
generation: *generation,
weak: sync::Weak::clone(weak),
},
};
Self { inner }
}
}
impl PartialEq for WIBinder {
fn eq(&self, other: &Self) -> bool {
match (&self.inner, &other.inner) {
(WIBinderInner::Native(a), WIBinderInner::Native(b)) => sync::Weak::ptr_eq(a, b),
(
WIBinderInner::Proxy {
handle: ha,
generation: ga,
..
},
WIBinderInner::Proxy {
handle: hb,
generation: gb,
..
},
) => ha == hb && ga == gb,
_ => false,
}
}
}
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())
.expect("ToAsyncInterface guarantees binder compatibility")
}
pub fn into_sync(self) -> Strong<<I as ToSyncInterface>::Target>
where
I: ToSyncInterface,
{
FromIBinder::try_from(self.0.as_binder())
.expect("ToSyncInterface guarantees binder compatibility")
}
}
impl<I: FromIBinder + ?Sized> Clone for Strong<I> {
fn clone(&self) -> Self {
FromIBinder::try_from(self.0.as_binder())
.expect("Failed to clone Strong<I>: existing strong reference guarantees valid binder")
}
}
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 + Debug + ?Sized> Debug for Strong<I> {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
Debug::fmt(&**self, f)
}
}
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: WIBinder,
interface_type: PhantomData<I>,
}
impl<I: FromIBinder + ?Sized> Weak<I> {
fn new(binder: &Strong<I>) -> Self {
let weak_binder = SIBinder::downgrade(&binder.as_binder());
Weak {
weak_binder,
interface_type: PhantomData,
}
}
pub fn upgrade(&self) -> Result<Strong<I>> {
self.weak_binder.upgrade().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,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
struct MockBinder;
impl IBinder for MockBinder {
fn link_to_death(&self, _: sync::Weak<dyn DeathRecipient>) -> Result<()> {
Err(StatusCode::InvalidOperation)
}
fn unlink_to_death(&self, _: sync::Weak<dyn DeathRecipient>) -> Result<()> {
Err(StatusCode::InvalidOperation)
}
fn ping_binder(&self) -> Result<()> {
Ok(())
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_transactable(&self) -> Option<&dyn Transactable> {
None
}
fn descriptor(&self) -> &str {
"rsbinder.test.MockBinder"
}
fn is_remote(&self) -> bool {
false
}
fn inc_strong(&self, _: &SIBinder) -> Result<()> {
Ok(())
}
fn attempt_inc_strong(&self) -> bool {
true
}
fn dec_strong(&self, _: Option<ManuallyDrop<SIBinder>>) -> Result<()> {
Ok(())
}
fn inc_weak(&self, _: &WIBinder) -> Result<()> {
Ok(())
}
fn dec_weak(&self) -> Result<()> {
Ok(())
}
}
#[test]
fn test_wibinder_upgrade_after_strong_drop_returns_dead_object() {
let strong = SIBinder::new(Arc::new(MockBinder)).expect("SIBinder::new");
let weak = SIBinder::downgrade(&strong);
let upgraded = weak.upgrade().expect("upgrade while alive");
assert!(Arc::ptr_eq(&strong.inner, &upgraded.inner));
drop(upgraded);
drop(strong);
match weak.upgrade() {
Err(StatusCode::DeadObject) => {}
Err(other) => panic!("expected DeadObject after Arc drop, got {other:?}"),
Ok(_) => panic!(
"expected DeadObject after Arc drop, but upgrade succeeded \
(regression: WIBinder::upgrade is no longer truly weak)"
),
}
}
#[test]
fn test_wibinder_clone_and_ptr_eq_after_drop() {
let strong = SIBinder::new(Arc::new(MockBinder)).expect("SIBinder::new");
let weak1 = SIBinder::downgrade(&strong);
let weak2 = weak1.clone();
assert_eq!(weak1, weak2);
drop(strong);
assert_eq!(weak1, weak2);
assert!(matches!(weak1.upgrade(), Err(StatusCode::DeadObject)));
assert!(matches!(weak2.upgrade(), Err(StatusCode::DeadObject)));
}
#[test]
fn test_strong() -> Result<()> {
Ok(())
}
#[test]
fn test_b_pack_chars() {
assert_eq!(b_pack_chars('_', 'P', 'N', 'G'), PING_TRANSACTION);
assert_eq!(b_pack_chars('_', 'D', 'M', 'P'), DUMP_TRANSACTION);
assert_eq!(b_pack_chars('_', 'C', 'M', 'D'), SHELL_COMMAND_TRANSACTION);
assert_eq!(b_pack_chars('_', 'N', 'T', 'F'), INTERFACE_TRANSACTION);
assert_eq!(b_pack_chars('_', 'S', 'P', 'R'), SYSPROPS_TRANSACTION);
assert_eq!(b_pack_chars('_', 'E', 'X', 'T'), EXTENSION_TRANSACTION);
assert_eq!(b_pack_chars('_', 'P', 'I', 'D'), DEBUG_PID_TRANSACTION);
assert_eq!(b_pack_chars('_', 'R', 'P', 'C'), SET_RPC_CLIENT_TRANSACTION);
assert_eq!(
b_pack_chars('_', 'S', 'R', 'D'),
START_RECORDING_TRANSACTION
);
assert_eq!(b_pack_chars('_', 'E', 'R', 'D'), STOP_RECORDING_TRANSACTION);
assert_eq!(b_pack_chars('_', 'T', 'W', 'T'), TWEET_TRANSACTION);
assert_eq!(b_pack_chars('_', 'L', 'I', 'K'), LIKE_TRANSACTION);
}
}
#[cfg(test)]
mod stability_tests {
use super::*;
#[test]
fn test_stability_wire_values() {
assert_eq!(Into::<i32>::into(Stability::Local), 0);
assert_eq!(Into::<i32>::into(Stability::Vendor), 0b000011);
assert_eq!(Into::<i32>::into(Stability::System), 0b001100);
assert_eq!(Into::<i32>::into(Stability::Vintf), 0b111111);
}
#[test]
fn test_stability_roundtrip() {
for s in [
Stability::Local,
Stability::Vendor,
Stability::System,
Stability::Vintf,
] {
let wire: i32 = s.into();
assert_eq!(Stability::try_from(wire).unwrap(), s);
}
}
#[test]
fn test_stability_category_format() {
let category = |level: i32, version: i32| -> i32 { (level << 24) | version };
assert_eq!(
Stability::try_from(category(0b000011, 1)).unwrap(),
Stability::Vendor
);
assert_eq!(
Stability::try_from(category(0b001100, 1)).unwrap(),
Stability::System
);
assert_eq!(
Stability::try_from(category(0b111111, 1)).unwrap(),
Stability::Vintf
);
assert_eq!(
Stability::try_from(category(0b001100, 12)).unwrap(),
Stability::System
);
assert_eq!(
Stability::try_from(0b001100 | 0x0c000000_i32).unwrap(),
Stability::System
);
}
#[test]
fn test_stability_invalid_value() {
assert_eq!(Stability::try_from(0x7F).unwrap_err(), StatusCode::BadValue);
assert_eq!(Stability::try_from(0x01).unwrap_err(), StatusCode::BadValue);
}
#[test]
fn test_stability_includes() {
assert!(Stability::Local.includes(Stability::Local));
assert!(Stability::Vendor.includes(Stability::Local));
assert!(Stability::System.includes(Stability::Local));
assert!(Stability::Vintf.includes(Stability::Local));
assert!(!Stability::Vendor.includes(Stability::System));
assert!(!Stability::System.includes(Stability::Vendor));
assert!(Stability::Vintf.includes(Stability::Vendor));
assert!(Stability::Vintf.includes(Stability::System));
assert!(Stability::Vintf.includes(Stability::Vintf));
assert!(Stability::Vendor.includes(Stability::Vendor));
assert!(Stability::System.includes(Stability::System));
}
}