Cómo ejecutar servicios de AIDL de forma dinámica

A partir de Android 11, los servicios de 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 están en uso.

Servicios que pueden ejecutarse de forma dinámica

Esta función solo está disponible para servicios nativos cuyos ciclos de vida se pueden controlar con init y servicemanager. Los servicios dentro de los paquetes de apps no son compatibles y, en su lugar, deben usar servicios vinculados.

El cierre dinámico funciona finalizando el proceso en el que se ejecuta el servicio. Si existen varios servicios en el mismo proceso, todos deben registrarse como dinámicos para que sean compatibles con esta función. Ese proceso se cerrará cuando no se usen todos los servicios.

Configura el archivo .rc init de un servicio

Para ejecutar un servicio de forma dinámica, agrega las siguientes opciones al archivo init .rc 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 lo que servicemanager espera y pueden diferir del nombre del proceso.
  • disabled: Impide 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 archivo readme sobre el lenguaje Init de Android en el AOSP.

Ejemplos:

Registra 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 así:

using android::defaultServiceManager;

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

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

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

#include <binder/LazyServiceRegistrar.h>

using android::binder::LazyServiceRegistrar;

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

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

Ejemplos:

Configura los clientes de servicio del AIDL

Obtener el servicio

Para recuperar un servicio diferido, se debe iniciar y recuperar el servicio. Si llamas a getService en el administrador de servicios, se iniciará el servicio, pero, por lo general, es recomendable obtenerlo en cuanto esté disponible y se deben usar variantes waitForService. Consulta la documentación específica del backend sobre cómo usarlos.

Libera el servicio

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

Ejemplos:

Inhabilitar temporalmente el cierre

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

Ejemplo: apexservice