Czujniki HAL 2.0

Warstwa abstrakcji sprzętu czujników (HAL) to interfejs między strukturą czujników systemu Android a czujnikami urządzenia, takimi jak akcelerometr czy żyroskop. Sensors HAL definiuje funkcje, które muszą zostać zaimplementowane, aby umożliwić frameworkowi kontrolowanie czujników.

Czujniki HAL 2.0 są dostępne w systemie Android 10 i nowszych wersjach dla nowych i ulepszonych urządzeń. Sensors HAL 2.0 jest oparty na Sensors HAL 1.0 , ale ma kilka kluczowych różnic, które uniemożliwiają mu wsteczną kompatybilność. Sensory HAL 2.0 wykorzystuje szybkie kolejki komunikatów (FMQ) do wysyłania zdarzeń czujników z warstwy HAL do środowiska czujników systemu Android.

Czujniki HAL 2.1 są dostępne w systemie Android 11 i nowszych wersjach dla nowych i ulepszonych urządzeń. Sensors HAL 2.1 to iteracja Sensors HAL 2.0, która udostępnia typ czujnika HINGE_ANGLE i aktualizuje różne metody, aby akceptować typ HINGE_ANGLE .

Interfejs HAL 2.1

Głównym źródłem dokumentacji Sensors HAL 2.1 jest definicja HAL pod adresem hardware/interfaces/sensors/2.1/ISensors.hal . Jeśli istnieje konflikt wymagań między tą stroną a ISensors.hal , użyj wymagania w ISensors.hal .

Interfejs HAL 2.0

Głównym źródłem dokumentacji Sensors HAL 2.0 jest definicja HAL pod adresem hardware/interfaces/sensors/2.0/ISensors.hal . Jeśli istnieje konflikt wymagań między tą stroną a ISensors.hal , użyj wymagania w ISensors.hal .

Wdrożenie czujników HAL 2.0 i HAL 2.1

Aby zaimplementować Sensors HAL 2.0 lub 2.1, obiekt musi rozszerzyć interfejs ISensors i implementować wszystkie funkcje zdefiniowane w 2.0/ISensors.hal lub 2.1/ISensors.hal .

Zainicjuj warstwę HAL

Aby można było użyć warstwy HAL czujników, musi ona zostać zainicjowana przez platformę czujników systemu Android. Struktura wywołuje funkcję initialize() dla warstwy HAL 2.0 i funkcję initialize_2_1() dla warstwy HAL 2.1, aby zapewnić trzy parametry warstwie Sensors HAL: dwa deskryptory FMQ i jeden wskaźnik do obiektu ISensorsCallback .

HAL wykorzystuje pierwszy deskryptor do utworzenia zdarzenia FMQ używanego do zapisywania zdarzeń czujnika w strukturze. HAL wykorzystuje drugi deskryptor do utworzenia blokady wybudzenia FMQ używanej do synchronizacji, gdy warstwa HAL zwalnia blokadę wybudzenia dla zdarzeń czujnika WAKE_UP . HAL musi zapisać wskaźnik do obiektu ISensorsCallback , aby można było wywołać wszelkie niezbędne funkcje wywołania zwrotnego.

Funkcja initialize() lub initialize_2_1() musi być pierwszą funkcją wywoływaną podczas inicjowania warstwy HAL czujników.

Odsłoń dostępne czujniki

Aby uzyskać listę wszystkich dostępnych czujników statycznych w urządzeniu, użyj funkcji getSensorsList() w HAL 2.0 i funkcji getSensorsList_2_1() w HAL 2.1. Ta funkcja zwraca listę czujników, z których każdy jest jednoznacznie identyfikowany poprzez swój uchwyt. Uchwyt dla danego czujnika nie może się zmienić po ponownym uruchomieniu procesu obsługującego warstwę Sensors HAL. Uchwyty mogą się zmieniać po ponownym uruchomieniu urządzenia i ponownym uruchomieniu serwera systemowego.

Jeśli kilka czujników ma ten sam typ czujnika i tę samą właściwość wybudzania, pierwszy czujnik na liście nazywany jest czujnikiem domyślnym i jest zwracany do aplikacji korzystających z funkcji getDefaultSensor(int sensorType, bool wakeUp) .

Stabilność listy czujników

Jeśli po ponownym uruchomieniu Sensors HAL dane zwrócone przez getSensorsList() lub getSensorsList_2_1() wskazują na znaczącą zmianę w porównaniu z listą czujników pobraną przed ponownym uruchomieniem, struktura wyzwala ponowne uruchomienie środowiska wykonawczego Androida. Istotnymi zmianami na liście czujników są przypadki braku czujnika z danym uchwytem, ​​zmiany atrybutów lub wprowadzenie nowych czujników. Chociaż ponowne uruchomienie środowiska wykonawczego systemu Android jest uciążliwe dla użytkownika, jest to wymagane, ponieważ platforma systemu Android nie może już spełniać warunków umowy interfejsu API systemu Android, zgodnie z którą czujniki statyczne (niedynamiczne) nie zmieniają się w okresie istnienia aplikacji. Może to również uniemożliwić platformie ponowne ustanowienie aktywnych żądań czujnika wysyłanych przez aplikacje. Dlatego też zaleca się dostawcom rozwiązań HAL, aby zapobiegali zmianom list czujników, których można uniknąć.

Aby zapewnić stabilne uchwyty czujników, warstwa HAL musi deterministycznie mapować dany czujnik fizyczny w urządzeniu na jego uchwyt. Chociaż interfejs Sensors HAL nie wymaga żadnej konkretnej implementacji, programiści mają do dyspozycji wiele opcji umożliwiających spełnienie tego wymagania.

Na przykład listę czujników można posortować przy użyciu kombinacji stałych atrybutów każdego czujnika, takich jak dostawca, model i typ czujnika. Inna opcja opiera się na fakcie, że zestaw czujników statycznych urządzenia jest ustalony sprzętowo, więc warstwa HAL musi wiedzieć, kiedy wszystkie oczekiwane czujniki zakończyły inicjalizację, zanim wróci z getSensorsList() lub getSensorsList_2_1() . Tę listę oczekiwanych czujników można skompilować do pliku binarnego HAL lub zapisać w pliku konfiguracyjnym w systemie plików, a kolejność pojawiania się można wykorzystać do uzyskania stabilnych uchwytów. Chociaż najlepsze rozwiązanie zależy od konkretnych szczegółów implementacji warstwy HAL, kluczowym wymaganiem jest to, że uchwyty czujników nie zmieniają się po ponownym uruchomieniu warstwy HAL.

Skonfiguruj czujniki

Przed aktywacją czujnika należy skonfigurować czujnik z okresem próbkowania i maksymalnym opóźnieniem raportowania za pomocą funkcji batch() .

Musi istnieć możliwość ponownej konfiguracji czujnika w dowolnym momencie za pomocą batch() bez utraty danych czujnika.

Okres próbkowania

Okres próbkowania ma różne znaczenie w zależności od typu konfigurowanego czujnika:

  • Ciągłe: zdarzenia czujnika są generowane w sposób ciągły.
  • Przy zmianie: Zdarzenia są generowane nie szybciej niż okres próbkowania i mogą być generowane z częstotliwością mniejszą niż okres próbkowania, jeśli zmierzona wartość nie ulegnie zmianie.
  • One-shot: Okres próbkowania jest ignorowany.
  • Specjalne: Więcej informacji można znaleźć w części Typy czujników .

Aby dowiedzieć się więcej na temat interakcji pomiędzy okresem próbkowania a trybami raportowania czujnika, zobacz Tryby raportowania .

Maksymalne opóźnienie raportowania

Maksymalne opóźnienie raportowania określa maksymalny czas w nanosekundach, przez jaki zdarzenia mogą być opóźniane i przechowywane w sprzętowym FIFO przed zapisaniem w Event FMQ przez warstwę HAL, gdy SoC nie śpi.

Wartość zero oznacza, że ​​zdarzenia muszą być zgłaszane natychmiast po ich zmierzeniu, albo całkowicie pomijając FIFO, albo opróżniając FIFO, gdy tylko jedno zdarzenie z czujnika pojawi się w FIFO.

Na przykład akcelerometr aktywowany przy 50 Hz z maksymalnym opóźnieniem raportowania wynoszącym zero, wyzwala przerwania 50 razy na sekundę, gdy SoC jest wybudzony.

Gdy maksymalne opóźnienie raportowania jest większe od zera, zdarzenia czujnika nie muszą być zgłaszane natychmiast po ich wykryciu. Zdarzenia mogą być tymczasowo przechowywane w sprzętowym FIFO i raportowane partiami, o ile żadne zdarzenie nie jest opóźnione o więcej niż maksymalne opóźnienie raportowania. Wszystkie zdarzenia od poprzedniej partii są rejestrowane i zwracane jednocześnie. Zmniejsza to liczbę przerwań wysyłanych do SoC i pozwala SoC przełączyć się na tryb niższego poboru mocy, podczas gdy czujnik przechwytuje i grupuje dane.

Każde wydarzenie ma przypisany znacznik czasu. Opóźnienie momentu zgłoszenia zdarzenia nie może mieć wpływu na znacznik czasu zdarzenia. Znacznik czasu musi być dokładny i odpowiadać godzinie, w której zdarzenie fizycznie miało miejsce, a nie godzinie jego zgłoszenia.

Aby uzyskać dodatkowe informacje i wymagania dotyczące raportowania zdarzeń czujnika z niezerowym maksymalnym opóźnieniem raportowania, zobacz sekcję Batch .

Aktywuj czujniki

Struktura włącza i wyłącza czujniki za pomocą funkcji activate() . Przed aktywacją czujnika środowisko musi najpierw skonfigurować czujnik za pomocą batch() .

Po dezaktywacji czujnika dodatkowe zdarzenia czujnika z tego czujnika nie mogą być zapisywane w Event FMQ.

Czujniki płukania

Jeśli czujnik jest skonfigurowany do przetwarzania wsadowego danych czujnika, platforma może wymusić natychmiastowe opróżnienie zdarzeń czujnika wsadowego, wywołując funkcję flush() . Powoduje to, że zbiorcze zdarzenia czujnika dla określonego uchwytu czujnika są natychmiast zapisywane w Event FMQ. Sensors HAL musi dołączyć zdarzenie zakończenia spłukiwania na końcu zdarzeń czujnika zapisanych w wyniku wywołania funkcji flush() .

Spłukiwanie odbywa się asynchronicznie (tzn. funkcja ta musi zwrócić natychmiast). Jeśli implementacja wykorzystuje pojedyncze FIFO dla kilku czujników, to FIFO jest opróżniane i zdarzenie zakończenia płukania jest dodawane tylko dla określonego czujnika.

Jeśli określony czujnik nie ma FIFO (nie jest możliwe buforowanie) lub jeśli FIFO było puste w momencie wywołania, flush() nadal musi się powieść i wysłać zdarzenie zakończenia opróżniania dla tego czujnika. Dotyczy to wszystkich czujników innych niż czujniki jednorazowe.

Jeśli flush() zostanie wywołana dla czujnika jednorazowego, flush() musi zwrócić BAD_VALUE i nie generować zdarzenia zakończenia opróżniania.

Zapisz zdarzenia czujnika do FMQ

Event FMQ jest używany przez warstwę Sensors HAL do wypychania zdarzeń czujnika do struktury czujników systemu Android.

Event FMQ jest zsynchronizowanym FMQ, co oznacza, że ​​jakakolwiek próba zapisania większej liczby zdarzeń w FMQ, niż pozwala na to dostępna przestrzeń, kończy się niepowodzeniem. W takim przypadku warstwa HAL powinna określić, czy zapisać bieżący zestaw zdarzeń jako dwie mniejsze grupy zdarzeń, czy też zapisać wszystkie zdarzenia razem, gdy będzie dostępna wystarczająca ilość miejsca.

Gdy warstwa Sensors HAL zapisze żądaną liczbę zdarzeń czujnika do zdarzenia FMQ, warstwa Sensors HAL musi powiadomić strukturę, że zdarzenia są gotowe, zapisując bit EventQueueFlagBits::READ_AND_PROCESS do funkcji EventFlag::wake FMQ. Flagę EventFlag można utworzyć na podstawie zdarzenia FMQ przy użyciu EventFlag::createEventFlag i funkcji getEventFlagWord() zdarzenia FMQ.

Czujniki HAL 2.0/2.1 obsługują zarówno blokowanie write , jak i writeBlocking w FMQ zdarzenia. Domyślna implementacja zawiera odniesienie do używania write . Jeśli używana jest funkcja writeBlocking , flaga readNotification musi być ustawiona na EventQueueFlagBits::EVENTS_READ , która jest ustawiana przez platformę podczas odczytu zdarzeń z Event FMQ. Flaga powiadomienia o zapisie musi być ustawiona na EventQueueFlagBits::READ_AND_PROCESS , co powiadamia platformę, że zdarzenia zostały zapisane w FMQ zdarzenia.

Wydarzenia WAKE_UP

Zdarzenia WAKE_UP to zdarzenia czujnika, które powodują wybudzenie procesora aplikacji (AP) i natychmiastową obsługę zdarzenia. Za każdym razem, gdy zdarzenie WAKE_UP jest zapisywane w FMQ zdarzenia, warstwa HAL czujników musi zabezpieczyć blokadę wybudzenia, aby zapewnić, że system pozostanie w stanie czuwania do czasu, aż struktura będzie w stanie obsłużyć zdarzenie. Po odebraniu zdarzenia WAKE_UP platforma zabezpiecza własną blokadę wybudzenia, umożliwiając warstwie Sensors HAL zwolnienie blokady wybudzenia. Aby zsynchronizować moment, w którym Sensors HAL zwalnia blokadę wybudzania, użyj funkcji Wake Lock FMQ.

HAL czujników musi odczytać FMQ blokady wybudzenia, aby określić liczbę zdarzeń WAKE_UP obsłużonych przez platformę. HAL powinna zwolnić blokadę wybudzania dla zdarzeń WAKE_UP tylko wtedy, gdy całkowita liczba nieobsłużonych zdarzeń WAKE_UP wynosi zero. Po obsłużeniu zdarzeń czujnika framework zlicza liczbę zdarzeń oznaczonych jako zdarzenia WAKE_UP i zapisuje tę liczbę z powrotem do Wake Lock FMQ.

Struktura ustawia powiadomienie o zapisie WakeLockQueueFlagBits::DATA_WRITTEN w Wake Lock FMQ za każdym razem, gdy zapisuje dane do Wake Lock FMQ.

Czujniki dynamiczne

Czujniki dynamiczne to czujniki, które fizycznie nie są częścią urządzenia, ale mogą służyć jako dane wejściowe urządzenia, np. gamepad z akcelerometrem.

Po podłączeniu czujnika dynamicznego należy wywołać funkcję onDynamicSensorConnected w ISensorsCallback z poziomu warstwy Sensors HAL. Powiadamia to platformę o nowym dynamicznym czujniku i umożliwia sterowanie czujnikiem za pośrednictwem struktury oraz umożliwienie klientom wykorzystania zdarzeń czujnika.

Podobnie, gdy czujnik dynamiczny zostanie odłączony, należy wywołać funkcję onDynamicSensorDisconnected w ISensorsCallback , aby platforma mogła usunąć dowolny czujnik, który nie jest już dostępny.

Kanał bezpośredni

Kanał bezpośredni to metoda działania, w której zdarzenia czujnika są zapisywane w określonej pamięci zamiast w Event FMQ z pominięciem platformy Android Sensors Framework. Klient rejestrujący kanał bezpośredni musi odczytać zdarzenia czujnika bezpośrednio z pamięci użytej do utworzenia kanału bezpośredniego i nie będzie odbierał zdarzeń czujnika przez platformę. Funkcja configDirectReport() jest podobna do batch() w przypadku normalnego działania i konfiguruje kanał bezpośredniego raportowania.

Funkcje registerDirectChannel() i unregisterDirectChannel() tworzą lub niszczą nowy kanał bezpośredni.

Tryby pracy

Funkcja setOperationMode() umożliwia platformie skonfigurowanie czujnika w taki sposób, aby platforma mogła wstrzykiwać dane z czujnika do czujnika. Jest to przydatne do testowania, szczególnie w przypadku algorytmów istniejących poniżej frameworka.

Funkcja injectSensorData() w warstwie HAL 2.0 i funkcja injectSensorsData_2_1() w warstwie HAL 2.0 są zwykle używane do przekazywania parametrów operacyjnych do warstwy HAL czujników. Funkcji tej można również używać do wstrzykiwania zdarzeń czujnika do określonego czujnika.

Walidacja

Aby sprawdzić poprawność implementacji Sensors HAL, uruchom testy CTS i VTS sensora.

Testy CTS

Testy czujnika CTS istnieją zarówno w automatycznych testach CTS, jak i ręcznej aplikacji CTS Verifier.

Zautomatyzowane testy znajdują się w cts/tests/sensor/src/android/hardware/cts . Testy te weryfikują standardową funkcjonalność czujników, taką jak aktywacja czujników, grupowanie i częstość zdarzeń czujnika.

Testy CTS Verifier znajdują się w cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors . Testy te wymagają ręcznego wprowadzania danych przez operatora testu i zapewniają, że czujniki zgłaszają dokładne wartości.

Przejście testów CTS ma kluczowe znaczenie dla zapewnienia, że ​​testowane urządzenie spełnia wszystkie wymagania CDD.

Testy VTS

Testy VTS dla czujników HAL 2.0 znajdują się w hardware/interfaces/sensors/2.0/vts . Testy VTS dla czujników HAL 2.1 znajdują się w hardware/interfaces/sensors/2.1/vts . Testy te zapewniają, że Sensors HAL jest prawidłowo zaimplementowany i że wszystkie wymagania w ramach ISensors.hal i ISensorsCallback.hal są prawidłowo spełnione.

Uaktualnij do czujników HAL 2.1 z wersji 2.0

Podczas aktualizacji do wersji Sensors HAL 2.1 z wersji 2.0 implementacja HAL musi zawierać metody initialize_2_1() , getSensorsList_2_1() i injectSensorsData_2_1() wraz z typami HAL 2.1. Metody te muszą spełniać te same wymagania, które opisano powyżej dla HAL 2.0.

Ponieważ warstwy HAL w wersji pomocniczej muszą obsługiwać wszystkie funkcje z poprzednich warstw HAL, warstwy HAL w wersji 2.1 muszą obsługiwać inicjalizację jako warstwy HAL w wersji 2.0. Aby uniknąć złożoności obsługi obu wersji HAL, zdecydowanie zaleca się użycie Multi-HAL 2.1.

Przykład implementacji własnych czujników 2.1 HAL znajdziesz w Sensors.h .

Aktualizacja do czujników HAL 2.0 z wersji 1.0

W przypadku aktualizacji do Sensors HAL 2.0 z wersji 1.0 upewnij się, że implementacja HAL spełnia następujące wymagania.

Zainicjuj warstwę HAL

Funkcja initialize() musi być obsługiwana, aby ustanowić FMQ pomiędzy strukturą a warstwą HAL.

Odsłoń dostępne czujniki

W Sensors HAL 2.0 funkcja getSensorsList() musi zwracać tę samą wartość podczas uruchamiania pojedynczego urządzenia, nawet po ponownym uruchomieniu Sensors HAL. Nowym wymaganiem funkcji getSensorsList() jest to, że musi ona zwracać tę samą wartość podczas uruchamiania pojedynczego urządzenia, nawet po ponownym uruchomieniu warstwy Sensors HAL. 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.

Zapisz zdarzenia czujnika do FMQ

Zamiast czekać na wywołanie poll() , w Sensors HAL 2.0 warstwa Sensors HAL musi proaktywnie zapisywać zdarzenia czujnika w Event FMQ, gdy tylko zdarzenia czujnika są dostępne. HAL jest również odpowiedzialny za zapisanie poprawnych bitów do EventFlag , aby spowodować odczyt FMQ w ramach.

Wydarzenia WAKE_UP

W Sensors HAL 1.0 warstwa HAL była w stanie zwolnić blokadę wybudzenia dla dowolnego zdarzenia WAKE_UP przy każdym kolejnym wywołaniu funkcji poll() po wysłaniu WAKE_UP do poll() , ponieważ wskazywało to, że platforma przetworzyła wszystkie zdarzenia czujnika i uzyskała blokadę budzenia, jeśli to konieczne. Ponieważ w Sensors HAL 2.0 warstwa HAL nie wie już, kiedy struktura przetworzyła zdarzenia zapisane w FMQ, Wake Lock FMQ umożliwia platformie komunikację z warstwą HAL, gdy obsłuży ona zdarzenia WAKE_UP .

W Sensors HAL 2.0 blokada wybudzania zabezpieczona przez Sensors HAL dla zdarzeń WAKE_UP musi zaczynać się od SensorsHAL_WAKEUP .

Czujniki dynamiczne

Czujniki dynamiczne zostały zwrócone przy użyciu funkcji poll() w Sensors HAL 1.0. Sensors HAL 2.0 wymaga, aby onDynamicSensorsConnected i onDynamicSensorsDisconnected w ISensorsCallback 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 ISensorsCallback udostępnianego za pośrednictwem funkcji initialize() .

Tryby pracy

Tryb DATA_INJECTION dla czujników WAKE_UP musi być obsługiwany w Sensors HAL 2.0.

Obsługa wielu HAL

Sensors HAL 2.0 i 2.1 obsługują multi-HAL przy użyciu platformy Sensors Multi-HAL . Aby uzyskać szczegółowe informacje na temat implementacji, zobacz Przenoszenie z czujników HAL 1.0 .