Czujniki wielofunkcyjne HAL

Multi-HAL czujników to platforma, która umożliwia uruchamianie interfejsów HAL czujników obok innych interfejsów HAL czujników. Multi-HAL Sensors dynamicznie wczytuje pod-HAL czujników zapisane jako biblioteki dynamiczne na partycji dostawcy i przekazuje im obiekt wywołania zwrotnego, który może obsługiwać zdarzenia publikowania oraz pobierać i zwalniać blokadę uśpienia. Podsystem HAL czujników to interfejs HAL czujników wbudowany w wspólny obiekt w partycji dostawcy, który jest używany przez interfejs wielopoziomowego interfejsu HAL. Te podrzędne HAL nie zależą od siebie ani od kodu z wieloma HAL, który zawiera główną funkcję procesu.

Interfejs Sensors Multi-HAL 2.1, dostępny na urządzeniach z Androidem 11 lub nowszym, to wersja interfejsu Sensors Multi-HAL 2.0, która obsługuje wczytywanie podinterfejsów HAL, które mogą udostępniać typ czujnika kąt zawiasu. Aby obsługiwać ten typ czujnika, podsystemy HAL muszą używać interfejsów API podsystemów HAL zdefiniowanych w nagłówku 2.1 SubHal.

W przypadku urządzeń z Androidem 13 lub nowszym, które korzystają z interfejsu sterownika HAL interfejsu AIDL dla czujników, możesz użyć warstwy shim dla wielu interfejsów HAL, aby umożliwić obsługę wielu interfejsów HAL. Szczegółowe informacje o wdrożeniu znajdziesz w artykule Korzystanie z Sensors Multi-HAL z Sensors AIDL HAL.

Różnica między czujnikami Multi-HAL 2 a czujnikami HAL 2

Interfejs Sensors Multi-HAL 2, dostępny na urządzeniach z Androidem 10 lub nowszym, wprowadza kilka abstrakcji na poziomie interfejsu Sensors HAL 2, aby ułatwić interakcję z interfejsami HAL. Interfejs Sensors Multi-HAL 2 wprowadza klasę HalProxy, która obsługuje implementację interfejsu Sensors HAL 2 oraz interfejs V2_1/SubHal (lub V2_0/SubHal), aby umożliwić HalProxy interakcję z podrzędnymi interfejsami HAL.

Interfejs ISensorsSubHal różni się od interfejsu 2.1/ISensors.hal (lub 2.0/ISensors.hal) w następujący sposób:

  • Metoda initialize przekazuje klasę IHalProxyCallback zamiast 2 obiektów FMQ i ISensorsCallback.
  • Sub-HALs musi implementować funkcję debugowania, aby dostarczać informacje o debugowaniu w raportach o błędach.
  • Sub-HAL musi implementować funkcję nazwy, która umożliwia odróżnienie wczytanej części podrzędnej od innych podrzędnych elementów HAL.

Główna różnica między interfejsem Sensors Multi-HAL 2 a interfejsem Sensors HAL 2 dotyczy funkcji inicjowania. Zamiast udostępniać sygnały FMQ interfejs IHalProxyCallback udostępnia 2 metody: jedną do publikowania zdarzeń z czujnika w ramce czujników, a drugą do tworzenia blokad uśpienia. W ramach tej usługi zarządza się wszystkimi interakcjami z interfejsami FMQ, aby zapewnić terminowe dostarczanie zdarzeń czujników do wszystkich podrzędnych interfejsów HAL. Zdecydowanie zalecamy, aby interfejsy HAL podrzędnych używały metody createScopedWakelock, aby przekazać obciążenie związane z czasową blokadą na rzecz interfejsu Sensors Multi-HAL, oraz aby scentralizować użycie blokady na rzecz jednej wspólnej blokady dla całego interfejsu Sensors Multi-HAL, co minimalizuje wywołania blokady i odblokowania.

Sensors Multi-HAL 2 ma też wbudowane funkcje bezpieczeństwa. Obsługuje sytuacje, w których czujnik FMQ jest pełny lub gdy platforma czujnika Androida uruchamia się ponownie i trzeba zresetować stan czujnika. Dodatkowo, gdy zdarzenia są publikowane w klasie HalProxy, ale framework czujnika nie może ich od razu zaakceptować, czujniki Multi-HAL mogą przenieść te zdarzenia do wątku w tle, aby umożliwić kontynuowanie pracy we wszystkich podrzędnych HAL-ach w czasie oczekiwania na opublikowanie zdarzeń.

Implementacja kodu źródłowego i referencyjnego

Kod Multi-HAL wszystkich czujników jest dostępny w hardware/interfaces/sensors/common/default/2.X/multihal/. Oto kilka linków do materiałów.

  • HalProxy.h: obiekt HalProxy jest tworzony przez wieloplatformowy interfejs API czujników i przekazuje dane z interfejsów podrzędnych do interfejsu sensora.
  • HalProxy.cpp: Implementacja HalProxy zawiera całą logikę potrzebną do multipleksowania komunikacji między podsystemami HAL i ramką czujnika.
  • SubHal.h: Interfejs ISensorsSubHal określa interfejs, który musi być używany przez podrzędne części HAL, aby były zgodne z HalProxy. Sub-HAL implementuje metodę initialize, aby obiekt HalProxyCallback można było używać w przypadku postEventscreateScopedWakelock.

    W przypadku implementacji Multi-HAL 2.0 użyj wersji 2.0 pliku SubHal.h.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/: Te testy jednostkowe sprawdzają implementację HalProxy.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/: w tym przykładzie implementacji podsystemu HAL używa się fałszywych czujników do generowania fałszywych danych. Ta opcja jest przydatna do sprawdzania, jak różne części podrzędne HAL współdziałają na urządzeniu.

Implementacja

W tej sekcji opisano, jak zaimplementować interfejs Multi-HAL czujników w tych sytuacjach:

Używaj czujników Multi-HAL z czujnikami AIDL HAL

Aby umożliwić obsługę wielu HAL za pomocą interfejsu Sensors AIDL HAL, zaimportuj moduł warstwy podkładowej AIDL, który znajduje się w lokalizacji hardware/interfaces/sensors/aidl/default/multihal/. Moduł obsługuje konwersję między typami definicji HAL czujników AIDL i HIDL oraz definiuje opakowanie dla interfejsu wielowarstwowego HAL opisanego w artykule Implementing Sensors Multi-HAL 2.1 (w języku angielskim). Warstwę shimu wielopoziomowego AIDL można stosować na urządzeniach, które implementują interfejs Sensors Multi-HAL 2.1.

Warstwa podkładkowa AIDL Multi-HAL pozwala pokazać głowę trackera oraz typy czujników IMU o ograniczonych osiach w interfejsie Sensors AIDL HAL. Aby używać tych typów czujników zdefiniowanych przez interfejs AIDL HAL, ustaw pole type w strukturze SensorInfo w implementacji getSensorsList_2_1(). Jest to bezpieczne, ponieważ pola HAL czujników AIDL i HIDL z obsługą liczb całkowitych nie nakładają się na siebie.

Wdrożenie interfejsu Sensors Multi-HAL 2.1

Aby zaimplementować interfejs Sensors Multi-HAL 2.1 na nowym urządzeniu, wykonaj te czynności:

  1. Zaimplementuj interfejs ISensorsSubHal zgodnie z opisem w dokumentacji SubHal.h.
  2. Zaimplementuj metodę sensorsHalGetSubHal_2_1SubHal.h.
  3. Dodaj cel cc_library_shared, aby utworzyć nowo wdrożony podsystem HAL. Podczas dodawania środowiska docelowego:

    1. Upewnij się, że środowisko docelowe jest przeniesione do partycji dostawcy urządzenia.
    2. W pliku konfiguracji znajdującym się pod adresem /vendor/etc/sensors/hals.conf dodaj w nowym wierszu ścieżkę do biblioteki. W razie potrzeby utwórz plik hals.conf.

    Przykładowy wpis Android.bp dotyczący tworzenia biblioteki niższego poziomu HAL znajdziesz tutaj: hardware/interfaces/sensors/common/default/2.X/multihal/tests/Android.bp.

  4. Usuń wszystkie wpisy android.hardware.sensors z pliku manifest.xml, który zawiera listę obsługiwanych licencji HAL na urządzeniu.

  5. Usuń wszystkie pliki usługi android.hardware.sensors i pliki service.rc z pliku device.mk, a potem dodaj pliki android.hardware.sensors@2.1-service.multihalandroid.hardware.sensors@2.1-service.multihal.rc do pliku PRODUCT_PACKAGES.

Podczas uruchamiania HalProxy szuka nowo zaimplementowanego podsystemu HAL i inicjalizuje go, wywołując sensorsHalGetSubHal_2_1.

Przenoszenie z Sensors Multi-HAL 2.0 do Multi-HAL 2.1

Aby przenieść dane z Multi-HAL 2.0 na Multi-HAL 2.1, zaimplementuj interfejs SubHal i ponownie skompiluj subdomenę HAL.

Oto różnice między interfejsami SubHal w wersjach 2.0 i 2.1:

  • IHalProxyCallback używa typów utworzonych w wersji 2.1 specyfikacji ISensors.hal.
  • Funkcja initialize() przekazuje nowy parametr IHalProxyCallback zamiast interfejsu SubHal w wersji 2.0
  • Podsystemy HAL muszą implementować metody getSensorsList_2_1injectSensorData_2_1 zamiast getSensorsListinjectSensorData, ponieważ te metody używają nowych typów dodanych w wersji 2.1 specyfikacji ISensors.hal.
  • Sub-HAL musi udostępniać elementowi sensorsHalGetSubHal_2_1, a nie sensorsHalGetSubHal, aby mogły traktować je jako Sub-HAL w wersji 2.1.

Port z Czujnika HAL 2.0

Podczas aktualizacji z Sensors HAL 2.0 na Sensors Multi-HAL 2.0 sprawdź, czy implementacja HAL spełnia te wymagania.

Inicjowanie HAL

HAL 2.0 ma funkcję inicjowania, która umożliwia usłudze czujnika przekazywanie sygnałów FMQ i dynamiczne wywołanie zwrotne czujnika. W Sensors Multi-HAL 2.0 funkcja initialize() przekazuje pojedynczą funkcję wywołania zwrotnego, która musi być używana do publikowania zdarzeń czujnika, uzyskiwania blokad aktywacji i powiadamiania o dynamicznych połączeniach i rozłączeniach czujnika.

Przesyłanie zdarzeń czujnika do implementacji Multi-HAL

Zamiast publikować zdarzenia z czujnika za pomocą FMQ, pod-HAL musi zapisywać zdarzenia czujnika w IHalProxyCallback, gdy są one dostępne.

Zdarzenia WAKE_UP

W przypadku interfejsu Sensors HAL 2.0 HAL może zarządzać blokadą uśpienia w celu jej implementacji. W Sensors Multi-HAL 2.0 podrzędne listy HAL umożliwiają wdrożeniu Multi-HAL zarządzanie blokadami uśpienia i mogą żądać uzyskania blokady uśpienia przez wywołanie createScopedWakelock. Podczas publikowania zdarzeń aktywacji w implementacji Multi-HAL należy uzyskać i przekazać postEvents zablokowany ograniczony blokadę aktywacji.

Czujniki dynamiczne

Czujniki Multi-HAL 2.0 wymagają wywoływania onDynamicSensorsConnected i onDynamicSensorsDisconnected w IHalProxyCallback przy każdej zmianie połączeń z czujnikami dynamicznymi. Te wywołania zwrotne są dostępne jako część wskaźnika IHalProxyCallback udostępnianego przez funkcję initialize().

Port z Sensors HAL 1.0

Jeśli przechodzisz z Sensors HAL 1.0 na Sensors Multi-HAL 2.0, upewnij się, że implementacja HAL spełnia poniższe wymagania.

Inicjowanie HAL

Aby ustanowić wywołanie zwrotne między implementacją sub-HAL a implementacją Multi-HAL, musi być obsługiwana funkcja initialize().

Udostępnij dostępne czujniki

W Sensors Multi-HAL 2.0 funkcja getSensorsList() musi zwracać tę samą wartość podczas uruchamiania urządzenia, nawet po ponownym uruchomieniu interfejsu HAL czujników. Dzięki temu framework może spróbować ponownie połączyć się z czujnikiem, jeśli serwer systemowy zostanie ponownie uruchomiony. Wartość zwracana przez getSensorsList() może się zmienić po ponownym uruchomieniu urządzenia.

Publikuj zdarzenia z czujników w implementacji Multi-HAL

W Sensors HAL 2.0 zamiast czekać na wywołanie funkcji poll() podrzędny interfejs HAL musi aktywnie zapisywać zdarzenia czujnika do IHalProxyCallback, gdy tylko są dostępne.

Zdarzenia WAKE_UP

W interfejsie HAL czujników 1.0 interfejs HAL może zarządzać blokadą aktywacji w ramach swojej implementacji. W Sensors Multi-HAL 2.0 podrzędne listy HAL umożliwiają wdrożeniu Multi-HAL zarządzanie blokadami uśpienia i mogą żądać uzyskania blokady uśpienia przez wywołanie createScopedWakelock. Podczas publikowania zdarzeń aktywacji w implementacji Multi-HAL należy uzyskać i przekazać postEvents zablokowany ograniczony blokadę aktywacji.

Czujniki dynamiczne

W HAL 1.0 czujniki dynamiczne są zwracane przez funkcję poll(). Interfejs Sensors Multi-HAL 2.0 wymaga, aby funkcje onDynamicSensorsConnectedonDynamicSensorsDisconnectedIHalProxyCallback były wywoływane za każdym razem, gdy zmieniają się dynamiczne połączenia czujników. Te wywołania zwrotne są dostępne w ramach wskaźnika IHalProxyCallback, który jest udostępniany przez funkcję initialize().

Port z Czujnika Multi-HAL 1.0

Aby przenieść istniejące rozwiązanie z Sensors Multi-HAL 1.0, wykonaj te czynności.

  1. Sprawdź, czy konfiguracja HAL czujników znajduje się w /vendor/etc/sensors/hals.conf. Może to oznaczać przeniesienie pliku znajdującego się pod adresem /system/etc/sensors/hals.conf.
  2. Usuń wszystkie odwołania do hardware/hardware.h i hardware/sensors.h, ponieważ nie są one obsługiwane w HAL 2.0.
  3. Przenoś podsystemy HAL zgodnie z opisem w artykule Przenoszenie z Sensors HAL 1.0.
  4. Aby ustawić interfejs Sensors Multi-HAL 2.0 jako docelowy interfejs HAL, wykonaj czynności opisane w punktach 3 i 4 w sekcji Wdrażanie interfejsu Sensors Multi-HAL 2.0.

Weryfikacja

Uruchamianie VTS

Gdy zintegrujesz co najmniej jedną podrzędną część HAL z urządzeniem Sensors Multi-Hal 2.1, użyj pakietu Vendor Test Suite (VTS), aby mieć pewność, że implementacje podrzędne tego interfejsu spełniają wszystkie wymagania określone w interfejsie Sensors HAL.

Aby uruchomić tylko testy VTS czujników po skonfigurowaniu VTS na komputerze hosta, wykonaj te polecenia:

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

Jeśli używasz warstwy podkładowej AIDL Multi-HAL, uruchom VtsAidlHalSensorsTargetTest.

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

Przeprowadzanie testów jednostkowych

Testy jednostkowe w HalProxy_test.cpp test HalProxy korzystają z fałszywych podsystemów HAL, które są tworzone w teście jednostkowym i nie są ładowane dynamicznie. Podczas tworzenia nowego podsystemu HAL te testy powinny służyć jako wskazówka, jak dodawać testy jednostkowe, które weryfikują, czy nowy podsystem HAL jest prawidłowo zaimplementowany.

Aby uruchomić testy, wykonaj te polecenia:

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

Testowanie z wykorzystaniem fałszywych sub-HAL

Fałszywe sub-HAL to fikcyjne implementacje interfejsu ISensorsSubHal. Podsystemy HAL udostępniają różne listy czujników. Po aktywowaniu czujniki okresowo publikują automatycznie wygenerowane zdarzenia czujnika w usłudze HalProxy na podstawie interwałów określonych w danym żądaniu czujnika.

Używając fałszywych podsystemów HAL, można testować, jak działa pełny kod Multi-HAL z innymi wczytanymi do systemu podsystemami HAL, oraz sprawdzać różne aspekty kodu Multi-HAL czujników.

Na stronie hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/ są dostępne 2 fałszywe sub-HAL.

Aby utworzyć fałszywe sub-HAL i przesłać je na urządzenie, wykonaj te czynności:

  1. Aby utworzyć i przesłać na urządzenie 3 różne fałszywe podsystemy HAL, uruchom te polecenia:

    $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. Zaktualizuj konfigurację HAL czujników na /vendor/etc/sensors/hals.conf, dodając ścieżki do fałszywych podkatalogów HAL.

    /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. Uruchom ponownie usługę HalProxy i załaduj nowe podrzędne części HAL wymienione w konfiguracji.

    adb shell stop
    adb shell start

Debugowanie

Deweloperzy mogą debugować platformę za pomocą polecenia lshal. Aby uzyskać dane debugowania interfejsu HAL czujników, uruchom to polecenie:

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

Informacje o bieżącym stanie instancji HalProxy i jej podrzędnych list HAL są następnie wysyłane do terminala. Poniżej znajduje się przykład danych wyjściowych polecenia dotyczącego obiektu HalProxy i fałszywych podsystemów HAL.

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

Jeśli podana w polu # of events on pending write queue liczba jest duża (co najmniej 1000), oznacza to, że w ramce czujników oczekuje na zapisanie w platformie wielu zdarzeń. Wskazuje to, że usługa czujnika jest zablokowana lub uległa awarii i nie przetwarza zdarzeń czujnika albo że z poziomu podrzędnego HAL niedawno opublikowano dużą partię zdarzeń czujnika.

Jeśli liczba odwołań do blokady aktywacji jest większa niż 0, oznacza to, że HalProxy uzyskała blokadę aktywacji. Wartość ta powinna być większa niż 0 tylko wtedy, gdy ScopedWakelock jest celowo wstrzymywany lub gdy zdarzenia aktywacji zostały wysłane do HalProxy i nie zostały przetworzone przez interfejs sensora.

Deskryptor pliku przekazywany do metody debugowania w interfejsie HalProxy jest przekazywany do każdej podrzędnej części HAL, dlatego deweloperzy muszą wdrożyć tę metodę debugowania w interfejsie ISensorsSubHal.