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

Commit 5a67ed3e authored by Amos Bianchi's avatar Amos Bianchi Committed by Android (Google) Code Review
Browse files

Merge "Add active services count callback to lazy services."

parents c7204b2f 2055e9b4
Loading
Loading
Loading
Loading
+118 −42
Original line number Original line Diff line number Diff line
@@ -14,6 +14,7 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


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


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


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

    bool tryUnregister();

    void reRegister();

protected:
protected:
    Status onClients(const sp<IBinder>& service, bool clients) override;
    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
        // whether, based on onClients calls, we know we have a client for this
        // service or not
        // service or not
        bool clients = false;
        bool clients = false;
        bool registered = true;
    };
    };


    /**
    /**
@@ -62,6 +71,14 @@ private:
     */
     */
    void tryShutdown();
    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
    // count of services with clients
    size_t mNumConnectedServices;
    size_t mNumConnectedServices;


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


    bool mForcePersist;
    bool mForcePersist;

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


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


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

    bool tryUnregister();

    void reRegister();

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


void ClientCounterCallbackImpl::forcePersist(bool persist) {
void ClientCounterCallbackImpl::forcePersist(bool persist) {
    mForcePersist = 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
        // 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();
        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",
    ALOGI("Process has %zu (of %zu available) client(s) in use after notification %s has clients: %d",
          mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);
          mNumConnectedServices, mRegisteredServices.size(), name.c_str(), clients);


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


 void ClientCounterCallbackImpl::tryShutdown() {
 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.");
     ALOGI("Trying to shut down the service. No clients in use for any service in process.");


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

    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()) {
         ALOGI("Unregistered all clients and exiting");
         ALOGI("Unregistered all clients and exiting");
         exit(EXIT_SUCCESS);
         exit(EXIT_SUCCESS);
     }
     }


    for (auto reRegisterIt = mRegisteredServices.begin(); reRegisterIt != unRegisterIt;
    reRegister();
         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");
        }
}
}

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


ClientCounterCallback::ClientCounterCallback() {
ClientCounterCallback::ClientCounterCallback() {
@@ -224,6 +274,19 @@ void ClientCounterCallback::forcePersist(bool persist) {
    mImpl->forcePersist(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
}  // namespace internal


LazyServiceRegistrar::LazyServiceRegistrar() {
LazyServiceRegistrar::LazyServiceRegistrar() {
@@ -247,5 +310,18 @@ void LazyServiceRegistrar::forcePersist(bool persist) {
    mClientCC->forcePersist(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 hardware
}  // namespace android
}  // namespace android
+36 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,8 @@


#pragma once
#pragma once


#include <functional>

#include <binder/IServiceManager.h>
#include <binder/IServiceManager.h>
#include <binder/Status.h>
#include <binder/Status.h>
#include <utils/StrongPointer.h>
#include <utils/StrongPointer.h>
@@ -53,6 +55,40 @@ class LazyServiceRegistrar {
      */
      */
     void forcePersist(bool persist);
     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:
   private:
     std::shared_ptr<internal::ClientCounterCallback> mClientCC;
     std::shared_ptr<internal::ClientCounterCallback> mClientCC;
     LazyServiceRegistrar();
     LazyServiceRegistrar();