Czujniki Multi-HAL

Sensors Multi-HAL to platforma, która umożliwia współpracę czujników HAL z innymi czujnikami HAL. Sensors Multi-HAL dynamicznie ładuje pod-HAL czujników przechowywane jako biblioteki dynamiczne na partycji dostawcy i udostępnia im obiekt wywołania zwrotnego, który może obsłużyć wysyłanie zdarzeń oraz pozyskiwanie i zwalnianie blokady wybudzania. Sub-HAL czujników to warstwa HAL czujników wbudowana we współdzielony obiekt na partycji dostawcy i używana przez platformę multi-HAL. Te pod-HAL nie zależą od siebie nawzajem ani od kodu multi-HAL, który zawiera główną funkcję procesu.

Sensors Multi-HAL 2.1, dostępny na urządzeniach z systemem Android 11 lub nowszym, to wersja Sensors Multi-HAL 2.0, która obsługuje ładowanie sub-HAL, które mogą ujawnić typ czujnika kąta zawiasu . Aby obsługiwać ten typ czujnika, sub-HAL muszą używać interfejsów API sub-HAL zdefiniowanych w nagłówku SubHal 2.1 .

W przypadku urządzeń z systemem Android 13 lub nowszym, które korzystają z czujników AIDL HAL , można użyć warstwy podkładki multi-HAL, aby umożliwić obsługę multi-HAL. Aby poznać szczegóły implementacji, zobacz Używanie czujników Multi-HAL z czujnikami AIDL HAL .

Różnica pomiędzy czujnikami Multi-HAL 2 i czujnikami HAL 2

Sensors Multi-HAL 2, dostępny na urządzeniach z systemem Android 10 lub nowszym, oprócz Sensors HAL 2 wprowadza kilka abstrakcji, aby ułatwić interakcję z interfejsami API HAL. Sensors Multi-HAL 2 wprowadza klasę HalProxy do obsługi implementacji interfejsu Sensors HAL 2 i interfejsu V2_1/SubHal (lub V2_0/SubHal ), aby umożliwić HalProxy interakcję z podrzędnymi warstwami HAL.

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

  • Metoda inicjalizacji przekazuje klasę IHalProxyCallback zamiast dwóch FMQ i ISensorsCallback .
  • Sub-HAL muszą implementować funkcję debugowania w celu dostarczania informacji debugowania w raportach o błędach.
  • Sub-HAL muszą implementować funkcję nazwy, aby załadowana pod-HAL mogła zostać odróżniona od innych pod-HAL.

Główna różnica pomiędzy Sensors Multi-HAL 2 i Sensors HAL 2 polega na funkcjach inicjalizacji. Zamiast udostępniać FMQ, interfejs IHalProxyCallback udostępnia dwie metody, jedną metodę wysyłania zdarzeń czujnika do struktury czujników i jedną metodę tworzenia blokad uśpienia. Pod maską Sensors Multi-HAL zarządza wszystkimi interakcjami z FMQ, aby zapewnić terminowe dostarczanie zdarzeń z czujników dla wszystkich sub-HAL. Zdecydowanie zaleca się, aby podrzędne warstwy HAL korzystały z metody createScopedWakelock w celu delegowania ciężaru związanego z przekroczeniem limitu czasu blokad wybudzenia na warstwę Sensors Multi-HAL i aby scentralizować użycie blokady wybudzenia w jednej wspólnej blokadzie wybudzenia dla całej warstwy Sensors Multi-HAL, co minimalizuje blokowanie i odblokowywanie dzwoni.

Czujniki Multi-HAL 2 posiadają także wbudowane funkcje bezpieczeństwa. Obsługuje sytuacje, w których FMQ czujnika jest zapełnione lub gdy środowisko czujnika Android uruchamia się ponownie i konieczne jest zresetowanie stanu czujnika. Dodatkowo, gdy zdarzenia są wysyłane do klasy HalProxy , ale struktura czujnika nie jest w stanie natychmiast ich zaakceptować, Sensors Multi-HAL może przenieść zdarzenia do wątku w tle, aby umożliwić kontynuację pracy we wszystkich podrzędnych warstwach HAL podczas oczekiwania na zdarzenia Do wysłania.

Kod źródłowy i implementacja referencyjna

Kod Multi-HAL wszystkich czujników jest dostępny w hardware/interfaces/sensors/common/default/2.X/multihal/ . Oto wskazówki do niektórych zasobów.

  • HalProxy.h : Obiekt HalProxy jest tworzony przez technologię Sensors multi-HAL i obsługuje przekazywanie danych z podrzędnych warstw HAL do struktury czujnika.
  • HalProxy.cpp : Implementacja HalProxy zawiera całą logikę potrzebną do multipleksowania komunikacji pomiędzy podrzędnymi warstwami HAL i strukturą czujników.
  • SubHal.h : Interfejs ISensorsSubHal definiuje interfejs, którego muszą przestrzegać sub-HAL, aby były kompatybilne z HalProxy . Sub-HAL implementuje metodę inicjowania, dzięki czemu obiekt HalProxyCallback może być używany dla postEvents i createScopedWakelock .

    W przypadku implementacji Multi-HAL 2.0 użyj wersji 2.0 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 sub-HAL wykorzystuje fałszywe czujniki do generowania fałszywych danych. Przydatne do testowania interakcji wielu sub-HAL na urządzeniu.

Realizacja

W tej sekcji opisano, jak wdrożyć Sensors Multi-HAL w następujących sytuacjach:

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

Aby umożliwić obsługę wielu HAL za pomocą Sensors AIDL HAL, zaimportuj moduł warstwy podkładki AIDL Multi-HAL, który można znaleźć w hardware/interfaces/sensors/aidl/default/multihal/ . Moduł obsługuje konwersję pomiędzy typami definicji HAL czujników AIDL i HIDL oraz definiuje opakowanie wokół interfejsu multi-HAL opisanego w Implementing Sensors Multi-HAL 2.1 . Warstwa podkładkowa AIDL multi-HAL jest kompatybilna z urządzeniami obsługującymi Sensors Multi-HAL 2.1.

Warstwa podkładki AIDL multi-HAL umożliwia wyeksponowanie czujników śledzenia głowy i czujników IMU o ograniczonej osi w czujnikach AIDL HAL. Aby używać 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 czujników AIDL i HIDL HAL nie nakładają się.

Czujniki wdrożenia Multi-HAL 2.1

Aby wdrożyć Sensors Multi-HAL 2.1 na nowym urządzeniu, wykonaj następujące kroki:

  1. Zaimplementuj interfejs ISensorsSubHal zgodnie z opisem w SubHal.h .
  2. Zaimplementuj metodę sensorsHalGetSubHal_2_1 w SubHal.h .
  3. Dodaj cel cc_library_shared , aby zbudować nowo zaimplementowaną sub-HAL. Podczas dodawania celu:

    1. Upewnij się, że cel został wypchnięty gdzieś na partycję dostawcy urządzenia.
    2. W pliku konfiguracyjnym znajdującym się pod /vendor/etc/sensors/hals.conf dodaj w nowej linii ścieżkę do biblioteki. Jeśli to konieczne, utwórz plik hals.conf .

    Przykładowy wpis Android.bp dotyczący budowania biblioteki sub-HAL można znaleźć w 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 pliki android.hardware.sensors service i service.rc z pliku device.mk i dodaj android.hardware.sensors@2.1-service.multihal i android.hardware.sensors@2.1-service.multihal.rc do PRODUCT_PACKAGES .

Podczas rozruchu HalProxy uruchamia się, szuka nowo zaimplementowanej warstwy podrzędnej HAL i inicjuje ją, wywołując sensorsHalGetSubHal_2_1 .

Port z czujników Multi-HAL 2.0 na Multi-HAL 2.1

Aby przenieść z Multi-HAL 2.0 do Multi-HAL 2.1, zaimplementuj interfejs SubHal i przekompiluj sub-HAL.

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

  • IHalProxyCallback wykorzystuje typy utworzone w wersji 2.1 specyfikacji ISensors.hal .
  • Funkcja initialize() przekazuje nowe IHalProxyCallback zamiast tego z interfejsu SubHal 2.0
  • Sub-HAL muszą implementować metody getSensorsList_2_1 i injectSensorData_2_1 zamiast getSensorsList i injectSensorData , ponieważ metody te korzystają z nowych typów dodanych w wersji 2.1 specyfikacji ISensors.hal .
  • Sub-HAL muszą udostępniać sensorsHalGetSubHal_2_1 zamiast sensorsHalGetSubHal , aby Multi-HAL traktował je jako sub-HAL w wersji 2.1.

Port z czujników HAL 2.0

W przypadku aktualizacji do Sensors Multi-HAL 2.0 z Sensors HAL 2.0 należy upewnić się, że implementacja HAL spełnia następujące wymagania.

Zainicjuj warstwę HAL

Czujniki HAL 2.0 posiada funkcję inicjowania, która umożliwia usłudze czujnika przekazywanie FMQ i dynamicznego wywołania zwrotnego czujnika. W Sensors Multi-HAL 2.0 funkcja initialize() przekazuje pojedyncze wywołanie zwrotne, które musi zostać użyte do wysyłania zdarzeń z czujnika, uzyskiwania blokad wybudzania i powiadamiania o dynamicznych połączeniach i rozłączeniach czujników.

Publikuj zdarzenia czujnika w implementacji Multi-HAL

Zamiast wysyłać zdarzenia czujnika przez FMQ, podrzędna warstwa HAL musi zapisywać zdarzenia czujnika do IHalProxyCallback , gdy zdarzenia czujnika są dostępne.

Wydarzenia WAKE_UP

W Sensors HAL 2.0 warstwa HAL może zarządzać blokadą wybudzania w celu jej wdrożenia. W Sensors Multi-HAL 2.0 podwarstwy HAL umożliwiają implementacji Multi-HAL zarządzanie blokadami uśpienia i mogą zażądać uzyskania blokady uśpienia poprzez wywołanie createScopedWakelock . Podczas wysyłania zdarzeń wybudzenia do implementacji Multi-HAL należy uzyskać blokadę uśpienia o zablokowanym zakresie i przekazać ją do postEvents .

Czujniki dynamiczne

Sensors Multi-HAL 2.0 wymaga, aby onDynamicSensorsConnected i onDynamicSensorsDisconnected w IHalProxyCallback były wywoływane za każdym razem, gdy zmieniają się połączenia czujników dynamicznych. Te wywołania zwrotne są dostępne jako część wskaźnika IHalProxyCallback udostępnianego za pośrednictwem funkcji initialize() .

Port z czujników HAL 1.0

W przypadku aktualizacji do wersji Sensors Multi-HAL 2.0 z wersji Sensors HAL 1.0 należy upewnić się, że implementacja HAL spełnia następujące wymagania.

Zainicjuj warstwę HAL

Funkcja initialize() musi być obsługiwana, aby ustanowić wywołanie zwrotne pomiędzy implementacją sub-HAL i Multi-HAL.

Odsłoń dostępne czujniki

W Sensors Multi-HAL 2.0 funkcja getSensorsList() musi zwracać tę samą wartość podczas uruchamiania pojedynczego urządzenia, nawet po ponownym uruchomieniu HAL czujników. Dzięki temu struktura może podjąć próbę ponownego nawiązania połączenia z czujnikiem w przypadku ponownego uruchomienia serwera systemowego. Wartość zwrócona przez getSensorsList() może ulec zmianie po ponownym uruchomieniu urządzenia.

Publikuj zdarzenia czujnika w implementacji Multi-HAL

W Sensors HAL 2.0, zamiast czekać na wywołanie poll() , sub-HAL musi proaktywnie zapisywać zdarzenia czujników do IHalProxyCallback , gdy tylko zdarzenia czujnika są dostępne.

Wydarzenia WAKE_UP

W Sensors HAL 1.0 warstwa HAL może zarządzać blokadą wybudzania w celu jej wdrożenia. W Sensors Multi-HAL 2.0 podrzędne warstwy HAL umożliwiają implementacji Multi-HAL zarządzanie blokadami uśpienia i mogą zażądać uzyskania blokady uśpienia poprzez wywołanie createScopedWakelock . Podczas wysyłania zdarzeń wybudzenia do implementacji Multi-HAL należy uzyskać blokadę uśpienia o zablokowanym zakresie i przekazać ją do postEvents .

Czujniki dynamiczne

W Sensors HAL 1.0 czujniki dynamiczne są zwracane poprzez funkcję poll() . Sensors Multi-HAL 2.0 wymaga, aby onDynamicSensorsConnected i onDynamicSensorsDisconnected w IHalProxyCallback były wywoływane za każdym razem, gdy zmieniają się połączenia czujników dynamicznych. Te wywołania zwrotne są dostępne jako część wskaźnika IHalProxyCallback udostępnianego za pośrednictwem funkcji initialize() .

Port z czujników Multi-HAL 1.0

Aby przenieść istniejącą implementację z Sensors Multi-HAL 1.0 , wykonaj następujące kroki.

  1. Upewnij się, że konfiguracja HAL czujników znajduje się w /vendor/etc/sensors/hals.conf. Może to obejmować przeniesienie pliku znajdującego się w /system/etc/sensors/hals.conf .
  2. Usuń wszelkie odniesienia do hardware/hardware.h i hardware/sensors.h ponieważ nie są one obsługiwane przez HAL 2.0.
  3. Port sub-HAL zgodnie z opisem w sekcji Porting from Sensors Hal 1.0 .
  4. Ustaw Sensors Multi-HAL 2.0 jako wyznaczoną warstwę HAL, wykonując kroki 3 i 4 w sekcji Implementowanie Sensors Mutli-HAL 2.0 .

Walidacja

Uruchom VTS

Jeśli zintegrujesz jedną lub więcej sub-HAL z Sensors Multi-Hal 2.1, użyj pakietu Vendor Test Suite (VTS) , aby upewnić się, że Twoje implementacje sub-HAL spełniają wszystkie wymagania określone przez interfejs Sensors HAL.

Aby uruchomić tylko testy czujników VTS, gdy VTS jest skonfigurowany na komputerze głównym, wykonaj następujące 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ładki AIDL Multi-HAL, uruchom VtsAidlHalSensorsTargetTest .

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

Uruchom testy jednostkowe

Testy jednostkowe w HalProxy_test.cpp testują HalProxy przy użyciu fałszywych podrzędnych warstw HAL, które są tworzone w teście jednostkowym i nie są ładowane dynamicznie. Podczas tworzenia nowej pod-HAL testy te powinny służyć jako wskazówka, jak dodać testy jednostkowe weryfikujące, czy nowa pod-HAL jest poprawnie zaimplementowana.

Aby uruchomić testy, wykonaj następujące polecenia:

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

Przetestuj z fałszywymi sub-HAL

Fałszywe sub-HAL są fikcyjnymi implementacjami interfejsu ISensorsSubHal . Sub-HAL udostępniają różne listy czujników. Gdy czujniki są aktywowane, okresowo wysyłają automatycznie wygenerowane zdarzenia czujnika do HalProxy w oparciu o interwały określone w danym żądaniu czujnika.

Fałszywych warstw podrzędnych HAL można używać do testowania działania pełnego kodu Multi-HAL z innymi podrzędnymi warstwami HAL załadowanymi do systemu oraz do podkreślania różnych aspektów kodu Multi-HAL czujników.

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

Aby zbudować i wypchnąć fałszywe sub-HAL do urządzenia, wykonaj następujące kroki:

  1. Uruchom następujące polecenia, aby zbudować i wypchnąć trzy różne fałszywe warstwy podrzędne HAL do urządzenia:

    $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 sub-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 załaduj nowe podrzędne warstwy HAL wymienione w pliku config.

    adb shell stop
    adb shell start
    

Debugowanie

Programiści mogą debugować framework za pomocą polecenia lshal . Aby zażądać wyników debugowania warstwy Sensors HAL, uruchom następującą komendę:

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

Informacje o bieżącym stanie HalProxy i jego sub-HAL są następnie wysyłane do terminala. Poniżej pokazano przykład wyniku polecenia dla obiektu HalProxy i fałszywych sub-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 określona dla # of events on pending write queue jest duża (1000 lub więcej), oznacza to, że istnieje wiele zdarzeń oczekujących na zapis w strukturze czujników. Oznacza to, że usługa czujnika jest zablokowana, uległa awarii i nie przetwarza zdarzeń czujnika, lub że niedawno opublikowano dużą partię zdarzeń czujnika z podrzędnej warstwy HAL.

Jeśli liczba ref. blokady wybudzenia jest większa niż 0 , oznacza to, że HalProxy uzyskał blokadę wybudzenia. Wartość ta powinna być większa od 0 , jeśli celowo wstrzymywano ScopedWakelock lub jeśli zdarzenia wybudzania zostały wysłane do HalProxy i nie zostały przetworzone przez strukturę czujnika.

Deskryptor pliku przekazany do metody debugowania HalProxy jest przekazywany do każdej podrzędnej warstwy HAL, więc programiści muszą zaimplementować metodę debugowania jako część interfejsu ISensorsSubHal .