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