cloudfox-coreshift-core 2.11.0

Low-level Linux and Android systems primitives for CoreShift (CloudFox)
Documentation
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/

//! NDK binder primitives for querying Android system services.
//!
//! Uses `dlopen` on `libbinder_ndk.so` to avoid hard-linking against a library
//! absent from older NDK toolchains or non-Android targets.
//!
//! ## Transaction code resolution
//!
//! Transaction codes are resolved fresh from `framework.jar` DEX on each
//! startup; no persistent cache.
//!
//! ## Observer mode
//!
//! `ActivityManager::open_with_observer` registers this process as an
//! `IProcessObserver` with ActivityManager. Callbacks fire when foreground
//! activities change and signal an `eventfd` that callers can poll via epoll.
//! After the eventfd fires, call `get_focused_package` to read the new value.

// ─────────────────────────────────────────────────────────────────────────────
// Android-only implementation
// ─────────────────────────────────────────────────────────────────────────────

#[cfg(target_os = "android")]
mod am;
#[cfg(target_os = "android")]
mod display;
#[cfg(target_os = "android")]
mod fps;
#[cfg(target_os = "android")]
mod handoff;
#[cfg(target_os = "android")]
mod raw;
#[cfg(target_os = "android")]
mod serve;
#[cfg(target_os = "android")]
mod sys;
#[cfg(target_os = "android")]
mod task_stack;

// ── Public re-exports ─────────────────────────────────────────────────────────

#[cfg(target_os = "android")]
pub use am::{
    ActivityManager, TxCodes, last_foreground_pid, last_uid_event, resolve_tx_codes,
};
#[cfg(target_os = "android")]
pub use display::{DisplayInfo, DisplayManager};
#[cfg(target_os = "android")]
pub use fps::FpsListener;
#[cfg(target_os = "android")]
pub use handoff::{Handoff, ProviderHandle};
#[cfg(target_os = "android")]
pub use raw::RawBinderService;
#[cfg(target_os = "android")]
pub use serve::{DeathRecipient, OnewaySender, ServeCall, ServeHandler, ServingBinder};
#[cfg(target_os = "android")]
pub use sys::{OwnedBinder, ParcelReader, ParcelWriter};
#[cfg(target_os = "android")]
pub use task_stack::TaskStackListener;

// ── Non-Android stubs ─────────────────────────────────────────────────────────

#[cfg(not(target_os = "android"))]
pub struct ActivityManager;

#[cfg(not(target_os = "android"))]
impl ActivityManager {
    pub fn open() -> Result<Self, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn open_with_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn open_with_fgproc_observer() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn get_focused_task(&self) -> Result<Option<(i32, Option<String>)>, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn get_focused_package(&self) -> Result<Option<String>, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn get_focused_task_id(&self) -> Result<Option<i32>, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
}

#[cfg(not(target_os = "android"))]
pub struct DisplayManager;

#[cfg(not(target_os = "android"))]
impl DisplayManager {
    pub fn open_with_callback() -> Result<(Self, crate::fd::Fd), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn is_interactive(&self) -> Result<bool, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn info(&self, _display_id: i32) -> Result<DisplayInfo, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
}

#[cfg(not(target_os = "android"))]
#[derive(Clone, Copy, Debug, PartialEq, Default)]
pub struct DisplayInfo {
    pub active_mode_id: i32,
    pub vsync_rate: f32,
    pub peak_refresh_rate: f32,
    pub render_frame_rate: f32,
    pub is_interactive: bool,
}

#[cfg(not(target_os = "android"))]
pub struct RawBinderService;

#[cfg(not(target_os = "android"))]
impl RawBinderService {
    pub fn open(_service_name: &str) -> Result<Self, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn transact_bool(&self, _code: u32) -> Result<bool, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn transact_i32(&self, _code: u32, _arg: i32) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
}

#[cfg(not(target_os = "android"))]
pub struct FpsListener;

#[cfg(not(target_os = "android"))]
impl FpsListener {
    pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn register(&mut self, _task_id: i32) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn unregister(&mut self) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn last_fps(&self) -> Option<f32> {
        None
    }
    pub fn task_id(&self) -> Option<i32> {
        None
    }
}

#[cfg(not(target_os = "android"))]
pub struct TaskStackListener;

#[cfg(not(target_os = "android"))]
impl TaskStackListener {
    pub fn open() -> Result<(Self, std::os::fd::OwnedFd), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn register(&self) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn unregister(&self) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
}

#[cfg(not(target_os = "android"))]
pub struct Handoff;

#[cfg(not(target_os = "android"))]
impl Handoff {
    pub fn open() -> Result<Self, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn acquire_provider(
        &self,
        _authority: &str,
        _user_id: i32,
    ) -> Result<ProviderHandle, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn send_binder(
        &self,
        _handle: &ProviderHandle,
        _authority: &str,
        _method: &str,
        _arg: &str,
        _service_binder: *mut std::os::raw::c_void,
    ) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn remove_provider(&self, _authority: &str, _user_id: i32) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn handoff(
        &self,
        _authority: &str,
        _user_id: i32,
        _method: &str,
        _arg: &str,
        _service_binder: *mut std::os::raw::c_void,
    ) -> Result<i32, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
}

#[cfg(not(target_os = "android"))]
pub struct ProviderHandle {
    pub uid: i32,
    pub no_release_needed: bool,
}

#[cfg(not(target_os = "android"))]
pub struct TxCodes {
    pub observer_code: u32,
    pub query_code: u32,
    pub api_mode: u8,
    pub fg_code: u32,
}

#[cfg(not(target_os = "android"))]
pub fn resolve_tx_codes() -> Result<TxCodes, crate::CoreError> {
    Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
}

#[cfg(not(target_os = "android"))]
pub fn last_foreground_pid() -> i32 {
    0
}

// Stub parcel cursors so handlers can be written once and type-checked on
// non-Android builds. They can never be constructed or called there; every
// method returns an unsupported-platform error.
#[cfg(not(target_os = "android"))]
pub struct ParcelReader<'a> {
    _marker: std::marker::PhantomData<&'a ()>,
}

#[cfg(not(target_os = "android"))]
impl<'a> ParcelReader<'a> {
    pub fn read_i32(&self) -> Result<i32, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn read_string(&self) -> Result<Option<String>, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn read_strong_binder(&self) -> Result<Option<OwnedBinder>, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn read_float(&self) -> Result<f32, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn read_int64(&self) -> Result<i64, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn read_bool(&self) -> Result<bool, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
}

#[cfg(not(target_os = "android"))]
pub struct ParcelWriter<'a> {
    _marker: std::marker::PhantomData<&'a ()>,
}

#[cfg(not(target_os = "android"))]
impl<'a> ParcelWriter<'a> {
    pub fn write_i32(&self, _v: i32) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn write_strong_binder(
        &self,
        _b: *mut std::os::raw::c_void,
    ) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn write_string(&self, _s: Option<&str>) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
}

#[cfg(not(target_os = "android"))]
pub struct OwnedBinder;

#[cfg(not(target_os = "android"))]
impl OwnedBinder {
    pub fn as_raw(&self) -> *mut std::os::raw::c_void {
        std::ptr::null_mut()
    }
}

#[cfg(not(target_os = "android"))]
pub struct ServeCall<'a> {
    pub code: u32,
    pub calling_uid: u32,
    pub calling_pid: i32,
    pub request: ParcelReader<'a>,
    pub reply: Option<ParcelWriter<'a>>,
}

#[cfg(not(target_os = "android"))]
pub type ServeHandler =
    Box<dyn for<'a> FnMut(ServeCall<'a>) -> Result<(), crate::CoreError> + Send>;

#[cfg(not(target_os = "android"))]
pub struct ServingBinder;

#[cfg(not(target_os = "android"))]
impl ServingBinder {
    pub fn open(_descriptor: &[u8], _handler: ServeHandler) -> Result<Self, crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn as_raw(&self) -> *mut std::os::raw::c_void {
        std::ptr::null_mut()
    }
    pub fn associate(&self, _target: &OwnedBinder) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn push_oneway(
        &self,
        _target: &OwnedBinder,
        _code: u32,
        _writes: impl FnOnce(&ParcelWriter<'_>) -> Result<(), crate::CoreError>,
    ) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn death_recipient(&self, _on_died: Box<dyn FnMut() + Send>) -> DeathRecipient {
        DeathRecipient {
            _cb: Box::new(Box::new(|| {})),
        }
    }
    pub fn oneway_sender(&self) -> OnewaySender {
        OnewaySender
    }
}

#[cfg(not(target_os = "android"))]
#[derive(Clone, Copy)]
pub struct OnewaySender;

#[cfg(not(target_os = "android"))]
impl OnewaySender {
    pub fn push_oneway(
        &self,
        _target: &OwnedBinder,
        _code: u32,
        _writes: impl FnOnce(&ParcelWriter<'_>) -> Result<(), crate::CoreError>,
    ) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
}

#[cfg(not(target_os = "android"))]
pub struct DeathRecipient {
    _cb: Box<Box<dyn FnMut() + Send>>,
}

#[cfg(not(target_os = "android"))]
impl DeathRecipient {
    pub fn link(&self, _target: &OwnedBinder) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
    pub fn unlink(&self, _target: &OwnedBinder) -> Result<(), crate::CoreError> {
        Err(crate::CoreError::binder(-1, "binder:unsupported platform"))
    }
}