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 get_user_data: unsafe extern "C" fn(*const AIBinder) -> *mut c_void,
233 write_int32: unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus,
234 read_bool: Option<unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus>,
236 }
237
238 struct DlHandle(*mut c_void);
241 unsafe impl Send for DlHandle {}
242 impl Drop for DlHandle {
243 fn drop(&mut self) {
244 }
250 }
251
252 struct OwnedParcel { ptr: *mut AParcel, delete: unsafe extern "C" fn(*mut AParcel) }
253 impl Drop for OwnedParcel {
254 fn drop(&mut self) { if !self.ptr.is_null() { unsafe { (self.delete)(self.ptr) }; } }
255 }
256
257 struct OwnedBinder { ptr: *mut AIBinder, dec_strong: unsafe extern "C" fn(*mut AIBinder) }
258 unsafe impl Send for OwnedBinder {}
259 impl Drop for OwnedBinder {
260 fn drop(&mut self) { if !self.ptr.is_null() { unsafe { (self.dec_strong)(self.ptr) }; } }
261 }
262
263 macro_rules! dlsym_fn {
266 ($handle:expr, $name:literal, $ty:ty) => {{
267 let sym = unsafe {
268 libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char)
269 };
270 if sym.is_null() {
271 return Err(CoreError::binder(-1, concat!("dlsym:", $name)));
272 }
273 unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) }
274 }};
275 }
276
277 macro_rules! dlsym_opt {
278 ($handle:expr, $name:literal, $ty:ty) => {{
279 let sym = unsafe {
280 libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char)
281 };
282 if sym.is_null() { None }
283 else { Some(unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) }) }
284 }};
285 }
286
287 fn load_vtable(handle: *mut c_void) -> Result<Vtable, CoreError> {
288 Ok(Vtable {
289 get_service: dlsym_fn!(handle, "AServiceManager_getService",
290 unsafe extern "C" fn(*const c_char) -> *mut AIBinder),
291 class_define: dlsym_fn!(handle, "AIBinder_Class_define",
292 unsafe extern "C" fn(
293 *const c_char,
294 unsafe extern "C" fn(*mut c_void) -> *mut c_void,
295 unsafe extern "C" fn(*mut c_void),
296 unsafe extern "C" fn(*mut AIBinder, u32, *const AParcel, *mut AParcel) -> BinderStatus,
297 ) -> *mut AIBinder_Class),
298 associate_class: dlsym_fn!(handle, "AIBinder_associateClass",
299 unsafe extern "C" fn(*mut AIBinder, *mut AIBinder_Class) -> bool),
300 new_binder: dlsym_fn!(handle, "AIBinder_new",
301 unsafe extern "C" fn(*const AIBinder_Class, *mut c_void) -> *mut AIBinder),
302 prepare_transaction: dlsym_fn!(handle, "AIBinder_prepareTransaction",
303 unsafe extern "C" fn(*mut AIBinder, *mut *mut AParcel) -> BinderStatus),
304 transact: dlsym_fn!(handle, "AIBinder_transact",
305 unsafe extern "C" fn(*mut AIBinder, u32, *mut *mut AParcel, *mut *mut AParcel, u32) -> BinderStatus),
306 dec_strong: dlsym_fn!(handle, "AIBinder_decStrong",
307 unsafe extern "C" fn(*mut AIBinder)),
308 parcel_delete: dlsym_fn!(handle, "AParcel_delete",
309 unsafe extern "C" fn(*mut AParcel)),
310 read_int32: dlsym_fn!(handle, "AParcel_readInt32",
311 unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus),
312 read_string: dlsym_fn!(handle, "AParcel_readString",
313 unsafe extern "C" fn(*const AParcel, *mut c_void, StringAllocator) -> BinderStatus),
314 write_strong_binder: dlsym_fn!(handle, "AParcel_writeStrongBinder",
315 unsafe extern "C" fn(*mut AParcel, *mut AIBinder) -> BinderStatus),
316 set_thread_pool_max: dlsym_fn!(handle, "ABinderProcess_setThreadPoolMaxThreadCount",
317 unsafe extern "C" fn(u32)),
318 join_thread_pool: dlsym_fn!(handle, "ABinderProcess_joinThreadPool",
319 unsafe extern "C" fn()),
320 get_user_data: dlsym_fn!(handle, "AIBinder_getUserData",
321 unsafe extern "C" fn(*const AIBinder) -> *mut c_void),
322 write_int32: dlsym_fn!(handle, "AParcel_writeInt32",
323 unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus),
324 read_bool: dlsym_opt!(handle, "AParcel_readBool",
325 unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus),
326 })
327 }
328
329 struct ParcelReader<'a> { vt: &'a Vtable, parcel: &'a OwnedParcel }
332
333 impl<'a> ParcelReader<'a> {
334 fn read_i32(&self) -> Result<i32, CoreError> {
335 let mut v = 0i32;
336 let s = unsafe { (self.vt.read_int32)(self.parcel.ptr, &mut v) };
337 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readInt32")); }
338 Ok(v)
339 }
340 fn read_string(&self) -> Result<Option<String>, CoreError> {
341 let mut buf = StringBuf::new();
342 let s = unsafe {
343 (self.vt.read_string)(self.parcel.ptr, &mut buf as *mut StringBuf as *mut c_void, string_alloc)
344 };
345 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readString")); }
346 Ok(buf.finish())
347 }
348 fn skip_i32s(&self, n: usize) -> Result<(), CoreError> {
349 for _ in 0..n { self.read_i32()?; }
350 Ok(())
351 }
352 fn skip_int_array(&self) -> Result<(), CoreError> {
353 let count = self.read_i32()?.max(0) as usize;
354 self.skip_i32s(count)
355 }
356 fn read_first_package_from_names(&self) -> Result<Option<String>, CoreError> {
357 let count = self.read_i32()?.max(0) as usize;
358 let mut first: Option<String> = None;
359 for _ in 0..count {
360 let s = self.read_string()?;
361 if first.is_none() {
362 first = s.and_then(|c| c.split('/').next().map(str::to_owned));
363 }
364 }
365 Ok(first)
366 }
367 }
368
369 fn parse_stack_info_body(r: &ParcelReader<'_>) -> Result<Option<String>, CoreError> {
372 r.skip_i32s(5)?;
373 r.skip_int_array()?;
374 r.read_first_package_from_names()
375 }
376
377 fn parse_root_task_info_task(r: &ParcelReader<'_>) -> Result<(i32, Option<String>), CoreError> {
384 let scratch = r.read_i32()?;
385 if scratch != 0 { r.skip_i32s(4)?; }
386 r.skip_int_array()?; let pkg = r.read_first_package_from_names()?; let bounds_count = r.read_i32()?;
390 let n = if bounds_count < 0 { 0 } else { bounds_count as usize };
391 for _ in 0..n {
392 let entry = r.read_i32()?;
393 if entry != 0 { r.skip_i32s(4)?; }
394 }
395 r.skip_int_array()?; r.skip_i32s(2)?; r.skip_i32s(1)?; let task_id = r.read_i32()?;
399 Ok((task_id, pkg))
400 }
401
402 pub struct TxCodes {
405 pub observer_code: u32,
406 pub query_code: u32,
407 pub api_mode: u8, pub fg_code: u32,
409 }
410
411 pub fn resolve_tx_codes() -> Result<TxCodes, CoreError> {
412 let (obs, query, api, fg) = dex::resolve_tx_codes_from_dex()
413 .ok_or_else(|| CoreError::binder(-1, "tx_code_resolution:dex_parse_failed"))?;
414 Ok(TxCodes { observer_code: obs, query_code: query, api_mode: api, fg_code: fg })
415 }
416
417 pub struct ActivityManagerBinder {
420 _lib: DlHandle,
421 vt: Vtable,
422 _class: *mut AIBinder_Class,
423 service: OwnedBinder,
424 tx_code: u32,
425 legacy: bool,
426 }
427 unsafe impl Send for ActivityManagerBinder {}
428
429 impl ActivityManagerBinder {
430 fn open_inner(handle: *mut c_void) -> Result<(DlHandle, Vtable, *mut AIBinder_Class, OwnedBinder), CoreError> {
431 let lib = DlHandle(handle);
432 let vt = load_vtable(handle)?;
433
434 let am_class = unsafe {
435 (vt.class_define)(
436 AM_DESCRIPTOR.as_ptr() as *const c_char,
437 am_on_create, am_on_destroy, am_on_transact,
438 )
439 };
440 if am_class.is_null() { return Err(CoreError::binder(-1, "AIBinder_Class_define:AM")); }
441
442 let raw = unsafe { (vt.get_service)(ACTIVITY_SERVICE.as_ptr() as *const c_char) };
443 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:activity")); }
444 unsafe { (vt.associate_class)(raw, am_class) };
445
446 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
447 Ok((lib, vt, am_class, service))
448 }
449
450 fn dlopen_libbinder() -> Result<*mut c_void, CoreError> {
451 use std::os::raw::c_char;
452 let handle = unsafe {
453 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
454 };
455 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
456 Ok(handle)
457 }
458
459 pub fn open() -> Result<Self, CoreError> {
462 let handle = Self::dlopen_libbinder()?;
463 let (lib, vt, class, service) = Self::open_inner(handle)?;
464 let codes = resolve_tx_codes()?;
465 let legacy = codes.api_mode == 2;
466 Ok(Self { _lib: lib, vt, _class: class, service, tx_code: codes.query_code, legacy })
467 }
468
469 pub fn open_with_observer() -> Result<(Self, OwnedFd), CoreError> {
478 let handle = Self::dlopen_libbinder()?;
479 let (lib, vt, am_class, service) = Self::open_inner(handle)?;
480 let codes = resolve_tx_codes()?;
481 let legacy = codes.api_mode == 2;
482
483 let owned = unsafe {
486 let raw = libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC);
487 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
488 OwnedFd::from_raw_fd(raw)
489 };
490
491 let obs_class = unsafe {
493 (vt.class_define)(
494 OBS_DESCRIPTOR.as_ptr() as *const c_char,
495 obs_on_create, obs_on_destroy, obs_on_transact,
496 )
497 };
498 if obs_class.is_null() {
499 return Err(CoreError::binder(-1, "AIBinder_Class_define:Observer"));
500 }
501
502 let obs_binder = unsafe { (vt.new_binder)(obs_class, std::ptr::null_mut()) };
504 if obs_binder.is_null() {
505 return Err(CoreError::binder(-1, "AIBinder_new:Observer"));
506 }
507 unsafe { (vt.associate_class)(obs_binder, obs_class) };
508
509 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
511 let s = unsafe { (vt.prepare_transaction)(service.ptr, &mut in_ptr) };
512 if s != STATUS_OK {
513 return Err(CoreError::binder(s, "prepareTransaction:registerObserver"));
514 }
515 unsafe { (vt.write_strong_binder)(in_ptr, obs_binder) };
516 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
517 let s = unsafe {
518 (vt.transact)(service.ptr, codes.observer_code, &mut in_ptr, &mut out_ptr, 0)
519 };
520 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
521 if s != STATUS_OK {
522 return Err(CoreError::binder(s, "transact:registerProcessObserver"));
523 }
524
525 let consumer = owned.try_clone()
528 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:observer"))?;
529
530 OBS_FG_CODE.store(codes.fg_code, Ordering::Relaxed);
532 *obs_eventfd_guard() = Some(owned);
533
534 unsafe { (vt.set_thread_pool_max)(0) };
536 let join_fn = vt.join_thread_pool;
537 std::thread::spawn(move || unsafe { join_fn() });
538
539 let binder = Self { _lib: lib, vt, _class: am_class, service, tx_code: codes.query_code, legacy };
540 Ok((binder, consumer))
541 }
542
543 pub fn open_with_fgproc_observer() -> Result<(Self, OwnedFd), CoreError> {
567 let handle = Self::dlopen_libbinder()?;
568 let (lib, vt, am_class, service) = Self::open_inner(handle)?;
569
570 let (register_code, fgproc_code, mode, descriptor): (u32, u32, u32, &[u8]) =
575 match crate::dex::resolve_fgproc_codes() {
576 Some((r, c)) => (r, c, 0, FGPROC_DESCRIPTOR),
577 None => match crate::dex::resolve_fgproc_codes_fallback() {
578 Some((r, c)) => (r, c, 1, OBS_DESCRIPTOR),
579 None => {
580 return Err(CoreError::binder(-1, "tx_code_resolution:fgproc_dex_parse_failed"));
581 }
582 },
583 };
584
585 let owned = unsafe {
588 let raw = libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC);
589 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
590 OwnedFd::from_raw_fd(raw)
591 };
592
593 let obs_class = unsafe {
596 (vt.class_define)(
597 descriptor.as_ptr() as *const c_char,
598 fgproc_on_create, fgproc_on_destroy, fgproc_on_transact,
599 )
600 };
601 if obs_class.is_null() {
602 return Err(CoreError::binder(-1, "AIBinder_Class_define:FGProcessObserver"));
603 }
604
605 let obs_binder = unsafe { (vt.new_binder)(obs_class, std::ptr::null_mut()) };
607 if obs_binder.is_null() {
608 return Err(CoreError::binder(-1, "AIBinder_new:FGProcessObserver"));
609 }
610 unsafe { (vt.associate_class)(obs_binder, obs_class) };
611
612 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
615 let s = unsafe { (vt.prepare_transaction)(service.ptr, &mut in_ptr) };
616 if s != STATUS_OK {
617 return Err(CoreError::binder(s, "prepareTransaction:registerForegroundProcessObserver"));
618 }
619 unsafe { (vt.write_strong_binder)(in_ptr, obs_binder) };
620 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
621 let s = unsafe {
622 (vt.transact)(service.ptr, register_code, &mut in_ptr, &mut out_ptr, 0)
623 };
624 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
625 if s != STATUS_OK {
626 return Err(CoreError::binder(s, "transact:registerForegroundProcessObserver"));
627 }
628
629 let consumer = owned.try_clone()
632 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:fgproc_observer"))?;
633
634 FGPROC_READ_I32.store(vt.read_int32 as usize, Ordering::Relaxed);
639 FGPROC_IPROC_MODE.store(mode, Ordering::Relaxed);
640 FGPROC_FG_CODE.store(fgproc_code, Ordering::Relaxed);
641 FGPROC_PID.store(0, Ordering::Relaxed);
642 *fgproc_eventfd_guard() = Some(owned);
643
644 unsafe { (vt.set_thread_pool_max)(0) };
646 let join_fn = vt.join_thread_pool;
647 std::thread::spawn(move || unsafe { join_fn() });
648
649 let binder = Self { _lib: lib, vt, _class: am_class, service, tx_code: 0, legacy: false };
650 Ok((binder, consumer))
651 }
652
653 fn do_transact(&self) -> Result<OwnedParcel, CoreError> {
654 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
655 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut in_ptr) };
656 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
657 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
658 let s = unsafe {
659 (self.vt.transact)(self.service.ptr, self.tx_code, &mut in_ptr, &mut out_ptr, 0)
660 };
661 let out = OwnedParcel { ptr: out_ptr, delete: self.vt.parcel_delete };
662 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
663 Ok(out)
664 }
665
666 pub fn get_focused_task(&self) -> Result<Option<(i32, Option<String>)>, CoreError> {
673 if self.legacy {
674 return Ok(None);
676 }
677 let out = self.do_transact()?;
678 let r = ParcelReader { vt: &self.vt, parcel: &out };
679 let ex = r.read_i32()?;
680 if ex != EX_NONE { return Err(CoreError::binder(ex, "getFocusedTask:exception")); }
681 let present = r.read_i32()?;
682 if present == 0 { return Ok(None); }
683 Ok(Some(parse_root_task_info_task(&r)?))
684 }
685
686 pub fn get_focused_package(&self) -> Result<Option<String>, CoreError> {
690 if self.legacy {
691 let out = self.do_transact()?;
692 let r = ParcelReader { vt: &self.vt, parcel: &out };
693 let ex = r.read_i32()?;
694 if ex != EX_NONE { return Err(CoreError::binder(ex, "getFocusedTask:exception")); }
695 let present = r.read_i32()?;
696 if present == 0 { return Ok(None); }
697 return parse_stack_info_body(&r);
698 }
699 Ok(self.get_focused_task()?.map(|(_, pkg)| pkg).flatten())
700 }
701
702 pub fn get_focused_task_id(&self) -> Result<Option<i32>, CoreError> {
706 Ok(self.get_focused_task()?.map(|(task_id, _)| task_id))
707 }
708 }
709
710 const DISPLAY_SERVICE: &[u8] = b"display\0";
713 const DISPLAY_DESCRIPTOR: &[u8] = b"android.hardware.display.IDisplayManager\0";
714 const CALLBACK_DESCRIPTOR: &[u8] = b"android.hardware.display.IDisplayManagerCallback\0";
715 const POWER_SERVICE: &[u8] = b"power\0";
716
717 const TX_DISPLAY_REGISTER_CALLBACK: u32 = 4;
718
719 static DISP_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
722
723 fn disp_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
724 DISP_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
725 }
726
727 unsafe extern "C" fn disp_cb_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
728 unsafe extern "C" fn disp_cb_on_destroy(_: *mut c_void) {}
729 unsafe extern "C" fn disp_cb_on_transact(
730 _: *mut AIBinder, code: u32, _: *const AParcel, _: *mut AParcel,
731 ) -> BinderStatus {
732 if code == 1 {
733 if let Some(fd) = disp_eventfd_guard().as_ref() {
734 let val: u64 = 1;
735 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
736 }
737 }
738 STATUS_OK
739 }
740
741 pub struct DisplayManagerBinder {
742 _lib: DlHandle,
743 vt: Vtable,
744 display: OwnedBinder,
745 power: Option<OwnedBinder>,
746 is_interactive_tx: u32,
747 }
748 unsafe impl Send for DisplayManagerBinder {}
749
750 impl DisplayManagerBinder {
751 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), CoreError> {
752 let handle = unsafe {
753 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
754 };
755 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
756 let lib = DlHandle(handle);
757 let vt = load_vtable(handle)?;
758
759 let owned = unsafe {
763 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
764 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
765 OwnedFd::from_raw_fd(raw)
766 };
767
768 let raw_display = unsafe { (vt.get_service)(DISPLAY_SERVICE.as_ptr() as *const c_char) };
770 if raw_display.is_null() {
771 return Err(CoreError::binder(-1, "AServiceManager_getService:display"));
772 }
773 let display = OwnedBinder { ptr: raw_display, dec_strong: vt.dec_strong };
774
775 let cb_class = unsafe {
777 (vt.class_define)(
778 CALLBACK_DESCRIPTOR.as_ptr() as *const c_char,
779 disp_cb_on_create, disp_cb_on_destroy, disp_cb_on_transact,
780 )
781 };
782 if cb_class.is_null() {
783 return Err(CoreError::binder(-1, "AIBinder_Class_define:DisplayCallback"));
784 }
785
786 let cb_binder = unsafe { (vt.new_binder)(cb_class, std::ptr::null_mut()) };
787 if cb_binder.is_null() {
788 return Err(CoreError::binder(-1, "AIBinder_new:DisplayCallback"));
789 }
790
791 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
793 let s = unsafe { (vt.prepare_transaction)(display.ptr, &mut in_ptr) };
794 if s != STATUS_OK {
795 return Err(CoreError::binder(s, "prepareTransaction:registerCallback"));
796 }
797 unsafe { (vt.write_strong_binder)(in_ptr, cb_binder) };
798 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
799 let s = unsafe {
800 (vt.transact)(display.ptr, TX_DISPLAY_REGISTER_CALLBACK, &mut in_ptr, &mut out_ptr, 0)
801 };
802 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
803 if s != STATUS_OK {
804 return Err(CoreError::binder(s, "transact:registerCallback"));
805 }
806
807 let power = {
809 let raw = unsafe { (vt.get_service)(POWER_SERVICE.as_ptr() as *const c_char) };
810 if raw.is_null() { None } else { Some(OwnedBinder { ptr: raw, dec_strong: vt.dec_strong }) }
811 };
812
813 let is_interactive_tx = crate::dex::resolve_is_interactive_tx()
815 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_isInteractive not found"))?;
816
817 let efd_owned = owned.try_clone()
820 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:display"))
821 .and_then(|dup| unsafe {
822 crate::reactor::Fd::from_owned_raw_fd(dup.into_raw_fd(), "display.efd")
823 .map_err(|_| CoreError::binder(-1, "Fd::from_owned_raw_fd:display.efd"))
824 })?;
825
826 *disp_eventfd_guard() = Some(owned);
828
829 unsafe { (vt.set_thread_pool_max)(0) };
831 let join_fn = vt.join_thread_pool;
832 std::thread::spawn(move || unsafe { join_fn() });
833
834 Ok((Self { _lib: lib, vt, display, power, is_interactive_tx }, efd_owned))
835 }
836
837 pub fn is_interactive(&self) -> Result<bool, CoreError> {
838 let power = self.power.as_ref()
839 .ok_or_else(|| CoreError::binder(-1, "power:unavailable"))?;
840 let mut inp: *mut AParcel = std::ptr::null_mut();
841 let s = unsafe { (self.vt.prepare_transaction)(power.ptr, &mut inp) };
842 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:isInteractive")); }
843 let mut out: *mut AParcel = std::ptr::null_mut();
844 let s = unsafe {
845 (self.vt.transact)(power.ptr, self.is_interactive_tx, &mut inp, &mut out, 0)
846 };
847 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
848 if s != STATUS_OK { return Err(CoreError::binder(s, "transact:isInteractive")); }
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, "isInteractive: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, "readBool:isInteractive")); }
856 Ok(v)
857 } else {
858 Ok(r.read_i32()? != 0)
859 }
860 }
861 }
862
863 const WINDOW_SERVICE: &[u8] = b"window\0";
866 const WM_DESCRIPTOR: &[u8] = b"android.view.IWindowManager\0";
867 const FPS_DESCRIPTOR: &[u8] = b"android.window.ITaskFpsCallback\0";
868 static FPS_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
873 static FPS_VALUE: AtomicU32 = AtomicU32::new(0);
874 static FPS_CODE: AtomicU32 = AtomicU32::new(0);
875 static FPS_READ_I32: AtomicUsize = AtomicUsize::new(0);
876
877 fn fps_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
878 FPS_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
879 }
880
881 unsafe extern "C" fn wm_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
885 unsafe extern "C" fn wm_on_destroy(_: *mut c_void) {}
886 unsafe extern "C" fn wm_on_transact(
887 _: *mut AIBinder, _: u32, _: *const AParcel, _: *mut AParcel,
888 ) -> BinderStatus { STATUS_OK }
889
890 unsafe extern "C" fn fps_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
891 unsafe extern "C" fn fps_on_destroy(_: *mut c_void) {}
892 unsafe extern "C" fn fps_on_transact(
893 _: *mut AIBinder, code: u32, in_parcel: *const AParcel, _: *mut AParcel,
894 ) -> BinderStatus {
895 if code != FPS_CODE.load(Ordering::Relaxed) {
896 return STATUS_UNKNOWN_TRANSACTION;
897 }
898 let read_addr = FPS_READ_I32.load(Ordering::Relaxed);
901 if read_addr != 0 {
902 let read_fn: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus =
903 unsafe { std::mem::transmute(read_addr) };
904 let mut bits: i32 = 0;
905 if unsafe { read_fn(in_parcel, &mut bits) } == STATUS_OK {
906 FPS_VALUE.store(bits as u32, Ordering::Relaxed);
909 if let Some(fd) = fps_eventfd_guard().as_ref() {
910 let val: u64 = 1;
911 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
912 }
913 }
914 }
915 STATUS_OK
916 }
917
918 pub struct FpsListener {
932 _lib: DlHandle,
933 vt: Vtable,
934 window: OwnedBinder,
935 cb_binder: *mut AIBinder,
936 _wm_class: *mut AIBinder_Class,
937 register_code: u32,
938 unregister_code: u32,
939 task_id: i32,
940 }
941 unsafe impl Send for FpsListener {}
942
943 impl FpsListener {
944 pub fn open() -> Result<(Self, OwnedFd), CoreError> {
950 let handle = unsafe {
951 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
952 };
953 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
954 let lib = DlHandle(handle);
955 let vt = load_vtable(handle)?;
956
957 let (register_code, unregister_code, on_fps_code) =
958 crate::dex::resolve_fps_codes()
959 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_registerTaskFpsCallback not found"))?;
960
961 let window = {
962 let raw = unsafe { (vt.get_service)(WINDOW_SERVICE.as_ptr() as *const c_char) };
963 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:window")); }
964 OwnedBinder { ptr: raw, dec_strong: vt.dec_strong }
965 };
966
967 let wm_class = unsafe {
970 (vt.class_define)(
971 WM_DESCRIPTOR.as_ptr() as *const c_char,
972 wm_on_create, wm_on_destroy, wm_on_transact,
973 )
974 };
975 if wm_class.is_null() {
976 return Err(CoreError::binder(-1, "AIBinder_Class_define:IWindowManager"));
977 }
978 unsafe { (vt.associate_class)(window.ptr, wm_class) };
979
980 let cb_class = unsafe {
981 (vt.class_define)(
982 FPS_DESCRIPTOR.as_ptr() as *const c_char,
983 fps_on_create, fps_on_destroy, fps_on_transact,
984 )
985 };
986 if cb_class.is_null() {
987 return Err(CoreError::binder(-1, "AIBinder_Class_define:ITaskFpsCallback"));
988 }
989
990 let cb_binder = unsafe { (vt.new_binder)(cb_class, std::ptr::null_mut()) };
991 if cb_binder.is_null() {
992 return Err(CoreError::binder(-1, "AIBinder_new:ITaskFpsCallback"));
993 }
994 unsafe { (vt.associate_class)(cb_binder, cb_class) };
995
996 let owned = unsafe {
999 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
1000 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
1001 OwnedFd::from_raw_fd(raw)
1002 };
1003
1004 let consumer = owned.try_clone()
1005 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:fps"))?;
1006
1007 FPS_READ_I32.store(vt.read_int32 as usize, Ordering::Relaxed);
1010 FPS_CODE.store(on_fps_code, Ordering::Relaxed);
1011 FPS_VALUE.store(0, Ordering::Relaxed);
1012 *fps_eventfd_guard() = Some(owned);
1013
1014 unsafe { (vt.set_thread_pool_max)(0) };
1015 let join_fn = vt.join_thread_pool;
1016 std::thread::spawn(move || unsafe { join_fn() });
1017
1018 Ok((Self {
1019 _lib: lib, vt, window, cb_binder, _wm_class: wm_class,
1020 register_code, unregister_code, task_id: -1,
1021 }, consumer))
1022 }
1023
1024 pub fn register(&mut self, task_id: i32) -> Result<(), CoreError> {
1028 if self.task_id == task_id {
1029 return Ok(());
1030 }
1031 if self.task_id >= 0 {
1032 let _ = self.unregister();
1033 }
1034
1035 let mut inp: *mut AParcel = std::ptr::null_mut();
1036 let s = unsafe { (self.vt.prepare_transaction)(self.window.ptr, &mut inp) };
1037 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:registerTaskFpsCallback")); }
1038 let s = unsafe { (self.vt.write_int32)(inp, task_id) };
1039 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeInt32:taskId")); }
1040 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1041 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1042 let mut out: *mut AParcel = std::ptr::null_mut();
1043 let s = unsafe {
1044 (self.vt.transact)(self.window.ptr, self.register_code, &mut inp, &mut out, 0)
1045 };
1046 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1047 if s != STATUS_OK {
1048 return Err(CoreError::binder(s, "transact:registerTaskFpsCallback"));
1049 }
1050 self.task_id = task_id;
1051 Ok(())
1052 }
1053
1054 pub fn unregister(&mut self) -> Result<(), CoreError> {
1057 if self.task_id < 0 {
1058 return Ok(());
1059 }
1060 let mut inp: *mut AParcel = std::ptr::null_mut();
1061 let s = unsafe { (self.vt.prepare_transaction)(self.window.ptr, &mut inp) };
1062 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:unregisterTaskFpsCallback")); }
1063 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1064 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1065 let mut out: *mut AParcel = std::ptr::null_mut();
1066 let s = unsafe {
1067 (self.vt.transact)(self.window.ptr, self.unregister_code, &mut inp, &mut out, 0)
1068 };
1069 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1070 if s != STATUS_OK {
1071 return Err(CoreError::binder(s, "transact:unregisterTaskFpsCallback"));
1072 }
1073 self.task_id = -1;
1074 Ok(())
1075 }
1076
1077 pub fn last_fps(&self) -> Option<f32> {
1081 let bits = FPS_VALUE.load(Ordering::Relaxed);
1082 if bits == 0 { None } else { Some(f32::from_bits(bits)) }
1083 }
1084
1085 pub fn task_id(&self) -> Option<i32> {
1087 (self.task_id >= 0).then_some(self.task_id)
1088 }
1089 }
1090
1091 const TASK_SERVICE: &[u8] = b"activity_task\0";
1094 const ATM_DESCRIPTOR: &[u8] = b"android.app.IActivityTaskManager\0";
1095 const TASK_STACK_DESCRIPTOR: &[u8] = b"android.app.ITaskStackListener\0";
1096
1097 unsafe extern "C" fn atm_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
1101 unsafe extern "C" fn atm_on_destroy(_: *mut c_void) {}
1102 unsafe extern "C" fn atm_on_transact(
1103 _: *mut AIBinder, _: u32, _: *const AParcel, _: *mut AParcel,
1104 ) -> BinderStatus { STATUS_OK }
1105
1106 static GET_USER_DATA: std::sync::Mutex<Option<unsafe extern "C" fn(*const AIBinder) -> *mut c_void>> =
1122 std::sync::Mutex::new(None);
1123
1124 unsafe extern "C" fn task_stack_on_create(userdata: *mut c_void) -> *mut c_void { userdata }
1125 unsafe extern "C" fn task_stack_on_destroy(userdata: *mut c_void) {
1126 if !userdata.is_null() {
1127 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1128 }
1129 }
1130 unsafe extern "C" fn task_stack_on_transact(
1131 binder: *mut AIBinder, _code: u32, _in_parcel: *const AParcel, _reply: *mut AParcel,
1132 ) -> BinderStatus {
1133 let get_user_data = GET_USER_DATA
1134 .lock()
1135 .unwrap_or_else(|p| p.into_inner());
1136 if let Some(get_user_data) = *get_user_data {
1137 let userdata = unsafe { get_user_data(binder) };
1138 if !userdata.is_null() {
1139 let efd = userdata as *mut OwnedFd;
1140 let val: u64 = 1;
1141 unsafe { libc::write((*efd).as_raw_fd(), &val as *const u64 as *const c_void, 8) };
1142 }
1143 }
1144 STATUS_OK
1145 }
1146
1147 pub struct TaskStackListener {
1167 _lib: DlHandle,
1168 vt: Vtable,
1169 service: OwnedBinder,
1170 cb_binder: *mut AIBinder,
1171 _atm_class: *mut AIBinder_Class,
1172 register_code: u32,
1173 unregister_code: u32,
1174 }
1175 unsafe impl Send for TaskStackListener {}
1176
1177 impl TaskStackListener {
1178 pub fn open() -> Result<(Self, OwnedFd), CoreError> {
1182 let handle = unsafe {
1183 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
1184 };
1185 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
1186 let lib = DlHandle(handle);
1187 let vt = load_vtable(handle)?;
1188
1189 let (register_code, unregister_code) =
1190 crate::dex::resolve_task_stack_codes()
1191 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_registerTaskStackListener not found"))?;
1192
1193 let service = {
1194 let raw = unsafe { (vt.get_service)(TASK_SERVICE.as_ptr() as *const c_char) };
1195 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:activity_task")); }
1196 OwnedBinder { ptr: raw, dec_strong: vt.dec_strong }
1197 };
1198
1199 let atm_class = unsafe {
1202 (vt.class_define)(
1203 ATM_DESCRIPTOR.as_ptr() as *const c_char,
1204 atm_on_create, atm_on_destroy, atm_on_transact,
1205 )
1206 };
1207 if atm_class.is_null() {
1208 return Err(CoreError::binder(-1, "AIBinder_Class_define:IActivityTaskManager"));
1209 }
1210 unsafe { (vt.associate_class)(service.ptr, atm_class) };
1211
1212 let cb_class = unsafe {
1213 (vt.class_define)(
1214 TASK_STACK_DESCRIPTOR.as_ptr() as *const c_char,
1215 task_stack_on_create, task_stack_on_destroy, task_stack_on_transact,
1216 )
1217 };
1218 if cb_class.is_null() {
1219 return Err(CoreError::binder(-1, "AIBinder_Class_define:ITaskStackListener"));
1220 }
1221
1222 let owned = unsafe {
1227 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
1228 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
1229 OwnedFd::from_raw_fd(raw)
1230 };
1231
1232 let consumer = owned.try_clone()
1233 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:task_stack"))?;
1234
1235 let userdata = Box::into_raw(Box::new(owned)) as *mut c_void;
1236 let cb_binder = unsafe { (vt.new_binder)(cb_class, userdata) };
1237 if cb_binder.is_null() {
1238 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1240 return Err(CoreError::binder(-1, "AIBinder_new:ITaskStackListener"));
1241 }
1242 unsafe { (vt.associate_class)(cb_binder, cb_class) };
1243
1244 *GET_USER_DATA.lock().unwrap_or_else(|p| p.into_inner()) = Some(vt.get_user_data);
1247
1248 unsafe { (vt.set_thread_pool_max)(0) };
1249 let join_fn = vt.join_thread_pool;
1250 std::thread::spawn(move || unsafe { join_fn() });
1251
1252 Ok((Self {
1253 _lib: lib, vt, service, cb_binder, _atm_class: atm_class,
1254 register_code, unregister_code,
1255 }, consumer))
1256 }
1257
1258 pub fn register(&self) -> Result<(), CoreError> {
1262 let mut inp: *mut AParcel = std::ptr::null_mut();
1263 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1264 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:registerTaskStackListener")); }
1265 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1266 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1267 let mut out: *mut AParcel = std::ptr::null_mut();
1268 let s = unsafe {
1269 (self.vt.transact)(self.service.ptr, self.register_code, &mut inp, &mut out, 0)
1270 };
1271 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1272 if s != STATUS_OK {
1273 return Err(CoreError::binder(s, "transact:registerTaskStackListener"));
1274 }
1275 Ok(())
1276 }
1277
1278 pub fn unregister(&self) -> Result<(), CoreError> {
1282 let mut inp: *mut AParcel = std::ptr::null_mut();
1283 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1284 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:unregisterTaskStackListener")); }
1285 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1286 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1287 let mut out: *mut AParcel = std::ptr::null_mut();
1288 let s = unsafe {
1289 (self.vt.transact)(self.service.ptr, self.unregister_code, &mut inp, &mut out, 0)
1290 };
1291 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1292 if s != STATUS_OK {
1293 return Err(CoreError::binder(s, "transact:unregisterTaskStackListener"));
1294 }
1295 Ok(())
1296 }
1297 }
1298
1299 pub struct RawBinderService {
1308 _lib: DlHandle,
1309 vt: Vtable,
1310 service: OwnedBinder,
1311 }
1312 unsafe impl Send for RawBinderService {}
1313
1314 impl RawBinderService {
1315 pub fn open(service_name: &str) -> Result<Self, CoreError> {
1317 use std::ffi::CString;
1318 let handle = unsafe {
1319 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
1320 };
1321 if handle.is_null() {
1322 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
1323 }
1324 let lib = DlHandle(handle);
1325 let vt = load_vtable(handle)?;
1326 let cs = CString::new(service_name)
1327 .map_err(|_| CoreError::binder(-1, "service_name:nul_byte"))?;
1328 let raw = unsafe { (vt.get_service)(cs.as_ptr()) };
1329 if raw.is_null() {
1330 return Err(CoreError::binder(-1, "AServiceManager_getService:null"));
1331 }
1332 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
1333 Ok(Self { _lib: lib, vt, service })
1334 }
1335
1336 pub fn transact_bool(&self, code: u32) -> Result<bool, CoreError> {
1338 let out = self.raw_noarg(code)?;
1339 let r = ParcelReader { vt: &self.vt, parcel: &out };
1340 let ex = r.read_i32()?;
1341 if ex != EX_NONE { return Err(CoreError::binder(ex, "transact_bool:exception")); }
1342 if let Some(rb) = self.vt.read_bool {
1343 let mut v = false;
1344 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
1345 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readBool")); }
1346 Ok(v)
1347 } else {
1348 Ok(r.read_i32()? != 0)
1349 }
1350 }
1351
1352 pub fn transact_i32(&self, code: u32, arg: i32) -> Result<(), CoreError> {
1354 let mut inp: *mut AParcel = std::ptr::null_mut();
1355 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1356 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
1357 let s = unsafe { (self.vt.write_int32)(inp, arg) };
1358 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeInt32")); }
1359 let mut out: *mut AParcel = std::ptr::null_mut();
1360 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
1361 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1362 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
1363 Ok(())
1364 }
1365
1366 fn raw_noarg(&self, code: u32) -> Result<OwnedParcel, CoreError> {
1367 let mut inp: *mut AParcel = std::ptr::null_mut();
1368 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1369 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
1370 let mut out: *mut AParcel = std::ptr::null_mut();
1371 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
1372 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
1373 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
1374 Ok(out)
1375 }
1376 }
1377}
1378
1379#[cfg(target_os = "android")]
1382pub use imp::{ActivityManagerBinder, DisplayManagerBinder, FpsListener, RawBinderService, TaskStackListener, TxCodes, last_foreground_pid, resolve_tx_codes};
1383
1384#[cfg(not(target_os = "android"))]
1387pub struct ActivityManagerBinder;
1388
1389#[cfg(not(target_os = "android"))]
1390impl ActivityManagerBinder {
1391 pub fn open() -> Result<Self, crate::CoreError> {
1392 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1393 }
1394 pub fn open_with_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1395 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1396 }
1397 pub fn open_with_fgproc_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1398 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1399 }
1400 pub fn get_focused_task(&self) -> Result<Option<(i32, Option<String>)>, crate::CoreError> {
1401 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1402 }
1403 pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
1404 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1405 }
1406 pub fn get_focused_task_id(&self) -> Result<Option<i32>, crate::CoreError> {
1407 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1408 }
1409}
1410
1411#[cfg(not(target_os = "android"))]
1412pub struct DisplayManagerBinder;
1413
1414#[cfg(not(target_os = "android"))]
1415impl DisplayManagerBinder {
1416 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), crate::CoreError> {
1417 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1418 }
1419 pub fn is_interactive(&self) -> Result<bool, crate::CoreError> {
1420 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1421 }
1422}
1423
1424#[cfg(not(target_os = "android"))]
1425pub struct RawBinderService;
1426
1427#[cfg(not(target_os = "android"))]
1428impl RawBinderService {
1429 pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
1430 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1431 }
1432 pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
1433 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1434 }
1435 pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
1436 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1437 }
1438}
1439
1440#[cfg(not(target_os = "android"))]
1441pub struct FpsListener;
1442
1443#[cfg(not(target_os = "android"))]
1444impl FpsListener {
1445 pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1446 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1447 }
1448 pub fn register(&mut self, _task_id: i32) -> Result<(), crate::CoreError> {
1449 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1450 }
1451 pub fn unregister(&mut self) -> Result<(), crate::CoreError> {
1452 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1453 }
1454 pub fn last_fps(&self) -> Option<f32> {
1455 None
1456 }
1457 pub fn task_id(&self) -> Option<i32> {
1458 None
1459 }
1460}
1461
1462#[cfg(not(target_os = "android"))]
1463pub struct TaskStackListener;
1464
1465#[cfg(not(target_os = "android"))]
1466impl TaskStackListener {
1467 pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1468 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1469 }
1470 pub fn register(&self) -> Result<(), crate::CoreError> {
1471 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1472 }
1473 pub fn unregister(&self) -> Result<(), crate::CoreError> {
1474 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1475 }
1476}
1477
1478#[cfg(not(target_os = "android"))]
1479pub struct TxCodes { pub observer_code: u32, pub query_code: u32, pub api_mode: u8, pub fg_code: u32 }
1480
1481#[cfg(not(target_os = "android"))]
1482pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
1483 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1484}
1485
1486#[cfg(not(target_os = "android"))]
1487pub fn last_foreground_pid() -> i32 {
1488 0
1489}