1use crate::CoreError;
23
24#[cfg(target_os = "android")]
29mod imp {
30 use super::*;
31 use crate::dex;
32 use std::os::raw::{c_char, c_void};
33 use std::sync::atomic::{AtomicI32, AtomicU32, Ordering};
34
35 const STATUS_OK: i32 = 0;
38 const STATUS_UNKNOWN_TRANSACTION: i32 = -2;
39 const EX_NONE: i32 = 0;
40
41 const AM_DESCRIPTOR: &[u8] = b"android.app.IActivityManager\0";
44 const OBS_DESCRIPTOR: &[u8] = b"android.app.IProcessObserver\0";
45 const ACTIVITY_SERVICE: &[u8] = b"activity\0";
46 const LIBBINDER_PATH: &[u8] = b"/system/lib64/libbinder_ndk.so\0";
47
48 static OBS_FG_CODE: AtomicU32 = AtomicU32::new(0);
57 static OBS_EVENTFD: AtomicI32 = AtomicI32::new(-1);
58
59 type AIBinder = c_void;
62 #[allow(non_camel_case_types)]
63 type AIBinder_Class = c_void;
64 type AParcel = c_void;
65 type BinderStatus = i32;
66 type StringAllocator = unsafe extern "C" fn(*mut c_void, i32, *mut *mut c_char) -> bool;
67
68 unsafe extern "C" fn am_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
72 unsafe extern "C" fn am_on_destroy(_: *mut c_void) {}
73 unsafe extern "C" fn am_on_transact(
74 _: *mut AIBinder, _: u32, _: *const AParcel, _: *mut AParcel,
75 ) -> BinderStatus { STATUS_UNKNOWN_TRANSACTION }
76
77 unsafe extern "C" fn obs_on_create(_: *mut c_void) -> *mut c_void { std::ptr::null_mut() }
79 unsafe extern "C" fn obs_on_destroy(_: *mut c_void) {}
80 unsafe extern "C" fn obs_on_transact(
81 _: *mut AIBinder, code: u32, _: *const AParcel, _: *mut AParcel,
82 ) -> BinderStatus {
83 if code == OBS_FG_CODE.load(Ordering::Relaxed) {
84 let efd = OBS_EVENTFD.load(Ordering::Relaxed);
85 if efd >= 0 {
86 let val: u64 = 1;
87 unsafe { libc::write(efd, &val as *const u64 as *const c_void, 8) };
88 }
89 }
90 STATUS_OK
91 }
92
93 unsafe extern "C" fn string_alloc(
96 cookie: *mut c_void, length: i32, buffer: *mut *mut c_char,
97 ) -> bool {
98 if length < 0 { return true; }
99 let s = unsafe { &mut *(cookie as *mut StringBuf) };
100 s.0.reserve_exact(length as usize + 1);
101 unsafe { s.0.as_mut_vec().resize(length as usize + 1, 0) };
102 unsafe { *buffer = s.0.as_mut_ptr() as *mut c_char };
103 true
104 }
105
106 struct StringBuf(String);
107 impl StringBuf {
108 fn new() -> Self { Self(String::new()) }
109 fn finish(mut self) -> Option<String> {
110 if let Some(pos) = self.0.as_bytes().iter().position(|&b| b == 0) {
111 unsafe { self.0.as_mut_vec().truncate(pos) };
112 }
113 if self.0.is_empty() { None } else { Some(self.0) }
114 }
115 }
116
117 struct Vtable {
120 get_service: unsafe extern "C" fn(*const c_char) -> *mut AIBinder,
121 class_define: unsafe extern "C" fn(
122 *const c_char,
123 unsafe extern "C" fn(*mut c_void) -> *mut c_void,
124 unsafe extern "C" fn(*mut c_void),
125 unsafe extern "C" fn(*mut AIBinder, u32, *const AParcel, *mut AParcel) -> BinderStatus,
126 ) -> *mut AIBinder_Class,
127 associate_class: unsafe extern "C" fn(*mut AIBinder, *mut AIBinder_Class) -> bool,
128 new_binder: unsafe extern "C" fn(*const AIBinder_Class, *mut c_void) -> *mut AIBinder,
129 prepare_transaction: unsafe extern "C" fn(*mut AIBinder, *mut *mut AParcel) -> BinderStatus,
130 transact: unsafe extern "C" fn(*mut AIBinder, u32, *mut *mut AParcel, *mut *mut AParcel, u32) -> BinderStatus,
131 dec_strong: unsafe extern "C" fn(*mut AIBinder),
132 parcel_delete: unsafe extern "C" fn(*mut AParcel),
133 read_int32: unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus,
134 read_string: unsafe extern "C" fn(*const AParcel, *mut c_void, StringAllocator) -> BinderStatus,
135 write_strong_binder: unsafe extern "C" fn(*mut AParcel, *mut AIBinder) -> BinderStatus,
136 set_thread_pool_max: unsafe extern "C" fn(u32),
137 join_thread_pool: unsafe extern "C" fn(),
138 write_int32: unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus,
139 read_bool: Option<unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus>,
141 }
142
143 struct DlHandle(*mut c_void);
146 unsafe impl Send for DlHandle {}
147 impl Drop for DlHandle {
148 fn drop(&mut self) {
149 }
155 }
156
157 struct OwnedParcel { ptr: *mut AParcel, delete: unsafe extern "C" fn(*mut AParcel) }
158 impl Drop for OwnedParcel {
159 fn drop(&mut self) { if !self.ptr.is_null() { unsafe { (self.delete)(self.ptr) }; } }
160 }
161
162 struct OwnedBinder { ptr: *mut AIBinder, dec_strong: unsafe extern "C" fn(*mut AIBinder) }
163 unsafe impl Send for OwnedBinder {}
164 impl Drop for OwnedBinder {
165 fn drop(&mut self) { if !self.ptr.is_null() { unsafe { (self.dec_strong)(self.ptr) }; } }
166 }
167
168 macro_rules! dlsym_fn {
171 ($handle:expr, $name:literal, $ty:ty) => {{
172 let sym = unsafe {
173 libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char)
174 };
175 if sym.is_null() {
176 return Err(CoreError::binder(-1, concat!("dlsym:", $name)));
177 }
178 unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) }
179 }};
180 }
181
182 macro_rules! dlsym_opt {
183 ($handle:expr, $name:literal, $ty:ty) => {{
184 let sym = unsafe {
185 libc::dlsym($handle, concat!($name, "\0").as_ptr() as *const c_char)
186 };
187 if sym.is_null() { None }
188 else { Some(unsafe { std::mem::transmute::<*mut c_void, $ty>(sym) }) }
189 }};
190 }
191
192 fn load_vtable(handle: *mut c_void) -> Result<Vtable, CoreError> {
193 Ok(Vtable {
194 get_service: dlsym_fn!(handle, "AServiceManager_getService",
195 unsafe extern "C" fn(*const c_char) -> *mut AIBinder),
196 class_define: dlsym_fn!(handle, "AIBinder_Class_define",
197 unsafe extern "C" fn(
198 *const c_char,
199 unsafe extern "C" fn(*mut c_void) -> *mut c_void,
200 unsafe extern "C" fn(*mut c_void),
201 unsafe extern "C" fn(*mut AIBinder, u32, *const AParcel, *mut AParcel) -> BinderStatus,
202 ) -> *mut AIBinder_Class),
203 associate_class: dlsym_fn!(handle, "AIBinder_associateClass",
204 unsafe extern "C" fn(*mut AIBinder, *mut AIBinder_Class) -> bool),
205 new_binder: dlsym_fn!(handle, "AIBinder_new",
206 unsafe extern "C" fn(*const AIBinder_Class, *mut c_void) -> *mut AIBinder),
207 prepare_transaction: dlsym_fn!(handle, "AIBinder_prepareTransaction",
208 unsafe extern "C" fn(*mut AIBinder, *mut *mut AParcel) -> BinderStatus),
209 transact: dlsym_fn!(handle, "AIBinder_transact",
210 unsafe extern "C" fn(*mut AIBinder, u32, *mut *mut AParcel, *mut *mut AParcel, u32) -> BinderStatus),
211 dec_strong: dlsym_fn!(handle, "AIBinder_decStrong",
212 unsafe extern "C" fn(*mut AIBinder)),
213 parcel_delete: dlsym_fn!(handle, "AParcel_delete",
214 unsafe extern "C" fn(*mut AParcel)),
215 read_int32: dlsym_fn!(handle, "AParcel_readInt32",
216 unsafe extern "C" fn(*const AParcel, *mut i32) -> BinderStatus),
217 read_string: dlsym_fn!(handle, "AParcel_readString",
218 unsafe extern "C" fn(*const AParcel, *mut c_void, StringAllocator) -> BinderStatus),
219 write_strong_binder: dlsym_fn!(handle, "AParcel_writeStrongBinder",
220 unsafe extern "C" fn(*mut AParcel, *mut AIBinder) -> BinderStatus),
221 set_thread_pool_max: dlsym_fn!(handle, "ABinderProcess_setThreadPoolMaxThreadCount",
222 unsafe extern "C" fn(u32)),
223 join_thread_pool: dlsym_fn!(handle, "ABinderProcess_joinThreadPool",
224 unsafe extern "C" fn()),
225 write_int32: dlsym_fn!(handle, "AParcel_writeInt32",
226 unsafe extern "C" fn(*mut AParcel, i32) -> BinderStatus),
227 read_bool: dlsym_opt!(handle, "AParcel_readBool",
228 unsafe extern "C" fn(*const AParcel, *mut bool) -> BinderStatus),
229 })
230 }
231
232 struct ParcelReader<'a> { vt: &'a Vtable, parcel: &'a OwnedParcel }
235
236 impl<'a> ParcelReader<'a> {
237 fn read_i32(&self) -> Result<i32, CoreError> {
238 let mut v = 0i32;
239 let s = unsafe { (self.vt.read_int32)(self.parcel.ptr, &mut v) };
240 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readInt32")); }
241 Ok(v)
242 }
243 fn read_string(&self) -> Result<Option<String>, CoreError> {
244 let mut buf = StringBuf::new();
245 let s = unsafe {
246 (self.vt.read_string)(self.parcel.ptr, &mut buf as *mut StringBuf as *mut c_void, string_alloc)
247 };
248 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readString")); }
249 Ok(buf.finish())
250 }
251 fn skip_i32s(&self, n: usize) -> Result<(), CoreError> {
252 for _ in 0..n { self.read_i32()?; }
253 Ok(())
254 }
255 fn skip_int_array(&self) -> Result<(), CoreError> {
256 let count = self.read_i32()?.max(0) as usize;
257 self.skip_i32s(count)
258 }
259 fn read_first_package_from_names(&self) -> Result<Option<String>, CoreError> {
260 let count = self.read_i32()?.max(0) as usize;
261 let mut first: Option<String> = None;
262 for _ in 0..count {
263 let s = self.read_string()?;
264 if first.is_none() {
265 first = s.and_then(|c| c.split('/').next().map(str::to_owned));
266 }
267 }
268 Ok(first)
269 }
270 }
271
272 fn parse_root_task_info_body(r: &ParcelReader<'_>) -> Result<Option<String>, CoreError> {
275 let scratch = r.read_i32()?;
276 if scratch != 0 { r.skip_i32s(4)?; }
277 r.skip_int_array()?;
278 r.read_first_package_from_names()
279 }
280
281 fn parse_stack_info_body(r: &ParcelReader<'_>) -> Result<Option<String>, CoreError> {
282 r.skip_i32s(5)?;
283 r.skip_int_array()?;
284 r.read_first_package_from_names()
285 }
286
287 pub struct TxCodes {
290 pub observer_code: u32,
291 pub query_code: u32,
292 pub api_mode: u8, pub fg_code: u32,
294 }
295
296 pub fn resolve_tx_codes() -> Result<TxCodes, CoreError> {
297 let (obs, query, api, fg) = dex::resolve_tx_codes_from_dex()
298 .ok_or_else(|| CoreError::binder(-1, "tx_code_resolution:dex_parse_failed"))?;
299 Ok(TxCodes { observer_code: obs, query_code: query, api_mode: api, fg_code: fg })
300 }
301
302 pub struct ActivityManagerBinder {
305 _lib: DlHandle,
306 vt: Vtable,
307 _class: *mut AIBinder_Class,
308 service: OwnedBinder,
309 tx_code: u32,
310 legacy: bool,
311 }
312 unsafe impl Send for ActivityManagerBinder {}
313
314 impl ActivityManagerBinder {
315 fn open_inner(handle: *mut c_void) -> Result<(DlHandle, Vtable, *mut AIBinder_Class, OwnedBinder), CoreError> {
316 let lib = DlHandle(handle);
317 let vt = load_vtable(handle)?;
318
319 let am_class = unsafe {
320 (vt.class_define)(
321 AM_DESCRIPTOR.as_ptr() as *const c_char,
322 am_on_create, am_on_destroy, am_on_transact,
323 )
324 };
325 if am_class.is_null() { return Err(CoreError::binder(-1, "AIBinder_Class_define:AM")); }
326
327 let raw = unsafe { (vt.get_service)(ACTIVITY_SERVICE.as_ptr() as *const c_char) };
328 if raw.is_null() { return Err(CoreError::binder(-1, "AServiceManager_getService:activity")); }
329 unsafe { (vt.associate_class)(raw, am_class) };
330
331 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
332 Ok((lib, vt, am_class, service))
333 }
334
335 fn dlopen_libbinder() -> Result<*mut c_void, CoreError> {
336 use std::os::raw::c_char;
337 let handle = unsafe {
338 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
339 };
340 if handle.is_null() { return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so")); }
341 Ok(handle)
342 }
343
344 pub fn open() -> Result<Self, CoreError> {
347 let handle = Self::dlopen_libbinder()?;
348 let (lib, vt, class, service) = Self::open_inner(handle)?;
349 let codes = resolve_tx_codes()?;
350 let legacy = codes.api_mode == 2;
351 Ok(Self { _lib: lib, vt, _class: class, service, tx_code: codes.query_code, legacy })
352 }
353
354 pub fn open_with_observer() -> Result<(Self, i32), CoreError> {
360 let handle = Self::dlopen_libbinder()?;
361 let (lib, vt, am_class, service) = Self::open_inner(handle)?;
362 let codes = resolve_tx_codes()?;
363 let legacy = codes.api_mode == 2;
364
365 let efd = unsafe { libc::eventfd(0, libc::EFD_NONBLOCK | libc::EFD_CLOEXEC) };
367 if efd < 0 { return Err(CoreError::sys(unsafe { *libc::__errno() }, "eventfd")); }
368
369 OBS_FG_CODE.store(codes.fg_code, Ordering::Relaxed);
371 OBS_EVENTFD.store(efd, Ordering::Relaxed);
372
373 let obs_class = unsafe {
375 (vt.class_define)(
376 OBS_DESCRIPTOR.as_ptr() as *const c_char,
377 obs_on_create, obs_on_destroy, obs_on_transact,
378 )
379 };
380 if obs_class.is_null() {
381 unsafe { libc::close(efd) };
382 return Err(CoreError::binder(-1, "AIBinder_Class_define:Observer"));
383 }
384
385 let obs_binder = unsafe { (vt.new_binder)(obs_class, std::ptr::null_mut()) };
387 if obs_binder.is_null() {
388 unsafe { libc::close(efd) };
389 return Err(CoreError::binder(-1, "AIBinder_new:Observer"));
390 }
391 unsafe { (vt.associate_class)(obs_binder, obs_class) };
392
393 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
395 let s = unsafe { (vt.prepare_transaction)(service.ptr, &mut in_ptr) };
396 if s != STATUS_OK {
397 unsafe { libc::close(efd) };
398 return Err(CoreError::binder(s, "prepareTransaction:registerObserver"));
399 }
400 unsafe { (vt.write_strong_binder)(in_ptr, obs_binder) };
401 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
402 let s = unsafe {
403 (vt.transact)(service.ptr, codes.observer_code, &mut in_ptr, &mut out_ptr, 0)
404 };
405 if !out_ptr.is_null() { unsafe { (vt.parcel_delete)(out_ptr) }; }
406 if s != STATUS_OK {
407 unsafe { libc::close(efd) };
408 return Err(CoreError::binder(s, "transact:registerProcessObserver"));
409 }
410
411 unsafe { (vt.set_thread_pool_max)(0) };
413 let join_fn = vt.join_thread_pool;
414 std::thread::spawn(move || unsafe { join_fn() });
415
416 let binder = Self { _lib: lib, vt, _class: am_class, service, tx_code: codes.query_code, legacy };
417 Ok((binder, efd))
418 }
419
420 fn do_transact(&self) -> Result<OwnedParcel, CoreError> {
421 let mut in_ptr: *mut AParcel = std::ptr::null_mut();
422 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut in_ptr) };
423 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
424 let mut out_ptr: *mut AParcel = std::ptr::null_mut();
425 let s = unsafe {
426 (self.vt.transact)(self.service.ptr, self.tx_code, &mut in_ptr, &mut out_ptr, 0)
427 };
428 let out = OwnedParcel { ptr: out_ptr, delete: self.vt.parcel_delete };
429 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
430 Ok(out)
431 }
432
433 pub fn get_focused_package(&self) -> Result<Option<String>, CoreError> {
434 let out = self.do_transact()?;
435 let r = ParcelReader { vt: &self.vt, parcel: &out };
436 let ex = r.read_i32()?;
437 if ex != EX_NONE { return Err(CoreError::binder(ex, "getFocusedTask:exception")); }
438 let present = r.read_i32()?;
439 if present == 0 { return Ok(None); }
440 if self.legacy { parse_stack_info_body(&r) } else { parse_root_task_info_body(&r) }
441 }
442 }
443
444 pub struct RawBinderService {
453 _lib: DlHandle,
454 vt: Vtable,
455 service: OwnedBinder,
456 }
457 unsafe impl Send for RawBinderService {}
458
459 impl RawBinderService {
460 pub fn open(service_name: &str) -> Result<Self, CoreError> {
462 use std::ffi::CString;
463 let handle = unsafe {
464 libc::dlopen(LIBBINDER_PATH.as_ptr() as *const c_char, libc::RTLD_NOW | libc::RTLD_LOCAL)
465 };
466 if handle.is_null() {
467 return Err(CoreError::binder(-1, "dlopen:libbinder_ndk.so"));
468 }
469 let lib = DlHandle(handle);
470 let vt = load_vtable(handle)?;
471 let cs = CString::new(service_name)
472 .map_err(|_| CoreError::binder(-1, "service_name:nul_byte"))?;
473 let raw = unsafe { (vt.get_service)(cs.as_ptr()) };
474 if raw.is_null() {
475 return Err(CoreError::binder(-1, "AServiceManager_getService:null"));
476 }
477 let service = OwnedBinder { ptr: raw, dec_strong: vt.dec_strong };
478 Ok(Self { _lib: lib, vt, service })
479 }
480
481 pub fn transact_bool(&self, code: u32) -> Result<bool, CoreError> {
483 let out = self.raw_noarg(code)?;
484 let r = ParcelReader { vt: &self.vt, parcel: &out };
485 let ex = r.read_i32()?;
486 if ex != EX_NONE { return Err(CoreError::binder(ex, "transact_bool:exception")); }
487 if let Some(rb) = self.vt.read_bool {
488 let mut v = false;
489 let s = unsafe { rb(out.ptr as *const AParcel, &mut v) };
490 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_readBool")); }
491 Ok(v)
492 } else {
493 Ok(r.read_i32()? != 0)
494 }
495 }
496
497 pub fn transact_i32(&self, code: u32, arg: i32) -> Result<(), CoreError> {
499 let mut inp: *mut AParcel = std::ptr::null_mut();
500 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
501 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
502 let s = unsafe { (self.vt.write_int32)(inp, arg) };
503 if s != STATUS_OK { return Err(CoreError::binder(s, "AParcel_writeInt32")); }
504 let mut out: *mut AParcel = std::ptr::null_mut();
505 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
506 if !out.is_null() { unsafe { (self.vt.parcel_delete)(out) }; }
507 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
508 Ok(())
509 }
510
511 fn raw_noarg(&self, code: u32) -> Result<OwnedParcel, CoreError> {
512 let mut inp: *mut AParcel = std::ptr::null_mut();
513 let s = unsafe { (self.vt.prepare_transaction)(self.service.ptr, &mut inp) };
514 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_prepareTransaction")); }
515 let mut out: *mut AParcel = std::ptr::null_mut();
516 let s = unsafe { (self.vt.transact)(self.service.ptr, code, &mut inp, &mut out, 0) };
517 let out = OwnedParcel { ptr: out, delete: self.vt.parcel_delete };
518 if s != STATUS_OK { return Err(CoreError::binder(s, "AIBinder_transact")); }
519 Ok(out)
520 }
521 }
522}
523
524#[cfg(target_os = "android")]
527pub use imp::{ActivityManagerBinder, RawBinderService, TxCodes, resolve_tx_codes};
528
529#[cfg(not(target_os = "android"))]
532pub struct ActivityManagerBinder;
533
534#[cfg(not(target_os = "android"))]
535impl ActivityManagerBinder {
536 pub fn open() -> Result<Self, crate::CoreError> {
537 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
538 }
539 pub fn open_with_observer() -> Result<(Self, i32), crate::CoreError> {
540 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
541 }
542 pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
543 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
544 }
545}
546
547#[cfg(not(target_os = "android"))]
548pub struct RawBinderService;
549
550#[cfg(not(target_os = "android"))]
551impl RawBinderService {
552 pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
553 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
554 }
555 pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
556 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
557 }
558 pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
559 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
560 }
561}
562
563#[cfg(not(target_os = "android"))]
564pub struct TxCodes { pub observer_code: u32, pub query_code: u32, pub api_mode: u8, pub fg_code: u32 }
565
566#[cfg(not(target_os = "android"))]
567pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
568 Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
569}