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

Commit 03cb1fd2 authored by Devin Moore's avatar Devin Moore Committed by Gerrit Code Review
Browse files

Merge changes from topic "no_sm_proc" into main

* changes:
  Change callback handling from Arc to Box
  Add listServices/isDeclared/getDeclaredInstances for Accessors
  Enable ServiceManager APIs without servicemanager process
parents c9e5f470 4449d4e5
Loading
Loading
Loading
Loading
+121 −21
Original line number Original line Diff line number Diff line
@@ -15,6 +15,7 @@
 */
 */
#include "BackendUnifiedServiceManager.h"
#include "BackendUnifiedServiceManager.h"


#include <android-base/strings.h>
#include <android/os/IAccessor.h>
#include <android/os/IAccessor.h>
#include <android/os/IServiceManager.h>
#include <android/os/IServiceManager.h>
#include <binder/RpcSession.h>
#include <binder/RpcSession.h>
@@ -47,6 +48,9 @@ using AidlServiceManager = android::os::IServiceManager;
using android::os::IAccessor;
using android::os::IAccessor;
using binder::Status;
using binder::Status;


static const char* kUnsupportedOpNoServiceManager =
        "Unsupported operation without a kernel binder servicemanager process";

static const char* kStaticCachableList[] = {
static const char* kStaticCachableList[] = {
        // go/keep-sorted start
        // go/keep-sorted start
        "accessibility",
        "accessibility",
@@ -220,7 +224,10 @@ Status BackendUnifiedServiceManager::getService2(const ::std::string& name, os::
        return Status::ok();
        return Status::ok();
    }
    }
    os::Service service;
    os::Service service;
    Status status = mTheRealServiceManager->getService2(name, &service);
    Status status = Status::ok();
    if (mTheRealServiceManager) {
        status = mTheRealServiceManager->getService2(name, &service);
    }


    if (status.isOk()) {
    if (status.isOk()) {
        status = toBinderService(name, service, _out);
        status = toBinderService(name, service, _out);
@@ -237,7 +244,10 @@ Status BackendUnifiedServiceManager::checkService(const ::std::string& name, os:
        return Status::ok();
        return Status::ok();
    }
    }


    Status status = mTheRealServiceManager->checkService(name, &service);
    Status status = Status::ok();
    if (mTheRealServiceManager) {
        status = mTheRealServiceManager->checkService(name, &service);
    }
    if (status.isOk()) {
    if (status.isOk()) {
        status = toBinderService(name, service, _out);
        status = toBinderService(name, service, _out);
        if (status.isOk()) {
        if (status.isOk()) {
@@ -315,7 +325,9 @@ Status BackendUnifiedServiceManager::toBinderService(const ::std::string& name,
Status BackendUnifiedServiceManager::addService(const ::std::string& name,
Status BackendUnifiedServiceManager::addService(const ::std::string& name,
                                                const sp<IBinder>& service, bool allowIsolated,
                                                const sp<IBinder>& service, bool allowIsolated,
                                                int32_t dumpPriority) {
                                                int32_t dumpPriority) {
    Status status = mTheRealServiceManager->addService(name, service, allowIsolated, dumpPriority);
    if (mTheRealServiceManager) {
        Status status =
                mTheRealServiceManager->addService(name, service, allowIsolated, dumpPriority);
        // mEnableAddServiceCache is true by default.
        // mEnableAddServiceCache is true by default.
        if (kUseCacheInAddService && mEnableAddServiceCache && status.isOk()) {
        if (kUseCacheInAddService && mEnableAddServiceCache && status.isOk()) {
            return updateCache(name, service,
            return updateCache(name, service,
@@ -323,58 +335,146 @@ Status BackendUnifiedServiceManager::addService(const ::std::string& name,
        }
        }
        return status;
        return status;
    }
    }
    return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
                                     kUnsupportedOpNoServiceManager);
}
Status BackendUnifiedServiceManager::listServices(int32_t dumpPriority,
Status BackendUnifiedServiceManager::listServices(int32_t dumpPriority,
                                                  ::std::vector<::std::string>* _aidl_return) {
                                                  ::std::vector<::std::string>* _aidl_return) {
    return mTheRealServiceManager->listServices(dumpPriority, _aidl_return);
    Status status = Status::ok();
    if (mTheRealServiceManager) {
        status = mTheRealServiceManager->listServices(dumpPriority, _aidl_return);
    }
    if (!status.isOk()) return status;

    appendInjectedAccessorServices(_aidl_return);

    return status;
}
}
Status BackendUnifiedServiceManager::registerForNotifications(
Status BackendUnifiedServiceManager::registerForNotifications(
        const ::std::string& name, const sp<os::IServiceCallback>& callback) {
        const ::std::string& name, const sp<os::IServiceCallback>& callback) {
    if (mTheRealServiceManager) {
        return mTheRealServiceManager->registerForNotifications(name, callback);
        return mTheRealServiceManager->registerForNotifications(name, callback);
    }
    }
    return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
                                     kUnsupportedOpNoServiceManager);
}
Status BackendUnifiedServiceManager::unregisterForNotifications(
Status BackendUnifiedServiceManager::unregisterForNotifications(
        const ::std::string& name, const sp<os::IServiceCallback>& callback) {
        const ::std::string& name, const sp<os::IServiceCallback>& callback) {
    if (mTheRealServiceManager) {
        return mTheRealServiceManager->unregisterForNotifications(name, callback);
        return mTheRealServiceManager->unregisterForNotifications(name, callback);
    }
    }
    return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
                                     kUnsupportedOpNoServiceManager);
}
Status BackendUnifiedServiceManager::isDeclared(const ::std::string& name, bool* _aidl_return) {
Status BackendUnifiedServiceManager::isDeclared(const ::std::string& name, bool* _aidl_return) {
    return mTheRealServiceManager->isDeclared(name, _aidl_return);
    Status status = Status::ok();
    if (mTheRealServiceManager) {
        status = mTheRealServiceManager->isDeclared(name, _aidl_return);
    }
    if (!status.isOk()) return status;

    if (!*_aidl_return) {
        forEachInjectedAccessorService([&](const std::string& instance) {
            if (name == instance) {
                *_aidl_return = true;
            }
        });
    }

    return status;
}
}
Status BackendUnifiedServiceManager::getDeclaredInstances(
Status BackendUnifiedServiceManager::getDeclaredInstances(
        const ::std::string& iface, ::std::vector<::std::string>* _aidl_return) {
        const ::std::string& iface, ::std::vector<::std::string>* _aidl_return) {
    return mTheRealServiceManager->getDeclaredInstances(iface, _aidl_return);
    Status status = Status::ok();
    if (mTheRealServiceManager) {
        status = mTheRealServiceManager->getDeclaredInstances(iface, _aidl_return);
    }
    if (!status.isOk()) return status;

    forEachInjectedAccessorService([&](const std::string& instance) {
        // Declared instances have the format
        // <interface>/instance like foo.bar.ISomething/instance
        // If it does not have that format, consider the instance to be ""
        std::string_view name(instance);
        if (base::ConsumePrefix(&name, iface + "/")) {
            _aidl_return->emplace_back(name);
        } else if (iface == instance) {
            _aidl_return->push_back("");
        }
    });

    return status;
}
}
Status BackendUnifiedServiceManager::updatableViaApex(
Status BackendUnifiedServiceManager::updatableViaApex(
        const ::std::string& name, ::std::optional<::std::string>* _aidl_return) {
        const ::std::string& name, ::std::optional<::std::string>* _aidl_return) {
    if (mTheRealServiceManager) {
        return mTheRealServiceManager->updatableViaApex(name, _aidl_return);
        return mTheRealServiceManager->updatableViaApex(name, _aidl_return);
    }
    }
    return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
                                     kUnsupportedOpNoServiceManager);
}
Status BackendUnifiedServiceManager::getUpdatableNames(const ::std::string& apexName,
Status BackendUnifiedServiceManager::getUpdatableNames(const ::std::string& apexName,
                                                       ::std::vector<::std::string>* _aidl_return) {
                                                       ::std::vector<::std::string>* _aidl_return) {
    if (mTheRealServiceManager) {
        return mTheRealServiceManager->getUpdatableNames(apexName, _aidl_return);
        return mTheRealServiceManager->getUpdatableNames(apexName, _aidl_return);
    }
    }
    return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
                                     kUnsupportedOpNoServiceManager);
}
Status BackendUnifiedServiceManager::getConnectionInfo(
Status BackendUnifiedServiceManager::getConnectionInfo(
        const ::std::string& name, ::std::optional<os::ConnectionInfo>* _aidl_return) {
        const ::std::string& name, ::std::optional<os::ConnectionInfo>* _aidl_return) {
    if (mTheRealServiceManager) {
        return mTheRealServiceManager->getConnectionInfo(name, _aidl_return);
        return mTheRealServiceManager->getConnectionInfo(name, _aidl_return);
    }
    }
    return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
                                     kUnsupportedOpNoServiceManager);
}
Status BackendUnifiedServiceManager::registerClientCallback(
Status BackendUnifiedServiceManager::registerClientCallback(
        const ::std::string& name, const sp<IBinder>& service,
        const ::std::string& name, const sp<IBinder>& service,
        const sp<os::IClientCallback>& callback) {
        const sp<os::IClientCallback>& callback) {
    if (mTheRealServiceManager) {
        return mTheRealServiceManager->registerClientCallback(name, service, callback);
        return mTheRealServiceManager->registerClientCallback(name, service, callback);
    }
    }
    return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
                                     kUnsupportedOpNoServiceManager);
}
Status BackendUnifiedServiceManager::tryUnregisterService(const ::std::string& name,
Status BackendUnifiedServiceManager::tryUnregisterService(const ::std::string& name,
                                                          const sp<IBinder>& service) {
                                                          const sp<IBinder>& service) {
    if (mTheRealServiceManager) {
        return mTheRealServiceManager->tryUnregisterService(name, service);
        return mTheRealServiceManager->tryUnregisterService(name, service);
    }
    }
    return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
                                     kUnsupportedOpNoServiceManager);
}
Status BackendUnifiedServiceManager::getServiceDebugInfo(
Status BackendUnifiedServiceManager::getServiceDebugInfo(
        ::std::vector<os::ServiceDebugInfo>* _aidl_return) {
        ::std::vector<os::ServiceDebugInfo>* _aidl_return) {
    if (mTheRealServiceManager) {
        return mTheRealServiceManager->getServiceDebugInfo(_aidl_return);
        return mTheRealServiceManager->getServiceDebugInfo(_aidl_return);
    }
    }
    return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
                                     kUnsupportedOpNoServiceManager);
}


[[clang::no_destroy]] static std::once_flag gUSmOnce;
[[clang::no_destroy]] static std::once_flag gUSmOnce;
[[clang::no_destroy]] static sp<BackendUnifiedServiceManager> gUnifiedServiceManager;
[[clang::no_destroy]] static sp<BackendUnifiedServiceManager> gUnifiedServiceManager;


static bool hasOutOfProcessServiceManager() {
#ifndef BINDER_WITH_KERNEL_IPC
    return false;
#else
#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
    return android::base::GetBoolProperty("servicemanager.installed", true);
#else
    return true;
#endif
#endif // BINDER_WITH_KERNEL_IPC
}

sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager() {
sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager() {
    std::call_once(gUSmOnce, []() {
    std::call_once(gUSmOnce, []() {
#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
        /* wait for service manager */ {
        /* wait for service manager */
        if (hasOutOfProcessServiceManager()) {
            using std::literals::chrono_literals::operator""s;
            using std::literals::chrono_literals::operator""s;
            using android::base::WaitForProperty;
            using android::base::WaitForProperty;
            while (!WaitForProperty("servicemanager.ready", "true", 1s)) {
            while (!WaitForProperty("servicemanager.ready", "true", 1s)) {
@@ -384,7 +484,7 @@ sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager() {
#endif
#endif


        sp<AidlServiceManager> sm = nullptr;
        sp<AidlServiceManager> sm = nullptr;
        while (sm == nullptr) {
        while (hasOutOfProcessServiceManager() && sm == nullptr) {
            sm = interface_cast<AidlServiceManager>(
            sm = interface_cast<AidlServiceManager>(
                    ProcessState::self()->getContextObject(nullptr));
                    ProcessState::self()->getContextObject(nullptr));
            if (sm == nullptr) {
            if (sm == nullptr) {
+4 −0
Original line number Original line Diff line number Diff line
@@ -167,5 +167,9 @@ private:
sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager();
sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager();


android::binder::Status getInjectedAccessor(const std::string& name, android::os::Service* service);
android::binder::Status getInjectedAccessor(const std::string& name, android::os::Service* service);
void appendInjectedAccessorServices(std::vector<std::string>* list);
// Do not call any other service manager APIs that might take the accessor
// mutex because this will be holding it!
void forEachInjectedAccessorService(const std::function<void(const std::string&)>& f);


} // namespace android
} // namespace android
+19 −0
Original line number Original line Diff line number Diff line
@@ -304,6 +304,25 @@ android::binder::Status getInjectedAccessor(const std::string& name,
    return android::binder::Status::ok();
    return android::binder::Status::ok();
}
}


void appendInjectedAccessorServices(std::vector<std::string>* list) {
    LOG_ALWAYS_FATAL_IF(list == nullptr,
                        "Attempted to get list of services from Accessors with nullptr");
    std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
    for (const auto& entry : gAccessorProviders) {
        list->insert(list->end(), entry.mProvider->instances().begin(),
                     entry.mProvider->instances().end());
    }
}

void forEachInjectedAccessorService(const std::function<void(const std::string&)>& f) {
    std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
    for (const auto& entry : gAccessorProviders) {
        for (const auto& instance : entry.mProvider->instances()) {
            f(instance);
        }
    }
}

sp<IServiceManager> defaultServiceManager()
sp<IServiceManager> defaultServiceManager()
{
{
    std::call_once(gSmOnce, []() {
    std::call_once(gSmOnce, []() {
+8 −0
Original line number Original line Diff line number Diff line
@@ -80,6 +80,14 @@ public:


    /**
    /**
     * Register a service.
     * Register a service.
     *
     * Note:
     * This status_t return value may be an exception code from an underlying
     * Status type that doesn't have a representive error code in
     * utils/Errors.h.
     * One example of this is a return value of -7
     * (Status::Exception::EX_UNSUPPORTED_OPERATION) when the service manager
     * process is not installed on the device when addService is called.
     */
     */
    // NOLINTNEXTLINE(google-default-arguments)
    // NOLINTNEXTLINE(google-default-arguments)
    virtual status_t addService(const String16& name, const sp<IBinder>& service,
    virtual status_t addService(const String16& name, const sp<IBinder>& service,
+13 −13
Original line number Original line Diff line number Diff line
@@ -23,7 +23,7 @@ use std::ffi::{c_void, CStr, CString};
use std::os::raw::c_char;
use std::os::raw::c_char;


use libc::{sockaddr, sockaddr_un, sockaddr_vm, socklen_t};
use libc::{sockaddr, sockaddr_un, sockaddr_vm, socklen_t};
use std::sync::Arc;
use std::boxed::Box;
use std::{mem, ptr};
use std::{mem, ptr};


/// Rust wrapper around ABinderRpc_Accessor objects for RPC binder service management.
/// Rust wrapper around ABinderRpc_Accessor objects for RPC binder service management.
@@ -65,7 +65,7 @@ impl Accessor {
    where
    where
        F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static,
        F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static,
    {
    {
        let callback: *mut c_void = Arc::into_raw(Arc::new(callback)) as *mut c_void;
        let callback: *mut c_void = Box::into_raw(Box::new(callback)) as *mut c_void;
        let inst = CString::new(instance).unwrap();
        let inst = CString::new(instance).unwrap();


        // Safety: The function pointer is a valid connection_info callback.
        // Safety: The function pointer is a valid connection_info callback.
@@ -149,7 +149,7 @@ impl Accessor {
    ///   the string within isize::MAX from the pointer. The memory must not be mutated for
    ///   the string within isize::MAX from the pointer. The memory must not be mutated for
    ///   the duration of this function  call and must be valid for reads from the pointer
    ///   the duration of this function  call and must be valid for reads from the pointer
    ///   to the null terminator.
    ///   to the null terminator.
    /// - The `cookie` parameter must be the cookie for an `Arc<F>` and
    /// - The `cookie` parameter must be the cookie for a `Box<F>` and
    ///   the caller must hold a ref-count to it.
    ///   the caller must hold a ref-count to it.
    unsafe extern "C" fn connection_info<F>(
    unsafe extern "C" fn connection_info<F>(
        instance: *const c_char,
        instance: *const c_char,
@@ -162,7 +162,7 @@ impl Accessor {
            log::error!("Cookie({cookie:p}) or instance({instance:p}) is null!");
            log::error!("Cookie({cookie:p}) or instance({instance:p}) is null!");
            return ptr::null_mut();
            return ptr::null_mut();
        }
        }
        // Safety: The caller promises that `cookie` is for an Arc<F>.
        // Safety: The caller promises that `cookie` is for a Box<F>.
        let callback = unsafe { (cookie as *const F).as_ref().unwrap() };
        let callback = unsafe { (cookie as *const F).as_ref().unwrap() };


        // Safety: The caller in libbinder_ndk will have already verified this is a valid
        // Safety: The caller in libbinder_ndk will have already verified this is a valid
@@ -207,19 +207,19 @@ impl Accessor {
        }
        }
    }
    }


    /// Callback that decrements the ref-count.
    /// Callback that drops the `Box<F>`.
    /// This is invoked from C++ when a binder is unlinked.
    /// This is invoked from C++ when a binder is unlinked.
    ///
    ///
    /// # Safety
    /// # Safety
    ///
    ///
    /// - The `cookie` parameter must be the cookie for an `Arc<F>` and
    /// - The `cookie` parameter must be the cookie for a `Box<F>` and
    ///   the owner must give up a ref-count to it.
    ///   the owner must give up a ref-count to it.
    unsafe extern "C" fn cookie_decr_refcount<F>(cookie: *mut c_void)
    unsafe extern "C" fn cookie_decr_refcount<F>(cookie: *mut c_void)
    where
    where
        F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static,
        F: Fn(&str) -> Option<ConnectionInfo> + Send + Sync + 'static,
    {
    {
        // Safety: The caller promises that `cookie` is for an Arc<F>.
        // Safety: The caller promises that `cookie` is for a Box<F>.
        unsafe { Arc::decrement_strong_count(cookie as *const F) };
        unsafe { std::mem::drop(Box::from_raw(cookie as *mut F)) };
    }
    }
}
}


@@ -296,7 +296,7 @@ impl AccessorProvider {
    where
    where
        F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,
        F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,
    {
    {
        let callback: *mut c_void = Arc::into_raw(Arc::new(provider)) as *mut c_void;
        let callback: *mut c_void = Box::into_raw(Box::new(provider)) as *mut c_void;
        let c_str_instances: Vec<CString> =
        let c_str_instances: Vec<CString> =
            instances.iter().map(|s| CString::new(s.as_bytes()).unwrap()).collect();
            instances.iter().map(|s| CString::new(s.as_bytes()).unwrap()).collect();
        let mut c_instances: Vec<*const c_char> =
        let mut c_instances: Vec<*const c_char> =
@@ -346,7 +346,7 @@ impl AccessorProvider {
            log::error!("Cookie({cookie:p}) or instance({instance:p}) is null!");
            log::error!("Cookie({cookie:p}) or instance({instance:p}) is null!");
            return ptr::null_mut();
            return ptr::null_mut();
        }
        }
        // Safety: The caller promises that `cookie` is for an Arc<F>.
        // Safety: The caller promises that `cookie` is for a Box<F>.
        let callback = unsafe { (cookie as *const F).as_ref().unwrap() };
        let callback = unsafe { (cookie as *const F).as_ref().unwrap() };


        let inst = {
        let inst = {
@@ -377,14 +377,14 @@ impl AccessorProvider {
    ///
    ///
    /// # Safety
    /// # Safety
    ///
    ///
    /// - The `cookie` parameter must be the cookie for an `Arc<F>` and
    /// - The `cookie` parameter must be the cookie for a `Box<F>` and
    ///   the owner must give up a ref-count to it.
    ///   the owner must give up a ref-count to it.
    unsafe extern "C" fn accessor_cookie_decr_refcount<F>(cookie: *mut c_void)
    unsafe extern "C" fn accessor_cookie_decr_refcount<F>(cookie: *mut c_void)
    where
    where
        F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,
        F: Fn(&str) -> Option<Accessor> + Send + Sync + 'static,
    {
    {
        // Safety: The caller promises that `cookie` is for an Arc<F>.
        // Safety: The caller promises that `cookie` is for a Box<F>.
        unsafe { Arc::decrement_strong_count(cookie as *const F) };
        unsafe { std::mem::drop(Box::from_raw(cookie as *mut F)) };
    }
    }
}
}


Loading