1#[cfg(target_os = "android")]
27mod imp {
28 use crate::CoreError;
29 use crate::dex;
30 use std::os::fd::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd};
31 use std::os::raw::{c_char, c_void};
32 use std::sync::atomic::{AtomicI32, AtomicU32, AtomicUsize, Ordering};
33 use std::sync::Mutex;
34
35 const STATUS_OK: i32 = 0;
38 const STATUS_UNKNOWN_TRANSACTION: i32 = -2;
39 const EX_NONE: i32 = 0;
40
41 const AM_DESCRIPTOR: &[u8] = b"android.app.IActivityManager\0";
44 const OBS_DESCRIPTOR: &[u8] = b"android.app.IProcessObserver\0";
45 const FGPROC_DESCRIPTOR: &[u8] = b"android.app.IForegroundProcessObserver\0";
46 const ACTIVITY_SERVICE: &[u8] = b"activity\0";
47 #[cfg(target_pointer_width = "64")]
48 const LIBBINDER_PATH: &[u8] = b"/system/lib64/libbinder_ndk.so\0";
49 #[cfg(target_pointer_width = "32")]
50 const LIBBINDER_PATH: &[u8] = b"/system/lib/libbinder_ndk.so\0";
51
52 static OBS_FG_CODE: AtomicU32 = AtomicU32::new(0);
63 static OBS_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
64
65 fn obs_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
66 OBS_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
67 }
68
69 static FGPROC_FG_CODE: AtomicU32 = AtomicU32::new(0);
77 static FGPROC_PID: AtomicI32 = AtomicI32::new(0);
78 static FGPROC_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
79 static FGPROC_READ_I32: AtomicUsize = AtomicUsize::new(0);
80
81 fn fgproc_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
82 FGPROC_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
83 }
84
85 type AIBinder = c_void;
88 #[allow(non_camel_case_types)]
89 type AIBinder_Class = c_void;
90 type AParcel = c_void;
91 type BinderStatus = i32;
92 type StringAllocator = unsafe extern "C" fn(*mut c_void, i32, *mut *mut c_char) -> bool;
93
94 unsafe extern "C" fn am_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
98 unsafe extern "C" fn am_on_destroy(_: *mut c_void) {}
99 unsafe extern "C" fn am_on_transact(
100 _: *mut AIBinder, _: u32, _: *const AParcel, _: *mut AParcel,
101 ) -> BinderStatus { STATUS_UNKNOWN_TRANSACTION }
102
103 unsafe extern "C" fn obs_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
105 unsafe extern "C" fn obs_on_destroy(_: *mut c_void) {}
106 unsafe extern "C" fn obs_on_transact(
107 _: *mut AIBinder, code: u32, _: *const AParcel, _: *mut AParcel,
108 ) -> BinderStatus {
109 if code == OBS_FG_CODE.load(Ordering::Relaxed) {
110 if let Some(fd) = obs_eventfd_guard().as_ref() {
113 let val: u64 = 1;
114 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
115 }
116 }
117 STATUS_OK
118 }
119
120 unsafe extern "C" fn fgproc_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
124 unsafe extern "C" fn fgproc_on_destroy(_: *mut c_void) {}
125 unsafe extern "C" fn fgproc_on_transact(
126 _: *mut AIBinder, code: u32, in_parcel: *const AParcel, _: *mut AParcel,
127 ) -> BinderStatus {
128 if code != FGPROC_FG_CODE.load(Ordering::Relaxed) {
129 return STATUS_UNKNOWN_TRANSACTION;
130 }
131 let read_addr = FGPROC_READ_I32.load(Ordering::Relaxed);
134 if read_addr != 0 {
135 let read_fn: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus =
136 unsafe { std::mem::transmute(read_addr) };
137 let mut pid: i32 = 0;
138 if unsafe { read_fn(in_parcel, &mut pid) } == STATUS_OK {
139 FGPROC_PID.store(pid, Ordering::Relaxed);
140 }
141 }
142 if let Some(fd) = fgproc_eventfd_guard().as_ref() {
145 let val: u64 = 1;
146 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
147 }
148 STATUS_OK
149 }
150
151 pub fn last_foreground_pid() -> i32 {
154 FGPROC_PID.load(Ordering::Relaxed)
155 }
156
157 unsafe extern "C" fn string_alloc(
160 cookie: *mut c_void, length: i32, buffer: *mut *mut c_char,
161 ) -> bool {
162 if length < 0 { return true; }
163 let s = unsafe { &mut *(cookie as *mut StringBuf) };
164 s.0.reserve_exact(length as usize + 1);
165 unsafe { s.0.as_mut_vec().resize(length as usize + 1, 0) };
166 unsafe { *buffer = s.0.as_mut_ptr() as *mut c_char };
167 true
168 }
169
170 struct StringBuf(String);
171 impl StringBuf {
172 fn new() -> Self { Self(String::new()) }
173 fn finish(mut self) -> Option<String> {
174 if let Some(pos) = self.0.as_bytes().iter().position(|&b| b == 0) {
175 unsafe { self.0.as_mut_vec().truncate(pos) };
176 }
177 if self.0.is_empty() { None } else { Some(self.0) }
178 }
179 }
180
181 struct Vtable {
184 get_service: unsafe extern "C" fn(*const c_char) -> *mut AIBinder,
185 class_define: unsafe extern "C" fn(
186 *const c_char,
187 unsafe extern "C" fn(*mut c_void) -> *mut c_void,
188 unsafe extern "C" fn(*mut c_void),
189 unsafe extern "C" fn(*mut AIBinder, u32, *const AParcel, *mut AParcel) -> BinderStatus,
190 ) -> *mut AIBinder_Class,
191 associate_class: unsafe extern "C" fn(*mut AIBinder, *mut AIBinder_Class) -> bool,
192 new_binder: unsafe extern "C" fn(*const AIBinder_Class, *mut c_void) -> *mut AIBinder,
193 prepare_transaction: unsafe extern "C" fn(*mut AIBinder, *mut *mut AParcel) -> BinderStatus,
194 transact: unsafe extern "C" fn(*mut AIBinder, u32, *mut *mut AParcel, *mut *mut AParcel, u32) -> BinderStatus,
195 dec_strong: unsafe extern "C" fn(*mut AIBinder),
196 parcel_delete: unsafe extern "C" fn(*mut AParcel),
197 read_int32: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus,
198 read_string: unsafe extern "C" fn(*const AParcel, *mut c_void, StringAllocator) -> BinderStatus,
199 write_strong_binder: unsafe extern "C" fn(*mut AParcel, *mut AIBinder) -> BinderStatus,
200 set_thread_pool_max: unsafe extern "C" fn(u32),
201 join_thread_pool: unsafe extern "C" fn(),
202 write_int32: unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus,
203 read_bool: Option<unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus>,
205 }
206
207 struct DlHandle(*mut c_void);
210 unsafe impl Send for DlHandle {}
211 impl Drop for DlHandle {
212 fn drop(&mut self) {
213 }
219 }
220
221 struct OwnedParcel { ptr: *mut AParcel, delete: unsafe extern "C" fn(*mut AParcel) }
222 impl Drop for OwnedParcel {
223 fn drop(&mut self) { if !self.ptr.is_null() { unsafe { (self.delete)(self.ptr) }; } }
224 }
225
226 struct OwnedBinder { ptr: *mut AIBinder, dec_strong: unsafe extern "C" fn(*mut AIBinder) }
227 unsafe impl Send for OwnedBinder {}
228 impl Drop for OwnedBinder {
229 fn drop(&mut self) { if !self.ptr.is_null() { unsafe { (self.dec_strong)(self.ptr) }; } }
230 }
231
232 macro_rules! dlsym_fn {
235 ($handle:expr, $name:literal, $ty:ty) => {{
236 let sym = unsafe {
237 libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char)
238 };
239 if sym.is_null() {
240 return Err(CoreError::binder(-1, concat!("dlsym:", $name)));
241 }
242 unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) }
243 }};
244 }
245
246 macro_rules! dlsym_opt {
247 ($handle:expr, $name:literal, $ty:ty) => {{
248 let sym = unsafe {
249 libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char)
250 };
251 if sym.is_null() { None }
252 else { Some(unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) }) }
253 }};
254 }
255
256 fn load_vtable(handle: *mut c_void) -> Result<Vtable, CoreError> {
257 Ok(Vtable {
258 get_service: dlsym_fn!(handle, "AServiceManager_getService",
259 unsafe extern "C" fn(*const c_char) -> *mut AIBinder),
260 class_define: dlsym_fn!(handle, "AIBinder_Class_define",
261 unsafe extern "C" fn(
262 *const c_char,
263 unsafe extern "C" fn(*mut c_void) -> *mut c_void,
264 unsafe extern "C" fn(*mut c_void),
265 unsafe extern "C" fn(*mut AIBinder, u32, *const AParcel, *mut AParcel) -> BinderStatus,
266 ) -> *mut AIBinder_Class),
267 associate_class: dlsym_fn!(handle, "AIBinder_associateClass",
268 unsafe extern "C" fn(*mut AIBinder, *mut AIBinder_Class) -> bool),
269 new_binder: dlsym_fn!(handle, "AIBinder_new",
270 unsafe extern "C" fn(*const AIBinder_Class, *mut c_void) -> *mut AIBinder),
271 prepare_transaction: dlsym_fn!(handle, "AIBinder_prepareTransaction",
272 unsafe extern "C" fn(*mut AIBinder, *mut *mut AParcel) -> BinderStatus),
273 transact: dlsym_fn!(handle, "AIBinder_transact",
274 unsafe extern "C" fn(*mut AIBinder, u32, *mut *mut AParcel, *mut *mut AParcel, u32) -> BinderStatus),
275 dec_strong: dlsym_fn!(handle, "AIBinder_decStrong",
276 unsafe extern "C" fn(*mut AIBinder)),
277 parcel_delete: dlsym_fn!(handle, "AParcel_delete",
278 unsafe extern "C" fn(*mut AParcel)),
279 read_int32: dlsym_fn!(handle, "AParcel_readInt32",
280 unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus),
281 read_string: dlsym_fn!(handle, "AParcel_readString",
282 unsafe extern "C" fn(*const AParcel, *mut c_void, StringAllocator) -> BinderStatus),
283 write_strong_binder: dlsym_fn!(handle, "AParcel_writeStrongBinder",
284 unsafe extern "C" fn(*mut AParcel, *mut AIBinder) -> BinderStatus),
285 set_thread_pool_max: dlsym_fn!(handle, "ABinderProcess_setThreadPoolMaxThreadCount",
286 unsafe extern "C" fn(u32)),
287 join_thread_pool: dlsym_fn!(handle, "ABinderProcess_joinThreadPool",
288 unsafe extern "C" fn()),
289 write_int32: dlsym_fn!(handle, "AParcel_writeInt32",
290 unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus),
291 read_bool: dlsym_opt!(handle, "AParcel_readBool",
292 unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus),
293 })
294 }
295
296 struct ParcelReader<'a> { vt: &'a Vtable, parcel: &'a OwnedParcel }
299
300 impl<'a> ParcelReader<'a> {
301 fn read_i32(&self) -> Result<i32, CoreError> {
302 let mut v = 0i32;
303 let s = unsafe { (self.vt.read_int32)(self.parcel.ptr, &mut v) };
304 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readInt32")); }
305 Ok(v)
306 }
307 fn read_string(&self) -> Result<Option<String>, CoreError> {
308 let mut buf = StringBuf::new();
309 let s = unsafe {
310 (self.vt.read_string)(self.parcel.ptr, &mut buf as *mut StringBuf as *mut c_void, string_alloc)
311 };
312 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readString")); }
313 Ok(buf.finish())
314 }
315 fn skip_i32s(&self, n: usize) -> Result<(), CoreError> {
316 for _ in 0..n { self.read_i32()?; }
317 Ok(())
318 }
319 fn skip_int_array(&self) -> Result<(), CoreError> {
320 let count = self.read_i32()?.max(0) as usize;
321 self.skip_i32s(count)
322 }
323 fn read_first_package_from_names(&self) -> Result<Option<String>, CoreError> {
324 let count = self.read_i32()?.max(0) as usize;
325 let mut first: Option<String> = None;
326 for _ in 0..count {
327 let s = self.read_string()?;
328 if first.is_none() {
329 first = s.and_then(|c| c.split('/').next().map(str::to_owned));
330 }
331 }
332 Ok(first)
333 }
334 }
335
336 fn parse_root_task_info_body(r: &ParcelReader<'_>) -> Result<Option<String>, CoreError> {
339 let scratch = r.read_i32()?;
340 if scratch != 0 { r.skip_i32s(4)?; }
341 r.skip_int_array()?;
342 r.read_first_package_from_names()
343 }
344
345 fn parse_stack_info_body(r: &ParcelReader<'_>) -> Result<Option<String>, CoreError> {
346 r.skip_i32s(5)?;
347 r.skip_int_array()?;
348 r.read_first_package_from_names()
349 }
350
351 pub struct TxCodes {
354 pub observer_code: u32,
355 pub query_code: u32,
356 pub api_mode: u8, pub fg_code: u32,
358 }
359
360 pub fn resolve_tx_codes() -> Result<TxCodes, CoreError> {
361 let (obs, query, api, fg) = dex::resolve_tx_codes_from_dex()
362 .ok_or_else(|| CoreError::binder(-1, "tx_code_resolution:dex_parse_failed"))?;
363 Ok(TxCodes { observer_code: obs, query_code: query, api_mode: api, fg_code: fg })
364 }
365
366 pub struct ActivityManagerBinder {
369 _lib: DlHandle,
370 vt: Vtable,
371 _class: *mut AIBinder_Class,
372 service: OwnedBinder,
373 tx_code: u32,
374 legacy: bool,
375 }
376 unsafe impl Send for ActivityManagerBinder {}
377
378 impl ActivityManagerBinder {
379 fn open_inner(handle: *mut c_void) -> Result<(DlHandle, Vtable, *mut AIBinder_Class, OwnedBinder), CoreError> {
380 let lib = DlHandle(handle);
381 let vt = load_vtable(handle)?;
382
383 let am_class = unsafe {
384 (vt.class_define)(
385 AM_DESCRIPTOR.as_ptr() as *const c_char,
386 am_on_create, am_on_destroy, am_on_transact,
387 )
388 };
389 if am_class.is_null() { return Err(CoreError::binder(-1, "AIBinder_Class_define:AM")); }
390
391 let raw = unsafe { (vt.get_service)(ACTIVITY_SERVICE.as_ptr() as *const c_char) };
392 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:activity")); }
393 unsafe { (vt.associate_class)(raw, am_class) };
394
395 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
396 Ok((lib, vt, am_class, service))
397 }
398
399 fn dlopen_libbinder() -> Result<*mut c_void, CoreError> {
400 use std::os::raw::c_char;
401 let handle = unsafe {
402 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
403 };
404 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
405 Ok(handle)
406 }
407
408 pub fn open() -> Result<Self, CoreError> {
411 let handle = Self::dlopen_libbinder()?;
412 let (lib, vt, class, service) = Self::open_inner(handle)?;
413 let codes = resolve_tx_codes()?;
414 let legacy = codes.api_mode == 2;
415 Ok(Self { _lib: lib, vt, _class: class, service, tx_code: codes.query_code, legacy })
416 }
417
418 pub fn open_with_observer() -> Result<(Self, OwnedFd), CoreError> {
427 let handle = Self::dlopen_libbinder()?;
428 let (lib, vt, am_class, service) = Self::open_inner(handle)?;
429 let codes = resolve_tx_codes()?;
430 let legacy = codes.api_mode == 2;
431
432 let owned = unsafe {
435 let raw = libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC);
436 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
437 OwnedFd::from_raw_fd(raw)
438 };
439
440 let obs_class = unsafe {
442 (vt.class_define)(
443 OBS_DESCRIPTOR.as_ptr() as *const c_char,
444 obs_on_create, obs_on_destroy, obs_on_transact,
445 )
446 };
447 if obs_class.is_null() {
448 return Err(CoreError::binder(-1, "AIBinder_Class_define:Observer"));
449 }
450
451 let obs_binder = unsafe { (vt.new_binder)(obs_class, std::ptr::null_mut()) };
453 if obs_binder.is_null() {
454 return Err(CoreError::binder(-1, "AIBinder_new:Observer"));
455 }
456 unsafe { (vt.associate_class)(obs_binder, obs_class) };
457
458 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
460 let s = unsafe { (vt.prepare_transaction)(service.ptr, &mut in_ptr) };
461 if s != STATUS_OK {
462 return Err(CoreError::binder(s, "prepareTransaction:registerObserver"));
463 }
464 unsafe { (vt.write_strong_binder)(in_ptr, obs_binder) };
465 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
466 let s = unsafe {
467 (vt.transact)(service.ptr, codes.observer_code, &mut in_ptr, &mut out_ptr, 0)
468 };
469 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
470 if s != STATUS_OK {
471 return Err(CoreError::binder(s, "transact:registerProcessObserver"));
472 }
473
474 let consumer = owned.try_clone()
477 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:observer"))?;
478
479 OBS_FG_CODE.store(codes.fg_code, Ordering::Relaxed);
481 *obs_eventfd_guard() = Some(owned);
482
483 unsafe { (vt.set_thread_pool_max)(0) };
485 let join_fn = vt.join_thread_pool;
486 std::thread::spawn(move || unsafe { join_fn() });
487
488 let binder = Self { _lib: lib, vt, _class: am_class, service, tx_code: codes.query_code, legacy };
489 Ok((binder, consumer))
490 }
491
492 pub fn open_with_fgproc_observer() -> Result<(Self, OwnedFd), CoreError> {
507 let handle = Self::dlopen_libbinder()?;
508 let (lib, vt, am_class, service) = Self::open_inner(handle)?;
509 let (register_code, fgproc_code) = crate::dex::resolve_fgproc_codes()
510 .ok_or_else(|| CoreError::binder(-1, "tx_code_resolution:fgproc_dex_parse_failed"))?;
511
512 let owned = unsafe {
515 let raw = libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC);
516 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
517 OwnedFd::from_raw_fd(raw)
518 };
519
520 let obs_class = unsafe {
522 (vt.class_define)(
523 FGPROC_DESCRIPTOR.as_ptr() as *const c_char,
524 fgproc_on_create, fgproc_on_destroy, fgproc_on_transact,
525 )
526 };
527 if obs_class.is_null() {
528 return Err(CoreError::binder(-1, "AIBinder_Class_define:FGProcessObserver"));
529 }
530
531 let obs_binder = unsafe { (vt.new_binder)(obs_class, std::ptr::null_mut()) };
533 if obs_binder.is_null() {
534 return Err(CoreError::binder(-1, "AIBinder_new:FGProcessObserver"));
535 }
536 unsafe { (vt.associate_class)(obs_binder, obs_class) };
537
538 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
540 let s = unsafe { (vt.prepare_transaction)(service.ptr, &mut in_ptr) };
541 if s != STATUS_OK {
542 return Err(CoreError::binder(s, "prepareTransaction:registerForegroundProcessObserver"));
543 }
544 unsafe { (vt.write_strong_binder)(in_ptr, obs_binder) };
545 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
546 let s = unsafe {
547 (vt.transact)(service.ptr, register_code, &mut in_ptr, &mut out_ptr, 0)
548 };
549 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
550 if s != STATUS_OK {
551 return Err(CoreError::binder(s, "transact:registerForegroundProcessObserver"));
552 }
553
554 let consumer = owned.try_clone()
557 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:fgproc_observer"))?;
558
559 FGPROC_READ_I32.store(vt.read_int32 as usize, Ordering::Relaxed);
563 FGPROC_FG_CODE.store(fgproc_code, Ordering::Relaxed);
564 FGPROC_PID.store(0, Ordering::Relaxed);
565 *fgproc_eventfd_guard() = Some(owned);
566
567 unsafe { (vt.set_thread_pool_max)(0) };
569 let join_fn = vt.join_thread_pool;
570 std::thread::spawn(move || unsafe { join_fn() });
571
572 let binder = Self { _lib: lib, vt, _class: am_class, service, tx_code: 0, legacy: false };
573 Ok((binder, consumer))
574 }
575
576 fn do_transact(&self) -> Result<OwnedParcel, CoreError> {
577 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
578 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut in_ptr) };
579 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
580 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
581 let s = unsafe {
582 (self.vt.transact)(self.service.ptr, self.tx_code, &mut in_ptr, &mut out_ptr, 0)
583 };
584 let out = OwnedParcel { ptr: out_ptr, delete: self.vt.parcel_delete };
585 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
586 Ok(out)
587 }
588
589 pub fn get_focused_package(&self) -> Result<Option<String>, CoreError> {
590 let out = self.do_transact()?;
591 let r = ParcelReader { vt: &self.vt, parcel: &out };
592 let ex = r.read_i32()?;
593 if ex != EX_NONE { return Err(CoreError::binder(ex, "getFocusedTask:exception")); }
594 let present = r.read_i32()?;
595 if present == 0 { return Ok(None); }
596 if self.legacy { parse_stack_info_body(&r) } else { parse_root_task_info_body(&r) }
597 }
598 }
599
600 const DISPLAY_SERVICE: &[u8] = b"display\0";
603 const DISPLAY_DESCRIPTOR: &[u8] = b"android.hardware.display.IDisplayManager\0";
604 const CALLBACK_DESCRIPTOR: &[u8] = b"android.hardware.display.IDisplayManagerCallback\0";
605 const POWER_SERVICE: &[u8] = b"power\0";
606
607 const TX_DISPLAY_REGISTER_CALLBACK: u32 = 4;
608
609 static DISP_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
612
613 fn disp_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
614 DISP_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
615 }
616
617 unsafe extern "C" fn disp_cb_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
618 unsafe extern "C" fn disp_cb_on_destroy(_: *mut c_void) {}
619 unsafe extern "C" fn disp_cb_on_transact(
620 _: *mut AIBinder, code: u32, _: *const AParcel, _: *mut AParcel,
621 ) -> BinderStatus {
622 if code == 1 {
623 if let Some(fd) = disp_eventfd_guard().as_ref() {
624 let val: u64 = 1;
625 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
626 }
627 }
628 STATUS_OK
629 }
630
631 pub struct DisplayManagerBinder {
632 _lib: DlHandle,
633 vt: Vtable,
634 display: OwnedBinder,
635 power: Option<OwnedBinder>,
636 is_interactive_tx: u32,
637 }
638 unsafe impl Send for DisplayManagerBinder {}
639
640 impl DisplayManagerBinder {
641 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), CoreError> {
642 let handle = unsafe {
643 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
644 };
645 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
646 let lib = DlHandle(handle);
647 let vt = load_vtable(handle)?;
648
649 let owned = unsafe {
653 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
654 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
655 OwnedFd::from_raw_fd(raw)
656 };
657
658 let raw_display = unsafe { (vt.get_service)(DISPLAY_SERVICE.as_ptr() as *const c_char) };
660 if raw_display.is_null() {
661 return Err(CoreError::binder(-1, "AServiceManager_getService:display"));
662 }
663 let display = OwnedBinder { ptr: raw_display, dec_strong: vt.dec_strong };
664
665 let cb_class = unsafe {
667 (vt.class_define)(
668 CALLBACK_DESCRIPTOR.as_ptr() as *const c_char,
669 disp_cb_on_create, disp_cb_on_destroy, disp_cb_on_transact,
670 )
671 };
672 if cb_class.is_null() {
673 return Err(CoreError::binder(-1, "AIBinder_Class_define:DisplayCallback"));
674 }
675
676 let cb_binder = unsafe { (vt.new_binder)(cb_class, std::ptr::null_mut()) };
677 if cb_binder.is_null() {
678 return Err(CoreError::binder(-1, "AIBinder_new:DisplayCallback"));
679 }
680
681 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
683 let s = unsafe { (vt.prepare_transaction)(display.ptr, &mut in_ptr) };
684 if s != STATUS_OK {
685 return Err(CoreError::binder(s, "prepareTransaction:registerCallback"));
686 }
687 unsafe { (vt.write_strong_binder)(in_ptr, cb_binder) };
688 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
689 let s = unsafe {
690 (vt.transact)(display.ptr, TX_DISPLAY_REGISTER_CALLBACK, &mut in_ptr, &mut out_ptr, 0)
691 };
692 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
693 if s != STATUS_OK {
694 return Err(CoreError::binder(s, "transact:registerCallback"));
695 }
696
697 let power = {
699 let raw = unsafe { (vt.get_service)(POWER_SERVICE.as_ptr() as *const c_char) };
700 if raw.is_null() { None } else { Some(OwnedBinder { ptr: raw, dec_strong: vt.dec_strong }) }
701 };
702
703 let is_interactive_tx = crate::dex::resolve_is_interactive_tx()
705 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_isInteractive not found"))?;
706
707 let efd_owned = owned.try_clone()
710 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:display"))
711 .and_then(|dup| unsafe {
712 crate::reactor::Fd::from_owned_raw_fd(dup.into_raw_fd(), "display.efd")
713 .map_err(|_| CoreError::binder(-1, "Fd::from_owned_raw_fd:display.efd"))
714 })?;
715
716 *disp_eventfd_guard() = Some(owned);
718
719 unsafe { (vt.set_thread_pool_max)(0) };
721 let join_fn = vt.join_thread_pool;
722 std::thread::spawn(move || unsafe { join_fn() });
723
724 Ok((Self { _lib: lib, vt, display, power, is_interactive_tx }, efd_owned))
725 }
726
727 pub fn is_interactive(&self) -> Result<bool, CoreError> {
728 let power = self.power.as_ref()
729 .ok_or_else(|| CoreError::binder(-1, "power:unavailable"))?;
730 let mut inp: *mut AParcel = std::ptr::null_mut();
731 let s = unsafe { (self.vt.prepare_transaction)(power.ptr, &mut inp) };
732 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:isInteractive")); }
733 let mut out: *mut AParcel = std::ptr::null_mut();
734 let s = unsafe {
735 (self.vt.transact)(power.ptr, self.is_interactive_tx, &mut inp, &mut out, 0)
736 };
737 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
738 if s != STATUS_OK { return Err(CoreError::binder(s, "transact:isInteractive")); }
739 let r = ParcelReader { vt: &self.vt, parcel: &out };
740 let ex = r.read_i32()?;
741 if ex != EX_NONE { return Err(CoreError::binder(ex, "isInteractive:exception")); }
742 if let Some(rb) = self.vt.read_bool {
743 let mut v = false;
744 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
745 if s != STATUS_OK { return Err(CoreError::binder(s, "readBool:isInteractive")); }
746 Ok(v)
747 } else {
748 Ok(r.read_i32()? != 0)
749 }
750 }
751 }
752
753 pub struct RawBinderService {
762 _lib: DlHandle,
763 vt: Vtable,
764 service: OwnedBinder,
765 }
766 unsafe impl Send for RawBinderService {}
767
768 impl RawBinderService {
769 pub fn open(service_name: &str) -> Result<Self, CoreError> {
771 use std::ffi::CString;
772 let handle = unsafe {
773 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
774 };
775 if handle.is_null() {
776 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
777 }
778 let lib = DlHandle(handle);
779 let vt = load_vtable(handle)?;
780 let cs = CString::new(service_name)
781 .map_err(|_| CoreError::binder(-1, "service_name:nul_byte"))?;
782 let raw = unsafe { (vt.get_service)(cs.as_ptr()) };
783 if raw.is_null() {
784 return Err(CoreError::binder(-1, "AServiceManager_getService:null"));
785 }
786 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
787 Ok(Self { _lib: lib, vt, service })
788 }
789
790 pub fn transact_bool(&self, code: u32) -> Result<bool, CoreError> {
792 let out = self.raw_noarg(code)?;
793 let r = ParcelReader { vt: &self.vt, parcel: &out };
794 let ex = r.read_i32()?;
795 if ex != EX_NONE { return Err(CoreError::binder(ex, "transact_bool:exception")); }
796 if let Some(rb) = self.vt.read_bool {
797 let mut v = false;
798 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
799 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readBool")); }
800 Ok(v)
801 } else {
802 Ok(r.read_i32()? != 0)
803 }
804 }
805
806 pub fn transact_i32(&self, code: u32, arg: i32) -> Result<(), CoreError> {
808 let mut inp: *mut AParcel = std::ptr::null_mut();
809 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
810 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
811 let s = unsafe { (self.vt.write_int32)(inp, arg) };
812 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeInt32")); }
813 let mut out: *mut AParcel = std::ptr::null_mut();
814 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
815 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
816 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
817 Ok(())
818 }
819
820 fn raw_noarg(&self, code: u32) -> Result<OwnedParcel, CoreError> {
821 let mut inp: *mut AParcel = std::ptr::null_mut();
822 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
823 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
824 let mut out: *mut AParcel = std::ptr::null_mut();
825 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
826 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
827 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
828 Ok(out)
829 }
830 }
831}
832
833#[cfg(target_os = "android")]
836pub use imp::{ActivityManagerBinder, DisplayManagerBinder, RawBinderService, TxCodes, last_foreground_pid, resolve_tx_codes};
837
838#[cfg(not(target_os = "android"))]
841pub struct ActivityManagerBinder;
842
843#[cfg(not(target_os = "android"))]
844impl ActivityManagerBinder {
845 pub fn open() -> Result<Self, crate::CoreError> {
846 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
847 }
848 pub fn open_with_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
849 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
850 }
851 pub fn open_with_fgproc_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
852 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
853 }
854 pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
855 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
856 }
857}
858
859#[cfg(not(target_os = "android"))]
860pub struct DisplayManagerBinder;
861
862#[cfg(not(target_os = "android"))]
863impl DisplayManagerBinder {
864 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), crate::CoreError> {
865 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
866 }
867 pub fn is_interactive(&self) -> Result<bool, crate::CoreError> {
868 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
869 }
870}
871
872#[cfg(not(target_os = "android"))]
873pub struct RawBinderService;
874
875#[cfg(not(target_os = "android"))]
876impl RawBinderService {
877 pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
878 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
879 }
880 pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
881 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
882 }
883 pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
884 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
885 }
886}
887
888#[cfg(not(target_os = "android"))]
889pub struct TxCodes { pub observer_code: u32, pub query_code: u32, pub api_mode: u8, pub fg_code: u32 }
890
891#[cfg(not(target_os = "android"))]
892pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
893 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
894}
895
896#[cfg(not(target_os = "android"))]
897pub fn last_foreground_pid() -> i32 {
898 0
899}