1#[cfg(target_os = "android")]
27mod imp {
28 use crate::CoreError;
29 use crate::dex;
30 use std::os::fd::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd};
31 use std::os::raw::{c_char, c_void};
32 use std::sync::atomic::{AtomicI32, AtomicU32, AtomicUsize, Ordering};
33 use std::sync::Mutex;
34
35 const STATUS_OK: i32 = 0;
38 const STATUS_UNKNOWN_TRANSACTION: i32 = -2;
39 const EX_NONE: i32 = 0;
40
41 const AM_DESCRIPTOR: &[u8] = b"android.app.IActivityManager\0";
44 const OBS_DESCRIPTOR: &[u8] = b"android.app.IProcessObserver\0";
45 const FGPROC_DESCRIPTOR: &[u8] = b"android.app.IForegroundProcessObserver\0";
46 const ACTIVITY_SERVICE: &[u8] = b"activity\0";
47 #[cfg(target_pointer_width = "64")]
48 const LIBBINDER_PATH: &[u8] = b"/system/lib64/libbinder_ndk.so\0";
49 #[cfg(target_pointer_width = "32")]
50 const LIBBINDER_PATH: &[u8] = b"/system/lib/libbinder_ndk.so\0";
51
52 static OBS_FG_CODE: AtomicU32 = AtomicU32::new(0);
63 static OBS_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
64
65 fn obs_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
66 OBS_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
67 }
68
69 static FGPROC_FG_CODE: AtomicU32 = AtomicU32::new(0);
77 static FGPROC_PID: AtomicI32 = AtomicI32::new(0);
78 static FGPROC_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
79 static FGPROC_READ_I32: AtomicUsize = AtomicUsize::new(0);
80 static FGPROC_IPROC_MODE: AtomicU32 = AtomicU32::new(0);
85
86 fn fgproc_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
87 FGPROC_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
88 }
89
90 type AIBinder = c_void;
93 #[allow(non_camel_case_types)]
94 type AIBinder_Class = c_void;
95 type AParcel = c_void;
96 type BinderStatus = i32;
97 type StringAllocator = unsafe extern "C" fn(*mut c_void, i32, *mut *mut c_char) -> bool;
98
99 unsafe extern "C" fn am_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
103 unsafe extern "C" fn am_on_destroy(_: *mut c_void) {}
104 unsafe extern "C" fn am_on_transact(
105 _: *mut AIBinder, _: u32, _: *const AParcel, _: *mut AParcel,
106 ) -> BinderStatus { STATUS_UNKNOWN_TRANSACTION }
107
108 unsafe extern "C" fn obs_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
110 unsafe extern "C" fn obs_on_destroy(_: *mut c_void) {}
111 unsafe extern "C" fn obs_on_transact(
112 _: *mut AIBinder, code: u32, _: *const AParcel, _: *mut AParcel,
113 ) -> BinderStatus {
114 if code == OBS_FG_CODE.load(Ordering::Relaxed) {
115 if let Some(fd) = obs_eventfd_guard().as_ref() {
118 let val: u64 = 1;
119 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
120 }
121 }
122 STATUS_OK
123 }
124
125 unsafe extern "C" fn fgproc_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
134 unsafe extern "C" fn fgproc_on_destroy(_: *mut c_void) {}
135 unsafe extern "C" fn fgproc_on_transact(
136 _: *mut AIBinder, code: u32, in_parcel: *const AParcel, _: *mut AParcel,
137 ) -> BinderStatus {
138 if code != FGPROC_FG_CODE.load(Ordering::Relaxed) {
139 return STATUS_UNKNOWN_TRANSACTION;
140 }
141 let read_addr = FGPROC_READ_I32.load(Ordering::Relaxed);
144 if read_addr != 0 {
145 let read_fn: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus =
146 unsafe { std::mem::transmute(read_addr) };
147 if FGPROC_IPROC_MODE.load(Ordering::Relaxed) == 1 {
148 let mut pid: i32 = 0;
150 let mut _uid: i32 = 0;
151 let mut fg: i32 = 0;
152 let mut ok = unsafe { read_fn(in_parcel, &mut pid) } == STATUS_OK;
153 ok &= unsafe { read_fn(in_parcel, &mut _uid) } == STATUS_OK;
154 ok &= unsafe { read_fn(in_parcel, &mut fg) } == STATUS_OK;
155 if ok {
156 FGPROC_PID.store(pid, Ordering::Relaxed);
157 if fg == 0 {
160 return STATUS_OK;
161 }
162 } else {
163 return STATUS_OK;
164 }
165 } else {
166 let mut pid: i32 = 0;
167 if unsafe { read_fn(in_parcel, &mut pid) } == STATUS_OK {
168 FGPROC_PID.store(pid, Ordering::Relaxed);
169 }
170 }
171 }
172 if let Some(fd) = fgproc_eventfd_guard().as_ref() {
175 let val: u64 = 1;
176 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
177 }
178 STATUS_OK
179 }
180
181 pub fn last_foreground_pid() -> i32 {
184 FGPROC_PID.load(Ordering::Relaxed)
185 }
186
187 unsafe extern "C" fn string_alloc(
190 cookie: *mut c_void, length: i32, buffer: *mut *mut c_char,
191 ) -> bool {
192 if length < 0 { return true; }
193 let s = unsafe { &mut *(cookie as *mut StringBuf) };
194 s.0.reserve_exact(length as usize + 1);
195 unsafe { s.0.as_mut_vec().resize(length as usize + 1, 0) };
196 unsafe { *buffer = s.0.as_mut_ptr() as *mut c_char };
197 true
198 }
199
200 struct StringBuf(String);
201 impl StringBuf {
202 fn new() -> Self { Self(String::new()) }
203 fn finish(mut self) -> Option<String> {
204 if let Some(pos) = self.0.as_bytes().iter().position(|&b| b == 0) {
205 unsafe { self.0.as_mut_vec().truncate(pos) };
206 }
207 if self.0.is_empty() { None } else { Some(self.0) }
208 }
209 }
210
211 struct Vtable {
214 get_service: unsafe extern "C" fn(*const c_char) -> *mut AIBinder,
215 class_define: unsafe extern "C" fn(
216 *const c_char,
217 unsafe extern "C" fn(*mut c_void) -> *mut c_void,
218 unsafe extern "C" fn(*mut c_void),
219 unsafe extern "C" fn(*mut AIBinder, u32, *const AParcel, *mut AParcel) -> BinderStatus,
220 ) -> *mut AIBinder_Class,
221 associate_class: unsafe extern "C" fn(*mut AIBinder, *mut AIBinder_Class) -> bool,
222 new_binder: unsafe extern "C" fn(*const AIBinder_Class, *mut c_void) -> *mut AIBinder,
223 prepare_transaction: unsafe extern "C" fn(*mut AIBinder, *mut *mut AParcel) -> BinderStatus,
224 transact: unsafe extern "C" fn(*mut AIBinder, u32, *mut *mut AParcel, *mut *mut AParcel, u32) -> BinderStatus,
225 dec_strong: unsafe extern "C" fn(*mut AIBinder),
226 parcel_delete: unsafe extern "C" fn(*mut AParcel),
227 read_int32: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus,
228 read_string: unsafe extern "C" fn(*const AParcel, *mut c_void, StringAllocator) -> BinderStatus,
229 write_strong_binder: unsafe extern "C" fn(*mut AParcel, *mut AIBinder) -> BinderStatus,
230 set_thread_pool_max: unsafe extern "C" fn(u32),
231 join_thread_pool: unsafe extern "C" fn(),
232 write_int32: unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus,
233 read_bool: Option<unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus>,
235 }
236
237 struct DlHandle(*mut c_void);
240 unsafe impl Send for DlHandle {}
241 impl Drop for DlHandle {
242 fn drop(&mut self) {
243 }
249 }
250
251 struct OwnedParcel { ptr: *mut AParcel, delete: unsafe extern "C" fn(*mut AParcel) }
252 impl Drop for OwnedParcel {
253 fn drop(&mut self) { if !self.ptr.is_null() { unsafe { (self.delete)(self.ptr) }; } }
254 }
255
256 struct OwnedBinder { ptr: *mut AIBinder, dec_strong: unsafe extern "C" fn(*mut AIBinder) }
257 unsafe impl Send for OwnedBinder {}
258 impl Drop for OwnedBinder {
259 fn drop(&mut self) { if !self.ptr.is_null() { unsafe { (self.dec_strong)(self.ptr) }; } }
260 }
261
262 macro_rules! dlsym_fn {
265 ($handle:expr, $name:literal, $ty:ty) => {{
266 let sym = unsafe {
267 libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char)
268 };
269 if sym.is_null() {
270 return Err(CoreError::binder(-1, concat!("dlsym:", $name)));
271 }
272 unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) }
273 }};
274 }
275
276 macro_rules! dlsym_opt {
277 ($handle:expr, $name:literal, $ty:ty) => {{
278 let sym = unsafe {
279 libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char)
280 };
281 if sym.is_null() { None }
282 else { Some(unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) }) }
283 }};
284 }
285
286 fn load_vtable(handle: *mut c_void) -> Result<Vtable, CoreError> {
287 Ok(Vtable {
288 get_service: dlsym_fn!(handle, "AServiceManager_getService",
289 unsafe extern "C" fn(*const c_char) -> *mut AIBinder),
290 class_define: dlsym_fn!(handle, "AIBinder_Class_define",
291 unsafe extern "C" fn(
292 *const c_char,
293 unsafe extern "C" fn(*mut c_void) -> *mut c_void,
294 unsafe extern "C" fn(*mut c_void),
295 unsafe extern "C" fn(*mut AIBinder, u32, *const AParcel, *mut AParcel) -> BinderStatus,
296 ) -> *mut AIBinder_Class),
297 associate_class: dlsym_fn!(handle, "AIBinder_associateClass",
298 unsafe extern "C" fn(*mut AIBinder, *mut AIBinder_Class) -> bool),
299 new_binder: dlsym_fn!(handle, "AIBinder_new",
300 unsafe extern "C" fn(*const AIBinder_Class, *mut c_void) -> *mut AIBinder),
301 prepare_transaction: dlsym_fn!(handle, "AIBinder_prepareTransaction",
302 unsafe extern "C" fn(*mut AIBinder, *mut *mut AParcel) -> BinderStatus),
303 transact: dlsym_fn!(handle, "AIBinder_transact",
304 unsafe extern "C" fn(*mut AIBinder, u32, *mut *mut AParcel, *mut *mut AParcel, u32) -> BinderStatus),
305 dec_strong: dlsym_fn!(handle, "AIBinder_decStrong",
306 unsafe extern "C" fn(*mut AIBinder)),
307 parcel_delete: dlsym_fn!(handle, "AParcel_delete",
308 unsafe extern "C" fn(*mut AParcel)),
309 read_int32: dlsym_fn!(handle, "AParcel_readInt32",
310 unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus),
311 read_string: dlsym_fn!(handle, "AParcel_readString",
312 unsafe extern "C" fn(*const AParcel, *mut c_void, StringAllocator) -> BinderStatus),
313 write_strong_binder: dlsym_fn!(handle, "AParcel_writeStrongBinder",
314 unsafe extern "C" fn(*mut AParcel, *mut AIBinder) -> BinderStatus),
315 set_thread_pool_max: dlsym_fn!(handle, "ABinderProcess_setThreadPoolMaxThreadCount",
316 unsafe extern "C" fn(u32)),
317 join_thread_pool: dlsym_fn!(handle, "ABinderProcess_joinThreadPool",
318 unsafe extern "C" fn()),
319 write_int32: dlsym_fn!(handle, "AParcel_writeInt32",
320 unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus),
321 read_bool: dlsym_opt!(handle, "AParcel_readBool",
322 unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus),
323 })
324 }
325
326 struct ParcelReader<'a> { vt: &'a Vtable, parcel: &'a OwnedParcel }
329
330 impl<'a> ParcelReader<'a> {
331 fn read_i32(&self) -> Result<i32, CoreError> {
332 let mut v = 0i32;
333 let s = unsafe { (self.vt.read_int32)(self.parcel.ptr, &mut v) };
334 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readInt32")); }
335 Ok(v)
336 }
337 fn read_string(&self) -> Result<Option<String>, CoreError> {
338 let mut buf = StringBuf::new();
339 let s = unsafe {
340 (self.vt.read_string)(self.parcel.ptr, &mut buf as *mut StringBuf as *mut c_void, string_alloc)
341 };
342 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readString")); }
343 Ok(buf.finish())
344 }
345 fn skip_i32s(&self, n: usize) -> Result<(), CoreError> {
346 for _ in 0..n { self.read_i32()?; }
347 Ok(())
348 }
349 fn skip_int_array(&self) -> Result<(), CoreError> {
350 let count = self.read_i32()?.max(0) as usize;
351 self.skip_i32s(count)
352 }
353 fn read_first_package_from_names(&self) -> Result<Option<String>, CoreError> {
354 let count = self.read_i32()?.max(0) as usize;
355 let mut first: Option<String> = None;
356 for _ in 0..count {
357 let s = self.read_string()?;
358 if first.is_none() {
359 first = s.and_then(|c| c.split('/').next().map(str::to_owned));
360 }
361 }
362 Ok(first)
363 }
364 }
365
366 fn parse_stack_info_body(r: &ParcelReader<'_>) -> Result<Option<String>, CoreError> {
369 r.skip_i32s(5)?;
370 r.skip_int_array()?;
371 r.read_first_package_from_names()
372 }
373
374 fn parse_root_task_info_task(r: &ParcelReader<'_>) -> Result<(i32, Option<String>), CoreError> {
381 let scratch = r.read_i32()?;
382 if scratch != 0 { r.skip_i32s(4)?; }
383 r.skip_int_array()?; let pkg = r.read_first_package_from_names()?; let bounds_count = r.read_i32()?;
387 let n = if bounds_count < 0 { 0 } else { bounds_count as usize };
388 for _ in 0..n {
389 let entry = r.read_i32()?;
390 if entry != 0 { r.skip_i32s(4)?; }
391 }
392 r.skip_int_array()?; r.skip_i32s(2)?; r.skip_i32s(1)?; let task_id = r.read_i32()?;
396 Ok((task_id, pkg))
397 }
398
399 pub struct TxCodes {
402 pub observer_code: u32,
403 pub query_code: u32,
404 pub api_mode: u8, pub fg_code: u32,
406 }
407
408 pub fn resolve_tx_codes() -> Result<TxCodes, CoreError> {
409 let (obs, query, api, fg) = dex::resolve_tx_codes_from_dex()
410 .ok_or_else(|| CoreError::binder(-1, "tx_code_resolution:dex_parse_failed"))?;
411 Ok(TxCodes { observer_code: obs, query_code: query, api_mode: api, fg_code: fg })
412 }
413
414 pub struct ActivityManagerBinder {
417 _lib: DlHandle,
418 vt: Vtable,
419 _class: *mut AIBinder_Class,
420 service: OwnedBinder,
421 tx_code: u32,
422 legacy: bool,
423 }
424 unsafe impl Send for ActivityManagerBinder {}
425
426 impl ActivityManagerBinder {
427 fn open_inner(handle: *mut c_void) -> Result<(DlHandle, Vtable, *mut AIBinder_Class, OwnedBinder), CoreError> {
428 let lib = DlHandle(handle);
429 let vt = load_vtable(handle)?;
430
431 let am_class = unsafe {
432 (vt.class_define)(
433 AM_DESCRIPTOR.as_ptr() as *const c_char,
434 am_on_create, am_on_destroy, am_on_transact,
435 )
436 };
437 if am_class.is_null() { return Err(CoreError::binder(-1, "AIBinder_Class_define:AM")); }
438
439 let raw = unsafe { (vt.get_service)(ACTIVITY_SERVICE.as_ptr() as *const c_char) };
440 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:activity")); }
441 unsafe { (vt.associate_class)(raw, am_class) };
442
443 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
444 Ok((lib, vt, am_class, service))
445 }
446
447 fn dlopen_libbinder() -> Result<*mut c_void, CoreError> {
448 use std::os::raw::c_char;
449 let handle = unsafe {
450 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
451 };
452 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
453 Ok(handle)
454 }
455
456 pub fn open() -> Result<Self, CoreError> {
459 let handle = Self::dlopen_libbinder()?;
460 let (lib, vt, class, service) = Self::open_inner(handle)?;
461 let codes = resolve_tx_codes()?;
462 let legacy = codes.api_mode == 2;
463 Ok(Self { _lib: lib, vt, _class: class, service, tx_code: codes.query_code, legacy })
464 }
465
466 pub fn open_with_observer() -> Result<(Self, OwnedFd), CoreError> {
475 let handle = Self::dlopen_libbinder()?;
476 let (lib, vt, am_class, service) = Self::open_inner(handle)?;
477 let codes = resolve_tx_codes()?;
478 let legacy = codes.api_mode == 2;
479
480 let owned = unsafe {
483 let raw = libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC);
484 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
485 OwnedFd::from_raw_fd(raw)
486 };
487
488 let obs_class = unsafe {
490 (vt.class_define)(
491 OBS_DESCRIPTOR.as_ptr() as *const c_char,
492 obs_on_create, obs_on_destroy, obs_on_transact,
493 )
494 };
495 if obs_class.is_null() {
496 return Err(CoreError::binder(-1, "AIBinder_Class_define:Observer"));
497 }
498
499 let obs_binder = unsafe { (vt.new_binder)(obs_class, std::ptr::null_mut()) };
501 if obs_binder.is_null() {
502 return Err(CoreError::binder(-1, "AIBinder_new:Observer"));
503 }
504 unsafe { (vt.associate_class)(obs_binder, obs_class) };
505
506 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
508 let s = unsafe { (vt.prepare_transaction)(service.ptr, &mut in_ptr) };
509 if s != STATUS_OK {
510 return Err(CoreError::binder(s, "prepareTransaction:registerObserver"));
511 }
512 unsafe { (vt.write_strong_binder)(in_ptr, obs_binder) };
513 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
514 let s = unsafe {
515 (vt.transact)(service.ptr, codes.observer_code, &mut in_ptr, &mut out_ptr, 0)
516 };
517 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
518 if s != STATUS_OK {
519 return Err(CoreError::binder(s, "transact:registerProcessObserver"));
520 }
521
522 let consumer = owned.try_clone()
525 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:observer"))?;
526
527 OBS_FG_CODE.store(codes.fg_code, Ordering::Relaxed);
529 *obs_eventfd_guard() = Some(owned);
530
531 unsafe { (vt.set_thread_pool_max)(0) };
533 let join_fn = vt.join_thread_pool;
534 std::thread::spawn(move || unsafe { join_fn() });
535
536 let binder = Self { _lib: lib, vt, _class: am_class, service, tx_code: codes.query_code, legacy };
537 Ok((binder, consumer))
538 }
539
540 pub fn open_with_fgproc_observer() -> Result<(Self, OwnedFd), CoreError> {
564 let handle = Self::dlopen_libbinder()?;
565 let (lib, vt, am_class, service) = Self::open_inner(handle)?;
566
567 let (register_code, fgproc_code, mode, descriptor): (u32, u32, u32, &[u8]) =
572 match crate::dex::resolve_fgproc_codes() {
573 Some((r, c)) => (r, c, 0, FGPROC_DESCRIPTOR),
574 None => match crate::dex::resolve_fgproc_codes_fallback() {
575 Some((r, c)) => (r, c, 1, OBS_DESCRIPTOR),
576 None => {
577 return Err(CoreError::binder(-1, "tx_code_resolution:fgproc_dex_parse_failed"));
578 }
579 },
580 };
581
582 let owned = unsafe {
585 let raw = libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC);
586 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
587 OwnedFd::from_raw_fd(raw)
588 };
589
590 let obs_class = unsafe {
593 (vt.class_define)(
594 descriptor.as_ptr() as *const c_char,
595 fgproc_on_create, fgproc_on_destroy, fgproc_on_transact,
596 )
597 };
598 if obs_class.is_null() {
599 return Err(CoreError::binder(-1, "AIBinder_Class_define:FGProcessObserver"));
600 }
601
602 let obs_binder = unsafe { (vt.new_binder)(obs_class, std::ptr::null_mut()) };
604 if obs_binder.is_null() {
605 return Err(CoreError::binder(-1, "AIBinder_new:FGProcessObserver"));
606 }
607 unsafe { (vt.associate_class)(obs_binder, obs_class) };
608
609 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
612 let s = unsafe { (vt.prepare_transaction)(service.ptr, &mut in_ptr) };
613 if s != STATUS_OK {
614 return Err(CoreError::binder(s, "prepareTransaction:registerForegroundProcessObserver"));
615 }
616 unsafe { (vt.write_strong_binder)(in_ptr, obs_binder) };
617 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
618 let s = unsafe {
619 (vt.transact)(service.ptr, register_code, &mut in_ptr, &mut out_ptr, 0)
620 };
621 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
622 if s != STATUS_OK {
623 return Err(CoreError::binder(s, "transact:registerForegroundProcessObserver"));
624 }
625
626 let consumer = owned.try_clone()
629 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:fgproc_observer"))?;
630
631 FGPROC_READ_I32.store(vt.read_int32 as usize, Ordering::Relaxed);
636 FGPROC_IPROC_MODE.store(mode, Ordering::Relaxed);
637 FGPROC_FG_CODE.store(fgproc_code, Ordering::Relaxed);
638 FGPROC_PID.store(0, Ordering::Relaxed);
639 *fgproc_eventfd_guard() = Some(owned);
640
641 unsafe { (vt.set_thread_pool_max)(0) };
643 let join_fn = vt.join_thread_pool;
644 std::thread::spawn(move || unsafe { join_fn() });
645
646 let binder = Self { _lib: lib, vt, _class: am_class, service, tx_code: 0, legacy: false };
647 Ok((binder, consumer))
648 }
649
650 fn do_transact(&self) -> Result<OwnedParcel, CoreError> {
651 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
652 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut in_ptr) };
653 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
654 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
655 let s = unsafe {
656 (self.vt.transact)(self.service.ptr, self.tx_code, &mut in_ptr, &mut out_ptr, 0)
657 };
658 let out = OwnedParcel { ptr: out_ptr, delete: self.vt.parcel_delete };
659 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
660 Ok(out)
661 }
662
663 pub fn get_focused_task(&self) -> Result<Option<(i32, Option<String>)>, CoreError> {
670 if self.legacy {
671 return Ok(None);
673 }
674 let out = self.do_transact()?;
675 let r = ParcelReader { vt: &self.vt, parcel: &out };
676 let ex = r.read_i32()?;
677 if ex != EX_NONE { return Err(CoreError::binder(ex, "getFocusedTask:exception")); }
678 let present = r.read_i32()?;
679 if present == 0 { return Ok(None); }
680 Ok(Some(parse_root_task_info_task(&r)?))
681 }
682
683 pub fn get_focused_package(&self) -> Result<Option<String>, CoreError> {
687 if self.legacy {
688 let out = self.do_transact()?;
689 let r = ParcelReader { vt: &self.vt, parcel: &out };
690 let ex = r.read_i32()?;
691 if ex != EX_NONE { return Err(CoreError::binder(ex, "getFocusedTask:exception")); }
692 let present = r.read_i32()?;
693 if present == 0 { return Ok(None); }
694 return parse_stack_info_body(&r);
695 }
696 Ok(self.get_focused_task()?.map(|(_, pkg)| pkg).flatten())
697 }
698
699 pub fn get_focused_task_id(&self) -> Result<Option<i32>, CoreError> {
703 Ok(self.get_focused_task()?.map(|(task_id, _)| task_id))
704 }
705 }
706
707 const DISPLAY_SERVICE: &[u8] = b"display\0";
710 const DISPLAY_DESCRIPTOR: &[u8] = b"android.hardware.display.IDisplayManager\0";
711 const CALLBACK_DESCRIPTOR: &[u8] = b"android.hardware.display.IDisplayManagerCallback\0";
712 const POWER_SERVICE: &[u8] = b"power\0";
713
714 const TX_DISPLAY_REGISTER_CALLBACK: u32 = 4;
715
716 static DISP_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
719
720 fn disp_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
721 DISP_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
722 }
723
724 unsafe extern "C" fn disp_cb_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
725 unsafe extern "C" fn disp_cb_on_destroy(_: *mut c_void) {}
726 unsafe extern "C" fn disp_cb_on_transact(
727 _: *mut AIBinder, code: u32, _: *const AParcel, _: *mut AParcel,
728 ) -> BinderStatus {
729 if code == 1 {
730 if let Some(fd) = disp_eventfd_guard().as_ref() {
731 let val: u64 = 1;
732 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
733 }
734 }
735 STATUS_OK
736 }
737
738 pub struct DisplayManagerBinder {
739 _lib: DlHandle,
740 vt: Vtable,
741 display: OwnedBinder,
742 power: Option<OwnedBinder>,
743 is_interactive_tx: u32,
744 }
745 unsafe impl Send for DisplayManagerBinder {}
746
747 impl DisplayManagerBinder {
748 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), CoreError> {
749 let handle = unsafe {
750 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
751 };
752 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
753 let lib = DlHandle(handle);
754 let vt = load_vtable(handle)?;
755
756 let owned = unsafe {
760 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
761 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
762 OwnedFd::from_raw_fd(raw)
763 };
764
765 let raw_display = unsafe { (vt.get_service)(DISPLAY_SERVICE.as_ptr() as *const c_char) };
767 if raw_display.is_null() {
768 return Err(CoreError::binder(-1, "AServiceManager_getService:display"));
769 }
770 let display = OwnedBinder { ptr: raw_display, dec_strong: vt.dec_strong };
771
772 let cb_class = unsafe {
774 (vt.class_define)(
775 CALLBACK_DESCRIPTOR.as_ptr() as *const c_char,
776 disp_cb_on_create, disp_cb_on_destroy, disp_cb_on_transact,
777 )
778 };
779 if cb_class.is_null() {
780 return Err(CoreError::binder(-1, "AIBinder_Class_define:DisplayCallback"));
781 }
782
783 let cb_binder = unsafe { (vt.new_binder)(cb_class, std::ptr::null_mut()) };
784 if cb_binder.is_null() {
785 return Err(CoreError::binder(-1, "AIBinder_new:DisplayCallback"));
786 }
787
788 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
790 let s = unsafe { (vt.prepare_transaction)(display.ptr, &mut in_ptr) };
791 if s != STATUS_OK {
792 return Err(CoreError::binder(s, "prepareTransaction:registerCallback"));
793 }
794 unsafe { (vt.write_strong_binder)(in_ptr, cb_binder) };
795 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
796 let s = unsafe {
797 (vt.transact)(display.ptr, TX_DISPLAY_REGISTER_CALLBACK, &mut in_ptr, &mut out_ptr, 0)
798 };
799 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
800 if s != STATUS_OK {
801 return Err(CoreError::binder(s, "transact:registerCallback"));
802 }
803
804 let power = {
806 let raw = unsafe { (vt.get_service)(POWER_SERVICE.as_ptr() as *const c_char) };
807 if raw.is_null() { None } else { Some(OwnedBinder { ptr: raw, dec_strong: vt.dec_strong }) }
808 };
809
810 let is_interactive_tx = crate::dex::resolve_is_interactive_tx()
812 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_isInteractive not found"))?;
813
814 let efd_owned = owned.try_clone()
817 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:display"))
818 .and_then(|dup| unsafe {
819 crate::reactor::Fd::from_owned_raw_fd(dup.into_raw_fd(), "display.efd")
820 .map_err(|_| CoreError::binder(-1, "Fd::from_owned_raw_fd:display.efd"))
821 })?;
822
823 *disp_eventfd_guard() = Some(owned);
825
826 unsafe { (vt.set_thread_pool_max)(0) };
828 let join_fn = vt.join_thread_pool;
829 std::thread::spawn(move || unsafe { join_fn() });
830
831 Ok((Self { _lib: lib, vt, display, power, is_interactive_tx }, efd_owned))
832 }
833
834 pub fn is_interactive(&self) -> Result<bool, CoreError> {
835 let power = self.power.as_ref()
836 .ok_or_else(|| CoreError::binder(-1, "power:unavailable"))?;
837 let mut inp: *mut AParcel = std::ptr::null_mut();
838 let s = unsafe { (self.vt.prepare_transaction)(power.ptr, &mut inp) };
839 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:isInteractive")); }
840 let mut out: *mut AParcel = std::ptr::null_mut();
841 let s = unsafe {
842 (self.vt.transact)(power.ptr, self.is_interactive_tx, &mut inp, &mut out, 0)
843 };
844 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
845 if s != STATUS_OK { return Err(CoreError::binder(s, "transact:isInteractive")); }
846 let r = ParcelReader { vt: &self.vt, parcel: &out };
847 let ex = r.read_i32()?;
848 if ex != EX_NONE { return Err(CoreError::binder(ex, "isInteractive:exception")); }
849 if let Some(rb) = self.vt.read_bool {
850 let mut v = false;
851 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
852 if s != STATUS_OK { return Err(CoreError::binder(s, "readBool:isInteractive")); }
853 Ok(v)
854 } else {
855 Ok(r.read_i32()? != 0)
856 }
857 }
858 }
859
860 const WINDOW_SERVICE: &[u8] = b"window\0";
863 const WM_DESCRIPTOR: &[u8] = b"android.view.IWindowManager\0";
864 const FPS_DESCRIPTOR: &[u8] = b"android.window.ITaskFpsCallback\0";
865 static FPS_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
870 static FPS_VALUE: AtomicU32 = AtomicU32::new(0);
871 static FPS_CODE: AtomicU32 = AtomicU32::new(0);
872 static FPS_READ_I32: AtomicUsize = AtomicUsize::new(0);
873
874 fn fps_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
875 FPS_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
876 }
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 _: *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 if let Some(fd) = fps_eventfd_guard().as_ref() {
907 let val: u64 = 1;
908 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
909 }
910 }
911 }
912 STATUS_OK
913 }
914
915 pub struct FpsListener {
929 _lib: DlHandle,
930 vt: Vtable,
931 window: OwnedBinder,
932 cb_binder: *mut AIBinder,
933 _wm_class: *mut AIBinder_Class,
934 register_code: u32,
935 unregister_code: u32,
936 task_id: i32,
937 }
938 unsafe impl Send for FpsListener {}
939
940 impl FpsListener {
941 pub fn open() -> Result<(Self, OwnedFd), CoreError> {
947 let handle = unsafe {
948 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
949 };
950 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
951 let lib = DlHandle(handle);
952 let vt = load_vtable(handle)?;
953
954 let (register_code, unregister_code, on_fps_code) =
955 crate::dex::resolve_fps_codes()
956 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_registerTaskFpsCallback not found"))?;
957
958 let window = {
959 let raw = unsafe { (vt.get_service)(WINDOW_SERVICE.as_ptr() as *const c_char) };
960 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:window")); }
961 OwnedBinder { ptr: raw, dec_strong: vt.dec_strong }
962 };
963
964 let wm_class = unsafe {
967 (vt.class_define)(
968 WM_DESCRIPTOR.as_ptr() as *const c_char,
969 wm_on_create, wm_on_destroy, wm_on_transact,
970 )
971 };
972 if wm_class.is_null() {
973 return Err(CoreError::binder(-1, "AIBinder_Class_define:IWindowManager"));
974 }
975 unsafe { (vt.associate_class)(window.ptr, wm_class) };
976
977 let cb_class = unsafe {
978 (vt.class_define)(
979 FPS_DESCRIPTOR.as_ptr() as *const c_char,
980 fps_on_create, fps_on_destroy, fps_on_transact,
981 )
982 };
983 if cb_class.is_null() {
984 return Err(CoreError::binder(-1, "AIBinder_Class_define:ITaskFpsCallback"));
985 }
986
987 let cb_binder = unsafe { (vt.new_binder)(cb_class, std::ptr::null_mut()) };
988 if cb_binder.is_null() {
989 return Err(CoreError::binder(-1, "AIBinder_new:ITaskFpsCallback"));
990 }
991 unsafe { (vt.associate_class)(cb_binder, cb_class) };
992
993 let owned = unsafe {
996 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
997 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
998 OwnedFd::from_raw_fd(raw)
999 };
1000
1001 let consumer = owned.try_clone()
1002 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:fps"))?;
1003
1004 FPS_READ_I32.store(vt.read_int32 as usize, Ordering::Relaxed);
1007 FPS_CODE.store(on_fps_code, Ordering::Relaxed);
1008 FPS_VALUE.store(0, Ordering::Relaxed);
1009 *fps_eventfd_guard() = Some(owned);
1010
1011 unsafe { (vt.set_thread_pool_max)(0) };
1012 let join_fn = vt.join_thread_pool;
1013 std::thread::spawn(move || unsafe { join_fn() });
1014
1015 Ok((Self {
1016 _lib: lib, vt, window, cb_binder, _wm_class: wm_class,
1017 register_code, unregister_code, task_id: -1,
1018 }, consumer))
1019 }
1020
1021 pub fn register(&mut self, task_id: i32) -> Result<(), CoreError> {
1025 if self.task_id == task_id {
1026 return Ok(());
1027 }
1028 if self.task_id >= 0 {
1029 let _ = self.unregister();
1030 }
1031
1032 let mut inp: *mut AParcel = std::ptr::null_mut();
1033 let s = unsafe { (self.vt.prepare_transaction)(self.window.ptr, &mut inp) };
1034 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:registerTaskFpsCallback")); }
1035 let s = unsafe { (self.vt.write_int32)(inp, task_id) };
1036 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeInt32:taskId")); }
1037 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1038 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1039 let mut out: *mut AParcel = std::ptr::null_mut();
1040 let s = unsafe {
1041 (self.vt.transact)(self.window.ptr, self.register_code, &mut inp, &mut out, 0)
1042 };
1043 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1044 if s != STATUS_OK {
1045 return Err(CoreError::binder(s, "transact:registerTaskFpsCallback"));
1046 }
1047 self.task_id = task_id;
1048 Ok(())
1049 }
1050
1051 pub fn unregister(&mut self) -> Result<(), CoreError> {
1054 if self.task_id < 0 {
1055 return Ok(());
1056 }
1057 let mut inp: *mut AParcel = std::ptr::null_mut();
1058 let s = unsafe { (self.vt.prepare_transaction)(self.window.ptr, &mut inp) };
1059 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:unregisterTaskFpsCallback")); }
1060 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1061 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1062 let mut out: *mut AParcel = std::ptr::null_mut();
1063 let s = unsafe {
1064 (self.vt.transact)(self.window.ptr, self.unregister_code, &mut inp, &mut out, 0)
1065 };
1066 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1067 if s != STATUS_OK {
1068 return Err(CoreError::binder(s, "transact:unregisterTaskFpsCallback"));
1069 }
1070 self.task_id = -1;
1071 Ok(())
1072 }
1073
1074 pub fn last_fps(&self) -> Option<f32> {
1078 let bits = FPS_VALUE.load(Ordering::Relaxed);
1079 if bits == 0 { None } else { Some(f32::from_bits(bits)) }
1080 }
1081
1082 pub fn task_id(&self) -> Option<i32> {
1084 (self.task_id >= 0).then_some(self.task_id)
1085 }
1086 }
1087
1088 const TASK_SERVICE: &[u8] = b"activity_task\0";
1091 const ATM_DESCRIPTOR: &[u8] = b"android.app.IActivityTaskManager\0";
1092 const TASK_STACK_DESCRIPTOR: &[u8] = b"android.app.ITaskStackListener\0";
1093 static TASK_STACK_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
1096
1097 fn task_stack_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
1098 TASK_STACK_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
1099 }
1100
1101 unsafe extern "C" fn atm_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
1105 unsafe extern "C" fn atm_on_destroy(_: *mut c_void) {}
1106 unsafe extern "C" fn atm_on_transact(
1107 _: *mut AIBinder, _: u32, _: *const AParcel, _: *mut AParcel,
1108 ) -> BinderStatus { STATUS_OK }
1109
1110 unsafe extern "C" fn task_stack_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
1117 unsafe extern "C" fn task_stack_on_destroy(_: *mut c_void) {}
1118 unsafe extern "C" fn task_stack_on_transact(
1119 _: *mut AIBinder, _code: u32, _in_parcel: *const AParcel, _reply: *mut AParcel,
1120 ) -> BinderStatus {
1121 if let Some(fd) = task_stack_eventfd_guard().as_ref() {
1122 let val: u64 = 1;
1123 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
1124 }
1125 STATUS_OK
1126 }
1127
1128 pub struct TaskStackListener {
1148 _lib: DlHandle,
1149 vt: Vtable,
1150 service: OwnedBinder,
1151 cb_binder: *mut AIBinder,
1152 _atm_class: *mut AIBinder_Class,
1153 register_code: u32,
1154 unregister_code: u32,
1155 }
1156 unsafe impl Send for TaskStackListener {}
1157
1158 impl TaskStackListener {
1159 pub fn open() -> Result<(Self, OwnedFd), CoreError> {
1163 let handle = unsafe {
1164 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
1165 };
1166 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
1167 let lib = DlHandle(handle);
1168 let vt = load_vtable(handle)?;
1169
1170 let (register_code, unregister_code) =
1171 crate::dex::resolve_task_stack_codes()
1172 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_registerTaskStackListener not found"))?;
1173
1174 let service = {
1175 let raw = unsafe { (vt.get_service)(TASK_SERVICE.as_ptr() as *const c_char) };
1176 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:activity_task")); }
1177 OwnedBinder { ptr: raw, dec_strong: vt.dec_strong }
1178 };
1179
1180 let atm_class = unsafe {
1183 (vt.class_define)(
1184 ATM_DESCRIPTOR.as_ptr() as *const c_char,
1185 atm_on_create, atm_on_destroy, atm_on_transact,
1186 )
1187 };
1188 if atm_class.is_null() {
1189 return Err(CoreError::binder(-1, "AIBinder_Class_define:IActivityTaskManager"));
1190 }
1191 unsafe { (vt.associate_class)(service.ptr, atm_class) };
1192
1193 let cb_class = unsafe {
1194 (vt.class_define)(
1195 TASK_STACK_DESCRIPTOR.as_ptr() as *const c_char,
1196 task_stack_on_create, task_stack_on_destroy, task_stack_on_transact,
1197 )
1198 };
1199 if cb_class.is_null() {
1200 return Err(CoreError::binder(-1, "AIBinder_Class_define:ITaskStackListener"));
1201 }
1202
1203 let cb_binder = unsafe { (vt.new_binder)(cb_class, std::ptr::null_mut()) };
1204 if cb_binder.is_null() {
1205 return Err(CoreError::binder(-1, "AIBinder_new:ITaskStackListener"));
1206 }
1207 unsafe { (vt.associate_class)(cb_binder, cb_class) };
1208
1209 let owned = unsafe {
1212 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
1213 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
1214 OwnedFd::from_raw_fd(raw)
1215 };
1216
1217 let consumer = owned.try_clone()
1218 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:task_stack"))?;
1219
1220 *task_stack_eventfd_guard() = Some(owned);
1221
1222 unsafe { (vt.set_thread_pool_max)(0) };
1223 let join_fn = vt.join_thread_pool;
1224 std::thread::spawn(move || unsafe { join_fn() });
1225
1226 Ok((Self {
1227 _lib: lib, vt, service, cb_binder, _atm_class: atm_class,
1228 register_code, unregister_code,
1229 }, consumer))
1230 }
1231
1232 pub fn register(&self) -> Result<(), CoreError> {
1236 let mut inp: *mut AParcel = std::ptr::null_mut();
1237 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1238 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:registerTaskStackListener")); }
1239 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1240 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1241 let mut out: *mut AParcel = std::ptr::null_mut();
1242 let s = unsafe {
1243 (self.vt.transact)(self.service.ptr, self.register_code, &mut inp, &mut out, 0)
1244 };
1245 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1246 if s != STATUS_OK {
1247 return Err(CoreError::binder(s, "transact:registerTaskStackListener"));
1248 }
1249 Ok(())
1250 }
1251
1252 pub fn unregister(&self) -> Result<(), CoreError> {
1256 let mut inp: *mut AParcel = std::ptr::null_mut();
1257 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1258 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:unregisterTaskStackListener")); }
1259 let s = unsafe { (self.vt.write_strong_binder)(inp, self.cb_binder) };
1260 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeStrongBinder")); }
1261 let mut out: *mut AParcel = std::ptr::null_mut();
1262 let s = unsafe {
1263 (self.vt.transact)(self.service.ptr, self.unregister_code, &mut inp, &mut out, 0)
1264 };
1265 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1266 if s != STATUS_OK {
1267 return Err(CoreError::binder(s, "transact:unregisterTaskStackListener"));
1268 }
1269 Ok(())
1270 }
1271 }
1272
1273 pub struct RawBinderService {
1282 _lib: DlHandle,
1283 vt: Vtable,
1284 service: OwnedBinder,
1285 }
1286 unsafe impl Send for RawBinderService {}
1287
1288 impl RawBinderService {
1289 pub fn open(service_name: &str) -> Result<Self, CoreError> {
1291 use std::ffi::CString;
1292 let handle = unsafe {
1293 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
1294 };
1295 if handle.is_null() {
1296 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
1297 }
1298 let lib = DlHandle(handle);
1299 let vt = load_vtable(handle)?;
1300 let cs = CString::new(service_name)
1301 .map_err(|_| CoreError::binder(-1, "service_name:nul_byte"))?;
1302 let raw = unsafe { (vt.get_service)(cs.as_ptr()) };
1303 if raw.is_null() {
1304 return Err(CoreError::binder(-1, "AServiceManager_getService:null"));
1305 }
1306 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
1307 Ok(Self { _lib: lib, vt, service })
1308 }
1309
1310 pub fn transact_bool(&self, code: u32) -> Result<bool, CoreError> {
1312 let out = self.raw_noarg(code)?;
1313 let r = ParcelReader { vt: &self.vt, parcel: &out };
1314 let ex = r.read_i32()?;
1315 if ex != EX_NONE { return Err(CoreError::binder(ex, "transact_bool:exception")); }
1316 if let Some(rb) = self.vt.read_bool {
1317 let mut v = false;
1318 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
1319 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readBool")); }
1320 Ok(v)
1321 } else {
1322 Ok(r.read_i32()? != 0)
1323 }
1324 }
1325
1326 pub fn transact_i32(&self, code: u32, arg: i32) -> Result<(), CoreError> {
1328 let mut inp: *mut AParcel = std::ptr::null_mut();
1329 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1330 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
1331 let s = unsafe { (self.vt.write_int32)(inp, arg) };
1332 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeInt32")); }
1333 let mut out: *mut AParcel = std::ptr::null_mut();
1334 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
1335 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
1336 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
1337 Ok(())
1338 }
1339
1340 fn raw_noarg(&self, code: u32) -> Result<OwnedParcel, CoreError> {
1341 let mut inp: *mut AParcel = std::ptr::null_mut();
1342 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
1343 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
1344 let mut out: *mut AParcel = std::ptr::null_mut();
1345 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
1346 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
1347 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
1348 Ok(out)
1349 }
1350 }
1351}
1352
1353#[cfg(target_os = "android")]
1356pub use imp::{ActivityManagerBinder, DisplayManagerBinder, FpsListener, RawBinderService, TaskStackListener, TxCodes, last_foreground_pid, resolve_tx_codes};
1357
1358#[cfg(not(target_os = "android"))]
1361pub struct ActivityManagerBinder;
1362
1363#[cfg(not(target_os = "android"))]
1364impl ActivityManagerBinder {
1365 pub fn open() -> Result<Self, crate::CoreError> {
1366 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1367 }
1368 pub fn open_with_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1369 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1370 }
1371 pub fn open_with_fgproc_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1372 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1373 }
1374 pub fn get_focused_task(&self) -> Result<Option<(i32, Option<String>)>, crate::CoreError> {
1375 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1376 }
1377 pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
1378 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1379 }
1380 pub fn get_focused_task_id(&self) -> Result<Option<i32>, crate::CoreError> {
1381 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1382 }
1383}
1384
1385#[cfg(not(target_os = "android"))]
1386pub struct DisplayManagerBinder;
1387
1388#[cfg(not(target_os = "android"))]
1389impl DisplayManagerBinder {
1390 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), crate::CoreError> {
1391 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1392 }
1393 pub fn is_interactive(&self) -> Result<bool, crate::CoreError> {
1394 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1395 }
1396}
1397
1398#[cfg(not(target_os = "android"))]
1399pub struct RawBinderService;
1400
1401#[cfg(not(target_os = "android"))]
1402impl RawBinderService {
1403 pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
1404 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1405 }
1406 pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
1407 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1408 }
1409 pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
1410 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1411 }
1412}
1413
1414#[cfg(not(target_os = "android"))]
1415pub struct FpsListener;
1416
1417#[cfg(not(target_os = "android"))]
1418impl FpsListener {
1419 pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1420 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1421 }
1422 pub fn register(&mut self, _task_id: i32) -> Result<(), crate::CoreError> {
1423 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1424 }
1425 pub fn unregister(&mut self) -> Result<(), crate::CoreError> {
1426 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1427 }
1428 pub fn last_fps(&self) -> Option<f32> {
1429 None
1430 }
1431 pub fn task_id(&self) -> Option<i32> {
1432 None
1433 }
1434}
1435
1436#[cfg(not(target_os = "android"))]
1437pub struct TaskStackListener;
1438
1439#[cfg(not(target_os = "android"))]
1440impl TaskStackListener {
1441 pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1442 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1443 }
1444 pub fn register(&self) -> Result<(), crate::CoreError> {
1445 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1446 }
1447 pub fn unregister(&self) -> Result<(), crate::CoreError> {
1448 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1449 }
1450}
1451
1452#[cfg(not(target_os = "android"))]
1453pub struct TxCodes { pub observer_code: u32, pub query_code: u32, pub api_mode: u8, pub fg_code: u32 }
1454
1455#[cfg(not(target_os = "android"))]
1456pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
1457 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1458}
1459
1460#[cfg(not(target_os = "android"))]
1461pub fn last_foreground_pid() -> i32 {
1462 0
1463}