Multi-HAL per i sensori

Sensors Multi-HAL è un framework che consente alle HAL dei sensori di essere eseguite insieme ad altre HAL dei sensori. Sensors Multi-HAL carica dinamicamente le sub-HAL dei sensori memorizzate come librerie dinamiche nella partizione del fornitore e fornisce loro un oggetto di callback che può gestire la pubblicazione di eventi e l'acquisizione e il rilascio del wake lock. Una sub-HAL dei sensori è una HAL dei sensori integrata in un oggetto condiviso nella partizione del fornitore e viene utilizzata dal framework multi-HAL. Questi sub-HAL non dipendono l'uno dall'altro o dal codice multi-HAL che contiene la funzione principale per il processo.

Sensors Multi-HAL 2.1, disponibile sui dispositivi con Android 11 o versioni successive, è un'iterazione di Sensors Multi-HAL 2.0 che supporta il caricamento di sub-HAL in grado di esporre il tipo di sensore angolo della cerniera. Per supportare questo tipo di sensore, le 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 l'HAL AIDL dei sensori, puoi utilizzare il livello shim multi-HAL per consentire la funzionalità multi-HAL. Per i dettagli di implementazione, vedi Utilizzo di Sensors Multi-HAL con Sensors AIDL HAL.

Differenza tra Sensors Multi-HAL 2 e Sensors HAL 2

Sensors Multi-HAL 2, disponibile sui dispositivi con Android 10 o versioni successive, introduce diverse astrazioni sopra Sensors HAL 2 per semplificare l'interazione con le API HAL. Sensors Multi-HAL 2 introduce la classe HalProxy per gestire l'implementazione dell'interfaccia Sensors HAL 2 e l'interfaccia V2_1/SubHal (o V2_0/SubHal) per consentire a HalProxy di interagire con le 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 initialize passa una classe IHalProxyCallback anziché due FMQ e ISensorsCallback.
  • Le sub-HAL devono implementare una funzione di debug per fornire informazioni di debug nelle segnalazioni di bug.
  • Le sub-HAL devono implementare una funzione di denominazione in modo che la sub-HAL caricata possa essere distinta dalle altre sub-HAL.

La differenza principale tra Sensors Multi-HAL 2 e Sensors HAL 2 risiede nelle funzioni di inizializzazione. Anziché fornire FMQ, l'interfaccia IHalProxyCallback fornisce due metodi: uno per pubblicare eventi dei sensori nel framework dei sensori e uno per creare wake lock. A livello interno, Sensors Multi-HAL gestisce tutte le interazioni con le FMQ per garantire la distribuzione tempestiva degli eventi dei sensori per tutti gli HAL secondari. È consigliabile che le sub-HAL utilizzino il metodo createScopedWakelock per delegare l'onere del timeout dei wake lock a Sensors Multi-HAL e per centralizzare l'utilizzo dei wake lock in un unico wake lock comune per l'intera Sensors Multi-HAL, il che riduce 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 la coda di messaggi veloci del sensore è piena 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 dei sensori non è in grado di accettare gli eventi immediatamente, Sensors Multi-HAL può spostare gli eventi in un thread in background per consentire la continuazione del lavoro in tutti gli HAL secondari durante l'attesa della pubblicazione degli eventi.

Codice sorgente e implementazione di riferimento

Tutto il codice Multi-HAL dei sensori è disponibile in hardware/interfaces/sensors/common/default/2.X/multihal/. Ecco alcuni suggerimenti per alcune risorse.

  • HalProxy.h: L'oggetto HalProxy viene istanziato da Sensors multi-HAL e gestisce il passaggio dei dati dalle sub-HAL al framework dei sensori.
  • HalProxy.cpp: L'implementazione di HalProxy contiene tutta la logica necessaria per multiplexare la comunicazione tra le sub-HAL e il framework dei sensori.
  • SubHal.h: L'interfaccia ISensorsSubHal definisce l'interfaccia che le sub-HAL devono seguire per essere compatibili con HalProxy. La sub-HAL implementa il metodo initialize in modo che l'oggetto HalProxyCallback possa essere utilizzato per postEvents e createScopedWakelock.

    Per le implementazioni di 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/: Questa implementazione di sub-HAL di esempio utilizza sensori fittizi per generare dati fittizi. Utile per testare l'interazione di più sub-HAL su un dispositivo.

Implementazione

Questa sezione descrive come implementare Sensors Multi-HAL nelle seguenti situazioni:

Utilizzare Sensors Multi-HAL con Sensors AIDL HAL

Per consentire la funzionalità multi-HAL con l'HAL AIDL Sensors, importa il modulo del livello shim multi-HAL AIDL, 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 intorno all'interfaccia multi-HAL descritta in Implementazione di Sensors Multi-HAL 2.1. Il livello shim multi-HAL AIDL è compatibile con i dispositivi che implementano Sensors Multi-HAL 2.1.

Il livello shim multi-HAL AIDL consente di esporre i tipi di sensori head tracker e IMU ad assi limitati nell'HAL AIDL dei sensori. Per utilizzare questi tipi di sensore definiti dall'interfaccia AIDL HAL, imposta il campo type nello struct SensorInfo nell'implementazione di getSensorsList_2_1(). Questa operazione è sicura perché i campi del tipo di sensore basati su numeri interi delle 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 il nuovo sub-HAL implementato. Quando aggiungi la destinazione:

    1. Assicurati che il target venga inviato a una posizione nella partizione del fornitore del dispositivo.
    2. Nel file di configurazione che si trova in /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 sub-HAL, vedi hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp.

  4. Rimuovi tutte le voci android.hardware.sensors dal file manifest.xml, 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 la sub-HAL appena implementata e la inizializza chiamando sensorsHalGetSubHal_2_1.

Porta da Sensors Multi-HAL 2.0 a Multi-HAL 2.1

Per eseguire il porting da Multi-HAL 2.0 a Multi-HAL 2.1, implementa l'interfaccia SubHal e ricompila la tua sub-HAL.

Di seguito sono riportate 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 anziché quello dell'interfaccia 2.0 SubHal
  • Le sub-HAL devono implementare getSensorsList_2_1 e injectSensorData_2_1 anziché getSensorsList e injectSensorData, poiché questi metodi utilizzano i nuovi tipi aggiunti nella versione 2.1 della specifica ISensors.hal.
  • Le sub-HAL devono esporre sensorsHalGetSubHal_2_1 anziché sensorsHalGetSubHal affinché la Multi-HAL le tratti come sub-HAL di 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 HAL soddisfi i seguenti requisiti.

Inizializza l'HAL

Sensors HAL 2.0 ha una funzione di inizializzazione che consente al servizio sensore di passare FMQ e un callback del sensore dinamico. In Sensors Multi-HAL 2.0, la funzione initialize() passa un singolo callback che deve essere utilizzato per pubblicare eventi del sensore, ottenere wake lock e notificare la connessione e la disconnessione dei sensori dinamici.

Pubblica gli eventi del sensore nell'implementazione di Multi-HAL

Anziché pubblicare eventi del sensore tramite FMQ, la sub-HAL deve scrivere gli eventi del sensore in IHalProxyCallback quando sono disponibili.

Eventi WAKE_UP

In Sensors HAL 2.0, l'HAL può gestire il wake lock per la sua implementazione. In Sensors Multi-HAL 2.0, le sub-HAL consentono all'implementazione di Multi-HAL di gestire i wake lock e possono richiedere l'acquisizione di un wake lock richiamando createScopedWakelock. Un wake lock con ambito bloccato deve essere acquisito e passato a postEvents quando vengono pubblicati eventi di riattivazione nell'implementazione di Multi-HAL.

Sensori dinamici

Sensors Multi-HAL 2.0 richiede che onDynamicSensorsConnected e onDynamicSensorsDisconnected in IHalProxyCallback vengano chiamati ogni volta che cambiano le connessioni dinamiche dei sensori. 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 HAL soddisfi i seguenti requisiti.

Inizializza l'HAL

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

Esporre i sensori disponibili

In Sensors Multi-HAL 2.0, la funzione getSensorsList() deve restituire lo stesso valore durante un singolo avvio del dispositivo, anche in caso di riavvii di Sensors HAL. Ciò consente al framework di tentare di ristabilire le connessioni dei sensori se il server di sistema viene riavviato. Il valore restituito da getSensorsList() può cambiare dopo il riavvio del dispositivo.

Pubblica gli eventi del sensore nell'implementazione di Multi-HAL

In Sensors HAL 2.0, anziché attendere la chiamata di poll(), la 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 wake lock per la sua implementazione. In Sensors Multi-HAL 2.0, le sub-HAL consentono all'implementazione di Multi-HAL di gestire i wake lock e possono richiedere l'acquisizione di un wake lock richiamando createScopedWakelock. Un wake lock con ambito bloccato deve essere acquisito e passato a postEvents quando vengono pubblicati eventi di riattivazione nell'implementazione di 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 cambiano le connessioni dinamiche dei sensori. Questi callback sono disponibili come parte del puntatore IHalProxyCallback fornito tramite la funzione initialize().

Porta da Sensors Multi-HAL 1.0

Per eseguire il porting di un'implementazione esistente da Sensors Multi-HAL 1.0, segui questi passaggi.

  1. Assicurati che la configurazione HAL dei sensori si trovi in /vendor/etc/sensors/hals.conf. Potrebbe essere necessario spostare il file che si trova in /system/etc/sensors/hals.conf.
  2. Rimuovi tutti i riferimenti a hardware/hardware.h e hardware/sensors.h in quanto non sono supportati per HAL 2.0.
  3. Trasferisci le sub-HAL delle porte come descritto in Porting da Sensors Hal 1.0.
  4. Imposta Sensors Multi-HAL 2.0 come HAL designato seguendo i passaggi 3 e 4 della sezione Implementazione di Sensors Multi-HAL 2.0.

Convalida

Esegui VTS

Dopo aver integrato uno o più sub-HAL con Sensors Multi-Hal 2.1, utilizza la Vendor Test Suite (VTS) per assicurarti che le implementazioni dei sub-HAL soddisfino tutti i requisiti stabiliti dall'interfaccia HAL di Sensors.

Per eseguire solo i test VTS dei sensori 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 esegui 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

Esegui test delle unità

I test delle unità in HalProxy_test.cpp test HalProxy utilizzano sub-HAL falsi che vengono istanziati nel test delle unità e non vengono caricati dinamicamente. Quando crei una nuova sub-HAL, questi test devono fungere da guida su come aggiungere test unitari che verifichino che la nuova sub-HAL sia implementata correttamente.

Per eseguire i test, esegui questi comandi:

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

Testare con le HAL secondarie fittizie

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

Le sub-HAL false possono essere utilizzate per testare il funzionamento del codice Multi-HAL completo con altre sub-HAL caricate nel sistema e per mettere alla prova vari aspetti del codice Multi-HAL dei sensori.

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

Per creare e inviare le sub-HAL fittizie a un dispositivo, segui questi passaggi:

  1. Esegui i seguenti comandi per creare ed eseguire il push dei tre diversi sub-HAL fittizi sul 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 HAL dei sensori in /vendor/etc/sensors/hals.conf con i percorsi per le sub-HAL fittizie.

    /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 sub-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 Sensors, esegui questo comando:

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

Le informazioni sullo stato attuale di HalProxy e dei relativi sub-HAL vengono quindi output nel terminale. Di seguito è riportato un esempio dell'output del comando per l'oggetto HalProxy e le false sub-HAL.

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. Ciò indica che il servizio sensore è in deadlock o si è arrestato in modo anomalo e non elabora gli eventi sensore oppure che di recente è stato pubblicato un batch di grandi dimensioni di eventi sensore da una sub-HAL.

Se il conteggio dei riferimenti del wake lock è maggiore di 0, significa che HalProxy ha acquisito un wake lock. Deve essere maggiore di 0 solo se è in corso una ScopedWakelock intenzionale o se gli eventi di riattivazione sono stati inviati a HalProxy e non sono stati elaborati dal framework dei sensori.

Il descrittore di file passato al metodo di debug di HalProxy viene passato a ogni sub-HAL, pertanto gli sviluppatori devono implementare il metodo di debug come parte dell'interfaccia ISensorsSubHal.