L'HAL (Hardware Abstraction Layer) dei sensori è l'interfaccia tra il framework dei sensori Android e i sensori di un dispositivo, ad esempio un accelerometro o un giroscopio. L'HAL Sensors definisce le funzioni che devono essere implementate per consentire al framework di controllare i sensori.
L'HAL AIDL Sensors è disponibile in Android 13 e versioni successive per i dispositivi nuovi e di cui è stato eseguito l'upgrade. L'HAL AIDL Sensors, basato su Sensors HAL 2.1, utilizza la interfaccia HAL AIDL e mostra i tipi di sensori IMU con assi limitati e tracker per la testa.
Interfaccia HAL AIDL
La fonte principale della documentazione per l'HAL AIDL Sensors si trova all'interno della definizione dell'HAL in hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.
Implementa l'HAL AIDL Sensors
Per implementare l'HAL AIDL Sensors, un oggetto deve estendere l'interfaccia ISensors
e implementare tutte le funzioni definite in
hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.
Inizializza l'HAL
L'HAL dei sensori deve essere inizializzato dal framework dei sensori Android prima di poter essere utilizzato. Il framework chiama la funzione initialize()
per fornire tre
parametri all'HAL dei sensori: 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()
deve essere la prima funzione chiamata durante l'inizializzazione
dell'HAL dei sensori.
Esporre i sensori disponibili
Per visualizzare un elenco di tutti i sensori statici disponibili nel dispositivo, utilizza la funzione
getSensorsList()
. 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 potrebbero cambiare con i riavvii del dispositivo e 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 un riavvio dell'HAL dei sensori, se i dati restituiti da getSensorsList()
indicano una variazione significativa rispetto all'elenco dei sensori recuperato prima del riavvio, il framework attiva un riavvio del runtime 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. Sebbene il riavvio del runtime Android sia fastidioso per l'utente, è obbligatorio perché il framework Android non è più in grado di soddisfare il contratto dell'API Android in base al quale i sensori statici (non dinamici) non cambiano durante il ciclo di vita di un'app. Questo potrebbe anche impedire al framework di ristabilire le richieste di sensori attive effettuate dalle app. Pertanto, i fornitori HAL sono invitati a
evitare modifiche evitabili all'elenco dei sensori.
Per garantire handle dei sensori stabili, l'HAL deve mappare in modo deterministico un determinato sensore fisico nel dispositivo al relativo handle. Sebbene non sia obbligatoria alcuna implementazione specifica da parte dell'interfaccia HAL Sensors, 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()
. 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 attivarlo, un sensore deve essere configurato con un periodo di campionamento e una latenza di reporting massima 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.
- Una tantum: il periodo di campionamento viene ignorato.
- Speciale: per maggiori dettagli, consulta Tipi di sensori.
Per saperne di più sull'interazione tra un periodo di campionamento e le modalità di generazione dei report di un sensore, consulta Modalità di report.
Latenza massima dei report
La latenza massima dei report imposta il tempo massimo in nanosecondi in cui gli eventi possono essere ritardati e archiviati nel file FIFO hardware prima di essere scritti nell'FMQ dell'evento tramite l'HAL mentre il SoC è attivo.
Il valore zero indica che gli eventi devono essere riportati non appena vengono misurati, saltando completamente il FIFO o svuotando il FIFO non appena è presente un evento del sensore nel FIFO.
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 archiviati temporaneamente nel FIFO hardware e riportati in batch, purché nessun evento venga ritardato oltre la latenza massima dei report. Tutti gli eventi a partire 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 mentre il sensore acquisisce e raggruppa i dati.
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 una singola coda FIFO per più sensori, la coda FIFO viene svuotata e l'evento di aggiornamento 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. Ciò vale per tutti i sensori, tranne quelli
one-shot.
Se flush()
viene chiamato per un sensore una tantum, flush()
deve restituire
BAD_VALUE
e non generare un evento di aggiornamento 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 di eventi attuale 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.
L'HAL AIDL Sensors supporta sia write
che writeBlocking
nella coda FMQ di eventi.
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. Al ricevimento di un evento WAKE_UP
, il framework protegge il proprio blocco di attivazione, consentendo all'HAL Sensors di rilasciare il proprio blocco di attivazione. 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 proprio wakelock
per gli eventi WAKE_UP
solo 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
nell'FMQ Wake Lock ogni volta che scrive dati nell'FMQ Wake Lock.
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 Sensors. In questo modo viene notificato il framework del nuovo sensore dinamico e viene consentito il controllo del sensore attraverso il framework e fare in modo che gli eventi del sensore vengano consumati dai clienti.
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 di funzionamento in cui gli eventi dei sensori vengono scritti in una memoria specifica anziché nell'FMQ di eventi, bypassando il framework Android Sensors. Un client che registra un canale diretto deve leggere gli eventi del sensore direttamente dalla memoria utilizzata per creare il canale diretto e non li riceverà tramite 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 al di sotto del framework.
La funzione injectSensorData()
viene normalmente utilizzata per inviare 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 l'HAL per i sensori AIDL si trovano in
hardware/interfaces/sensors/aidl/vts/.
Questi test assicurano che l'HAL Sensors sia implementato correttamente e che tutti i requisiti di ISensors.aidl
e ISensorsCallback.aidl
siano soddisfatti.
Inizializzare l'HAL
La funzione initialize()
deve essere supportata per stabilire FMQ tra il framework e HAL.
Esporre i sensori disponibili
Nell'HAL AIDL Sensors, la funzione getSensorsList()
deve restituire lo stesso valore
durante un singolo avvio del dispositivo, anche dopo i riavvii dell'HAL Sensors. 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 dei sensori in FMQ
Invece di attendere la chiamata di poll()
, nell'HAL AIDL Sensors, l'HAL debe scrivere in modo proattivo gli eventi del sensore nella coda FMQ di eventi ogni volta che sono disponibili. L'HAL è responsabile anche della scrittura dei bit corretti inEventFlag
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é nell'HAL
AIDL dei sensori l'HAL non viene più informato quando il framework ha elaborato gli eventi
scritti nella FMQ, la FMQ Wake Lock consente al framework di comunicare con l'HAL quando ha gestito gli eventi WAKE_UP
.
Nell'HAL AIDL Sensors, il blocco di attivazione protetto dall'HAL Sensors 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.
L'HAL AIDL Sensors richiede che onDynamicSensorsConnected
e
onDynamicSensorsDisconnected
in ISensorsCallback
vengano chiamati ogni volta che le connessioni
senzoriali dinamiche cambiano. Questi callback sono disponibili come parte del puntatore ISensorsCallback
fornito tramite la funzione initialize()
.
Modalità di funzionamento
La modalità DATA_INJECTION
per i sensori WAKE_UP
deve essere supportata.
Supporto di più HAL
L'HAL di Sensors AIDL supporta l'HAL multi-HAL utilizzando il framework dei sensori Multi-HAL. Per i dettagli sull'implementazione, consulta Portabilità dai sensori HAL 2.1.