Esegui i servizi AIDL in modo dinamico

A partire da Android 11, i servizi AIDL nativi in esecuzione nella partizione di sistema possono essere avviati e arrestati dinamicamente in base alle necessità. I servizi dinamici iniziano quando vengono richiesti per la prima volta e si interrompono automaticamente quando non sono più in uso.

Servizi che possono essere eseguiti in modo dinamico

Questa funzionalità è disponibile solo per i servizi nativi il cui ciclo di vita può essere controllato da init e servicemanager. I servizi all'interno dei pacchetti di app non sono supportati e devono utilizzare servizi associati invece.

L'arresto dinamico funziona arrestando il processo in cui viene eseguito il servizio. Se nello stesso processo esistono più servizi, tutti devono essere registrati come dinamici per essere compatibili con questa funzionalità. Il processo verrà quindi arrestato quando tutti i servizi non vengono utilizzati.

Configura il file .rc init di un servizio

Per eseguire un servizio in modo dinamico, aggiungi le seguenti opzioni al file init .rc del servizio dopo la riga service <name> <cmd> iniziale.

interface aidl serviceName
disabled
oneshot

Queste opzioni eseguono le seguenti operazioni:

  • interface aidl serviceName: consente a servicemanager di trovare il servizio. Se il servizio utilizza più interfacce, dichiara ogni interfaccia sulla propria riga. Questi nomi devono corrispondere esattamente a quelli previsti da servicemanager e potrebbero differire dal nome del processo.
  • disabled: impedisce l'avvio automatico del servizio all'avvio.
  • oneshot: impedisce il riavvio automatico del servizio ogni volta che viene interrotto.

Per saperne di più, consulta il file Readme di Android Init Language in AOSP.

Esempi:

Registrare un servizio

Ogni servizio viene creato e registrato con servicemanager. La registrazione spesso avviene in un file denominato main.cpp, ma l'implementazione può variare. La registrazione in genere ha un aspetto simile a questo:

using android::defaultServiceManager;

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

La registrazione a volte viene astratta da BinderService::publish o BinderService::instantiate, che chiamano il codice precedente.

Per registrare un servizio come dinamico, sostituisci il codice di registrazione con il seguente:

#include <binder/LazyServiceRegistrar.h>

using android::binder::LazyServiceRegistrar;

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

servicemanager comunica con LazyServiceRegistrar per disattivare i servizi in base al numero di riferimenti.

Esempi:

Configura i client di servizio AIDL

Recuperare il servizio

Per recuperare un servizio lazy, il servizio deve essere avviato e poi recuperato. La chiamata di getService sul gestore del servizio avvierà il servizio, ma di solito vuoi ottenere il servizio non appena è disponibile e devono essere utilizzate le varianti waitForService. Consulta la documentazione specifica per il backend su come utilizzarli.

Rilasciare il servizio

L'arresto dinamico si basa sul conteggio dei riferimenti, pertanto i client non devono mantenere il servizio quando non è in uso.

Esempi:

Disattivare temporaneamente l'arresto

Se vuoi che un servizio venga eseguito in modo indipendente fino al completamento di determinate attività e poi passi a un comportamento dinamico, puoi utilizzare LazyServiceRegistrar::forcePersist per attivare e disattivare l'arresto dinamico. Se viene chiamato dal lato server, deve essere chiamato prima di registerService.

Esempio: apexservice