Skip to main content

coreshift_core/binder/
mod.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/
4
5//! NDK binder primitives for querying Android system services.
6//!
7//! Uses `dlopen` on `libbinder_ndk.so` to avoid hard-linking against a library
8//! absent from older NDK toolchains or non-Android targets.
9//!
10//! ## Transaction code resolution
11//!
12//! Transaction codes are resolved fresh from `framework.jar` DEX on each
13//! startup; no persistent cache.
14//!
15//! ## Observer mode
16//!
17//! `ActivityManager::open_with_observer` registers this process as an
18//! `IProcessObserver` with ActivityManager. Callbacks fire when foreground
19//! activities change and signal an `eventfd` that callers can poll via epoll.
20//! After the eventfd fires, call `get_focused_package` to read the new value.
21
22// ─────────────────────────────────────────────────────────────────────────────
23// Android-only implementation
24// ─────────────────────────────────────────────────────────────────────────────
25
26#[cfg(target_os = "android")]
27mod am;
28#[cfg(target_os = "android")]
29mod display;
30#[cfg(target_os = "android")]
31mod fps;
32#[cfg(target_os = "android")]
33mod handoff;
34#[cfg(target_os = "android")]
35mod raw;
36#[cfg(target_os = "android")]
37mod serve;
38#[cfg(target_os = "android")]
39mod sys;
40#[cfg(target_os = "android")]
41mod task_stack;
42
43// ── Public re-exports ─────────────────────────────────────────────────────────
44
45#[cfg(target_os = "android")]
46pub use am::{
47    ActivityManager, TxCodes, last_foreground_pid, last_uid_event, resolve_tx_codes,
48};
49#[cfg(target_os = "android")]
50pub use display::{DisplayInfo, DisplayManager};
51#[cfg(target_os = "android")]
52pub use fps::FpsListener;
53#[cfg(target_os = "android")]
54pub use handoff::{Handoff, ProviderHandle};
55#[cfg(target_os = "android")]
56pub use raw::RawBinderService;
57#[cfg(target_os = "android")]
58pub use serve::{DeathRecipient, OnewaySender, ServeCall, ServeHandler, ServingBinder};
59#[cfg(target_os = "android")]
60pub use sys::{OwnedBinder, ParcelReader, ParcelWriter};
61#[cfg(target_os = "android")]
62pub use task_stack::TaskStackListener;
63
64// ── Non-Android stubs ─────────────────────────────────────────────────────────
65
66#[cfg(not(target_os = "android"))]
67pub struct ActivityManager;
68
69#[cfg(not(target_os = "android"))]
70impl ActivityManager {
71    pub fn open() -> Result<Self, crate::CoreError> {
72        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
73    }
74    pub fn open_with_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
75        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
76    }
77    pub fn open_with_fgproc_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
78        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
79    }
80    pub fn get_focused_task(&self) -> Result<Option<(i32, Option<String>)>, crate::CoreError> {
81        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
82    }
83    pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
84        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
85    }
86    pub fn get_focused_task_id(&self) -> Result<Option<i32>, crate::CoreError> {
87        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
88    }
89}
90
91#[cfg(not(target_os = "android"))]
92pub struct DisplayManager;
93
94#[cfg(not(target_os = "android"))]
95impl DisplayManager {
96    pub fn open_with_callback() -> Result<(Self, crate::fd::Fd), crate::CoreError> {
97        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
98    }
99    pub fn is_interactive(&self) -> Result<bool, crate::CoreError> {
100        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
101    }
102    pub fn info(&self, _display_id: i32) -> Result<DisplayInfo, crate::CoreError> {
103        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
104    }
105}
106
107#[cfg(not(target_os = "android"))]
108#[derive(Clone, Copy, Debug, PartialEq, Default)]
109pub struct DisplayInfo {
110    pub active_mode_id: i32,
111    pub vsync_rate: f32,
112    pub peak_refresh_rate: f32,
113    pub render_frame_rate: f32,
114    pub is_interactive: bool,
115}
116
117#[cfg(not(target_os = "android"))]
118pub struct RawBinderService;
119
120#[cfg(not(target_os = "android"))]
121impl RawBinderService {
122    pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
123        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
124    }
125    pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
126        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
127    }
128    pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
129        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
130    }
131}
132
133#[cfg(not(target_os = "android"))]
134pub struct FpsListener;
135
136#[cfg(not(target_os = "android"))]
137impl FpsListener {
138    pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
139        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
140    }
141    pub fn register(&mut self, _task_id: i32) -> Result<(), crate::CoreError> {
142        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
143    }
144    pub fn unregister(&mut self) -> Result<(), crate::CoreError> {
145        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
146    }
147    pub fn last_fps(&self) -> Option<f32> {
148        None
149    }
150    pub fn task_id(&self) -> Option<i32> {
151        None
152    }
153}
154
155#[cfg(not(target_os = "android"))]
156pub struct TaskStackListener;
157
158#[cfg(not(target_os = "android"))]
159impl TaskStackListener {
160    pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
161        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
162    }
163    pub fn register(&self) -> Result<(), crate::CoreError> {
164        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
165    }
166    pub fn unregister(&self) -> Result<(), crate::CoreError> {
167        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
168    }
169}
170
171#[cfg(not(target_os = "android"))]
172pub struct Handoff;
173
174#[cfg(not(target_os = "android"))]
175impl Handoff {
176    pub fn open() -> Result<Self, crate::CoreError> {
177        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
178    }
179    pub fn acquire_provider(
180        &self,
181        _authority: &str,
182        _user_id: i32,
183    ) -> Result<ProviderHandle, crate::CoreError> {
184        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
185    }
186    pub fn send_binder(
187        &self,
188        _handle: &ProviderHandle,
189        _authority: &str,
190        _method: &str,
191        _arg: &str,
192        _service_binder: *mut std::os::raw::c_void,
193    ) -> Result<(), crate::CoreError> {
194        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
195    }
196    pub fn remove_provider(&self, _authority: &str, _user_id: i32) -> Result<(), crate::CoreError> {
197        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
198    }
199    pub fn handoff(
200        &self,
201        _authority: &str,
202        _user_id: i32,
203        _method: &str,
204        _arg: &str,
205        _service_binder: *mut std::os::raw::c_void,
206    ) -> Result<i32, crate::CoreError> {
207        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
208    }
209}
210
211#[cfg(not(target_os = "android"))]
212pub struct ProviderHandle {
213    pub uid: i32,
214    pub no_release_needed: bool,
215}
216
217#[cfg(not(target_os = "android"))]
218pub struct TxCodes {
219    pub observer_code: u32,
220    pub query_code: u32,
221    pub api_mode: u8,
222    pub fg_code: u32,
223}
224
225#[cfg(not(target_os = "android"))]
226pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
227    Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
228}
229
230#[cfg(not(target_os = "android"))]
231pub fn last_foreground_pid() -> i32 {
232    0
233}
234
235// Stub parcel cursors so handlers can be written once and type-checked on
236// non-Android builds. They can never be constructed or called there; every
237// method returns an unsupported-platform error.
238#[cfg(not(target_os = "android"))]
239pub struct ParcelReader<'a> {
240    _marker: std::marker::PhantomData<&'a ()>,
241}
242
243#[cfg(not(target_os = "android"))]
244impl<'a> ParcelReader<'a> {
245    pub fn read_i32(&self) -> Result<i32, crate::CoreError> {
246        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
247    }
248    pub fn read_string(&self) -> Result<Option<String>, crate::CoreError> {
249        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
250    }
251    pub fn read_strong_binder(&self) -> Result<Option<OwnedBinder>, crate::CoreError> {
252        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
253    }
254    pub fn read_float(&self) -> Result<f32, crate::CoreError> {
255        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
256    }
257    pub fn read_int64(&self) -> Result<i64, crate::CoreError> {
258        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
259    }
260    pub fn read_bool(&self) -> Result<bool, crate::CoreError> {
261        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
262    }
263}
264
265#[cfg(not(target_os = "android"))]
266pub struct ParcelWriter<'a> {
267    _marker: std::marker::PhantomData<&'a ()>,
268}
269
270#[cfg(not(target_os = "android"))]
271impl<'a> ParcelWriter<'a> {
272    pub fn write_i32(&self, _v: i32) -> Result<(), crate::CoreError> {
273        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
274    }
275    pub fn write_strong_binder(
276        &self,
277        _b: *mut std::os::raw::c_void,
278    ) -> Result<(), crate::CoreError> {
279        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
280    }
281    pub fn write_string(&self, _s: Option<&str>) -> Result<(), crate::CoreError> {
282        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
283    }
284}
285
286#[cfg(not(target_os = "android"))]
287pub struct OwnedBinder;
288
289#[cfg(not(target_os = "android"))]
290impl OwnedBinder {
291    pub fn as_raw(&self) -> *mut std::os::raw::c_void {
292        std::ptr::null_mut()
293    }
294}
295
296#[cfg(not(target_os = "android"))]
297pub struct ServeCall<'a> {
298    pub code: u32,
299    pub calling_uid: u32,
300    pub calling_pid: i32,
301    pub request: ParcelReader<'a>,
302    pub reply: Option<ParcelWriter<'a>>,
303}
304
305#[cfg(not(target_os = "android"))]
306pub type ServeHandler =
307    Box<dyn for<'a> FnMut(ServeCall<'a>) -> Result<(), crate::CoreError> + Send>;
308
309#[cfg(not(target_os = "android"))]
310pub struct ServingBinder;
311
312#[cfg(not(target_os = "android"))]
313impl ServingBinder {
314    pub fn open(_descriptor: &[u8], _handler: ServeHandler) -> Result<Self, crate::CoreError> {
315        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
316    }
317    pub fn as_raw(&self) -> *mut std::os::raw::c_void {
318        std::ptr::null_mut()
319    }
320    pub fn associate(&self, _target: &OwnedBinder) -> Result<(), crate::CoreError> {
321        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
322    }
323    pub fn push_oneway(
324        &self,
325        _target: &OwnedBinder,
326        _code: u32,
327        _writes: impl FnOnce(&ParcelWriter<'_>) -> Result<(), crate::CoreError>,
328    ) -> Result<(), crate::CoreError> {
329        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
330    }
331    pub fn death_recipient(&self, _on_died: Box<dyn FnMut() + Send>) -> DeathRecipient {
332        DeathRecipient {
333            _cb: Box::new(Box::new(|| {})),
334        }
335    }
336    pub fn oneway_sender(&self) -> OnewaySender {
337        OnewaySender
338    }
339}
340
341#[cfg(not(target_os = "android"))]
342#[derive(Clone, Copy)]
343pub struct OnewaySender;
344
345#[cfg(not(target_os = "android"))]
346impl OnewaySender {
347    pub fn push_oneway(
348        &self,
349        _target: &OwnedBinder,
350        _code: u32,
351        _writes: impl FnOnce(&ParcelWriter<'_>) -> Result<(), crate::CoreError>,
352    ) -> Result<(), crate::CoreError> {
353        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
354    }
355}
356
357#[cfg(not(target_os = "android"))]
358pub struct DeathRecipient {
359    _cb: Box<Box<dyn FnMut() + Send>>,
360}
361
362#[cfg(not(target_os = "android"))]
363impl DeathRecipient {
364    pub fn link(&self, _target: &OwnedBinder) -> Result<(), crate::CoreError> {
365        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
366    }
367    pub fn unlink(&self, _target: &OwnedBinder) -> Result<(), crate::CoreError> {
368        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
369    }
370}