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

Commit a3867c73 authored by Devin Moore's avatar Devin Moore
Browse files

Add listServices/isDeclared/getDeclaredInstances for Accessors

We associate specific accessors with instance names, so we can get
more information about what is available through the existing service
manager APIs.

Test: atest binderRpcTest
Bug: 358427181
Change-Id: I337430a222b537643351bfc70178ccd1dc06d73b
parent 3c93111c
Loading
Loading
Loading
Loading
+38 −9
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
#include "BackendUnifiedServiceManager.h"

#include <android-base/strings.h>
#include <android/os/IAccessor.h>
#include <android/os/IServiceManager.h>
#include <binder/RpcSession.h>
@@ -339,11 +340,15 @@ Status BackendUnifiedServiceManager::addService(const ::std::string& name,
}
Status BackendUnifiedServiceManager::listServices(int32_t dumpPriority,
                                                  ::std::vector<::std::string>* _aidl_return) {
    Status status = Status::ok();
    if (mTheRealServiceManager) {
        return mTheRealServiceManager->listServices(dumpPriority, _aidl_return);
        status = mTheRealServiceManager->listServices(dumpPriority, _aidl_return);
    }
    return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
                                     kUnsupportedOpNoServiceManager);
    if (!status.isOk()) return status;

    appendInjectedAccessorServices(_aidl_return);

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

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

    return status;
}
Status BackendUnifiedServiceManager::getDeclaredInstances(
        const ::std::string& iface, ::std::vector<::std::string>* _aidl_return) {
    Status status = Status::ok();
    if (mTheRealServiceManager) {
        return mTheRealServiceManager->getDeclaredInstances(iface, _aidl_return);
        status = mTheRealServiceManager->getDeclaredInstances(iface, _aidl_return);
    }
    return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION,
                                     kUnsupportedOpNoServiceManager);
    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(
        const ::std::string& name, ::std::optional<::std::string>* _aidl_return) {
+4 −0
Original line number Diff line number Diff line
@@ -167,5 +167,9 @@ private:
sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager();

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
+19 −0
Original line number Diff line number Diff line
@@ -304,6 +304,25 @@ android::binder::Status getInjectedAccessor(const std::string& name,
    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()
{
    std::call_once(gSmOnce, []() {
+103 −0
Original line number Diff line number Diff line
@@ -1328,6 +1328,109 @@ TEST_P(BinderRpcAccessor, InjectNoSockaddrProvided) {
    EXPECT_EQ(status, OK);
}

class BinderRpcAccessorNoConnection : public ::testing::Test {};

TEST_F(BinderRpcAccessorNoConnection, listServices) {
    const String16 kInstanceName("super.cool.service/better_than_default");
    const String16 kInstanceName2("super.cool.service/better_than_default2");

    auto receipt =
            addAccessorProvider({String8(kInstanceName).c_str(), String8(kInstanceName2).c_str()},
                                [&](const String16&) -> sp<IBinder> { return nullptr; });
    EXPECT_FALSE(receipt.expired());
    Vector<String16> list =
            defaultServiceManager()->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL);
    bool name1 = false;
    bool name2 = false;
    for (auto name : list) {
        if (name == kInstanceName) name1 = true;
        if (name == kInstanceName2) name2 = true;
    }
    EXPECT_TRUE(name1);
    EXPECT_TRUE(name2);
    status_t status = removeAccessorProvider(receipt);
    EXPECT_EQ(status, OK);
}

TEST_F(BinderRpcAccessorNoConnection, isDeclared) {
    const String16 kInstanceName("super.cool.service/default");
    const String16 kInstanceName2("still_counts_as_declared");

    auto receipt =
            addAccessorProvider({String8(kInstanceName).c_str(), String8(kInstanceName2).c_str()},
                                [&](const String16&) -> sp<IBinder> { return nullptr; });
    EXPECT_FALSE(receipt.expired());
    EXPECT_TRUE(defaultServiceManager()->isDeclared(kInstanceName));
    EXPECT_TRUE(defaultServiceManager()->isDeclared(kInstanceName2));
    EXPECT_FALSE(defaultServiceManager()->isDeclared(String16("doesnt_exist")));
    status_t status = removeAccessorProvider(receipt);
    EXPECT_EQ(status, OK);
}

TEST_F(BinderRpcAccessorNoConnection, getDeclaredInstances) {
    const String16 kInstanceName("super.cool.service.IFoo/default");
    const String16 kInstanceName2("super.cool.service.IFoo/extra/default");
    const String16 kInstanceName3("super.cool.service.IFoo");

    auto receipt =
            addAccessorProvider({String8(kInstanceName).c_str(), String8(kInstanceName2).c_str(),
                                 String8(kInstanceName3).c_str()},
                                [&](const String16&) -> sp<IBinder> { return nullptr; });
    EXPECT_FALSE(receipt.expired());
    Vector<String16> list =
            defaultServiceManager()->getDeclaredInstances(String16("super.cool.service.IFoo"));
    // We would prefer ASSERT_EQ here, but we must call removeAccessorProvider
    EXPECT_EQ(list.size(), 3u);
    if (list.size() == 3) {
        bool name1 = false;
        bool name2 = false;
        bool name3 = false;
        for (auto name : list) {
            if (name == String16("default")) name1 = true;
            if (name == String16("extra/default")) name2 = true;
            if (name == String16()) name3 = true;
        }
        EXPECT_TRUE(name1) << String8(list[0]);
        EXPECT_TRUE(name2) << String8(list[1]);
        EXPECT_TRUE(name3) << String8(list[2]);
    }

    status_t status = removeAccessorProvider(receipt);
    EXPECT_EQ(status, OK);
}

TEST_F(BinderRpcAccessorNoConnection, getDeclaredWrongInstances) {
    const String16 kInstanceName("super.cool.service.IFoo");

    auto receipt = addAccessorProvider({String8(kInstanceName).c_str()},
                                       [&](const String16&) -> sp<IBinder> { return nullptr; });
    EXPECT_FALSE(receipt.expired());
    Vector<String16> list = defaultServiceManager()->getDeclaredInstances(String16("unknown"));
    EXPECT_TRUE(list.empty());

    status_t status = removeAccessorProvider(receipt);
    EXPECT_EQ(status, OK);
}

TEST_F(BinderRpcAccessorNoConnection, getDeclaredInstancesSlash) {
    // This is treated as if there were no '/' and the declared instance is ""
    const String16 kInstanceName("super.cool.service.IFoo/");

    auto receipt = addAccessorProvider({String8(kInstanceName).c_str()},
                                       [&](const String16&) -> sp<IBinder> { return nullptr; });
    EXPECT_FALSE(receipt.expired());
    Vector<String16> list =
            defaultServiceManager()->getDeclaredInstances(String16("super.cool.service.IFoo"));
    bool name1 = false;
    for (auto name : list) {
        if (name == String16("")) name1 = true;
    }
    EXPECT_TRUE(name1);

    status_t status = removeAccessorProvider(receipt);
    EXPECT_EQ(status, OK);
}

constexpr const char* kARpcInstance = "some.instance.name.IFoo/default";
const char* kARpcSupportedServices[] = {
        kARpcInstance,