interfejs HAL czujników 2.0,

Warstwa abstrakcji sprzętu (HAL) czujników to interfejs między platformą czujników Androida a czujnikami urządzenia, takimi jak akcelerometr czy żyroskop. Warstwa HAL czujników definiuje funkcje, które muszą być zaimplementowane, aby umożliwić platformie sterowanie czujnikami.

Interfejs HAL czujników 2.0 jest dostępny na urządzeniach z Androidem 10 i nowszym, zarówno nowych, jak i zaktualizowanych. Sensors HAL 2.0 bazuje na Sensors HAL 1.0, ale ma kilka istotnych różnic, które uniemożliwiają zachowanie zgodności wstecznej. Sensors HAL 2.0 używa szybkich kolejek wiadomości (FMQ) do wysyłania zdarzeń z czujników z HAL do platformy czujników Androida.

Interfejs HAL czujników 2.1 jest dostępny w Androidzie 11 i nowszym na nowych i zaktualizowanych urządzeniach. Sensors HAL 2.1 to kolejna wersja 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 HAL czujników 2.1 jest definicja HAL w hardware/interfaces/sensors/2.1/ISensors.hal. Jeśli występuje sprzeczność między wymaganiami na tej stronie a wymaganiami w ISensors.hal, zastosuj wymagania z ISensors.hal.

Interfejs HAL 2.0

Głównym źródłem dokumentacji HAL czujników 2.0 jest definicja HAL w pliku hardware/interfaces/sensors/2.0/ISensors.hal. Jeśli występuje sprzeczność między wymaganiami na tej stronie a wymaganiami w ISensors.hal, zastosuj wymagania z ISensors.hal.

Implementacja interfejsów HAL czujników w wersjach 2.0 i 2.1

Aby zaimplementować interfejs HAL czujników w wersji 2.0 lub 2.1, obiekt musi rozszerzać interfejs ISensors i implementować wszystkie funkcje zdefiniowane w 2.0/ISensors.hal lub 2.1/ISensors.hal.

Inicjowanie interfejsu HAL

Warstwa HAL czujników musi zostać zainicjowana przez platformę czujników Androida, zanim będzie można jej używać. Platforma wywołuje funkcję initialize() w przypadku HAL 2.0 i funkcję initialize_2_1() w przypadku HAL 2.1, aby przekazać do HAL czujników 3 parametry: 2 deskryptory FMQ i wskaźnik do obiektu ISensorsCallback.

HAL używa pierwszego deskryptora do utworzenia kolejki FMQ zdarzeń, która służy do zapisywania zdarzeń czujnika w platformie. HAL używa drugiego deskryptora do utworzenia kolejki FMQ WakeLock, która służy do synchronizacji momentu, w którym HAL zwalnia blokadę wybudzania dla WAKE_UPzdarzeń czujnika. Warstwa HAL musi zapisać wskaźnik do obiektu ISensorsCallback, aby można było wywoływać niezbędne funkcje wywołań zwrotnych.

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

Udostępnianie dostępnych czujników

Aby uzyskać listę wszystkich dostępnych czujników statycznych na 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 przez uchwyt. Uchwyt danego czujnika nie może się zmieniać, gdy proces hostujący HAL czujników zostanie ponownie uruchomiony. Uchwyty mogą się zmieniać po ponownym uruchomieniu urządzenia i serwera systemowego.

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

Stabilność listy czujników

Po ponownym uruchomieniu HAL czujników, jeśli 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, platforma wywołuje ponowne uruchomienie środowiska wykonawczego Androida. Znaczące zmiany na liście czujników obejmują przypadki, w których brakuje czujnika o danym uchwycie lub zmieniły się jego atrybuty, a także przypadki, w których pojawiły się nowe czujniki. Ponowne uruchomienie środowiska wykonawczego Androida jest uciążliwe dla użytkownika, ale konieczne, ponieważ platforma Androida nie może już spełniać warunków umowy interfejsu API Androida, zgodnie z którymi statyczne (niedynamiczne) czujniki nie zmieniają się w czasie działania aplikacji. Może to również uniemożliwić platformie ponowne nawiązanie aktywnych żądań czujników wysyłanych przez aplikacje. Dlatego dostawcom HAL zaleca się zapobieganie niepotrzebnym zmianom na liście czujników.

Aby zapewnić stabilne uchwyty czujników, HAL musi deterministycznie mapować dany czujnik fizyczny w urządzeniu na jego uchwyt. Interfejs HAL czujników nie narzuca żadnej konkretnej implementacji, ale deweloperzy mają do dyspozycji kilka opcji, które pozwalają spełnić to wymaganie.

Na przykład listę czujników można posortować, używając kombinacji stałych atrybutów każdego czujnika, takich jak dostawca, model i typ czujnika. Inna opcja polega na tym, że zestaw statycznych czujników urządzenia jest na stałe wbudowany w sprzęt, więc HAL musi wiedzieć, kiedy wszystkie oczekiwane czujniki zakończyły inicjowanie, zanim zwróci wartość z funkcji getSensorsList() lub getSensorsList_2_1(). Lista oczekiwanych czujników może być skompilowana w binarnym pliku HAL lub przechowywana w pliku konfiguracyjnym w systemie plików, a kolejność występowania może służyć do uzyskiwania stabilnych uchwytów. Chociaż najlepsze rozwiązanie zależy od szczegółów implementacji HAL, kluczowym wymaganiem jest to, aby uchwyty czujników nie zmieniały się po ponownym uruchomieniu HAL.

Konfigurowanie czujników

Przed aktywacją czujnika należy go skonfigurować, podając okres próbkowania i maksymalne opóźnienie raportowania za pomocą funkcji batch().

Czujnik musi mieć możliwość ponownej konfiguracji w dowolnym momencie za pomocą batch() bez utraty danych.

Okres próbkowania

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

  • Ciągły: zdarzenia czujnika są generowane w sposób ciągły.
  • On-change: zdarzenia są generowane nie szybciej niż w okresie próbkowania i mogą być generowane z częstotliwością mniejszą niż okres próbkowania, jeśli zmierzona wartość się nie zmienia.
  • Jednorazowe: okres próbkowania jest ignorowany.
  • Specjalne: więcej informacji znajdziesz w artykule Typy czujników.

Więcej informacji o interakcji między okresem próbkowania a trybami raportowania czujnika znajdziesz w sekcji Tryby raportowania.

Maksymalny czas oczekiwania na raport

Maksymalne opóźnienie raportowania określa maksymalny czas w nanosekundach, o jaki zdarzenia mogą być opóźnione i przechowywane w sprzętowej kolejce FIFO przed zapisaniem w kolejce FMQ zdarzeń za pomocą HAL, gdy SoC jest aktywny.

Wartość zero oznacza, że zdarzenia muszą być zgłaszane natychmiast po ich pomiarze, z pominięciem kolejki FIFO lub opróżnieniem jej, gdy tylko pojawi się w niej zdarzenie z czujnika.

Na przykład akcelerometr aktywowany z częstotliwością 50 Hz i maksymalnym opóźnieniem raportowania wynoszącym 0 wywołuje przerwania 50 razy na sekundę, gdy SoC jest aktywny.

Gdy maksymalne opóźnienie raportowania jest większe od zera, zdarzenia czujnika nie muszą być raportowane od razu po wykryciu. Zdarzenia mogą być tymczasowo przechowywane w kolejce FIFO sprzętu i zgłaszane w partiach, o ile żadne zdarzenie nie jest opóźnione o więcej niż maksymalne opóźnienie raportowania. Wszystkie zdarzenia od czasu poprzedniej partii są rejestrowane i zwracane jednocześnie. Zmniejsza to liczbę przerwań wysyłanych do układu SoC i umożliwia mu przejście w tryb niskiego zużycia energii, gdy czujnik rejestruje i grupuje dane.

Każde zdarzenie ma powiązaną z nim sygnaturę czasową. Opóźnienie czasu zgłoszenia zdarzenia nie może wpływać na sygnaturę czasową zdarzenia. Sygnatura czasowa musi być dokładna i odpowiadać czasowi, w którym zdarzenie faktycznie miało miejsce, a nie czasowi, w którym zostało zgłoszone.

Więcej informacji i wymagań dotyczących raportowania zdarzeń z czujników z niezerowym maksymalnym opóźnieniem raportowania znajdziesz w sekcji Grupowanie.

Aktywowanie czujników

Platforma włącza i wyłącza czujniki za pomocą funkcji activate(). Przed aktywowaniem czujnika platforma musi najpierw skonfigurować czujnik za pomocą funkcji batch().

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

Czujniki montowane na równi z powierzchnią

Jeśli czujnik jest skonfigurowany do przetwarzania danych czujnika w pakietach, platforma może wymusić natychmiastowe opróżnienie pakietów zdarzeń czujnika, wywołując funkcję flush(). Powoduje to natychmiastowe zapisanie w kolejce FMQ zdarzeń czujnika w pakietach dla określonego uchwytu czujnika. Warstwa HAL czujników musi dołączyć zdarzenie zakończenia opróżniania na końcu zdarzeń czujników zapisywanych w wyniku wywołania funkcji flush().

Opróżnianie bufora odbywa się asynchronicznie (tzn. ta funkcja musi natychmiast zwrócić wartość). Jeśli implementacja używa jednej kolejki FIFO dla kilku czujników, jest ona opróżniana, a zdarzenie zakończenia opróżniania jest dodawane tylko w przypadku określonego czujnika.

Jeśli określony czujnik nie ma kolejki FIFO (buforowanie jest niemożliwe) lub jeśli w momencie wywołania kolejka FIFO była pusta, funkcja flush() musi nadal działać i wysyłać zdarzenie zakończenia opróżniania dla tego czujnika. Dotyczy to wszystkich czujników innych niż czujniki jednorazowe.

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

Zapisywanie zdarzeń z czujników w FMQ

Kolejka FMQ zdarzeń jest używana przez HAL czujników do przesyłania zdarzeń czujników do platformy czujników Androida.

Kolejka FMQ zdarzeń jest zsynchronizowana, co oznacza, że każda próba zapisania w niej większej liczby zdarzeń niż pozwala na to dostępne miejsce kończy się niepowodzeniem. W takim przypadku warstwa HAL powinna określić, czy zapisać bieżący zestaw zdarzeń jako 2 mniejsze grupy zdarzeń, czy zapisać wszystkie zdarzenia razem, gdy będzie dostępna wystarczająca ilość miejsca.

Gdy HAL czujników zapisze w kolejce FMQ zdarzeń żądaną liczbę zdarzeń czujnika, musi powiadomić platformę, że zdarzenia są gotowe, zapisując bit EventQueueFlagBits::READ_AND_PROCESS w funkcji EventFlag::wake kolejki FMQ zdarzeń. Element EventFlag można utworzyć na podstawie kolejki FMQ zdarzeń za pomocą funkcji EventFlag::createEventFlaggetEventFlagWord() kolejki FMQ zdarzeń.

Interfejs HAL czujników w wersji 2.0/2.1 obsługuje zarówno write, jak i writeBlocking w przypadku kolejki FMQ zdarzeń. Domyślna implementacja zawiera odniesienie do używania write. Jeśli używana jest funkcja writeBlocking, flaga readNotification musi mieć wartość EventQueueFlagBits::EVENTS_READ, która jest ustawiana przez platformę podczas odczytywania zdarzeń z kolejki FMQ zdarzeń. Flaga powiadomienia o zapisie musi mieć wartość EventQueueFlagBits::READ_AND_PROCESS, która informuje platformę, że zdarzenia zostały zapisane w kolejce FMQ zdarzeń.

Zdarzenia WAKE_UP

WAKE_UP to zdarzenia z czujników, które powodują wybudzenie procesora aplikacji i natychmiastowe obsłużenie zdarzenia. Za każdym razem, gdy zdarzenie WAKE_UP jest zapisywane w kolejce FMQ zdarzeń, HAL czujników musi zabezpieczyć blokadę wybudzania, aby system pozostawał aktywny, dopóki platforma nie będzie mogła obsłużyć zdarzenia. Po otrzymaniu zdarzenia WAKE_UP framework zabezpiecza własną blokadę wybudzania, co pozwala warstwie HAL czujników zwolnić swoją blokadę. Aby synchronizować moment, w którym HAL czujników zwalnia blokadę wybudzania, użyj FMQ blokady wybudzania.

Warstwa HAL czujników musi odczytać FMQ blokady wybudzania, aby określić liczbę WAKE_UP zdarzeń, które obsłużyła platforma. HAL powinien zwalniać blokadę wybudzania tylko w przypadku zdarzeń WAKE_UP, jeśli łączna liczba nieobsłużonych zdarzeń WAKE_UP wynosi zero. Po obsłużeniu zdarzeń czujnika platforma zlicza liczbę zdarzeń oznaczonych jako zdarzenia WAKE_UP i zapisuje tę liczbę z powrotem w kolejce FMQ blokady wybudzania.

Framework ustawia WakeLockQueueFlagBits::DATA_WRITTEN write notification w FMQ blokady wybudzania za każdym razem, gdy zapisuje dane w FMQ blokady wybudzania.

Czujniki dynamiczne

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

Gdy podłączony jest czujnik dynamiczny, funkcja onDynamicSensorConnectedISensorsCallback musi być wywoływana z warstwy HAL czujników. Informuje to platformę o nowym czujniku dynamicznym i umożliwia sterowanie nim za pomocą platformy oraz wykorzystywanie zdarzeń czujnika przez klientów.

Podobnie, gdy dynamiczny czujnik zostanie odłączony, należy wywołać funkcję onDynamicSensorDisconnectedISensorsCallback, aby platforma mogła usunąć 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, a nie w kolejce FMQ zdarzeń, z pominięciem platformy czujników Androida. Klient, który rejestruje kanał bezpośredni, musi odczytywać zdarzenia z czujnika bezpośrednio z pamięci użytej do utworzenia kanału bezpośredniego. Nie będzie otrzymywać zdarzeń z czujnika za pomocą platformy. Funkcja configDirectReport() jest podobna do funkcji batch() w przypadku normalnego działania i konfiguruje kanał raportowania bezpośredniego.

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

Tryby działania

Funkcja setOperationMode()umożliwia platformie skonfigurowanie czujnika, aby mogła wstrzykiwać do niego dane. Jest to przydatne w przypadku testowania, zwłaszcza algorytmów, które działają poniżej struktury.

Funkcja injectSensorData() w HAL 2.0 i injectSensorsData_2_1() w HAL 2.0 jest zwykle używana do przekazywania parametrów operacyjnych do HAL czujników. Funkcja ta może też służyć do wstrzykiwania zdarzeń czujnika do konkretnego czujnika.

Weryfikacja

Aby sprawdzić implementację HAL czujników, uruchom testy CTS i VTS czujników.

Testy CTS

Testy CTS czujników są dostępne zarówno w automatycznych testach CTS, jak i w aplikacji CTS Verifier.

Automatyczne testy znajdują się w folderze cts/tests/sensor/src/android/hardware/cts. Testy te sprawdzają standardowe funkcje czujników, takie jak aktywowanie czujników, przetwarzanie wsadowe i częstotliwość zdarzeń czujnika.

Testy weryfikatora CTS znajdują się w katalogu cts/apps/CtsVerifier/src/com/android/cts/verifier/sensors. Testy te wymagają ręcznego wprowadzania danych przez operatora i zapewniają, że czujniki podają 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 interfejsu HAL czujników 2.0 znajdują się w folderze hardware/interfaces/sensors/2.0/vts. Testy VTS dla interfejsu HAL czujników 2.1 znajdują się w folderze hardware/interfaces/sensors/2.1/vts. Te testy zapewniają prawidłową implementację HAL czujników i spełnienie wszystkich wymagań określonych w dokumentach ISensors.halISensorsCallback.hal.

Uaktualnianie z wersji 2.0 do 2.1 interfejsu HAL czujników

Podczas uaktualniania z Sensors HAL 2.0 do 2.1 implementacja HAL musi zawierać metody initialize_2_1(), getSensorsList_2_1()injectSensorsData_2_1() oraz typy HAL 2.1. Te metody muszą spełniać te same wymagania, które zostały opisane powyżej w przypadku HAL 2.0.

Ponieważ HAL-e w wersji podrzędnej muszą obsługiwać wszystkie funkcje z poprzednich HAL-i, HAL-e w wersji 2.1 muszą obsługiwać inicjowanie jako HAL-e w wersji 2.0. Aby uniknąć złożoności związanej z obsługą obu wersji HAL, zdecydowanie zalecamy używanie Multi-HAL 2.1.

Przykład implementacji własnego interfejsu HAL czujników 2.1 znajdziesz w pliku Sensors.h.

Uaktualnianie z Sensors HAL 1.0 do 2.0

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

Inicjowanie interfejsu HAL

Aby można było utworzyć kolejki FMQ między platformą a HAL, musi być obsługiwana funkcja initialize().

Udostępnianie dostępnych czujników

W przypadku Sensors HAL 2.0 funkcja getSensorsList() musi zwracać tę samą wartość podczas jednego uruchomienia urządzenia, nawet po ponownym uruchomieniu Sensors HAL. Nowym wymaganiem funkcji getSensorsList() jest to, że musi ona zwracać tę samą wartość podczas jednego uruchomienia urządzenia, nawet po ponownym uruchomieniu HAL czujników. Umożliwia to platformie 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.

Zapisywanie zdarzeń z czujników w FMQ

W przypadku interfejsu HAL czujników w wersji 2.0 interfejs HAL czujników musi aktywnie zapisywać zdarzenia czujników w kolejce FMQ zdarzeń, gdy tylko są one dostępne, zamiast czekać na wywołanie funkcji poll(). HAL odpowiada też za zapisywanie odpowiednich bitów w EventFlag, aby spowodować odczyt FMQ w ramach platformy.

Zdarzenia WAKE_UP

W interfejsie HAL czujników 1.0 interfejs HAL mógł zwalniać blokadę wybudzania dla dowolnego WAKE_UPzdarzenia w dowolnym kolejnym wywołaniu funkcji poll() po wysłaniu zdarzenia WAKE_UP do funkcji poll(), ponieważ oznaczało to, że platforma przetworzyła wszystkie zdarzenia czujnika i w razie potrzeby uzyskała blokadę wybudzania. W interfejsie HAL czujników 2.0 nie ma już informacji o tym, kiedy platforma przetworzyła zdarzenia zapisane w kolejce FMQ. Kolejka FMQ blokady wybudzania umożliwia platformie przekazywanie do interfejsu HAL informacji o tym, kiedy obsłużyła WAKE_UP zdarzenia.

W interfejsie HAL czujników 2.0 blokada wybudzania zabezpieczona przez interfejs HAL czujników na potrzeby zdarzeń WAKE_UP musi zaczynać się od SensorsHAL_WAKEUP.

Czujniki dynamiczne

Czujniki dynamiczne były zwracane za pomocą funkcji poll() w interfejsie HAL czujników w wersji 1.0. Interfejs HAL czujników 2.0 wymaga, aby funkcje onDynamicSensorsConnectedonDynamicSensorsDisconnectedISensorsCallback 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 ISensorsCallback, który jest udostępniany przez funkcję initialize().

Tryby działania

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

Obsługa wielu HAL

Warstwy HAL czujników w wersjach 2.0 i 2.1 obsługują wiele warstw HAL za pomocą platformy Sensors Multi-HAL. Szczegóły implementacji znajdziesz w artykule Przenoszenie z Sensors HAL 1.0.