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 queservicemanager
encuentre el servicio. Si el servicio usa varias interfaces, declara cada una en su propia línea. Estos nombres deben ser exactamente los que esperaservicemanager
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