Sensoren – Multi-HAL

Die Sensors Multi-HAL ist ein Framework, mit dem HALs für Sensoren neben anderen HALs für Sensoren ausgeführt werden können. Die Sensors Multi-HAL lädt dynamisch Sensor-Unter-HALs, die als dynamische Bibliotheken auf der Anbieterpartition gespeichert sind, und weist ihnen ein Rückrufobjekt zu, das Ereignisse posten und die Wake-Lock erwerben und freigeben kann. Eine Sensor-Sub-HAL ist eine Sensor-HAL, die in ein freigegebenes Objekt auf der Anbieterpartition eingebunden ist und vom Multi-HAL-Framework verwendet wird. Diese untergeordneten HALs sind weder voneinander noch vom Multi-HAL-Code abhängig, der die Hauptfunktion für den Prozess enthält.

Sensors Multi-HAL 2.1 ist auf Geräten mit Android 11 oder höher verfügbar und eine Iteration von Sensors Multi-HAL 2.0. Es unterstützt das Laden von untergeordneten HALs, die den Sensortyp für den Scharnierwinkel freigeben können. Zur Unterstützung dieses Sensortyps müssen Sub-HALs die im 2.1 SubHal-Header definierten Sub-HAL-APIs verwenden.

Auf Geräten mit Android 13 oder höher, die den Sensors AIDL HAL verwenden, können Sie die Multi-HAL-Shimsschicht verwenden, um Multi-HAL-Funktionen zu ermöglichen. Implementierungsdetails finden Sie unter Sensors Multi-HAL mit der Sensors AIDL HAL verwenden.

Unterschied zwischen Sensors Multi-HAL 2 und Sensors HAL 2

Sensors Multi-HAL 2 ist auf Geräten mit Android 10 oder höher verfügbar und bietet mehrere Abstraktionsschichten zusätzlich zu Sensors HAL 2, um die Interaktion mit HAL APIs zu vereinfachen. In Sensors Multi-HAL 2 wird die Klasse HalProxy eingeführt, die die Implementierung der Sensors HAL 2-Schnittstelle und der Schnittstelle V2_1/SubHal (oder V2_0/SubHal) übernimmt, damit HalProxy mit untergeordneten HALs interagieren kann.

Die Schnittstelle ISensorsSubHal unterscheidet sich in folgenden Punkten von der Schnittstelle 2.1/ISensors.hal (oder 2.0/ISensors.hal):

  • Die Methode „initialize“ übergibt eine IHalProxyCallback-Klasse anstelle von zwei FMQs und ISensorsCallback.
  • Untergeordnete HALs müssen eine Debug-Funktion implementieren, um Debugging-Informationen in Fehlerberichten bereitzustellen.
  • Untergeordnete HALs müssen eine Namensfunktion implementieren, damit die geladene untergeordnete HAL von anderen untergeordneten HALs unterschieden werden kann.

Der Hauptunterschied zwischen Sensors Multi-HAL 2 und Sensors HAL 2 besteht in den Initialisierungsfunktionen. Anstatt FMQs bietet die IHalProxyCallback-Schnittstelle zwei Methoden: eine Methode zum Posten von Sensorereignissen an das Sensor Framework und eine Methode zum Erstellen von Wakelocks. Im Hintergrund verwaltet die Multi-HAL für Sensoren alle Interaktionen mit den FMQs, um eine zeitnahe Übermittlung von Sensorereignissen für alle untergeordneten HALs zu gewährleisten. Es wird dringend empfohlen, dass untergeordnete HALs die createScopedWakelock-Methode verwenden, um die Zeitüberschreitung von Wakelocks an die Sensors Multi-HAL zu delegieren und die Verwendung von Wakelocks auf eine gemeinsame Wakelock für die gesamte Sensors Multi-HAL zu zentralisieren. Dadurch werden Sperr- und Entsperraufrufe minimiert.

Sensors Multi-HAL 2 bietet außerdem einige integrierte Sicherheitsfunktionen. Sie verarbeitet Situationen, in denen der FMQ des Sensors voll ist oder das Android-Sensor-Framework neu gestartet wird und der Sensorstatus zurückgesetzt werden muss. Wenn Ereignisse an die HalProxy-Klasse gepostet werden, das Sensor-Framework sie aber nicht sofort akzeptieren kann, kann die Multi-HAL von Sensors die Ereignisse in einen Hintergrund-Thread verschieben, damit die Arbeit in allen untergeordneten HALs fortgesetzt werden kann, während auf das Posten der Ereignisse gewartet wird.

Quellcode und Referenzimplementierung

Der Multi-HAL-Code für alle Sensoren ist in hardware/interfaces/sensors/common/default/2.X/multihal/ verfügbar. Hier finden Sie einige hilfreiche Ressourcen.

  • HalProxy.h: Das HalProxy-Objekt wird von der Sensors Multi-HAL instanziiert und kümmert sich um die Weitergabe von Daten von den untergeordneten HALs an das Sensor-Framework.
  • HalProxy.cpp: Die Implementierung von HalProxy enthält die gesamte Logik, die für die Multiplex-Kommunikation zwischen Sub-HALs und dem Sensor-Framework erforderlich ist.
  • SubHal.h: Die ISensorsSubHal-Schnittstelle definiert die Schnittstelle, der untergeordnete HALs entsprechen müssen, um mit HalProxy kompatibel zu sein. Die untergeordnete HAL implementiert die Methode „initialize“, sodass das HalProxyCallback-Objekt für postEvents und createScopedWakelock verwendet werden kann.

    Verwenden Sie für Multi-HAL 2.0-Implementierungen Version 2.0 von SubHal.h.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/: Mit diesen Unittests wird die HalProxy-Implementierung überprüft.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/: In dieser Beispielimplementierung der Sub-HAL werden gefälschte Sensoren verwendet, um gefälschte Daten zu generieren. Nützlich, um zu testen, wie mehrere Sub-HALs auf einem Gerät interagieren.

Implementierung

In diesem Abschnitt wird beschrieben, wie Sie Sensors Multi-HAL in den folgenden Situationen implementieren:

Sensors Multi-HAL mit der Sensors AIDL HAL verwenden

Wenn Sie die Multi-HAL-Funktion mit der Sensors AIDL HAL zulassen möchten, importieren Sie das AIDL-Multi-HAL-Shimstapelmodul, das sich unter hardware/interfaces/sensors/aidl/default/multihal/ befindet. Das Modul übernimmt die Umwandlung zwischen HAL-Definitionen von AIDL- und HIDL-Sensoren und definiert einen Wrapper für die Multi-HAL-Schnittstelle, die in Implementing Sensors Multi-HAL 2.1 beschrieben wird. Die AIDL-Multi-HAL-Shimsschicht ist mit Geräten kompatibel, die Sensors Multi-HAL 2.1 implementieren.

Mit der AIDL-Multi-HAL-Shimsschicht können Sie den Kopf-Tracker und die IMU-Sensortypen mit begrenzter Achse in der Sensors AIDL HAL freigeben. Wenn Sie diese von der AIDL HAL-Schnittstelle definierten Sensortypen verwenden möchten, setzen Sie das Feld type in der Struktur SensorInfo in der getSensorsList_2_1()-Implementierung. Das ist sicher, da sich die Felder für den Sensortyp der AIDL- und HIDL-Sensoren HAL nicht überschneiden.

Implementieren von Sensors Multi-HAL 2.1

So implementieren Sie Sensors Multi-HAL 2.1 auf einem neuen Gerät:

  1. Implementieren Sie die ISensorsSubHal-Oberfläche wie unter SubHal.h beschrieben.
  2. Implementieren Sie die Methode sensorsHalGetSubHal_2_1 in SubHal.h.
  3. Fügen Sie ein cc_library_shared-Ziel hinzu, um die neu implementierte untergeordnete HAL zu erstellen. Beachten Sie beim Hinzufügen des Ziels Folgendes:

    1. Achten Sie darauf, dass das Ziel an eine Stelle auf der Anbieterpartition des Geräts gesendet wird.
    2. Fügen Sie in der Konfigurationsdatei unter /vendor/etc/sensors/hals.conf den Pfad zur Bibliothek in einer neuen Zeile hinzu. Erstellen Sie bei Bedarf die Datei hals.conf.

    Ein Beispiel für einen Android.bp-Eintrag zum Erstellen einer Sub-HAL-Bibliothek finden Sie unter hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp.

  4. Entfernen Sie alle android.hardware.sensors-Einträge aus der Datei manifest.xml, die die Liste der unterstützten HALs auf dem Gerät enthält.

  5. Entfernen Sie alle android.hardware.sensors-Dienst- und service.rc-Dateien aus der Datei device.mk und fügen Sie android.hardware.sensors@2.1-service.multihal und android.hardware.sensors@2.1-service.multihal.rc zu PRODUCT_PACKAGES hinzu.

Beim Starten wird HalProxy gestartet, nach der neu implementierten Sub-HAL gesucht und diese durch Aufrufen von sensorsHalGetSubHal_2_1 initialisiert.

Port von Sensors Multi-HAL 2.0 zu Multi-HAL 2.1

Wenn Sie von Multi-HAL 2.0 zu Multi-HAL 2.1 wechseln möchten, implementieren Sie die Schnittstelle SubHal und kompilieren Sie die untergeordnete HAL neu.

Das sind die Unterschiede zwischen den SubHal-Benutzeroberflächen 2.0 und 2.1:

  • IHalProxyCallback verwendet die Typen, die in Version 2.1 der ISensors.hal-Spezifikation erstellt wurden.
  • Die Funktion initialize() gibt eine neue IHalProxyCallback anstelle der SubHal-Oberfläche von Version 2.0 weiter.
  • Untergeordnete HALs müssen getSensorsList_2_1 und injectSensorData_2_1 anstelle von getSensorsList und injectSensorData implementieren, da diese Methoden die neuen Typen verwenden, die in Version 2.1 der ISensors.hal-Spezifikation hinzugefügt wurden.
  • Untergeordnete HALs müssen sensorsHalGetSubHal_2_1 anstelle von sensorsHalGetSubHal bereitstellen, damit die Multi-HAL sie als untergeordnete HALs der Version 2.1 behandelt.

Port von Sensors HAL 2.0

Wenn Sie von Sensors HAL 2.0 auf Sensors Multi-HAL 2.0 umstellen, muss die HAL-Implementierung die folgenden Anforderungen erfüllen.

HAL initialisieren

Sensors HAL 2.0 hat eine Initialisierungsfunktion, mit der der Sensordienst FMQs und einen dynamischen Sensor-Callback übergeben kann. In Sensors Multi-HAL 2.0 übergibt die Funktion initialize() einen einzelnen Rückruf, der verwendet werden muss, um Sensorereignisse zu posten, Wakelocks zu erhalten und über dynamische Sensorverbindungen und ‑trennungen zu benachrichtigen.

Sensorereignisse an die Multi-HAL-Implementierung posten

Anstatt Sensorereignisse über die FMQ zu posten, muss die untergeordnete HAL Sensorereignisse in die IHalProxyCallback schreiben, wenn Sensorereignisse verfügbar sind.

WAKE_UP-Ereignisse

In Sensors HAL 2.0 kann die HAL die Wake-Lock für die Implementierung verwalten. In Sensors Multi-HAL 2.0 können die untergeordneten HALs die Multi-HAL-Implementierung zum Verwalten von Wakelocks verwenden und durch Aufrufen von createScopedWakelock ein Wakelock anfordern. Wenn Weck-Ereignisse an die Multi-HAL-Implementierung gesendet werden, muss eine gesperrte Wecksperre abgerufen und an postEvents übergeben werden.

Dynamische Sensoren

Bei Sensors Multi-HAL 2.0 müssen onDynamicSensorsConnected und onDynamicSensorsDisconnected in IHalProxyCallback aufgerufen werden, wenn sich dynamische Sensorverbindungen ändern. Diese Callbacks sind über den IHalProxyCallback-Zeiger verfügbar, der über die initialize()-Funktion bereitgestellt wird.

Port von Sensors HAL 1.0

Wenn Sie von Sensors HAL 1.0 auf Sensors Multi-HAL 2.0 umstellen, muss die HAL-Implementierung die folgenden Anforderungen erfüllen.

HAL initialisieren

Die Funktion initialize() muss unterstützt werden, um den Rückruf zwischen der untergeordneten HAL und der Multi-HAL-Implementierung herzustellen.

Verfügbare Sensoren bereitstellen

In Sensors Multi-HAL 2.0 muss die Funktion getSensorsList() bei einem einzelnen Gerätestart denselben Wert zurückgeben, auch bei Neustarts der HAL der Sensoren. So 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 an die Multi-HAL-Implementierung posten

In Sensors HAL 2.0 muss die untergeordnete HAL nicht darauf warten, dass poll() aufgerufen wird, sondern Sensorereignisse proaktiv in IHalProxyCallback schreiben, sobald Sensorereignisse verfügbar sind.

WAKE_UP-Ereignisse

In Sensors HAL 1.0 kann die HAL die Wake-Lock für die Implementierung verwalten. In Sensors Multi-HAL 2.0 können die untergeordneten HALs die Multi-HAL-Implementierung zum Verwalten von Wakelocks verwenden und durch Aufrufen von createScopedWakelock ein Wakelock anfordern. Wenn Weck-Ereignisse an die Multi-HAL-Implementierung gesendet werden, muss eine gesperrte Wecksperre abgerufen und an postEvents übergeben werden.

Dynamische Sensoren

In Sensors HAL 1.0 werden dynamische Sensoren über die Funktion poll() zurückgegeben. Bei Sensors Multi-HAL 2.0 müssen onDynamicSensorsConnected und onDynamicSensorsDisconnected in IHalProxyCallback aufgerufen werden, wenn sich dynamische Sensorverbindungen ändern. Diese Callbacks sind über den IHalProxyCallback-Zeiger verfügbar, der über die initialize()-Funktion bereitgestellt wird.

Port von Sensors Multi-HAL 1.0

So portieren Sie eine vorhandene Implementierung von Sensors Multi-HAL 1.0:

  1. Die HAL-Konfiguration der Sensoren muss sich unter /vendor/etc/sensors/hals.conf befinden. Dazu muss möglicherweise die Datei unter /system/etc/sensors/hals.conf verschoben werden.
  2. Entfernen Sie alle Verweise auf hardware/hardware.h und hardware/sensors.h, da diese für HAL 2.0 nicht unterstützt werden.
  3. Portieren Sie untergeordnete HALs wie unter Porting von Sensors HAL 1.0 beschrieben.
  4. Legen Sie Sensors Multi-HAL 2.0 als die angegebene HAL fest. Folgen Sie dazu den Schritten 3 und 4 im Abschnitt Implementing Sensors Mutli-HAL 2.0 (Implementierung von Sensors Multi-HAL 2.0).

Zertifizierungsstufe

VTS ausführen

Wenn Sie eine oder mehrere untergeordnete HALs in Sensors Multi-HAL 2.1 eingebunden haben, verwenden Sie die Vendor Test Suite (VTS), um sicherzustellen, dass Ihre untergeordneten HAL-Implementierungen alle Anforderungen der Sensors HAL-Schnittstelle erfüllen.

Wenn Sie nur die VTS-Tests für Sensoren ausführen möchten, wenn VTS auf einem Hostcomputer eingerichtet ist, führen Sie die folgenden Befehle aus:

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

Wenn Sie die AIDL-Multi-HAL-Shimsschicht verwenden, führen Sie VtsAidlHalSensorsTargetTest aus.

vts-tradefed run commandAndExit vts \
    --skip-all-system-status-check \
    --primary-abi-only \
    --skip-preconditions \
    --module VtsAidlHalSensorsTargetTest

Unittests ausführen

Die Unittests in HalProxy_test.cpp testen HalProxy mit gefälschten Sub-HALs, die im Unittest instanziiert und nicht dynamisch geladen werden. Beim Erstellen einer neuen untergeordneten HAL sollten diese Tests als Leitfaden dienen, um Unit-Tests hinzuzufügen, die überprüfen, ob die neue untergeordnete HAL richtig implementiert ist.

Führen Sie die folgenden Befehle aus, um die Tests auszuführen:

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

Mit den gefälschten untergeordneten HALs testen

Die gefälschten untergeordneten HALs sind Dummy-Implementierungen der ISensorsSubHal-Schnittstelle. Die untergeordneten HALs stellen unterschiedliche Listen von Sensoren bereit. Wenn die Sensoren aktiviert sind, senden sie basierend auf den in einer bestimmten Sensoranfrage angegebenen Intervallen regelmäßig automatisch generierte Sensorereignisse an HalProxy.

Mit den gefälschten Sub-HALs kann getestet werden, wie der vollständige Multi-HAL-Code mit anderen Sub-HALs funktioniert, die in das System geladen werden, und verschiedene Aspekte des Multi-HAL-Codes der Sensoren beansprucht werden.

Unter hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/ sind zwei gefälschte untergeordnete HALs verfügbar.

So erstellen Sie die gefälschten Sub-HALs und schieben sie auf ein Gerät:

  1. Führen Sie die folgenden Befehle aus, um die drei verschiedenen gefälschten Sub-HALs zu erstellen und auf das Gerät zu übertragen:

    $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. Aktualisieren Sie die HAL-Konfiguration der Sensoren unter /vendor/etc/sensors/hals.conf mit den Pfaden zu den gefälschten untergeordneten HALs.

    /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. Starte HalProxy neu und lade die neuen in der Konfiguration aufgeführten untergeordneten HALs.

    adb shell stop
    adb shell start

Fehlerbehebung

Entwickler können das Framework mit dem Befehl lshal debuggen. Führen Sie den folgenden Befehl aus, um die Debugausgabe der Sensors HAL anzufordern:

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

Informationen zum aktuellen Status von HalProxy und seinen untergeordneten HALs werden dann im Terminal ausgegeben. Unten sehen Sie ein Beispiel für die Befehlsausgabe für das HalProxy-Objekt und die gefälschten untergeordneten HALs.

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

Wenn die für # of events on pending write queue angegebene Zahl sehr hoch ist (1.000 oder mehr), gibt es viele Ereignisse, die noch in das Sensor-Framework geschrieben werden müssen. Dies bedeutet, dass der Sensordienst in einer Deadlock-Situation ist oder abgestürzt ist und keine Sensorereignisse verarbeitet oder dass vor Kurzem eine große Anzahl von Sensorereignissen von einer untergeordneten HAL gepostet wurde.

Wenn die Anzahl der Wakelock-Referenzen größer als 0 ist, hat HalProxy ein Wakelock erworben. Dieser Wert sollte nur dann größer als 0 sein, wenn eine ScopedWakelock absichtlich gehalten wird oder wenn Weck-Ereignisse an HalProxy gesendet und nicht vom Sensor-Framework verarbeitet wurden.

Der Dateideskriptor, der an die Debug-Methode von HalProxy übergeben wird, wird an jede untergeordnete HAL übergeben. Entwickler müssen die Debug-Methode daher als Teil der ISensorsSubHal-Schnittstelle implementieren.