Android 11 wprowadza możliwość używania AIDL w przypadku warstw HAL w Androidzie, co umożliwia implementowanie części Androida bez HIDL. Przejście na HAL-e korzystające wyłącznie z AIDL (w przypadku HAL-i wyższego poziomu korzystających z HIDL należy używać HIDL).
Warstwy HAL, które używają AIDL do komunikacji między komponentami platformy, np. w system.img, a komponentami sprzętowymi, np. w vendor.img, muszą używać stabilnego AIDL. Jednak w przypadku komunikacji w ramach partycji, np. między różnymi interfejsami HAL, nie ma ograniczeń co do mechanizmu IPC.
Motywacja
AIDL jest starszy niż HIDL i jest używany w wielu innych miejscach, np. między komponentami platformy Android lub w aplikacjach. Teraz, gdy AIDL obsługuje stabilność, można zaimplementować cały stos za pomocą jednego środowiska wykonawczego IPC. AIDL ma też lepszy system wersji niż HIDL. Oto niektóre zalety AIDL:
- Używanie jednego języka IPC oznacza, że musisz się nauczyć tylko jednej rzeczy, debugować, optymalizować i zabezpieczać tylko jedną rzecz.
 - AIDL obsługuje wersjonowanie w miejscu dla właścicieli interfejsu:
- Właściciele mogą dodawać metody na końcu interfejsów lub pola do obiektów Parcelable. Oznacza to, że łatwiej jest wersjonować kod na przestrzeni lat, a koszt z roku na rok jest mniejszy (typy można modyfikować w miejscu i nie ma potrzeby stosowania dodatkowych bibliotek dla każdej wersji interfejsu).
 - Interfejsy rozszerzeń można dołączać w czasie działania, a nie w systemie typów, więc nie trzeba zmieniać podstawy rozszerzeń podrzędnych na nowsze wersje interfejsów.
 
 - Istniejący interfejs AIDL można używać bezpośrednio, jeśli jego właściciel zdecyduje się go ustabilizować. Wcześniej trzeba było utworzyć w HIDL całą kopię interfejsu.
 
Tworzenie kompilacji w środowisku wykonawczym AIDL
AIDL ma 3 różne interfejsy: Java, NDK i CPP. Aby używać stabilnego AIDL, zawsze korzystaj z kopii systemowej libbinder w system/lib*/libbinder.so i rozmawiaj na /dev/binder. W przypadku kodu na obrazie vendor oznacza to, że nie można używać biblioteki libbinder (z VNDK): ma ona niestabilny interfejs API C++ i niestabilne elementy wewnętrzne. Zamiast tego kod dostawcy natywnego musi używać backendu AIDL NDK, łączyć się z libbinder_ndk (który jest obsługiwany przez libbinder.so) i łączyć się z bibliotekami NDK utworzonymi przez wpisy aidl_interface. Dokładne nazwy modułów znajdziesz w zasadach dotyczących nazewnictwa modułów.
Pisanie interfejsu HAL AIDL
Aby interfejs AIDL mógł być używany między systemem a dostawcą, musi zostać zmieniony w 2 sposoby:
- Każda definicja typu musi być opatrzona adnotacją 
@VintfStability. aidl_interfacedeklaracja musi zawieraćstability: "vintf",.
Tych zmian może dokonać tylko właściciel interfejsu.
Aby te zmiany działały, interfejs musi znajdować się w manifeście VINTF. Przetestuj to (i powiązane wymagania, np. sprawdzenie, czy opublikowane interfejsy są zamrożone) za pomocą testu Vendor Test Suite (VTS) vts_treble_vintf_vendor_test. Możesz używać interfejsu
@VintfStability bez tych wymagań, wywołując funkcję
AIBinder_forceDowngradeToLocalStability w NDK backend,
android::Stability::forceDowngradeToLocalStability w C++ backend lub android.os.Binder#forceDowngradeToSystemStability w Java backend
na obiekcie bindera, zanim zostanie on wysłany do innego procesu.
Dodatkowo, aby zapewnić maksymalną przenośność kodu i uniknąć potencjalnych problemów, takich jak niepotrzebne dodatkowe biblioteki, wyłącz backend CPP.
Kod pokazuje, jak wyłączyć backend CPP:
    aidl_interface: {
        ...
        backend: {
            cpp: {
                enabled: false,
            },
        },
    }
Znajdowanie interfejsów AIDL HAL
Stabilne interfejsy AIDL AOSP dla HAL znajdują się w folderach aidl w tych samych katalogach podstawowych co interfejsy HIDL:
hardware/interfaces– interfejsy zwykle udostępniane przez sprzęt.frameworks/hardware/interfaces– interfejsy wysokiego poziomu udostępniane sprzętowi.system/hardware/interfacesto interfejsy niskiego poziomu udostępniane sprzętowi.
Umieść interfejsy rozszerzeń w innych podkatalogach w hardware/interfaces, vendor lub hardware.
Interfejsy rozszerzeń
W każdej wersji Androida dostępny jest zestaw oficjalnych interfejsów AOSP. Jeśli partnerzy Androida chcą dodać funkcje do tych interfejsów, nie powinni ich bezpośrednio zmieniać, ponieważ spowoduje to, że ich środowisko wykonawcze Androida będzie niezgodne ze środowiskiem wykonawczym Androida w AOSP. Nie zmieniaj tych interfejsów, aby obraz GSI mógł nadal działać.
Rozszerzenia mogą rejestrować się na 2 sposoby:
- w czasie działania; patrz Interfejsy dołączonych rozszerzeń.
 - Jako samodzielny, zarejestrowany globalnie i w VINTF
 
Niezależnie od tego, w jaki sposób zarejestrowane jest rozszerzenie, gdy komponenty specyficzne dla dostawcy (czyli niebędące częścią AOSP) korzystają z interfejsu, konflikty scalania nie są możliwe. Jeśli jednak wprowadzane są modyfikacje komponentów AOSP, mogą wystąpić konflikty scalania. W takim przypadku zalecane są te strategie:
- W następnej wersji udostępnimy dodatki do interfejsu w AOSP.
 - Dodanie interfejsów upstream, które w przyszłej wersji zapewnią większą elastyczność (bez konfliktów scalania).
 
Rozszerzenia obiektów Parcelable: ParcelableHolder
ParcelableHolder to instancja interfejsu Parcelable, która może zawierać inną instancję Parcelable.
Głównym zastosowaniem ParcelableHolder jest rozszerzanie Parcelable.
Na przykład producenci urządzeń oczekują, że będą mogli rozszerzyć zdefiniowane w AOSP właściwości Parcelable i AospDefinedParcelable o dodatkowe funkcje.
Użyj interfejsu ParcelableHolder, aby rozszerzyć Parcelable o funkcje zwiększające wartość. Interfejs ParcelableHolder zawiera instancję elementu Parcelable. Jeśli spróbujesz dodać pola bezpośrednio do Parcelable, spowoduje to błąd:
parcelable AospDefinedParcelable {
  int a;
  String b;
  String x; // ERROR: added by a device implementer
  int[] y; // added by a device implementer
}
Jak widać w poprzednim kodzie, ta praktyka jest nieprawidłowa, ponieważ pola dodane przez producenta urządzenia mogą powodować konflikt, gdy Parcelable zostanie zmieniona w kolejnych wersjach Androida.
Za pomocą adnotacji ParcelableHolder właściciel obiektu Parcelable może zdefiniować punkt rozszerzenia w instancji Parcelable:
parcelable AospDefinedParcelable {
  int a;
  String b;
  ParcelableHolder extension;
}
Następnie twórcy urządzeń mogą zdefiniować własną Parcelableinstancję dla rozszerzenia:
parcelable OemDefinedParcelable {
  String x;
  int[] y;
}
Nowe wystąpienie Parcelable można dołączyć do oryginalnego Parcelable za pomocą pola ParcelableHolder:
// Java
AospDefinedParcelable ap = ...;
OemDefinedParcelable op = new OemDefinedParcelable();
op.x = ...;
op.y = ...;
ap.extension.setParcelable(op);
...
OemDefinedParcelable op = ap.extension.getParcelable(OemDefinedParcelable.class);
// C++
AospDefinedParcelable ap;
OemDefinedParcelable op;
std::shared_ptr<OemDefinedParcelable> op_ptr = make_shared<OemDefinedParcelable>();
ap.extension.setParcelable(op);
ap.extension.setParcelable(op_ptr);
...
std::shared_ptr<OemDefinedParcelable> op_ptr;
ap.extension.getParcelable(&op_ptr);
// NDK
AospDefinedParcelable ap;
OemDefinedParcelable op;
ap.extension.setParcelable(op);
...
std::optional<OemDefinedParcelable> op;
ap.extension.getParcelable(&op);
// Rust
let mut ap = AospDefinedParcelable { .. };
let op = Rc::new(OemDefinedParcelable { .. });
ap.extension.set_parcelable(Rc::clone(&op));
...
let op = ap.extension.get_parcelable::<OemDefinedParcelable>();
Nazwy instancji serwera HAL języka AIDL
Zgodnie z konwencją usługi AIDL HAL mają nazwę instancji w formacie
$package.$type/$instance. Na przykład instancja HAL wibratora jest rejestrowana jako android.hardware.vibrator.IVibrator/default.
Pisanie serwera HAL AIDL
@VintfStability Serwery AIDL muszą być zadeklarowane w pliku manifestu VINTF, np.:
    <hal format="aidl">
        <name>android.hardware.vibrator</name>
        <version>1</version>
        <fqname>IVibrator/default</fqname>
    </hal>
W przeciwnym razie powinni zarejestrować usługę AIDL w zwykły sposób. Podczas przeprowadzania testów VTS wszystkie zadeklarowane interfejsy HAL AIDL powinny być dostępne.
Pisanie klienta AIDL
Klienci AIDL muszą zadeklarować się w macierzy zgodności, np.:
    <hal format="aidl" optional="true">
        <name>android.hardware.vibrator</name>
        <version>1-2</version>
        <interface>
            <name>IVibrator</name>
            <instance>default</instance>
        </interface>
    </hal>
Konwertowanie istniejącej warstwy HAL z HIDL na AIDL
Użyj narzędzia hidl2aidl, aby przekonwertować interfejs HIDL na AIDL.
Funkcje hidl2aidl:
- Utwórz pliki AIDL (
.aidl) na podstawie plików HAL (.hal) dla danego pakietu. - Utwórz reguły kompilacji dla nowo utworzonego pakietu AIDL ze wszystkimi włączonymi backendami.
 - Utwórz metody tłumaczenia w backendach Java, CPP i NDK, które będą tłumaczyć typy HIDL na typy AIDL.
 - Utwórz reguły kompilacji dla bibliotek tłumaczeń z wymaganymi zależnościami.
 - Utwórz statyczne asercje, aby mieć pewność, że wyliczenia HIDL i AIDL mają te same wartości w backendach CPP i NDK.
 
Aby przekonwertować pakiet plików HAL na pliki AIDL:
Zbuduj narzędzie znajdujące się w
system/tools/hidl/hidl2aidl.Korzystanie z najnowszej wersji tego narzędzia zapewnia pełną funkcjonalność. Najnowszej wersji możesz użyć do konwertowania interfejsów w starszych gałęziach z poprzednich wersji:
m hidl2aidlUruchom narzędzie z katalogiem wyjściowym, a następnie z pakietem do przekonwertowania.
Opcjonalnie możesz użyć argumentu
-l, aby dodać zawartość nowego pliku licencji na początku wszystkich wygenerowanych plików. Upewnij się, że używasz prawidłowej licencji i daty:hidl2aidl -o <output directory> -l <file with license> <package>Na przykład:
hidl2aidl -o . -l my_license.txt android.hardware.nfc@1.2Przejrzyj wygenerowane pliki i rozwiąż problemy z konwersją:
conversion.logzawiera nieobsłużone problemy, które należy najpierw rozwiązać.- Wygenerowane pliki AIDL mogą zawierać ostrzeżenia i sugestie, które wymagają podjęcia działań. Te komentarze zaczynają się od 
//. - Oczyść pakiet i wprowadź w nim ulepszenia.
 - Sprawdź adnotację 
@JavaDerivew przypadku funkcji, które mogą być potrzebne, np.toStringlubequals. 
Twórz tylko te środowiska docelowe, których potrzebujesz:
- Wyłącz zaplecza, które nie będą używane. Preferuj backend NDK zamiast backendu CPP. Więcej informacji znajdziesz w artykule Kompilowanie pod kątem środowiska wykonawczego AIDL.
 - Usuń biblioteki tłumaczeń lub wygenerowany przez nie kod, który nie będzie używany.
 
Zobacz główne różnice między AIDL a HIDL:
- Korzystanie z wbudowanych w AIDL 
Statusi wyjątków zwykle poprawia interfejs i eliminuje potrzebę stosowania innego typu stanu specyficznego dla interfejsu. - Argumenty interfejsu AIDL w metodach nie są domyślnie 
@nullable, jak to miało miejsce w HIDL. 
- Korzystanie z wbudowanych w AIDL 
 
SEPolicy dla warstw HAL języka AIDL
Typ usługi AIDL widoczny dla kodu dostawcy musi mieć atrybut hal_service_type. W przeciwnym razie konfiguracja sepolicy jest taka sama jak w przypadku każdej innej usługi AIDL (chociaż istnieją specjalne atrybuty dla HAL). Oto przykładowa definicja kontekstu usługi HAL:
    type hal_foo_service, service_manager_type, hal_service_type;
W przypadku większości usług zdefiniowanych przez platformę kontekst usługi z odpowiednim typem jest już dodany (np. android.hardware.foo.IFoo/default jest już oznaczony jako hal_foo_service). Jeśli jednak klient platformy obsługuje wiele nazw instancji, dodatkowe nazwy instancji należy dodać w plikach service_contexts specyficznych dla urządzenia:
    android.hardware.foo.IFoo/custom_instance u:object_r:hal_foo_service:s0
Podczas tworzenia nowego typu HAL musisz dodać atrybuty HAL. Określony atrybut HAL może być powiązany z wieloma typami usług (z których każdy może mieć wiele instancji, jak wspomnieliśmy wcześniej). W przypadku HAL foo występuje hal_attribute(foo). Ten makrodefinicja określa atrybuty hal_foo_client i hal_foo_server. W przypadku danej domeny makra hal_client_domain i hal_server_domain łączą domenę z danym atrybutem HAL. Na przykład serwer systemowy będący klientem tej warstwy HAL odpowiada zasadzie hal_client_domain(system_server, hal_foo). Podobnie serwer HAL zawierahal_server_domain(my_hal_domain, hal_foo).
Zwykle w przypadku danego atrybutu HAL tworzy się też domenę, np.hal_foo_default, która zawiera przykładowe lub referencyjne HAL. Niektóre urządzenia używają jednak tych domen na potrzeby własnych serwerów. Rozróżnianie domen w przypadku wielu serwerów ma znaczenie tylko wtedy, gdy istnieje wiele serwerów, które obsługują ten sam interfejs i wymagają w swoich implementacjach innego zestawu uprawnień.
We wszystkich tych makrach hal_foo nie jest obiektem sepolicy. Zamiast tego makra te używają tego tokena do odwoływania się do grupy atrybutów powiązanych z parą serwerów klienta.
Jednak do tej pory atrybuty hal_foo_service i hal_foo (para atrybutów z hal_attribute(foo)) nie są powiązane. Atrybut HAL jest powiązany z usługami HAL AIDL za pomocą makra hal_attribute_service (usługi HAL HIDL używają makra hal_attribute_hwservice), np. hal_attribute_service(hal_foo, hal_foo_service). Oznacza to, że procesy hal_foo_client mogą uzyskać dostęp do HAL, a procesy hal_foo_server mogą zarejestrować HAL. Egzekwowaniem tych reguł rejestracji zajmuje się menedżer kontekstu (servicemanager).
Nazwy usług nie zawsze odpowiadają atrybutom HAL, np.hal_attribute_service(hal_foo, hal_foo2_service). Ogólnie rzecz biorąc, ponieważ oznacza to, że usługi są zawsze używane razem, możesz usunąć hal_foo2_service i używać hal_foo_service we wszystkich kontekstach usług. Gdy warstwy HAL ustawiają wiele instancji hal_attribute_service, dzieje się tak, ponieważ oryginalna nazwa atrybutu HAL nie jest wystarczająco ogólna i nie można jej zmienić.
Przykład HAL po połączeniu wszystkich elementów:
    public/attributes:
    // define hal_foo, hal_foo_client, hal_foo_server
    hal_attribute(foo)
    public/service.te
    // define hal_foo_service
    type hal_foo_service, hal_service_type, protected_service, service_manager_type
    public/hal_foo.te:
    // allow binder connection from client to server
    binder_call(hal_foo_client, hal_foo_server)
    // allow client to find the service, allow server to register the service
    hal_attribute_service(hal_foo, hal_foo_service)
    // allow binder communication from server to service_manager
    binder_use(hal_foo_server)
    private/service_contexts:
    // bind an AIDL service name to the selinux type
    android.hardware.foo.IFooXxxx/default u:object_r:hal_foo_service:s0
    private/<some_domain>.te:
    // let this domain use the hal service
    binder_use(some_domain)
    hal_client_domain(some_domain, hal_foo)
    vendor/<some_hal_server_domain>.te
    // let this domain serve the hal service
    hal_server_domain(some_hal_server_domain, hal_foo)
Dołączone interfejsy rozszerzeń
Rozszerzenie można dołączyć do dowolnego interfejsu bindera, niezależnie od tego, czy jest to interfejs najwyższego poziomu zarejestrowany bezpośrednio w menedżerze usług, czy interfejs podrzędny. Gdy otrzymasz rozszerzenie, musisz potwierdzić, że jego typ jest zgodny z oczekiwaniami. Rozszerzenia możesz ustawić tylko w procesie obsługującym segregator.
Używaj dołączonych rozszerzeń, gdy rozszerzenie modyfikuje funkcjonalność istniejącego HAL-u. Jeśli potrzebna jest zupełnie nowa funkcja, ten mechanizm nie jest konieczny i możesz zarejestrować interfejs rozszerzenia bezpośrednio w menedżerze usług. Interfejsy dołączonych rozszerzeń mają największy sens, gdy są dołączone do interfejsów podrzędnych, ponieważ te hierarchie mogą być rozbudowane lub wieloinstancyjne. Używanie globalnego rozszerzenia do odzwierciedlania hierarchii interfejsu bindera innej usługi wymaga rozbudowanej księgowości, aby zapewnić możliwości równoważne bezpośrednio dołączonym rozszerzeniom.
Aby ustawić rozszerzenie w przypadku segregatora, użyj tych interfejsów API:
- Backend NDK: 
AIBinder_setExtension - Backend Java: 
android.os.Binder.setExtension - Backend CPP: 
android::Binder::setExtension - Backend Rust: 
binder::Binder::set_extension 
Aby uzyskać rozszerzenie na segregatorze, użyj tych interfejsów API:
- Backend NDK: 
AIBinder_getExtension - Backend Java: 
android.os.IBinder.getExtension - Backend CPP: 
android::IBinder::getExtension - Backend Rust: 
binder::Binder::get_extension 
Więcej informacji o tych interfejsach API znajdziesz w dokumentacji funkcji getExtension w odpowiednim backendzie. Przykładem użycia rozszerzeń jest hardware/interfaces/tests/extension/vibrator.
Główne różnice między AIDL a HIDL
Jeśli używasz interfejsów HAL AIDL lub interfejsów HAL AIDL, pamiętaj o różnicach w porównaniu z pisaniem interfejsów HAL HIDL.
- Składnia języka AIDL jest bliższa językowi Java. Składnia HIDL jest podobna do składni C++.
 - Wszystkie interfejsy AIDL mają wbudowane stany błędów. Zamiast tworzyć niestandardowe typy stanu, utwórz stałe liczby całkowite stanu w plikach interfejsu i używaj 
EX_SERVICE_SPECIFICw backendach CPP i NDK orazServiceSpecificExceptionw backendzie Java. Zobacz Obsługa błędów. - AIDL nie uruchamia automatycznie puli wątków, gdy wysyłane są obiekty interfejsu. Musisz je uruchamiać ręcznie (patrz Zarządzanie wątkami).
 - AIDL nie przerywa działania w przypadku nieobsługiwanych błędów transportu (HIDL 
Returnprzerywa działanie w przypadku nieobsługiwanych błędów). - W każdym pliku AIDL można zadeklarować tylko 1 typ.
 - Argumenty AIDL można określić jako 
in,outlubinoutoprócz parametru wyjściowego (nie ma wywołań zwrotnych synchronicznych). - AIDL używa 
fdjako typu podstawowego zamiasthandle. - HIDL używa wersji głównych w przypadku zmian niezgodnych i wersji podrzędnych w przypadku zmian zgodnych. W AIDL zmiany zgodne wstecznie są wprowadzane w miejscu.
AIDL nie ma wyraźnej koncepcji wersji głównej. Zamiast tego jest ona włączona do nazw pakietów. Na przykład AIDL może używać nazwy pakietu 
bluetooth2. - AIDL domyślnie nie dziedziczy priorytetu czasu rzeczywistego. Aby włączyć dziedziczenie priorytetu w czasie rzeczywistym, w przypadku każdego bindera należy użyć funkcji 
setInheritRt. 
Testy HAL
W tej sekcji opisujemy sprawdzone metody testowania HAL-i. Te sprawdzone metody są ważne nawet wtedy, gdy test integracji interfejsu HAL nie znajduje się w VTS.
Android korzysta z VTS do weryfikowania oczekiwanych implementacji HAL. VTS pomaga zapewnić zgodność wsteczną Androida ze starszymi implementacjami dostawców. Implementacje, które nie przejdą testu VTS, mają znane problemy ze zgodnością, które mogą uniemożliwić im działanie w przyszłych wersjach systemu operacyjnego.
VTS dla HAL składa się z 2 głównych części.
1. Sprawdzanie, czy warstwy HAL na urządzeniu są znane i oczekiwane przez Androida
Android wymaga statycznej, dokładnej listy wszystkich zainstalowanych warstw HAL. Ta lista jest wyrażona w pliku manifestu VINTF. Specjalne testy na poziomie platformy weryfikują integralność warstw HAL w całym systemie. Przed napisaniem testów specyficznych dla HAL-u należy również uruchomić te testy, ponieważ mogą one wykryć niespójne konfiguracje VINTF w HAL-u.
Ten zestaw testów znajdziesz w sekcji test/vts-testcase/hal/treble/vintf. Jeśli pracujesz nad implementacją HAL dostawcy, użyj vts_treble_vintf_vendor_test, aby ją zweryfikować. Ten test możesz uruchomić za pomocą polecenia atest vts_treble_vintf_vendor_test.
Testy te służą do weryfikacji:
- Każdy interfejs 
@VintfStabilityzadeklarowany w manifeście VINTF jest zamrożony w znanej wersji. Weryfikuje to, czy obie strony interfejsu zgadzają się co do dokładnej definicji tej wersji interfejsu. Jest to niezbędne do podstawowego działania. - Wszystkie interfejsy HAL zadeklarowane w pliku manifestu VINTF są dostępne na tym urządzeniu. Każdy klient z uprawnieniami wystarczającymi do korzystania z zadeklarowanej usługi HAL musi mieć możliwość uzyskania i korzystania z tych usług w dowolnym momencie.
 - Wszystkie interfejsy HAL zadeklarowane w pliku manifestu VINTF obsługują wersję interfejsu zadeklarowaną w tym pliku.
 - Na urządzeniu nie są obsługiwane żadne wycofane interfejsy HAL. Android przestaje obsługiwać starsze wersje interfejsów HAL zgodnie z opisem w sekcji Cykl życia FCM.
 - Na urządzeniu są obecne wymagane warstwy HAL. Niektóre warstwy HAL są wymagane do prawidłowego działania Androida.
 
2. Sprawdzanie oczekiwanego działania każdego HAL-u
Każdy interfejs HAL ma własne testy VTS, które weryfikują oczekiwane zachowanie klientów. Testy są przeprowadzane na każdym wystąpieniu zadeklarowanego interfejsu HAL i wymagają określonego zachowania na podstawie wdrożonej wersji interfejsu.
W C++ możesz uzyskać listę wszystkich interfejsów HAL zainstalowanych w systemie za pomocą funkcji android::getAidlHalInstanceNames w libaidlvintf_gtest_helper. W Rust użyj binder::get_declared_instances.
Testy te obejmują wszystkie aspekty implementacji HAL, na których opiera się lub może się opierać w przyszłości platforma Androida.
Testy te obejmują weryfikację obsługi funkcji, obsługi błędów i innych zachowań, których klient może oczekiwać od usługi.
Kamienie milowe VTS w przypadku tworzenia HAL
Podczas tworzenia lub modyfikowania interfejsów HAL Androida należy aktualizować testy VTS (lub inne testy).
Testy VTS muszą być ukończone i gotowe do weryfikacji implementacji dostawców zanim zostaną zamrożone na potrzeby wydań interfejsu API dostawcy Androida. Muszą być gotowe, zanim interfejsy zostaną zablokowane, aby deweloperzy mogli tworzyć implementacje, weryfikować je i przekazywać opinie deweloperom interfejsu HAL.
Testowanie na platformie Cuttlefish
Gdy sprzęt nie jest dostępny, Android używa Cuttlefish jako platformy deweloperskiej dla interfejsów HAL. Umożliwia to skalowalne testowanie integracji Androida.
hal_implementation_test testy, które Cuttlefish ma zaimplementowane w najnowszych wersjach interfejsu HAL, aby mieć pewność, że Android jest gotowy do obsługi nowych interfejsów, a testy VTS są gotowe do testowania nowych implementacji dostawców, gdy tylko pojawią się nowe urządzenia.