Czujniki wielofunkcyjne HAL

Platforma HAL Sensors Multi-HAL umożliwia działanie terminali HAL czujników razem z innymi HAL. 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. Podrzędna lista HAL czujników to takich, które są wbudowane we wspólny obiekt w partycji dostawcy i są używane przez platformę wieloskładnikową HAL. Te podrzędne części HAL nie zależą od siebie ani od kodu z wieloma HAL, który zawiera główną funkcję procesu.

Czujniki Multi-HAL 2.1, dostępne na urządzeniach z Androidem 11 lub nowszym, to iteracja funkcji Sensors Multi-HAL 2.0, która obsługuje wczytywanie podrzędnych interfejsów podrzędnych HAL, które mogą ujawniać typ kąta zawiasu. Aby obsługiwać ten typ czujnika, podrzędne interfejsy HAL muszą używać interfejsów API subHAL określonych w nagłówku SubHal 2.1.

W przypadku urządzeń z Androidem 13 lub nowszym, które korzystają z interfejsu HAL Sensors AIDL, możesz użyć warstwy z podkładką HAL, aby umożliwić obsługę wielu HAL. Szczegóły implementacji znajdziesz w artykule na temat używania czujników Multi-HAL z czujnikami AIDL HAL.

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

Czujniki Multi-HAL 2, dostępne na urządzeniach z Androidem 10 lub nowszym, dodają kilka abstrakcji oprócz interfejsu Sensors HAL 2, aby ułatwić interakcję z interfejsami HAL API. Interfejs Sensors Multi-HAL 2 wprowadza klasę HalProxy do obsługi implementacji interfejsu Sensors HAL 2 oraz interfejs V2_1/SubHal (lub V2_0/SubHal), który umożliwia usłudze HalProxy interakcję z pod-HAL.

Interfejs ISensorsSubHal różni się od interfejsu 2.1/ISensors.hal (lub 2.0/ISensors.hal) pod kilkoma względami:

  • Metoda inicjowania przekazuje klasę IHalProxyCallback zamiast dwóch FMQ i ISensorsCallback.
  • Sub-HAL muszą implementować funkcję debugowania, która umożliwia dodawanie informacji na potrzeby debugowania 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 czujnikami Multi-HAL 2 i HAL 2 czujnika występuje w funkcjach 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. Pod jej działaniem czujniki Multi-HAL zarządzają wszystkimi interakcjami z FMQ, aby na czas dostarczać zdarzenia czujnika do wszystkich podrzędnych kont HAL. Zdecydowanie zalecamy, aby podrzędne bloki uśpienia używały metody createScopedWakelock do przekazywania obciążenia czasowego wygaszania blokad uśpienia do interfejsu Sensors Multi-HAL i scentralizowania użycia tej funkcji na potrzeby jednej wspólnej blokady uśpienia dla całej platformy Sensors Multi-HAL, co minimalizuje ryzyko blokowania i odblokowywania połączeń.

Czujniki Multi-HAL 2 mają 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. Poza tym, gdy zdarzenia są publikowane w klasie HalProxy, ale platforma czujnika nie może natychmiast zaakceptować zdarzeń, interfejs Sensors Multi-HAL może przenieść te zdarzenia do wątku w tle, aby umożliwić kontynuację pracy między wszystkimi podrzędnymi produktami HAL podczas oczekiwania na opublikowanie zdarzeń.

Implementacja kodu źródłowego i referencyjnego

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

  • HalProxy.h: obiekt HalProxy jest tworzony przez Sensors Multi-HAL i obsługuje przesyłanie danych z podrzędnych list HAL do platformy czujnika.
  • HalProxy.cpp: implementacja HalProxy zawiera wszystkie funkcje logiczne niezbędne do Multipleksowania komunikacji między podrzędnymi półkami HAL a platformą czujnika.
  • SubHal.h: Interfejs ISensorsSubHal określa interfejs, który musi być używany przez podrzędne listy HAL, aby były zgodne z HalProxy. Sub-HAL implementuje metodę inicjowania, dzięki czemu obiekt HalProxyCallback może być używany na potrzeby postEvents i createScopedWakelock.

    W przypadku implementacji z wieloma HAL 2.0 użyj wersji 2.0 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 tej przykładowej implementacji kodu sub-HAL wykorzystuje się fałszywe czujniki 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 opisujemy, jak wdrożyć wiele czujników HAL czujniki 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 i definiuje kod z interfejsu multi-HAL opisany w artykule Implementowanie czujników Multi-HAL 2.1. Warstwa podkładkowa AIDL Multi-HAL jest zgodna z urządzeniami, które obsługują czujniki 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.

Zastosuj czujniki Multi-HAL 2.1

Aby wdrożyć Sensors Multi-HAL 2.1 na nowym urządzeniu, wykonaj te czynności:

  1. Zaimplementuj interfejs ISensorsSubHal w sposób opisany w SubHal.h.
  2. Zaimplementuj metodę sensorsHalGetSubHal_2_1 w SubHal.h.
  3. Dodaj cel cc_library_shared, aby utworzyć nowo wdrożoną podrzędną listę klientów (HAL). Podczas dodawania środowiska docelowego:

    1. Upewnij się, że środowisko docelowe jest przeniesione do partycji producenta 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 usługi android.hardware.sensors i pliki service.rc z pliku device.mk oraz dodaj android.hardware.sensors@2.1-service.multihal i android.hardware.sensors@2.1-service.multihal.rc do PRODUCT_PACKAGES.

Podczas uruchamiania HalProxy szuka nowo wdrożonej podrzędnej HAL i inicjuje ją, wywołując funkcję sensorsHalGetSubHal_2_1.

Port z Czujników Multi-HAL 2.0 na 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.

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

  • IHalProxyCallback korzysta z typów utworzonych w wersji 2.1 specyfikacji ISensors.hal.
  • Funkcja initialize() przekazuje nowy obiekt IHalProxyCallback zamiast tego z interfejsu SubHal 2.0
  • Sub-HAL muszą implementować getSensorsList_2_1 i injectSensorData_2_1 zamiast getSensorsList i injectSensorData, ponieważ te metody korzystają z 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

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

Inicjowanie HAL

HAL 2.0 czujnika ma funkcję inicjowania, która umożliwia usłudze czujnika przekazywanie sygnałów FMQ i dynamiczne wywołanie zwrotne czujnika. W systemie Sensors Multi-HAL 2.0 funkcja initialize() przekazuje jedno wywołanie zwrotne, które jest używane do wysyłania zdarzeń z czujnika, uzyskiwania blokad uśpienia oraz powiadamiania o dynamicznym podłączeniu i rozłączeniu czujników.

Publikuj zdarzenia z czujników w 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 ramach 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ń wybudzenia do implementacji wielu HAL należy uzyskać blokadę uśpienia o zakresie zablokowanym i przekazać ją do postEvents.

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 Czujnika 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

Do ustanowienia wywołania zwrotnego między sub-HAL a implementacją Multi-HAL musi być obsługiwana funkcja initialize().

Udostępnij dostępne czujniki

W przypadku Sensors Multi-HAL 2.0 funkcja getSensorsList() musi zwracać tę samą wartość podczas jednego uruchomienia urządzenia, nawet w przypadku ponownego uruchomienia HAL czujników. Dzięki temu platforma może spróbować ponownie nawiązać połączenia z czujnikiem po ponownym uruchomieniu serwera systemu. Wartość zwrócona przez funkcję getSensorsList() może się zmienić po ponownym uruchomieniu urządzenia.

Publikuj zdarzenia z czujników w implementacji Multi-HAL

W HAL 2.0 Sensors HAL 2.0 nie trzeba czekać na wywołanie funkcji poll(), ale podrzędna HAL musi aktywnie zapisywać zdarzenia czujnika w IHalProxyCallback, gdy tylko są dostępne.

Zdarzenia WAKE_UP

W przypadku interfejsu Sensors HAL 1.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ń wybudzenia do implementacji wielu HAL należy uzyskać blokadę uśpienia o zakresie zablokowanym i przekazać ją do postEvents.

Czujniki dynamiczne

W HAL 1.0 czujniki dynamiczne są zwracane przez funkcję poll(). 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 Czujnika Multi-HAL 1.0

Aby przenieść istniejącą implementację 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ń wszelkie odwołania do hardware/hardware.h i hardware/sensors.h, ponieważ nie są one obsługiwane przez HAL 2.0.
  3. Sub-HAL portów zgodnie z opisem w sekcji Przenoszenie z Sensors Hal 1.0.
  4. Jako wyznaczoną HAL ustaw Sensors Multi-HAL 2.0, wykonując kroki 3 i 4 z sekcji Implementing Sensors Mutli-HAL 2.0 (Implementowanie czujników z komponentami HAL 2.0).

Weryfikacja

Uruchom 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 HAL spełniają wszystkie wymagania określone w interfejsie Sensors HAL.

Aby uruchomić tylko testy VTS czujników po skonfigurowaniu VTS na hoście, 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 ramach testu HalProxy_test.cppHalProxy z wykorzystaniem fałszywych podrzędnych list HAL, które są tworzone w teście jednostkowym i nie są ładowane dynamicznie. Podczas tworzenia nowej podrzędnej HAL testy te powinny służyć za wskazówkę przy dodawaniu testów jednostkowych sprawdzających, czy nowa wersja podrzędna HAL została 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. Sub-HAL zawierają różne listy czujników. Gdy czujniki są aktywowane, co jakiś czas wysyłają do HalProxy automatycznie wygenerowane zdarzenia dotyczące czujnika w odstępach czasu określonych w danym żądaniu dotyczącym czujnika.

Fałszywe sub-HAL można wykorzystać do przetestowania, jak pełny kod Multi-HAL działa z innymi subkontami podrzędnymi wczytywanymi do systemu, oraz do podkreślenia różnych aspektów kodu Multi-HAL czujnika.

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

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

  1. Uruchom następujące polecenia, aby utworzyć i przekazać na urządzenie 3 różne fałszywe klucze Sub-HAL:

    $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 poprosić o dane wyjściowe debugowania interfejsu HAL Sensors, 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 znajdziesz przykład danych wyjściowych polecenia dla obiektu HalProxy i fałszywych list podrzędnych 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ń. Oznacza to, że usługa czujnika jest zablokowana, uległa awarii i nie przetwarza zdarzeń z czujnika lub że duża porcja takich zdarzeń została niedawno opublikowana z poziomu podrzędnej HAL.

Jeśli liczba referencji blokady uśpienia przekracza 0, oznacza to, że aplikacja HalProxy nawiązała blokadę uśpienia. Wartość powinna być większa od 0 tylko wtedy, gdy ScopedWakelock został celowo wstrzymany lub zdarzenia wybudzenia zostały wysłane do HalProxy i nie zostały przetworzone przez platformę czujnika.

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.