Sensoren – Multi-HAL

Das Sensors Multi-HAL ist ein Framework, mit dem Sensor-HALs parallel zu anderen Sensor-HALs ausgeführt werden können. Das Sensors Multi-HAL lädt dynamisch Sensor-Sub-HALs, die als dynamische Bibliotheken auf der Anbieterpartition gespeichert sind, und stellt ihnen ein Callback-Objekt zur Verfügung, mit dem Ereignisse gepostet und das Wake Lock abgerufen und freigegeben werden kann. Ein Sensors-Sub-HAL ist ein Sensors-HAL, das in ein gemeinsam genutztes Objekt auf der Anbieterpartition eingebunden ist und vom Multi-HAL-Framework verwendet wird. Diese Sub-HALs sind nicht voneinander oder 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 Weiterentwicklung von Sensors Multi-HAL 2.0. Es unterstützt das Laden von Sub-HALs, die den Sensortyp Scharnierwinkel verfügbar machen können. Um diesen Sensortyp zu unterstützen, müssen Sub-HALs die in 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-Shim-Ebene verwenden, um die Multi-HAL-Funktion 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 Abstraktionen für Sensors HAL 2, um die Interaktion mit HAL-APIs zu vereinfachen. Sensors Multi-HAL 2 führt die Klasse HalProxy ein, um die Implementierung der Sensors HAL 2-Schnittstelle und der V2_1/SubHal-Schnittstelle (oder V2_0/SubHal-Schnittstelle) zu ermöglichen, damit HalProxy mit Sub-HALs interagieren kann.

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

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

Der Hauptunterschied zwischen Sensors Multi-HAL 2 und Sensors HAL 2 liegt in den Initialisierungsfunktionen. Anstelle von FMQs bietet die IHalProxyCallback-Schnittstelle zwei Methoden: eine zum Senden von Sensorereignissen an das Sensor-Framework und eine zum Erstellen von Wake Locks. Im Hintergrund verwaltet der Sensors Multi-HAL alle Interaktionen mit den FMQs, um eine rechtzeitige Übermittlung von Sensorereignissen für alle Sub-HALs zu gewährleisten. Es wird dringend empfohlen, dass untergeordnete HALs die Methode createScopedWakelock verwenden, um die Aufgabe, Zeitüberschreitungen für Wake Locks zu verarbeiten, an das Sensors Multi-HAL zu delegieren und die Verwendung von Wake Locks auf ein gemeinsames Wake Lock für das gesamte Sensors Multi-HAL zu zentralisieren. Dadurch werden Sperr- und Entsperrvorgänge minimiert.

Sensors Multi-HAL 2 bietet auch einige integrierte Sicherheitsfunktionen. Es werden Situationen behandelt, in denen die FMQ des Sensors voll ist oder das Android-Sensor-Framework neu gestartet wird und der Sensorstatus zurückgesetzt werden muss. Wenn Ereignisse in die HalProxy-Klasse gepostet werden, das Sensor-Framework die Ereignisse aber nicht sofort annehmen kann, kann das Sensors Multi-HAL die Ereignisse in einen Hintergrundthread verschieben, damit die Arbeit in allen Sub-HALs fortgesetzt werden kann, während auf das Posten der Ereignisse gewartet wird.

Quellcode und Referenzimplementierung

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

  • HalProxy.h: Das HalProxy-Objekt wird von Sensors Multi-HAL instanziiert und verarbeitet die Übergabe von Daten von den Sub-HALs an das Sensor-Framework.
  • HalProxy.cpp: Die Implementierung von HalProxy enthält die gesamte Logik, die zum Multiplexen der Kommunikation zwischen Sub-HALs und dem Sensor-Framework erforderlich ist.
  • SubHal.h: Die ISensorsSubHal-Schnittstelle definiert die Schnittstelle, die Sub-HALs einhalten müssen, um mit HalProxy kompatibel zu sein. Die Sub-HAL implementiert die Methode „initialize“, damit 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 Einheitentests wird die HalProxy-Implementierung überprüft.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/: In dieser Beispiel-Sub-HAL-Implementierung 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 Sensors AIDL HAL verwenden

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

Mit der AIDL-Multi-HAL-Shim-Ebene können Sie die Sensortypen „Head Tracker“ und „IMU mit eingeschränkter Achse“ in der Sensors AIDL HAL verfügbar machen. Wenn Sie diese Sensortypen verwenden möchten, die von der AIDL-HAL-Schnittstelle definiert werden, legen Sie das Feld type in der Struktur SensorInfo in der getSensorsList_2_1()-Implementierung fest. Das ist sicher, da sich die Felder für den sensortypbasierten Integer der AIDL- und HIDL-Sensoren HAL nicht überschneiden.

Sensors Multi-HAL 2.1 implementieren

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

  1. Implementieren Sie die ISensorsSubHal-Schnittstelle 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 das neu implementierte Sub-HAL zu erstellen. Beim Hinzufügen des Ziels:

    1. Das Ziel muss auf der Anbieterpartition des Geräts platziert werden.
    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, sucht nach dem neu implementierten Sub-HAL und initialisiert es durch Aufrufen von sensorsHalGetSubHal_2_1.

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

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

Das sind die Unterschiede zwischen den SubHal-Schnittstellen 2.0 und 2.1:

  • IHalProxyCallback verwendet die Typen, die in Version 2.1 der ISensors.hal-Spezifikation erstellt wurden.
  • Die Funktion initialize() übergibt ein neues IHalProxyCallback anstelle des IHalProxyCallback aus der 2.0-Schnittstelle SubHal.
  • Unter-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.
  • Unter-HALs müssen sensorsHalGetSubHal_2_1 anstelle von sensorsHalGetSubHal verfügbar machen, damit sie vom Multi-HAL als Unter-HALs der Version 2.1 behandelt werden.

Port von Sensors HAL 2.0

Wenn Sie von Sensors HAL 2.0 auf Sensors Multi-HAL 2.0 aktualisieren, 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 Callback, der zum Posten von Sensorereignissen, zum Abrufen von Wake Locks und zum Benachrichtigen über dynamische Sensorverbindungen und ‑trennungen verwendet werden muss.

Sensorereignisse an die Multi-HAL-Implementierung senden

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

WAKE_UP-Ereignisse

In Sensors HAL 2.0 kann die HAL das Wake Lock für ihre Implementierung verwalten. In Sensors Multi-HAL 2.0 können die Sub-HALs die Multi-HAL-Implementierung verwalten und einen Wakelock anfordern, indem sie createScopedWakelock aufrufen. Eine gesperrte Wake Lock mit Bereich muss abgerufen und an postEvents übergeben werden, wenn Weckereignisse an die Multi-HAL-Implementierung gesendet werden.

Dynamische Sensoren

Sensors Multi-HAL 2.0 erfordert, dass onDynamicSensorsConnected und onDynamicSensorsDisconnected in IHalProxyCallback aufgerufen werden, wenn sich dynamische Sensorverbindungen ändern. Diese Callbacks sind als Teil des IHalProxyCallback-Zeigers verfügbar, der über die Funktion initialize() bereitgestellt wird.

Port von Sensors HAL 1.0

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

HAL initialisieren

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

Verfügbare Sensoren bereitstellen

In Sensors Multi-HAL 2.0 muss die Funktion getSensorsList() während eines einzelnen Gerätestarts denselben Wert zurückgeben, 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 an die Multi-HAL-Implementierung senden

In Sensors HAL 2.0 muss das Sub-HAL Sensorereignisse proaktiv in IHalProxyCallback schreiben, sobald sie verfügbar sind, anstatt auf den Aufruf von poll() zu warten.

WAKE_UP-Ereignisse

In Sensors HAL 1.0 kann die HAL das Wake Lock für ihre Implementierung verwalten. In Sensors Multi-HAL 2.0 können die Sub-HALs Wakelocks verwalten und einen Wakelock anfordern, indem sie createScopedWakelock aufrufen. Eine gesperrte Wake Lock mit Bereich muss abgerufen und an postEvents übergeben werden, wenn Weckereignisse an die Multi-HAL-Implementierung gesendet werden.

Dynamische Sensoren

In Sensors HAL 1.0 werden dynamische Sensoren über die Funktion poll() zurückgegeben. Sensors Multi-HAL 2.0 erfordert, dass onDynamicSensorsConnected und onDynamicSensorsDisconnected in IHalProxyCallback aufgerufen werden, wenn sich dynamische Sensorverbindungen ändern. Diese Callbacks sind als Teil des IHalProxyCallback-Zeigers verfügbar, der über die Funktion initialize() bereitgestellt wird.

Port von Sensors Multi-HAL 1.0

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

  1. Prüfen Sie, ob sich die HAL-Konfiguration der Sensoren unter /vendor/etc/sensors/hals.conf befindet. Dazu müssen Sie möglicherweise die Datei unter /system/etc/sensors/hals.conf verschieben.
  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 die Sub-HALs wie unter Von Sensors HAL 1.0 portieren beschrieben.
  4. Legen Sie Sensors Multi-HAL 2.0 als die vorgesehene HAL fest, indem Sie die Schritte 3 und 4 im Abschnitt Sensors Multi-HAL 2.0 implementieren ausführen.

Zertifizierungsstufe

VTS ausführen

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

Wenn VTS auf einem Hostcomputer eingerichtet ist und Sie nur die VTS-Tests für Sensoren ausführen möchten, 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-Shim-Schicht ausführen, führen Sie VtsAidlHalSensorsTargetTest aus.

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

Einheitentests 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 eines neuen Sub-HAL sollten diese Tests als Leitfaden dafür dienen, wie Unittests hinzugefügt werden, die überprüfen, ob das neue Sub-HAL richtig implementiert ist.

Führen Sie die Tests mit folgenden Befehlen aus:

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

Mit den gefälschten untergeordneten HALs testen

Die gefälschten Sub-HALs sind Dummy-Implementierungen der ISensorsSubHal-Schnittstelle. Die untergeordneten HALs stellen verschiedene Sensorlisten zur Verfügung. Wenn die Sensoren aktiviert sind, werden automatisch generierte Sensorereignisse in regelmäßigen Abständen an HalProxy gesendet. Die Intervalle werden in einer bestimmten Sensoranfrage angegeben.

Mit den gefälschten Sub-HALs kann getestet werden, wie der vollständige Multi-HAL-Code mit anderen im System geladenen Sub-HALs funktioniert, und verschiedene Aspekte des Sensors Multi-HAL-Codes können getestet werden.

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

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

  1. Führen Sie die folgenden Befehle aus, um die drei verschiedenen Fake-Sub-HALs zu erstellen und per Push 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 Sensors HAL-Konfiguration unter /vendor/etc/sensors/hals.conf mit den Pfaden für die gefälschten Sub-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. Starten Sie HalProxy neu und laden Sie die neuen Sub-HALs, die in der Konfiguration aufgeführt sind.

    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 Debug-Ausgabe 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 Sub-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 groß ist (1.000 oder mehr), bedeutet das, dass viele Ereignisse darauf warten, in das Sensors-Framework geschrieben zu werden. Dies weist darauf hin, dass der Sensordienst blockiert ist oder abgestürzt ist und keine Sensorereignisse verarbeitet, oder dass vor Kurzem ein großer Batch von Sensorereignissen von einem Sub-HAL gesendet wurde.

Wenn die Anzahl der Wake Locks größer als 0 ist, hat HalProxy einen Wake Lock erhalten. Dieser Wert sollte nur größer als 0 sein, wenn ein ScopedWakelock absichtlich zurückgehalten wird oder wenn Weckereignisse an HalProxy gesendet wurden und nicht vom Sensor-Framework verarbeitet wurden.

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