pub use imp::ThermalMonitor;
#[cfg(target_os = "android")]
mod imp {
use libc::{RTLD_NOW, dlclose, dlopen, dlsym};
use std::ffi::c_void;
use std::os::raw::c_int;
type AcquireFn = unsafe extern "C" fn() -> *mut c_void;
type ReleaseFn = unsafe extern "C" fn(*mut c_void);
type HeadroomFn = unsafe extern "C" fn(*mut c_void, c_int) -> f32;
pub struct ThermalMonitor {
lib: *mut c_void,
manager: *mut c_void,
release: ReleaseFn,
headroom: HeadroomFn,
}
impl ThermalMonitor {
pub fn new() -> Option<Self> {
unsafe {
let lib = dlopen(c"libandroid.so".as_ptr().cast(), RTLD_NOW);
if lib.is_null() {
return None;
}
let acquire = dlsym(lib, c"AThermal_acquireManager".as_ptr().cast());
let release = dlsym(lib, c"AThermal_releaseManager".as_ptr().cast());
let headroom = dlsym(lib, c"AThermal_getThermalHeadroom".as_ptr().cast());
if acquire.is_null() || release.is_null() || headroom.is_null() {
dlclose(lib);
return None;
}
let acquire: AcquireFn = std::mem::transmute(acquire);
let release: ReleaseFn = std::mem::transmute(release);
let headroom: HeadroomFn = std::mem::transmute(headroom);
let manager = acquire();
if manager.is_null() {
dlclose(lib);
return None;
}
Some(Self {
lib,
manager,
release,
headroom,
})
}
}
pub fn headroom(&self, forecast_secs: i32) -> Option<f32> {
let h = unsafe { (self.headroom)(self.manager, forecast_secs as c_int) };
if h.is_nan() { None } else { Some(h) }
}
}
impl Drop for ThermalMonitor {
fn drop(&mut self) {
unsafe {
(self.release)(self.manager);
dlclose(self.lib);
}
}
}
}
#[cfg(not(target_os = "android"))]
mod imp {
pub struct ThermalMonitor;
impl ThermalMonitor {
pub fn new() -> Option<Self> {
None
}
pub fn headroom(&self, _forecast_secs: i32) -> Option<f32> {
None
}
}
}