use std::sync::{Arc, OnceLock};
#[cfg(all(target_os = "android", feature = "android_10"))]
mod servicemanager_10;
#[cfg(all(target_os = "android", feature = "android_10"))]
pub mod android_10 {
pub use super::servicemanager_10::*;
}
#[cfg(all(target_os = "android", feature = "android_11"))]
mod servicemanager_11;
#[cfg(all(target_os = "android", feature = "android_11"))]
pub mod android_11 {
pub use super::servicemanager_11::*;
}
#[cfg(all(target_os = "android", feature = "android_12"))]
mod servicemanager_12;
#[cfg(all(target_os = "android", feature = "android_12"))]
pub mod android_12 {
pub use super::servicemanager_12::*;
}
#[cfg(all(target_os = "android", feature = "android_13"))]
mod servicemanager_13;
#[cfg(all(target_os = "android", feature = "android_13"))]
pub mod android_13 {
pub use super::servicemanager_13::*;
}
#[cfg(all(target_os = "android", feature = "android_14"))]
mod servicemanager_14;
#[cfg(all(target_os = "android", feature = "android_14"))]
pub mod android_14 {
pub use super::servicemanager_14::*;
}
mod servicemanager_16;
pub mod android_16 {
pub use super::servicemanager_16::*;
}
use crate::*;
pub use android_16::{
BnServiceCallback, IServiceCallback, ServiceDebugInfo, DUMP_FLAG_PRIORITY_ALL,
DUMP_FLAG_PRIORITY_CRITICAL, DUMP_FLAG_PRIORITY_DEFAULT, DUMP_FLAG_PRIORITY_HIGH,
DUMP_FLAG_PRIORITY_NORMAL,
};
#[cfg(target_os = "android")]
pub mod sdk_versions {
pub const ANDROID_16: u32 = 36;
pub const ANDROID_15: u32 = 35;
pub const ANDROID_14: u32 = 34;
pub const ANDROID_13: u32 = 33;
pub const ANDROID_12L: u32 = 32;
pub const ANDROID_12: u32 = 31;
pub const ANDROID_11: u32 = 30;
pub const ANDROID_10: u32 = 29;
pub const MIN_SUPPORTED: u32 = ANDROID_10;
pub const MAX_SUPPORTED: u32 = ANDROID_16;
}
pub enum ServiceManager {
#[cfg(all(target_os = "android", feature = "android_10"))]
Android10(android_10::BpServiceManager),
#[cfg(all(target_os = "android", feature = "android_11"))]
Android11(android_11::BpServiceManager),
#[cfg(all(target_os = "android", feature = "android_12"))]
Android12(android_12::BpServiceManager),
#[cfg(all(target_os = "android", feature = "android_13"))]
Android13(android_13::BpServiceManager),
#[cfg(all(target_os = "android", feature = "android_14"))]
Android14(android_14::BpServiceManager),
Android16(android_16::BpServiceManager),
}
pub fn default() -> Result<Arc<ServiceManager>> {
static GLOBAL_SM: OnceLock<Arc<ServiceManager>> = OnceLock::new();
if let Some(sm) = GLOBAL_SM.get() {
return Ok(sm.clone());
}
let process = ProcessState::as_self();
let context = process.context_object()?;
#[cfg(target_os = "android")]
let sdk_version = crate::get_android_sdk_version();
#[cfg(target_os = "android")]
let service_manager = {
macro_rules! create_service_manager {
($variant:ident, $module:ident) => {
ServiceManager::$variant(
$module::BpServiceManager::from_binder(context).ok_or(StatusCode::BadType)?,
)
};
}
match sdk_version {
sdk_versions::ANDROID_16 => create_service_manager!(Android16, android_16),
#[cfg(feature = "android_14")]
sdk_versions::ANDROID_14 | sdk_versions::ANDROID_15 => {
create_service_manager!(Android14, android_14)
}
#[cfg(feature = "android_13")]
sdk_versions::ANDROID_13 => create_service_manager!(Android13, android_13),
#[cfg(feature = "android_12")]
sdk_versions::ANDROID_12 | sdk_versions::ANDROID_12L => {
create_service_manager!(Android12, android_12)
}
#[cfg(feature = "android_11")]
sdk_versions::ANDROID_11 => create_service_manager!(Android11, android_11),
#[cfg(feature = "android_10")]
sdk_versions::ANDROID_10 => create_service_manager!(Android10, android_10),
_ => return Err(StatusCode::InvalidOperation),
}
};
#[cfg(not(target_os = "android"))]
let service_manager = ServiceManager::Android16(
android_16::BpServiceManager::from_binder(context).ok_or(StatusCode::BadType)?,
);
Ok(GLOBAL_SM.get_or_init(|| Arc::new(service_manager)).clone())
}
#[cfg(all(
target_os = "android",
any(
feature = "android_11",
feature = "android_12",
feature = "android_13",
feature = "android_14"
)
))]
struct ForwardServiceCallback(crate::SIBinder);
#[cfg(all(
target_os = "android",
any(
feature = "android_11",
feature = "android_12",
feature = "android_13",
feature = "android_14"
)
))]
impl crate::Interface for ForwardServiceCallback {
fn as_binder(&self) -> crate::SIBinder {
self.0.clone()
}
}
macro_rules! forward_service_callback_impl {
($modu:ident, $feat:literal) => {
#[cfg(all(target_os = "android", feature = $feat))]
impl $modu::IServiceCallback for ForwardServiceCallback {
fn r#onRegistration(
&self,
_name: &str,
_binder: &crate::SIBinder,
) -> crate::status::Result<()> {
Err(crate::StatusCode::UnknownTransaction.into())
}
}
};
}
forward_service_callback_impl!(android_11, "android_11");
forward_service_callback_impl!(android_12, "android_12");
forward_service_callback_impl!(android_13, "android_13");
forward_service_callback_impl!(android_14, "android_14");
impl ServiceManager {
pub fn get_service(&self, name: &str) -> Option<SIBinder> {
match self {
#[cfg(all(target_os = "android", feature = "android_10"))]
ServiceManager::Android10(sm) => android_10::get_service(sm, name),
#[cfg(all(target_os = "android", feature = "android_11"))]
ServiceManager::Android11(sm) => android_11::get_service(sm, name),
#[cfg(all(target_os = "android", feature = "android_12"))]
ServiceManager::Android12(sm) => android_12::get_service(sm, name),
#[cfg(all(target_os = "android", feature = "android_13"))]
ServiceManager::Android13(sm) => android_13::get_service(sm, name),
#[cfg(all(target_os = "android", feature = "android_14"))]
ServiceManager::Android14(sm) => android_14::get_service(sm, name),
ServiceManager::Android16(sm) => {
android_16::get_service(sm, name).and_then(|s| s.service)
}
}
}
pub fn get_interface<T: FromIBinder + ?Sized>(&self, name: &str) -> Result<Strong<T>> {
match self {
#[cfg(all(target_os = "android", feature = "android_10"))]
ServiceManager::Android10(sm) => android_10::get_interface(sm, name),
#[cfg(all(target_os = "android", feature = "android_11"))]
ServiceManager::Android11(sm) => android_11::get_interface(sm, name),
#[cfg(all(target_os = "android", feature = "android_12"))]
ServiceManager::Android12(sm) => android_12::get_interface(sm, name),
#[cfg(all(target_os = "android", feature = "android_13"))]
ServiceManager::Android13(sm) => android_13::get_interface(sm, name),
#[cfg(all(target_os = "android", feature = "android_14"))]
ServiceManager::Android14(sm) => android_14::get_interface(sm, name),
ServiceManager::Android16(sm) => android_16::get_interface(sm, name),
}
}
pub fn check_service(&self, name: &str) -> Option<SIBinder> {
match self {
#[cfg(all(target_os = "android", feature = "android_10"))]
ServiceManager::Android10(sm) => android_10::check_service(sm, name),
#[cfg(all(target_os = "android", feature = "android_11"))]
ServiceManager::Android11(sm) => android_11::check_service(sm, name),
#[cfg(all(target_os = "android", feature = "android_12"))]
ServiceManager::Android12(sm) => android_12::check_service(sm, name),
#[cfg(all(target_os = "android", feature = "android_13"))]
ServiceManager::Android13(sm) => android_13::check_service(sm, name),
#[cfg(all(target_os = "android", feature = "android_14"))]
ServiceManager::Android14(sm) => android_14::check_service(sm, name),
ServiceManager::Android16(sm) => {
android_16::check_service(sm, name).and_then(|s| s.service)
}
}
}
pub fn is_declared(&self, name: &str) -> bool {
match self {
#[cfg(all(target_os = "android", feature = "android_10"))]
ServiceManager::Android10(_) => {
log::error!("is_declared: not supported on Android 10");
false
}
#[cfg(all(target_os = "android", feature = "android_11"))]
ServiceManager::Android11(sm) => android_11::is_declared(sm, name),
#[cfg(all(target_os = "android", feature = "android_12"))]
ServiceManager::Android12(sm) => android_12::is_declared(sm, name),
#[cfg(all(target_os = "android", feature = "android_13"))]
ServiceManager::Android13(sm) => android_13::is_declared(sm, name),
#[cfg(all(target_os = "android", feature = "android_14"))]
ServiceManager::Android14(sm) => android_14::is_declared(sm, name),
ServiceManager::Android16(sm) => android_16::is_declared(sm, name),
}
}
pub fn list_services(&self, dump_priority: i32) -> Vec<String> {
match self {
#[cfg(all(target_os = "android", feature = "android_10"))]
ServiceManager::Android10(sm) => android_10::list_services(sm, dump_priority),
#[cfg(all(target_os = "android", feature = "android_11"))]
ServiceManager::Android11(sm) => android_11::list_services(sm, dump_priority),
#[cfg(all(target_os = "android", feature = "android_12"))]
ServiceManager::Android12(sm) => android_12::list_services(sm, dump_priority),
#[cfg(all(target_os = "android", feature = "android_13"))]
ServiceManager::Android13(sm) => android_13::list_services(sm, dump_priority),
#[cfg(all(target_os = "android", feature = "android_14"))]
ServiceManager::Android14(sm) => android_14::list_services(sm, dump_priority),
ServiceManager::Android16(sm) => android_16::list_services(sm, dump_priority),
}
}
pub fn add_service(
&self,
identifier: &str,
binder: SIBinder,
) -> std::result::Result<(), Status> {
match self {
#[cfg(all(target_os = "android", feature = "android_10"))]
ServiceManager::Android10(sm) => android_10::add_service(sm, identifier, binder),
#[cfg(all(target_os = "android", feature = "android_11"))]
ServiceManager::Android11(sm) => android_11::add_service(sm, identifier, binder),
#[cfg(all(target_os = "android", feature = "android_12"))]
ServiceManager::Android12(sm) => android_12::add_service(sm, identifier, binder),
#[cfg(all(target_os = "android", feature = "android_13"))]
ServiceManager::Android13(sm) => android_13::add_service(sm, identifier, binder),
#[cfg(all(target_os = "android", feature = "android_14"))]
ServiceManager::Android14(sm) => android_14::add_service(sm, identifier, binder),
ServiceManager::Android16(sm) => android_16::add_service(sm, identifier, binder),
}
}
pub fn get_service_debug_info(&self) -> Result<Vec<ServiceDebugInfo>> {
match self {
#[cfg(all(target_os = "android", feature = "android_10"))]
ServiceManager::Android10(_) => {
log::error!(
"get_service_debug_info: Unsupported Android SDK version: {}",
crate::get_android_sdk_version()
);
Err(StatusCode::UnknownTransaction)
}
#[cfg(all(target_os = "android", feature = "android_11"))]
ServiceManager::Android11(_) => {
log::error!(
"get_service_debug_info: Unsupported Android SDK version: {}",
crate::get_android_sdk_version()
);
Err(StatusCode::UnknownTransaction)
}
#[cfg(all(target_os = "android", feature = "android_12"))]
ServiceManager::Android12(sm) => {
let result = android_12::get_service_debug_info(sm)?;
Ok(result
.into_iter()
.map(|info| ServiceDebugInfo {
name: info.name,
debugPid: info.debugPid,
})
.collect())
}
#[cfg(all(target_os = "android", feature = "android_13"))]
ServiceManager::Android13(sm) => {
let result = android_13::get_service_debug_info(sm)?;
Ok(result
.into_iter()
.map(|info| ServiceDebugInfo {
name: info.name,
debugPid: info.debugPid,
})
.collect())
}
#[cfg(all(target_os = "android", feature = "android_14"))]
ServiceManager::Android14(sm) => {
let result = android_14::get_service_debug_info(sm)?;
Ok(result
.into_iter()
.map(|info| ServiceDebugInfo {
name: info.name,
debugPid: info.debugPid,
})
.collect())
}
ServiceManager::Android16(sm) => android_16::get_service_debug_info(sm),
}
}
pub fn register_for_notifications(
&self,
name: &str,
callback: &crate::Strong<dyn IServiceCallback>,
) -> Result<()> {
match self {
#[cfg(all(target_os = "android", feature = "android_10"))]
ServiceManager::Android10(_) => {
log::error!("register_for_notifications: not supported on Android 10");
Err(StatusCode::UnknownTransaction)
}
#[cfg(all(target_os = "android", feature = "android_11"))]
ServiceManager::Android11(sm) => {
let callback: crate::Strong<dyn android_11::IServiceCallback> =
crate::Strong::new(Box::new(ForwardServiceCallback(callback.as_binder())));
android_11::register_for_notifications(sm, name, &callback)
}
#[cfg(all(target_os = "android", feature = "android_12"))]
ServiceManager::Android12(sm) => {
let callback: crate::Strong<dyn android_12::IServiceCallback> =
crate::Strong::new(Box::new(ForwardServiceCallback(callback.as_binder())));
android_12::register_for_notifications(sm, name, &callback)
}
#[cfg(all(target_os = "android", feature = "android_13"))]
ServiceManager::Android13(sm) => {
let callback: crate::Strong<dyn android_13::IServiceCallback> =
crate::Strong::new(Box::new(ForwardServiceCallback(callback.as_binder())));
android_13::register_for_notifications(sm, name, &callback)
}
#[cfg(all(target_os = "android", feature = "android_14"))]
ServiceManager::Android14(sm) => {
let callback: crate::Strong<dyn android_14::IServiceCallback> =
crate::Strong::new(Box::new(ForwardServiceCallback(callback.as_binder())));
android_14::register_for_notifications(sm, name, &callback)
}
ServiceManager::Android16(sm) => {
android_16::register_for_notifications(sm, name, callback)
}
}
}
pub fn unregister_for_notifications(
&self,
name: &str,
callback: &crate::Strong<dyn IServiceCallback>,
) -> Result<()> {
match self {
#[cfg(all(target_os = "android", feature = "android_10"))]
ServiceManager::Android10(_) => {
log::error!("unregister_for_notifications: not supported on Android 10");
Err(StatusCode::UnknownTransaction)
}
#[cfg(all(target_os = "android", feature = "android_11"))]
ServiceManager::Android11(sm) => {
let callback: crate::Strong<dyn android_11::IServiceCallback> =
crate::Strong::new(Box::new(ForwardServiceCallback(callback.as_binder())));
android_11::unregister_for_notifications(sm, name, &callback)
}
#[cfg(all(target_os = "android", feature = "android_12"))]
ServiceManager::Android12(sm) => {
let callback: crate::Strong<dyn android_12::IServiceCallback> =
crate::Strong::new(Box::new(ForwardServiceCallback(callback.as_binder())));
android_12::unregister_for_notifications(sm, name, &callback)
}
#[cfg(all(target_os = "android", feature = "android_13"))]
ServiceManager::Android13(sm) => {
let callback: crate::Strong<dyn android_13::IServiceCallback> =
crate::Strong::new(Box::new(ForwardServiceCallback(callback.as_binder())));
android_13::unregister_for_notifications(sm, name, &callback)
}
#[cfg(all(target_os = "android", feature = "android_14"))]
ServiceManager::Android14(sm) => {
let callback: crate::Strong<dyn android_14::IServiceCallback> =
crate::Strong::new(Box::new(ForwardServiceCallback(callback.as_binder())));
android_14::unregister_for_notifications(sm, name, &callback)
}
ServiceManager::Android16(sm) => {
android_16::unregister_for_notifications(sm, name, callback)
}
}
}
}
#[inline]
pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
default()?.get_interface(name)
}
#[inline]
pub fn list_services(dump_priority: i32) -> Vec<String> {
default()
.map(|sm| sm.list_services(dump_priority))
.unwrap_or_default()
}
#[inline]
pub fn register_for_notifications(
name: &str,
callback: &crate::Strong<dyn IServiceCallback>,
) -> Result<()> {
default()?.register_for_notifications(name, callback)
}
#[inline]
pub fn unregister_for_notifications(
name: &str,
callback: &crate::Strong<dyn IServiceCallback>,
) -> Result<()> {
default()?.unregister_for_notifications(name, callback)
}
#[inline]
pub fn add_service(identifier: &str, binder: SIBinder) -> std::result::Result<(), Status> {
default()?.add_service(identifier, binder)
}
#[inline]
pub fn get_service(name: &str) -> Option<SIBinder> {
default().ok()?.get_service(name)
}
#[inline]
pub fn check_service(name: &str) -> Option<SIBinder> {
default().ok()?.check_service(name)
}
#[inline]
pub fn is_declared(name: &str) -> bool {
default().map(|sm| sm.is_declared(name)).unwrap_or(false)
}
#[inline]
pub fn get_service_debug_info() -> Result<Vec<ServiceDebugInfo>> {
default()?.get_service_debug_info()
}