Sensori Multi-HAL

Sensors Multi-HAL è un framework che consente ai sensori HAL di funzionare insieme ad altri HAL di sensori. L'opzione Sensors Multi-HAL carica dinamicamente gli HAL secondari dei sensori memorizzati come librerie dinamiche sulla partizione del fornitore e fornisce loro un oggetto di callback in grado di gestire gli eventi di pubblicazione e l'acquisizione e il rilascio del wakelock. Un sotto-HAL dei sensori è un HAL dei sensori integrato in un oggetto condiviso nella partizione del fornitore e utilizzato dal framework multi-HAL. Questi sotto-HAL non dipendono tra loro o dal codice multi-HAL che contiene la funzione principale per il processo.

Sensors Multi-HAL 2.1, disponibile sui dispositivi con sistema operativo Android 11 o versioni successive, è un'iterazione di Sensors Multi-HAL 2.0 che supporta il caricamento di sub-HAL che possono esporre il tipo di sensore angolo di cerniera. Per supportare questo tipo di sensore, i sub-HAL devono utilizzare le API sub-HAL definite nell'intestazione SubHal 2.1.

Per i dispositivi con Android 13 o versioni successive che utilizzano il Sensors AIDL HAL, puoi utilizzare il livello shim multi-HAL per consentire la funzionalità multi-HAL. Per i dettagli sull'implementazione, consulta la pagina Utilizzo di Sensors Multi-HAL con Sensors AIDL HAL.

Differenza tra Sensors Multi-HAL 2 e Sensors HAL 2

Sensori Multi-HAL 2, disponibile su dispositivi con Android 10 o versioni successive, introduce diverse astrazioni oltre a Sensors HAL 2 per facilitare l'interazione con le API HAL. Sensors Multi-HAL 2 introduce la classe HalProxy per gestire l'implementazione dell'interfaccia Sensors HAL 2 e dell'interfaccia V2_1/SubHal (o V2_0/SubHal) per consentire a HalProxy di interagire con i sub-HAL.

L'interfaccia di ISensorsSubHal è diversa da quella di 2.1/ISensors.hal (o 2.0/ISensors.hal) per i seguenti motivi:

  • Il metodo di inizializzazione passa una classe IHalProxyCallback anziché due FMQ e ISensorsCallback.
  • Gli HAL secondari devono implementare una funzione di debug per fornire informazioni di debugging nelle segnalazioni di bug.
  • I sub-HAL devono implementare una funzione di nome in modo che il sub-HAL caricato possa essere distinto da altri sub-HAL.

La differenza principale tra i sensori Multi-HAL 2 e i sensori HAL 2 consiste nelle funzioni di inizializzazione. Anziché fornire FMQ, l'interfaccia IHalProxyCallback fornisce due metodi: uno per pubblicare eventi del sensore nel framework di gestione dei sensori e uno per creare blocchi di riattivazione. Sotto il cofano, il Multi-HAL dei sensori gestisce tutte le interazioni con le FMQ per garantire l'invio tempestivo degli eventi dei sensori per tutti i sub-HAL. Consigliamo vivamente agli HAL secondari di utilizzare il metodo createScopedWakelock per delegare l'onere del timeout dei wakelock all'HAL per i sensori e di centralizzare l'utilizzo dei wakelock in un unico wakelock comune per l'intero HAL per i sensori, in modo da ridurre al minimo le chiamate di blocco e sblocco.

Sensors Multi-HAL 2 dispone anche di alcune funzionalità di sicurezza integrate. Gestisce le situazioni in cui il valore FMQ del sensore è pieno o in cui il framework dei sensori Android si riavvia e lo stato del sensore deve essere reimpostato. Inoltre, quando gli eventi vengono pubblicati nella classe HalProxy, ma il framework del sensore non è in grado di accettarli immediatamente, il Multi-HAL dei sensori può spostarli in un thread in background per consentire il proseguimento del lavoro in tutti i sub-HAL in attesa della pubblicazione degli eventi.

Codice sorgente e implementazione di riferimento

Il codice Multi-HAL di tutti i sensori è disponibile in hardware/interfaces/sensors/common/default/2.X/multihal/. Di seguito sono riportati alcuni rimandi ad alcune risorse.

  • HalProxy.h: l'oggetto HalProxy viene creato da Sensors multi-HAL e gestisce il trasferimento dei dati dalle HAL secondarie al framework del sensore.
  • HalProxy.cpp: l'implementazione di HalProxy contiene tutta la logica necessaria per la comunicazione multiplex tra gli HAL secondari e il framework dei sensori.
  • SubHal.h: l'interfaccia ISensorsSubHal definisce l'interfaccia che gli HAL secondari devono seguire per essere compatibili con HalProxy. L'HAL secondario implementa il metodo initialize in modo che l'oggetto HalProxyCallback possa essere utilizzato per postEvents e createScopedWakelock.

    Per le implementazioni Multi-HAL 2.0, utilizza la versione 2.0 di SubHal.h.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/: questi test delle unità verificano l'implementazione di HalProxy.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/: Questo esempio di implementazione dell'HAL utilizza sensori falsi per generare dati falsi. Utile per testare il modo in cui più HAL secondari interagiscono su un dispositivo.

Implementazione

Questa sezione descrive come implementare Multi-HAL per i sensori nelle seguenti situazioni:

Utilizzo di Sensors Multi-HAL con Sensors AIDL HAL

Per consentire la funzionalità multi-HAL con l'HAL per i sensori AIDL, importa il modulo dello shim Layer AIDL Multi-HAL, che si trova in hardware/interfaces/sensors/aidl/default/multihal/. Il modulo gestisce la conversione tra i tipi di definizione HAL dei sensori AIDL e HIDL e definisce un wrapper attorno all'interfaccia multi-HAL descritta in Implementazione di sensori Multi-HAL 2.1. Il livello shim multi-HAL AIDL è compatibile con i dispositivi che implementano Sensors Multi-HAL 2.1.

Lo strato di spessore AIDL multi-HAL consente di esporre il tracker della testa e i tipi di sensori IMU ad asse limitato nei Sensors AIDL HAL. Per utilizzare questi tipi di sensori definiti dall'interfaccia HAL AIDL, imposta il campo type nella struttura SensorInfo nell'implementazione getSensorsList_2_1(). Questo è sicuro perché i campi di tipo di sensore basati su interi dell'HAL dei sensori AIDL e HIDL non si sovrappongono.

Implementare Sensors Multi-HAL 2.1

Per implementare Sensors Multi-HAL 2.1 su un nuovo dispositivo, segui questi passaggi:

  1. Implementa l'interfaccia ISensorsSubHal come descritto in SubHal.h.
  2. Implementa il metodo sensorsHalGetSubHal_2_1 in SubHal.h.
  3. Aggiungi un target cc_library_shared per creare l'HAL secondario appena implementato. Quando aggiungi il target:

    1. Assicurati che il push del target venga inviato a una qualche parte della partizione del fornitore del dispositivo.
    2. Nel file di configurazione all'indirizzo /vendor/etc/sensors/hals.conf, aggiungi il percorso della libreria su una nuova riga. Se necessario, crea il file hals.conf.

    Per un esempio di voce Android.bp per la creazione di una libreria HAL secondaria, consulta hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp.

  4. Rimuovi tutte le voci android.hardware.sensors dal manifest.xml file, che contiene l'elenco degli HAL supportati sul dispositivo.

  5. Rimuovi tutti i servizi android.hardware.sensors e i file service.rc dal file device.mk e aggiungi android.hardware.sensors@2.1-service.multihal e android.hardware.sensors@2.1-service.multihal.rc a PRODUCT_PACKAGES.

All'avvio, HalProxy si avvia, cerca il sub-HAL appena implementato e lo inizializza chiamando sensorsHalGetSubHal_2_1.

Eseguire il trasferimento da Multi-HAL 2.0 per i sensori a Multi-HAL 2.1

Per eseguire la porta da Multi-HAL 2.0 a Multi-HAL 2.1, implementa l'interfaccia SubHal e ricompila l'HAL secondario.

Queste sono le differenze tra le interfacce 2.0 e 2.1 di SubHal:

  • IHalProxyCallback utilizza i tipi creati nella versione 2.1 della specifica ISensors.hal.
  • La funzione initialize() passa un nuovo IHalProxyCallback invece di quello dell'interfaccia SubHal 2.0
  • Gli HAL secondari devono implementare getSensorsList_2_1 e injectSensorData_2_1 instead of getSensorsList e injectSensorData poiché questi metodi utilizzano i nuovi tipi aggiunti nella versione 2.1 della specifica ISensors.hal.
  • Gli HAL secondari devono esporre sensorsHalGetSubHal_2_1 anziché sensorsHalGetSubHal affinché l'HAL multiplo li consideri come HAL secondari della versione 2.1.

Porta da Sensors HAL 2.0

Quando esegui l'upgrade a Sensors Multi-HAL 2.0 da Sensors HAL 2.0, assicurati che l'implementazione di HAL soddisfi i seguenti requisiti.

Inizializzare l'HAL

I sensori HAL 2.0 hanno una funzione di inizializzazione che consente al servizio dei sensori di superare gli FMQ e un callback del sensore dinamico. In Sensori Multi-HAL 2.0, la funzione initialize() passa un singolo callback che deve essere utilizzato per pubblicare gli eventi dei sensori, ottenere i wakelock e notificare la connessione e le disconnessioni dei sensori dinamici.

Dopo gli eventi dei sensori nell'implementazione Multi-HAL

Invece di pubblicare gli eventi del sensore tramite la coda FMQ, l'HAL secondario deve scrivere gli eventi del sensore in IHalProxyCallback quando sono disponibili.

Eventi WAKE_UP

In Sensors HAL 2.0, l'HAL può gestire il blocco di attivazione per la sua implementazione. In Sensors Multi-HAL 2.0, gli HAL secondari consentono all'implementazione Multi-HAL di gestire i wakelock e possono richiedere l'acquisizione di un wakelock chiamando createScopedWakelock. È necessario acquisire e passare un blocco di riattivazione con ambito bloccato a postEvents quando si pubblicano eventi di riattivazione nell'implementazione Multi-HAL.

Sensori dinamici

Sensors Multi-HAL 2.0 richiede che onDynamicSensorsConnected e onDynamicSensorsDisconnected in IHalProxyCallback vengano chiamati ogni volta che le connessioni dei sensori dinamici cambiano. Questi callback sono disponibili come parte del puntatore IHalProxyCallback fornito tramite la funzione initialize().

Porta da Sensors HAL 1.0

Quando esegui l'upgrade a Sensors Multi-HAL 2.0 da Sensors HAL 1.0, assicurati che l'implementazione di HAL soddisfi i seguenti requisiti.

Inizializza l'HAL

La funzione initialize() deve essere supportata per stabilire il callback tra il sub-HAL e l'implementazione Multi-HAL.

Esporre i sensori disponibili

In Sensori Multi-HAL 2.0, la funzione getSensorsList() deve restituire lo stesso valore durante l'avvio di un singolo dispositivo, anche tra i sensori che l'HAL si riavvia. In questo modo il framework può tentare di ristabilire le connessioni dei sensori al riavvio del server di sistema. Il valore restituito da getSensorsList() può cambiare dopo il riavvio del dispositivo.

Dopo gli eventi dei sensori nell'implementazione Multi-HAL

In Sensors HAL 2.0, anziché attendere la chiamata di poll(), il sub-HAL deve scrivere in modo proattivo gli eventi del sensore in IHalProxyCallback ogni volta che sono disponibili.

Eventi WAKE_UP

In Sensors HAL 1.0, l'HAL può gestire il blocco di attivazione per la sua implementazione. In Sensors Multi-HAL 2.0, gli HAL secondari consentono all'implementazione Multi-HAL di gestire i wakelock e possono richiedere l'acquisizione di un wakelock chiamando createScopedWakelock. Un wakelock con ambito bloccato deve essere acquisito e passato a postEvents quando vengono pubblicati eventi di wakeup nell'implementazione Multi-HAL.

Sensori dinamici

In Sensors HAL 1.0, i sensori dinamici vengono restituiti tramite la funzione poll(). Sensors Multi-HAL 2.0 richiede che onDynamicSensorsConnected e onDynamicSensorsDisconnected in IHalProxyCallback vengano chiamati ogni volta che le connessioni dei sensori dinamici cambiano. Questi callback sono disponibili come parte del puntatore IHalProxyCallback fornito tramite la funzione initialize().

Porta da Sensors Multi-HAL 1.0

Per trasferire un'implementazione esistente da Sensors Multi-HAL 1.0, segui questi passaggi.

  1. Assicurati che la configurazione dell'HAL dei sensori si trovi in /vendor/etc/sensors/hals.conf. Potrebbe essere necessario spostare il file all'indirizzo /system/etc/sensors/hals.conf.
  2. Rimuovi tutti i riferimenti a hardware/hardware.h e hardware/sensors.h poiché non sono supportati per HAL 2.0.
  3. Porta gli HAL sub-HAL come descritto in Portabilità dai sensori Hal 1.0.
  4. Imposta i sensori Multi-HAL 2.0 come HAL designato seguendo i passaggi 3 e 4 nella sezione Implementazione di sensori Mutli-HAL 2.0.

Convalida

Esegui VTS

Dopo aver integrato uno o più HAL secondari con Sensors Multi-HAL 2.1, utilizza la Vendor Test Suite (VTS) per assicurarti che le implementazioni degli HAL secondarisoddisfano tutti i requisiti impostati dall'interfaccia HAL di Sensors.

Per eseguire solo i test dei sensori VTS quando VTS è configurato su una macchina host, esegui i seguenti comandi:

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_0Target && \
  vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsHalSensorsV2_1Target

Se stai eseguendo il livello shim AIDL Multi-HAL, esegui VtsAidlHalSensorsTargetTest.

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsAidlHalSensorsTargetTest

Esecuzione dei test delle unità

Il test delle unità in HalProxy_test.cpp testa HalProxy utilizzando HAL sub-HAL fittizi che vengono create in un'istanza nel test delle unità e non vengono caricati dinamicamente. Quando crei un nuovo HAL secondario, questi test dovrebbero essere usati come guida per aggiungere test delle unità che verificano che il nuovo HAL sia implementato correttamente.

Per eseguire i test, esegui questi comandi:

cd $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests
atest

Esegui il test con gli HAL secondari falsi

I sub-HAL falsi sono implementazioni simulati dell'interfaccia ISensorsSubHal. Gli HAL secondari espongono diversi elenchi di sensori. Quando i sensori vengono attivati, pubblicano periodicamente eventi dei sensori generati automaticamente su HalProxy in base agli intervalli specificati in una determinata richiesta di sensore.

I sub-HAL falsi possono essere utilizzati per testare il funzionamento del codice Multi-HAL completo con altri sub-HAL caricati nel sistema e per sottoporre a stress vari aspetti del codice Multi-HAL dei sensori.

Due HAL secondari falsi sono disponibili all'indirizzo hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/.

Per compilare e inviare gli HAL secondari falsi a un dispositivo, svolgi i seguenti passaggi:

  1. Esegui questi comandi per creare ed eseguire il push dei tre diversi HAL secondari falsi al dispositivo:

    $ANDROID_BUILD_TOP/hardware/interfaces/sensors/common/default/2.X/multihal/tests/
    mma
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    adb push \
      $ANDROID_BUILD_TOP/out/target/product/<device>/symbols/vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so \
      /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
  2. Aggiorna la configurazione dell'HAL dei sensori in /vendor/etc/sensors/hals.conf con i percorsi degli HAL secondari falsi.

    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config1.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config2.so
    /vendor/lib64/android.hardware.sensors@2.X-fakesubhal-config3.so
    
  3. Riavvia HalProxy e carica i nuovi sotto-HAL elencati nella configurazione.

    adb shell stop
    adb shell start

Debug…

Gli sviluppatori possono eseguire il debug del framework utilizzando il comando lshal. Per richiedere l'output di debug dell'HAL per sensori, esegui questo comando:

adb root
adb shell lshal debug android.hardware.sensors@2.1::ISensors/default

Le informazioni sullo stato corrente di HalProxy e dei relativi HAL secondari vengono quindi messe in output nel terminale. Di seguito è riportato un esempio dell'output del comando per l'oggetto HalProxy e gli HAL secondari falsi.

Internal values:
  Threads are running: true
  Wakelock timeout start time: 200 ms ago
  Wakelock timeout reset time: 73208 ms ago
  Wakelock ref count: 0
  # of events on pending write queue: 0
  # of non-dynamic sensors across all subhals: 8
  # of dynamic sensors across all subhals: 0
SubHals (2):
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2
  Name: FakeSubHal-OnChange
  Debug dump:
Available sensors:
Name: Ambient Temp Sensor
Min delay: 40000
Flags: 2
Name: Light Sensor
Min delay: 200000
Flags: 2
Name: Proximity Sensor
Min delay: 200000
Flags: 3
Name: Relative Humidity Sensor
Min delay: 40000
Flags: 2

Se il numero specificato per # of events on pending write queue è un numero elevato (1000 o più), significa che ci sono molti eventi in attesa di essere scritti nel framework dei sensori. Questo indica che il servizio dei sensori è in un deadlock o si è arrestato in modo anomalo e non sta elaborando gli eventi dei sensori oppure che un grande gruppo di eventi dei sensori è stato recentemente pubblicato da un sub-HAL.

Se il conteggio dei riferimenti al blocco di attivazione è maggiore di 0, significa che HalProxy ha acquisito un blocco di attivazione. Questo valore deve essere maggiore di 0 solo se un ScopedWakelock viene tenuto intenzionalmente premuto o se gli eventi di risveglio sono stati inviati a HalProxy e non sono stati elaborati dal framework del sensore.

Il descrittore del file passato al metodo di debug di HalProxy viene trasmesso a ogni HAL secondario, per cui gli sviluppatori devono implementare il metodo di debug nell'interfaccia ISensorsSubHal.