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