Loading cmds/dumpstate/dumpstate.cpp +22 −0 Original line number Diff line number Diff line Loading @@ -1752,6 +1752,7 @@ Dumpstate::RunStatus Dumpstate::dumpstate() { DumpFile("ZONEINFO", "/proc/zoneinfo"); DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo"); DumpFile("BUDDYINFO", "/proc/buddyinfo"); DumpFile("MGLRU", "/sys/kernel/mm/lru_gen/enabled"); DumpExternalFragmentationInfo(); DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state"); Loading Loading @@ -3459,6 +3460,7 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, } MaybeTakeEarlyScreenshot(); MaybeSavePlaceholderScreenshot(); MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace)); onUiIntensiveBugreportDumpsFinished(calling_uid); MaybeCheckUserConsent(calling_uid, calling_package); Loading Loading @@ -3558,6 +3560,26 @@ void Dumpstate::MaybeTakeEarlyScreenshot() { TakeScreenshot(); } void Dumpstate::MaybeSavePlaceholderScreenshot() { if (options_->do_screenshot) { // No need to save a placeholder screenshot if a real one will be taken. return; } if (!options_->is_consent_deferred) { return; } // When consent is deferred, a screenshot used to be taken even when one // was not requested. The screenshot is not taken any more but a placeholder // is saved for backwards compatibility. std::string path = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png"); if (android::os::CopyFileToFile(DEFAULT_SCREENSHOT_PATH, path)) { MYLOGD("Saved fallback screenshot on %s\n", path.c_str()); } else { MYLOGE("Failed to save fallback screenshot on %s\n", path.c_str()); }; } std::future<std::string> Dumpstate::MaybeSnapshotSystemTraceAsync() { // When capturing traces via bugreport handler (BH), this function will be invoked twice: // 1) When BH invokes IDumpstate::PreDumpUiData() Loading cmds/dumpstate/dumpstate.h +1 −0 Original line number Diff line number Diff line Loading @@ -573,6 +573,7 @@ class Dumpstate { RunStatus dumpstate(); void MaybeTakeEarlyScreenshot(); void MaybeSavePlaceholderScreenshot(); std::future<std::string> MaybeSnapshotSystemTraceAsync(); void MaybeWaitForSnapshotSystemTrace(std::future<std::string> task); void MaybeSnapshotUiTraces(); Loading cmds/dumpstate/tests/dumpstate_test.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -1082,6 +1082,38 @@ TEST_F(ZippedBugReportStreamTest, DISABLED_StreamLimitedOnlyReport) { VerifyEntry(handle_, bugreport_txt_name, &entry); } TEST_F(ZippedBugReportStreamTest, ScreenShotFileCreated) { std::string out_path = kTestDataPath + "ScreenShotCapturedOut.zip"; android::base::unique_fd out_fd; CreateFd(out_path, &out_fd); ds_.options_->limited_only = true; ds_.options_->stream_to_socket = true; ds_.options_->do_screenshot = false; ds_.options_->is_consent_deferred = true; RedirectOutputToFd(out_fd); GenerateBugreport(); std::string screenshot = ds_.GetPath(ds_.CalledByApi() ? "-png.tmp" : ".png"); EXPECT_TRUE(std::filesystem::exists(screenshot)) << screenshot << " was not created."; } TEST_F(ZippedBugReportStreamTest, ScreenShotFileIsNotCreated) { std::string out_path = kTestDataPath + "ScreenShotCapturedOut.zip"; android::base::unique_fd out_fd; CreateFd(out_path, &out_fd); ds_.options_->limited_only = true; ds_.options_->stream_to_socket = true; ds_.options_->do_screenshot = false; ds_.options_->is_consent_deferred = false; RedirectOutputToFd(out_fd); GenerateBugreport(); std::string screenshot = ds_.GetPath(ds_.CalledByApi() ? "-png.tmp" : ".png"); EXPECT_FALSE(std::filesystem::exists(screenshot)) << screenshot << " was created."; } class ProgressTest : public DumpstateBaseTest { public: Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") { Loading cmds/servicemanager/rpc_servicemanager/Android.bp 0 → 100644 +26 −0 Original line number Diff line number Diff line package { // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_native_license" // to get the below license kinds: // SPDX-license-identifier-Apache-2.0 default_applicable_licenses: ["frameworks_native_license"], } rust_library { name: "librpc_servicemanager", crate_name: "rpc_servicemanager", srcs: ["rpc_servicemanager.rs"], rustlibs: [ "android.system.virtualmachineservice-rust", "libanyhow", "libbinder_rs", "liblibc", "liblog_rust", "librpcbinder_rs", "librustutils", "libvsock", "rpc_servicemanager_aidl-rust", "servicemanager_aidl-rust", ], } cmds/servicemanager/rpc_servicemanager/rpc_servicemanager.rs 0 → 100644 +195 −0 Original line number Diff line number Diff line // Copyright 2025, The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! Implementation of the AIDL interface `IServiceManager`. use anyhow::Result; use binder::{Accessor, BinderFeatures, Interface, Strong}; use libc::{sa_family_t, sockaddr_vm, AF_VSOCK}; use log::{error, info}; use rpc_servicemanager_aidl::aidl::android::os::IRpcProvider::{ IRpcProvider, ServiceConnectionInfo::ServiceConnectionInfo, }; use rpcbinder::{FileDescriptorTransportMode, RpcServer}; use rustutils::sockets::{android_get_control_socket, SocketError}; use servicemanager_aidl::aidl::android::os::IServiceManager::{ BnServiceManager, CallerContext::CallerContext, IServiceManager, }; use servicemanager_aidl::aidl::android::os::{ ConnectionInfo::ConnectionInfo, IClientCallback::IClientCallback, IServiceCallback::IServiceCallback, Service::Service, ServiceDebugInfo::ServiceDebugInfo, }; use std::os::unix::io::OwnedFd; use vsock::VMADDR_CID_HOST; // Name of the socket that libbinder is expecting IServiceManager to be served from const RPC_SERVICEMANAGER_UDS_NAME: &str = "rpc_servicemanager"; /// Implementation of `IServiceManager`. pub struct RpcServiceManager { provider_service: Strong<dyn IRpcProvider>, } impl IServiceManager for RpcServiceManager { fn getService(&self, _name: &str) -> binder::Result<Option<binder::SpIBinder>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn getService2(&self, name: &str) -> binder::Result<Service> { let provider_service = self.provider_service.clone(); let get_connection_info = move |inst: &str| { let connection_info = provider_service.getServiceConnectionInfo(inst).unwrap(); match connection_info { ServiceConnectionInfo::Vsock(info) => { let addr = sockaddr_vm { svm_family: AF_VSOCK as sa_family_t, svm_reserved1: 0, svm_port: info.port as u32, svm_cid: VMADDR_CID_HOST, svm_zero: [0u8; 4], }; Some(binder::ConnectionInfo::Vsock(addr)) } #[allow(unreachable_patterns)] _ => { error!("Unexpected ServiceConnectionInfo type!"); None } } }; let accessor = Accessor::new(name, get_connection_info); Ok(Service::Accessor(accessor.as_binder())) } fn checkService(&self, _name: &str) -> binder::Result<Option<binder::SpIBinder>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn checkService2(&self, _name: &str) -> binder::Result<Service> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn addService( &self, _name: &str, _service: &binder::SpIBinder, _allow_isolated: bool, _dump_priority: i32, ) -> binder::Result<()> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn listServices(&self, _dump_priority: i32) -> binder::Result<Vec<String>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn registerForNotifications( &self, _name: &str, _callback: &binder::Strong<dyn IServiceCallback>, ) -> binder::Result<()> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn unregisterForNotifications( &self, _name: &str, _callback: &binder::Strong<dyn IServiceCallback>, ) -> binder::Result<()> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn isDeclared(&self, _name: &str) -> binder::Result<bool> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn getDeclaredInstances(&self, _iface: &str) -> binder::Result<Vec<String>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn updatableViaApex(&self, _name: &str) -> binder::Result<Option<String>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn getUpdatableNames(&self, _apex_name: &str) -> binder::Result<Vec<String>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn getConnectionInfo(&self, _name: &str) -> binder::Result<Option<ConnectionInfo>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn registerClientCallback( &self, _name: &str, _service: &binder::SpIBinder, _callback: &binder::Strong<dyn IClientCallback>, ) -> binder::Result<()> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn tryUnregisterService( &self, _name: &str, _service: &binder::SpIBinder, ) -> binder::Result<()> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn getServiceDebugInfo(&self) -> binder::Result<Vec<ServiceDebugInfo>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn checkServiceAccess(&self, _: &CallerContext, _: &str, _: &str) -> binder::Result<bool> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } } impl Interface for RpcServiceManager {} impl RpcServiceManager { /// Creates a new `RpcServiceManager` instance from the `IServiceManager` reference. fn new(provider_service: Strong<dyn IRpcProvider>) -> RpcServiceManager { Self { provider_service } } } /// Get the Unix Domain Socket file descriptor for RPC_SERVICEMANAGER_UDS_NAME /// /// A client might need to do this in order to get an FD with the FD_CLOEXEC flag set before /// it forks any other processes. pub fn get_default_rpc_servicemanager_uds_fd() -> Result<OwnedFd, SocketError> { android_get_control_socket(RPC_SERVICEMANAGER_UDS_NAME) } /// Registers the `IServiceManager` service. /// /// servicemanager_fd is an optional argument to provide the Unix Domain Socked file /// descriptor to use for the server. If None is provided, then it will use the default /// of RPC_SERVICEMANAGER_UDS_NAME to get the FD. pub fn register_rpc_servicemanager( provider_service: Strong<dyn IRpcProvider>, servicemanager_fd: Option<OwnedFd>, ) -> Result<()> { let rpc_servicemanager_binder = BnServiceManager::new_binder( RpcServiceManager::new(provider_service), BinderFeatures::default(), ); let servicemanager_fd = match servicemanager_fd { Some(fd) => fd, None => android_get_control_socket(RPC_SERVICEMANAGER_UDS_NAME)?, }; let server = RpcServer::new_bound_socket(rpc_servicemanager_binder.as_binder(), servicemanager_fd)?; // Required for the FD being passed through libbinder's accessor binder server.set_supported_file_descriptor_transport_modes(&[FileDescriptorTransportMode::Unix]); info!("The RPC server '{}' is running.", RPC_SERVICEMANAGER_UDS_NAME); if let Err(e) = rustutils::system_properties::write("servicemanager.ready", "true") { error!("failed to set ro.servicemanager.ready {:?}", e); } // Move server reference into a background thread and run it forever. std::thread::spawn(move || { server.join(); }); Ok(()) } Loading
cmds/dumpstate/dumpstate.cpp +22 −0 Original line number Diff line number Diff line Loading @@ -1752,6 +1752,7 @@ Dumpstate::RunStatus Dumpstate::dumpstate() { DumpFile("ZONEINFO", "/proc/zoneinfo"); DumpFile("PAGETYPEINFO", "/proc/pagetypeinfo"); DumpFile("BUDDYINFO", "/proc/buddyinfo"); DumpFile("MGLRU", "/sys/kernel/mm/lru_gen/enabled"); DumpExternalFragmentationInfo(); DumpFile("KERNEL CPUFREQ", "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state"); Loading Loading @@ -3459,6 +3460,7 @@ Dumpstate::RunStatus Dumpstate::RunInternal(int32_t calling_uid, } MaybeTakeEarlyScreenshot(); MaybeSavePlaceholderScreenshot(); MaybeWaitForSnapshotSystemTrace(std::move(snapshot_system_trace)); onUiIntensiveBugreportDumpsFinished(calling_uid); MaybeCheckUserConsent(calling_uid, calling_package); Loading Loading @@ -3558,6 +3560,26 @@ void Dumpstate::MaybeTakeEarlyScreenshot() { TakeScreenshot(); } void Dumpstate::MaybeSavePlaceholderScreenshot() { if (options_->do_screenshot) { // No need to save a placeholder screenshot if a real one will be taken. return; } if (!options_->is_consent_deferred) { return; } // When consent is deferred, a screenshot used to be taken even when one // was not requested. The screenshot is not taken any more but a placeholder // is saved for backwards compatibility. std::string path = ds.GetPath(ds.CalledByApi() ? "-png.tmp" : ".png"); if (android::os::CopyFileToFile(DEFAULT_SCREENSHOT_PATH, path)) { MYLOGD("Saved fallback screenshot on %s\n", path.c_str()); } else { MYLOGE("Failed to save fallback screenshot on %s\n", path.c_str()); }; } std::future<std::string> Dumpstate::MaybeSnapshotSystemTraceAsync() { // When capturing traces via bugreport handler (BH), this function will be invoked twice: // 1) When BH invokes IDumpstate::PreDumpUiData() Loading
cmds/dumpstate/dumpstate.h +1 −0 Original line number Diff line number Diff line Loading @@ -573,6 +573,7 @@ class Dumpstate { RunStatus dumpstate(); void MaybeTakeEarlyScreenshot(); void MaybeSavePlaceholderScreenshot(); std::future<std::string> MaybeSnapshotSystemTraceAsync(); void MaybeWaitForSnapshotSystemTrace(std::future<std::string> task); void MaybeSnapshotUiTraces(); Loading
cmds/dumpstate/tests/dumpstate_test.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -1082,6 +1082,38 @@ TEST_F(ZippedBugReportStreamTest, DISABLED_StreamLimitedOnlyReport) { VerifyEntry(handle_, bugreport_txt_name, &entry); } TEST_F(ZippedBugReportStreamTest, ScreenShotFileCreated) { std::string out_path = kTestDataPath + "ScreenShotCapturedOut.zip"; android::base::unique_fd out_fd; CreateFd(out_path, &out_fd); ds_.options_->limited_only = true; ds_.options_->stream_to_socket = true; ds_.options_->do_screenshot = false; ds_.options_->is_consent_deferred = true; RedirectOutputToFd(out_fd); GenerateBugreport(); std::string screenshot = ds_.GetPath(ds_.CalledByApi() ? "-png.tmp" : ".png"); EXPECT_TRUE(std::filesystem::exists(screenshot)) << screenshot << " was not created."; } TEST_F(ZippedBugReportStreamTest, ScreenShotFileIsNotCreated) { std::string out_path = kTestDataPath + "ScreenShotCapturedOut.zip"; android::base::unique_fd out_fd; CreateFd(out_path, &out_fd); ds_.options_->limited_only = true; ds_.options_->stream_to_socket = true; ds_.options_->do_screenshot = false; ds_.options_->is_consent_deferred = false; RedirectOutputToFd(out_fd); GenerateBugreport(); std::string screenshot = ds_.GetPath(ds_.CalledByApi() ? "-png.tmp" : ".png"); EXPECT_FALSE(std::filesystem::exists(screenshot)) << screenshot << " was created."; } class ProgressTest : public DumpstateBaseTest { public: Progress GetInstance(int32_t max, double growth_factor, const std::string& path = "") { Loading
cmds/servicemanager/rpc_servicemanager/Android.bp 0 → 100644 +26 −0 Original line number Diff line number Diff line package { // See: http://go/android-license-faq // A large-scale-change added 'default_applicable_licenses' to import // all of the 'license_kinds' from "frameworks_native_license" // to get the below license kinds: // SPDX-license-identifier-Apache-2.0 default_applicable_licenses: ["frameworks_native_license"], } rust_library { name: "librpc_servicemanager", crate_name: "rpc_servicemanager", srcs: ["rpc_servicemanager.rs"], rustlibs: [ "android.system.virtualmachineservice-rust", "libanyhow", "libbinder_rs", "liblibc", "liblog_rust", "librpcbinder_rs", "librustutils", "libvsock", "rpc_servicemanager_aidl-rust", "servicemanager_aidl-rust", ], }
cmds/servicemanager/rpc_servicemanager/rpc_servicemanager.rs 0 → 100644 +195 −0 Original line number Diff line number Diff line // Copyright 2025, The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! Implementation of the AIDL interface `IServiceManager`. use anyhow::Result; use binder::{Accessor, BinderFeatures, Interface, Strong}; use libc::{sa_family_t, sockaddr_vm, AF_VSOCK}; use log::{error, info}; use rpc_servicemanager_aidl::aidl::android::os::IRpcProvider::{ IRpcProvider, ServiceConnectionInfo::ServiceConnectionInfo, }; use rpcbinder::{FileDescriptorTransportMode, RpcServer}; use rustutils::sockets::{android_get_control_socket, SocketError}; use servicemanager_aidl::aidl::android::os::IServiceManager::{ BnServiceManager, CallerContext::CallerContext, IServiceManager, }; use servicemanager_aidl::aidl::android::os::{ ConnectionInfo::ConnectionInfo, IClientCallback::IClientCallback, IServiceCallback::IServiceCallback, Service::Service, ServiceDebugInfo::ServiceDebugInfo, }; use std::os::unix::io::OwnedFd; use vsock::VMADDR_CID_HOST; // Name of the socket that libbinder is expecting IServiceManager to be served from const RPC_SERVICEMANAGER_UDS_NAME: &str = "rpc_servicemanager"; /// Implementation of `IServiceManager`. pub struct RpcServiceManager { provider_service: Strong<dyn IRpcProvider>, } impl IServiceManager for RpcServiceManager { fn getService(&self, _name: &str) -> binder::Result<Option<binder::SpIBinder>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn getService2(&self, name: &str) -> binder::Result<Service> { let provider_service = self.provider_service.clone(); let get_connection_info = move |inst: &str| { let connection_info = provider_service.getServiceConnectionInfo(inst).unwrap(); match connection_info { ServiceConnectionInfo::Vsock(info) => { let addr = sockaddr_vm { svm_family: AF_VSOCK as sa_family_t, svm_reserved1: 0, svm_port: info.port as u32, svm_cid: VMADDR_CID_HOST, svm_zero: [0u8; 4], }; Some(binder::ConnectionInfo::Vsock(addr)) } #[allow(unreachable_patterns)] _ => { error!("Unexpected ServiceConnectionInfo type!"); None } } }; let accessor = Accessor::new(name, get_connection_info); Ok(Service::Accessor(accessor.as_binder())) } fn checkService(&self, _name: &str) -> binder::Result<Option<binder::SpIBinder>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn checkService2(&self, _name: &str) -> binder::Result<Service> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn addService( &self, _name: &str, _service: &binder::SpIBinder, _allow_isolated: bool, _dump_priority: i32, ) -> binder::Result<()> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn listServices(&self, _dump_priority: i32) -> binder::Result<Vec<String>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn registerForNotifications( &self, _name: &str, _callback: &binder::Strong<dyn IServiceCallback>, ) -> binder::Result<()> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn unregisterForNotifications( &self, _name: &str, _callback: &binder::Strong<dyn IServiceCallback>, ) -> binder::Result<()> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn isDeclared(&self, _name: &str) -> binder::Result<bool> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn getDeclaredInstances(&self, _iface: &str) -> binder::Result<Vec<String>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn updatableViaApex(&self, _name: &str) -> binder::Result<Option<String>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn getUpdatableNames(&self, _apex_name: &str) -> binder::Result<Vec<String>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn getConnectionInfo(&self, _name: &str) -> binder::Result<Option<ConnectionInfo>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn registerClientCallback( &self, _name: &str, _service: &binder::SpIBinder, _callback: &binder::Strong<dyn IClientCallback>, ) -> binder::Result<()> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn tryUnregisterService( &self, _name: &str, _service: &binder::SpIBinder, ) -> binder::Result<()> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn getServiceDebugInfo(&self) -> binder::Result<Vec<ServiceDebugInfo>> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } fn checkServiceAccess(&self, _: &CallerContext, _: &str, _: &str) -> binder::Result<bool> { Err(binder::ExceptionCode::UNSUPPORTED_OPERATION.into()) } } impl Interface for RpcServiceManager {} impl RpcServiceManager { /// Creates a new `RpcServiceManager` instance from the `IServiceManager` reference. fn new(provider_service: Strong<dyn IRpcProvider>) -> RpcServiceManager { Self { provider_service } } } /// Get the Unix Domain Socket file descriptor for RPC_SERVICEMANAGER_UDS_NAME /// /// A client might need to do this in order to get an FD with the FD_CLOEXEC flag set before /// it forks any other processes. pub fn get_default_rpc_servicemanager_uds_fd() -> Result<OwnedFd, SocketError> { android_get_control_socket(RPC_SERVICEMANAGER_UDS_NAME) } /// Registers the `IServiceManager` service. /// /// servicemanager_fd is an optional argument to provide the Unix Domain Socked file /// descriptor to use for the server. If None is provided, then it will use the default /// of RPC_SERVICEMANAGER_UDS_NAME to get the FD. pub fn register_rpc_servicemanager( provider_service: Strong<dyn IRpcProvider>, servicemanager_fd: Option<OwnedFd>, ) -> Result<()> { let rpc_servicemanager_binder = BnServiceManager::new_binder( RpcServiceManager::new(provider_service), BinderFeatures::default(), ); let servicemanager_fd = match servicemanager_fd { Some(fd) => fd, None => android_get_control_socket(RPC_SERVICEMANAGER_UDS_NAME)?, }; let server = RpcServer::new_bound_socket(rpc_servicemanager_binder.as_binder(), servicemanager_fd)?; // Required for the FD being passed through libbinder's accessor binder server.set_supported_file_descriptor_transport_modes(&[FileDescriptorTransportMode::Unix]); info!("The RPC server '{}' is running.", RPC_SERVICEMANAGER_UDS_NAME); if let Err(e) = rustutils::system_properties::write("servicemanager.ready", "true") { error!("failed to set ro.servicemanager.ready {:?}", e); } // Move server reference into a background thread and run it forever. std::thread::spawn(move || { server.join(); }); Ok(()) }