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::Mutex;
33 use std::sync::atomic::{AtomicBool, AtomicI32, AtomicU32, AtomicUsize, Ordering};
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 {
103 std::ptr::null_mut()
104 }
105 unsafe extern "C" fn am_on_destroy(_: *mut c_void) {}
106 unsafe extern "C" fn am_on_transact(
107 _: *mut AIBinder,
108 _: u32,
109 _: *const AParcel,
110 _: *mut AParcel,
111 ) -> BinderStatus {
112 STATUS_UNKNOWN_TRANSACTION
113 }
114
115 unsafe extern "C" fn obs_on_create(_: *mut c_void) -> *mut c_void {
117 std::ptr::null_mut()
118 }
119 unsafe extern "C" fn obs_on_destroy(_: *mut c_void) {}
120 unsafe extern "C" fn obs_on_transact(
121 _: *mut AIBinder,
122 code: u32,
123 _: *const AParcel,
124 _: *mut AParcel,
125 ) -> BinderStatus {
126 if code == OBS_FG_CODE.load(Ordering::Relaxed) {
127 if let Some(fd) = obs_eventfd_guard().as_ref() {
130 let val: u64 = 1;
131 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
132 }
133 }
134 STATUS_OK
135 }
136
137 unsafe extern "C" fn fgproc_on_create(_: *mut c_void) -> *mut c_void {
146 std::ptr::null_mut()
147 }
148 unsafe extern "C" fn fgproc_on_destroy(_: *mut c_void) {}
149 unsafe extern "C" fn fgproc_on_transact(
150 _: *mut AIBinder,
151 code: u32,
152 in_parcel: *const AParcel,
153 _: *mut AParcel,
154 ) -> BinderStatus {
155 if code != FGPROC_FG_CODE.load(Ordering::Relaxed) {
156 return STATUS_UNKNOWN_TRANSACTION;
157 }
158 let read_addr = FGPROC_READ_I32.load(Ordering::Relaxed);
161 if read_addr != 0 {
162 let read_fn: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus =
163 unsafe { std::mem::transmute(read_addr) };
164 if FGPROC_IPROC_MODE.load(Ordering::Relaxed) == 1 {
165 let mut pid: i32 = 0;
167 let mut _uid: i32 = 0;
168 let mut fg: i32 = 0;
169 let mut ok = unsafe { read_fn(in_parcel, &mut pid) } == STATUS_OK;
170 ok &= unsafe { read_fn(in_parcel, &mut _uid) } == STATUS_OK;
171 ok &= unsafe { read_fn(in_parcel, &mut fg) } == STATUS_OK;
172 if ok {
173 FGPROC_PID.store(pid, Ordering::Relaxed);
174 if fg == 0 {
177 return STATUS_OK;
178 }
179 } else {
180 return STATUS_OK;
181 }
182 } else {
183 let mut pid: i32 = 0;
184 if unsafe { read_fn(in_parcel, &mut pid) } == STATUS_OK {
185 FGPROC_PID.store(pid, Ordering::Relaxed);
186 }
187 }
188 }
189 if let Some(fd) = fgproc_eventfd_guard().as_ref() {
192 let val: u64 = 1;
193 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
194 }
195 STATUS_OK
196 }
197
198 pub fn last_foreground_pid() -> i32 {
201 FGPROC_PID.load(Ordering::Relaxed)
202 }
203
204 const MAX_BINDER_STRING_LEN: usize = 1024 * 1024;
211
212 unsafe extern "C" fn string_alloc(
213 cookie: *mut c_void,
214 length: i32,
215 buffer: *mut *mut c_char,
216 ) -> bool {
217 if length < 0 {
221 return false;
222 }
223 let len = length as usize;
224 if len > MAX_BINDER_STRING_LEN {
225 return false;
226 }
227 let s = unsafe { &mut *(cookie as *mut StringBuf) };
228 s.0.reserve_exact(len + 1);
229 unsafe { s.0.as_mut_vec().resize(len + 1, 0) };
230 unsafe { *buffer = s.0.as_mut_ptr() as *mut c_char };
231 true
232 }
233
234 struct StringBuf(String);
235 impl StringBuf {
236 fn new() -> Self {
237 Self(String::new())
238 }
239 fn finish(mut self) -> Option<String> {
240 if let Some(pos) = self.0.as_bytes().iter().position(|&b| b == 0) {
241 unsafe { self.0.as_mut_vec().truncate(pos) };
242 }
243 if self.0.is_empty() {
244 None
245 } else {
246 Some(self.0)
247 }
248 }
249 }
250
251 struct Vtable {
254 get_service: unsafe extern "C" fn(*const c_char) -> *mut AIBinder,
255 class_define: unsafe extern "C" fn(
256 *const c_char,
257 unsafe extern "C" fn(*mut c_void) -> *mut c_void,
258 unsafe extern "C" fn(*mut c_void),
259 unsafe extern "C" fn(*mut AIBinder, u32, *const AParcel, *mut AParcel) -> BinderStatus,
260 ) -> *mut AIBinder_Class,
261 associate_class: unsafe extern "C" fn(*mut AIBinder, *mut AIBinder_Class) -> bool,
262 new_binder: unsafe extern "C" fn(*const AIBinder_Class, *mut c_void) -> *mut AIBinder,
263 prepare_transaction: unsafe extern "C" fn(*mut AIBinder, *mut *mut AParcel) -> BinderStatus,
264 transact: unsafe extern "C" fn(
265 *mut AIBinder,
266 u32,
267 *mut *mut AParcel,
268 *mut *mut AParcel,
269 u32,
270 ) -> BinderStatus,
271 dec_strong: unsafe extern "C" fn(*mut AIBinder),
272 parcel_delete: unsafe extern "C" fn(*mut AParcel),
273 read_int32: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus,
274 read_string:
275 unsafe extern "C" fn(*const AParcel, *mut c_void, StringAllocator) -> BinderStatus,
276 write_strong_binder: unsafe extern "C" fn(*mut AParcel, *mut AIBinder) -> BinderStatus,
277 set_thread_pool_max: unsafe extern "C" fn(u32),
278 join_thread_pool: unsafe extern "C" fn(),
279 get_user_data: unsafe extern "C" fn(*const AIBinder) -> *mut c_void,
280 write_int32: unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus,
281 read_bool: Option<unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus>,
283 }
284
285 struct DlHandle;
288 unsafe impl Send for DlHandle {}
289 impl Drop for DlHandle {
290 fn drop(&mut self) {
291 }
297 }
298
299 struct OwnedParcel {
300 ptr: *mut AParcel,
301 delete: unsafe extern "C" fn(*mut AParcel),
302 }
303 impl Drop for OwnedParcel {
304 fn drop(&mut self) {
305 if !self.ptr.is_null() {
306 unsafe { (self.delete)(self.ptr) };
307 }
308 }
309 }
310
311 struct OwnedBinder {
312 ptr: *mut AIBinder,
313 dec_strong: unsafe extern "C" fn(*mut AIBinder),
314 }
315 unsafe impl Send for OwnedBinder {}
316 impl Drop for OwnedBinder {
317 fn drop(&mut self) {
318 if !self.ptr.is_null() {
319 unsafe { (self.dec_strong)(self.ptr) };
320 }
321 }
322 }
323
324 macro_rules! dlsym_fn {
327 ($handle:expr, $name:literal, $ty:ty) => {{
328 let sym =
329 unsafe { libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char) };
330 if sym.is_null() {
331 return Err(CoreError::binder(-1, concat!("dlsym:", $name)));
332 }
333 unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) }
334 }};
335 }
336
337 macro_rules! dlsym_opt {
338 ($handle:expr, $name:literal, $ty:ty) => {{
339 let sym =
340 unsafe { libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char) };
341 if sym.is_null() {
342 None
343 } else {
344 Some(unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) })
345 }
346 }};
347 }
348
349 fn load_vtable(handle: *mut c_void) -> Result<Vtable, CoreError> {
350 Ok(Vtable {
351 get_service: dlsym_fn!(
352 handle,
353 "AServiceManager_getService",
354 unsafe extern "C" fn(*const c_char) -> *mut AIBinder
355 ),
356 class_define: dlsym_fn!(
357 handle,
358 "AIBinder_Class_define",
359 unsafe extern "C" fn(
360 *const c_char,
361 unsafe extern "C" fn(*mut c_void) -> *mut c_void,
362 unsafe extern "C" fn(*mut c_void),
363 unsafe extern "C" fn(
364 *mut AIBinder,
365 u32,
366 *const AParcel,
367 *mut AParcel,
368 ) -> BinderStatus,
369 ) -> *mut AIBinder_Class
370 ),
371 associate_class: dlsym_fn!(
372 handle,
373 "AIBinder_associateClass",
374 unsafe extern "C" fn(*mut AIBinder, *mut AIBinder_Class) -> bool
375 ),
376 new_binder: dlsym_fn!(
377 handle,
378 "AIBinder_new",
379 unsafe extern "C" fn(*const AIBinder_Class, *mut c_void) -> *mut AIBinder
380 ),
381 prepare_transaction: dlsym_fn!(
382 handle,
383 "AIBinder_prepareTransaction",
384 unsafe extern "C" fn(*mut AIBinder, *mut *mut AParcel) -> BinderStatus
385 ),
386 transact: dlsym_fn!(
387 handle,
388 "AIBinder_transact",
389 unsafe extern "C" fn(
390 *mut AIBinder,
391 u32,
392 *mut *mut AParcel,
393 *mut *mut AParcel,
394 u32,
395 ) -> BinderStatus
396 ),
397 dec_strong: dlsym_fn!(
398 handle,
399 "AIBinder_decStrong",
400 unsafe extern "C" fn(*mut AIBinder)
401 ),
402 parcel_delete: dlsym_fn!(handle, "AParcel_delete", unsafe extern "C" fn(*mut AParcel)),
403 read_int32: dlsym_fn!(
404 handle,
405 "AParcel_readInt32",
406 unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus
407 ),
408 read_string: dlsym_fn!(
409 handle,
410 "AParcel_readString",
411 unsafe extern "C" fn(*const AParcel, *mut c_void, StringAllocator) -> BinderStatus
412 ),
413 write_strong_binder: dlsym_fn!(
414 handle,
415 "AParcel_writeStrongBinder",
416 unsafe extern "C" fn(*mut AParcel, *mut AIBinder) -> BinderStatus
417 ),
418 set_thread_pool_max: dlsym_fn!(
419 handle,
420 "ABinderProcess_setThreadPoolMaxThreadCount",
421 unsafe extern "C" fn(u32)
422 ),
423 join_thread_pool: dlsym_fn!(
424 handle,
425 "ABinderProcess_joinThreadPool",
426 unsafe extern "C" fn()
427 ),
428 get_user_data: dlsym_fn!(
429 handle,
430 "AIBinder_getUserData",
431 unsafe extern "C" fn(*const AIBinder) -> *mut c_void
432 ),
433 write_int32: dlsym_fn!(
434 handle,
435 "AParcel_writeInt32",
436 unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus
437 ),
438 read_bool: dlsym_opt!(
439 handle,
440 "AParcel_readBool",
441 unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus
442 ),
443 })
444 }
445
446 struct ParcelReader<'a> {
449 vt: &'a Vtable,
450 parcel: &'a OwnedParcel,
451 }
452
453 impl<'a> ParcelReader<'a> {
454 fn read_i32(&self) -> Result<i32, CoreError> {
455 let mut v = 0i32;
456 let s = unsafe { (self.vt.read_int32)(self.parcel.ptr, &mut v) };
457 if s != STATUS_OK {
458 return Err(CoreError::binder(s, "AParcel_readInt32"));
459 }
460 Ok(v)
461 }
462 fn read_string(&self) -> Result<Option<String>, CoreError> {
463 let mut buf = StringBuf::new();
464 let s = unsafe {
465 (self.vt.read_string)(
466 self.parcel.ptr,
467 &mut buf as *mut StringBuf as *mut c_void,
468 string_alloc,
469 )
470 };
471 if s != STATUS_OK {
472 return Err(CoreError::binder(s, "AParcel_readString"));
473 }
474 Ok(buf.finish())
475 }
476 fn skip_i32s(&self, n: usize) -> Result<(), CoreError> {
477 for _ in 0..n {
478 self.read_i32()?;
479 }
480 Ok(())
481 }
482 fn skip_int_array(&self) -> Result<(), CoreError> {
483 let count = self.read_i32()?.max(0) as usize;
484 self.skip_i32s(count)
485 }
486 fn read_first_package_from_names(&self) -> Result<Option<String>, CoreError> {
487 let count = self.read_i32()?.max(0) as usize;
488 let mut first: Option<String> = None;
489 for _ in 0..count {
490 let s = self.read_string()?;
491 if first.is_none() {
492 first = s.and_then(|c| c.split('/').next().map(str::to_owned));
493 }
494 }
495 Ok(first)
496 }
497 }
498
499 struct ParcelWriter<'a> {
502 vt: &'a Vtable,
503 parcel: &'a OwnedParcel,
504 }
505
506 impl<'a> ParcelWriter<'a> {
507 fn write_i32(&self, v: i32) -> Result<(), CoreError> {
508 let s = unsafe { (self.vt.write_int32)(self.parcel.ptr, v) };
509 if s != STATUS_OK {
510 return Err(CoreError::binder(s, "AParcel_writeInt32"));
511 }
512 Ok(())
513 }
514 fn write_strong_binder(&self, b: *mut AIBinder) -> Result<(), CoreError> {
515 let s = unsafe { (self.vt.write_strong_binder)(self.parcel.ptr, b) };
516 if s != STATUS_OK {
517 return Err(CoreError::binder(s, "AParcel_writeStrongBinder"));
518 }
519 Ok(())
520 }
521 }
522
523 fn transact_write(
530 vt: &Vtable,
531 binder: *mut AIBinder,
532 code: u32,
533 writes: impl FnOnce(&ParcelWriter<'_>) -> Result<(), CoreError>,
534 ) -> Result<OwnedParcel, CoreError> {
535 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
536 let s = unsafe { (vt.prepare_transaction)(binder, &mut in_ptr) };
537 if s != STATUS_OK {
538 return Err(CoreError::binder(s, "AIBinder_prepareTransaction"));
539 }
540 let mut inp = OwnedParcel {
541 ptr: in_ptr,
542 delete: vt.parcel_delete,
543 };
544 {
545 let writer = ParcelWriter { vt, parcel: &inp };
546 writes(&writer)?;
547 }
548 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
549 let s = unsafe { (vt.transact)(binder, code, &mut inp.ptr, &mut out_ptr, 0) };
550 inp.ptr = std::ptr::null_mut();
552 let out = OwnedParcel {
553 ptr: out_ptr,
554 delete: vt.parcel_delete,
555 };
556 if s != STATUS_OK {
557 return Err(CoreError::binder(s, "AIBinder_transact"));
558 }
559 Ok(out)
560 }
561
562 fn parse_stack_info_body(r: &ParcelReader<'_>) -> Result<Option<String>, CoreError> {
565 r.skip_i32s(5)?;
566 r.skip_int_array()?;
567 r.read_first_package_from_names()
568 }
569
570 fn parse_root_task_info_task(r: &ParcelReader<'_>) -> Result<(i32, Option<String>), CoreError> {
577 let scratch = r.read_i32()?;
578 if scratch != 0 {
579 r.skip_i32s(4)?;
580 }
581 r.skip_int_array()?; let pkg = r.read_first_package_from_names()?; let bounds_count = r.read_i32()?;
585 let n = if bounds_count < 0 {
586 0
587 } else {
588 bounds_count as usize
589 };
590 for _ in 0..n {
591 let entry = r.read_i32()?;
592 if entry != 0 {
593 r.skip_i32s(4)?;
594 }
595 }
596 r.skip_int_array()?; r.skip_i32s(2)?; r.skip_i32s(1)?; let task_id = r.read_i32()?;
600 Ok((task_id, pkg))
601 }
602
603 pub struct TxCodes {
606 pub observer_code: u32,
607 pub query_code: u32,
608 pub api_mode: u8, pub fg_code: u32,
610 }
611
612 pub fn resolve_tx_codes() -> Result<TxCodes, CoreError> {
613 let (obs, query, api, fg) = dex::resolve_tx_codes_from_dex()
614 .ok_or_else(|| CoreError::binder(-1, "tx_code_resolution:dex_parse_failed"))?;
615 Ok(TxCodes {
616 observer_code: obs,
617 query_code: query,
618 api_mode: api,
619 fg_code: fg,
620 })
621 }
622
623 pub struct ActivityManagerBinder {
626 _lib: DlHandle,
627 vt: Vtable,
628 _class: *mut AIBinder_Class,
629 service: OwnedBinder,
630 tx_code: u32,
631 legacy: bool,
632 }
633 unsafe impl Send for ActivityManagerBinder {}
634
635 impl ActivityManagerBinder {
636 fn open_inner(
637 handle: *mut c_void,
638 ) -> Result<(DlHandle, Vtable, *mut AIBinder_Class, OwnedBinder), CoreError> {
639 let lib = DlHandle;
640 let vt = load_vtable(handle)?;
641
642 let am_class = unsafe {
643 (vt.class_define)(
644 AM_DESCRIPTOR.as_ptr() as *const c_char,
645 am_on_create,
646 am_on_destroy,
647 am_on_transact,
648 )
649 };
650 if am_class.is_null() {
651 return Err(CoreError::binder(-1, "AIBinder_Class_define:AM"));
652 }
653
654 let raw = unsafe { (vt.get_service)(ACTIVITY_SERVICE.as_ptr() as *const c_char) };
655 if raw.is_null() {
656 return Err(CoreError::binder(-1, "AServiceManager_getService:activity"));
657 }
658 unsafe { (vt.associate_class)(raw, am_class) };
659
660 let service = OwnedBinder {
661 ptr: raw,
662 dec_strong: vt.dec_strong,
663 };
664 Ok((lib, vt, am_class, service))
665 }
666
667 fn dlopen_libbinder() -> Result<*mut c_void, CoreError> {
668 use std::os::raw::c_char;
669 let handle = unsafe {
670 libc::dlopen(
671 LIBBINDER_PATH.as_ptr() as *const c_char,
672 libc::RTLD_NOW | libc::RTLD_LOCAL,
673 )
674 };
675 if handle.is_null() {
676 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
677 }
678 Ok(handle)
679 }
680
681 pub fn open() -> Result<Self, CoreError> {
684 let handle = Self::dlopen_libbinder()?;
685 let (lib, vt, class, service) = Self::open_inner(handle)?;
686 let codes = resolve_tx_codes()?;
687 let legacy = codes.api_mode == 2;
688 Ok(Self {
689 _lib: lib,
690 vt,
691 _class: class,
692 service,
693 tx_code: codes.query_code,
694 legacy,
695 })
696 }
697
698 pub fn open_with_observer() -> Result<(Self, OwnedFd), CoreError> {
707 let handle = Self::dlopen_libbinder()?;
708 let (lib, vt, am_class, service) = Self::open_inner(handle)?;
709 let codes = resolve_tx_codes()?;
710 let legacy = codes.api_mode == 2;
711
712 let owned = unsafe {
715 let raw = libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC);
716 if raw < 0 {
717 return Err(CoreError::sys(*libc::__errno(), "eventfd"));
718 }
719 OwnedFd::from_raw_fd(raw)
720 };
721
722 let obs_class = unsafe {
724 (vt.class_define)(
725 OBS_DESCRIPTOR.as_ptr() as *const c_char,
726 obs_on_create,
727 obs_on_destroy,
728 obs_on_transact,
729 )
730 };
731 if obs_class.is_null() {
732 return Err(CoreError::binder(-1, "AIBinder_Class_define:Observer"));
733 }
734
735 let obs_binder = unsafe { (vt.new_binder)(obs_class, std::ptr::null_mut()) };
737 if obs_binder.is_null() {
738 return Err(CoreError::binder(-1, "AIBinder_new:Observer"));
739 }
740 unsafe { (vt.associate_class)(obs_binder, obs_class) };
741
742 let _ = transact_write(&vt, service.ptr, codes.observer_code, |w| {
744 w.write_strong_binder(obs_binder)
745 })?;
746
747 let consumer = owned
750 .try_clone()
751 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:observer"))?;
752
753 OBS_FG_CODE.store(codes.fg_code, Ordering::Relaxed);
755 *obs_eventfd_guard() = Some(owned);
756
757 unsafe { (vt.set_thread_pool_max)(0) };
759 let join_fn = vt.join_thread_pool;
760 std::thread::spawn(move || unsafe { join_fn() });
761
762 let binder = Self {
763 _lib: lib,
764 vt,
765 _class: am_class,
766 service,
767 tx_code: codes.query_code,
768 legacy,
769 };
770 Ok((binder, consumer))
771 }
772
773 pub fn open_with_fgproc_observer() -> Result<(Self, OwnedFd), CoreError> {
797 let handle = Self::dlopen_libbinder()?;
798 let (lib, vt, am_class, service) = Self::open_inner(handle)?;
799
800 let (register_code, fgproc_code, mode, descriptor): (u32, u32, u32, &[u8]) =
805 match crate::dex::resolve_fgproc_codes() {
806 Some((r, c)) => (r, c, 0, FGPROC_DESCRIPTOR),
807 None => match crate::dex::resolve_fgproc_codes_fallback() {
808 Some((r, c)) => (r, c, 1, OBS_DESCRIPTOR),
809 None => {
810 return Err(CoreError::binder(
811 -1,
812 "tx_code_resolution:fgproc_dex_parse_failed",
813 ));
814 }
815 },
816 };
817
818 let owned = unsafe {
821 let raw = libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC);
822 if raw < 0 {
823 return Err(CoreError::sys(*libc::__errno(), "eventfd"));
824 }
825 OwnedFd::from_raw_fd(raw)
826 };
827
828 let obs_class = unsafe {
831 (vt.class_define)(
832 descriptor.as_ptr() as *const c_char,
833 fgproc_on_create,
834 fgproc_on_destroy,
835 fgproc_on_transact,
836 )
837 };
838 if obs_class.is_null() {
839 return Err(CoreError::binder(
840 -1,
841 "AIBinder_Class_define:FGProcessObserver",
842 ));
843 }
844
845 let obs_binder = unsafe { (vt.new_binder)(obs_class, std::ptr::null_mut()) };
847 if obs_binder.is_null() {
848 return Err(CoreError::binder(-1, "AIBinder_new:FGProcessObserver"));
849 }
850 unsafe { (vt.associate_class)(obs_binder, obs_class) };
851
852 let _ = transact_write(&vt, service.ptr, register_code, |w| {
855 w.write_strong_binder(obs_binder)
856 })?;
857
858 let consumer = owned.try_clone().map_err(|e| {
861 CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:fgproc_observer")
862 })?;
863
864 FGPROC_READ_I32.store(vt.read_int32 as usize, Ordering::Relaxed);
869 FGPROC_IPROC_MODE.store(mode, Ordering::Relaxed);
870 FGPROC_FG_CODE.store(fgproc_code, Ordering::Relaxed);
871 FGPROC_PID.store(0, Ordering::Relaxed);
872 *fgproc_eventfd_guard() = Some(owned);
873
874 unsafe { (vt.set_thread_pool_max)(0) };
876 let join_fn = vt.join_thread_pool;
877 std::thread::spawn(move || unsafe { join_fn() });
878
879 let binder = Self {
880 _lib: lib,
881 vt,
882 _class: am_class,
883 service,
884 tx_code: 0,
885 legacy: false,
886 };
887 Ok((binder, consumer))
888 }
889
890 fn do_transact(&self) -> Result<OwnedParcel, CoreError> {
891 transact_write(&self.vt, self.service.ptr, self.tx_code, |_| Ok(()))
892 }
893
894 pub fn get_focused_task(&self) -> Result<Option<(i32, Option<String>)>, CoreError> {
901 if self.legacy {
902 return Ok(None);
904 }
905 let out = self.do_transact()?;
906 let r = ParcelReader {
907 vt: &self.vt,
908 parcel: &out,
909 };
910 let ex = r.read_i32()?;
911 if ex != EX_NONE {
912 return Err(CoreError::binder(ex, "getFocusedTask:exception"));
913 }
914 let present = r.read_i32()?;
915 if present == 0 {
916 return Ok(None);
917 }
918 Ok(Some(parse_root_task_info_task(&r)?))
919 }
920
921 pub fn get_focused_package(&self) -> Result<Option<String>, CoreError> {
925 if self.legacy {
926 let out = self.do_transact()?;
927 let r = ParcelReader {
928 vt: &self.vt,
929 parcel: &out,
930 };
931 let ex = r.read_i32()?;
932 if ex != EX_NONE {
933 return Err(CoreError::binder(ex, "getFocusedTask:exception"));
934 }
935 let present = r.read_i32()?;
936 if present == 0 {
937 return Ok(None);
938 }
939 return parse_stack_info_body(&r);
940 }
941 Ok(self.get_focused_task()?.map(|(_, pkg)| pkg).flatten())
942 }
943
944 pub fn get_focused_task_id(&self) -> Result<Option<i32>, CoreError> {
948 Ok(self.get_focused_task()?.map(|(task_id, _)| task_id))
949 }
950 }
951
952 const DISPLAY_SERVICE: &[u8] = b"display\0";
955 const CALLBACK_DESCRIPTOR: &[u8] = b"android.hardware.display.IDisplayManagerCallback\0";
956 const POWER_SERVICE: &[u8] = b"power\0";
957
958 const TX_DISPLAY_REGISTER_CALLBACK: u32 = 4;
959
960 static DISP_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
963
964 fn disp_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
965 DISP_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
966 }
967
968 unsafe extern "C" fn disp_cb_on_create(_: *mut c_void) -> *mut c_void {
969 std::ptr::null_mut()
970 }
971 unsafe extern "C" fn disp_cb_on_destroy(_: *mut c_void) {}
972 unsafe extern "C" fn disp_cb_on_transact(
973 _: *mut AIBinder,
974 code: u32,
975 _: *const AParcel,
976 _: *mut AParcel,
977 ) -> BinderStatus {
978 if code == 1 {
979 if let Some(fd) = disp_eventfd_guard().as_ref() {
980 let val: u64 = 1;
981 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
982 }
983 }
984 STATUS_OK
985 }
986
987 pub struct DisplayManagerBinder {
988 _lib: DlHandle,
989 vt: Vtable,
990 power: Option<OwnedBinder>,
991 is_interactive_tx: u32,
992 }
993 unsafe impl Send for DisplayManagerBinder {}
994
995 impl DisplayManagerBinder {
996 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), CoreError> {
997 let handle = unsafe {
998 libc::dlopen(
999 LIBBINDER_PATH.as_ptr() as *const c_char,
1000 libc::RTLD_NOW | libc::RTLD_LOCAL,
1001 )
1002 };
1003 if handle.is_null() {
1004 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
1005 }
1006 let lib = DlHandle;
1007 let vt = load_vtable(handle)?;
1008
1009 let owned = unsafe {
1013 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
1014 if raw < 0 {
1015 return Err(CoreError::sys(*libc::__errno(), "eventfd"));
1016 }
1017 OwnedFd::from_raw_fd(raw)
1018 };
1019
1020 let raw_display =
1022 unsafe { (vt.get_service)(DISPLAY_SERVICE.as_ptr() as *const c_char) };
1023 if raw_display.is_null() {
1024 return Err(CoreError::binder(-1, "AServiceManager_getService:display"));
1025 }
1026 let display = OwnedBinder {
1027 ptr: raw_display,
1028 dec_strong: vt.dec_strong,
1029 };
1030
1031 let cb_class = unsafe {
1033 (vt.class_define)(
1034 CALLBACK_DESCRIPTOR.as_ptr() as *const c_char,
1035 disp_cb_on_create,
1036 disp_cb_on_destroy,
1037 disp_cb_on_transact,
1038 )
1039 };
1040 if cb_class.is_null() {
1041 return Err(CoreError::binder(
1042 -1,
1043 "AIBinder_Class_define:DisplayCallback",
1044 ));
1045 }
1046
1047 let cb_binder = unsafe { (vt.new_binder)(cb_class, std::ptr::null_mut()) };
1048 if cb_binder.is_null() {
1049 return Err(CoreError::binder(-1, "AIBinder_new:DisplayCallback"));
1050 }
1051
1052 let _ = transact_write(&vt, display.ptr, TX_DISPLAY_REGISTER_CALLBACK, |w| {
1054 w.write_strong_binder(cb_binder)
1055 })?;
1056
1057 let power = {
1059 let raw = unsafe { (vt.get_service)(POWER_SERVICE.as_ptr() as *const c_char) };
1060 if raw.is_null() {
1061 None
1062 } else {
1063 Some(OwnedBinder {
1064 ptr: raw,
1065 dec_strong: vt.dec_strong,
1066 })
1067 }
1068 };
1069
1070 let is_interactive_tx = crate::dex::resolve_is_interactive_tx()
1072 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_isInteractive not found"))?;
1073
1074 let efd_owned = owned
1077 .try_clone()
1078 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:display"))
1079 .and_then(|dup| unsafe {
1080 crate::reactor::Fd::from_owned_raw_fd(dup.into_raw_fd(), "display.efd")
1081 .map_err(|_| CoreError::binder(-1, "Fd::from_owned_raw_fd:display.efd"))
1082 })?;
1083
1084 *disp_eventfd_guard() = Some(owned);
1086
1087 unsafe { (vt.set_thread_pool_max)(0) };
1089 let join_fn = vt.join_thread_pool;
1090 std::thread::spawn(move || unsafe { join_fn() });
1091
1092 Ok((
1093 Self {
1094 _lib: lib,
1095 vt,
1096 power,
1097 is_interactive_tx,
1098 },
1099 efd_owned,
1100 ))
1101 }
1102
1103 pub fn is_interactive(&self) -> Result<bool, CoreError> {
1104 let power = self
1105 .power
1106 .as_ref()
1107 .ok_or_else(|| CoreError::binder(-1, "power:unavailable"))?;
1108 let out = transact_write(&self.vt, power.ptr, self.is_interactive_tx, |_| Ok(()))?;
1109 let r = ParcelReader {
1110 vt: &self.vt,
1111 parcel: &out,
1112 };
1113 let ex = r.read_i32()?;
1114 if ex != EX_NONE {
1115 return Err(CoreError::binder(ex, "isInteractive:exception"));
1116 }
1117 if let Some(rb) = self.vt.read_bool {
1118 let mut v = false;
1119 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
1120 if s != STATUS_OK {
1121 return Err(CoreError::binder(s, "readBool:isInteractive"));
1122 }
1123 Ok(v)
1124 } else {
1125 Ok(r.read_i32()? != 0)
1126 }
1127 }
1128 }
1129
1130 const WINDOW_SERVICE: &[u8] = b"window\0";
1133 const WM_DESCRIPTOR: &[u8] = b"android.view.IWindowManager\0";
1134 const FPS_DESCRIPTOR: &[u8] = b"android.window.ITaskFpsCallback\0";
1135 static FPS_VALUE: AtomicU32 = AtomicU32::new(0);
1142 static FPS_SEEN: AtomicBool = AtomicBool::new(false);
1147 static FPS_CODE: AtomicU32 = AtomicU32::new(0);
1148 static FPS_READ_I32: AtomicUsize = AtomicUsize::new(0);
1149
1150 unsafe extern "C" fn wm_on_create(_: *mut c_void) -> *mut c_void {
1154 std::ptr::null_mut()
1155 }
1156 unsafe extern "C" fn wm_on_destroy(_: *mut c_void) {}
1157 unsafe extern "C" fn wm_on_transact(
1158 _: *mut AIBinder,
1159 _: u32,
1160 _: *const AParcel,
1161 _: *mut AParcel,
1162 ) -> BinderStatus {
1163 STATUS_OK
1164 }
1165
1166 unsafe extern "C" fn fps_on_create(userdata: *mut c_void) -> *mut c_void {
1172 userdata
1173 }
1174 unsafe extern "C" fn fps_on_destroy(userdata: *mut c_void) {
1175 if !userdata.is_null() {
1176 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1177 }
1178 }
1179 unsafe extern "C" fn fps_on_transact(
1180 binder: *mut AIBinder,
1181 code: u32,
1182 in_parcel: *const AParcel,
1183 _: *mut AParcel,
1184 ) -> BinderStatus {
1185 if code != FPS_CODE.load(Ordering::Relaxed) {
1186 return STATUS_UNKNOWN_TRANSACTION;
1187 }
1188 let read_addr = FPS_READ_I32.load(Ordering::Relaxed);
1191 if read_addr != 0 {
1192 let read_fn: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus =
1193 unsafe { std::mem::transmute(read_addr) };
1194 let mut bits: i32 = 0;
1195 if unsafe { read_fn(in_parcel, &mut bits) } == STATUS_OK {
1196 FPS_VALUE.store(sanitize_fps(bits as u32), Ordering::Relaxed);
1201 FPS_SEEN.store(true, Ordering::Release);
1202 let get_user_data = GET_USER_DATA.lock().unwrap_or_else(|p| p.into_inner());
1208 if let Some(get_user_data) = *get_user_data {
1209 let userdata = unsafe { get_user_data(binder) };
1210 if !userdata.is_null() {
1211 let efd = userdata as *mut OwnedFd;
1212 let val: u64 = 1;
1213 unsafe {
1214 libc::write((*efd).as_raw_fd(), &val as *const u64 as *const c_void, 8)
1215 };
1216 }
1217 }
1218 }
1219 }
1220 STATUS_OK
1221 }
1222
1223 pub struct FpsListener {
1237 _lib: DlHandle,
1238 vt: Vtable,
1239 window: OwnedBinder,
1240 cb_binder: *mut AIBinder,
1241 _wm_class: *mut AIBinder_Class,
1242 register_code: u32,
1243 unregister_code: u32,
1244 task_id: i32,
1245 }
1246 unsafe impl Send for FpsListener {}
1247
1248 impl FpsListener {
1249 pub fn open() -> Result<(Self, OwnedFd), CoreError> {
1255 let handle = unsafe {
1256 libc::dlopen(
1257 LIBBINDER_PATH.as_ptr() as *const c_char,
1258 libc::RTLD_NOW | libc::RTLD_LOCAL,
1259 )
1260 };
1261 if handle.is_null() {
1262 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
1263 }
1264 let lib = DlHandle;
1265 let vt = load_vtable(handle)?;
1266
1267 let (register_code, unregister_code, on_fps_code) = crate::dex::resolve_fps_codes()
1268 .ok_or_else(|| {
1269 CoreError::binder(-1, "dex:TRANSACTION_registerTaskFpsCallback not found")
1270 })?;
1271
1272 let window = {
1273 let raw = unsafe { (vt.get_service)(WINDOW_SERVICE.as_ptr() as *const c_char) };
1274 if raw.is_null() {
1275 return Err(CoreError::binder(-1, "AServiceManager_getService:window"));
1276 }
1277 OwnedBinder {
1278 ptr: raw,
1279 dec_strong: vt.dec_strong,
1280 }
1281 };
1282
1283 let wm_class = unsafe {
1286 (vt.class_define)(
1287 WM_DESCRIPTOR.as_ptr() as *const c_char,
1288 wm_on_create,
1289 wm_on_destroy,
1290 wm_on_transact,
1291 )
1292 };
1293 if wm_class.is_null() {
1294 return Err(CoreError::binder(
1295 -1,
1296 "AIBinder_Class_define:IWindowManager",
1297 ));
1298 }
1299 unsafe { (vt.associate_class)(window.ptr, wm_class) };
1300
1301 let cb_class = unsafe {
1302 (vt.class_define)(
1303 FPS_DESCRIPTOR.as_ptr() as *const c_char,
1304 fps_on_create,
1305 fps_on_destroy,
1306 fps_on_transact,
1307 )
1308 };
1309 if cb_class.is_null() {
1310 return Err(CoreError::binder(
1311 -1,
1312 "AIBinder_Class_define:ITaskFpsCallback",
1313 ));
1314 }
1315
1316 let owned = unsafe {
1324 let raw = libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC);
1325 if raw < 0 {
1326 return Err(CoreError::sys(*libc::__errno(), "eventfd"));
1327 }
1328 OwnedFd::from_raw_fd(raw)
1329 };
1330
1331 let consumer = owned
1332 .try_clone()
1333 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:fps"))?;
1334
1335 let userdata = Box::into_raw(Box::new(owned)) as *mut c_void;
1336 let cb_binder = unsafe { (vt.new_binder)(cb_class, userdata) };
1337 if cb_binder.is_null() {
1338 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1340 return Err(CoreError::binder(-1, "AIBinder_new:ITaskFpsCallback"));
1341 }
1342 unsafe { (vt.associate_class)(cb_binder, cb_class) };
1343
1344 FPS_READ_I32.store(vt.read_int32 as usize, Ordering::Relaxed);
1347 FPS_SEEN.store(false, Ordering::Relaxed);
1348 FPS_CODE.store(on_fps_code, Ordering::Relaxed);
1349 FPS_VALUE.store(0, Ordering::Relaxed);
1350 *GET_USER_DATA.lock().unwrap_or_else(|p| p.into_inner()) = Some(vt.get_user_data);
1353
1354 unsafe { (vt.set_thread_pool_max)(0) };
1355 let join_fn = vt.join_thread_pool;
1356 std::thread::spawn(move || unsafe { join_fn() });
1357
1358 Ok((
1359 Self {
1360 _lib: lib,
1361 vt,
1362 window,
1363 cb_binder,
1364 _wm_class: wm_class,
1365 register_code,
1366 unregister_code,
1367 task_id: -1,
1368 },
1369 consumer,
1370 ))
1371 }
1372
1373 pub fn register(&mut self, task_id: i32) -> Result<(), CoreError> {
1377 if self.task_id == task_id {
1378 return Ok(());
1379 }
1380 if self.task_id >= 0 {
1381 let _ = self.unregister();
1382 }
1383
1384 let _ = transact_write(&self.vt, self.window.ptr, self.register_code, |w| {
1385 w.write_i32(task_id)?;
1386 w.write_strong_binder(self.cb_binder)
1387 })?;
1388 self.task_id = task_id;
1389 Ok(())
1390 }
1391
1392 pub fn unregister(&mut self) -> Result<(), CoreError> {
1395 if self.task_id < 0 {
1396 return Ok(());
1397 }
1398 let _ = transact_write(&self.vt, self.window.ptr, self.unregister_code, |w| {
1399 w.write_strong_binder(self.cb_binder)
1400 })?;
1401 self.task_id = -1;
1402 Ok(())
1403 }
1404
1405 pub fn last_fps(&self) -> Option<f32> {
1410 fps_from_state(
1411 FPS_SEEN.load(Ordering::Acquire),
1412 FPS_VALUE.load(Ordering::Relaxed),
1413 )
1414 }
1415
1416 pub fn task_id(&self) -> Option<i32> {
1418 (self.task_id >= 0).then_some(self.task_id)
1419 }
1420 }
1421
1422 impl Drop for FpsListener {
1423 fn drop(&mut self) {
1431 let _ = self.unregister();
1432 }
1433 }
1434
1435 fn fps_from_state(seen: bool, bits: u32) -> Option<f32> {
1440 if seen {
1441 Some(f32::from_bits(bits))
1442 } else {
1443 None
1444 }
1445 }
1446
1447 fn sanitize_fps(bits: u32) -> u32 {
1452 let v = f32::from_bits(bits);
1453 if v.is_finite() && v >= 0.0 {
1454 bits
1455 } else {
1456 0.0f32.to_bits()
1457 }
1458 }
1459
1460 const TASK_SERVICE: &[u8] = b"activity_task\0";
1463 const ATM_DESCRIPTOR: &[u8] = b"android.app.IActivityTaskManager\0";
1464 const TASK_STACK_DESCRIPTOR: &[u8] = b"android.app.ITaskStackListener\0";
1465
1466 unsafe extern "C" fn atm_on_create(_: *mut c_void) -> *mut c_void {
1470 std::ptr::null_mut()
1471 }
1472 unsafe extern "C" fn atm_on_destroy(_: *mut c_void) {}
1473 unsafe extern "C" fn atm_on_transact(
1474 _: *mut AIBinder,
1475 _: u32,
1476 _: *const AParcel,
1477 _: *mut AParcel,
1478 ) -> BinderStatus {
1479 STATUS_OK
1480 }
1481
1482 static GET_USER_DATA: std::sync::Mutex<
1498 Option<unsafe extern "C" fn(*const AIBinder) -> *mut c_void>,
1499 > = std::sync::Mutex::new(None);
1500
1501 unsafe extern "C" fn task_stack_on_create(userdata: *mut c_void) -> *mut c_void {
1502 userdata
1503 }
1504 unsafe extern "C" fn task_stack_on_destroy(userdata: *mut c_void) {
1505 if !userdata.is_null() {
1506 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1507 }
1508 }
1509 unsafe extern "C" fn task_stack_on_transact(
1510 binder: *mut AIBinder,
1511 _code: u32,
1512 _in_parcel: *const AParcel,
1513 _reply: *mut AParcel,
1514 ) -> BinderStatus {
1515 let get_user_data = GET_USER_DATA.lock().unwrap_or_else(|p| p.into_inner());
1516 if let Some(get_user_data) = *get_user_data {
1517 let userdata = unsafe { get_user_data(binder) };
1518 if !userdata.is_null() {
1519 let efd = userdata as *mut OwnedFd;
1520 let val: u64 = 1;
1521 unsafe { libc::write((*efd).as_raw_fd(), &val as *const u64 as *const c_void, 8) };
1522 }
1523 }
1524 STATUS_OK
1525 }
1526
1527 pub struct TaskStackListener {
1547 _lib: DlHandle,
1548 vt: Vtable,
1549 service: OwnedBinder,
1550 cb_binder: *mut AIBinder,
1551 _atm_class: *mut AIBinder_Class,
1552 register_code: u32,
1553 unregister_code: u32,
1554 }
1555 unsafe impl Send for TaskStackListener {}
1556
1557 impl TaskStackListener {
1558 pub fn open() -> Result<(Self, OwnedFd), CoreError> {
1562 let handle = unsafe {
1563 libc::dlopen(
1564 LIBBINDER_PATH.as_ptr() as *const c_char,
1565 libc::RTLD_NOW | libc::RTLD_LOCAL,
1566 )
1567 };
1568 if handle.is_null() {
1569 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
1570 }
1571 let lib = DlHandle;
1572 let vt = load_vtable(handle)?;
1573
1574 let (register_code, unregister_code) = crate::dex::resolve_task_stack_codes()
1575 .ok_or_else(|| {
1576 CoreError::binder(-1, "dex:TRANSACTION_registerTaskStackListener not found")
1577 })?;
1578
1579 let service = {
1580 let raw = unsafe { (vt.get_service)(TASK_SERVICE.as_ptr() as *const c_char) };
1581 if raw.is_null() {
1582 return Err(CoreError::binder(
1583 -1,
1584 "AServiceManager_getService:activity_task",
1585 ));
1586 }
1587 OwnedBinder {
1588 ptr: raw,
1589 dec_strong: vt.dec_strong,
1590 }
1591 };
1592
1593 let atm_class = unsafe {
1596 (vt.class_define)(
1597 ATM_DESCRIPTOR.as_ptr() as *const c_char,
1598 atm_on_create,
1599 atm_on_destroy,
1600 atm_on_transact,
1601 )
1602 };
1603 if atm_class.is_null() {
1604 return Err(CoreError::binder(
1605 -1,
1606 "AIBinder_Class_define:IActivityTaskManager",
1607 ));
1608 }
1609 unsafe { (vt.associate_class)(service.ptr, atm_class) };
1610
1611 let cb_class = unsafe {
1612 (vt.class_define)(
1613 TASK_STACK_DESCRIPTOR.as_ptr() as *const c_char,
1614 task_stack_on_create,
1615 task_stack_on_destroy,
1616 task_stack_on_transact,
1617 )
1618 };
1619 if cb_class.is_null() {
1620 return Err(CoreError::binder(
1621 -1,
1622 "AIBinder_Class_define:ITaskStackListener",
1623 ));
1624 }
1625
1626 let owned = unsafe {
1631 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
1632 if raw < 0 {
1633 return Err(CoreError::sys(*libc::__errno(), "eventfd"));
1634 }
1635 OwnedFd::from_raw_fd(raw)
1636 };
1637
1638 let consumer = owned
1639 .try_clone()
1640 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:task_stack"))?;
1641
1642 let userdata = Box::into_raw(Box::new(owned)) as *mut c_void;
1643 let cb_binder = unsafe { (vt.new_binder)(cb_class, userdata) };
1644 if cb_binder.is_null() {
1645 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1647 return Err(CoreError::binder(-1, "AIBinder_new:ITaskStackListener"));
1648 }
1649 unsafe { (vt.associate_class)(cb_binder, cb_class) };
1650
1651 *GET_USER_DATA.lock().unwrap_or_else(|p| p.into_inner()) = Some(vt.get_user_data);
1654
1655 unsafe { (vt.set_thread_pool_max)(0) };
1656 let join_fn = vt.join_thread_pool;
1657 std::thread::spawn(move || unsafe { join_fn() });
1658
1659 Ok((
1660 Self {
1661 _lib: lib,
1662 vt,
1663 service,
1664 cb_binder,
1665 _atm_class: atm_class,
1666 register_code,
1667 unregister_code,
1668 },
1669 consumer,
1670 ))
1671 }
1672
1673 pub fn register(&self) -> Result<(), CoreError> {
1677 let _ = transact_write(&self.vt, self.service.ptr, self.register_code, |w| {
1678 w.write_strong_binder(self.cb_binder)
1679 })?;
1680 Ok(())
1681 }
1682
1683 pub fn unregister(&self) -> Result<(), CoreError> {
1687 let _ = transact_write(&self.vt, self.service.ptr, self.unregister_code, |w| {
1688 w.write_strong_binder(self.cb_binder)
1689 })?;
1690 Ok(())
1691 }
1692 }
1693
1694 impl Drop for TaskStackListener {
1695 fn drop(&mut self) {
1700 let _ = self.unregister();
1701 }
1702 }
1703
1704 pub struct RawBinderService {
1713 _lib: DlHandle,
1714 vt: Vtable,
1715 service: OwnedBinder,
1716 }
1717 unsafe impl Send for RawBinderService {}
1718
1719 impl RawBinderService {
1720 pub fn open(service_name: &str) -> Result<Self, CoreError> {
1722 use std::ffi::CString;
1723 let handle = unsafe {
1724 libc::dlopen(
1725 LIBBINDER_PATH.as_ptr() as *const c_char,
1726 libc::RTLD_NOW | libc::RTLD_LOCAL,
1727 )
1728 };
1729 if handle.is_null() {
1730 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
1731 }
1732 let lib = DlHandle;
1733 let vt = load_vtable(handle)?;
1734 let cs = CString::new(service_name)
1735 .map_err(|_| CoreError::binder(-1, "service_name:nul_byte"))?;
1736 let raw = unsafe { (vt.get_service)(cs.as_ptr()) };
1737 if raw.is_null() {
1738 return Err(CoreError::binder(-1, "AServiceManager_getService:null"));
1739 }
1740 let service = OwnedBinder {
1741 ptr: raw,
1742 dec_strong: vt.dec_strong,
1743 };
1744 Ok(Self {
1745 _lib: lib,
1746 vt,
1747 service,
1748 })
1749 }
1750
1751 pub fn transact_bool(&self, code: u32) -> Result<bool, CoreError> {
1753 let out = self.raw_noarg(code)?;
1754 let r = ParcelReader {
1755 vt: &self.vt,
1756 parcel: &out,
1757 };
1758 let ex = r.read_i32()?;
1759 if ex != EX_NONE {
1760 return Err(CoreError::binder(ex, "transact_bool:exception"));
1761 }
1762 if let Some(rb) = self.vt.read_bool {
1763 let mut v = false;
1764 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
1765 if s != STATUS_OK {
1766 return Err(CoreError::binder(s, "AParcel_readBool"));
1767 }
1768 Ok(v)
1769 } else {
1770 Ok(r.read_i32()? != 0)
1771 }
1772 }
1773
1774 pub fn transact_i32(&self, code: u32, arg: i32) -> Result<(), CoreError> {
1776 let _ = transact_write(&self.vt, self.service.ptr, code, |w| w.write_i32(arg))?;
1777 Ok(())
1778 }
1779
1780 fn raw_noarg(&self, code: u32) -> Result<OwnedParcel, CoreError> {
1781 transact_write(&self.vt, self.service.ptr, code, |_| Ok(()))
1782 }
1783 }
1784
1785 #[cfg(test)]
1786 mod tests {
1787 use super::*;
1788
1789 fn alloc(length: i32) -> bool {
1790 let mut buf = StringBuf::new();
1791 let mut out: *mut c_char = std::ptr::null_mut();
1792 unsafe { string_alloc(&mut buf as *mut StringBuf as *mut c_void, length, &mut out) }
1793 }
1794
1795 #[test]
1796 fn string_alloc_rejects_oversized() {
1797 assert!(!alloc(MAX_BINDER_STRING_LEN as i32 + 1));
1798 }
1799
1800 #[test]
1801 fn string_alloc_rejects_negative() {
1802 assert!(!alloc(-1));
1803 }
1804
1805 #[test]
1806 fn string_alloc_accepts_valid_len_and_nul_terminates() {
1807 let mut buf = StringBuf::new();
1808 let mut out: *mut c_char = std::ptr::null_mut();
1809 let ok =
1810 unsafe { string_alloc(&mut buf as *mut StringBuf as *mut c_void, 4, &mut out) };
1811 assert!(ok);
1812 assert!(!out.is_null());
1813 {
1814 let vec = unsafe { buf.0.as_mut_vec() };
1815 b"ABCD".iter().enumerate().for_each(|(i, &b)| vec[i] = b);
1816 vec[4] = 0;
1817 }
1818 assert_eq!(buf.finish().as_deref(), Some("ABCD"));
1819 }
1820
1821 #[test]
1822 fn fps_zero_report_distinct_from_unseen() {
1823 assert_eq!(fps_from_state(false, 0), None);
1824 assert_eq!(fps_from_state(true, 0), Some(0.0));
1825 assert_eq!(fps_from_state(true, 60.0f32.to_bits()), Some(60.0));
1826 assert_eq!(fps_from_state(false, 60.0f32.to_bits()), None);
1827 }
1828
1829 #[test]
1830 fn sanitize_fps_rejects_non_finite_and_negative() {
1831 let de = |bits| f32::from_bits(sanitize_fps(bits));
1832 assert_eq!(de(0.0f32.to_bits()), 0.0);
1833 assert_eq!(de(60.0f32.to_bits()), 60.0);
1834 assert_eq!(de(f32::NAN.to_bits()), 0.0);
1835 assert_eq!(de(f32::INFINITY.to_bits()), 0.0);
1836 assert_eq!(de(f32::NEG_INFINITY.to_bits()), 0.0);
1837 assert_eq!(de((-5.0f32).to_bits()), 0.0);
1838 }
1839 }
1840}
1841
1842#[cfg(target_os = "android")]
1845pub use imp::{
1846 ActivityManagerBinder, DisplayManagerBinder, FpsListener, RawBinderService, TaskStackListener,
1847 TxCodes, last_foreground_pid, resolve_tx_codes,
1848};
1849
1850#[cfg(not(target_os = "android"))]
1853pub struct ActivityManagerBinder;
1854
1855#[cfg(not(target_os = "android"))]
1856impl ActivityManagerBinder {
1857 pub fn open() -> Result<Self, crate::CoreError> {
1858 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1859 }
1860 pub fn open_with_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1861 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1862 }
1863 pub fn open_with_fgproc_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1864 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1865 }
1866 pub fn get_focused_task(&self) -> Result<Option<(i32, Option<String>)>, crate::CoreError> {
1867 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1868 }
1869 pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
1870 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1871 }
1872 pub fn get_focused_task_id(&self) -> Result<Option<i32>, crate::CoreError> {
1873 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1874 }
1875}
1876
1877#[cfg(not(target_os = "android"))]
1878pub struct DisplayManagerBinder;
1879
1880#[cfg(not(target_os = "android"))]
1881impl DisplayManagerBinder {
1882 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), crate::CoreError> {
1883 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1884 }
1885 pub fn is_interactive(&self) -> Result<bool, crate::CoreError> {
1886 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1887 }
1888}
1889
1890#[cfg(not(target_os = "android"))]
1891pub struct RawBinderService;
1892
1893#[cfg(not(target_os = "android"))]
1894impl RawBinderService {
1895 pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
1896 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1897 }
1898 pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
1899 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1900 }
1901 pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
1902 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1903 }
1904}
1905
1906#[cfg(not(target_os = "android"))]
1907pub struct FpsListener;
1908
1909#[cfg(not(target_os = "android"))]
1910impl FpsListener {
1911 pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1912 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1913 }
1914 pub fn register(&mut self, _task_id: i32) -> Result<(), crate::CoreError> {
1915 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1916 }
1917 pub fn unregister(&mut self) -> Result<(), crate::CoreError> {
1918 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1919 }
1920 pub fn last_fps(&self) -> Option<f32> {
1921 None
1922 }
1923 pub fn task_id(&self) -> Option<i32> {
1924 None
1925 }
1926}
1927
1928#[cfg(not(target_os = "android"))]
1929pub struct TaskStackListener;
1930
1931#[cfg(not(target_os = "android"))]
1932impl TaskStackListener {
1933 pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1934 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1935 }
1936 pub fn register(&self) -> Result<(), crate::CoreError> {
1937 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1938 }
1939 pub fn unregister(&self) -> Result<(), crate::CoreError> {
1940 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1941 }
1942}
1943
1944#[cfg(not(target_os = "android"))]
1945pub struct TxCodes {
1946 pub observer_code: u32,
1947 pub query_code: u32,
1948 pub api_mode: u8,
1949 pub fg_code: u32,
1950}
1951
1952#[cfg(not(target_os = "android"))]
1953pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
1954 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1955}
1956
1957#[cfg(not(target_os = "android"))]
1958pub fn last_foreground_pid() -> i32 {
1959 0
1960}