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 {
1321 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
1322 if raw < 0 {
1323 return Err(CoreError::sys(*libc::__errno(), "eventfd"));
1324 }
1325 OwnedFd::from_raw_fd(raw)
1326 };
1327
1328 let consumer = owned
1329 .try_clone()
1330 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:fps"))?;
1331
1332 let userdata = Box::into_raw(Box::new(owned)) as *mut c_void;
1333 let cb_binder = unsafe { (vt.new_binder)(cb_class, userdata) };
1334 if cb_binder.is_null() {
1335 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1337 return Err(CoreError::binder(-1, "AIBinder_new:ITaskFpsCallback"));
1338 }
1339 unsafe { (vt.associate_class)(cb_binder, cb_class) };
1340
1341 FPS_READ_I32.store(vt.read_int32 as usize, Ordering::Relaxed);
1344 FPS_SEEN.store(false, Ordering::Relaxed);
1345 FPS_CODE.store(on_fps_code, Ordering::Relaxed);
1346 FPS_VALUE.store(0, Ordering::Relaxed);
1347 *GET_USER_DATA.lock().unwrap_or_else(|p| p.into_inner()) = Some(vt.get_user_data);
1350
1351 unsafe { (vt.set_thread_pool_max)(0) };
1352 let join_fn = vt.join_thread_pool;
1353 std::thread::spawn(move || unsafe { join_fn() });
1354
1355 Ok((
1356 Self {
1357 _lib: lib,
1358 vt,
1359 window,
1360 cb_binder,
1361 _wm_class: wm_class,
1362 register_code,
1363 unregister_code,
1364 task_id: -1,
1365 },
1366 consumer,
1367 ))
1368 }
1369
1370 pub fn register(&mut self, task_id: i32) -> Result<(), CoreError> {
1374 if self.task_id == task_id {
1375 return Ok(());
1376 }
1377 if self.task_id >= 0 {
1378 let _ = self.unregister();
1379 }
1380
1381 let _ = transact_write(&self.vt, self.window.ptr, self.register_code, |w| {
1382 w.write_i32(task_id)?;
1383 w.write_strong_binder(self.cb_binder)
1384 })?;
1385 self.task_id = task_id;
1386 Ok(())
1387 }
1388
1389 pub fn unregister(&mut self) -> Result<(), CoreError> {
1392 if self.task_id < 0 {
1393 return Ok(());
1394 }
1395 let _ = transact_write(&self.vt, self.window.ptr, self.unregister_code, |w| {
1396 w.write_strong_binder(self.cb_binder)
1397 })?;
1398 self.task_id = -1;
1399 Ok(())
1400 }
1401
1402 pub fn last_fps(&self) -> Option<f32> {
1407 fps_from_state(
1408 FPS_SEEN.load(Ordering::Acquire),
1409 FPS_VALUE.load(Ordering::Relaxed),
1410 )
1411 }
1412
1413 pub fn task_id(&self) -> Option<i32> {
1415 (self.task_id >= 0).then_some(self.task_id)
1416 }
1417 }
1418
1419 impl Drop for FpsListener {
1420 fn drop(&mut self) {
1428 let _ = self.unregister();
1429 }
1430 }
1431
1432 fn fps_from_state(seen: bool, bits: u32) -> Option<f32> {
1437 if seen {
1438 Some(f32::from_bits(bits))
1439 } else {
1440 None
1441 }
1442 }
1443
1444 fn sanitize_fps(bits: u32) -> u32 {
1449 let v = f32::from_bits(bits);
1450 if v.is_finite() && v >= 0.0 {
1451 bits
1452 } else {
1453 0.0f32.to_bits()
1454 }
1455 }
1456
1457 const TASK_SERVICE: &[u8] = b"activity_task\0";
1460 const ATM_DESCRIPTOR: &[u8] = b"android.app.IActivityTaskManager\0";
1461 const TASK_STACK_DESCRIPTOR: &[u8] = b"android.app.ITaskStackListener\0";
1462
1463 unsafe extern "C" fn atm_on_create(_: *mut c_void) -> *mut c_void {
1467 std::ptr::null_mut()
1468 }
1469 unsafe extern "C" fn atm_on_destroy(_: *mut c_void) {}
1470 unsafe extern "C" fn atm_on_transact(
1471 _: *mut AIBinder,
1472 _: u32,
1473 _: *const AParcel,
1474 _: *mut AParcel,
1475 ) -> BinderStatus {
1476 STATUS_OK
1477 }
1478
1479 static GET_USER_DATA: std::sync::Mutex<
1495 Option<unsafe extern "C" fn(*const AIBinder) -> *mut c_void>,
1496 > = std::sync::Mutex::new(None);
1497
1498 unsafe extern "C" fn task_stack_on_create(userdata: *mut c_void) -> *mut c_void {
1499 userdata
1500 }
1501 unsafe extern "C" fn task_stack_on_destroy(userdata: *mut c_void) {
1502 if !userdata.is_null() {
1503 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1504 }
1505 }
1506 unsafe extern "C" fn task_stack_on_transact(
1507 binder: *mut AIBinder,
1508 _code: u32,
1509 _in_parcel: *const AParcel,
1510 _reply: *mut AParcel,
1511 ) -> BinderStatus {
1512 let get_user_data = GET_USER_DATA.lock().unwrap_or_else(|p| p.into_inner());
1513 if let Some(get_user_data) = *get_user_data {
1514 let userdata = unsafe { get_user_data(binder) };
1515 if !userdata.is_null() {
1516 let efd = userdata as *mut OwnedFd;
1517 let val: u64 = 1;
1518 unsafe { libc::write((*efd).as_raw_fd(), &val as *const u64 as *const c_void, 8) };
1519 }
1520 }
1521 STATUS_OK
1522 }
1523
1524 pub struct TaskStackListener {
1544 _lib: DlHandle,
1545 vt: Vtable,
1546 service: OwnedBinder,
1547 cb_binder: *mut AIBinder,
1548 _atm_class: *mut AIBinder_Class,
1549 register_code: u32,
1550 unregister_code: u32,
1551 }
1552 unsafe impl Send for TaskStackListener {}
1553
1554 impl TaskStackListener {
1555 pub fn open() -> Result<(Self, OwnedFd), CoreError> {
1559 let handle = unsafe {
1560 libc::dlopen(
1561 LIBBINDER_PATH.as_ptr() as *const c_char,
1562 libc::RTLD_NOW | libc::RTLD_LOCAL,
1563 )
1564 };
1565 if handle.is_null() {
1566 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
1567 }
1568 let lib = DlHandle;
1569 let vt = load_vtable(handle)?;
1570
1571 let (register_code, unregister_code) = crate::dex::resolve_task_stack_codes()
1572 .ok_or_else(|| {
1573 CoreError::binder(-1, "dex:TRANSACTION_registerTaskStackListener not found")
1574 })?;
1575
1576 let service = {
1577 let raw = unsafe { (vt.get_service)(TASK_SERVICE.as_ptr() as *const c_char) };
1578 if raw.is_null() {
1579 return Err(CoreError::binder(
1580 -1,
1581 "AServiceManager_getService:activity_task",
1582 ));
1583 }
1584 OwnedBinder {
1585 ptr: raw,
1586 dec_strong: vt.dec_strong,
1587 }
1588 };
1589
1590 let atm_class = unsafe {
1593 (vt.class_define)(
1594 ATM_DESCRIPTOR.as_ptr() as *const c_char,
1595 atm_on_create,
1596 atm_on_destroy,
1597 atm_on_transact,
1598 )
1599 };
1600 if atm_class.is_null() {
1601 return Err(CoreError::binder(
1602 -1,
1603 "AIBinder_Class_define:IActivityTaskManager",
1604 ));
1605 }
1606 unsafe { (vt.associate_class)(service.ptr, atm_class) };
1607
1608 let cb_class = unsafe {
1609 (vt.class_define)(
1610 TASK_STACK_DESCRIPTOR.as_ptr() as *const c_char,
1611 task_stack_on_create,
1612 task_stack_on_destroy,
1613 task_stack_on_transact,
1614 )
1615 };
1616 if cb_class.is_null() {
1617 return Err(CoreError::binder(
1618 -1,
1619 "AIBinder_Class_define:ITaskStackListener",
1620 ));
1621 }
1622
1623 let owned = unsafe {
1628 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
1629 if raw < 0 {
1630 return Err(CoreError::sys(*libc::__errno(), "eventfd"));
1631 }
1632 OwnedFd::from_raw_fd(raw)
1633 };
1634
1635 let consumer = owned
1636 .try_clone()
1637 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:task_stack"))?;
1638
1639 let userdata = Box::into_raw(Box::new(owned)) as *mut c_void;
1640 let cb_binder = unsafe { (vt.new_binder)(cb_class, userdata) };
1641 if cb_binder.is_null() {
1642 unsafe { drop(Box::from_raw(userdata as *mut OwnedFd)) };
1644 return Err(CoreError::binder(-1, "AIBinder_new:ITaskStackListener"));
1645 }
1646 unsafe { (vt.associate_class)(cb_binder, cb_class) };
1647
1648 *GET_USER_DATA.lock().unwrap_or_else(|p| p.into_inner()) = Some(vt.get_user_data);
1651
1652 unsafe { (vt.set_thread_pool_max)(0) };
1653 let join_fn = vt.join_thread_pool;
1654 std::thread::spawn(move || unsafe { join_fn() });
1655
1656 Ok((
1657 Self {
1658 _lib: lib,
1659 vt,
1660 service,
1661 cb_binder,
1662 _atm_class: atm_class,
1663 register_code,
1664 unregister_code,
1665 },
1666 consumer,
1667 ))
1668 }
1669
1670 pub fn register(&self) -> Result<(), CoreError> {
1674 let _ = transact_write(&self.vt, self.service.ptr, self.register_code, |w| {
1675 w.write_strong_binder(self.cb_binder)
1676 })?;
1677 Ok(())
1678 }
1679
1680 pub fn unregister(&self) -> Result<(), CoreError> {
1684 let _ = transact_write(&self.vt, self.service.ptr, self.unregister_code, |w| {
1685 w.write_strong_binder(self.cb_binder)
1686 })?;
1687 Ok(())
1688 }
1689 }
1690
1691 impl Drop for TaskStackListener {
1692 fn drop(&mut self) {
1697 let _ = self.unregister();
1698 }
1699 }
1700
1701 pub struct RawBinderService {
1710 _lib: DlHandle,
1711 vt: Vtable,
1712 service: OwnedBinder,
1713 }
1714 unsafe impl Send for RawBinderService {}
1715
1716 impl RawBinderService {
1717 pub fn open(service_name: &str) -> Result<Self, CoreError> {
1719 use std::ffi::CString;
1720 let handle = unsafe {
1721 libc::dlopen(
1722 LIBBINDER_PATH.as_ptr() as *const c_char,
1723 libc::RTLD_NOW | libc::RTLD_LOCAL,
1724 )
1725 };
1726 if handle.is_null() {
1727 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
1728 }
1729 let lib = DlHandle;
1730 let vt = load_vtable(handle)?;
1731 let cs = CString::new(service_name)
1732 .map_err(|_| CoreError::binder(-1, "service_name:nul_byte"))?;
1733 let raw = unsafe { (vt.get_service)(cs.as_ptr()) };
1734 if raw.is_null() {
1735 return Err(CoreError::binder(-1, "AServiceManager_getService:null"));
1736 }
1737 let service = OwnedBinder {
1738 ptr: raw,
1739 dec_strong: vt.dec_strong,
1740 };
1741 Ok(Self {
1742 _lib: lib,
1743 vt,
1744 service,
1745 })
1746 }
1747
1748 pub fn transact_bool(&self, code: u32) -> Result<bool, CoreError> {
1750 let out = self.raw_noarg(code)?;
1751 let r = ParcelReader {
1752 vt: &self.vt,
1753 parcel: &out,
1754 };
1755 let ex = r.read_i32()?;
1756 if ex != EX_NONE {
1757 return Err(CoreError::binder(ex, "transact_bool:exception"));
1758 }
1759 if let Some(rb) = self.vt.read_bool {
1760 let mut v = false;
1761 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
1762 if s != STATUS_OK {
1763 return Err(CoreError::binder(s, "AParcel_readBool"));
1764 }
1765 Ok(v)
1766 } else {
1767 Ok(r.read_i32()? != 0)
1768 }
1769 }
1770
1771 pub fn transact_i32(&self, code: u32, arg: i32) -> Result<(), CoreError> {
1773 let _ = transact_write(&self.vt, self.service.ptr, code, |w| w.write_i32(arg))?;
1774 Ok(())
1775 }
1776
1777 fn raw_noarg(&self, code: u32) -> Result<OwnedParcel, CoreError> {
1778 transact_write(&self.vt, self.service.ptr, code, |_| Ok(()))
1779 }
1780 }
1781
1782 #[cfg(test)]
1783 mod tests {
1784 use super::*;
1785
1786 fn alloc(length: i32) -> bool {
1787 let mut buf = StringBuf::new();
1788 let mut out: *mut c_char = std::ptr::null_mut();
1789 unsafe { string_alloc(&mut buf as *mut StringBuf as *mut c_void, length, &mut out) }
1790 }
1791
1792 #[test]
1793 fn string_alloc_rejects_oversized() {
1794 assert!(!alloc(MAX_BINDER_STRING_LEN as i32 + 1));
1795 }
1796
1797 #[test]
1798 fn string_alloc_rejects_negative() {
1799 assert!(!alloc(-1));
1800 }
1801
1802 #[test]
1803 fn string_alloc_accepts_valid_len_and_nul_terminates() {
1804 let mut buf = StringBuf::new();
1805 let mut out: *mut c_char = std::ptr::null_mut();
1806 let ok =
1807 unsafe { string_alloc(&mut buf as *mut StringBuf as *mut c_void, 4, &mut out) };
1808 assert!(ok);
1809 assert!(!out.is_null());
1810 {
1811 let vec = unsafe { buf.0.as_mut_vec() };
1812 b"ABCD".iter().enumerate().for_each(|(i, &b)| vec[i] = b);
1813 vec[4] = 0;
1814 }
1815 assert_eq!(buf.finish().as_deref(), Some("ABCD"));
1816 }
1817
1818 #[test]
1819 fn fps_zero_report_distinct_from_unseen() {
1820 assert_eq!(fps_from_state(false, 0), None);
1821 assert_eq!(fps_from_state(true, 0), Some(0.0));
1822 assert_eq!(fps_from_state(true, 60.0f32.to_bits()), Some(60.0));
1823 assert_eq!(fps_from_state(false, 60.0f32.to_bits()), None);
1824 }
1825
1826 #[test]
1827 fn sanitize_fps_rejects_non_finite_and_negative() {
1828 let de = |bits| f32::from_bits(sanitize_fps(bits));
1829 assert_eq!(de(0.0f32.to_bits()), 0.0);
1830 assert_eq!(de(60.0f32.to_bits()), 60.0);
1831 assert_eq!(de(f32::NAN.to_bits()), 0.0);
1832 assert_eq!(de(f32::INFINITY.to_bits()), 0.0);
1833 assert_eq!(de(f32::NEG_INFINITY.to_bits()), 0.0);
1834 assert_eq!(de((-5.0f32).to_bits()), 0.0);
1835 }
1836 }
1837}
1838
1839#[cfg(target_os = "android")]
1842pub use imp::{
1843 ActivityManagerBinder, DisplayManagerBinder, FpsListener, RawBinderService, TaskStackListener,
1844 TxCodes, last_foreground_pid, resolve_tx_codes,
1845};
1846
1847#[cfg(not(target_os = "android"))]
1850pub struct ActivityManagerBinder;
1851
1852#[cfg(not(target_os = "android"))]
1853impl ActivityManagerBinder {
1854 pub fn open() -> Result<Self, crate::CoreError> {
1855 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1856 }
1857 pub fn open_with_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1858 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1859 }
1860 pub fn open_with_fgproc_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1861 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1862 }
1863 pub fn get_focused_task(&self) -> Result<Option<(i32, Option<String>)>, crate::CoreError> {
1864 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1865 }
1866 pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
1867 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1868 }
1869 pub fn get_focused_task_id(&self) -> Result<Option<i32>, crate::CoreError> {
1870 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1871 }
1872}
1873
1874#[cfg(not(target_os = "android"))]
1875pub struct DisplayManagerBinder;
1876
1877#[cfg(not(target_os = "android"))]
1878impl DisplayManagerBinder {
1879 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), crate::CoreError> {
1880 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1881 }
1882 pub fn is_interactive(&self) -> Result<bool, crate::CoreError> {
1883 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1884 }
1885}
1886
1887#[cfg(not(target_os = "android"))]
1888pub struct RawBinderService;
1889
1890#[cfg(not(target_os = "android"))]
1891impl RawBinderService {
1892 pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
1893 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1894 }
1895 pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
1896 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1897 }
1898 pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
1899 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1900 }
1901}
1902
1903#[cfg(not(target_os = "android"))]
1904pub struct FpsListener;
1905
1906#[cfg(not(target_os = "android"))]
1907impl FpsListener {
1908 pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1909 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1910 }
1911 pub fn register(&mut self, _task_id: i32) -> Result<(), crate::CoreError> {
1912 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1913 }
1914 pub fn unregister(&mut self) -> Result<(), crate::CoreError> {
1915 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1916 }
1917 pub fn last_fps(&self) -> Option<f32> {
1918 None
1919 }
1920 pub fn task_id(&self) -> Option<i32> {
1921 None
1922 }
1923}
1924
1925#[cfg(not(target_os = "android"))]
1926pub struct TaskStackListener;
1927
1928#[cfg(not(target_os = "android"))]
1929impl TaskStackListener {
1930 pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
1931 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1932 }
1933 pub fn register(&self) -> Result<(), crate::CoreError> {
1934 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1935 }
1936 pub fn unregister(&self) -> Result<(), crate::CoreError> {
1937 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1938 }
1939}
1940
1941#[cfg(not(target_os = "android"))]
1942pub struct TxCodes {
1943 pub observer_code: u32,
1944 pub query_code: u32,
1945 pub api_mode: u8,
1946 pub fg_code: u32,
1947}
1948
1949#[cfg(not(target_os = "android"))]
1950pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
1951 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
1952}
1953
1954#[cfg(not(target_os = "android"))]
1955pub fn last_foreground_pid() -> i32 {
1956 0
1957}