Sensori HAL 2.0

L'HAL (Sensors Hardware Abstraction Layer) è l'interfaccia tra il framework dei sensori Android e i sensori di un dispositivo, ad esempio un accelerometro o un giroscopio. L'HAL dei sensori definisce le funzioni che devono essere implementate per consentire al framework di controllare i sensori.

Sensors HAL 2.0 è disponibile in Android 10 e versioni successive per i dispositivi nuovi e di cui è stato eseguito l'upgrade. L'HAL 2.0 si basa sull'HAL 1.0, ma presenta diverse differenze fondamentali che ne impediscono la compatibilità con le versioni precedenti. Sensori HAL 2.0 utilizza Fast Message Queues (FMQ) per inviare gli eventi dei sensori dall'HAL al framework dei sensori Android.

Sensors HAL 2.1 è disponibile in Android 11 e versioni successive per i dispositivi nuovi e di cui è stato eseguito l'upgrade. Sensori HAL 2.1 è un'iterazione dei sensori HAL 2.0 che espone il tipo di sensore HINGE_ANGLE e aggiorna vari metodi per accettare il tipo HINGE_ANGLE.

Interfaccia HAL 2.1

La fonte principale della documentazione per l'HAL Sensors 2.1 si trova nella definizione dell'HAL in hardware/interfaces/sensors/2.1/ISensors.hal. Se esiste un conflitto di requisiti tra questa pagina e ISensors.hal, utilizza il requisito in ISensors.hal.

Interfaccia HAL 2.0

La fonte principale della documentazione per l'HAL Sensors 2.0 si trova nella definizione dell'HAL in hardware/interfaces/sensors/2.0/ISensors.hal. Se esiste un conflitto di requisiti tra questa pagina e ISensors.hal, utilizza il requisito in ISensors.hal.

Implementa Sensors HAL 2.0 e HAL 2.1

Per implementare i sensori HAL 2.0 o 2.1, un oggetto deve estendere l'interfaccia ISensors e implementare tutte le funzioni definite in 2.0/ISensors.hal o 2.1/ISensors.hal.

Inizializza l'HAL

L'HAL Sensors deve essere inizializzato dal framework dei sensori Android prima di poter essere utilizzato. Il framework chiama la funzione initialize() per HAL 2.0 e la funzione initialize_2_1() per HAL 2.1 per fornire tre parametri all'HAL Sensors: due descrittori FMQ e un puntatore a un oggetto ISensorsCallback.

L'HAL utilizza il primo descrittore per creare l'FMQ di eventi utilizzato per scrivere gli eventi del sensore nel framework. L'HAL utilizza il secondo descrittore per creare la coda FMQ Wake Lock utilizzata per la sincronizzazione quando l'HAL rilascia il blocco di attivazione per gli eventi del WAKE_UP sensore. L'HAL deve salvare un puntatore all'oggetto ISensorsCallback in modo che sia possibile richiamare eventuali funzioni di callback necessarie.

La funzione initialize() o initialize_2_1() deve essere la prima funzione invocata durante l'inizializzazione dell'HAL Sensors.

Esporre i sensori disponibili

Per ottenere un elenco di tutti i sensori statici disponibili nel dispositivo, utilizza la funzione getSensorsList() su HAL 2.0 e la funzione getSensorsList_2_1() su HAL 2.1. Questa funzione restituisce un elenco di sensori, ciascuno identificato in modo univoco dal relativo handle. L'handle di un determinato sensore non deve cambiare quando il processo che ospita l'HAL Sensors viene riavviato. Gli handle possono cambiare durante i riavvii del dispositivo e i riavvii del server di sistema.

Se più sensori condividono lo stesso tipo di sensore e la stessa proprietà di attivazione, il primo sensore nell'elenco è chiamato sensore predefinito e viene restituito alle app che utilizzano la funzione getDefaultSensor(int sensorType, bool wakeUp).

Stabilità dell'elenco dei sensori

Dopo il riavvio di un HAL dei sensori, se i dati restituiti da getSensorsList() o getSensorsList_2_1() indicano una variazione significativa rispetto all'elenco di sensori recuperato prima del riavvio, il framework attiva un riavvio del runtime di Android. Le modifiche significative all'elenco dei sensori includono i casi in cui un sensore con un determinato handle non è presente o ha attributi modificati o in cui vengono introdotti nuovi sensori. Anche se il riavvio del runtime di Android è problematico per l'utente, è necessario perché il framework Android non è più in grado di soddisfare il contratto dell'API Android che prevede che i sensori statici (non dinamici) non cambino durante la vita di un'app. Ciò potrebbe anche impedire al framework di ristabilire le richieste dei sensori attivi effettuate dalle app. Pertanto, consigliamo ai fornitori di HAL di evitare modifiche all'elenco dei sensori evitabili.

Per garantire handle dei sensori stabili, l'HAL deve mappare in modo deterministico un determinato sensore fisico nel dispositivo al relativo handle. Anche se l'interfaccia dell'HAL per sensori non richiede alcuna implementazione specifica, gli sviluppatori hanno a disposizione una serie di opzioni per soddisfare questo requisito.

Ad esempio, l'elenco dei sensori può essere ordinato utilizzando una combinazione di attributi fissi di ciascun sensore, come fornitore, modello e tipo di sensore. Un'altra opzione si basa sul fatto che l'insieme di sensori statici del dispositivo è fisso nell'hardware, pertanto l'HAL deve sapere quando tutti i sensori previsti hanno completato l'inizializzazione prima di tornare da getSensorsList() o getSensorsList_2_1(). Questo elenco di sensori previsti può essere compilato nel file binario HAL o memorizzato in un file di configurazione nel file system e l'ordine di visualizzazione può essere utilizzato per ricavare handle stabili. Sebbene la soluzione migliore dipenda dai dettagli di implementazione specifici dell'HAL, il requisito principale è che i handle dei sensori non cambino durante i riavvii dell'HAL.

Configurare i sensori

Prima di essere attivato, un sensore deve essere configurato con un periodo di campionamento e una latenza massima dei report utilizzando la funzione batch().

Un sensore deve essere in grado di essere riconfigurato in qualsiasi momento utilizzando batch() senza la perdita dei dati del sensore.

Periodo di campionamento

Il periodo di campionamento ha un significato diverso in base al tipo di sensore che viene configurato:

  • Continuo: gli eventi del sensore vengono generati a una frequenza continua.
  • Al cambio: gli eventi vengono generati non più velocemente del periodo di campionamento e possono essere generati a una frequenza inferiore al periodo di campionamento se il valore misurato non cambia.
  • One-shot: il periodo di campionamento viene ignorato.
  • Speciale: per maggiori dettagli, consulta Tipi di sensori.

Per informazioni sull'interazione tra un periodo di campionamento e le modalità di generazione di report di un sensore, consulta Modalità di generazione di report.

Latenza massima dei report

La latenza massima dei report imposta il tempo massimo in nanosecondi per cui gli eventi possono essere ritardati e memorizzati nella coda FIFO hardware prima di essere scritti nella coda FMQ di eventi tramite l'HAL mentre il SoC è attivo.

Un valore pari a zero indica che gli eventi devono essere registrati non appena vengono misurati, ignorando del tutto la coda FIFO o svuotandola non appena un evento del sensore è presente nella coda.

Ad esempio, un accelerometro attivato a 50 Hz con una latenza massima di generazione dei report pari a zero attiva le interruzioni 50 volte al secondo quando il SoC è attivo.

Quando la latenza massima dei report è maggiore di zero, non è necessario registrare gli eventi del sensore non appena vengono rilevati. Gli eventi possono essere memorizzati temporaneamente nella coda FIFO hardware e registrati in batch, a condizione che nessun evento sia in ritardo per più della latenza massima dei report. Tutti gli eventi dal batch precedente vengono registrati e restituiti contemporaneamente. In questo modo si riduce il numero di interruzioni inviate al SoC e il SoC può passare a una modalità di risparmio energetico inferiore durante l'acquisizione e il raggruppamento dei dati in batch.

A ogni evento è associato un timestamp. Il ritardo nell'ora in cui viene registrato un evento non deve influire sul timestamp dell'evento. Il timestamp deve essere preciso e corrispondere all'ora in cui si è verificato l'evento fisicamente, non all'ora in cui è stato registrato.

Per ulteriori informazioni e requisiti relativi alla generazione di report sugli eventi dei sensori con una latenza massima non pari a zero, vedi Raggruppamento.

Attivare i sensori

Il framework attiva e disattiva i sensori utilizzando la funzione activate(). Prima di attivare un sensore, il framework deve prima configurarlo utilizzando batch().

Dopo la disattivazione di un sensore, non devono essere scritti altri eventi del sensore nella coda FMQ di eventi.

Sensori a filo

Se un sensore è configurato per aggregare i dati del sensore, il framework può forzare un svuotamento immediato degli eventi aggregati del sensore chiamando flush(). Di conseguenza, gli eventi del sensore raggruppati per l'handle del sensore specificato vengono immediatamente scritti nella coda FMQ di eventi. L'HAL Sensors deve aggiungere un evento di aggiornamento completo alla fine degli eventi del sensore scritti a seguito di una chiamata a flush().

Lo svuotamento avviene in modo asincrono (ovvero questa funzione deve restituire immediatamente). Se l'implementazione utilizza un singolo FIFO per diversi sensori, questo FIFO viene svuotato e l'evento di svuotamento completo viene aggiunto solo per il sensore specificato.

Se il sensore specificato non ha una coda FIFO (non è possibile il buffering) o se la coda FIFO era vuota al momento della chiamata, flush() deve comunque riuscire e inviare un evento di svuotamento completo per quel sensore. Questo vale per tutti i sensori diversi da quelli con acquisizione singola.

Se flush() viene richiesto per un sensore one-shot, flush() deve restituire BAD_VALUE e non generare un evento di svuotamento completo.

Scrivere gli eventi del sensore nella coda FMQ

L'Event FMQ viene utilizzato dall'HAL Sensors per inviare gli eventi del sensore nel framework del sensore Android.

La coda FMQ di eventi è una coda FMQ sincronizzata, il che significa che qualsiasi tentativo di scrivere più eventi nella coda FMQ rispetto allo spazio disponibile comporta un fallimento della scrittura. In questo caso, l'HAL deve determinare se scrivere l'insieme corrente di eventi come due gruppi più piccoli di eventi o scrivere tutti gli eventi insieme quando è disponibile spazio sufficiente.

Quando l'HAL Sensors ha scritto il numero desiderato di eventi del sensore nell'FMQ Event, l'HAL Sensors deve notificare al framework che gli eventi sono pronti scrivendo il bit EventQueueFlagBits::READ_AND_PROCESS nella funzione EventFlag::wake dell'FMQ Event. L'EventFlag può essere creato dall'FMQ evento utilizzando EventFlag::createEventFlag e la funzione getEventFlagWord() dell'FMQ evento.

I sensori HAL 2.0/2.1 supportano sia write sia writeBlocking nell'FMQ dell'evento. L'implementazione predefinita fornisce un riferimento per l'utilizzo di write. Se viene utilizzata la funzione writeBlocking, il flag readNotification deve essere impostato su EventQueueFlagBits::EVENTS_READ, che viene impostato dal framework quando legge gli eventi dall'FMQ dell'evento. Il flag di notifica della scrittura deve essere impostato su EventQueueFlagBits::READ_AND_PROCESS, che comunica al framework che gli eventi sono stati scritti nella coda FMQ degli eventi.

Eventi WAKE_UP

Gli eventi WAKE_UP sono eventi del sensore che fanno svegliare il processore dell'applicazione (AP) e gestire immediatamente l'evento. Ogni volta che viene scritto un evento WAKE_UP nella coda FMQ di eventi, l'HAL Sensors deve acquisire un blocco di attivazione per garantire che il sistema rimanga attivo finché il framework non è in grado di gestire l'evento. Alla ricezione di un evento WAKE_UP, il framework protegge il proprio wakelock, consentendo all'HAL dei sensori di rilasciare il proprio wakelock. Per sincronizzare quando l'HAL dei sensori rilascia il blocco di attivazione, utilizza la FMQ di blocco di attivazione.

L'HAL Sensors deve leggere la coda FMQ Wake Lock per determinare il numero di eventi WAKE_UP che il framework ha gestito. L'HAL deve rilasciare il blocco di attivazione solo per gli eventi WAKE_UP se il numero totale di eventi WAKE_UP non gestiti è zero. Dopo aver gestito gli eventi del sensore, il framework conteggia il numero di eventi contrassegnati come eventi WAKE_UP e riscrivi questo numero nella coda FMQ di blocco sveglia.

Il framework imposta la notifica di scrittura WakeLockQueueFlagBits::DATA_WRITTEN sulla coda FMQ di blocco risveglio ogni volta che scrive dati nella coda FMQ di blocco risveglio.

Sensori dinamici

I sensori dinamici non fanno fisicamente parte del dispositivo, ma possono essere utilizzati come input, ad esempio un gamepad con un accelerometro.

Quando è collegato un sensore dinamico, la funzione onDynamicSensorConnected in ISensorsCallback deve essere chiamata dall'HAL dei sensori. In questo modo, il framework viene informato del nuovo sensore dinamico e consente di controllarlo tramite il framework e di consentire ai client di utilizzare gli eventi del sensore.

Analogamente, quando un sensore dinamico viene scollegato, deve essere chiamata la funzione onDynamicSensorDisconnected in ISensorsCallback in modo che il framework possa rimuovere qualsiasi sensore non più disponibile.

Canale diretto

Il canale diretto è un metodo operativo in cui gli eventi dei sensori vengono scritti in una memoria specifica anziché nell'FMQ dell'evento che bypassa il framework dei sensori Android. Un client che registra un canale diretto deve leggere gli eventi del sensore direttamente dalla memoria utilizzata per creare il canale diretto e non riceverà gli eventi del sensore attraverso il framework. La funzione configDirectReport() è simile a batch() per il normale funzionamento e configura il canale di report diretto.

Le funzioni registerDirectChannel() e unregisterDirectChannel() creano o eliminano un nuovo canale diretto.

Modalità di funzionamento

La funzione setOperationMode() consente al framework di configurare un sensore in modo da poter iniettare i dati del sensore al suo interno. Questo è utile per i test, in particolare per gli algoritmi esistenti sotto il framework.

La funzione injectSensorData() in HAL 2.0 e la funzione injectSensorsData_2_1() in HAL 2.0 vengono normalmente utilizzate per inviare i parametri operativi all'HAL Sensors. La funzione può essere utilizzata anche per iniettare eventi del sensore in un sensore specifico.

Convalida

Per convalidare l'implementazione dell'HAL Sensors, esegui i test CTS e VTS del sensore.

Test CTS

I test CTS dei sensori vengono eseguiti sia nei test CTS automatici sia nell'app manuale di verifica CTS.

I test automatici si trovano in cts/tests/sensor/src/android/hardware/cts. Questi test verificano la funzionalità standard dei sensori, ad esempio l'attivazione sui sensori, il raggruppamento e le frequenze degli eventi dei sensori.

I test di CTS Verifier si trovano in cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors. Questi test richiedono l'inserimento manuale dell'operatore di test e assicurano che i sensori riportino valori accurati.

Il superamento dei test CTS è fondamentale per garantire che il dispositivo sottoposto a test soddisfi tutti i requisiti CDD.

Test VTS

I test VTS per Sensors HAL 2.0 si trovano in hardware/interfaces/sensors/2.0/vts. I test VTS per Sensors HAL 2.1 si trovano in hardware/interfaces/sensors/2.1/vts. Questi test assicurano che l'HAL Sensors sia implementato correttamente e che tutti i requisiti di ISensors.hal e ISensorsCallback.hal siano soddisfatti.

Eseguire l'upgrade a Sensors HAL 2.1 da 2.0

Quando esegui l'upgrade a Sensors HAL 2.1 da 2.0, l'implementazione HAL deve includere i metodi initialize_2_1(), getSensorsList_2_1() e injectSensorsData_2_1(), insieme ai tipi HAL 2.1. Questi metodi devono soddisfare gli stessi requisiti descritti per l'HAL 2.0 sopra.

Poiché gli HAL delle versioni secondarie devono supportare tutte le funzioni degli HAL precedenti, gli HAL 2.1 devono supportare l'inizializzazione come HAL 2.0. Per evitare la complessità del supporto di entrambe le versioni HAL, consigliamo vivamente di utilizzare Multi-HAL 2.1.

Per un esempio di come implementare il tuo HAL Sensors 2.1, consulta Sensors.h.

Eseguire l'upgrade a Sensors HAL 2.0 da 1.0

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

Inizializza l'HAL

La funzione initialize() deve essere supportata per stabilire FMQ tra il framework e HAL.

Esporre i sensori disponibili

Nei sensori HAL 2.0, la funzione getSensorsList() deve restituire lo stesso valore durante l'avvio di un singolo dispositivo, anche tra i riavvii dell'HAL per i sensori. Un nuovo requisito della funzione getSensorsList() è che deve restituire lo stesso valore durante l'avvio di un singolo dispositivo, anche dopo i riavvii dell'HAL dei sensori. In questo modo, il framework può 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.

Scrivere gli eventi del sensore nella coda FMQ

Anziché attendere la chiamata di poll(), nei sensori HAL 2.0 l'HAL deve scrivere in modo proattivo gli eventi dei sensori nell'FMQ evento ogni volta che sono disponibili eventi dei sensori. L'HAL è anche responsabile di scrivere i bit corretti in EventFlag per causare una lettura FMQ all'interno del framework.

Eventi WAKE_UP

In Sensors HAL 1.0, l'HAL era in grado di rilasciare il blocco di attivazione per qualsiasi evento WAKE_UP in qualsiasi chiamata successiva a poll() dopo che un WAKE_UP era stato inviato a poll() perché indicava che il framework aveva elaborato tutti gli eventi del sensore e aveva ottenuto un blocco di attivazione, se necessario. Poiché in Sensors HAL 2.0 l'HAL non sa più quando il framework ha elaborato gli eventi scritti nella FMQ, la FMQ Wake Lock consente al framework di comunicare all'HAL quando ha gestito gli eventi WAKE_UP.

In Sensors HAL 2.0, il blocco di attivazione protetto da Sensors HAL per gli eventi WAKE_UP deve iniziare con SensorsHAL_WAKEUP.

Sensori dinamici

I sensori dinamici sono stati restituiti utilizzando la funzione poll() in Sensors HAL 1.0. Sensors HAL 2.0 richiede che onDynamicSensorsConnected e onDynamicSensorsDisconnected in ISensorsCallback vengano chiamati ogni volta che le connessioni senzoriali dinamiche cambiano. Questi callback sono disponibili come parte del ISensorsCallback cursore fornito tramite la funzione initialize().

Modalità di funzionamento

La modalità DATA_INJECTION per i sensori WAKE_UP deve essere supportata in HAL per i sensori 2.0.

Supporto di più HAL

Sensors HAL 2.0 e 2.1 supportano il multi-HAL utilizzando il framework Sensors Multi-HAL. Per dettagli sull'implementazione, consulta Porting da Sensors HAL 1.0.