1#[cfg(target_os = "android")]
27mod imp {
28 use crate::CoreError;
29 use crate::dex;
30 use std::os::fd::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd};
31 use std::os::raw::{c_char, c_void};
32 use std::sync::atomic::{AtomicI32, AtomicU32, AtomicUsize, Ordering};
33 use std::sync::Mutex;
34
35 const STATUS_OK: i32 = 0;
38 const STATUS_UNKNOWN_TRANSACTION: i32 = -2;
39 const EX_NONE: i32 = 0;
40
41 const AM_DESCRIPTOR: &[u8] = b"android.app.IActivityManager\0";
44 const OBS_DESCRIPTOR: &[u8] = b"android.app.IProcessObserver\0";
45 const FGPROC_DESCRIPTOR: &[u8] = b"android.app.IForegroundProcessObserver\0";
46 const ACTIVITY_SERVICE: &[u8] = b"activity\0";
47 #[cfg(target_pointer_width = "64")]
48 const LIBBINDER_PATH: &[u8] = b"/system/lib64/libbinder_ndk.so\0";
49 #[cfg(target_pointer_width = "32")]
50 const LIBBINDER_PATH: &[u8] = b"/system/lib/libbinder_ndk.so\0";
51
52 static OBS_FG_CODE: AtomicU32 = AtomicU32::new(0);
63 static OBS_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
64
65 fn obs_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
66 OBS_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
67 }
68
69 static FGPROC_FG_CODE: AtomicU32 = AtomicU32::new(0);
77 static FGPROC_PID: AtomicI32 = AtomicI32::new(0);
78 static FGPROC_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
79 static FGPROC_READ_I32: AtomicUsize = AtomicUsize::new(0);
80 static FGPROC_IPROC_MODE: AtomicU32 = AtomicU32::new(0);
85
86 fn fgproc_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
87 FGPROC_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
88 }
89
90 type AIBinder = c_void;
93 #[allow(non_camel_case_types)]
94 type AIBinder_Class = c_void;
95 type AParcel = c_void;
96 type BinderStatus = i32;
97 type StringAllocator = unsafe extern "C" fn(*mut c_void, i32, *mut *mut c_char) -> bool;
98
99 unsafe extern "C" fn am_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
103 unsafe extern "C" fn am_on_destroy(_: *mut c_void) {}
104 unsafe extern "C" fn am_on_transact(
105 _: *mut AIBinder, _: u32, _: *const AParcel, _: *mut AParcel,
106 ) -> BinderStatus { STATUS_UNKNOWN_TRANSACTION }
107
108 unsafe extern "C" fn obs_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
110 unsafe extern "C" fn obs_on_destroy(_: *mut c_void) {}
111 unsafe extern "C" fn obs_on_transact(
112 _: *mut AIBinder, code: u32, _: *const AParcel, _: *mut AParcel,
113 ) -> BinderStatus {
114 if code == OBS_FG_CODE.load(Ordering::Relaxed) {
115 if let Some(fd) = obs_eventfd_guard().as_ref() {
118 let val: u64 = 1;
119 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
120 }
121 }
122 STATUS_OK
123 }
124
125 unsafe extern "C" fn fgproc_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
134 unsafe extern "C" fn fgproc_on_destroy(_: *mut c_void) {}
135 unsafe extern "C" fn fgproc_on_transact(
136 _: *mut AIBinder, code: u32, in_parcel: *const AParcel, _: *mut AParcel,
137 ) -> BinderStatus {
138 if code != FGPROC_FG_CODE.load(Ordering::Relaxed) {
139 return STATUS_UNKNOWN_TRANSACTION;
140 }
141 let read_addr = FGPROC_READ_I32.load(Ordering::Relaxed);
144 if read_addr != 0 {
145 let read_fn: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus =
146 unsafe { std::mem::transmute(read_addr) };
147 if FGPROC_IPROC_MODE.load(Ordering::Relaxed) == 1 {
148 let mut pid: i32 = 0;
150 let mut _uid: i32 = 0;
151 let mut fg: i32 = 0;
152 let mut ok = unsafe { read_fn(in_parcel, &mut pid) } == STATUS_OK;
153 ok &= unsafe { read_fn(in_parcel, &mut _uid) } == STATUS_OK;
154 ok &= unsafe { read_fn(in_parcel, &mut fg) } == STATUS_OK;
155 if ok {
156 FGPROC_PID.store(pid, Ordering::Relaxed);
157 if fg == 0 {
160 return STATUS_OK;
161 }
162 } else {
163 return STATUS_OK;
164 }
165 } else {
166 let mut pid: i32 = 0;
167 if unsafe { read_fn(in_parcel, &mut pid) } == STATUS_OK {
168 FGPROC_PID.store(pid, Ordering::Relaxed);
169 }
170 }
171 }
172 if let Some(fd) = fgproc_eventfd_guard().as_ref() {
175 let val: u64 = 1;
176 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
177 }
178 STATUS_OK
179 }
180
181 pub fn last_foreground_pid() -> i32 {
184 FGPROC_PID.load(Ordering::Relaxed)
185 }
186
187 unsafe extern "C" fn string_alloc(
190 cookie: *mut c_void, length: i32, buffer: *mut *mut c_char,
191 ) -> bool {
192 if length < 0 { return true; }
193 let s = unsafe { &mut *(cookie as *mut StringBuf) };
194 s.0.reserve_exact(length as usize + 1);
195 unsafe { s.0.as_mut_vec().resize(length as usize + 1, 0) };
196 unsafe { *buffer = s.0.as_mut_ptr() as *mut c_char };
197 true
198 }
199
200 struct StringBuf(String);
201 impl StringBuf {
202 fn new() -> Self { Self(String::new()) }
203 fn finish(mut self) -> Option<String> {
204 if let Some(pos) = self.0.as_bytes().iter().position(|&b| b == 0) {
205 unsafe { self.0.as_mut_vec().truncate(pos) };
206 }
207 if self.0.is_empty() { None } else { Some(self.0) }
208 }
209 }
210
211 struct Vtable {
214 get_service: unsafe extern "C" fn(*const c_char) -> *mut AIBinder,
215 class_define: unsafe extern "C" fn(
216 *const c_char,
217 unsafe extern "C" fn(*mut c_void) -> *mut c_void,
218 unsafe extern "C" fn(*mut c_void),
219 unsafe extern "C" fn(*mut AIBinder, u32, *const AParcel, *mut AParcel) -> BinderStatus,
220 ) -> *mut AIBinder_Class,
221 associate_class: unsafe extern "C" fn(*mut AIBinder, *mut AIBinder_Class) -> bool,
222 new_binder: unsafe extern "C" fn(*const AIBinder_Class, *mut c_void) -> *mut AIBinder,
223 prepare_transaction: unsafe extern "C" fn(*mut AIBinder, *mut *mut AParcel) -> BinderStatus,
224 transact: unsafe extern "C" fn(*mut AIBinder, u32, *mut *mut AParcel, *mut *mut AParcel, u32) -> BinderStatus,
225 dec_strong: unsafe extern "C" fn(*mut AIBinder),
226 parcel_delete: unsafe extern "C" fn(*mut AParcel),
227 read_int32: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus,
228 read_string: unsafe extern "C" fn(*const AParcel, *mut c_void, StringAllocator) -> BinderStatus,
229 write_strong_binder: unsafe extern "C" fn(*mut AParcel, *mut AIBinder) -> BinderStatus,
230 set_thread_pool_max: unsafe extern "C" fn(u32),
231 join_thread_pool: unsafe extern "C" fn(),
232 write_int32: unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus,
233 read_bool: Option<unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus>,
235 }
236
237 struct DlHandle(*mut c_void);
240 unsafe impl Send for DlHandle {}
241 impl Drop for DlHandle {
242 fn drop(&mut self) {
243 }
249 }
250
251 struct OwnedParcel { ptr: *mut AParcel, delete: unsafe extern "C" fn(*mut AParcel) }
252 impl Drop for OwnedParcel {
253 fn drop(&mut self) { if !self.ptr.is_null() { unsafe { (self.delete)(self.ptr) }; } }
254 }
255
256 struct OwnedBinder { ptr: *mut AIBinder, dec_strong: unsafe extern "C" fn(*mut AIBinder) }
257 unsafe impl Send for OwnedBinder {}
258 impl Drop for OwnedBinder {
259 fn drop(&mut self) { if !self.ptr.is_null() { unsafe { (self.dec_strong)(self.ptr) }; } }
260 }
261
262 macro_rules! dlsym_fn {
265 ($handle:expr, $name:literal, $ty:ty) => {{
266 let sym = unsafe {
267 libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char)
268 };
269 if sym.is_null() {
270 return Err(CoreError::binder(-1, concat!("dlsym:", $name)));
271 }
272 unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) }
273 }};
274 }
275
276 macro_rules! dlsym_opt {
277 ($handle:expr, $name:literal, $ty:ty) => {{
278 let sym = unsafe {
279 libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char)
280 };
281 if sym.is_null() { None }
282 else { Some(unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) }) }
283 }};
284 }
285
286 fn load_vtable(handle: *mut c_void) -> Result<Vtable, CoreError> {
287 Ok(Vtable {
288 get_service: dlsym_fn!(handle, "AServiceManager_getService",
289 unsafe extern "C" fn(*const c_char) -> *mut AIBinder),
290 class_define: dlsym_fn!(handle, "AIBinder_Class_define",
291 unsafe extern "C" fn(
292 *const c_char,
293 unsafe extern "C" fn(*mut c_void) -> *mut c_void,
294 unsafe extern "C" fn(*mut c_void),
295 unsafe extern "C" fn(*mut AIBinder, u32, *const AParcel, *mut AParcel) -> BinderStatus,
296 ) -> *mut AIBinder_Class),
297 associate_class: dlsym_fn!(handle, "AIBinder_associateClass",
298 unsafe extern "C" fn(*mut AIBinder, *mut AIBinder_Class) -> bool),
299 new_binder: dlsym_fn!(handle, "AIBinder_new",
300 unsafe extern "C" fn(*const AIBinder_Class, *mut c_void) -> *mut AIBinder),
301 prepare_transaction: dlsym_fn!(handle, "AIBinder_prepareTransaction",
302 unsafe extern "C" fn(*mut AIBinder, *mut *mut AParcel) -> BinderStatus),
303 transact: dlsym_fn!(handle, "AIBinder_transact",
304 unsafe extern "C" fn(*mut AIBinder, u32, *mut *mut AParcel, *mut *mut AParcel, u32) -> BinderStatus),
305 dec_strong: dlsym_fn!(handle, "AIBinder_decStrong",
306 unsafe extern "C" fn(*mut AIBinder)),
307 parcel_delete: dlsym_fn!(handle, "AParcel_delete",
308 unsafe extern "C" fn(*mut AParcel)),
309 read_int32: dlsym_fn!(handle, "AParcel_readInt32",
310 unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus),
311 read_string: dlsym_fn!(handle, "AParcel_readString",
312 unsafe extern "C" fn(*const AParcel, *mut c_void, StringAllocator) -> BinderStatus),
313 write_strong_binder: dlsym_fn!(handle, "AParcel_writeStrongBinder",
314 unsafe extern "C" fn(*mut AParcel, *mut AIBinder) -> BinderStatus),
315 set_thread_pool_max: dlsym_fn!(handle, "ABinderProcess_setThreadPoolMaxThreadCount",
316 unsafe extern "C" fn(u32)),
317 join_thread_pool: dlsym_fn!(handle, "ABinderProcess_joinThreadPool",
318 unsafe extern "C" fn()),
319 write_int32: dlsym_fn!(handle, "AParcel_writeInt32",
320 unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus),
321 read_bool: dlsym_opt!(handle, "AParcel_readBool",
322 unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus),
323 })
324 }
325
326 struct ParcelReader<'a> { vt: &'a Vtable, parcel: &'a OwnedParcel }
329
330 impl<'a> ParcelReader<'a> {
331 fn read_i32(&self) -> Result<i32, CoreError> {
332 let mut v = 0i32;
333 let s = unsafe { (self.vt.read_int32)(self.parcel.ptr, &mut v) };
334 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readInt32")); }
335 Ok(v)
336 }
337 fn read_string(&self) -> Result<Option<String>, CoreError> {
338 let mut buf = StringBuf::new();
339 let s = unsafe {
340 (self.vt.read_string)(self.parcel.ptr, &mut buf as *mut StringBuf as *mut c_void, string_alloc)
341 };
342 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readString")); }
343 Ok(buf.finish())
344 }
345 fn skip_i32s(&self, n: usize) -> Result<(), CoreError> {
346 for _ in 0..n { self.read_i32()?; }
347 Ok(())
348 }
349 fn skip_int_array(&self) -> Result<(), CoreError> {
350 let count = self.read_i32()?.max(0) as usize;
351 self.skip_i32s(count)
352 }
353 fn read_first_package_from_names(&self) -> Result<Option<String>, CoreError> {
354 let count = self.read_i32()?.max(0) as usize;
355 let mut first: Option<String> = None;
356 for _ in 0..count {
357 let s = self.read_string()?;
358 if first.is_none() {
359 first = s.and_then(|c| c.split('/').next().map(str::to_owned));
360 }
361 }
362 Ok(first)
363 }
364 }
365
366 fn parse_root_task_info_body(r: &ParcelReader<'_>) -> Result<Option<String>, CoreError> {
369 let scratch = r.read_i32()?;
370 if scratch != 0 { r.skip_i32s(4)?; }
371 r.skip_int_array()?;
372 r.read_first_package_from_names()
373 }
374
375 fn parse_stack_info_body(r: &ParcelReader<'_>) -> Result<Option<String>, CoreError> {
376 r.skip_i32s(5)?;
377 r.skip_int_array()?;
378 r.read_first_package_from_names()
379 }
380
381 pub struct TxCodes {
384 pub observer_code: u32,
385 pub query_code: u32,
386 pub api_mode: u8, pub fg_code: u32,
388 }
389
390 pub fn resolve_tx_codes() -> Result<TxCodes, CoreError> {
391 let (obs, query, api, fg) = dex::resolve_tx_codes_from_dex()
392 .ok_or_else(|| CoreError::binder(-1, "tx_code_resolution:dex_parse_failed"))?;
393 Ok(TxCodes { observer_code: obs, query_code: query, api_mode: api, fg_code: fg })
394 }
395
396 pub struct ActivityManagerBinder {
399 _lib: DlHandle,
400 vt: Vtable,
401 _class: *mut AIBinder_Class,
402 service: OwnedBinder,
403 tx_code: u32,
404 legacy: bool,
405 }
406 unsafe impl Send for ActivityManagerBinder {}
407
408 impl ActivityManagerBinder {
409 fn open_inner(handle: *mut c_void) -> Result<(DlHandle, Vtable, *mut AIBinder_Class, OwnedBinder), CoreError> {
410 let lib = DlHandle(handle);
411 let vt = load_vtable(handle)?;
412
413 let am_class = unsafe {
414 (vt.class_define)(
415 AM_DESCRIPTOR.as_ptr() as *const c_char,
416 am_on_create, am_on_destroy, am_on_transact,
417 )
418 };
419 if am_class.is_null() { return Err(CoreError::binder(-1, "AIBinder_Class_define:AM")); }
420
421 let raw = unsafe { (vt.get_service)(ACTIVITY_SERVICE.as_ptr() as *const c_char) };
422 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:activity")); }
423 unsafe { (vt.associate_class)(raw, am_class) };
424
425 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
426 Ok((lib, vt, am_class, service))
427 }
428
429 fn dlopen_libbinder() -> Result<*mut c_void, CoreError> {
430 use std::os::raw::c_char;
431 let handle = unsafe {
432 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
433 };
434 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
435 Ok(handle)
436 }
437
438 pub fn open() -> Result<Self, CoreError> {
441 let handle = Self::dlopen_libbinder()?;
442 let (lib, vt, class, service) = Self::open_inner(handle)?;
443 let codes = resolve_tx_codes()?;
444 let legacy = codes.api_mode == 2;
445 Ok(Self { _lib: lib, vt, _class: class, service, tx_code: codes.query_code, legacy })
446 }
447
448 pub fn open_with_observer() -> Result<(Self, OwnedFd), CoreError> {
457 let handle = Self::dlopen_libbinder()?;
458 let (lib, vt, am_class, service) = Self::open_inner(handle)?;
459 let codes = resolve_tx_codes()?;
460 let legacy = codes.api_mode == 2;
461
462 let owned = unsafe {
465 let raw = libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC);
466 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
467 OwnedFd::from_raw_fd(raw)
468 };
469
470 let obs_class = unsafe {
472 (vt.class_define)(
473 OBS_DESCRIPTOR.as_ptr() as *const c_char,
474 obs_on_create, obs_on_destroy, obs_on_transact,
475 )
476 };
477 if obs_class.is_null() {
478 return Err(CoreError::binder(-1, "AIBinder_Class_define:Observer"));
479 }
480
481 let obs_binder = unsafe { (vt.new_binder)(obs_class, std::ptr::null_mut()) };
483 if obs_binder.is_null() {
484 return Err(CoreError::binder(-1, "AIBinder_new:Observer"));
485 }
486 unsafe { (vt.associate_class)(obs_binder, obs_class) };
487
488 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
490 let s = unsafe { (vt.prepare_transaction)(service.ptr, &mut in_ptr) };
491 if s != STATUS_OK {
492 return Err(CoreError::binder(s, "prepareTransaction:registerObserver"));
493 }
494 unsafe { (vt.write_strong_binder)(in_ptr, obs_binder) };
495 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
496 let s = unsafe {
497 (vt.transact)(service.ptr, codes.observer_code, &mut in_ptr, &mut out_ptr, 0)
498 };
499 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
500 if s != STATUS_OK {
501 return Err(CoreError::binder(s, "transact:registerProcessObserver"));
502 }
503
504 let consumer = owned.try_clone()
507 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:observer"))?;
508
509 OBS_FG_CODE.store(codes.fg_code, Ordering::Relaxed);
511 *obs_eventfd_guard() = Some(owned);
512
513 unsafe { (vt.set_thread_pool_max)(0) };
515 let join_fn = vt.join_thread_pool;
516 std::thread::spawn(move || unsafe { join_fn() });
517
518 let binder = Self { _lib: lib, vt, _class: am_class, service, tx_code: codes.query_code, legacy };
519 Ok((binder, consumer))
520 }
521
522 pub fn open_with_fgproc_observer() -> Result<(Self, OwnedFd), CoreError> {
546 let handle = Self::dlopen_libbinder()?;
547 let (lib, vt, am_class, service) = Self::open_inner(handle)?;
548
549 let (register_code, fgproc_code, mode, descriptor): (u32, u32, u32, &[u8]) =
554 match crate::dex::resolve_fgproc_codes() {
555 Some((r, c)) => (r, c, 0, FGPROC_DESCRIPTOR),
556 None => match crate::dex::resolve_fgproc_codes_fallback() {
557 Some((r, c)) => (r, c, 1, OBS_DESCRIPTOR),
558 None => {
559 return Err(CoreError::binder(-1, "tx_code_resolution:fgproc_dex_parse_failed"));
560 }
561 },
562 };
563
564 let owned = unsafe {
567 let raw = libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC);
568 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
569 OwnedFd::from_raw_fd(raw)
570 };
571
572 let obs_class = unsafe {
575 (vt.class_define)(
576 descriptor.as_ptr() as *const c_char,
577 fgproc_on_create, fgproc_on_destroy, fgproc_on_transact,
578 )
579 };
580 if obs_class.is_null() {
581 return Err(CoreError::binder(-1, "AIBinder_Class_define:FGProcessObserver"));
582 }
583
584 let obs_binder = unsafe { (vt.new_binder)(obs_class, std::ptr::null_mut()) };
586 if obs_binder.is_null() {
587 return Err(CoreError::binder(-1, "AIBinder_new:FGProcessObserver"));
588 }
589 unsafe { (vt.associate_class)(obs_binder, obs_class) };
590
591 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
594 let s = unsafe { (vt.prepare_transaction)(service.ptr, &mut in_ptr) };
595 if s != STATUS_OK {
596 return Err(CoreError::binder(s, "prepareTransaction:registerForegroundProcessObserver"));
597 }
598 unsafe { (vt.write_strong_binder)(in_ptr, obs_binder) };
599 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
600 let s = unsafe {
601 (vt.transact)(service.ptr, register_code, &mut in_ptr, &mut out_ptr, 0)
602 };
603 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
604 if s != STATUS_OK {
605 return Err(CoreError::binder(s, "transact:registerForegroundProcessObserver"));
606 }
607
608 let consumer = owned.try_clone()
611 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:fgproc_observer"))?;
612
613 FGPROC_READ_I32.store(vt.read_int32 as usize, Ordering::Relaxed);
618 FGPROC_IPROC_MODE.store(mode, Ordering::Relaxed);
619 FGPROC_FG_CODE.store(fgproc_code, Ordering::Relaxed);
620 FGPROC_PID.store(0, Ordering::Relaxed);
621 *fgproc_eventfd_guard() = Some(owned);
622
623 unsafe { (vt.set_thread_pool_max)(0) };
625 let join_fn = vt.join_thread_pool;
626 std::thread::spawn(move || unsafe { join_fn() });
627
628 let binder = Self { _lib: lib, vt, _class: am_class, service, tx_code: 0, legacy: false };
629 Ok((binder, consumer))
630 }
631
632 fn do_transact(&self) -> Result<OwnedParcel, CoreError> {
633 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
634 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut in_ptr) };
635 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
636 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
637 let s = unsafe {
638 (self.vt.transact)(self.service.ptr, self.tx_code, &mut in_ptr, &mut out_ptr, 0)
639 };
640 let out = OwnedParcel { ptr: out_ptr, delete: self.vt.parcel_delete };
641 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
642 Ok(out)
643 }
644
645 pub fn get_focused_package(&self) -> Result<Option<String>, CoreError> {
646 let out = self.do_transact()?;
647 let r = ParcelReader { vt: &self.vt, parcel: &out };
648 let ex = r.read_i32()?;
649 if ex != EX_NONE { return Err(CoreError::binder(ex, "getFocusedTask:exception")); }
650 let present = r.read_i32()?;
651 if present == 0 { return Ok(None); }
652 if self.legacy { parse_stack_info_body(&r) } else { parse_root_task_info_body(&r) }
653 }
654 }
655
656 const DISPLAY_SERVICE: &[u8] = b"display\0";
659 const DISPLAY_DESCRIPTOR: &[u8] = b"android.hardware.display.IDisplayManager\0";
660 const CALLBACK_DESCRIPTOR: &[u8] = b"android.hardware.display.IDisplayManagerCallback\0";
661 const POWER_SERVICE: &[u8] = b"power\0";
662
663 const TX_DISPLAY_REGISTER_CALLBACK: u32 = 4;
664
665 static DISP_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
668
669 fn disp_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
670 DISP_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
671 }
672
673 unsafe extern "C" fn disp_cb_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
674 unsafe extern "C" fn disp_cb_on_destroy(_: *mut c_void) {}
675 unsafe extern "C" fn disp_cb_on_transact(
676 _: *mut AIBinder, code: u32, _: *const AParcel, _: *mut AParcel,
677 ) -> BinderStatus {
678 if code == 1 {
679 if let Some(fd) = disp_eventfd_guard().as_ref() {
680 let val: u64 = 1;
681 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
682 }
683 }
684 STATUS_OK
685 }
686
687 pub struct DisplayManagerBinder {
688 _lib: DlHandle,
689 vt: Vtable,
690 display: OwnedBinder,
691 power: Option<OwnedBinder>,
692 is_interactive_tx: u32,
693 }
694 unsafe impl Send for DisplayManagerBinder {}
695
696 impl DisplayManagerBinder {
697 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), CoreError> {
698 let handle = unsafe {
699 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
700 };
701 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
702 let lib = DlHandle(handle);
703 let vt = load_vtable(handle)?;
704
705 let owned = unsafe {
709 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
710 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
711 OwnedFd::from_raw_fd(raw)
712 };
713
714 let raw_display = unsafe { (vt.get_service)(DISPLAY_SERVICE.as_ptr() as *const c_char) };
716 if raw_display.is_null() {
717 return Err(CoreError::binder(-1, "AServiceManager_getService:display"));
718 }
719 let display = OwnedBinder { ptr: raw_display, dec_strong: vt.dec_strong };
720
721 let cb_class = unsafe {
723 (vt.class_define)(
724 CALLBACK_DESCRIPTOR.as_ptr() as *const c_char,
725 disp_cb_on_create, disp_cb_on_destroy, disp_cb_on_transact,
726 )
727 };
728 if cb_class.is_null() {
729 return Err(CoreError::binder(-1, "AIBinder_Class_define:DisplayCallback"));
730 }
731
732 let cb_binder = unsafe { (vt.new_binder)(cb_class, std::ptr::null_mut()) };
733 if cb_binder.is_null() {
734 return Err(CoreError::binder(-1, "AIBinder_new:DisplayCallback"));
735 }
736
737 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
739 let s = unsafe { (vt.prepare_transaction)(display.ptr, &mut in_ptr) };
740 if s != STATUS_OK {
741 return Err(CoreError::binder(s, "prepareTransaction:registerCallback"));
742 }
743 unsafe { (vt.write_strong_binder)(in_ptr, cb_binder) };
744 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
745 let s = unsafe {
746 (vt.transact)(display.ptr, TX_DISPLAY_REGISTER_CALLBACK, &mut in_ptr, &mut out_ptr, 0)
747 };
748 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
749 if s != STATUS_OK {
750 return Err(CoreError::binder(s, "transact:registerCallback"));
751 }
752
753 let power = {
755 let raw = unsafe { (vt.get_service)(POWER_SERVICE.as_ptr() as *const c_char) };
756 if raw.is_null() { None } else { Some(OwnedBinder { ptr: raw, dec_strong: vt.dec_strong }) }
757 };
758
759 let is_interactive_tx = crate::dex::resolve_is_interactive_tx()
761 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_isInteractive not found"))?;
762
763 let efd_owned = owned.try_clone()
766 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:display"))
767 .and_then(|dup| unsafe {
768 crate::reactor::Fd::from_owned_raw_fd(dup.into_raw_fd(), "display.efd")
769 .map_err(|_| CoreError::binder(-1, "Fd::from_owned_raw_fd:display.efd"))
770 })?;
771
772 *disp_eventfd_guard() = Some(owned);
774
775 unsafe { (vt.set_thread_pool_max)(0) };
777 let join_fn = vt.join_thread_pool;
778 std::thread::spawn(move || unsafe { join_fn() });
779
780 Ok((Self { _lib: lib, vt, display, power, is_interactive_tx }, efd_owned))
781 }
782
783 pub fn is_interactive(&self) -> Result<bool, CoreError> {
784 let power = self.power.as_ref()
785 .ok_or_else(|| CoreError::binder(-1, "power:unavailable"))?;
786 let mut inp: *mut AParcel = std::ptr::null_mut();
787 let s = unsafe { (self.vt.prepare_transaction)(power.ptr, &mut inp) };
788 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:isInteractive")); }
789 let mut out: *mut AParcel = std::ptr::null_mut();
790 let s = unsafe {
791 (self.vt.transact)(power.ptr, self.is_interactive_tx, &mut inp, &mut out, 0)
792 };
793 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
794 if s != STATUS_OK { return Err(CoreError::binder(s, "transact:isInteractive")); }
795 let r = ParcelReader { vt: &self.vt, parcel: &out };
796 let ex = r.read_i32()?;
797 if ex != EX_NONE { return Err(CoreError::binder(ex, "isInteractive:exception")); }
798 if let Some(rb) = self.vt.read_bool {
799 let mut v = false;
800 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
801 if s != STATUS_OK { return Err(CoreError::binder(s, "readBool:isInteractive")); }
802 Ok(v)
803 } else {
804 Ok(r.read_i32()? != 0)
805 }
806 }
807 }
808
809 pub struct RawBinderService {
818 _lib: DlHandle,
819 vt: Vtable,
820 service: OwnedBinder,
821 }
822 unsafe impl Send for RawBinderService {}
823
824 impl RawBinderService {
825 pub fn open(service_name: &str) -> Result<Self, CoreError> {
827 use std::ffi::CString;
828 let handle = unsafe {
829 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
830 };
831 if handle.is_null() {
832 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
833 }
834 let lib = DlHandle(handle);
835 let vt = load_vtable(handle)?;
836 let cs = CString::new(service_name)
837 .map_err(|_| CoreError::binder(-1, "service_name:nul_byte"))?;
838 let raw = unsafe { (vt.get_service)(cs.as_ptr()) };
839 if raw.is_null() {
840 return Err(CoreError::binder(-1, "AServiceManager_getService:null"));
841 }
842 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
843 Ok(Self { _lib: lib, vt, service })
844 }
845
846 pub fn transact_bool(&self, code: u32) -> Result<bool, CoreError> {
848 let out = self.raw_noarg(code)?;
849 let r = ParcelReader { vt: &self.vt, parcel: &out };
850 let ex = r.read_i32()?;
851 if ex != EX_NONE { return Err(CoreError::binder(ex, "transact_bool:exception")); }
852 if let Some(rb) = self.vt.read_bool {
853 let mut v = false;
854 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
855 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readBool")); }
856 Ok(v)
857 } else {
858 Ok(r.read_i32()? != 0)
859 }
860 }
861
862 pub fn transact_i32(&self, code: u32, arg: i32) -> Result<(), CoreError> {
864 let mut inp: *mut AParcel = std::ptr::null_mut();
865 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
866 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
867 let s = unsafe { (self.vt.write_int32)(inp, arg) };
868 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeInt32")); }
869 let mut out: *mut AParcel = std::ptr::null_mut();
870 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
871 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
872 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
873 Ok(())
874 }
875
876 fn raw_noarg(&self, code: u32) -> Result<OwnedParcel, CoreError> {
877 let mut inp: *mut AParcel = std::ptr::null_mut();
878 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
879 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
880 let mut out: *mut AParcel = std::ptr::null_mut();
881 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
882 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
883 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
884 Ok(out)
885 }
886 }
887}
888
889#[cfg(target_os = "android")]
892pub use imp::{ActivityManagerBinder, DisplayManagerBinder, RawBinderService, TxCodes, last_foreground_pid, resolve_tx_codes};
893
894#[cfg(not(target_os = "android"))]
897pub struct ActivityManagerBinder;
898
899#[cfg(not(target_os = "android"))]
900impl ActivityManagerBinder {
901 pub fn open() -> Result<Self, crate::CoreError> {
902 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
903 }
904 pub fn open_with_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
905 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
906 }
907 pub fn open_with_fgproc_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
908 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
909 }
910 pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
911 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
912 }
913}
914
915#[cfg(not(target_os = "android"))]
916pub struct DisplayManagerBinder;
917
918#[cfg(not(target_os = "android"))]
919impl DisplayManagerBinder {
920 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), crate::CoreError> {
921 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
922 }
923 pub fn is_interactive(&self) -> Result<bool, crate::CoreError> {
924 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
925 }
926}
927
928#[cfg(not(target_os = "android"))]
929pub struct RawBinderService;
930
931#[cfg(not(target_os = "android"))]
932impl RawBinderService {
933 pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
934 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
935 }
936 pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
937 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
938 }
939 pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
940 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
941 }
942}
943
944#[cfg(not(target_os = "android"))]
945pub struct TxCodes { pub observer_code: u32, pub query_code: u32, pub api_mode: u8, pub fg_code: u32 }
946
947#[cfg(not(target_os = "android"))]
948pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
949 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
950}
951
952#[cfg(not(target_os = "android"))]
953pub fn last_foreground_pid() -> i32 {
954 0
955}