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_VALUE: AtomicU32 = AtomicU32::new(0);
875 static FPS_CODE: AtomicU32 = AtomicU32::new(0);
876 static FPS_READ_I32: AtomicUsize = AtomicUsize::new(0);
877
878 unsafe extern "C" fn wm_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
882 unsafe extern "C" fn wm_on_destroy(_: *mut c_void) {}
883 unsafe extern "C" fn wm_on_transact(
884 _: *mut AIBinder, _: u32, _: *const AParcel, _: *mut AParcel,
885 ) -> BinderStatus { STATUS_OK }
886
887 unsafe extern "C" fn fps_on_create(userdata: *mut c_void) -> *mut c_void { userdata }
893 unsafe extern "C" fn fps_on_destroy(userdata: *mut c_void) {
894 if !userdata.is_null() {
895 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
896 }
897 }
898 unsafe extern "C" fn fps_on_transact(
899 binder: *mut AIBinder, code: u32, in_parcel: *const AParcel, _: *mut AParcel,
900 ) -> BinderStatus {
901 if code != FPS_CODE.load(Ordering::Relaxed) {
902 return STATUS_UNKNOWN_TRANSACTION;
903 }
904 let read_addr = FPS_READ_I32.load(Ordering::Relaxed);
907 if read_addr != 0 {
908 let read_fn: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus =
909 unsafe { std::mem::transmute(read_addr) };
910 let mut bits: i32 = 0;
911 if unsafe { read_fn(in_parcel, &mut bits) } == STATUS_OK {
912 FPS_VALUE.store(bits as u32, Ordering::Relaxed);
915 let get_user_data = GET_USER_DATA
921 .lock()
922 .unwrap_or_else(|p| p.into_inner());
923 if let Some(get_user_data) = *get_user_data {
924 let userdata = unsafe { get_user_data(binder) };
925 if !userdata.is_null() {
926 let efd = userdata as *mut OwnedFd;
927 let val: u64 = 1;
928 unsafe {
929 libc::write((*efd).as_raw_fd(), &val as *const u64 as *const c_void, 8)
930 };
931 }
932 }
933 }
934 }
935 STATUS_OK
936 }
937
938 pub struct FpsListener {
952 _lib: DlHandle,
953 vt: Vtable,
954 window: OwnedBinder,
955 cb_binder: *mut AIBinder,
956 _wm_class: *mut AIBinder_Class,
957 register_code: u32,
958 unregister_code: u32,
959 task_id: i32,
960 }
961 unsafe impl Send for FpsListener {}
962
963 impl FpsListener {
964 pub fn open() -> Result<(Self, OwnedFd), CoreError> {
970 let handle = unsafe {
971 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
972 };
973 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
974 let lib = DlHandle(handle);
975 let vt = load_vtable(handle)?;
976
977 let (register_code, unregister_code, on_fps_code) =
978 crate::dex::resolve_fps_codes()
979 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_registerTaskFpsCallback not found"))?;
980
981 let window = {
982 let raw = unsafe { (vt.get_service)(WINDOW_SERVICE.as_ptr() as *const c_char) };
983 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:window")); }
984 OwnedBinder { ptr: raw, dec_strong: vt.dec_strong }
985 };
986
987 let wm_class = unsafe {
990 (vt.class_define)(
991 WM_DESCRIPTOR.as_ptr() as *const c_char,
992 wm_on_create, wm_on_destroy, wm_on_transact,
993 )
994 };
995 if wm_class.is_null() {
996 return Err(CoreError::binder(-1, "AIBinder_Class_define:IWindowManager"));
997 }
998 unsafe { (vt.associate_class)(window.ptr, wm_class) };
999
1000 let cb_class = unsafe {
1001 (vt.class_define)(
1002 FPS_DESCRIPTOR.as_ptr() as *const c_char,
1003 fps_on_create, fps_on_destroy, fps_on_transact,
1004 )
1005 };
1006 if cb_class.is_null() {
1007 return Err(CoreError::binder(-1, "AIBinder_Class_define:ITaskFpsCallback"));
1008 }
1009
1010 let owned = unsafe {
1015 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
1016 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
1017 OwnedFd::from_raw_fd(raw)
1018 };
1019
1020 let consumer = owned.try_clone()
1021 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:fps"))?;
1022
1023 let userdata = Box::into_raw(Box::new(owned)) as *mut c_void;
1024 let cb_binder = unsafe { (vt.new_binder)(cb_class, userdata) };
1025 if cb_binder.is_null() {
1026 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1028 return Err(CoreError::binder(-1, "AIBinder_new:ITaskFpsCallback"));
1029 }
1030 unsafe { (vt.associate_class)(cb_binder, cb_class) };
1031
1032 FPS_READ_I32.store(vt.read_int32 as usize, Ordering::Relaxed);
1035 FPS_CODE.store(on_fps_code, Ordering::Relaxed);
1036 FPS_VALUE.store(0, Ordering::Relaxed);
1037 *GET_USER_DATA.lock().unwrap_or_else(|p| p.into_inner()) = Some(vt.get_user_data);
1040
1041 unsafe { (vt.set_thread_pool_max)(0) };
1042 let join_fn = vt.join_thread_pool;
1043 std::thread::spawn(move || unsafe { join_fn() });
1044
1045 Ok((Self {
1046 _lib: lib, vt, window, cb_binder, _wm_class: wm_class,
1047 register_code, unregister_code, task_id: -1,
1048 }, consumer))
1049 }
1050
1051 pub fn register(&mut self, task_id: i32) -> Result<(), CoreError> {
1055 if self.task_id == task_id {
1056 return Ok(());
1057 }
1058 if self.task_id >= 0 {
1059 let _ = self.unregister();
1060 }
1061
1062 let mut inp: *mut AParcel = std::ptr::null_mut();
1063 let s = unsafe { (self.vt.prepare_transaction)(self.window.ptr, &mut inp) };
1064 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:registerTaskFpsCallback")); }
1065 let s = unsafe { (self.vt.write_int32)(inp, task_id) };
1066 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeInt32:taskId")); }
1067 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1068 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1069 let mut out: *mut AParcel = std::ptr::null_mut();
1070 let s = unsafe {
1071 (self.vt.transact)(self.window.ptr, self.register_code, &mut inp, &mut out, 0)
1072 };
1073 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1074 if s != STATUS_OK {
1075 return Err(CoreError::binder(s, "transact:registerTaskFpsCallback"));
1076 }
1077 self.task_id = task_id;
1078 Ok(())
1079 }
1080
1081 pub fn unregister(&mut self) -> Result<(), CoreError> {
1084 if self.task_id < 0 {
1085 return Ok(());
1086 }
1087 let mut inp: *mut AParcel = std::ptr::null_mut();
1088 let s = unsafe { (self.vt.prepare_transaction)(self.window.ptr, &mut inp) };
1089 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:unregisterTaskFpsCallback")); }
1090 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1091 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1092 let mut out: *mut AParcel = std::ptr::null_mut();
1093 let s = unsafe {
1094 (self.vt.transact)(self.window.ptr, self.unregister_code, &mut inp, &mut out, 0)
1095 };
1096 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1097 if s != STATUS_OK {
1098 return Err(CoreError::binder(s, "transact:unregisterTaskFpsCallback"));
1099 }
1100 self.task_id = -1;
1101 Ok(())
1102 }
1103
1104 pub fn last_fps(&self) -> Option<f32> {
1108 let bits = FPS_VALUE.load(Ordering::Relaxed);
1109 if bits == 0 { None } else { Some(f32::from_bits(bits)) }
1110 }
1111
1112 pub fn task_id(&self) -> Option<i32> {
1114 (self.task_id >= 0).then_some(self.task_id)
1115 }
1116 }
1117
1118 impl Drop for FpsListener {
1119 fn drop(&mut self) {
1127 let _ = self.unregister();
1128 }
1129 }
1130
1131 const TASK_SERVICE: &[u8] = b"activity_task\0";
1134 const ATM_DESCRIPTOR: &[u8] = b"android.app.IActivityTaskManager\0";
1135 const TASK_STACK_DESCRIPTOR: &[u8] = b"android.app.ITaskStackListener\0";
1136
1137 unsafe extern "C" fn atm_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
1141 unsafe extern "C" fn atm_on_destroy(_: *mut c_void) {}
1142 unsafe extern "C" fn atm_on_transact(
1143 _: *mut AIBinder, _: u32, _: *const AParcel, _: *mut AParcel,
1144 ) -> BinderStatus { STATUS_OK }
1145
1146 static GET_USER_DATA: std::sync::Mutex<Option<unsafe extern "C" fn(*const AIBinder) -> *mut c_void>> =
1162 std::sync::Mutex::new(None);
1163
1164 unsafe extern "C" fn task_stack_on_create(userdata: *mut c_void) -> *mut c_void { userdata }
1165 unsafe extern "C" fn task_stack_on_destroy(userdata: *mut c_void) {
1166 if !userdata.is_null() {
1167 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1168 }
1169 }
1170 unsafe extern "C" fn task_stack_on_transact(
1171 binder: *mut AIBinder, _code: u32, _in_parcel: *const AParcel, _reply: *mut AParcel,
1172 ) -> BinderStatus {
1173 let get_user_data = GET_USER_DATA
1174 .lock()
1175 .unwrap_or_else(|p| p.into_inner());
1176 if let Some(get_user_data) = *get_user_data {
1177 let userdata = unsafe { get_user_data(binder) };
1178 if !userdata.is_null() {
1179 let efd = userdata as *mut OwnedFd;
1180 let val: u64 = 1;
1181 unsafe { libc::write((*efd).as_raw_fd(), &val as *const u64 as *const c_void, 8) };
1182 }
1183 }
1184 STATUS_OK
1185 }
1186
1187 pub struct TaskStackListener {
1207 _lib: DlHandle,
1208 vt: Vtable,
1209 service: OwnedBinder,
1210 cb_binder: *mut AIBinder,
1211 _atm_class: *mut AIBinder_Class,
1212 register_code: u32,
1213 unregister_code: u32,
1214 }
1215 unsafe impl Send for TaskStackListener {}
1216
1217 impl TaskStackListener {
1218 pub fn open() -> Result<(Self, OwnedFd), CoreError> {
1222 let handle = unsafe {
1223 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
1224 };
1225 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
1226 let lib = DlHandle(handle);
1227 let vt = load_vtable(handle)?;
1228
1229 let (register_code, unregister_code) =
1230 crate::dex::resolve_task_stack_codes()
1231 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_registerTaskStackListener not found"))?;
1232
1233 let service = {
1234 let raw = unsafe { (vt.get_service)(TASK_SERVICE.as_ptr() as *const c_char) };
1235 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:activity_task")); }
1236 OwnedBinder { ptr: raw, dec_strong: vt.dec_strong }
1237 };
1238
1239 let atm_class = unsafe {
1242 (vt.class_define)(
1243 ATM_DESCRIPTOR.as_ptr() as *const c_char,
1244 atm_on_create, atm_on_destroy, atm_on_transact,
1245 )
1246 };
1247 if atm_class.is_null() {
1248 return Err(CoreError::binder(-1, "AIBinder_Class_define:IActivityTaskManager"));
1249 }
1250 unsafe { (vt.associate_class)(service.ptr, atm_class) };
1251
1252 let cb_class = unsafe {
1253 (vt.class_define)(
1254 TASK_STACK_DESCRIPTOR.as_ptr() as *const c_char,
1255 task_stack_on_create, task_stack_on_destroy, task_stack_on_transact,
1256 )
1257 };
1258 if cb_class.is_null() {
1259 return Err(CoreError::binder(-1, "AIBinder_Class_define:ITaskStackListener"));
1260 }
1261
1262 let owned = unsafe {
1267 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
1268 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
1269 OwnedFd::from_raw_fd(raw)
1270 };
1271
1272 let consumer = owned.try_clone()
1273 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:task_stack"))?;
1274
1275 let userdata = Box::into_raw(Box::new(owned)) as *mut c_void;
1276 let cb_binder = unsafe { (vt.new_binder)(cb_class, userdata) };
1277 if cb_binder.is_null() {
1278 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1280 return Err(CoreError::binder(-1, "AIBinder_new:ITaskStackListener"));
1281 }
1282 unsafe { (vt.associate_class)(cb_binder, cb_class) };
1283
1284 *GET_USER_DATA.lock().unwrap_or_else(|p| p.into_inner()) = Some(vt.get_user_data);
1287
1288 unsafe { (vt.set_thread_pool_max)(0) };
1289 let join_fn = vt.join_thread_pool;
1290 std::thread::spawn(move || unsafe { join_fn() });
1291
1292 Ok((Self {
1293 _lib: lib, vt, service, cb_binder, _atm_class: atm_class,
1294 register_code, unregister_code,
1295 }, consumer))
1296 }
1297
1298 pub fn register(&self) -> Result<(), CoreError> {
1302 let mut inp: *mut AParcel = std::ptr::null_mut();
1303 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1304 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:registerTaskStackListener")); }
1305 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1306 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1307 let mut out: *mut AParcel = std::ptr::null_mut();
1308 let s = unsafe {
1309 (self.vt.transact)(self.service.ptr, self.register_code, &mut inp, &mut out, 0)
1310 };
1311 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1312 if s != STATUS_OK {
1313 return Err(CoreError::binder(s, "transact:registerTaskStackListener"));
1314 }
1315 Ok(())
1316 }
1317
1318 pub fn unregister(&self) -> Result<(), CoreError> {
1322 let mut inp: *mut AParcel = std::ptr::null_mut();
1323 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1324 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:unregisterTaskStackListener")); }
1325 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1326 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1327 let mut out: *mut AParcel = std::ptr::null_mut();
1328 let s = unsafe {
1329 (self.vt.transact)(self.service.ptr, self.unregister_code, &mut inp, &mut out, 0)
1330 };
1331 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1332 if s != STATUS_OK {
1333 return Err(CoreError::binder(s, "transact:unregisterTaskStackListener"));
1334 }
1335 Ok(())
1336 }
1337 }
1338
1339 impl Drop for TaskStackListener {
1340 fn drop(&mut self) {
1345 let _ = self.unregister();
1346 }
1347 }
1348
1349 pub struct RawBinderService {
1358 _lib: DlHandle,
1359 vt: Vtable,
1360 service: OwnedBinder,
1361 }
1362 unsafe impl Send for RawBinderService {}
1363
1364 impl RawBinderService {
1365 pub fn open(service_name: &str) -> Result<Self, CoreError> {
1367 use std::ffi::CString;
1368 let handle = unsafe {
1369 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
1370 };
1371 if handle.is_null() {
1372 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
1373 }
1374 let lib = DlHandle(handle);
1375 let vt = load_vtable(handle)?;
1376 let cs = CString::new(service_name)
1377 .map_err(|_| CoreError::binder(-1, "service_name:nul_byte"))?;
1378 let raw = unsafe { (vt.get_service)(cs.as_ptr()) };
1379 if raw.is_null() {
1380 return Err(CoreError::binder(-1, "AServiceManager_getService:null"));
1381 }
1382 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
1383 Ok(Self { _lib: lib, vt, service })
1384 }
1385
1386 pub fn transact_bool(&self, code: u32) -> Result<bool, CoreError> {
1388 let out = self.raw_noarg(code)?;
1389 let r = ParcelReader { vt: &self.vt, parcel: &out };
1390 let ex = r.read_i32()?;
1391 if ex != EX_NONE { return Err(CoreError::binder(ex, "transact_bool:exception")); }
1392 if let Some(rb) = self.vt.read_bool {
1393 let mut v = false;
1394 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
1395 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readBool")); }
1396 Ok(v)
1397 } else {
1398 Ok(r.read_i32()? != 0)
1399 }
1400 }
1401
1402 pub fn transact_i32(&self, code: u32, arg: i32) -> Result<(), CoreError> {
1404 let mut inp: *mut AParcel = std::ptr::null_mut();
1405 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1406 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
1407 let s = unsafe { (self.vt.write_int32)(inp, arg) };
1408 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeInt32")); }
1409 let mut out: *mut AParcel = std::ptr::null_mut();
1410 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
1411 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1412 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
1413 Ok(())
1414 }
1415
1416 fn raw_noarg(&self, code: u32) -> Result<OwnedParcel, CoreError> {
1417 let mut inp: *mut AParcel = std::ptr::null_mut();
1418 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1419 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
1420 let mut out: *mut AParcel = std::ptr::null_mut();
1421 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
1422 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
1423 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
1424 Ok(out)
1425 }
1426 }
1427}
1428
1429#[cfg(target_os = "android")]
1432pub use imp::{ActivityManagerBinder, DisplayManagerBinder, FpsListener, RawBinderService, TaskStackListener, TxCodes, last_foreground_pid, resolve_tx_codes};
1433
1434#[cfg(not(target_os = "android"))]
1437pub struct ActivityManagerBinder;
1438
1439#[cfg(not(target_os = "android"))]
1440impl ActivityManagerBinder {
1441 pub fn open() -> Result<Self, crate::CoreError> {
1442 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1443 }
1444 pub fn open_with_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1445 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1446 }
1447 pub fn open_with_fgproc_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1448 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1449 }
1450 pub fn get_focused_task(&self) -> Result<Option<(i32, Option<String>)>, crate::CoreError> {
1451 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1452 }
1453 pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
1454 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1455 }
1456 pub fn get_focused_task_id(&self) -> Result<Option<i32>, crate::CoreError> {
1457 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1458 }
1459}
1460
1461#[cfg(not(target_os = "android"))]
1462pub struct DisplayManagerBinder;
1463
1464#[cfg(not(target_os = "android"))]
1465impl DisplayManagerBinder {
1466 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), crate::CoreError> {
1467 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1468 }
1469 pub fn is_interactive(&self) -> Result<bool, crate::CoreError> {
1470 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1471 }
1472}
1473
1474#[cfg(not(target_os = "android"))]
1475pub struct RawBinderService;
1476
1477#[cfg(not(target_os = "android"))]
1478impl RawBinderService {
1479 pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
1480 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1481 }
1482 pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
1483 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1484 }
1485 pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
1486 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1487 }
1488}
1489
1490#[cfg(not(target_os = "android"))]
1491pub struct FpsListener;
1492
1493#[cfg(not(target_os = "android"))]
1494impl FpsListener {
1495 pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1496 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1497 }
1498 pub fn register(&mut self, _task_id: i32) -> Result<(), crate::CoreError> {
1499 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1500 }
1501 pub fn unregister(&mut self) -> Result<(), crate::CoreError> {
1502 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1503 }
1504 pub fn last_fps(&self) -> Option<f32> {
1505 None
1506 }
1507 pub fn task_id(&self) -> Option<i32> {
1508 None
1509 }
1510}
1511
1512#[cfg(not(target_os = "android"))]
1513pub struct TaskStackListener;
1514
1515#[cfg(not(target_os = "android"))]
1516impl TaskStackListener {
1517 pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1518 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1519 }
1520 pub fn register(&self) -> Result<(), crate::CoreError> {
1521 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1522 }
1523 pub fn unregister(&self) -> Result<(), crate::CoreError> {
1524 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1525 }
1526}
1527
1528#[cfg(not(target_os = "android"))]
1529pub struct TxCodes { pub observer_code: u32, pub query_code: u32, pub api_mode: u8, pub fg_code: u32 }
1530
1531#[cfg(not(target_os = "android"))]
1532pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
1533 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1534}
1535
1536#[cfg(not(target_os = "android"))]
1537pub fn last_foreground_pid() -> i32 {
1538 0
1539}