HAL disponibili dinamicamente

Android 9 supporta lo spegnimento dinamico dei sottosistemi hardware Android quando non sono in uso o non sono necessari. Ad esempio, quando un utente non utilizza il Wi-Fi, i sottosistemi Wi-Fi non devono occupare memoria, potenza o altre risorse di sistema. Nelle versioni precedenti di Android, gli HAL/driver venivano mantenuti aperti sui dispositivi Android per l'intera durata dell'avvio di uno smartphone Android.

L'implementazione dell'arresto dinamico prevede il collegamento dei flussi di dati e l'esecuzione di processi dinamici, come descritto nelle sezioni seguenti.

Modifiche alle definizioni HAL

L'arresto dinamico richiede informazioni su quali processi servono quali interfacce HAL (queste informazioni possono essere utili anche in un secondo momento in altri contesti), nonché di non avviare i processi all'avvio e di non riavviarli (fino a quando non vengono richiesti di nuovo) al termine.

# some init.rc script associated with the HAL
service vendor.some-service-name /vendor/bin/hw/some-binary-service
    # init language extension, provides information of what service is served
    # if multiple interfaces are served, they can be specified one on each line
    interface android.hardware.light@2.0::ILight default
    # restarted if hwservicemanager dies
    # would also cause the hal to start early during boot if disabled wasn't set
    class hal
    # will not be restarted if it exits until it is requested to be restarted
    oneshot
    # will only be started when requested
    disabled
    # ... other properties

Modifiche a init e hwservicemanager

L'arresto dinamico richiede inoltre che hwservicemanager dica init di avviare i servizi richiesti. In Android 9, init include tre messaggi di controllo aggiuntivi (ad es. ctl.start): ctl.interface_start, ctl.interface_stop e ctl.interface_restart. Questi messaggi possono essere utilizzati per segnalare a init di attivare e disattivare specifiche interfacce hardware. Quando viene richiesto un servizio e non è registrato, hwservicemanager richiede di avviarlo. Tuttavia, gli HAL dinamici non richiedono l'utilizzo di nessuno di questi elementi.

Determinare l'uscita HAL

In Android 9, l'uscita HAL deve essere determinata manualmente. Per Android 10 e versioni successive, può essere determinato anche con i cicli di vita automatici.

L'arresto dinamico richiede più criteri per decidere quando avviare un HAL e quando arrestarlo. Se un HAL decide di uscire per qualsiasi motivo, verrà riavviato automaticamente quando sarà di nuovo necessario utilizzando le informazioni fornite nella definizione HAL e l'infrastruttura fornita dalle modifiche a init e hwservicemanager. Potrebbero essere impiegate diverse strategie, tra cui:

  • Un HAL potrebbe scegliere di chiamare exit su se stesso se qualcuno chiama un'API simile o chiusa. Questo comportamento deve essere specificato nell'interfaccia HAL corrispondente.
  • Gli HAL possono arrestarsi al termine dell'attività (documentato nel file HAL).

Cicli di vita automatici

Android 10 aggiunge ulteriore supporto al kernel e hwservicemanager, che consente agli HAL di arrestarsi automaticamente quando non hanno clienti. Per utilizzare questa funzionalità, svolgi tutti i passaggi descritti in Modifiche alle definizioni HAL, nonché:

  • Registra il servizio in C++ con LazyServiceRegistrar anziché con la funzione membro registerAsService, ad esempio:
    // only one instance of LazyServiceRegistrar per process
    LazyServiceRegistrar registrar;
    registrar.registerAsService(myHidlService /* , "default" */);
  • Verifica che il client HAL mantenga un riferimento all'HAL di primo livello (l'interfaccia registrata con hwservicemanager) solo quando è in uso. Per evitare ritardi se questo riferimento viene eliminato in un thread hwbinder che continua a essere eseguito, il client deve chiamare anche IPCThreadState::self()->flushCommands() dopo aver eliminato il riferimento per assicurarsi che al driver binder venga inviata una notifica delle modifiche associate al conteggio dei riferimenti.