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::{AtomicU32, 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 ACTIVITY_SERVICE: &[u8] = b"activity\0";
46 #[cfg(target_pointer_width = "64")]
47 const LIBBINDER_PATH: &[u8] = b"/system/lib64/libbinder_ndk.so\0";
48 #[cfg(target_pointer_width = "32")]
49 const LIBBINDER_PATH: &[u8] = b"/system/lib/libbinder_ndk.so\0";
50
51 static OBS_FG_CODE: AtomicU32 = AtomicU32::new(0);
62 static OBS_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
63
64 fn obs_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
65 OBS_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
66 }
67
68 type AIBinder = c_void;
71 #[allow(non_camel_case_types)]
72 type AIBinder_Class = c_void;
73 type AParcel = c_void;
74 type BinderStatus = i32;
75 type StringAllocator = unsafe extern "C" fn(*mut c_void, i32, *mut *mut c_char) -> bool;
76
77 unsafe extern "C" fn am_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
81 unsafe extern "C" fn am_on_destroy(_: *mut c_void) {}
82 unsafe extern "C" fn am_on_transact(
83 _: *mut AIBinder, _: u32, _: *const AParcel, _: *mut AParcel,
84 ) -> BinderStatus { STATUS_UNKNOWN_TRANSACTION }
85
86 unsafe extern "C" fn obs_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
88 unsafe extern "C" fn obs_on_destroy(_: *mut c_void) {}
89 unsafe extern "C" fn obs_on_transact(
90 _: *mut AIBinder, code: u32, _: *const AParcel, _: *mut AParcel,
91 ) -> BinderStatus {
92 if code == OBS_FG_CODE.load(Ordering::Relaxed) {
93 if let Some(fd) = obs_eventfd_guard().as_ref() {
96 let val: u64 = 1;
97 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
98 }
99 }
100 STATUS_OK
101 }
102
103 unsafe extern "C" fn string_alloc(
106 cookie: *mut c_void, length: i32, buffer: *mut *mut c_char,
107 ) -> bool {
108 if length < 0 { return true; }
109 let s = unsafe { &mut *(cookie as *mut StringBuf) };
110 s.0.reserve_exact(length as usize + 1);
111 unsafe { s.0.as_mut_vec().resize(length as usize + 1, 0) };
112 unsafe { *buffer = s.0.as_mut_ptr() as *mut c_char };
113 true
114 }
115
116 struct StringBuf(String);
117 impl StringBuf {
118 fn new() -> Self { Self(String::new()) }
119 fn finish(mut self) -> Option<String> {
120 if let Some(pos) = self.0.as_bytes().iter().position(|&b| b == 0) {
121 unsafe { self.0.as_mut_vec().truncate(pos) };
122 }
123 if self.0.is_empty() { None } else { Some(self.0) }
124 }
125 }
126
127 struct Vtable {
130 get_service: unsafe extern "C" fn(*const c_char) -> *mut AIBinder,
131 class_define: unsafe extern "C" fn(
132 *const c_char,
133 unsafe extern "C" fn(*mut c_void) -> *mut c_void,
134 unsafe extern "C" fn(*mut c_void),
135 unsafe extern "C" fn(*mut AIBinder, u32, *const AParcel, *mut AParcel) -> BinderStatus,
136 ) -> *mut AIBinder_Class,
137 associate_class: unsafe extern "C" fn(*mut AIBinder, *mut AIBinder_Class) -> bool,
138 new_binder: unsafe extern "C" fn(*const AIBinder_Class, *mut c_void) -> *mut AIBinder,
139 prepare_transaction: unsafe extern "C" fn(*mut AIBinder, *mut *mut AParcel) -> BinderStatus,
140 transact: unsafe extern "C" fn(*mut AIBinder, u32, *mut *mut AParcel, *mut *mut AParcel, u32) -> BinderStatus,
141 dec_strong: unsafe extern "C" fn(*mut AIBinder),
142 parcel_delete: unsafe extern "C" fn(*mut AParcel),
143 read_int32: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus,
144 read_string: unsafe extern "C" fn(*const AParcel, *mut c_void, StringAllocator) -> BinderStatus,
145 write_strong_binder: unsafe extern "C" fn(*mut AParcel, *mut AIBinder) -> BinderStatus,
146 set_thread_pool_max: unsafe extern "C" fn(u32),
147 join_thread_pool: unsafe extern "C" fn(),
148 write_int32: unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus,
149 read_bool: Option<unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus>,
151 }
152
153 struct DlHandle(*mut c_void);
156 unsafe impl Send for DlHandle {}
157 impl Drop for DlHandle {
158 fn drop(&mut self) {
159 }
165 }
166
167 struct OwnedParcel { ptr: *mut AParcel, delete: unsafe extern "C" fn(*mut AParcel) }
168 impl Drop for OwnedParcel {
169 fn drop(&mut self) { if !self.ptr.is_null() { unsafe { (self.delete)(self.ptr) }; } }
170 }
171
172 struct OwnedBinder { ptr: *mut AIBinder, dec_strong: unsafe extern "C" fn(*mut AIBinder) }
173 unsafe impl Send for OwnedBinder {}
174 impl Drop for OwnedBinder {
175 fn drop(&mut self) { if !self.ptr.is_null() { unsafe { (self.dec_strong)(self.ptr) }; } }
176 }
177
178 macro_rules! dlsym_fn {
181 ($handle:expr, $name:literal, $ty:ty) => {{
182 let sym = unsafe {
183 libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char)
184 };
185 if sym.is_null() {
186 return Err(CoreError::binder(-1, concat!("dlsym:", $name)));
187 }
188 unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) }
189 }};
190 }
191
192 macro_rules! dlsym_opt {
193 ($handle:expr, $name:literal, $ty:ty) => {{
194 let sym = unsafe {
195 libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char)
196 };
197 if sym.is_null() { None }
198 else { Some(unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) }) }
199 }};
200 }
201
202 fn load_vtable(handle: *mut c_void) -> Result<Vtable, CoreError> {
203 Ok(Vtable {
204 get_service: dlsym_fn!(handle, "AServiceManager_getService",
205 unsafe extern "C" fn(*const c_char) -> *mut AIBinder),
206 class_define: dlsym_fn!(handle, "AIBinder_Class_define",
207 unsafe extern "C" fn(
208 *const c_char,
209 unsafe extern "C" fn(*mut c_void) -> *mut c_void,
210 unsafe extern "C" fn(*mut c_void),
211 unsafe extern "C" fn(*mut AIBinder, u32, *const AParcel, *mut AParcel) -> BinderStatus,
212 ) -> *mut AIBinder_Class),
213 associate_class: dlsym_fn!(handle, "AIBinder_associateClass",
214 unsafe extern "C" fn(*mut AIBinder, *mut AIBinder_Class) -> bool),
215 new_binder: dlsym_fn!(handle, "AIBinder_new",
216 unsafe extern "C" fn(*const AIBinder_Class, *mut c_void) -> *mut AIBinder),
217 prepare_transaction: dlsym_fn!(handle, "AIBinder_prepareTransaction",
218 unsafe extern "C" fn(*mut AIBinder, *mut *mut AParcel) -> BinderStatus),
219 transact: dlsym_fn!(handle, "AIBinder_transact",
220 unsafe extern "C" fn(*mut AIBinder, u32, *mut *mut AParcel, *mut *mut AParcel, u32) -> BinderStatus),
221 dec_strong: dlsym_fn!(handle, "AIBinder_decStrong",
222 unsafe extern "C" fn(*mut AIBinder)),
223 parcel_delete: dlsym_fn!(handle, "AParcel_delete",
224 unsafe extern "C" fn(*mut AParcel)),
225 read_int32: dlsym_fn!(handle, "AParcel_readInt32",
226 unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus),
227 read_string: dlsym_fn!(handle, "AParcel_readString",
228 unsafe extern "C" fn(*const AParcel, *mut c_void, StringAllocator) -> BinderStatus),
229 write_strong_binder: dlsym_fn!(handle, "AParcel_writeStrongBinder",
230 unsafe extern "C" fn(*mut AParcel, *mut AIBinder) -> BinderStatus),
231 set_thread_pool_max: dlsym_fn!(handle, "ABinderProcess_setThreadPoolMaxThreadCount",
232 unsafe extern "C" fn(u32)),
233 join_thread_pool: dlsym_fn!(handle, "ABinderProcess_joinThreadPool",
234 unsafe extern "C" fn()),
235 write_int32: dlsym_fn!(handle, "AParcel_writeInt32",
236 unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus),
237 read_bool: dlsym_opt!(handle, "AParcel_readBool",
238 unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus),
239 })
240 }
241
242 struct ParcelReader<'a> { vt: &'a Vtable, parcel: &'a OwnedParcel }
245
246 impl<'a> ParcelReader<'a> {
247 fn read_i32(&self) -> Result<i32, CoreError> {
248 let mut v = 0i32;
249 let s = unsafe { (self.vt.read_int32)(self.parcel.ptr, &mut v) };
250 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readInt32")); }
251 Ok(v)
252 }
253 fn read_string(&self) -> Result<Option<String>, CoreError> {
254 let mut buf = StringBuf::new();
255 let s = unsafe {
256 (self.vt.read_string)(self.parcel.ptr, &mut buf as *mut StringBuf as *mut c_void, string_alloc)
257 };
258 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readString")); }
259 Ok(buf.finish())
260 }
261 fn skip_i32s(&self, n: usize) -> Result<(), CoreError> {
262 for _ in 0..n { self.read_i32()?; }
263 Ok(())
264 }
265 fn skip_int_array(&self) -> Result<(), CoreError> {
266 let count = self.read_i32()?.max(0) as usize;
267 self.skip_i32s(count)
268 }
269 fn read_first_package_from_names(&self) -> Result<Option<String>, CoreError> {
270 let count = self.read_i32()?.max(0) as usize;
271 let mut first: Option<String> = None;
272 for _ in 0..count {
273 let s = self.read_string()?;
274 if first.is_none() {
275 first = s.and_then(|c| c.split('/').next().map(str::to_owned));
276 }
277 }
278 Ok(first)
279 }
280 }
281
282 fn parse_root_task_info_body(r: &ParcelReader<'_>) -> Result<Option<String>, CoreError> {
285 let scratch = r.read_i32()?;
286 if scratch != 0 { r.skip_i32s(4)?; }
287 r.skip_int_array()?;
288 r.read_first_package_from_names()
289 }
290
291 fn parse_stack_info_body(r: &ParcelReader<'_>) -> Result<Option<String>, CoreError> {
292 r.skip_i32s(5)?;
293 r.skip_int_array()?;
294 r.read_first_package_from_names()
295 }
296
297 pub struct TxCodes {
300 pub observer_code: u32,
301 pub query_code: u32,
302 pub api_mode: u8, pub fg_code: u32,
304 }
305
306 pub fn resolve_tx_codes() -> Result<TxCodes, CoreError> {
307 let (obs, query, api, fg) = dex::resolve_tx_codes_from_dex()
308 .ok_or_else(|| CoreError::binder(-1, "tx_code_resolution:dex_parse_failed"))?;
309 Ok(TxCodes { observer_code: obs, query_code: query, api_mode: api, fg_code: fg })
310 }
311
312 pub struct ActivityManagerBinder {
315 _lib: DlHandle,
316 vt: Vtable,
317 _class: *mut AIBinder_Class,
318 service: OwnedBinder,
319 tx_code: u32,
320 legacy: bool,
321 }
322 unsafe impl Send for ActivityManagerBinder {}
323
324 impl ActivityManagerBinder {
325 fn open_inner(handle: *mut c_void) -> Result<(DlHandle, Vtable, *mut AIBinder_Class, OwnedBinder), CoreError> {
326 let lib = DlHandle(handle);
327 let vt = load_vtable(handle)?;
328
329 let am_class = unsafe {
330 (vt.class_define)(
331 AM_DESCRIPTOR.as_ptr() as *const c_char,
332 am_on_create, am_on_destroy, am_on_transact,
333 )
334 };
335 if am_class.is_null() { return Err(CoreError::binder(-1, "AIBinder_Class_define:AM")); }
336
337 let raw = unsafe { (vt.get_service)(ACTIVITY_SERVICE.as_ptr() as *const c_char) };
338 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:activity")); }
339 unsafe { (vt.associate_class)(raw, am_class) };
340
341 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
342 Ok((lib, vt, am_class, service))
343 }
344
345 fn dlopen_libbinder() -> Result<*mut c_void, CoreError> {
346 use std::os::raw::c_char;
347 let handle = unsafe {
348 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
349 };
350 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
351 Ok(handle)
352 }
353
354 pub fn open() -> Result<Self, CoreError> {
357 let handle = Self::dlopen_libbinder()?;
358 let (lib, vt, class, service) = Self::open_inner(handle)?;
359 let codes = resolve_tx_codes()?;
360 let legacy = codes.api_mode == 2;
361 Ok(Self { _lib: lib, vt, _class: class, service, tx_code: codes.query_code, legacy })
362 }
363
364 pub fn open_with_observer() -> Result<(Self, OwnedFd), CoreError> {
373 let handle = Self::dlopen_libbinder()?;
374 let (lib, vt, am_class, service) = Self::open_inner(handle)?;
375 let codes = resolve_tx_codes()?;
376 let legacy = codes.api_mode == 2;
377
378 let owned = unsafe {
381 let raw = libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC);
382 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
383 OwnedFd::from_raw_fd(raw)
384 };
385
386 let obs_class = unsafe {
388 (vt.class_define)(
389 OBS_DESCRIPTOR.as_ptr() as *const c_char,
390 obs_on_create, obs_on_destroy, obs_on_transact,
391 )
392 };
393 if obs_class.is_null() {
394 return Err(CoreError::binder(-1, "AIBinder_Class_define:Observer"));
395 }
396
397 let obs_binder = unsafe { (vt.new_binder)(obs_class, std::ptr::null_mut()) };
399 if obs_binder.is_null() {
400 return Err(CoreError::binder(-1, "AIBinder_new:Observer"));
401 }
402 unsafe { (vt.associate_class)(obs_binder, obs_class) };
403
404 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
406 let s = unsafe { (vt.prepare_transaction)(service.ptr, &mut in_ptr) };
407 if s != STATUS_OK {
408 return Err(CoreError::binder(s, "prepareTransaction:registerObserver"));
409 }
410 unsafe { (vt.write_strong_binder)(in_ptr, obs_binder) };
411 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
412 let s = unsafe {
413 (vt.transact)(service.ptr, codes.observer_code, &mut in_ptr, &mut out_ptr, 0)
414 };
415 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
416 if s != STATUS_OK {
417 return Err(CoreError::binder(s, "transact:registerProcessObserver"));
418 }
419
420 let consumer = owned.try_clone()
423 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:observer"))?;
424
425 OBS_FG_CODE.store(codes.fg_code, Ordering::Relaxed);
427 *obs_eventfd_guard() = Some(owned);
428
429 unsafe { (vt.set_thread_pool_max)(0) };
431 let join_fn = vt.join_thread_pool;
432 std::thread::spawn(move || unsafe { join_fn() });
433
434 let binder = Self { _lib: lib, vt, _class: am_class, service, tx_code: codes.query_code, legacy };
435 Ok((binder, consumer))
436 }
437
438 fn do_transact(&self) -> Result<OwnedParcel, CoreError> {
439 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
440 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut in_ptr) };
441 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
442 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
443 let s = unsafe {
444 (self.vt.transact)(self.service.ptr, self.tx_code, &mut in_ptr, &mut out_ptr, 0)
445 };
446 let out = OwnedParcel { ptr: out_ptr, delete: self.vt.parcel_delete };
447 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
448 Ok(out)
449 }
450
451 pub fn get_focused_package(&self) -> Result<Option<String>, CoreError> {
452 let out = self.do_transact()?;
453 let r = ParcelReader { vt: &self.vt, parcel: &out };
454 let ex = r.read_i32()?;
455 if ex != EX_NONE { return Err(CoreError::binder(ex, "getFocusedTask:exception")); }
456 let present = r.read_i32()?;
457 if present == 0 { return Ok(None); }
458 if self.legacy { parse_stack_info_body(&r) } else { parse_root_task_info_body(&r) }
459 }
460 }
461
462 const DISPLAY_SERVICE: &[u8] = b"display\0";
465 const DISPLAY_DESCRIPTOR: &[u8] = b"android.hardware.display.IDisplayManager\0";
466 const CALLBACK_DESCRIPTOR: &[u8] = b"android.hardware.display.IDisplayManagerCallback\0";
467 const POWER_SERVICE: &[u8] = b"power\0";
468
469 const TX_DISPLAY_REGISTER_CALLBACK: u32 = 4;
470
471 static DISP_EVENTFD: Mutex<Option<OwnedFd>> = Mutex::new(None);
474
475 fn disp_eventfd_guard() -> std::sync::MutexGuard<'static, Option<OwnedFd>> {
476 DISP_EVENTFD.lock().unwrap_or_else(|p| p.into_inner())
477 }
478
479 unsafe extern "C" fn disp_cb_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
480 unsafe extern "C" fn disp_cb_on_destroy(_: *mut c_void) {}
481 unsafe extern "C" fn disp_cb_on_transact(
482 _: *mut AIBinder, code: u32, _: *const AParcel, _: *mut AParcel,
483 ) -> BinderStatus {
484 if code == 1 {
485 if let Some(fd) = disp_eventfd_guard().as_ref() {
486 let val: u64 = 1;
487 unsafe { libc::write(fd.as_raw_fd(), &val as *const u64 as *const c_void, 8) };
488 }
489 }
490 STATUS_OK
491 }
492
493 pub struct DisplayManagerBinder {
494 _lib: DlHandle,
495 vt: Vtable,
496 display: OwnedBinder,
497 power: Option<OwnedBinder>,
498 is_interactive_tx: u32,
499 }
500 unsafe impl Send for DisplayManagerBinder {}
501
502 impl DisplayManagerBinder {
503 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), CoreError> {
504 let handle = unsafe {
505 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
506 };
507 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
508 let lib = DlHandle(handle);
509 let vt = load_vtable(handle)?;
510
511 let owned = unsafe {
515 let raw = libc::eventfd(0, libc::EFD_CLOEXEC);
516 if raw < 0 { return Err(CoreError::sys(*libc::__errno(), "eventfd")); }
517 OwnedFd::from_raw_fd(raw)
518 };
519
520 let raw_display = unsafe { (vt.get_service)(DISPLAY_SERVICE.as_ptr() as *const c_char) };
522 if raw_display.is_null() {
523 return Err(CoreError::binder(-1, "AServiceManager_getService:display"));
524 }
525 let display = OwnedBinder { ptr: raw_display, dec_strong: vt.dec_strong };
526
527 let cb_class = unsafe {
529 (vt.class_define)(
530 CALLBACK_DESCRIPTOR.as_ptr() as *const c_char,
531 disp_cb_on_create, disp_cb_on_destroy, disp_cb_on_transact,
532 )
533 };
534 if cb_class.is_null() {
535 return Err(CoreError::binder(-1, "AIBinder_Class_define:DisplayCallback"));
536 }
537
538 let cb_binder = unsafe { (vt.new_binder)(cb_class, std::ptr::null_mut()) };
539 if cb_binder.is_null() {
540 return Err(CoreError::binder(-1, "AIBinder_new:DisplayCallback"));
541 }
542
543 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
545 let s = unsafe { (vt.prepare_transaction)(display.ptr, &mut in_ptr) };
546 if s != STATUS_OK {
547 return Err(CoreError::binder(s, "prepareTransaction:registerCallback"));
548 }
549 unsafe { (vt.write_strong_binder)(in_ptr, cb_binder) };
550 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
551 let s = unsafe {
552 (vt.transact)(display.ptr, TX_DISPLAY_REGISTER_CALLBACK, &mut in_ptr, &mut out_ptr, 0)
553 };
554 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
555 if s != STATUS_OK {
556 return Err(CoreError::binder(s, "transact:registerCallback"));
557 }
558
559 let power = {
561 let raw = unsafe { (vt.get_service)(POWER_SERVICE.as_ptr() as *const c_char) };
562 if raw.is_null() { None } else { Some(OwnedBinder { ptr: raw, dec_strong: vt.dec_strong }) }
563 };
564
565 let is_interactive_tx = crate::dex::resolve_is_interactive_tx()
567 .ok_or_else(|| CoreError::binder(-1, "dex:TRANSACTION_isInteractive not found"))?;
568
569 let efd_owned = owned.try_clone()
572 .map_err(|e| CoreError::sys(e.raw_os_error().unwrap_or(-1), "dup:display"))
573 .and_then(|dup| unsafe {
574 crate::reactor::Fd::from_owned_raw_fd(dup.into_raw_fd(), "display.efd")
575 .map_err(|_| CoreError::binder(-1, "Fd::from_owned_raw_fd:display.efd"))
576 })?;
577
578 *disp_eventfd_guard() = Some(owned);
580
581 unsafe { (vt.set_thread_pool_max)(0) };
583 let join_fn = vt.join_thread_pool;
584 std::thread::spawn(move || unsafe { join_fn() });
585
586 Ok((Self { _lib: lib, vt, display, power, is_interactive_tx }, efd_owned))
587 }
588
589 pub fn is_interactive(&self) -> Result<bool, CoreError> {
590 let power = self.power.as_ref()
591 .ok_or_else(|| CoreError::binder(-1, "power:unavailable"))?;
592 let mut inp: *mut AParcel = std::ptr::null_mut();
593 let s = unsafe { (self.vt.prepare_transaction)(power.ptr, &mut inp) };
594 if s != STATUS_OK { return Err(CoreError::binder(s, "prepareTransaction:isInteractive")); }
595 let mut out: *mut AParcel = std::ptr::null_mut();
596 let s = unsafe {
597 (self.vt.transact)(power.ptr, self.is_interactive_tx, &mut inp, &mut out, 0)
598 };
599 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
600 if s != STATUS_OK { return Err(CoreError::binder(s, "transact:isInteractive")); }
601 let r = ParcelReader { vt: &self.vt, parcel: &out };
602 let ex = r.read_i32()?;
603 if ex != EX_NONE { return Err(CoreError::binder(ex, "isInteractive:exception")); }
604 if let Some(rb) = self.vt.read_bool {
605 let mut v = false;
606 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
607 if s != STATUS_OK { return Err(CoreError::binder(s, "readBool:isInteractive")); }
608 Ok(v)
609 } else {
610 Ok(r.read_i32()? != 0)
611 }
612 }
613 }
614
615 pub struct RawBinderService {
624 _lib: DlHandle,
625 vt: Vtable,
626 service: OwnedBinder,
627 }
628 unsafe impl Send for RawBinderService {}
629
630 impl RawBinderService {
631 pub fn open(service_name: &str) -> Result<Self, CoreError> {
633 use std::ffi::CString;
634 let handle = unsafe {
635 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
636 };
637 if handle.is_null() {
638 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
639 }
640 let lib = DlHandle(handle);
641 let vt = load_vtable(handle)?;
642 let cs = CString::new(service_name)
643 .map_err(|_| CoreError::binder(-1, "service_name:nul_byte"))?;
644 let raw = unsafe { (vt.get_service)(cs.as_ptr()) };
645 if raw.is_null() {
646 return Err(CoreError::binder(-1, "AServiceManager_getService:null"));
647 }
648 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
649 Ok(Self { _lib: lib, vt, service })
650 }
651
652 pub fn transact_bool(&self, code: u32) -> Result<bool, CoreError> {
654 let out = self.raw_noarg(code)?;
655 let r = ParcelReader { vt: &self.vt, parcel: &out };
656 let ex = r.read_i32()?;
657 if ex != EX_NONE { return Err(CoreError::binder(ex, "transact_bool:exception")); }
658 if let Some(rb) = self.vt.read_bool {
659 let mut v = false;
660 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
661 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readBool")); }
662 Ok(v)
663 } else {
664 Ok(r.read_i32()? != 0)
665 }
666 }
667
668 pub fn transact_i32(&self, code: u32, arg: i32) -> Result<(), CoreError> {
670 let mut inp: *mut AParcel = std::ptr::null_mut();
671 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
672 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
673 let s = unsafe { (self.vt.write_int32)(inp, arg) };
674 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeInt32")); }
675 let mut out: *mut AParcel = std::ptr::null_mut();
676 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
677 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
678 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
679 Ok(())
680 }
681
682 fn raw_noarg(&self, code: u32) -> Result<OwnedParcel, CoreError> {
683 let mut inp: *mut AParcel = std::ptr::null_mut();
684 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
685 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
686 let mut out: *mut AParcel = std::ptr::null_mut();
687 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
688 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
689 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
690 Ok(out)
691 }
692 }
693}
694
695#[cfg(target_os = "android")]
698pub use imp::{ActivityManagerBinder, DisplayManagerBinder, RawBinderService, TxCodes, resolve_tx_codes};
699
700#[cfg(not(target_os = "android"))]
703pub struct ActivityManagerBinder;
704
705#[cfg(not(target_os = "android"))]
706impl ActivityManagerBinder {
707 pub fn open() -> Result<Self, crate::CoreError> {
708 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
709 }
710 pub fn open_with_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
711 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
712 }
713 pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
714 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
715 }
716}
717
718#[cfg(not(target_os = "android"))]
719pub struct DisplayManagerBinder;
720
721#[cfg(not(target_os = "android"))]
722impl DisplayManagerBinder {
723 pub fn open_with_callback() -> Result<(Self, crate::reactor::Fd), crate::CoreError> {
724 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
725 }
726 pub fn is_interactive(&self) -> Result<bool, crate::CoreError> {
727 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
728 }
729}
730
731#[cfg(not(target_os = "android"))]
732pub struct RawBinderService;
733
734#[cfg(not(target_os = "android"))]
735impl RawBinderService {
736 pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
737 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
738 }
739 pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
740 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
741 }
742 pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
743 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
744 }
745}
746
747#[cfg(not(target_os = "android"))]
748pub struct TxCodes { pub observer_code: u32, pub query_code: u32, pub api_mode: u8, pub fg_code: u32 }
749
750#[cfg(not(target_os = "android"))]
751pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
752 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
753}