use std::sync::{Arc, OnceLock};
#[cfg(all(
target_os = "android",
any(
feature = "android_11",
feature = "android_12",
feature = "android_13",
feature = "android_14",
)
))]
macro_rules! impl_sm_module_body {
($($extra:tt)*) => {
use crate::*;
pub use android::os::IServiceManager::{
BnServiceManager, BpServiceManager, IServiceManager,
DUMP_FLAG_PRIORITY_ALL, DUMP_FLAG_PRIORITY_CRITICAL,
DUMP_FLAG_PRIORITY_DEFAULT, DUMP_FLAG_PRIORITY_HIGH,
DUMP_FLAG_PRIORITY_NORMAL, DUMP_FLAG_PROTO,
};
pub use android::os::IServiceCallback::{BnServiceCallback, IServiceCallback};
pub fn get_service(sm: &BpServiceManager, name: &str) -> Option<SIBinder> {
match sm.getService(name) {
Ok(result) => result,
Err(err) => {
log::error!("Failed to get service {}: {:?}", name, err);
None
}
}
}
pub fn check_service(sm: &BpServiceManager, name: &str) -> Option<SIBinder> {
match sm.checkService(name) {
Ok(result) => result,
Err(err) => {
log::error!("Failed to check service {}: {}", name, err);
None
}
}
}
pub fn list_services(sm: &BpServiceManager, dump_priority: i32) -> Vec<String> {
match sm.listServices(dump_priority) {
Ok(result) => result,
Err(err) => {
log::error!("Failed to list services: {}", err);
Vec::new()
}
}
}
pub fn add_service(
sm: &BpServiceManager,
identifier: &str,
binder: SIBinder,
) -> std::result::Result<(), Status> {
sm.addService(identifier, &binder, false, DUMP_FLAG_PRIORITY_DEFAULT)
}
pub fn register_for_notifications(
sm: &BpServiceManager,
name: &str,
callback: &crate::Strong<dyn IServiceCallback>,
) -> Result<()> {
sm.registerForNotifications(name, callback).map_err(|e| e.into())
}
pub fn unregister_for_notifications(
sm: &BpServiceManager,
name: &str,
callback: &crate::Strong<dyn IServiceCallback>,
) -> Result<()> {
sm.unregisterForNotifications(name, callback).map_err(|e| e.into())
}
pub fn is_declared(sm: &BpServiceManager, name: &str) -> bool {
match sm.isDeclared(name) {
Ok(result) => result,
Err(err) => {
log::error!("Failed to is_declared({}): {}", name, err);
false
}
}
}
pub fn get_interface<T: FromIBinder + ?Sized>(
sm: &BpServiceManager,
name: &str,
) -> Result<Strong<T>> {
match sm.getService(name) {
Ok(Some(service)) => FromIBinder::try_from(service),
Ok(None) => {
log::error!("Service {} not found", name);
Err(StatusCode::NameNotFound)
}
Err(err) => {
log::error!("Failed to get interface {}: {}", name, err);
Err(StatusCode::NameNotFound)
}
}
}
$($extra)*
};
}
#[cfg(all(
target_os = "android",
any(
feature = "android_11",
feature = "android_12",
feature = "android_13",
feature = "android_14",
)
))]
pub(crate) use impl_sm_module_body;
#[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::*;
}
#[cfg(feature = "rpc")]
pub(crate) mod accessor_16;
#[cfg(feature = "rpc")]
pub(crate) mod accessor_register;
mod servicemanager_16;
pub mod android_16 {
#[cfg(feature = "rpc")]
pub use super::accessor_16::{
__fuzz_accessor_error_decode, accessor_error_name, resolve_accessor, BnAccessor,
BpAccessor, IAccessor, IAccessorDefault, IAccessorDefaultRef,
ERROR_CONNECTION_INFO_NOT_FOUND, ERROR_FAILED_TO_CONNECT_EACCES,
ERROR_FAILED_TO_CONNECT_TO_SOCKET, ERROR_FAILED_TO_CREATE_SOCKET,
ERROR_UNSUPPORTED_SOCKET_FAMILY,
};
#[cfg(all(feature = "rpc", feature = "async"))]
pub use super::accessor_16::IAccessorAsyncService;
#[cfg(feature = "rpc")]
pub use super::accessor_register::{
add_accessor_provider, create_accessor, remove_accessor_provider,
resolve_via_process_local, AccessorAddrProvider, AccessorConnectError, AccessorProviderFn,
AccessorProviderHandle, AccessorSockAddr, LocalAccessor,
};
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()
}
}
#[cfg(all(
target_os = "android",
any(
feature = "android_11",
feature = "android_12",
feature = "android_13",
feature = "android_14",
)
))]
macro_rules! wrap_callback {
($modu:ident, $callback:expr) => {
crate::Strong::<dyn $modu::IServiceCallback>::new(Box::new(ForwardServiceCallback(
$callback.as_binder(),
)))
};
}
#[cfg(all(
target_os = "android",
any(feature = "android_12", feature = "android_13", feature = "android_14",)
))]
macro_rules! collect_debug_info {
($modu:ident, $sm:expr) => {{
let result = $modu::get_service_debug_info($sm)?;
Ok(result
.into_iter()
.map(|info| ServiceDebugInfo {
name: info.name,
debugPid: info.debugPid,
})
.collect())
}};
}
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) => collect_debug_info!(android_12, sm),
#[cfg(all(target_os = "android", feature = "android_13"))]
ServiceManager::Android13(sm) => collect_debug_info!(android_13, sm),
#[cfg(all(target_os = "android", feature = "android_14"))]
ServiceManager::Android14(sm) => collect_debug_info!(android_14, sm),
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) => android_11::register_for_notifications(
sm,
name,
&wrap_callback!(android_11, callback),
),
#[cfg(all(target_os = "android", feature = "android_12"))]
ServiceManager::Android12(sm) => android_12::register_for_notifications(
sm,
name,
&wrap_callback!(android_12, callback),
),
#[cfg(all(target_os = "android", feature = "android_13"))]
ServiceManager::Android13(sm) => android_13::register_for_notifications(
sm,
name,
&wrap_callback!(android_13, callback),
),
#[cfg(all(target_os = "android", feature = "android_14"))]
ServiceManager::Android14(sm) => android_14::register_for_notifications(
sm,
name,
&wrap_callback!(android_14, 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) => android_11::unregister_for_notifications(
sm,
name,
&wrap_callback!(android_11, callback),
),
#[cfg(all(target_os = "android", feature = "android_12"))]
ServiceManager::Android12(sm) => android_12::unregister_for_notifications(
sm,
name,
&wrap_callback!(android_12, callback),
),
#[cfg(all(target_os = "android", feature = "android_13"))]
ServiceManager::Android13(sm) => android_13::unregister_for_notifications(
sm,
name,
&wrap_callback!(android_13, callback),
),
#[cfg(all(target_os = "android", feature = "android_14"))]
ServiceManager::Android14(sm) => android_14::unregister_for_notifications(
sm,
name,
&wrap_callback!(android_14, 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()
}