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 pub struct RawBinderService {
454 _lib: DlHandle,
455 vt: Vtable,
456 service: OwnedBinder,
457 }
458 unsafe impl Send for RawBinderService {}
459
460 impl RawBinderService {
461 pub fn open(service_name: &str) -> Result<Self, CoreError> {
463 use std::ffi::CString;
464 let handle = unsafe {
465 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
466 };
467 if handle.is_null() {
468 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
469 }
470 let lib = DlHandle(handle);
471 let vt = load_vtable(handle)?;
472 let cs = CString::new(service_name)
473 .map_err(|_| CoreError::binder(-1, "service_name:nul_byte"))?;
474 let raw = unsafe { (vt.get_service)(cs.as_ptr()) };
475 if raw.is_null() {
476 return Err(CoreError::binder(-1, "AServiceManager_getService:null"));
477 }
478 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
479 Ok(Self { _lib: lib, vt, service })
480 }
481
482 pub fn transact_bool(&self, code: u32) -> Result<bool, CoreError> {
484 let out = self.raw_noarg(code)?;
485 let r = ParcelReader { vt: &self.vt, parcel: &out };
486 let ex = r.read_i32()?;
487 if ex != EX_NONE { return Err(CoreError::binder(ex, "transact_bool:exception")); }
488 if let Some(rb) = self.vt.read_bool {
489 let mut v = false;
490 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
491 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readBool")); }
492 Ok(v)
493 } else {
494 Ok(r.read_i32()? != 0)
495 }
496 }
497
498 pub fn transact_i32(&self, code: u32, arg: i32) -> Result<(), CoreError> {
500 let mut inp: *mut AParcel = std::ptr::null_mut();
501 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
502 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
503 let s = unsafe { (self.vt.write_int32)(inp, arg) };
504 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeInt32")); }
505 let mut out: *mut AParcel = std::ptr::null_mut();
506 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
507 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
508 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
509 Ok(())
510 }
511
512 fn raw_noarg(&self, code: u32) -> Result<OwnedParcel, CoreError> {
513 let mut inp: *mut AParcel = std::ptr::null_mut();
514 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
515 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
516 let mut out: *mut AParcel = std::ptr::null_mut();
517 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
518 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
519 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
520 Ok(out)
521 }
522 }
523}
524
525#[cfg(target_os = "android")]
528pub use imp::{ActivityManagerBinder, RawBinderService, TxCodes, resolve_tx_codes};
529
530#[cfg(not(target_os = "android"))]
533pub struct ActivityManagerBinder;
534
535#[cfg(not(target_os = "android"))]
536impl ActivityManagerBinder {
537 pub fn open() -> Result<Self, crate::CoreError> {
538 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
539 }
540 pub fn open_with_observer() -> Result<(Self, i32), crate::CoreError> {
541 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
542 }
543 pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
544 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
545 }
546}
547
548#[cfg(not(target_os = "android"))]
549pub struct RawBinderService;
550
551#[cfg(not(target_os = "android"))]
552impl RawBinderService {
553 pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
554 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
555 }
556 pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
557 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
558 }
559 pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
560 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
561 }
562}
563
564#[cfg(not(target_os = "android"))]
565pub struct TxCodes { pub observer_code: u32, pub query_code: u32, pub api_mode: u8, pub fg_code: u32 }
566
567#[cfg(not(target_os = "android"))]
568pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
569 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
570}