L'Hardware Abstraction Layer (HAL) dei sensori è l'interfaccia tra il framework dei sensori Android e i sensori di un dispositivo, come un accelerometro o un giroscopio. L'HAL dei sensori definisce le funzioni che devono essere implementate per consentire al framework di controllare i sensori.
L'HAL AIDL dei sensori è disponibile in Android 13 e versioni successive per i dispositivi nuovi e aggiornati. L'HAL AIDL dei sensori, basato su HAL dei sensori 2.1, utilizza l'interfaccia HAL AIDL ed espone i tipi di sensori di rilevamento della testa e IMU ad asse limitato.
Interfaccia HAL AIDL
La fonte principale di documentazione per l'HAL AIDL dei sensori si trova nella definizione HAL all'indirizzo hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.
Implementa l'HAL Sensors AIDL
Per implementare l'HAL Sensors AIDL, 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'Event FMQ utilizzato per scrivere gli eventi del sensore nel framework. L'HAL utilizza il secondo descrittore per creare la FMQ Wake
Lock utilizzata per sincronizzare il momento in cui l'HAL rilascia il wake lock per gli eventi del sensore WAKE_UP
. L'HAL deve salvare un puntatore all'oggetto ISensorsCallback
in modo che
possano essere richiamate le 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 ottenere un elenco di tutti i sensori statici disponibili nel dispositivo, utilizza la funzione
getSensorsList()
. Questa funzione restituisce un elenco di sensori, ognuno
identificato in modo univoco dal proprio handle. L'handle di un determinato sensore non deve cambiare
quando viene riavviato il processo che ospita l'HAL dei sensori. Gli handle potrebbero cambiare in seguito
ai riavvii del dispositivo e ai riavvii del server di sistema.
Se più sensori condividono lo stesso tipo di sensore e la stessa proprietà di riattivazione, 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 Sensors HAL, se i dati restituiti da getSensorsList()
indicano una variazione significativa rispetto all'elenco dei sensori recuperato prima del
riavvio, il framework attiva un riavvio di
Android Runtime. Le modifiche significative all'elenco dei sensori includono i casi in cui un
sensore con un determinato handle è mancante o ha modificato gli attributi oppure in cui vengono introdotti nuovi
sensori. Sebbene il riavvio di Android Runtime sia un'operazione che disturba l'utente, è necessario perché il framework Android non può più rispettare il contratto API Android secondo cui i sensori statici (non dinamici) non cambiano durante il ciclo di vita di un'app. Ciò potrebbe anche impedire al framework di ristabilire le richieste di sensori attivi effettuate dalle app. Pertanto, ai fornitori HAL si consiglia di
evitare modifiche evitabili all'elenco dei sensori.
Per garantire la stabilità degli handle dei sensori, l'HAL deve mappare in modo deterministico un determinato sensore fisico nel dispositivo al suo handle. Sebbene l'interfaccia HAL dei sensori non imponga un'implementazione specifica, gli sviluppatori hanno a disposizione diverse opzioni per soddisfare questo requisito.
Ad esempio, l'elenco dei sensori può essere ordinato utilizzando una combinazione degli attributi fissi di ciascun sensore, come fornitore, modello e tipo di sensore. Un'altra opzione si basa sul fatto che il set di sensori statici del dispositivo è fisso nell'hardware, quindi l'HAL deve sapere quando tutti i sensori previsti hanno completato l'inizializzazione prima di restituire il valore da getSensorsList()
. Questo elenco di
sensori previsti può essere compilato nel binario HAL o archiviato in un
file di configurazione nel file system e l'ordine di visualizzazione può essere utilizzato
per derivare handle stabili. Sebbene la soluzione migliore dipenda dai dettagli di implementazione specifici dell'HAL, il requisito fondamentale è che gli handle dei sensori non cambino al riavvio dell'HAL.
Configurare i sensori
Prima di essere attivato, un sensore deve essere configurato con un periodo di campionamento e una latenza massima di reporting utilizzando la funzione batch()
.
Un sensore deve poter essere riconfigurato in qualsiasi momento utilizzando batch()
senza la
perdita di dati.
Periodo di campionamento
Il periodo di campionamento ha un significato diverso a seconda del tipo di sensore che viene configurato:
- Continuo: gli eventi del sensore vengono generati a una velocità continua.
- Al cambio: gli eventi vengono generati a una velocità non superiore al periodo di campionamento e potrebbero essere generati a una velocità inferiore al periodo di campionamento se il valore misurato non cambia.
- Una tantum: il periodo di campionamento viene ignorato.
- Speciale: per maggiori dettagli, vedi Tipi di sensori.
Per informazioni sull'interazione tra un periodo di campionamento e le modalità di report di un sensore, consulta Modalità di report.
Latenza massima del report
La latenza massima dei report imposta il tempo massimo in nanosecondi in cui gli eventi possono essere ritardati e archiviati nella FIFO hardware prima di essere scritti nell'FMQ eventi tramite l'HAL mentre il SoC è attivo.
Un valore pari a zero indica che gli eventi devono essere segnalati non appena vengono misurati, saltando del tutto la coda FIFO o svuotandola non appena un evento del sensore è presente nella coda FIFO.
Ad esempio, un accelerometro attivato a 50 Hz con una latenza massima di reporting di zero genera interruzioni 50 volte al secondo quando il SoC è attivo.
Quando la latenza massima di reporting è maggiore di zero, gli eventi del sensore non devono essere segnalati non appena vengono rilevati. Gli eventi possono essere memorizzati temporaneamente nella FIFO hardware e segnalati in batch, a condizione che nessun evento venga ritardato di più della latenza massima di reporting. 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à a basso consumo mentre il sensore acquisisce e raggruppa i dati.
A ogni evento è associato un timestamp. Il ritardo nell'ora in cui viene segnalato un evento non deve influire sul timestamp dell'evento. Il timestamp deve essere accurato e corrispondere all'ora in cui si è verificato fisicamente l'evento, non all'ora in cui è stato segnalato.
Per ulteriori informazioni e requisiti sulla segnalazione di eventi dei sensori con latenza di segnalazione massima diversa da zero, vedi Batching.
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, gli eventi aggiuntivi del sensore non devono essere scritti nella FMQ eventi.
Sensori per scarico
Se un sensore è configurato per raggruppare i dati, il framework può forzare
lo svuotamento immediato degli eventi del sensore raggruppati chiamando flush()
. In questo modo gli eventi dei sensori batch per l'handle del sensore specificato vengono scritti immediatamente nella FMQ eventi. L'HAL dei sensori deve aggiungere un evento di svuotamento completato
alla fine degli eventi del sensore scritti in seguito a 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, questa viene svuotata e l'evento di completamento dello svuotamento viene aggiunto solo per il sensore specificato.
Se il sensore specificato non ha FIFO (nessun buffering possibile) o se il FIFO era
vuoto al momento della chiamata, flush()
deve comunque riuscire e inviare un evento di completamento
dello svuotamento per quel sensore. Questo vale per tutti i sensori diversi da quelli
one-shot.
Se flush()
viene chiamato per un sensore one-shot, flush()
deve restituire
BAD_VALUE
e non generare un evento di completamento dello scarico.
Scrivere eventi sensore nella FMQ
La coda di messaggi veloce per gli eventi viene utilizzata da Sensors HAL per inserire gli eventi dei sensori nel framework dei sensori Android.
La FMQ eventi è una FMQ sincronizzata, il che significa che qualsiasi tentativo di scrivere più eventi nella FMQ rispetto allo spazio disponibile comporta un errore di 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 dei sensori ha scritto il numero desiderato di eventi del sensore
nella FMQ eventi, deve notificare al framework che gli eventi sono pronti
scrivendo il bit EventQueueFlagBits::READ_AND_PROCESS
nella funzione
EventFlag::wake
della FMQ eventi. EventFlag può essere creato da Event FMQ
utilizzando EventFlag::createEventFlag
e la funzione getEventFlagWord()
di Event FMQ.
L'HAL AIDL dei sensori supporta sia write
sia writeBlocking
nella FMQ 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 dalla FMQ eventi. Il flag di notifica di scrittura deve essere impostato su
EventQueueFlagBits::READ_AND_PROCESS
, che comunica al framework che gli eventi
sono stati scritti nella FMQ eventi.
Eventi WAKE_UP
Gli eventi WAKE_UP
sono eventi del sensore che causano l'attivazione del processore dell'applicazione (AP) e la gestione immediata dell'evento. Ogni volta che viene scritto un evento WAKE_UP
nella FMQ eventi, la HAL dei sensori deve acquisire un wake lock 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 acquisisce il proprio wake lock, consentendo all'HAL dei sensori di rilasciare il proprio wake lock. Per sincronizzare il momento in cui l'HAL dei sensori
rilascia il wake lock, utilizza la FMQ wake lock.
L'HAL dei sensori deve leggere la FMQ di Wake Lock per determinare il numero di eventi WAKE_UP
gestiti dal framework. L'HAL deve rilasciare il wake lock
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 conta il numero di eventi
contrassegnati come eventi WAKE_UP
e scrive questo numero nel FMQ di Wake Lock.
Il framework imposta la notifica di scrittura WakeLockQueueFlagBits::DATA_WRITTEN
sulla FMQ di Wake Lock ogni volta che scrive dati nella FMQ di Wake Lock.
Sensori dinamici
I sensori dinamici non fanno fisicamente parte del dispositivo, ma possono essere utilizzati come input per il dispositivo, ad esempio un gamepad con un accelerometro.
Quando è collegato un sensore dinamico, la funzione onDynamicSensorConnected
in
ISensorsCallback
deve essere chiamata da Sensors HAL. In questo modo, il framework viene informato del nuovo sensore dinamico e consente di controllarlo tramite il framework e di far sì che gli eventi del sensore vengano utilizzati dai client.
Allo stesso modo, quando un sensore dinamico viene disconnesso, 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 del sensore vengono scritti in
una memoria specifica anziché nella FMQ eventi, bypassando l'Android Sensors
Framework. 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 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à operative
La funzione setOperationMode()
consente al framework di configurare un sensore
in modo che possa inserire i dati del sensore nel sensore. Questo è utile per i test, soprattutto per gli algoritmi che esistono al di sotto del framework.
La funzione injectSensorData()
viene normalmente utilizzata per inserire parametri operativi
nell'HAL dei sensori. La funzione può essere utilizzata anche per inserire eventi
del sensore in un sensore specifico.
Convalida
Per convalidare l'implementazione dell'HAL dei sensori, esegui i test CTS e VTS dei sensori.
Test CTS
I test CTS dei sensori sono disponibili sia nei test CTS automatizzati sia nell'app CTS Verifier manuale.
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 dei sensori, il batching e le frequenze degli eventi dei sensori.
I test CTS Verifier si trovano in cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors. Questi test richiedono l'inserimento manuale da parte dell'operatore del test e garantiscono che i sensori riportino valori accurati.
Il superamento dei test CTS è fondamentale per garantire che il dispositivo in esame soddisfi tutti i requisiti CDD.
Test VTS
I test VTS per l'HAL AIDL dei sensori si trovano in
hardware/interfaces/sensors/aidl/vts/.
Questi test assicurano che l'HAL dei sensori sia implementato correttamente e che tutti i requisiti all'interno di ISensors.aidl
e ISensorsCallback.aidl
siano soddisfatti correttamente.
Inizializza l'HAL
La funzione initialize()
deve essere supportata per stabilire FMQ tra il framework e HAL.
Esporre i sensori disponibili
Nella HAL AIDL dei sensori, la funzione getSensorsList()
deve restituire lo stesso valore
durante un singolo avvio del dispositivo, anche in caso di riavvii della HAL dei sensori. Un nuovo requisito
della funzione getSensorsList()
è che 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.
Scrivere eventi sensore nella FMQ
Anziché attendere la chiamata di poll()
, nell'HAL Sensors AIDL, l'HAL Sensors
deve scrivere in modo proattivo gli eventi del sensore nell'Event FMQ ogni volta che sono disponibili. L'HAL è anche responsabile della scrittura dei 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 proprio wake lock per qualsiasi evento WAKE_UP
in qualsiasi chiamata successiva a poll()
dopo la pubblicazione di un WAKE_UP
in
poll()
perché ciò indicava che il framework aveva elaborato tutti gli eventi del sensore e aveva ottenuto un wake lock, se necessario. Poiché nell'HAL AIDL
dei sensori, l'HAL non viene più avvisato 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
.
Nell'HAL AIDL dei sensori, il blocco di riattivazione protetto dall'HAL dei sensori 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 dei sensori richiede che onDynamicSensorsConnected
e
onDynamicSensorsDisconnected
in ISensorsCallback
vengano chiamati ogni volta che cambiano le connessioni
dei sensori dinamici. Questi callback sono disponibili come parte del
puntatore ISensorsCallback
fornito tramite la funzione initialize()
.
Modalità operative
Deve essere supportata la modalità DATA_INJECTION
per i sensori WAKE_UP
.
Supporto di più HAL
L'HAL Sensors AIDL supporta più HAL utilizzando il framework Sensors Multi-HAL. Per i dettagli di implementazione, vedi Porting da Sensors HAL 2.1.