Język definicji interfejsu HAL lub HIDL jest językiem opisu interfejsu (IDL). do interfejsu między HAL swoich użytkowników. HIDL umożliwia określenie typów i wywołań metod zbieranych w interfejsów i pakietów. Ogólnie HIDL to system komunikacji między bazami kodu, które mogą być skompilowane niezależnie.
Protokół HIDL jest przeznaczony do komunikacji między procesami (IPC). Listy HAL utworzone przy użyciu HDL tzw. wiązań HAL, ponieważ mogą komunikować się z innymi warstwami architektury za pomocą wiązania wywołaniami w komunikacji międzyprocesowej (IPC). Powiązane poziomy HAL są uruchamiane w procesie innym niż klient który ich używa. Dla: które muszą być połączone z procesem, przekazywaniem jest także dostępny (nieobsługiwany w Javie).
HIDL określa struktury danych i podpisy metod uporządkowane w interfejsach (podobne do klasy) zbierane w pakiety. Składnia języka HIDL wygląda znajomo w językach C++ z innymi programistami w Javie słowa kluczowe. HIDL wykorzystuje również adnotacje w stylu Java.
Terminologia
W tej sekcji używane są następujące terminy związane z HIDL:
powiązane | Wskazuje, że HIDL jest używany do zdalnych wywołań procedur między procesami. za pomocą mechanizmu podobnego do Binder. Zobacz też Przekazywanie. |
---|---|
wywołanie zwrotne, asynchroniczne | interfejs obsługiwany przez użytkownika HAL przekazywany do HAL (przy użyciu metody HIDL), przez HAL w celu zwrócenia danych w dowolnym momencie. |
wywołanie zwrotne, synchroniczne | Zwraca do klienta dane z implementacji metody HIDL serwera. Nieużywane w przypadku metod, które zwracają nieważną lub pojedynczą wartość podstawową. |
klient | Proces, który wywołuje metody określonego interfejsu. platforma HAL lub platforma Androida może być klientem jednego interfejsu, a drugim serwerem. Zobacz też przekazywanie. |
rozciąga się | Wskazuje interfejs, który dodaje metody i/lub typy do innego interfejsu. Interfejs może stanowić rozszerzenie tylko jednego innego interfejsu. Przeznaczone dla osób nieletnich zwiększenie wersji w przypadku tej samej nazwy pakietu lub nowego pakietu (np. dostawcy ), aby bazować na starszym pakiecie. |
generuje | Wskazuje metodę interfejsu, która zwraca wartości klientowi. Aby zwrócić jedną lub więcej niż jedną wartość, synchroniczną funkcję wywołania zwrotnego . |
interfejs | Zbiór metod i typów. Przetłumaczone na zajęcia w C++ lub Java. Wszystkie metody w interfejsie są wywoływane w tym samym kierunku: proces klienta wywołuje metody zaimplementowane przez proces serwera. |
w jedną stronę | Po zastosowaniu do metody HIDL wskazuje, że metoda nie zwraca żadnych wartości i nie zostanie zablokowana. |
paczka | Zbiór interfejsów i typów danych współużytkujących daną wersję. |
przekazywanie | Tryb HIDL, w którym serwer jest biblioteką współdzieloną, dlopen
przez klienta. W trybie przekazywania klient i serwer to ten sam proces, ale
w osobnych bazach kodu. Służy tylko do przeniesienia starszych baz kodu do modelu HIDL.
Zapoznaj się też z sekcją Powiązane. |
serwer | Proces implementujący metody interfejsu. Zobacz też przekazywanie. |
transport | infrastruktura HIDL, która służy do przenoszenia danych między serwerem a klientem. |
Wersja | Wersja pakietu. Składa się z 2 liczb całkowitych (dużej i małej). Nieletni przyrosty wersji mogą dodawać (ale nie zmieniać) typy i metody. |
Projekt HIDL
Celem standardu HIDL jest zastąpienie platformy Androida bez konieczności
odbudowywanie HAL. Listy HAL są tworzone przez dostawców lub twórców SOC i umieszczane
partycja /vendor
na urządzeniu, co samo w sobie daje dostęp do platformy Androida.
partycji i zastąpić ją OTA bez konieczności ponownej kompilacji list HAL.
Projekt HIDL obejmuje następujące problemy:
- Współdziałanie. Tworzenie niezawodnych, współdziałających interfejsów procesów, które można skompilować z użyciem różnych architektur, łańcuchów narzędzi i konfiguracje kompilacji. Interfejsy HIDL mają różne wersje i nie można ich zmieniać po ich opublikowaniu.
- Skuteczność. HIDL próbuje zminimalizować liczbę kopii operacji. Dane zdefiniowane przez HIDL są przesyłane do kodu C++ w standardowym układzie C++ struktury danych, których można używać bez rozpakowywania. HIDL udostępnia również a ponieważ interfejsy RPC są z natury nieco wolne, HIDL obsługuje dwa sposoby przenoszenia danych bez użycia wywołania RPC: pamięć współdzielona oraz funkcja Fast Kolejka wiadomości (FMQ).
- Intuicyjny. HIDL pozwala uniknąć poważnych problemów z własnością pamięci,
używając tylko parametrów
in
na potrzeby RPC (patrz Android język definiowania interfejsu (AIDL)); wartości, których nie można wydajnie zwracane przez metody są zwracane przez funkcje wywołania zwrotnego. Brak przekazywania danych na HIDL w celu przeniesienia lub otrzymywanie danych od HIDL zmienia własność dane—własność zawsze pozostaje w funkcji wywołującego. Dane muszą: pozostają aktywne tylko przez czas trwania wywołanej funkcji i mogą zostać zniszczone; bezpośrednio po zwróceniu wywołanej funkcji.
Używanie trybu przekazywania
Aby zaktualizować urządzenia z wcześniejszą wersją Androida do Androida O, możesz: opakować zarówno konwencjonalne (jak i starsze) listy HAL, w nowy interfejs HIDL, który obsługuje HAL w trybach powiązania i tego samego procesu (przekazywania). To opakowanie jest są przejrzyste zarówno dla HAL, jak i platformy Androida.
Tryb przekazywania jest dostępny tylko w przypadku klientów i implementacji C++. Urządzenia z wcześniejszymi wersjami Androida nie mają interfejsów HAL napisanych w języku Java, Interfejsy HAL Java są z natury powiązane.
Przekazujące pliki nagłówka
Po skompilowaniu pliku .hal
hidl-gen
generuje
dodatkowy przekazujący plik nagłówka BsFoo.h
oprócz nagłówków
używane do komunikacji z powiązanymi podmiotami; ten nagłówek definiuje funkcje
dlopen
ed. Przekazujące HAL działają w tym samym procesie, w którym
W większości przypadków metody przekazywania są wywoływane przez metody bezpośrednie
wywołanie funkcji (ten sam wątek). oneway
metoda działa w osobnym wątku
ponieważ nie muszą czekać, aż HAL je przetworzy (oznacza to, że wszystkie HAL
który korzysta z metod oneway
w trybie przekazywania, musi być bezpiecznym wątkiem.
Biorąc pod uwagę wartość IFoo.hal
, BsFoo.h
opakowuje wygenerowane przez HIDL
metod udostępniania dodatkowych funkcji (takich jak tworzenie oneway
transakcji wykonanych w innym wątku). Ten plik jest podobny do pliku
BpFoo.h
, jednak zamiast przekazywania wywołań IPC za pomocą bindera funkcja
wymagane funkcje są wywoływane bezpośrednio. Kolejne implementacje HAL
mogą zapewniać wiele implementacji, takich jak FooFast HAL,
Precyzyjne HAL. W takich przypadkach plik z każdą dodatkową implementacją byłby
(np. PTFooFast.cpp
i
PTFooAccurate.cpp
).
Powiązanie przekazujących HAL
Możesz powiązać implementacje HAL, które obsługują tryb przekazywania. Jeśli
Interfejs HAL a.b.c.d@M.N::IFoo
, tworzone są 2 pakiety:
a.b.c.d@M.N::IFoo-impl
Zawiera implementację HAL i ujawnia funkcjęIFoo* HIDL_FETCH_IFoo(const char* name)
. Wł. starszych urządzeń, ten pakiet jestdlopen
edytowany, a implementacja jest utworzono za pomocąHIDL_FETCH_IFoo
. Możesz wygenerować kod podstawowy za pomocą:hidl-gen
,-Lc++-impl
i-Landroidbp-impl
a.b.c.d@M.N::IFoo-service
Otwiera przekazywanie HAL i rejestruje się jako usługę powiązaną, umożliwiając tę samą implementację HAL do wykorzystania zarówno jako przekazu, jak i powiązania.
Typ IFoo
umożliwia wywołanie metody sp<IFoo>
IFoo::getService(string name, bool getStub)
, aby uzyskać dostęp do instancji
z IFoo
. Jeśli getStub
ma wartość prawda, getService
próbuje otworzyć zawartość HAL tylko w trybie przekazywania. Jeśli getStub
to
false, getService
próbuje znaleźć usługę powiązaną; jeśli
a następnie próbuje znaleźć usługę przekazywania. getStub
z wyjątkiem
defaultPassthroughServiceImplementation
(Urządzenia uruchamiane z
Android O to urządzenia w pełni powiązane, więc otwarcie usługi w trybie przekazywania
jest niedozwolone).
Gramatyka HIDL
Z założenia język HIDL jest podobny do języka C (ale nie używa
(preprocesor). wszelkie znaki interpunkcyjne nieopisane poniżej (z wyjątkiem oczywistego zastosowania)
=
i |
) jest częścią gramatyki.
Uwaga: szczegółowe informacje o stylu kodu HIDL znajdziesz w Przewodnik po stylach kodu.
/** */
oznacza komentarz do dokumentacji. Można je stosować tylko na deklaracje typu, metody, pól i wartości wyliczeniowych./* */
oznacza komentarz wielowierszowy.//
oznacza komentarz na końcu wiersza. Oprócz//
, znaki nowego wiersza są takie same jak wszystkie inne odstępy.- W przykładowej gramatyce poniżej tekst od
//
do końca wiersz nie jest częścią gramatyki, ale jest komentarzem na jej temat. [empty]
oznacza, że hasło może być puste.?
po literału lub pojęciu oznacza, że element jest opcjonalny....
oznacza sekwencję zawierającą 0 lub więcej elementów z argumentem oddzielając znaki interpunkcyjne zgodnie ze wskazówkami. W HIDL nie ma żadnych argumentów zmiennych.- Elementy sekwencji są rozdzielane przecinkami.
- Średniki kończą każdy element, w tym ostatni.
- WIELKIE LITERY to nieterminal.
italics
to rodzina tokenów, taka jakinteger
lubidentifier
(standardowy C reguły analizy składniowej).constexpr
to wyrażenie stałe stylu C (np.1 + 1
i1L << 3
).import_name
to kwalifikowana nazwa pakietu lub interfejsu zgodnie z opisem w HIDL Obsługa wersji.- Małe litery
words
to tokeny dosłowne.
Przykład:
ROOT = PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... } // not for types.hal | PACKAGE IMPORTS ITEM ITEM... // only for types.hal; no method definitions ITEM = ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?; | safe_union identifier { UFIELD; UFIELD; ...}; | struct identifier { SFIELD; SFIELD; ...}; // Note - no forward declarations | union identifier { UFIELD; UFIELD; ...}; | enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... }; // TYPE = enum or scalar | typedef TYPE identifier; VERSION = integer.integer; PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION; PREAMBLE = interface identifier EXTENDS EXTENDS = <empty> | extends import_name // must be interface, not package GENERATES = generates (FIELD, FIELD ...) // allows the Binder interface to be used as a type // (similar to typedef'ing the final identifier) IMPORTS = [empty] | IMPORTS import import_name; TYPE = uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t | float | double | bool | string | identifier // must be defined as a typedef, struct, union, enum or import // including those defined later in the file | memory | pointer | vec<TYPE> | bitfield<TYPE> // TYPE is user-defined enum | fmq_sync<TYPE> | fmq_unsync<TYPE> | TYPE[SIZE] FIELD = TYPE identifier UFIELD = TYPE identifier | safe_union identifier { FIELD; FIELD; ...} identifier; | struct identifier { FIELD; FIELD; ...} identifier; | union identifier { FIELD; FIELD; ...} identifier; SFIELD = TYPE identifier | safe_union identifier { FIELD; FIELD; ...}; | struct identifier { FIELD; FIELD; ...}; | union identifier { FIELD; FIELD; ...}; | safe_union identifier { FIELD; FIELD; ...} identifier; | struct identifier { FIELD; FIELD; ...} identifier; | union identifier { FIELD; FIELD; ...} identifier; SIZE = // Must be greater than zero constexpr ANNOTATIONS = [empty] | ANNOTATIONS ANNOTATION ANNOTATION = | @identifier | @identifier(VALUE) | @identifier(ANNO_ENTRY, ANNO_ENTRY ...) ANNO_ENTRY = identifier=VALUE VALUE = "any text including \" and other escapes" | constexpr | {VALUE, VALUE ...} // only in annotations ENUM_ENTRY = identifier | identifier = constexpr