HIDL opiera się na interfejsach – typie abstrakcyjnym używanym w do definiowania zachowań. Każdy interfejs jest częścią pakietu.
Pakiety
Nazwy pakietów mogą mieć poziomy podrzędne, np. package.subpackage
.
katalog główny opublikowanych pakietów HIDL to hardware/interfaces
lub vendor/vendorName
(np. vendor/google
w przypadku Pixela
urządzenia). Nazwa pakietu tworzy co najmniej jeden podkatalog w katalogu głównym
directory; wszystkie pliki definiujące pakiet znajdują się w tym samym katalogu. Przykład:
Można znaleźć package android.hardware.example.extension.light@2.0
poniżej hardware/interfaces/example/extension/light/2.0
.
W tej tabeli znajdziesz prefiksy pakietów i lokalizacje:
Prefiks pakietu | Lokalizacja | Typy interfejsów |
---|---|---|
android.hardware.* |
hardware/interfaces/* |
HAL |
android.frameworks.* |
frameworks/hardware/interfaces/* |
platformy/ powiązane |
android.system.* |
system/hardware/interfaces/* |
system/ pokrewne |
android.hidl.* |
system/libhidl/transport/* |
mięśnie głębokie |
Katalog pakietów zawiera pliki z rozszerzeniem .hal
. Co
musi zawierać instrukcję package
zawierającą nazwę pakietu i
wersji, do której należy plik. Plik types.hal
(jeśli istnieje)
nie definiuje interfejsu, lecz definiuje typy danych dostępne dla każdej
który znajduje się w pakiecie.
Definicja interfejsu
Oprócz pliku types.hal
każdy inny plik .hal
określa
interfejs. Interfejs jest zwykle definiowany w następujący sposób:
interface IBar extends IFoo { // IFoo is another interface // embedded types struct MyStruct {/*...*/}; // interface methods create(int32_t id) generates (MyStruct s); close(); };
Interfejs bez niejawnej deklaracji extends
rozciąga się od android.hidl.base@1.0::IBase
(podobne do
java.lang.Object
w Javie). Bezpośrednio za pomocą interfejsu IBase
zaimportowane, deklaruje kilka zarezerwowanych metod, których nie można
ponownie zadeklarowane w interfejsach zdefiniowanych przez użytkownika lub wykorzystane w inny sposób. Metody te
uwzględnij:
ping
interfaceChain
interfaceDescriptor
notifySyspropsChanged
linkToDeath
unlinkToDeath
setHALInstrumentation
getDebugInfo
debug
getHashChain
Proces importowania
Instrukcja import
to mechanizm HIDL uzyskujący dostęp do pakietu
z interfejsów i typów w innym pakiecie. Instrukcja import
dotyczy się dwóch podmiotów:
- Importowana encja, którą może być pakiet lub interfejs
- Zaimportowany element, którym może być pakiet lub interfejs
Importowany obiekt jest określany na podstawie lokalizacji
Instrukcja import
. Gdy instrukcja znajduje się w polu
types.hal
, to, co jest importowane, jest widoczne w całym pakiecie.
jest to import na poziomie pakietu. Gdy instrukcja znajduje się w tagu
elementem interfejsu jest sam interfejs, to jest
na poziomie interfejsu.
Zaimportowany element jest określany na podstawie wartości występującej po fragmencie import
słowa kluczowego. Wartość nie musi być w pełni kwalifikowaną nazwą; jeśli komponent to
zostanie on automatycznie wypełniony informacjami z bieżącego pakietu.
W przypadku w pełni kwalifikowanych wartości obsługiwane są następujące przypadki importu:
- Importowanie całego pakietu. Jeśli wartością jest nazwa pakietu i (składnię opisaną poniżej), cały pakiet zostanie zaimportowany do importujący encję.
- Importy częściowe. Jeśli wartość to:
- Interfejs,
types.hal
i interfejs pakietu zaimportowane do elementu importu. - w przypadku jednostki UDT zdefiniowanej w
types.hal
, do niej zaimportowana jest tylko ta funkcja importowany element (inne typy w polutypes.hal
nie są importowane).
- Interfejs,
- Importy tylko typów. Jeśli wartość korzysta ze składni
częściowy import opisany powyżej, ale ze słowem kluczowym
types
nazwy interfejsu, tylko identyfikatory UDT wtypes.hal
zaimportowanych pakietów.
Importowany element ma dostęp do kombinacji:
- Wspólne identyfikatory UDT zaimportowanego pakietu zdefiniowane w tabeli
types.hal
; - Interfejsy importowanego pakietu (w przypadku importu całego pakietu) lub określone (do częściowego importu) do ich wywołania, uchwytów do nich lub dziedziczenia z nich.
Instrukcja importu korzysta ze składni w pełni kwalifikowanej nazwy typu-nazwa, aby zapewnić nazwa i wersja importowanego pakietu lub interfejsu:
import android.hardware.nfc@1.0; // import a whole package import android.hardware.example@1.0::IQuux; // import an interface and types.hal import android.hardware.example@1.0::types; // import just types.hal
Dziedziczenie w interfejsie
Interfejs może być rozszerzeniem wcześniej zdefiniowanego interfejsu. Istnieją trzy typy rozszerzeń:
- Interfejs może dodać funkcje do innego, korzystając ze swojego interfejsu API bez zmian.
- Pakiet może dodać funkcje do innego pakietu, wykorzystując swój interfejs API bez zmian.
- Interfejs może importować typy z pakietu lub z określonego interfejsu.
Interfejs może stanowić rozszerzenie tylko jednego innego interfejsu (nie może być dziedziczeniem wielokrotnym).
Każdy interfejs w pakiecie z numerem wersji podrzędnej innej niż 0 musi obejmować rozszerzenie
w poprzedniej wersji pakietu. Jeśli na przykład interfejs użytkownika
IBar
w wersji 4.0 pakietu derivative
na podstawie
(rozszerza) interfejs IFoo
w wersji 1.2 pakietu
original
oraz wersja 1.3 pakietu original
to
utworzono, IBar
wersja 4.1 nie może rozszerzyć wersji 1.3
IFoo
Zamiast tego musi być rozszerzenie IBar
w wersji 4.1.
IBar
w wersji 4.0, która jest powiązana z IFoo
w wersji 1.2.
Przeglądarka IBar
w wersji 5.0 może rozszerzyć IFoo
wersję 1.3, jeśli
pożądaną.
Rozszerzenia interfejsu nie sugerują zależności od biblioteki ani nie uwzględniają treści HAL w wygenerowanym kodzie – wystarczy, że zaimportują strukturę i metodę danych, na poziomie HIDL. Każda metoda w HAL musi być zaimplementowana w tym HAL.
Rozszerzenia dostawców
W niektórych przypadkach rozszerzenia dostawców są zaimplementowane jako podklasa klasy który reprezentuje podstawowy interfejs, który jest rozszerzany. Ten sam obiekt jest zarejestrowane pod podstawową nazwą i wersją HAL oraz pod Nazwa i wersja HAL (dostawcy).
Obsługa wersji
Pakiety mają różne wersje, a interfejsy – swoją wersję. Wersje są wyrażone za pomocą 2 liczb całkowitych: duża.mniejsza.
- Wersje główne nie są zgodne wstecznie. Zwiększam numer wersji głównej resetuje numer wersji podrzędnej do 0.
- Wersje Minor są zgodne wstecznie. Zwiększam liczba pomniejszona oznacza, że nowsza wersja jest w pełni zgodna wstecznie z poprzedniej wersji. Można dodawać nowe struktury danych i metody, ale nie możesz dodawać istniejących struktury danych lub podpisy metod mogą ulec zmianie.
Na urządzeniu może znajdować się wiele głównych i podrzędnych wersji HAL. jednocześnie. Należy jednak preferować wersję podrzędną zamiast wersji głównej. ponieważ kod klienta działa z interfejsem poprzedniej wersji podrzędnej działa również z późniejszymi wersjami podrzędnymi tego samego interfejsu. Więcej szczegółowe informacje na temat obsługi wersji i rozszerzeń dostawców można znaleźć w artykule Obsługa wersji HIDL.
Podsumowanie układu interfejsu
Z tej sekcji dowiesz się, jak zarządzać pakietem interfejsu HIDL (takim jak
hardware/interfaces
) i konsoliduje przedstawiane informacje
w całej sekcji HIDL. Zanim zaczniesz czytać, zapoznaj się z
Obsługa wersji HIDL,
szyfrowanie z
koncepcje hidl-gen, szczegóły pracy z grupą
Ogólne informacje o HIDL oraz te definicje:
Termin | Definicja |
---|---|
interfejs binarny aplikacji (ABI) | Interfejs programowania aplikacji oraz wszelkie wymagane powiązania binarne. |
pełna nazwa (fqName) | Nazwa wyróżniająca typ hidl. Przykład:
android.hardware.foo@1.0::IFoo |
paczka | Pakiet zawierający interfejs i typy HIDL. Przykład:
android.hardware.foo@1.0 |
poziom główny pakietu | Pakiet główny zawierający interfejsy HIDL. Przykład: interfejs HIDL
android.hardware znajduje się w katalogu głównym pakietu
android.hardware.foo@1.0 |
ścieżka główna pakietu | Lokalizacja w drzewie źródłowym Androida, na którą mapuje się pakiet główny. |
Więcej definicji znajdziesz w sekcji HIDL Terminologia.
Każdy plik można znaleźć z mapowania głównego pakietu, jego pełna i jednoznaczna nazwa
Poziomy główne pakietu są określone jako hidl-gen
jako argument.
-r android.hardware:hardware/interfaces
Na przykład, jeśli plik
przesyłka to vendor.awesome.foo@1.0::IFoo
i hidl-gen
zostanie wysłany -r vendor.awesome:some/device/independent/path/interfaces
,
plik interfejsu powinien znajdować się w
$ANDROID_BUILD_TOP/some/device/independent/path/interfaces/foo/1.0/IFoo.hal
W praktyce jest to zalecane w przypadku dostawcy lub OEM o nazwie awesome
ich standardowe interfejsy zostały umieszczone w języku vendor.awesome
. Po paczce
została wybrana ścieżka, nie można jej zmieniać, ponieważ jest ona umieszczana w ABI
do interfejsu.
Mapowanie ścieżki pakietu powinno być unikalne
Na przykład, jeśli masz -rsome.package:$PATH_A
i
-rsome.package:$PATH_B
, $PATH_A
musi mieć wartość równą
$PATH_B
dla spójnego katalogu interfejsu (powoduje to również
interfejsy obsługi wersji
).
Element główny pakietu musi mieć plik obsługi wersji
Jeśli utworzysz ścieżkę pakietu, taką jak
-r vendor.awesome:vendor/awesome/interfaces
, także
utwórz plik
$ANDROID_BUILD_TOP/vendor/awesome/interfaces/current.txt
, czyli
powinien zawierać hasze interfejsów utworzonych przy użyciu opcji -Lhash
w
hidl-gen
(to szczegółowo omówiono w
Haszowanie z
hidl-gen).
Interfejsy działają niezależnie od urządzenia lokalizacje
W praktyce zalecamy współdzielenie interfejsów między gałęziami. Ten pozwala na maksymalne ponowne wykorzystanie i testowanie kodu w różnych urządzeń i przypadków użycia.