Google is committed to advancing racial equity for Black communities. See how.

Running AIDL Services Dynamically

Starting in Android 11, native AIDL services running in the system partition can be started and stopped dynamically as they are needed. Dynamic services start when they are first requested and automatically stop when they are no longer in use.

Services that can run dynamically

This feature is available only for native services whose lifecycles can be controlled by init and servicemanager. Services within app packages are not supported and should use bound services instead.

Dynamic shutdown works by shutting down the process in which the service runs. If multiple services exist in the same process, all of them must be registered as dynamic to be compatible with this feature. That process will then shut down when all of the services are unused.

Configuring a service’s init .rc file

To run a service dynamically, add the following options to the service’s init .rc file after the leading service <name> <cmd> line.

interface aidl serviceName
disabled
oneshot

These options do the following:

  • interface aidl serviceName: Allows servicemanager to find the service. If the service uses multiple interfaces, declare each interface on its own line. These names must be exactly what servicemanager expects and may differ from the process name.
  • disabled: Prevents the service from automatically starting at boot.
  • oneshot: Prevents the service from automatically restarting each time it is stopped.

For more information, see the Android Init Language Readme in AOSP.

Examples:

Registering a service

Each service is created and registered with servicemanager. Registration often occurs in a file named main.cpp, but the implementation can vary. The registration usually looks something like this:

using android::defaultServiceManager;

defaultServiceManager()->addService(serviceName, service);

Registration is sometimes abstracted by BinderService::publish or BinderService::instantiate, which call the above code.

To register a service as dynamic, replace its registration code with the following:

#include <binder/LazyServiceRegistrar.h>

using android::binder::LazyServiceRegistrar;

auto lazyRegistrar = LazyServiceRegistrar::getInstance();
lazyRegistrar.registerService(service, serviceName);

servicemanager communicates with LazyServiceRegistrar to shut down services based on their reference counts.

Examples:

Configuring AIDL service clients

Getting the service

To enable a client to retrieve a lazy service that may or may not be running, replace calls to getService and checkService with calls to waitForService. waitForService blocks and waits indefinitely, so only call it on services that actually exist. There is no VINTF manifest equivalent to verify whether an AIDL service exists on a device.

In C++ this will look something like:

sp<IServiceManager> sm = android::defaultServiceManager();
// sp<IBinder> binder = sm->getService(String16("serviceName"));
sp<IBinder> binder = sm->waitForService(String16("serviceName"));

In Java, this will look something like:

// IService.Stub.asInterface(ServiceManager.getService("serviceName"));
IService.Stub.asInterface(ServiceManager.waitForService("serviceName"));

Releasing the service

Dynamic shutdown is based on reference counting, so clients must not hold onto the service when it is not in use.

Examples:

Temporarily disabling shutdown

If you want a service to run independently until certain tasks are complete and then switch to dynamic behavior, you can use LazyServiceRegistrar::forcePersist to toggle dynamic shutdown on and off. If this is called from the server side, it should be called before registerService.

Example: apexservice