Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7f47a754 authored by Priyanka Advani (xWF)'s avatar Priyanka Advani (xWF) Committed by Android (Google) Code Review
Browse files

Merge "Revert "Allow other processes to implement a UDS servicemanager"" into main

parents d62b371d 2ab691f8
Loading
Loading
Loading
Loading
+0 −26
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",
    ],
}
+0 −177
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;
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 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 }
    }
}

/// Registers the `IServiceManager` service.
pub fn register_rpc_servicemanager(provider_service: Strong<dyn IRpcProvider>) -> Result<()> {
    let rpc_servicemanager_binder = BnServiceManager::new_binder(
        RpcServiceManager::new(provider_service),
        BinderFeatures::default(),
    );

    let servicemanager_fd = 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(())
}
+3 −45
Original line number Diff line number Diff line
@@ -469,6 +469,7 @@ release_libbinder_binder_observer_config {
    },
}


soong_config_module_type {
    name: "libbinder_remove_cache_static_list_config",
    module_type: "cc_defaults",
@@ -856,7 +857,7 @@ cc_library_static {
    ],
}

// ServiceManager AIDL interface between libbinder and framework.jar
// AIDL interface between libbinder and framework.jar
filegroup {
    name: "libbinder_aidl",
    srcs: [
@@ -880,15 +881,6 @@ filegroup {
    visibility: [":__subpackages__"],
}

filegroup {
    name: "libbinder_rpc_aidl",
    srcs: [
        "aidl/android/os/IRpcProvider.aidl",
    ],
    path: "aidl",
    visibility: [":__subpackages__"],
}

aidl_interface {
    name: "packagemanager_aidl",
    unstable: true,
@@ -912,19 +904,12 @@ aidl_interface {
}

aidl_interface {
    name: "servicemanager_aidl",
    name: "libbinder_aidl_test_stub",
    unstable: true,
    local_include_dir: "aidl",
    srcs: [":libbinder_aidl"],
    vendor_available: true,
    backend: {
        cpp: {
            // libbinder exports this type itself so use that
            enabled: false,
        },
        rust: {
            enabled: true,
        },
        java: {
            enabled: false,
        },
@@ -932,33 +917,6 @@ aidl_interface {
    visibility: [
        ":__subpackages__",
        "//system/tools/aidl:__subpackages__",
        "//frameworks/native/cmds/servicemanager/rpc_servicemanager",
    ],
}

aidl_interface {
    name: "rpc_servicemanager_aidl",
    unstable: true,
    local_include_dir: "aidl",
    srcs: [":libbinder_rpc_aidl"],
    vendor_available: true,
    backend: {
        rust: {
            enabled: true,
            apex_available: [
                "com.android.virt",
                "com.android.compos",
            ],
        },
        java: {
            enabled: false,
        },
    },
    visibility: [
        ":__subpackages__",
        "//system/tools/aidl:__subpackages__",
        "//frameworks/native/cmds/servicemanager/rpc_servicemanager",
        "//packages/modules/Virtualization:__subpackages__",
    ],
}

+4 −32
Original line number Diff line number Diff line
@@ -19,9 +19,6 @@
#include <android/os/IAccessor.h>
#include <android/os/IServiceManager.h>
#include <binder/RpcSession.h>
#include <cutils/sockets.h>
#include <sys/socket.h>
#include <sys/un.h>

#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
#include <android-base/properties.h>
@@ -29,10 +26,6 @@

namespace android {

// This is similar to the kernel binder servicemanager's context 0. It's the
// known socket that we expect the Unix Domain Socket servicemanager to be listening on.
const char kUdsServiceManagerName[] = ANDROID_SOCKET_DIR "/rpc_servicemanager";

#ifdef LIBBINDER_CLIENT_CACHE
constexpr bool kUseCache = true;
#else
@@ -506,16 +499,6 @@ static bool hasOutOfProcessServiceManager() {
#endif // BINDER_WITH_KERNEL_IPC
}

static sp<AidlServiceManager> getUdsServiceManager() {
    auto session = RpcSession::make();
    session->setFileDescriptorTransportMode(RpcSession::FileDescriptorTransportMode::UNIX);
    auto status = session->setupUnixDomainClient(kUdsServiceManagerName);
    if (status == OK) {
        return interface_cast<AidlServiceManager>(session->getRootObject());
    }
    return nullptr;
}

sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager() {
    std::call_once(gUSmOnce, []() {
#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
@@ -531,22 +514,11 @@ sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager() {

        sp<AidlServiceManager> sm = nullptr;
        while (hasOutOfProcessServiceManager() && sm == nullptr) {
            // There is either a kernel binder service manager, or an RPC binder
            // service manager
            sp<ProcessState> ps = ProcessState::selfIfKernelBinderEnabled();
            if (ps) {
                // Service management over kernel binder
                sm = interface_cast<AidlServiceManager>(ps->getContextObject(nullptr));
            } else {
                // Check for service management over Unix Domain Sockets
                sm = getUdsServiceManager();
            }

            sm = interface_cast<AidlServiceManager>(
                    ProcessState::self()->getContextObject(nullptr));
            if (sm == nullptr) {
                std::string contextObjectName = ps
                        ? ps->getDriverName() + ", " + kUdsServiceManagerName
                        : kUdsServiceManagerName;
                ALOGE("Waiting 1s on context object(s) on %s.", contextObjectName.c_str());
                ALOGE("Waiting 1s on context object on %s.",
                      ProcessState::self()->getDriverName().c_str());
                sleep(1);
            }
        }
+0 −5
Original line number Diff line number Diff line
@@ -117,11 +117,6 @@ sp<ProcessState> ProcessState::selfOrNull()
    return init(nullptr, false /*requireDefault*/);
}

sp<ProcessState> ProcessState::selfIfKernelBinderEnabled() {
    if (access(kDefaultDriver, R_OK) == -1) return nullptr;
    return init(kDefaultDriver, false /*requireDefault*/);
}

[[clang::no_destroy]] static sp<ProcessState> gProcess;
[[clang::no_destroy]] static std::mutex gProcessMutex;

Loading