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(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
888 unsafe extern "C" fn fps_on_destroy(_: *mut c_void) {}
889 unsafe extern "C" fn fps_on_transact(
890 binder: *mut AIBinder, code: u32, in_parcel: *const AParcel, _: *mut AParcel,
891 ) -> BinderStatus {
892 if code != FPS_CODE.load(Ordering::Relaxed) {
893 return STATUS_UNKNOWN_TRANSACTION;
894 }
895 let read_addr = FPS_READ_I32.load(Ordering::Relaxed);
898 if read_addr != 0 {
899 let read_fn: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus =
900 unsafe { std::mem::transmute(read_addr) };
901 let mut bits: i32 = 0;
902 if unsafe { read_fn(in_parcel, &mut bits) } == STATUS_OK {
903 FPS_VALUE.store(bits as u32, Ordering::Relaxed);
906 let get_user_data = GET_USER_DATA
912 .lock()
913 .unwrap_or_else(|p| p.into_inner());
914 if let Some(get_user_data) = *get_user_data {
915 let userdata = unsafe { get_user_data(binder) };
916 if !userdata.is_null() {
917 let efd = userdata as *mut OwnedFd;
918 let val: u64 = 1;
919 unsafe {
920 libc::write((*efd).as_raw_fd(), &val as *const u64 as *const c_void, 8)
921 };
922 }
923 }
924 }
925 }
926 STATUS_OK
927 }
928
929 pub struct FpsListener {
943 _lib: DlHandle,
944 vt: Vtable,
945 window: OwnedBinder,
946 cb_binder: *mut AIBinder,
947 _wm_class: *mut AIBinder_Class,
948 register_code: u32,
949 unregister_code: u32,
950 task_id: i32,
951 }
952 unsafe impl Send for FpsListener {}
953
954 impl FpsListener {
955 pub fn open() -> Result<(Self, OwnedFd), CoreError> {
961 let handle = unsafe {
962 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
963 };
964 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
965 let lib = DlHandle(handle);
966 let vt = load_vtable(handle)?;
967
968 let (register_code, unregister_code, on_fps_code) =
969 crate::dex::resolve_fps_codes()
970 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_registerTaskFpsCallback not found"))?;
971
972 let window = {
973 let raw = unsafe { (vt.get_service)(WINDOW_SERVICE.as_ptr() as *const c_char) };
974 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:window")); }
975 OwnedBinder { ptr: raw, dec_strong: vt.dec_strong }
976 };
977
978 let wm_class = unsafe {
981 (vt.class_define)(
982 WM_DESCRIPTOR.as_ptr() as *const c_char,
983 wm_on_create, wm_on_destroy, wm_on_transact,
984 )
985 };
986 if wm_class.is_null() {
987 return Err(CoreError::binder(-1, "AIBinder_Class_define:IWindowManager"));
988 }
989 unsafe { (vt.associate_class)(window.ptr, wm_class) };
990
991 let cb_class = unsafe {
992 (vt.class_define)(
993 FPS_DESCRIPTOR.as_ptr() as *const c_char,
994 fps_on_create, fps_on_destroy, fps_on_transact,
995 )
996 };
997 if cb_class.is_null() {
998 return Err(CoreError::binder(-1, "AIBinder_Class_define:ITaskFpsCallback"));
999 }
1000
1001 let owned = unsafe {
1006 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
1007 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
1008 OwnedFd::from_raw_fd(raw)
1009 };
1010
1011 let consumer = owned.try_clone()
1012 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:fps"))?;
1013
1014 let userdata = Box::into_raw(Box::new(owned)) as *mut c_void;
1015 let cb_binder = unsafe { (vt.new_binder)(cb_class, userdata) };
1016 if cb_binder.is_null() {
1017 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1019 return Err(CoreError::binder(-1, "AIBinder_new:ITaskFpsCallback"));
1020 }
1021 unsafe { (vt.associate_class)(cb_binder, cb_class) };
1022
1023 FPS_READ_I32.store(vt.read_int32 as usize, Ordering::Relaxed);
1026 FPS_CODE.store(on_fps_code, Ordering::Relaxed);
1027 FPS_VALUE.store(0, Ordering::Relaxed);
1028 *GET_USER_DATA.lock().unwrap_or_else(|p| p.into_inner()) = Some(vt.get_user_data);
1031
1032 unsafe { (vt.set_thread_pool_max)(0) };
1033 let join_fn = vt.join_thread_pool;
1034 std::thread::spawn(move || unsafe { join_fn() });
1035
1036 Ok((Self {
1037 _lib: lib, vt, window, cb_binder, _wm_class: wm_class,
1038 register_code, unregister_code, task_id: -1,
1039 }, consumer))
1040 }
1041
1042 pub fn register(&mut self, task_id: i32) -> Result<(), CoreError> {
1046 if self.task_id == task_id {
1047 return Ok(());
1048 }
1049 if self.task_id >= 0 {
1050 let _ = self.unregister();
1051 }
1052
1053 let mut inp: *mut AParcel = std::ptr::null_mut();
1054 let s = unsafe { (self.vt.prepare_transaction)(self.window.ptr, &mut inp) };
1055 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:registerTaskFpsCallback")); }
1056 let s = unsafe { (self.vt.write_int32)(inp, task_id) };
1057 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeInt32:taskId")); }
1058 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1059 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1060 let mut out: *mut AParcel = std::ptr::null_mut();
1061 let s = unsafe {
1062 (self.vt.transact)(self.window.ptr, self.register_code, &mut inp, &mut out, 0)
1063 };
1064 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1065 if s != STATUS_OK {
1066 return Err(CoreError::binder(s, "transact:registerTaskFpsCallback"));
1067 }
1068 self.task_id = task_id;
1069 Ok(())
1070 }
1071
1072 pub fn unregister(&mut self) -> Result<(), CoreError> {
1075 if self.task_id < 0 {
1076 return Ok(());
1077 }
1078 let mut inp: *mut AParcel = std::ptr::null_mut();
1079 let s = unsafe { (self.vt.prepare_transaction)(self.window.ptr, &mut inp) };
1080 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:unregisterTaskFpsCallback")); }
1081 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1082 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1083 let mut out: *mut AParcel = std::ptr::null_mut();
1084 let s = unsafe {
1085 (self.vt.transact)(self.window.ptr, self.unregister_code, &mut inp, &mut out, 0)
1086 };
1087 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1088 if s != STATUS_OK {
1089 return Err(CoreError::binder(s, "transact:unregisterTaskFpsCallback"));
1090 }
1091 self.task_id = -1;
1092 Ok(())
1093 }
1094
1095 pub fn last_fps(&self) -> Option<f32> {
1099 let bits = FPS_VALUE.load(Ordering::Relaxed);
1100 if bits == 0 { None } else { Some(f32::from_bits(bits)) }
1101 }
1102
1103 pub fn task_id(&self) -> Option<i32> {
1105 (self.task_id >= 0).then_some(self.task_id)
1106 }
1107 }
1108
1109 impl Drop for FpsListener {
1110 fn drop(&mut self) {
1118 let _ = self.unregister();
1119 }
1120 }
1121
1122 const TASK_SERVICE: &[u8] = b"activity_task\0";
1125 const ATM_DESCRIPTOR: &[u8] = b"android.app.IActivityTaskManager\0";
1126 const TASK_STACK_DESCRIPTOR: &[u8] = b"android.app.ITaskStackListener\0";
1127
1128 unsafe extern "C" fn atm_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
1132 unsafe extern "C" fn atm_on_destroy(_: *mut c_void) {}
1133 unsafe extern "C" fn atm_on_transact(
1134 _: *mut AIBinder, _: u32, _: *const AParcel, _: *mut AParcel,
1135 ) -> BinderStatus { STATUS_OK }
1136
1137 static GET_USER_DATA: std::sync::Mutex<Option<unsafe extern "C" fn(*const AIBinder) -> *mut c_void>> =
1153 std::sync::Mutex::new(None);
1154
1155 unsafe extern "C" fn task_stack_on_create(userdata: *mut c_void) -> *mut c_void { userdata }
1156 unsafe extern "C" fn task_stack_on_destroy(userdata: *mut c_void) {
1157 if !userdata.is_null() {
1158 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1159 }
1160 }
1161 unsafe extern "C" fn task_stack_on_transact(
1162 binder: *mut AIBinder, _code: u32, _in_parcel: *const AParcel, _reply: *mut AParcel,
1163 ) -> BinderStatus {
1164 let get_user_data = GET_USER_DATA
1165 .lock()
1166 .unwrap_or_else(|p| p.into_inner());
1167 if let Some(get_user_data) = *get_user_data {
1168 let userdata = unsafe { get_user_data(binder) };
1169 if !userdata.is_null() {
1170 let efd = userdata as *mut OwnedFd;
1171 let val: u64 = 1;
1172 unsafe { libc::write((*efd).as_raw_fd(), &val as *const u64 as *const c_void, 8) };
1173 }
1174 }
1175 STATUS_OK
1176 }
1177
1178 pub struct TaskStackListener {
1198 _lib: DlHandle,
1199 vt: Vtable,
1200 service: OwnedBinder,
1201 cb_binder: *mut AIBinder,
1202 _atm_class: *mut AIBinder_Class,
1203 register_code: u32,
1204 unregister_code: u32,
1205 }
1206 unsafe impl Send for TaskStackListener {}
1207
1208 impl TaskStackListener {
1209 pub fn open() -> Result<(Self, OwnedFd), CoreError> {
1213 let handle = unsafe {
1214 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
1215 };
1216 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
1217 let lib = DlHandle(handle);
1218 let vt = load_vtable(handle)?;
1219
1220 let (register_code, unregister_code) =
1221 crate::dex::resolve_task_stack_codes()
1222 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_registerTaskStackListener not found"))?;
1223
1224 let service = {
1225 let raw = unsafe { (vt.get_service)(TASK_SERVICE.as_ptr() as *const c_char) };
1226 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:activity_task")); }
1227 OwnedBinder { ptr: raw, dec_strong: vt.dec_strong }
1228 };
1229
1230 let atm_class = unsafe {
1233 (vt.class_define)(
1234 ATM_DESCRIPTOR.as_ptr() as *const c_char,
1235 atm_on_create, atm_on_destroy, atm_on_transact,
1236 )
1237 };
1238 if atm_class.is_null() {
1239 return Err(CoreError::binder(-1, "AIBinder_Class_define:IActivityTaskManager"));
1240 }
1241 unsafe { (vt.associate_class)(service.ptr, atm_class) };
1242
1243 let cb_class = unsafe {
1244 (vt.class_define)(
1245 TASK_STACK_DESCRIPTOR.as_ptr() as *const c_char,
1246 task_stack_on_create, task_stack_on_destroy, task_stack_on_transact,
1247 )
1248 };
1249 if cb_class.is_null() {
1250 return Err(CoreError::binder(-1, "AIBinder_Class_define:ITaskStackListener"));
1251 }
1252
1253 let owned = unsafe {
1258 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
1259 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
1260 OwnedFd::from_raw_fd(raw)
1261 };
1262
1263 let consumer = owned.try_clone()
1264 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:task_stack"))?;
1265
1266 let userdata = Box::into_raw(Box::new(owned)) as *mut c_void;
1267 let cb_binder = unsafe { (vt.new_binder)(cb_class, userdata) };
1268 if cb_binder.is_null() {
1269 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1271 return Err(CoreError::binder(-1, "AIBinder_new:ITaskStackListener"));
1272 }
1273 unsafe { (vt.associate_class)(cb_binder, cb_class) };
1274
1275 *GET_USER_DATA.lock().unwrap_or_else(|p| p.into_inner()) = Some(vt.get_user_data);
1278
1279 unsafe { (vt.set_thread_pool_max)(0) };
1280 let join_fn = vt.join_thread_pool;
1281 std::thread::spawn(move || unsafe { join_fn() });
1282
1283 Ok((Self {
1284 _lib: lib, vt, service, cb_binder, _atm_class: atm_class,
1285 register_code, unregister_code,
1286 }, consumer))
1287 }
1288
1289 pub fn register(&self) -> Result<(), CoreError> {
1293 let mut inp: *mut AParcel = std::ptr::null_mut();
1294 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1295 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:registerTaskStackListener")); }
1296 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1297 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1298 let mut out: *mut AParcel = std::ptr::null_mut();
1299 let s = unsafe {
1300 (self.vt.transact)(self.service.ptr, self.register_code, &mut inp, &mut out, 0)
1301 };
1302 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1303 if s != STATUS_OK {
1304 return Err(CoreError::binder(s, "transact:registerTaskStackListener"));
1305 }
1306 Ok(())
1307 }
1308
1309 pub fn unregister(&self) -> Result<(), CoreError> {
1313 let mut inp: *mut AParcel = std::ptr::null_mut();
1314 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1315 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:unregisterTaskStackListener")); }
1316 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1317 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1318 let mut out: *mut AParcel = std::ptr::null_mut();
1319 let s = unsafe {
1320 (self.vt.transact)(self.service.ptr, self.unregister_code, &mut inp, &mut out, 0)
1321 };
1322 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1323 if s != STATUS_OK {
1324 return Err(CoreError::binder(s, "transact:unregisterTaskStackListener"));
1325 }
1326 Ok(())
1327 }
1328 }
1329
1330 impl Drop for TaskStackListener {
1331 fn drop(&mut self) {
1336 let _ = self.unregister();
1337 }
1338 }
1339
1340 pub struct RawBinderService {
1349 _lib: DlHandle,
1350 vt: Vtable,
1351 service: OwnedBinder,
1352 }
1353 unsafe impl Send for RawBinderService {}
1354
1355 impl RawBinderService {
1356 pub fn open(service_name: &str) -> Result<Self, CoreError> {
1358 use std::ffi::CString;
1359 let handle = unsafe {
1360 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
1361 };
1362 if handle.is_null() {
1363 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
1364 }
1365 let lib = DlHandle(handle);
1366 let vt = load_vtable(handle)?;
1367 let cs = CString::new(service_name)
1368 .map_err(|_| CoreError::binder(-1, "service_name:nul_byte"))?;
1369 let raw = unsafe { (vt.get_service)(cs.as_ptr()) };
1370 if raw.is_null() {
1371 return Err(CoreError::binder(-1, "AServiceManager_getService:null"));
1372 }
1373 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
1374 Ok(Self { _lib: lib, vt, service })
1375 }
1376
1377 pub fn transact_bool(&self, code: u32) -> Result<bool, CoreError> {
1379 let out = self.raw_noarg(code)?;
1380 let r = ParcelReader { vt: &self.vt, parcel: &out };
1381 let ex = r.read_i32()?;
1382 if ex != EX_NONE { return Err(CoreError::binder(ex, "transact_bool:exception")); }
1383 if let Some(rb) = self.vt.read_bool {
1384 let mut v = false;
1385 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
1386 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readBool")); }
1387 Ok(v)
1388 } else {
1389 Ok(r.read_i32()? != 0)
1390 }
1391 }
1392
1393 pub fn transact_i32(&self, code: u32, arg: i32) -> Result<(), CoreError> {
1395 let mut inp: *mut AParcel = std::ptr::null_mut();
1396 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1397 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
1398 let s = unsafe { (self.vt.write_int32)(inp, arg) };
1399 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeInt32")); }
1400 let mut out: *mut AParcel = std::ptr::null_mut();
1401 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
1402 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1403 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
1404 Ok(())
1405 }
1406
1407 fn raw_noarg(&self, code: u32) -> Result<OwnedParcel, CoreError> {
1408 let mut inp: *mut AParcel = std::ptr::null_mut();
1409 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1410 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
1411 let mut out: *mut AParcel = std::ptr::null_mut();
1412 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
1413 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
1414 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
1415 Ok(out)
1416 }
1417 }
1418}
1419
1420#[cfg(target_os = "android")]
1423pub use imp::{ActivityManagerBinder, DisplayManagerBinder, FpsListener, RawBinderService, TaskStackListener, TxCodes, last_foreground_pid, resolve_tx_codes};
1424
1425#[cfg(not(target_os = "android"))]
1428pub struct ActivityManagerBinder;
1429
1430#[cfg(not(target_os = "android"))]
1431impl ActivityManagerBinder {
1432 pub fn open() -> Result<Self, crate::CoreError> {
1433 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1434 }
1435 pub fn open_with_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1436 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1437 }
1438 pub fn open_with_fgproc_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1439 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1440 }
1441 pub fn get_focused_task(&self) -> Result<Option<(i32, Option<String>)>, crate::CoreError> {
1442 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1443 }
1444 pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
1445 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1446 }
1447 pub fn get_focused_task_id(&self) -> Result<Option<i32>, crate::CoreError> {
1448 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1449 }
1450}
1451
1452#[cfg(not(target_os = "android"))]
1453pub struct DisplayManagerBinder;
1454
1455#[cfg(not(target_os = "android"))]
1456impl DisplayManagerBinder {
1457 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), crate::CoreError> {
1458 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1459 }
1460 pub fn is_interactive(&self) -> Result<bool, crate::CoreError> {
1461 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1462 }
1463}
1464
1465#[cfg(not(target_os = "android"))]
1466pub struct RawBinderService;
1467
1468#[cfg(not(target_os = "android"))]
1469impl RawBinderService {
1470 pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
1471 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1472 }
1473 pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
1474 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1475 }
1476 pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
1477 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1478 }
1479}
1480
1481#[cfg(not(target_os = "android"))]
1482pub struct FpsListener;
1483
1484#[cfg(not(target_os = "android"))]
1485impl FpsListener {
1486 pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1487 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1488 }
1489 pub fn register(&mut self, _task_id: i32) -> Result<(), crate::CoreError> {
1490 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1491 }
1492 pub fn unregister(&mut self) -> Result<(), crate::CoreError> {
1493 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1494 }
1495 pub fn last_fps(&self) -> Option<f32> {
1496 None
1497 }
1498 pub fn task_id(&self) -> Option<i32> {
1499 None
1500 }
1501}
1502
1503#[cfg(not(target_os = "android"))]
1504pub struct TaskStackListener;
1505
1506#[cfg(not(target_os = "android"))]
1507impl TaskStackListener {
1508 pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1509 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1510 }
1511 pub fn register(&self) -> Result<(), crate::CoreError> {
1512 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1513 }
1514 pub fn unregister(&self) -> Result<(), crate::CoreError> {
1515 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1516 }
1517}
1518
1519#[cfg(not(target_os = "android"))]
1520pub struct TxCodes { pub observer_code: u32, pub query_code: u32, pub api_mode: u8, pub fg_code: u32 }
1521
1522#[cfg(not(target_os = "android"))]
1523pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
1524 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1525}
1526
1527#[cfg(not(target_os = "android"))]
1528pub fn last_foreground_pid() -> i32 {
1529 0
1530}