Ejecuta servicios de AIDL de forma dinámica

A partir de Android 11, los servicios AIDL nativos que se ejecutan en la partición del sistema se pueden iniciar y detener de forma dinámica según sea necesario. Los servicios dinámicos se inician cuando se solicitan por primera vez y se detienen automáticamente cuando ya no se usan.

Servicios que se pueden ejecutar de forma dinámica

Esta función solo está disponible para los servicios nativos cuyos ciclos de vida pueden controlarse con init y servicemanager. No se admiten los servicios dentro de los paquetes de la app, por lo que se deben usar servicios vinculados.

El cierre dinámico funciona deteniendo el proceso en el que se ejecuta el servicio. Si existen varios servicios en el mismo proceso, todos deben registrarse como dinámicos para ser compatibles con esta función. Luego, ese proceso se cerrará cuando no se use ninguno de los servicios.

Cómo configurar el archivo .rc de inicialización de un servicio

Para ejecutar un servicio de forma dinámica, agrega las siguientes opciones al archivo .rc de init del servicio después de la línea service <name> <cmd> inicial.

interface aidl serviceName
disabled
oneshot

Estas opciones hacen lo siguiente:

  • interface aidl serviceName: Permite que servicemanager encuentre el servicio. Si el servicio usa varias interfaces, declara cada una en su propia línea. Estos nombres deben ser exactamente los que espera servicemanager y pueden diferir del nombre del proceso.
  • disabled: Evita que el servicio se inicie automáticamente durante el arranque.
  • oneshot: Evita que el servicio se reinicie automáticamente cada vez que se detiene.

Para obtener más información, consulta el Readme de Android Init Language en el AOSP.

Ejemplos:

Cómo registrar un servicio

Cada servicio se crea y registra con servicemanager. El registro suele ocurrir en un archivo llamado main.cpp, pero la implementación puede variar. Por lo general, el registro se ve de la siguiente manera:

using android::defaultServiceManager;

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

A veces, BinderService::publish o BinderService::instantiate abstraen el registro, que llama al código anterior.

Para registrar un servicio como dinámico, reemplaza su código de registro por el siguiente:

#include <binder/LazyServiceRegistrar.h>

using android::binder::LazyServiceRegistrar;

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

servicemanager se comunica con LazyServiceRegistrar para detener los servicios según sus recuentos de referencias.

Ejemplos:

Configura clientes de servicio de AIDL

Obtén el servicio

Para recuperar un servicio diferido, se debe iniciar el servicio y, luego, recuperarlo. Llamar a getService en el administrador de servicios iniciará el servicio, pero, por lo general, querrás obtener el servicio tan pronto como esté disponible, por lo que se deben usar las variantes de waitForService. Consulta la documentación específica del backend sobre cómo usarlos.

Lanza el servicio

El cierre dinámico se basa en el recuento de referencias, por lo que los clientes no deben mantener el servicio cuando no esté en uso.

Ejemplos:

Inhabilita el cierre temporalmente

Si quieres que un servicio se ejecute de forma independiente hasta que se completen ciertas tareas y, luego, cambie a un comportamiento dinámico, puedes usar LazyServiceRegistrar::forcePersist para activar y desactivar el cierre dinámico. Si se llama a este método desde el servidor, se debe llamar antes de registerService.

Ejemplo: apexservice