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

Commit e9692d42 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "IServiceManager: add registerForNotifications."

parents 60aac74f 30700944
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -61,6 +61,10 @@ class ServiceManagerMock : public IServiceManager {
    MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&));
    MOCK_METHOD1(updatableViaApex, std::optional<String16>(const String16&));
    MOCK_METHOD1(getConnectionInfo, std::optional<ConnectionInfo>(const String16&));
    MOCK_METHOD2(registerForNotifications, status_t(const String16&,
                                             const sp<LocalRegistrationCallback>&));
    MOCK_METHOD2(unregisterForNotifications, status_t(const String16&,
                                             const sp<LocalRegistrationCallback>&));
  protected:
    MOCK_METHOD0(onAsBinder, IBinder*());
};
+101 −0
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@

namespace android {

using AidlRegistrationCallback = IServiceManager::LocalRegistrationCallback;

using AidlServiceManager = android::os::IServiceManager;
using android::binder::Status;

@@ -79,7 +81,24 @@ public:
    Vector<String16> getDeclaredInstances(const String16& interface) override;
    std::optional<String16> updatableViaApex(const String16& name) override;
    std::optional<IServiceManager::ConnectionInfo> getConnectionInfo(const String16& name) override;
    class RegistrationWaiter : public android::os::BnServiceCallback {
    public:
        explicit RegistrationWaiter(const sp<AidlRegistrationCallback>& callback)
              : mImpl(callback) {}
        Status onRegistration(const std::string& name, const sp<IBinder>& binder) override {
            mImpl->onServiceRegistration(String16(name.c_str()), binder);
            return Status::ok();
        }

    private:
        sp<AidlRegistrationCallback> mImpl;
    };

    status_t registerForNotifications(const String16& service,
                                      const sp<AidlRegistrationCallback>& cb) override;

    status_t unregisterForNotifications(const String16& service,
                                        const sp<AidlRegistrationCallback>& cb) override;
    // for legacy ABI
    const String16& getInterfaceDescriptor() const override {
        return mTheRealServiceManager->getInterfaceDescriptor();
@@ -90,6 +109,17 @@ public:

protected:
    sp<AidlServiceManager> mTheRealServiceManager;
    // AidlRegistrationCallback -> services that its been registered for
    // notifications.
    using LocalRegistrationAndWaiter =
            std::pair<sp<LocalRegistrationCallback>, sp<RegistrationWaiter>>;
    using ServiceCallbackMap = std::map<std::string, std::vector<LocalRegistrationAndWaiter>>;
    ServiceCallbackMap mNameToRegistrationCallback;
    std::mutex mNameToRegistrationLock;

    void removeRegistrationCallbackLocked(const sp<AidlRegistrationCallback>& cb,
                                          ServiceCallbackMap::iterator* it,
                                          sp<RegistrationWaiter>* waiter);

    // Directly get the service in a way that, for lazy services, requests the service to be started
    // if it is not currently started. This way, calls directly to ServiceManagerShim::getService
@@ -442,6 +472,77 @@ std::optional<IServiceManager::ConnectionInfo> ServiceManagerShim::getConnection
            : std::nullopt;
}

status_t ServiceManagerShim::registerForNotifications(const String16& name,
                                                      const sp<AidlRegistrationCallback>& cb) {
    if (cb == nullptr) {
        ALOGE("%s: null cb passed", __FUNCTION__);
        return BAD_VALUE;
    }
    std::string nameStr = String8(name).c_str();
    sp<RegistrationWaiter> registrationWaiter = sp<RegistrationWaiter>::make(cb);
    std::lock_guard<std::mutex> lock(mNameToRegistrationLock);
    if (Status status =
                mTheRealServiceManager->registerForNotifications(nameStr, registrationWaiter);
        !status.isOk()) {
        ALOGW("Failed to registerForNotifications for %s: %s", nameStr.c_str(),
              status.toString8().c_str());
        return UNKNOWN_ERROR;
    }
    mNameToRegistrationCallback[nameStr].push_back(std::make_pair(cb, registrationWaiter));
    return OK;
}

void ServiceManagerShim::removeRegistrationCallbackLocked(const sp<AidlRegistrationCallback>& cb,
                                                          ServiceCallbackMap::iterator* it,
                                                          sp<RegistrationWaiter>* waiter) {
    std::vector<LocalRegistrationAndWaiter>& localRegistrationAndWaiters = (*it)->second;
    for (auto lit = localRegistrationAndWaiters.begin();
         lit != localRegistrationAndWaiters.end();) {
        if (lit->first == cb) {
            if (waiter) {
                *waiter = lit->second;
            }
            lit = localRegistrationAndWaiters.erase(lit);
        } else {
            ++lit;
        }
    }

    if (localRegistrationAndWaiters.empty()) {
        mNameToRegistrationCallback.erase(*it);
    }
}

status_t ServiceManagerShim::unregisterForNotifications(const String16& name,
                                                        const sp<AidlRegistrationCallback>& cb) {
    if (cb == nullptr) {
        ALOGE("%s: null cb passed", __FUNCTION__);
        return BAD_VALUE;
    }
    std::string nameStr = String8(name).c_str();
    std::lock_guard<std::mutex> lock(mNameToRegistrationLock);
    auto it = mNameToRegistrationCallback.find(nameStr);
    sp<RegistrationWaiter> registrationWaiter;
    if (it != mNameToRegistrationCallback.end()) {
        removeRegistrationCallbackLocked(cb, &it, &registrationWaiter);
    } else {
        ALOGE("%s no callback registered for notifications on %s", __FUNCTION__, nameStr.c_str());
        return BAD_VALUE;
    }
    if (registrationWaiter == nullptr) {
        ALOGE("%s Callback passed wasn't used to register for notifications", __FUNCTION__);
        return BAD_VALUE;
    }
    if (Status status = mTheRealServiceManager->unregisterForNotifications(String8(name).c_str(),
                                                                           registrationWaiter);
        !status.isOk()) {
        ALOGW("Failed to get service manager to unregisterForNotifications for %s: %s",
              String8(name).c_str(), status.toString8().c_str());
        return UNKNOWN_ERROR;
    }
    return OK;
}

#ifndef __ANDROID__
// ServiceManagerShim for host. Implements the old libbinder android::IServiceManager API.
// The internal implementation of the AIDL interface android::os::IServiceManager calls into
+11 −0
Original line number Diff line number Diff line
@@ -115,6 +115,17 @@ public:
        unsigned int port;
    };
    virtual std::optional<ConnectionInfo> getConnectionInfo(const String16& name) = 0;

    struct LocalRegistrationCallback : public virtual RefBase {
        virtual void onServiceRegistration(const String16& instance, const sp<IBinder>& binder) = 0;
        virtual ~LocalRegistrationCallback() {}
    };

    virtual status_t registerForNotifications(const String16& name,
                                              const sp<LocalRegistrationCallback>& callback) = 0;

    virtual status_t unregisterForNotifications(const String16& name,
                                                const sp<LocalRegistrationCallback>& callback) = 0;
};

sp<IServiceManager> defaultServiceManager();
+13 −0
Original line number Diff line number Diff line
@@ -1220,6 +1220,19 @@ TEST_F(BinderLibTest, GotSid) {
    EXPECT_THAT(server->transact(BINDER_LIB_TEST_CAN_GET_SID, data, nullptr), StatusEq(OK));
}

TEST(ServiceNotifications, Unregister) {
    auto sm = defaultServiceManager();
    using LocalRegistrationCallback = IServiceManager::LocalRegistrationCallback;
    class LocalRegistrationCallbackImpl : public virtual LocalRegistrationCallback {
        void onServiceRegistration(const String16 &, const sp<IBinder> &) override {}
        virtual ~LocalRegistrationCallbackImpl() {}
    };
    sp<LocalRegistrationCallback> cb = sp<LocalRegistrationCallbackImpl>::make();

    EXPECT_EQ(sm->registerForNotifications(String16("RogerRafa"), cb), OK);
    EXPECT_EQ(sm->unregisterForNotifications(String16("RogerRafa"), cb), OK);
}

class BinderLibRpcTestBase : public BinderLibTest {
public:
    void SetUp() override {
+10 −0
Original line number Diff line number Diff line
@@ -84,4 +84,14 @@ std::optional<IServiceManager::ConnectionInfo> ServiceManager::getConnectionInfo
    return std::nullopt;
}

status_t ServiceManager::registerForNotifications(const String16&,
                                                  const sp<LocalRegistrationCallback>&) {
    return INVALID_OPERATION;
}

status_t ServiceManager::unregisterForNotifications(const String16&,
                                                const sp<LocalRegistrationCallback>&) {
    return INVALID_OPERATION;
}

}  // namespace android
Loading