Die Sensors Hardware Abstraction Layer (HAL) ist die Schnittstelle zwischen dem Android-Sensor-Framework und den Sensoren eines Geräts, z. B. einem Beschleunigungsmesser oder Gyroskop. Die Sensors HAL definiert die Funktionen, die implementiert werden müssen, damit das Framework die Sensoren steuern kann.
Die Sensors AIDL HAL ist in Android 13 und höher für neue und aktualisierte Geräte verfügbar. Die Sensors AIDL HAL, die auf Sensors HAL 2.1 basiert, verwendet die AIDL-HAL-Schnittstelle und macht die Sensortypen „Head Tracker“ und „IMU mit eingeschränkten Achsen“ verfügbar.
AIDL-HAL-Schnittstelle
Die Hauptquelle für die Dokumentation der Sensors AIDL HAL ist die HAL-Definition unter hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl.
Sensors AIDL HAL implementieren
Um die Sensors AIDL HAL zu implementieren, muss ein Objekt die ISensors
-Schnittstelle erweitern und alle Funktionen implementieren, die in hardware/interfaces/sensors/aidl/android/hardware/sensors/ISensors.aidl definiert sind.
HAL initialisieren
Das Sensors HAL muss vom Android-Sensor-Framework initialisiert werden, bevor es verwendet werden kann. Das Framework ruft die Funktion initialize()
auf, um dem Sensors HAL drei Parameter bereitzustellen: zwei FMQ-Deskriptoren und einen Zeiger auf ein ISensorsCallback
-Objekt.
Das HAL verwendet den ersten Deskriptor, um den Event-FMQ zu erstellen, mit dem Sensorereignisse in das Framework geschrieben werden. Das HAL verwendet den zweiten Deskriptor, um das Wake Lock-FMQ zu erstellen, das zur Synchronisierung verwendet wird, wenn das HAL sein Wake Lock für WAKE_UP
-Sensorereignisse freigibt. Das HAL muss einen Zeiger auf das ISensorsCallback
-Objekt speichern, damit alle erforderlichen Callback-Funktionen aufgerufen werden können.
Die Funktion initialize()
muss die erste Funktion sein, die beim Initialisieren des Sensors HAL aufgerufen wird.
Verfügbare Sensoren bereitstellen
Wenn Sie eine Liste aller verfügbaren statischen Sensoren auf dem Gerät abrufen möchten, verwenden Sie die Funktion getSensorsList()
. Diese Funktion gibt eine Liste von Sensoren zurück, die jeweils durch ihr Handle eindeutig identifiziert werden. Der Handle für einen bestimmten Sensor darf sich nicht ändern, wenn der Prozess, der die Sensors HAL hostet, neu gestartet wird. Aliasse können sich bei Geräte- und Systemserverneustarts ändern.
Wenn mehrere Sensoren denselben Sensortyp und dieselbe Wake-up-Eigenschaft haben, wird der erste Sensor in der Liste als Standardsensor bezeichnet und an Apps zurückgegeben, die die Funktion getDefaultSensor(int sensorType, bool wakeUp)
verwenden.
Stabilität der Sensorliste
Wenn die von getSensorsList()
zurückgegebenen Daten nach einem Neustart des Sensors HAL eine erhebliche Änderung im Vergleich zur Sensorliste aufweisen, die vor dem Neustart abgerufen wurde, löst das Framework einen Neustart der Android-Laufzeit aus. Zu den wesentlichen Änderungen an der Sensorliste gehören Fälle, in denen ein Sensor mit einem bestimmten Handle fehlt oder sich seine Attribute geändert haben oder in denen neue Sensoren eingeführt werden. Das Neustarten der Android-Laufzeit ist zwar störend für den Nutzer, aber erforderlich, da das Android-Framework den Android-API-Vertrag nicht mehr erfüllen kann, der besagt, dass sich statische (nicht dynamische) Sensoren während der Lebensdauer einer App nicht ändern. Dies kann auch verhindern, dass das Framework aktive Sensoranfragen von Apps wiederherstellt. Daher wird HAL-Anbietern empfohlen, vermeidbare Änderungen an der Sensorliste zu verhindern.
Damit die Sensor-Handles stabil sind, muss das HAL einen bestimmten physischen Sensor im Gerät deterministisch seinem Handle zuordnen. Obwohl die Sensors HAL-Schnittstelle keine bestimmte Implementierung vorschreibt, haben Entwickler mehrere Optionen, um diese Anforderung zu erfüllen.
Die Sensorliste kann beispielsweise anhand einer Kombination der festen Attribute jedes Sensors sortiert werden, z. B. Anbieter, Modell und Sensortyp. Eine weitere Option beruht auf der Tatsache, dass die statischen Sensoren des Geräts in der Hardware festgelegt sind. Daher muss die HAL wissen, wann alle erwarteten Sensoren initialisiert wurden, bevor sie von getSensorsList()
zurückkehrt. Diese Liste der erwarteten Sensoren kann in die HAL-Binärdatei kompiliert oder in einer Konfigurationsdatei im Dateisystem gespeichert werden. Die Reihenfolge des Auftretens kann verwendet werden, um stabile Handles abzuleiten. Die beste Lösung hängt von den spezifischen Implementierungsdetails Ihres HAL ab. Die wichtigste Anforderung ist jedoch, dass sich die Sensor-Handles bei HAL-Neustarts nicht ändern.
Sensoren konfigurieren
Bevor ein Sensor aktiviert wird, muss er mit einem Erfassungszeitraum und einer maximalen Meldeverzögerung konfiguriert werden. Verwenden Sie dazu die Funktion batch()
.
Ein Sensor muss jederzeit über batch()
neu konfiguriert werden können, ohne dass Sensordaten verloren gehen.
Stichprobenzeitraum
Der Erfassungszeitraum hat je nach konfiguriertem Sensortyp eine andere Bedeutung:
- Kontinuierlich: Sensorereignisse werden kontinuierlich generiert.
- Bei Änderung: Ereignisse werden nicht schneller als im Stichprobenzeitraum generiert. Wenn sich der gemessene Wert nicht ändert, kann die Rate, mit der Ereignisse generiert werden, auch langsamer als im Stichprobenzeitraum sein.
- Einmalig: Der Stichprobenzeitraum wird ignoriert.
- Spezial: Weitere Informationen finden Sie unter Sensortypen.
Weitere Informationen zur Interaktion zwischen einem Erfassungszeitraum und den Berichtsmodi eines Sensors finden Sie unter Berichtsmodi.
Maximale Latenz bei der Berichterstellung
Die maximale Meldeverzögerung gibt die maximale Zeit in Nanosekunden an, um die Ereignisse verzögert und im Hardware-FIFO gespeichert werden können, bevor sie über das HAL in den Event-FMQ geschrieben werden, während der SoC aktiv ist.
Ein Wert von null bedeutet, dass die Ereignisse gemeldet werden müssen, sobald sie erfasst werden. Das FIFO wird entweder ganz übersprungen oder geleert, sobald ein Ereignis vom Sensor im FIFO vorhanden ist.
Ein Beschleunigungsmesser, der mit 50 Hz aktiviert ist und eine maximale Meldeverzögerung von null hat, löst beispielsweise 50 Unterbrechungen pro Sekunde aus, wenn der SoC aktiv ist.
Wenn die maximale Meldeverzögerung größer als null ist, müssen Sensorereignisse nicht sofort nach der Erkennung gemeldet werden. Ereignisse können vorübergehend im Hardware-FIFO gespeichert und in Batches gemeldet werden, sofern kein Ereignis um mehr als die maximale Meldeverzögerung verzögert wird. Alle Ereignisse seit dem vorherigen Batch werden aufgezeichnet und gleichzeitig zurückgegeben. Dadurch wird die Anzahl der an den SoC gesendeten Interrupts reduziert und der SoC kann in einen Energiesparmodus wechseln, während der Sensor Daten erfasst und in Batches zusammenfasst.
Jedem Ereignis ist ein Zeitstempel zugeordnet. Das Verzögern des Zeitpunkts, zu dem ein Ereignis gemeldet wird, darf sich nicht auf den Zeitstempel des Ereignisses auswirken. Der Zeitstempel muss korrekt sein und dem Zeitpunkt entsprechen, zu dem das Ereignis tatsächlich stattgefunden hat, nicht dem Zeitpunkt, zu dem es gemeldet wurde.
Weitere Informationen und Anforderungen zum Melden von Sensorereignissen mit einer maximalen Meldeverzögerung ungleich null finden Sie unter Batching.
Sensoren aktivieren
Das Framework aktiviert und deaktiviert Sensoren mit der Funktion activate()
.
Bevor ein Sensor aktiviert werden kann, muss das Framework ihn zuerst mit batch()
konfigurieren.
Nachdem ein Sensor deaktiviert wurde, dürfen keine zusätzlichen Sensorereignisse von diesem Sensor in die Event FMQ geschrieben werden.
Unterputzsensoren
Wenn ein Sensor so konfiguriert ist, dass Sensordaten in Batches verarbeitet werden, kann das Framework durch Aufrufen von flush()
ein sofortiges Leeren der Batch-Sensorereignisse erzwingen. Dadurch werden die Batch-Sensorereignisse für das angegebene Sensor-Handle sofort in die Event-FMQ geschrieben. Die Sensors HAL muss am Ende der Sensorereignisse, die als Ergebnis eines Aufrufs von flush()
geschrieben werden, ein Flush-Complete-Ereignis anhängen.
Das Leeren erfolgt asynchron. Das bedeutet, dass diese Funktion sofort zurückgegeben werden muss. Wenn in der Implementierung ein einzelner FIFO für mehrere Sensoren verwendet wird, wird dieser FIFO geleert und das Ereignis „Flush abgeschlossen“ wird nur für den angegebenen Sensor hinzugefügt.
Wenn der angegebene Sensor keinen FIFO-Speicher hat (keine Pufferung möglich) oder der FIFO-Speicher zum Zeitpunkt des Aufrufs leer war, muss flush()
trotzdem erfolgreich ausgeführt werden und ein Ereignis für das Abschließen des Flush-Vorgangs für diesen Sensor gesendet werden. Das gilt für alle Sensoren außer One-Shot-Sensoren.
Wenn flush()
für einen One-Shot-Sensor aufgerufen wird, muss flush()
BAD_VALUE
zurückgeben und kein Flush-Complete-Ereignis generieren.
Sensorereignisse in die FMQ schreiben
Die Event-FMQ wird von der Sensors HAL verwendet, um Sensorereignisse in das Android-Sensor-Framework zu übertragen.
Die Event-FMQ ist eine synchronisierte FMQ. Das bedeutet, dass jeder Versuch, mehr Ereignisse in die FMQ zu schreiben, als der verfügbare Speicherplatz zulässt, zu einem fehlgeschlagenen Schreibvorgang führt. In diesem Fall sollte das HAL entscheiden, ob der aktuelle Satz von Ereignissen als zwei kleinere Gruppen von Ereignissen oder als alle Ereignisse zusammen geschrieben werden soll, wenn genügend Speicherplatz verfügbar ist.
Wenn die Sensors HAL die gewünschte Anzahl von Sensorereignissen in die Event-FMQ geschrieben hat, muss sie das Framework benachrichtigen, dass die Ereignisse bereit sind. Dazu muss sie das EventQueueFlagBits::READ_AND_PROCESS
-Bit in die EventFlag::wake
-Funktion der Event-FMQ schreiben. Das EventFlag kann aus dem Event FMQ mit EventFlag::createEventFlag
und der getEventFlagWord()
-Funktion des Event FMQ erstellt werden.
Die Sensors AIDL HAL unterstützt sowohl write
als auch writeBlocking
im Event-FMQ.
Die Standardimplementierung bietet eine Referenz für die Verwendung von write
. Wenn die Funktion writeBlocking
verwendet wird, muss das Flag readNotification
auf EventQueueFlagBits::EVENTS_READ
gesetzt sein. Das Framework legt diesen Wert fest, wenn es Ereignisse aus der Event FMQ liest. Das Flag für Schreibbenachrichtigungen muss auf EventQueueFlagBits::READ_AND_PROCESS
gesetzt sein. Dadurch wird das Framework darüber informiert, dass Ereignisse in die Event FMQ geschrieben wurden.
WAKE_UP-Ereignisse
WAKE_UP
-Ereignisse sind Sensorereignisse, die dazu führen, dass der Anwendungsprozessor (AP) aktiviert wird und das Ereignis sofort verarbeitet. Immer wenn ein WAKE_UP
-Ereignis in die Event-FMQ geschrieben wird, muss die Sensors-HAL ein Wake Lock sichern, damit das System so lange aktiv bleibt, bis das Framework das Ereignis verarbeiten kann. Beim Empfang eines WAKE_UP
-Ereignisses sichert das Framework seinen eigenen Wake Lock, sodass das Sensors HAL seinen Wake Lock freigeben kann. Verwenden Sie das Wake Lock FMQ, um die Synchronisierung zu starten, wenn das Sensors HAL sein Wake Lock freigibt.
Die Sensors HAL muss das Wake Lock FMQ lesen, um die Anzahl der WAKE_UP
-Ereignisse zu ermitteln, die vom Framework verarbeitet wurden. Das HAL sollte sein Wake Lock für WAKE_UP
-Ereignisse nur freigeben, wenn die Gesamtzahl der nicht verarbeiteten WAKE_UP
-Ereignisse null ist.
Nach der Verarbeitung von Sensorereignissen zählt das Framework die Anzahl der Ereignisse, die als WAKE_UP
-Ereignisse gekennzeichnet sind, und schreibt diese Zahl zurück in die Wake Lock FMQ.
Das Framework legt die WakeLockQueueFlagBits::DATA_WRITTEN
-Schreibbenachrichtigung für die Wake Lock-FMQ fest, wenn Daten in die Wake Lock-FMQ geschrieben werden.
Dynamische Sensoren
Dynamische Sensoren sind Sensoren, die nicht physisch Teil des Geräts sind, aber als Eingabe für das Gerät verwendet werden können, z. B. ein Gamepad mit einem Beschleunigungsmesser.
Wenn ein dynamischer Sensor verbunden ist, muss die Funktion onDynamicSensorConnected
in ISensorsCallback
über die Sensors HAL aufgerufen werden. Dadurch wird das Framework über den neuen dynamischen Sensor informiert und der Sensor kann über das Framework gesteuert werden. Außerdem können die Ereignisse des Sensors von Clients genutzt werden.
Wenn ein dynamischer Sensor getrennt wird, muss die Funktion onDynamicSensorDisconnected
in ISensorsCallback
aufgerufen werden, damit das Framework alle Sensoren entfernen kann, die nicht mehr verfügbar sind.
Direkter Channel
Der direkte Kanal ist eine Betriebsmethode, bei der Sensorereignisse in einen bestimmten Speicher geschrieben werden, anstatt in die Event FMQ. Dabei wird das Android Sensors Framework umgangen. Ein Client, der einen direkten Kanal registriert, muss die Sensorereignisse direkt aus dem Speicher lesen, der zum Erstellen des direkten Kanals verwendet wurde. Er empfängt die Sensorereignisse nicht über das Framework. Die Funktion configDirectReport()
ähnelt batch()
für den normalen Betrieb und konfiguriert den direkten Meldekanal.
Mit den Funktionen registerDirectChannel()
und unregisterDirectChannel()
wird ein neuer direkter Kanal erstellt oder gelöscht.
Betriebsmodi
Mit der Funktion setOperationMode()
kann das Framework einen Sensor so konfigurieren, dass Sensordaten in den Sensor eingefügt werden können. Das ist nützlich für Tests, insbesondere für Algorithmen, die unter dem Framework liegen.
Die Funktion injectSensorData()
wird normalerweise verwendet, um Betriebsparameter in die Sensors HAL zu übertragen. Die Funktion kann auch verwendet werden, um Sensorereignisse in einen bestimmten Sensor einzufügen.
Zertifizierungsstufe
Führen Sie die Sensor-CTS- und VTS-Tests aus, um Ihre Implementierung des Sensors HAL zu validieren.
CTS-Tests
Sensor-CTS-Tests sind sowohl in automatisierten CTS-Tests als auch in der manuellen CTS-Verifier-App verfügbar.
Die automatisierten Tests befinden sich unter cts/tests/sensor/src/android/hardware/cts. Mit diesen Tests wird die Standardfunktionalität von Sensoren überprüft, z. B. das Aktivieren von Sensoren, das Batching und die Raten von Sensorereignissen.
Die CTS Verifier-Tests befinden sich unter cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors. Für diese Tests ist eine manuelle Eingabe durch den Tester erforderlich. Sie sorgen dafür, dass die Sensoren genaue Werte liefern.
Das Bestehen der CTS-Tests ist entscheidend, um sicherzustellen, dass das zu testende Gerät alle CDD-Anforderungen erfüllt.
VTS-Tests
VTS-Tests für die Sensors AIDL HAL befinden sich unter hardware/interfaces/sensors/aidl/vts/.
Mit diesen Tests wird sichergestellt, dass das Sensors HAL richtig implementiert ist und alle Anforderungen in ISensors.aidl
und ISensorsCallback.aidl
ordnungsgemäß erfüllt werden.
HAL initialisieren
Die Funktion initialize()
muss unterstützt werden, um FMQs zwischen dem Framework und der HAL einzurichten.
Verfügbare Sensoren bereitstellen
In der Sensors AIDL HAL muss die Funktion getSensorsList()
während eines einzelnen Gerätestarts denselben Wert zurückgeben, auch wenn die Sensors HAL neu gestartet wird. Eine neue Anforderung der Funktion getSensorsList()
ist, dass sie während eines einzelnen Geräteboots denselben Wert zurückgeben muss, auch bei Neustarts des Sensors HAL. Dadurch kann das Framework versuchen, Sensorverbindungen wiederherzustellen, wenn der Systemserver neu gestartet wird. Der von getSensorsList()
zurückgegebene Wert kann sich nach einem Neustart des Geräts ändern.
Sensorereignisse in die FMQ schreiben
Anstatt auf den Aufruf von poll()
zu warten, muss die Sensors HAL in der Sensors AIDL HAL proaktiv Sensorereignisse in die Event FMQ schreiben, sobald Sensorereignisse verfügbar sind. Das HAL ist auch dafür verantwortlich, die richtigen Bits in EventFlag
zu schreiben, um einen FMQ-Lesevorgang im Framework auszulösen.
WAKE_UP-Ereignisse
In Sensors HAL 1.0 konnte die HAL ihr Wake Lock für jedes WAKE_UP
-Ereignis bei jedem nachfolgenden Aufruf von poll()
freigeben, nachdem ein WAKE_UP
an poll()
gesendet wurde. Dies wies darauf hin, dass das Framework alle Sensorereignisse verarbeitet und bei Bedarf ein Wake Lock abgerufen hatte. Da die HAL in der Sensors AIDL HAL nicht mehr benachrichtigt wird, wenn das Framework Ereignisse verarbeitet hat, die in die FMQ geschrieben wurden, kann das Framework über die Wake Lock FMQ der HAL mitteilen, wenn es WAKE_UP
-Ereignisse verarbeitet hat.
In der Sensors AIDL HAL muss das von der Sensors HAL für WAKE_UP
-Ereignisse gesicherte Wake Lock mit SensorsHAL_WAKEUP
beginnen.
Dynamische Sensoren
Dynamische Sensoren wurden mit der Funktion poll()
in Sensors HAL 1.0 zurückgegeben.
Die Sensors AIDL HAL erfordert, dass onDynamicSensorsConnected
und onDynamicSensorsDisconnected
in ISensorsCallback
aufgerufen werden, wenn sich dynamische Sensorverbindungen ändern. Diese Callbacks sind als Teil des ISensorsCallback
-Zeigers verfügbar, der über die Funktion initialize()
bereitgestellt wird.
Betriebsmodi
Der DATA_INJECTION
-Modus für WAKE_UP
-Sensoren muss unterstützt werden.
Unterstützung mehrerer HALs
Die Sensors AIDL HAL unterstützt Multi-HAL mithilfe des Sensors Multi-HAL Framework. Implementierungsdetails finden Sie unter Von Sensors HAL 2.1 portieren.