interfejs HAL czujników 1.0,

Interfejs HAL czujników, zadeklarowany w pliku sensors.h, stanowi 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 – czyści kolejkę FIFO określonego czujnika i gdy to zrobi, zgłasza zdarzenie zakończenia czyszczenia.
  • 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 szczegółów 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 jego włączania i wyłączania. 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, a ich dezaktywacja musi zostać zaakceptowana przez wywołanie funkcji activate(..., enabled=0).

Czujniki niewybudzające nigdy nie uniemożliwiają przejścia układu SoC w tryb zawieszenia. Oznacza to, że HAL nie może utrzymywać częściowej blokady wybudzania 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 wykonuje żadnych działań i zwraca wartość true.

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

Funkcja zwraca 0, jeśli operacja się powiedzie, a w przeciwnym razie zwraca 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. Tę funkcję można wywołać, gdy czujnik jest aktywny. W takim przypadku nie może ona powodować utraty 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 wysokiej maksymalnej latencji raportu na niską maksymalną latencję 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 za pomocą HAL, w nanosekundach. Więcej informacji znajdziesz w akapitach dotyczących parametru max_report_latency_ns.

Funkcja zwraca 0, jeśli operacja się powiedzie, a w przeciwnym razie zwraca 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 do ustawiania parametru sampling_period_ns używano funkcji setDelay zamiast batch.

flush(sensor)

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

Dodaj zdarzenie zakończenia opróżniania na końcu kolejki FIFO sprzętu dla określonego czujnika i opróżnij kolejkę FIFO.Te zdarzenia są dostarczane w zwykły sposób (tzn. tak jakby upłynął maksymalny czas oczekiwania na raportowanie) 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 jeśli w momencie wywołania kolejka FIFO była pusta, funkcja flush musi się zakończyć 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 ma zastosowania do 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.

Funkcja zwraca 0, jeśli operacja się powiodła, -EINVAL, jeśli określony czujnik jest czujnikiem jednorazowym lub nie został włączony, 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 po wypełnieniu argumentu 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 zwraca wartości 0 (brak zdarzenia).

Kolejność połączeń

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).

Pamiętaj, że w wersji HAL 1.0 kolejność była odwrotna: najpierw wywoływano funkcję activate, a potem set_delay.

Gdy żądane cechy 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 wywoływana wielokrotnie 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 i 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 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 rodzajach czujników znajdziesz w artykule Czym są czujniki Androida?, a oficjalne rodzaje czujników znajdziesz w sekcji Rodzaje 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 jednoznacznego identyfikowania 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 informacje wrażliwe (np. dotyczące tętna) 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 maksymalnego zakresu w ciągu [-maxRange; maxRange]. Pamiętaj, że oznacza to, że całkowity zakres czujnika w sensie ogólnym wynosi 2*maxRange. Jeśli czujnik podaje wartości w kilku osiach, 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 obliczany na podstawie maxRange i liczby bitów w pomiarze.

power:koszt energii w miliamperach związany z włączeniem czujnika. Jest to prawie zawsze więcej niż zużycie energii podane w arkuszu danych bazowego czujnika. Więcej informacji znajdziesz w artykule Czujniki bazowe ≠ 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, zużycie energii podczas ruchu jest podawane w polu power.

minDelay: w przypadku czujników ciągłych okres próbkowania w mikrosekundach odpowiadający najszybszej częstotliwości obsługiwanej przez czujnik. Więcej informacji o tym, jak używana jest ta wartość, znajdziesz w sekcji sampling_period_ns. Pamiętaj, że minDelay jest wyrażona 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 najwolniejszej szybkości obsługiwanej przez czujnik. Więcej informacji o tym, jak używana jest ta wartość, znajdziesz w sekcji sampling_period_ns. Pamiętaj, że maxDelay jest wyrażona 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 udostępniana innym czujnikom, 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. Ta wartość jest zawsze 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ą zastępowane 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 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, zdefiniowany przez 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 nakładające się pola: 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 rodzajó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 i timestamp: 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ł wyczyszczony. Są one generowane tylko wtedy, gdy na czujniku zostanie wywołana funkcja flush. Więcej informacji znajdziesz w sekcji poświęconej funkcji flush.