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

Commit 2055e9b4 authored by Amos Bianchi's avatar Amos Bianchi
Browse files

Add active services count callback to lazy services.

Additionally, expose methods to tryUnregister/reRegister
services.

Bug: 176239128
Test: test aidl_lazy_test

Change-Id: I9aa3c9b681bd340ca340fe7ed818ba3533678af2
parent 87385889
Loading
Loading
Loading
Loading
+118 −42
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
 * limitations under the License.
 */

#include "log/log_main.h"
#define LOG_TAG "AidlLazyServiceRegistrar"

#include <binder/LazyServiceRegistrar.h>
@@ -37,6 +38,13 @@ public:
                         bool allowIsolated, int dumpFlags);
    void forcePersist(bool persist);

    void setActiveServicesCountCallback(const std::function<bool(int)>&
                                        activeServicesCountCallback);

    bool tryUnregister();

    void reRegister();

protected:
    Status onClients(const sp<IBinder>& service, bool clients) override;

@@ -49,6 +57,7 @@ private:
        // whether, based on onClients calls, we know we have a client for this
        // service or not
        bool clients = false;
        bool registered = true;
    };

    /**
@@ -62,6 +71,14 @@ private:
     */
    void tryShutdown();

    /**
     * Try to shutdown the process, unless:
     * - 'forcePersist' is 'true', or
     * - The active services count callback returns 'true', or
     * - Some services have clients.
     */
    void maybeTryShutdown();

    // count of services with clients
    size_t mNumConnectedServices;

@@ -69,6 +86,9 @@ private:
    std::map<std::string, Service> mRegisteredServices;

    bool mForcePersist;

    // Callback used to report the number of services with clients
    std::function<bool(int)> mActiveServicesCountCallback;
};

class ClientCounterCallback {
@@ -83,6 +103,13 @@ public:
     */
    void forcePersist(bool persist);

    void setActiveServicesCountCallback(const std::function<bool(int)>&
                                        activeServicesCountCallback);

    bool tryUnregister();

    void reRegister();

private:
    sp<ClientCounterCallbackImpl> mImpl;
};
@@ -131,8 +158,60 @@ std::map<std::string, ClientCounterCallbackImpl::Service>::iterator ClientCounte

void ClientCounterCallbackImpl::forcePersist(bool persist) {
    mForcePersist = persist;
    if(!mForcePersist) {
    if (!mForcePersist && mNumConnectedServices == 0) {
        // Attempt a shutdown in case the number of clients hit 0 while the flag was on
        maybeTryShutdown();
    }
}

bool ClientCounterCallbackImpl::tryUnregister() {
    auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));

    for (auto& [name, entry] : mRegisteredServices) {
        bool success = manager->tryUnregisterService(name, entry.service).isOk();

        if (!success) {
            ALOGI("Failed to unregister service %s", name.c_str());
            return false;
        }
        entry.registered = false;
    }

    return true;
}

void ClientCounterCallbackImpl::reRegister() {
    for (auto& [name, entry] : mRegisteredServices) {
        // re-register entry if not already registered
        if (entry.registered) {
            continue;
        }

        if (!registerService(entry.service, name, entry.allowIsolated,
                             entry.dumpFlags)) {
            // Must restart. Otherwise, clients will never be able to get a hold of this service.
            LOG_ALWAYS_FATAL("Bad state: could not re-register services");
        }

        entry.registered = true;
    }
}

void ClientCounterCallbackImpl::maybeTryShutdown() {
    if (mForcePersist) {
        ALOGI("Shutdown prevented by forcePersist override flag.");
        return;
    }

    bool handledInCallback = false;
    if (mActiveServicesCountCallback != nullptr) {
        handledInCallback = mActiveServicesCountCallback(mNumConnectedServices);
    }

    // If there is no callback defined or the callback did not handle this
    // client count change event, try to shutdown the process if its services
    // have no clients.
    if (!handledInCallback && mNumConnectedServices == 0) {
        tryShutdown();
    }
}
@@ -162,53 +241,24 @@ Status ClientCounterCallbackImpl::onClients(const sp<IBinder>& service, bool cli
    ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
          mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);

    tryShutdown();
    maybeTryShutdown();
    return Status::ok();
}

 void ClientCounterCallbackImpl::tryShutdown() {
    if(mNumConnectedServices > 0) {
        // Should only shut down if there are no clients
        return;
    }

    if(mForcePersist) {
        ALOGI("Shutdown prevented by forcePersist override flag.");
        return;
    }

     ALOGI("Trying to shut down the service. No clients in use for any service in process.");

    auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));

    auto unRegisterIt = mRegisteredServices.begin();
    for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) {
        auto& entry = (*unRegisterIt);

        bool success = manager->tryUnregisterService(entry.first, entry.second.service).isOk();

        if (!success) {
            ALOGI("Failed to unregister service %s", entry.first.c_str());
            break;
        }
    }

    if (unRegisterIt == mRegisteredServices.end()) {
    if (tryUnregister()) {
         ALOGI("Unregistered all clients and exiting");
         exit(EXIT_SUCCESS);
     }

    for (auto reRegisterIt = mRegisteredServices.begin(); reRegisterIt != unRegisterIt;
         reRegisterIt++) {
        auto& entry = (*reRegisterIt);

        // re-register entry
        if (!registerService(entry.second.service, entry.first, entry.second.allowIsolated,
                             entry.second.dumpFlags)) {
            // Must restart. Otherwise, clients will never be able to get a hold of this service.
            ALOGE("Bad state: could not re-register services");
        }
    reRegister();
}

void ClientCounterCallbackImpl::setActiveServicesCountCallback(const std::function<bool(int)>&
                                                               activeServicesCountCallback) {
    mActiveServicesCountCallback = activeServicesCountCallback;
}

ClientCounterCallback::ClientCounterCallback() {
@@ -224,6 +274,19 @@ void ClientCounterCallback::forcePersist(bool persist) {
    mImpl->forcePersist(persist);
}

void ClientCounterCallback::setActiveServicesCountCallback(const std::function<bool(int)>&
                                                           activeServicesCountCallback) {
    mImpl->setActiveServicesCountCallback(activeServicesCountCallback);
}

bool ClientCounterCallback::tryUnregister() {
    return mImpl->tryUnregister();
}

void ClientCounterCallback::reRegister() {
    mImpl->reRegister();
}

}  // namespace internal

LazyServiceRegistrar::LazyServiceRegistrar() {
@@ -247,5 +310,18 @@ void LazyServiceRegistrar::forcePersist(bool persist) {
    mClientCC->forcePersist(persist);
}

void LazyServiceRegistrar::setActiveServicesCountCallback(const std::function<bool(int)>&
                                                          activeServicesCountCallback) {
    mClientCC->setActiveServicesCountCallback(activeServicesCountCallback);
}

bool LazyServiceRegistrar::tryUnregister() {
    return mClientCC->tryUnregister();
}

void LazyServiceRegistrar::reRegister() {
    mClientCC->reRegister();
}

}  // namespace hardware
}  // namespace android
+36 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

#pragma once

#include <functional>

#include <binder/IServiceManager.h>
#include <binder/Status.h>
#include <utils/StrongPointer.h>
@@ -53,6 +55,40 @@ class LazyServiceRegistrar {
      */
     void forcePersist(bool persist);

     /**
      * Set a callback that is executed when the total number of services with
      * clients changes.
      * The callback takes an argument, which is the number of registered
      * lazy services for this process which have clients.
      *
      * Callback return value:
      * - false: Default behavior for lazy services (shut down the process if there
      *          are no clients).
      * - true:  Don't shut down the process even if there are no clients.
      *
      * This callback gives a chance to:
      * 1 - Perform some additional operations before exiting;
      * 2 - Prevent the process from exiting by returning "true" from the
      *     callback.
      *
      * This method should be called before 'registerService' to avoid races.
      */
     void setActiveServicesCountCallback(const std::function<bool(int)>&
                                         activeServicesCountCallback);

    /**
      * Try to unregister all services previously registered with 'registerService'.
      * Returns 'true' if successful.
      */
     bool tryUnregister();

     /**
      * Re-register services that were unregistered by 'tryUnregister'.
      * This method should be called in the case 'tryUnregister' fails
      * (and should be called on the same thread).
      */
     void reRegister();

   private:
     std::shared_ptr<internal::ClientCounterCallback> mClientCC;
     LazyServiceRegistrar();