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::{ActivityManager, TxCodes, last_foreground_pid, resolve_tx_codes};
47#[cfg(target_os = "android")]
48pub use display::{DisplayInfo, DisplayManager};
49#[cfg(target_os = "android")]
50pub use fps::FpsListener;
51#[cfg(target_os = "android")]
52pub use handoff::{Handoff, ProviderHandle};
53#[cfg(target_os = "android")]
54pub use raw::RawBinderService;
55#[cfg(target_os = "android")]
56pub use serve::{DeathRecipient, OnewaySender, ServeCall, ServeHandler, ServingBinder};
57#[cfg(target_os = "android")]
58pub use sys::{OwnedBinder, ParcelReader, ParcelWriter};
59#[cfg(target_os = "android")]
60pub use task_stack::TaskStackListener;
61
62// ── Non-Android stubs ─────────────────────────────────────────────────────────
63
64#[cfg(not(target_os = "android"))]
65pub struct ActivityManager;
66
67#[cfg(not(target_os = "android"))]
68impl ActivityManager {
69    pub fn open() -> Result<Self, crate::CoreError> {
70        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
71    }
72    pub fn open_with_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
73        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
74    }
75    pub fn open_with_fgproc_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
76        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
77    }
78    pub fn get_focused_task(&self) -> Result<Option<(i32, Option<String>)>, crate::CoreError> {
79        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
80    }
81    pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
82        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
83    }
84    pub fn get_focused_task_id(&self) -> Result<Option<i32>, crate::CoreError> {
85        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
86    }
87}
88
89#[cfg(not(target_os = "android"))]
90pub struct DisplayManager;
91
92#[cfg(not(target_os = "android"))]
93impl DisplayManager {
94    pub fn open_with_callback() -> Result<(Self, crate::fd::Fd), crate::CoreError> {
95        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
96    }
97    pub fn is_interactive(&self) -> Result<bool, crate::CoreError> {
98        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
99    }
100    pub fn info(&self, _display_id: i32) -> Result<DisplayInfo, crate::CoreError> {
101        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
102    }
103}
104
105#[cfg(not(target_os = "android"))]
106#[derive(Clone, Copy, Debug, PartialEq, Default)]
107pub struct DisplayInfo {
108    pub active_mode_id: i32,
109    pub vsync_rate: f32,
110    pub peak_refresh_rate: f32,
111    pub render_frame_rate: f32,
112    pub is_interactive: bool,
113}
114
115#[cfg(not(target_os = "android"))]
116pub struct RawBinderService;
117
118#[cfg(not(target_os = "android"))]
119impl RawBinderService {
120    pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
121        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
122    }
123    pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
124        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
125    }
126    pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
127        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
128    }
129}
130
131#[cfg(not(target_os = "android"))]
132pub struct FpsListener;
133
134#[cfg(not(target_os = "android"))]
135impl FpsListener {
136    pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
137        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
138    }
139    pub fn register(&mut self, _task_id: i32) -> Result<(), crate::CoreError> {
140        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
141    }
142    pub fn unregister(&mut self) -> Result<(), crate::CoreError> {
143        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
144    }
145    pub fn last_fps(&self) -> Option<f32> {
146        None
147    }
148    pub fn task_id(&self) -> Option<i32> {
149        None
150    }
151}
152
153#[cfg(not(target_os = "android"))]
154pub struct TaskStackListener;
155
156#[cfg(not(target_os = "android"))]
157impl TaskStackListener {
158    pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
159        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
160    }
161    pub fn register(&self) -> Result<(), crate::CoreError> {
162        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
163    }
164    pub fn unregister(&self) -> Result<(), crate::CoreError> {
165        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
166    }
167}
168
169#[cfg(not(target_os = "android"))]
170pub struct Handoff;
171
172#[cfg(not(target_os = "android"))]
173impl Handoff {
174    pub fn open() -> Result<Self, crate::CoreError> {
175        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
176    }
177    pub fn acquire_provider(
178        &self,
179        _authority: &str,
180        _user_id: i32,
181    ) -> Result<ProviderHandle, crate::CoreError> {
182        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
183    }
184    pub fn send_binder(
185        &self,
186        _handle: &ProviderHandle,
187        _authority: &str,
188        _method: &str,
189        _arg: &str,
190        _service_binder: *mut std::os::raw::c_void,
191    ) -> Result<(), crate::CoreError> {
192        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
193    }
194    pub fn remove_provider(&self, _authority: &str, _user_id: i32) -> Result<(), crate::CoreError> {
195        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
196    }
197    pub fn handoff(
198        &self,
199        _authority: &str,
200        _user_id: i32,
201        _method: &str,
202        _arg: &str,
203        _service_binder: *mut std::os::raw::c_void,
204    ) -> Result<i32, crate::CoreError> {
205        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
206    }
207}
208
209#[cfg(not(target_os = "android"))]
210pub struct ProviderHandle {
211    pub uid: i32,
212    pub no_release_needed: bool,
213}
214
215#[cfg(not(target_os = "android"))]
216pub struct TxCodes {
217    pub observer_code: u32,
218    pub query_code: u32,
219    pub api_mode: u8,
220    pub fg_code: u32,
221}
222
223#[cfg(not(target_os = "android"))]
224pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
225    Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
226}
227
228#[cfg(not(target_os = "android"))]
229pub fn last_foreground_pid() -> i32 {
230    0
231}
232
233// Stub parcel cursors so handlers can be written once and type-checked on
234// non-Android builds. They can never be constructed or called there; every
235// method returns an unsupported-platform error.
236#[cfg(not(target_os = "android"))]
237pub struct ParcelReader<'a> {
238    _marker: std::marker::PhantomData<&'a ()>,
239}
240
241#[cfg(not(target_os = "android"))]
242impl<'a> ParcelReader<'a> {
243    pub fn read_i32(&self) -> Result<i32, crate::CoreError> {
244        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
245    }
246    pub fn read_string(&self) -> Result<Option<String>, crate::CoreError> {
247        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
248    }
249    pub fn read_strong_binder(&self) -> Result<Option<OwnedBinder>, crate::CoreError> {
250        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
251    }
252    pub fn read_float(&self) -> Result<f32, crate::CoreError> {
253        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
254    }
255    pub fn read_int64(&self) -> Result<i64, crate::CoreError> {
256        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
257    }
258    pub fn read_bool(&self) -> Result<bool, crate::CoreError> {
259        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
260    }
261}
262
263#[cfg(not(target_os = "android"))]
264pub struct ParcelWriter<'a> {
265    _marker: std::marker::PhantomData<&'a ()>,
266}
267
268#[cfg(not(target_os = "android"))]
269impl<'a> ParcelWriter<'a> {
270    pub fn write_i32(&self, _v: i32) -> Result<(), crate::CoreError> {
271        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
272    }
273    pub fn write_strong_binder(
274        &self,
275        _b: *mut std::os::raw::c_void,
276    ) -> Result<(), crate::CoreError> {
277        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
278    }
279    pub fn write_string(&self, _s: Option<&str>) -> Result<(), crate::CoreError> {
280        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
281    }
282}
283
284#[cfg(not(target_os = "android"))]
285pub struct OwnedBinder;
286
287#[cfg(not(target_os = "android"))]
288impl OwnedBinder {
289    pub fn as_raw(&self) -> *mut std::os::raw::c_void {
290        std::ptr::null_mut()
291    }
292}
293
294#[cfg(not(target_os = "android"))]
295pub struct ServeCall<'a> {
296    pub code: u32,
297    pub calling_uid: u32,
298    pub calling_pid: i32,
299    pub request: ParcelReader<'a>,
300    pub reply: Option<ParcelWriter<'a>>,
301}
302
303#[cfg(not(target_os = "android"))]
304pub type ServeHandler =
305    Box<dyn for<'a> FnMut(ServeCall<'a>) -> Result<(), crate::CoreError> + Send>;
306
307#[cfg(not(target_os = "android"))]
308pub struct ServingBinder;
309
310#[cfg(not(target_os = "android"))]
311impl ServingBinder {
312    pub fn open(_descriptor: &[u8], _handler: ServeHandler) -> Result<Self, crate::CoreError> {
313        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
314    }
315    pub fn as_raw(&self) -> *mut std::os::raw::c_void {
316        std::ptr::null_mut()
317    }
318    pub fn push_oneway(
319        &self,
320        _target: &OwnedBinder,
321        _code: u32,
322        _writes: impl FnOnce(&ParcelWriter<'_>) -> Result<(), crate::CoreError>,
323    ) -> Result<(), crate::CoreError> {
324        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
325    }
326    pub fn death_recipient(&self, _on_died: Box<dyn FnMut() + Send>) -> DeathRecipient {
327        DeathRecipient {
328            _cb: Box::new(Box::new(|| {})),
329        }
330    }
331    pub fn oneway_sender(&self) -> OnewaySender {
332        OnewaySender
333    }
334}
335
336#[cfg(not(target_os = "android"))]
337#[derive(Clone, Copy)]
338pub struct OnewaySender;
339
340#[cfg(not(target_os = "android"))]
341impl OnewaySender {
342    pub fn push_oneway(
343        &self,
344        _target: &OwnedBinder,
345        _code: u32,
346        _writes: impl FnOnce(&ParcelWriter<'_>) -> Result<(), crate::CoreError>,
347    ) -> Result<(), crate::CoreError> {
348        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
349    }
350}
351
352#[cfg(not(target_os = "android"))]
353pub struct DeathRecipient {
354    _cb: Box<Box<dyn FnMut() + Send>>,
355}
356
357#[cfg(not(target_os = "android"))]
358impl DeathRecipient {
359    pub fn link(&self, _target: &OwnedBinder) -> Result<(), crate::CoreError> {
360        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
361    }
362    pub fn unlink(&self, _target: &OwnedBinder) -> Result<(), crate::CoreError> {
363        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
364    }
365}