interfejs HAL czujników 1.0,

Interfejs HAL czujników, zadeklarowany w pliku sensors.h, reprezentuje interfejs między platformą Androida a oprogramowaniem specyficznym dla sprzętu. Implementacja HAL musi definiować każdą funkcję zadeklarowaną w pliku sensors.h. Główne funkcje to:

  • get_sensors_list – zwraca listę wszystkich czujników.
  • activate – uruchamia lub zatrzymuje czujnik.
  • batch – ustawia parametry czujnika, takie jak częstotliwość próbkowania i maksymalne opóźnienie raportowania.
  • setDelay – używane tylko w HAL w wersji 1.0. Ustawia częstotliwość próbkowania dla danego czujnika.
  • flush – opróżnia kolejkę FIFO określonego czujnika i gdy to zrobi, zgłasza zdarzenie zakończenia opróżniania.
  • poll – zwraca dostępne zdarzenia czujnika.

Implementacja musi być bezpieczna dla wątków i umożliwiać wywoływanie tych funkcji z różnych wątków.

Interfejs definiuje też kilka typów używanych przez te funkcje. Główne typy to:

  • sensors_module_t
  • sensors_poll_device_t
  • sensor_t
  • sensors_event_t

Oprócz informacji w sekcjach poniżej więcej informacji o tych typach znajdziesz w pliku sensors.h.

get_sensors_list(list)

int (*get_sensors_list)(struct sensors_module_t* module, struct sensor_t
  const** list);

Zawiera listę czujników zaimplementowanych przez HAL. Szczegółowe informacje o tym, jak są zdefiniowane czujniki, znajdziesz w sekcji sensor_t.

Kolejność, w jakiej czujniki pojawiają się na liście, jest kolejnością, w jakiej będą zgłaszane aplikacjom. Zwykle najpierw pojawiają się czujniki podstawowe, a potem czujniki złożone.

Jeśli kilka czujników ma ten sam typ i właściwość wybudzania, pierwszy z nich na liście jest nazywany czujnikiem „domyślnym”. Jest to wartość zwracana przez funkcję getDefaultSensor(int sensorType, bool wakeUp).

Ta funkcja zwraca liczbę czujników na liście.

activate(sensor, true/false)

int (*activate)(struct sensors_poll_device_t *dev, int sensor_handle, int
  enabled);

Aktywuje lub dezaktywuje czujnik.

sensor_handle to uchwyt czujnika, który służy do aktywowania i dezaktywowania. Uchwyt czujnika jest zdefiniowany przez pole handle w strukturze sensor_t.

enabled ma wartość 1, aby włączyć czujnik, lub 0, aby go wyłączyć.

Czujniki jednorazowe dezaktywują się automatycznie po otrzymaniu zdarzenia i muszą nadal akceptować dezaktywację za pomocą wywołania funkcji activate(..., enabled=0).

Czujniki wybudzania nigdy nie uniemożliwiają przejścia układu SoC w tryb zawieszenia. Oznacza to, że HAL nie może utrzymywać częściowej blokady uśpienia w imieniu aplikacji.

Czujniki wybudzania, gdy stale dostarczają zdarzenia, mogą uniemożliwiać przejście układu SoC w tryb zawieszenia, ale jeśli nie trzeba dostarczać żadnego zdarzenia, należy zwolnić częściową blokadę wybudzania.

Jeśli wartość enabled wynosi 1 i czujnik jest już aktywowany, ta funkcja nie powoduje żadnych skutków i działa prawidłowo.

Jeśli wartość enabled wynosi 0, a czujnik jest już dezaktywowany, ta funkcja nie wykonuje żadnych działań i zwraca wartość true.

W przypadku powodzenia ta funkcja zwraca wartość 0, a w przeciwnym razie ujemny numer błędu.

batch(sensor, flags, sampling period, maximum report latency)

int (*batch)(
     struct sensors_poll_device_1* dev,
     int sensor_handle,
     int flags,
     int64_t sampling_period_ns,
     int64_t max_report_latency_ns);

Ustawia parametry czujnika, w tym częstotliwość próbkowaniamaksymalne opóźnienie raportu. Funkcję tę można wywołać, gdy czujnik jest aktywny. W takim przypadku nie może ona powodować utraty żadnych pomiarów czujnika: przejście z jednej częstotliwości próbkowania na inną nie może powodować utraty zdarzeń, podobnie jak przejście z wysokiego maksymalnego opóźnienia raportu na niskie maksymalne opóźnienie raportu.

sensor_handle to uchwyt czujnika do skonfigurowania.

flags jest obecnie nieużywane.

sampling_period_ns to okres próbkowania, w którym czujnik powinien działać, podany w nanosekundach. Więcej informacji znajdziesz w sekcji sampling_period_ns.

max_report_latency_ns to maksymalny czas, o jaki zdarzenia mogą być opóźnione przed zgłoszeniem przez HAL, w nanosekundach. Więcej informacji znajdziesz w akapitach dotyczących parametru max_report_latency_ns.

W przypadku powodzenia ta funkcja zwraca wartość 0, a w przeciwnym razie ujemny numer błędu.

setDelay(sensor, sampling period)

int (*setDelay)(
     struct sensors_poll_device_t *dev,
     int sensor_handle,
     int64_t sampling_period_ns);

Po wersji HAL 1.0 ta funkcja jest wycofana i nigdy nie jest wywoływana. Zamiast tego wywoływana jest funkcja batch, aby ustawić parametr sampling_period_ns.

W HAL w wersji 1.0 zamiast funkcji batch używano funkcji setDelay do ustawiania wartości sampling_period_ns.

flush(sensor)

int (*flush)(struct sensors_poll_device_1* dev, int sensor_handle);

Dodaje zdarzenie zakończenia opróżniania na końcu kolejki FIFO sprzętu dla określonego czujnika i opróżnia kolejkę FIFO.Te zdarzenia są dostarczane jak zwykle (tzn. tak jakby upłynął maksymalny czas oczekiwania na raport) i usuwane z kolejki FIFO.

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 w momencie wywołania kolejka FIFO była pusta, funkcja flush musi się zakończyć powodzeniem i wysłać zdarzenie zakończenia opróżniania dla tego czujnika. Dotyczy to wszystkich czujników innych niż czujniki jednorazowe.

Gdy wywoływana jest funkcja flush, nawet jeśli w kolejce FIFO danego czujnika znajduje się już zdarzenie opróżniania, należy utworzyć dodatkowe zdarzenie i dodać je na końcu kolejki FIFO, a następnie opróżnić kolejkę FIFO. Liczba wywołań flush musi być równa liczbie utworzonych zdarzeń zakończenia opróżniania.

flush nie dotyczy czujników jednorazowych; jeśli sensor_handle odnosi się do czujnika jednorazowego, flush musi zwrócić -EINVAL i nie generować żadnego zdarzenia metadanych o zakończeniu opróżniania.

W przypadku powodzenia ta funkcja zwraca wartość 0, w przypadku, gdy określony czujnik jest czujnikiem jednorazowym lub nie został włączony, zwraca wartość -EINVAL, a w pozostałych przypadkach zwraca ujemny numer błędu.

poll()

int (*poll)(struct sensors_poll_device_t *dev, sensors_event_t* data, int
  count);

Zwraca tablicę danych z czujnika, wypełniając argument data. Ta funkcja musi blokować działanie do momentu, aż będą dostępne zdarzenia. W przypadku powodzenia zwraca liczbę odczytanych zdarzeń, a w przypadku błędu – ujemny numer błędu.

Liczba zdarzeń zwróconych w data musi być mniejsza lub równa argumentowi count. Ta funkcja nigdy nie powinna zwracać wartości 0 (brak zdarzenia).

Kolejność wywołań

Po uruchomieniu urządzenia wywoływana jest funkcja get_sensors_list.

Gdy czujnik zostanie aktywowany, funkcja batch zostanie wywołana z żądanymi parametrami, a następnie activate(..., enable=1).

W wersji HAL 1.0 kolejność była odwrotna: najpierw wywoływano funkcję activate, a potem set_delay.

Gdy żądane charakterystyki czujnika zmieniają się w trakcie jego aktywacji, wywoływana jest funkcja batch.

flush można wywołać w dowolnym momencie, nawet w przypadku nieaktywnych czujników (w takim przypadku musi zwrócić wartość -EINVAL).

Gdy czujnik zostanie dezaktywowany, wywoływana jest funkcja activate(..., enable=0).

Równolegle do tych wywołań funkcja poll będzie wielokrotnie wywoływana w celu zażądania danych. poll można wywołać nawet wtedy, gdy żaden czujnik nie jest aktywny.

sensors_module_t

sensors_module_t to typ używany do tworzenia modułu sprzętowego Androida na potrzeby czujników. Implementacja HAL musi definiować obiektHAL_MODULE_INFO_SYM tego typu, aby udostępniać funkcję get_sensors_list. Więcej informacji znajdziesz w definicji sensors_module_t w pliku sensors.h oraz w definicji hw_module_t.

sensors_poll_device_t / sensors_poll_device_1_t

sensors_poll_device_1_t zawiera pozostałe metody zdefiniowane powyżej: activate, batch, flush i poll. Pole common (typu hw_device_t) określa numer wersji HAL.

sensor_t

sensor_t oznacza czujnik Androida. Oto niektóre z jego ważnych pól:

name: ciąg znaków widoczny dla użytkownika, który reprezentuje czujnik. Ten ciąg tekstowy często zawiera nazwę części bazowego czujnika, typ czujnika i informację o tym, czy jest to czujnik wybudzania. Na przykład „LIS2HH12 Accelerometer”, „MAX21000 Uncalibrated Gyroscope”, „BMP280 Wake-up Barometer”, „MPU6515 Game Rotation Vector”

handle: liczba całkowita używana do odwoływania się do czujnika podczas rejestrowania go lub generowania z niego zdarzeń.

type: typ czujnika. Więcej informacji o typach czujników znajdziesz w artykule Czym są czujniki Androida?, a oficjalne typy czujników znajdziesz w sekcji Typy czujników. W przypadku nieoficjalnych typów czujników wartość type musi zaczynać się od SENSOR_TYPE_DEVICE_PRIVATE_BASE.

stringType: typ czujnika jako ciąg znaków. Jeśli czujnik ma oficjalny typ, ustaw wartość SENSOR_STRING_TYPE_*. Jeśli czujnik ma typ specyficzny dla producenta, stringType musi zaczynać się od odwróconej nazwy domeny producenta. Na przykład czujnik (np. wykrywacz jednorożców) zdefiniowany przez zespół Cool-product w firmie Fictional-Company może używać stringType=”com.fictional_company.cool_product.unicorn_detector”. Symbol stringType służy do jednoznacznej identyfikacji typów nieoficjalnych czujników. Więcej informacji o typach i typach ciągów znajdziesz w pliku sensors.h.

requiredPermission: ciąg znaków reprezentujący uprawnienie, które aplikacje muszą mieć, aby widzieć czujnik, rejestrować się w nim i otrzymywać jego dane. Pusty ciąg znaków oznacza, że aplikacje nie wymagają żadnych uprawnień, aby uzyskać dostęp do tego czujnika. Niektóre typy czujników, np. monitor tętna, mają obowiązkowy requiredPermission. Wszystkie czujniki dostarczające wrażliwe informacje o użytkowniku (np. tętno) muszą być chronione przez uprawnienia.

flags: flagi tego czujnika określające tryb raportowania czujnika i to, czy jest on czujnikiem wybudzania. Na przykład czujnik jednorazowego wybudzania będzie miał wartość flags = SENSOR_FLAG_ONE_SHOT_MODE | SENSOR_FLAG_WAKE_UP. Bity flagi, które nie są używane w bieżącej wersji HAL, muszą mieć wartość 0.

maxRange: maksymalna wartość, jaką może zgłosić czujnik, w tej samej jednostce co zgłaszane wartości. Czujnik musi być w stanie podawać wartości bez osiągania stanu nasycenia w ciągu [-maxRange; maxRange]. Pamiętaj, że oznacza to, że całkowity zakres czujnika w sensie ogólnym wynosi 2*maxRange. Gdy czujnik podaje wartości dla kilku osi, zakres dotyczy każdej z nich. Na przykład akcelerometr „+/- 2g” zgłosi wartość maxRange = 2*9.81 = 2g.

rozdzielczość: najmniejsza różnica w wartości, jaką może zmierzyć czujnik. Zwykle obliczane na podstawie maxRange i liczby bitów w pomiarze.

power:koszt energii potrzebnej do włączenia czujnika, w miliamperach. Jest to prawie zawsze więcej niż zużycie energii podane w arkuszu danych bazowego czujnika. Więcej informacji znajdziesz w artykule Czujniki podstawowe ≠ czujniki fizyczne, a szczegóły pomiaru zużycia energii przez czujnik znajdziesz w artykule Proces pomiaru mocy. Jeśli zużycie energii przez czujnik zależy od tego, czy urządzenie jest w ruchu, w polu power podawane jest zużycie energii podczas ruchu.

minDelay: w przypadku czujników ciągłych okres próbkowania w mikrosekundach odpowiadający największej częstotliwości obsługiwanej przez czujnik. Szczegółowe informacje o tym, jak używana jest ta wartość, znajdziesz w sekcji sampling_period_ns. Pamiętaj, że minDelay jest wyrażony w mikrosekundach, a sampling_period_ns w nanosekundach. W przypadku czujników w trybie raportowania przy zmianie i w trybie specjalnym, o ile nie określono inaczej, minDelay musi wynosić 0. W przypadku czujników jednorazowych musi to być -1.

maxDelay: w przypadku czujników ciągłych i reagujących na zmiany okres próbkowania w mikrosekundach odpowiadający najniższej częstotliwości obsługiwanej przez czujnik. Szczegółowe informacje o tym, jak używana jest ta wartość, znajdziesz w sekcji sampling_period_ns. Pamiętaj, że maxDelay jest wyrażony w mikrosekundach, a sampling_period_ns w nanosekundach. W przypadku czujników specjalnych i jednorazowych wartość maxDelay musi wynosić 0.

fifoReservedEventCount: liczba zdarzeń zarezerwowanych dla tego czujnika w sprzętowej kolejce FIFO. Jeśli dla tego czujnika jest dostępna dedykowana pamięć FIFO, fifoReservedEventCount to jej rozmiar. Jeśli kolejka FIFO jest współdzielona z innymi czujnikami, fifoReservedEventCount to rozmiar części kolejki FIFO zarezerwowanej dla tego czujnika. W większości systemów FIFO z dostępem współdzielonym i w systemach bez sprzętowego FIFO ta wartość wynosi 0.

fifoMaxEventCount: maksymalna liczba zdarzeń, które mogą być przechowywane w kolejkach FIFO tego czujnika. Jest to zawsze wartość większa lub równa fifoReservedEventCount. Ta wartość służy do szacowania, jak szybko bufor FIFO zostanie zapełniony podczas rejestrowania danych z czujnika z określoną częstotliwością, przy założeniu, że nie są aktywowane żadne inne czujniki. W systemach, które nie mają sprzętowej kolejki FIFO, wartość fifoMaxEventCount wynosi 0. Więcej informacji znajdziesz w sekcji Grupowanie.

W przypadku czujników z oficjalnym typem czujnika niektóre pola są nadpisywane przez platformę. Na przykład czujniki akcelerometru muszą mieć tryb ciągłego raportowania, a monitory tętna muszą być chronione przez uprawnienie SENSOR_PERMISSION_BODY_SENSORS.

sensors_event_t

Zdarzenia z czujników generowane przez czujniki Androida i zgłaszane za pomocą funkcji poll mają wartość type sensors_event_t. Oto niektóre ważne pola sensors_event_t:

version: musi mieć wartość sizeof(struct sensors_event_t)

sensor:uchwyt czujnika, który wygenerował zdarzenie, zgodnie z definicją w sensor_t.handle.

type:typ czujnika, który wygenerował zdarzenie, zgodnie z definicją w sensor_t.type.

timestamp: sygnatura czasowa zdarzenia w nanosekundach. Jest to czas wystąpienia zdarzenia (wykonania kroku lub pomiaru akcelerometru), a nie czas zgłoszenia zdarzenia. timestamp musi być zsynchronizowany z zegarem elapsedRealtimeNano, a w przypadku czujników ciągłych drgania muszą być niewielkie. Filtrowanie sygnatur czasowych jest czasami konieczne, aby spełnić wymagania CDD, ponieważ używanie tylko czasu przerwania SoC do ustawiania sygnatur czasowych powoduje zbyt duże wahania, a używanie tylko czasu układu czujnika do ustawiania sygnatur czasowych może spowodować desynchronizację z zegarem elapsedRealtimeNano, ponieważ zegar czujnika ulega dryfowi.

dane i pola nakładające się: wartości zmierzone przez czujnik. Znaczenie i jednostki tych pól są specyficzne dla każdego typu czujnika. Opis pól danych znajdziesz w pliku sensors.h oraz w definicji różnych typów czujników. W przypadku niektórych czujników dokładność odczytów jest też podawana w ramach danych w polu status. To pole jest przekazywane tylko w przypadku wybranych typów czujników i pojawia się w warstwie SDK jako wartość dokładności. W przypadku tych czujników informacja o tym, że pole stanu musi być ustawione, jest podana w definicji typu czujnika.

Zdarzenia dotyczące zakończenia opróżniania metadanych

Zdarzenia metadanych mają ten sam typ co zwykłe zdarzenia z czujników:sensors_event_meta_data_t = sensors_event_t Są one zwracane wraz z innymi zdarzeniami czujnika w ramach odpytywania. Zawierają one te pola:

version: musi mieć wartość META_DATA_VERSION

type: musi mieć wartość SENSOR_TYPE_META_DATA

sensor, reserved, and timestamp (czujnik, zarezerwowany i sygnatura czasowa): musi mieć wartość 0.

meta_data.what: zawiera typ metadanych tego zdarzenia. Obecnie istnieje tylko 1 prawidłowy typ metadanych: META_DATA_FLUSH_COMPLETE.

Zdarzenia META_DATA_FLUSH_COMPLETE oznaczają zakończenie opróżniania kolejki FIFO czujnika. Gdy meta_data.what=META_DATA_FLUSH_COMPLETE, meta_data.sensor musi być ustawiony na uchwyt czujnika, który został opróżniony. Są one generowane tylko wtedy, gdy na czujniku zostanie wywołana funkcja flush. Więcej informacji znajdziesz w sekcji poświęconej funkcji flush.