Czujniki Multi-HAL

Sensors Multi-HAL to platforma, która umożliwia uruchamianie interfejsów HAL czujników obok innych interfejsów HAL czujników. Wielokrotny HAL czujników dynamicznie wczytuje podrzędne HAL-e czujników przechowywane jako biblioteki dynamiczne na partycji dostawcy i przekazuje im obiekt wywołania zwrotnego, który może obsługiwać publikowanie zdarzeń oraz uzyskiwanie i zwalnianie blokady wybudzania. Pod-HAL czujników to HAL czujników wbudowany w obiekt współdzielony na partycji dostawcy, który jest używany przez platformę multi-HAL. Te podmoduły HAL nie są od siebie zależne ani od kodu multi-HAL, który zawiera główną funkcję procesu.

Sensors Multi-HAL 2.1, dostępny na urządzeniach z Androidem 11 lub nowszym, to kolejna wersja Sensors Multi-HAL 2.0, która obsługuje wczytywanie podmodułów HAL mogących udostępniać typ czujnika kąta zawiasu. Aby obsługiwać ten typ czujnika, podrzędne HAL-e muszą korzystać z interfejsów API podrzędnych HAL-i zdefiniowanych w nagłówku 2.1 SubHal.

W przypadku urządzeń z Androidem 13 lub nowszym, które korzystają z interfejsu HAL AIDL czujników, możesz użyć warstwy pośredniej multi-HAL, aby umożliwić obsługę wielu interfejsów HAL. Szczegółowe informacje o wdrażaniu znajdziesz w artykule Korzystanie z wielu interfejsów HAL czujników z interfejsem AIDL HAL czujników.

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

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

Interfejs ISensorsSubHal różni się od interfejsu 2.1/ISensors.hal (lub 2.0/ISensors.hal) w tych aspektach:

  • Metoda initialize przekazuje IHalProxyCallback klasę zamiast dwóch FMQ i ISensorsCallback.
  • Podmoduły HAL muszą implementować funkcję debugowania, która dostarcza informacji na potrzeby debugowania w raportach o błędach.
  • Podmoduły HAL muszą implementować funkcję nazwy, aby załadowany podmoduł HAL można było odróżnić od innych podmodułów HAL.

Główna różnica między Sensors Multi-HAL 2 a Sensors HAL 2 polega na funkcjach inicjowania. Zamiast FMQ interfejs IHalProxyCallback udostępnia 2 metody: jedną do przesyłania zdarzeń z czujników do platformy czujników i jedną do tworzenia blokad wybudzania. W tle warstwa Sensors Multi-HAL zarządza wszystkimi interakcjami z kolejkami FMQ, aby zapewnić terminowe dostarczanie zdarzeń z czujników do wszystkich podwarstw HAL. Zdecydowanie zalecamy, aby podmoduły HAL korzystały z metody createScopedWakelock, aby przekazywać obciążenie związane z przekroczeniem limitu czasu blokad wybudzania do modułu Sensors Multi-HAL i centralizować użycie blokad wybudzania w jednej wspólnej blokadzie wybudzania dla całego modułu Sensors Multi-HAL, co minimalizuje wywołania blokowania i odblokowywania.

Sensors Multi-HAL 2 ma też wbudowane funkcje bezpieczeństwa. Obsługuje sytuacje, w których kolejka FMQ czujnika jest pełna lub gdy platforma czujników Androida uruchamia się ponownie i stan czujnika musi zostać zresetowany. Dodatkowo, gdy zdarzenia są wysyłane do klasy HalProxy, ale platforma czujników nie może ich od razu zaakceptować, interfejs Sensors Multi-HAL może przenieść zdarzenia do wątku w tle, aby umożliwić dalszą pracę we wszystkich podrzędnych interfejsach HAL podczas oczekiwania na wysłanie zdarzeń.

Kod źródłowy i implementacja referencyjna

Cały kod Multi-HAL czujników jest dostępny w hardware/interfaces/sensors/common/default/2.X/multihal/. Oto linki do niektórych materiałów.

  • HalProxy.h: obiekt HalProxy jest tworzony przez multi-HAL czujników i odpowiada za przekazywanie danych z sub-HAL do platformy czujników.
  • HalProxy.cpp: implementacja HalProxy zawiera całą logikę potrzebną do multipleksowania komunikacji między podrzędnymi HAL-ami a platformą czujników.
  • SubHal.h: interfejs ISensorsSubHal określa interfejs, którego podrzędne warstwy HAL muszą przestrzegać, aby były zgodne z HalProxy. Pod-HAL implementuje metodę initialize, dzięki czemu obiekt HalProxyCallback może być używany 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 weryfikują implementację HalProxy.

  • hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/: Ta przykładowa implementacja podrzędnego HAL-a używa fałszywych czujników do generowania fałszywych danych. Przydatne do testowania interakcji wielu podwarstw HAL na urządzeniu.

Implementacja

W tej sekcji opisujemy, jak wdrożyć interfejs Sensors Multi-HAL w tych sytuacjach:

Używanie interfejsu Sensors Multi-HAL z interfejsem Sensors AIDL HAL

Aby umożliwić obsługę wielu HAL za pomocą interfejsu AIDL HAL czujników, zaimportuj moduł warstwy pośredniej AIDL Multi-HAL, który znajduje się w katalogu hardware/interfaces/sensors/aidl/default/multihal/. Moduł obsługuje konwersję między typami definicji AIDL i HIDL interfejsu HAL czujników oraz definiuje otokę interfejsu multi-HAL opisanego w artykule Implementowanie interfejsu multi-HAL czujników w wersji 2.1. Warstwa pośrednia AIDL multi-HAL jest zgodna z urządzeniami, które implementują Sensors Multi-HAL 2.1.

Warstwa shim AIDL multi-HAL umożliwia udostępnianie typów czujników śledzenia ruchów głowy i IMU o ograniczonej liczbie osi w interfejsie HAL czujników AIDL. 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 typu czujnika oparte na liczbach całkowitych w przypadku interfejsów AIDL i HIDL w warstwie HAL czujników nie nakładają się na siebie.

Implementacja interfejsu Sensors Multi-HAL w wersji 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 cc_library_shared cel, aby utworzyć nowo wdrożony podsystem HAL. Podczas dodawania celu:

    1. Upewnij się, że element docelowy jest umieszczony w dowolnym miejscu na partycji dostawcy urządzenia.
    2. W pliku konfiguracji znajdującym się w lokalizacji /vendor/etc/sensors/hals.conf dodaj ścieżkę do biblioteki w nowym wierszu. W razie potrzeby utwórz plik hals.conf.

    Przykład wpisu Android.bp dotyczącego tworzenia biblioteki podrzędnej HAL znajdziesz w sekcji 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 warstw 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.multihalandroid.hardware.sensors@2.1-service.multihal.rc do PRODUCT_PACKAGES.

Podczas uruchamiania HalProxy rozpoczyna działanie, wyszukuje nowo wdrożony podsystem HAL i inicjuje go, wywołując sensorsHalGetSubHal_2_1.

Przenoszenie portu z wielu interfejsów HAL czujników 2.0 do wielu interfejsów HAL 2.1

Aby przenieść Multi-HAL 2.0 do Multi-HAL 2.1, zaimplementuj interfejs SubHal i ponownie skompiluj podrzędny HAL.

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

  • IHalProxyCallback korzysta z typów utworzonych w wersji 2.1 specyfikacji ISensors.hal.
  • Funkcja initialize() przekazuje nowy obiekt IHalProxyCallback zamiast obiektu z interfejsu 2.0 SubHal.
  • Podrzędne HAL-e muszą implementować getSensorsList_2_1injectSensorData_2_1 zamiast getSensorsListinjectSensorData, ponieważ te metody korzystają z nowych typów dodanych w wersji 2.1 specyfikacji ISensors.hal.
  • Podmoduły HAL muszą udostępniać sensorsHalGetSubHal_2_1 zamiast sensorsHalGetSubHal, aby moduł Multi-HAL traktował je jako podmoduły HAL w wersji 2.1.

Port z interfejsu HAL czujników 2.0

Podczas uaktualniania do Sensors Multi-HAL 2.0 z Sensors HAL 2.0 upewnij się, że implementacja HAL spełnia te wymagania.

Inicjowanie interfejsu HAL

Interfejs HAL czujników 2.0 ma funkcję inicjowania, która umożliwia usłudze czujników przekazywanie kolejek FMQ i dynamicznego wywołania zwrotnego czujnika. W interfejsie Sensors Multi-HAL 2.0 funkcja initialize() przekazuje pojedyncze wywołanie zwrotne, które musi być używane do publikowania zdarzeń czujnika, uzyskiwania blokad wybudzania i powiadamiania o dynamicznym połączeniu i rozłączeniu czujnika.

Przesyłanie zdarzeń z czujników do implementacji Multi-HAL

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

Zdarzenia WAKE_UP

W przypadku interfejsu HAL czujników w wersji 2.0 interfejs HAL może zarządzać blokadą wybudzania w ramach swojej implementacji. W interfejsie Sensors Multi-HAL 2.0 podrzędne interfejsy HAL umożliwiają implementacji Multi-HAL zarządzanie blokadami uśpienia i mogą żądać uzyskania blokady uśpienia przez wywołanie funkcji createScopedWakelock. Zablokowane blokady wybudzania o określonym zakresie muszą być uzyskiwane i przekazywane do postEvents podczas wysyłania zdarzeń wybudzania do implementacji Multi-HAL.

Czujniki dynamiczne

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

Port z warstwy HAL czujników 1.0

Podczas uaktualniania z Sensors HAL 1.0 do Sensors Multi-HAL 2.0 upewnij się, że implementacja HAL spełnia te wymagania.

Inicjowanie interfejsu HAL

Funkcja initialize() musi być obsługiwana, aby można było ustanowić wywołanie zwrotne między podrzędnym HAL-em a implementacją Multi-HAL.

Udostępnianie dostępnych czujników

W interfejsie Sensors Multi-HAL 2.0 funkcja getSensorsList() musi zwracać tę samą wartość podczas jednego uruchomienia urządzenia, nawet po ponownym uruchomieniu interfejsu HAL czujników. Umożliwia to frameworkowi ponowne nawiązanie połączeń z czujnikami w przypadku ponownego uruchomienia serwera systemowego. Wartość zwracana przez getSensorsList() może się zmienić po ponownym uruchomieniu urządzenia.

Przesyłanie zdarzeń z czujników do implementacji Multi-HAL

W przypadku Sensors HAL 2.0 podrzędny HAL nie czeka na wywołanie funkcji poll(), ale aktywnie zapisuje zdarzenia czujnika w IHalProxyCallback, gdy tylko są dostępne.

Zdarzenia WAKE_UP

W interfejsie HAL czujników 1.0 interfejs HAL może zarządzać blokadą wybudzania w ramach swojej implementacji. W interfejsie Sensors Multi-HAL 2.0 podrzędne interfejsy HAL umożliwiają implementacji Multi-HAL zarządzanie blokadami uśpienia i mogą żądać uzyskania blokady uśpienia przez wywołanie funkcji createScopedWakelock. Zablokowane blokady wybudzania o określonym zakresie muszą być uzyskiwane i przekazywane do postEvents podczas wysyłania zdarzeń wybudzania do implementacji Multi-HAL.

Czujniki dynamiczne

W komponencie HAL czujników w wersji 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ę połączenia czujników dynamicznych. Te wywołania zwrotne są dostępne w ramach wskaźnika IHalProxyCallback, który jest udostępniany przez funkcję initialize().

Przeniesienie z Sensors 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 lokalizacji /vendor/etc/sensors/hals.conf. Może to obejmować przeniesienie pliku znajdującego się w lokalizacji /system/etc/sensors/hals.conf.
  2. Usuń wszelkie odwołania do hardware/hardware.hhardware/sensors.h, ponieważ nie są one obsługiwane w przypadku HAL 2.0.
  3. Przenieś podmoduły HAL zgodnie z opisem w sekcji Przenoszenie z modułu HAL czujników w wersji 1.0.
  4. Ustaw Sensors Multi-HAL 2.0 jako wyznaczony HAL, wykonując kroki 3 i 4 w sekcji Wdrażanie Sensors Multi-HAL 2.0.

Weryfikacja

Uruchamianie VTS

Po zintegrowaniu co najmniej jednego podmodułu HAL z interfejsem Sensors Multi-Hal 2.1 użyj zestawu testów dostawcy (VTS), aby sprawdzić, czy implementacje podmodułu HAL spełniają wszystkie wymagania interfejsu Sensors HAL.

Aby uruchomić tylko testy VTS czujników, gdy VTS jest skonfigurowany 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 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 podmodułów HAL, które są tworzone w ramach testu jednostkowego i nie są ładowane dynamicznie. Podczas tworzenia nowego podrzędnego HAL te testy powinny służyć jako wskazówki dotyczące dodawania testów jednostkowych, które weryfikują prawidłowość implementacji nowego podrzędnego HAL.

Aby uruchomić testy, wpisz te polecenia:

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

Testowanie za pomocą fałszywych podmodułów HAL

Fałszywe podmoduły HAL to przykładowe implementacje interfejsu ISensorsSubHal. Podwarstwy HAL udostępniają różne listy czujników. Gdy czujniki są aktywne, okresowo wysyłają automatycznie generowane zdarzenia czujników do HalProxy na podstawie interwałów określonych w danym żądaniu czujnika.

Fałszywe podmoduły HAL mogą służyć do testowania, jak pełny kod Multi-HAL działa z innymi podmodułami HAL załadowanymi do systemu, oraz do sprawdzania różnych aspektów kodu Multi-HAL czujników.

Dostępne są 2 fałszywe podmoduły HAL:hardware/interfaces/sensors/common/default/2.X/multihal/tests/fake_subhal/

Aby skompilować i przesłać fałszywe podmoduły HAL na urządzenie, wykonaj te czynności:

  1. Uruchom te polecenia, aby utworzyć i przenieść na urządzenie 3 różne fałszywe podwarstwy 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 w /vendor/etc/sensors/hals.conf, podając ścieżki do fałszywych podmodułó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 HalProxy i wczytaj nowe podmoduły HAL wymienione w konfiguracji.

    adb shell stop
    adb shell start

Debugowanie

Programiści mogą debugować platformę za pomocą polecenia lshal. Aby poprosić o dane wyjściowe debugowania HAL czujników, uruchom to polecenie:

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

Informacje o bieżącym stanie HalProxy i jego podmodułów HAL są następnie wyświetlane w terminalu. Poniżej znajdziesz przykład danych wyjściowych polecenia dla obiektu HalProxy i fałszywych podmodułó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 liczba podana w przypadku # of events on pending write queue jest duża (1000 lub więcej), oznacza to, że do zapisu w ramach interfejsu Sensors API oczekuje wiele zdarzeń. Oznacza to, że usługa czujnika jest zablokowana lub uległa awarii i nie przetwarza zdarzeń z czujnika albo że z podrzędnej warstwy HAL niedawno przesłano dużą partię zdarzeń z czujnika.

Jeśli liczba odwołań do blokady wybudzania jest większa niż 0, oznacza to, że HalProxy uzyskał blokadę wybudzania. Wartość ta powinna być większa od 0 tylko wtedy, gdy celowo wstrzymywane jest wysyłanie ScopedWakelock lub gdy zdarzenia wybudzania zostały wysłane do HalProxy i nie zostały jeszcze przetworzone przez platformę czujników.

Deskryptor pliku przekazywany do metody debugowania interfejsu HalProxy jest przekazywany do każdego podrzędnego interfejsu HAL, więc deweloperzy muszą zaimplementować metodę debugowania w ramach interfejsu ISensorsSubHal.