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 retrieve a lazy service, the service must be started and then retrieved. Calling getService on the service manager will start the service, but usually, you want to get the service as soon as it is available, and waitForService variants should be used. See backend-specific documentation on how to use these.

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