HIDL w Javie

W Androidzie 8.0 zmieniono architekturę systemu operacyjnego Android, aby zdefiniować przejrzyste interfejsy między platformą Android niezależnie od urządzenia a modelem urządzenia i dostawcy, w kodzie. Wiele takich interfejsów w Androidzie zostały już zdefiniowane w postaci HAL. interfejsów zdefiniowanych jako nagłówki C w hardware/libhardware. HIDL zastąpiliśmy interfejsy HAL stabilnymi, wersjonowanymi interfejsami, które mogą być w języku Java (opisany poniżej) lub HIDL po stronie klienta i serwera w C++.

Interfejsy HIDL są przeznaczone przede wszystkim do stosowania w kodzie natywnym oraz jako W efekcie HIDL koncentruje się na automatycznym generowaniu wydajnego kodu w języku C++. Pamiętaj jednak: Interfejsy HIDL muszą być również dostępne do użycia bezpośrednio w języku Java, jak niektóre platformy Android podsystemy (np. Telefonia) mają interfejsy HIDL w Javie.

Na stronach w tej sekcji opisaliśmy frontend Java dla interfejsów HIDL, jak tworzyć, rejestrować i korzystać z usług oraz wyjaśnić, jak HAL i HAL Klienty napisane w Javie współdziałają z systemem RPC HIDL.

Przykład klienta

To jest przykład klienta interfejsu IFoo w pakiecie android.hardware.foo@1.0, która jest zarejestrowana jako nazwa usługi default i usługa dodatkowa o niestandardowej nazwie usługi second_impl

Dodaj biblioteki

Musisz dodać zależności od odpowiedniej biblioteki skróconej HIDL, jeśli chcesz go używać. Zwykle jest to biblioteka statyczna:

// in Android.bp
static_libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

Jeśli wiesz, że pobierasz już zależności od tych bibliotek, można też użyć udostępnionego linku:

// in Android.bp
libs: [ "android.hardware.foo-V1.0-java", ],
// in Android.mk
LOCAL_JAVA_LIBRARIES += android.hardware.foo-V1.0-java

Dodatkowe uwagi na temat dodawania bibliotek w Androidzie 10

Jeśli masz aplikację systemową lub aplikację dostawcy przeznaczoną na Androida 10 lub nowszego, możesz statycznie uwzględnić te biblioteki. Możesz też korzystać tylko z zajęć HIDL z niestandardowych plików JAR zainstalowanych na urządzeniu z udostępnionymi stabilnymi interfejsami API Java za pomocą istniejącego mechanizmu uses-library w przypadku aplikacji systemowych. pozwala zaoszczędzić miejsce na urządzeniu. Więcej informacji znajdziesz w artykule Wdrażanie biblioteki pakietu SDK Java. Dla: starszych aplikacji, zostaje zachowany stary sposób działania.

Od Androida 10 („płytki”) wersji tych bibliotek . Dotyczy to zajęć, których dotyczy problem, ale nie ma żadnych klas zależnych. Przykład: android.hardware.foo-V1.0-java-shallow obejmuje zajęcia w aplikacji pakiet, ale nie zawiera klas w android.hidl.base-V1.0-java, która zawiera klasę bazową wszystkich Interfejsy HIDL. Jeśli tworzysz bibliotekę, w której jest już preferowany klas podstawowych interfejsu są dostępne jako zależność, możesz użyć następującego kodu:

// in Android.bp
static_libs: [ "android.hardware.foo-V1.0-java-shallow", ],
// in Android.mk
LOCAL_STATIC_JAVA_LIBRARIES += android.hardware.foo-V1.0-java-shallow

Biblioteki podstawowe i menedżera HIDL nie są już dostępne podczas uruchamiania. classpath aplikacji (wcześniej były one czasem używane jako ukryte interfejsy API ze względu na w przypadku Androida z przekazywaniem dostępu w pierwszej kolejności). Zostały one przeniesione do nowego przestrzeni nazw z atrybutem jarjar oraz aplikacje, które z nich korzystają (niezbędne aplikacje) muszą mieć oddzielne kopie. Moduły w ścieżce klasy rozruchowej za pomocą funkcji HIDL musi używać płytkich wersji tych bibliotek Java i dodawać jarjar_rules: ":framework-jarjar-rules" na ich Android.bp, aby używać istniejących wersji tych bibliotek w ścieżce klasy uruchamiania.

Modyfikowanie źródła w Javie

Ta usługa istnieje tylko w jednej wersji (@1.0), więc ten kod pobiera tylko tę wersję. Zobacz rozszerzenia interfejsu , aby dowiedzieć się, jak obsługiwać różne wersje usługi.

import android.hardware.foo.V1_0.IFoo;
...
// retry to wait until the service starts up if it is in the manifest
IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
IFoo anotherServer = IFoo.getService("second_impl", true /* retry */);
server.doSomething(…);

Świadczenie usługi

Kod platformy w Javie może wymagać obsługi interfejsów, aby otrzymywać asynchroniczne wywołań zwrotnych z list HAL.

Dla interfejsu IFooCallback w wersji 1.0 android.hardware.foo, możesz wdrożyć swój interfejs w w Javie, wykonując te czynności:

  1. Zdefiniuj interfejs w HIDL.
  2. Otwórz aplikację /tmp/android/hardware/foo/IFooCallback.java jako odwołania.
  3. Utwórz nowy moduł implementacji w języku Java.
  4. Przeanalizuj klasę abstrakcyjną android.hardware.foo.V1_0.IFooCallback.Stub, a następnie napisz nowe zajęcia aby ją rozszerzyć i wdrożyć metody abstrakcyjne.

Wyświetl pliki wygenerowane automatycznie

Aby wyświetlić automatycznie wygenerowane pliki, uruchom polecenie:

hidl-gen -o /tmp -Ljava \
  -randroid.hardware:hardware/interfaces \
  -randroid.hidl:system/libhidl/transport android.hardware.foo@1.0

Te polecenia generują katalog /tmp/android/hardware/foo/1.0 W przypadku pliku hardware/interfaces/foo/1.0/IFooCallback.hal, generuje plik /tmp/android/hardware/foo/1.0/IFooCallback.java, który otacza interfejs Java, kod serwera proxy i namioty (zarówno proxy, jak i aktówki są zgodne z interfejsem).

-Lmakefile generuje reguły, które uruchamiają to polecenie podczas kompilacji i umieszczać w nim android.hardware.foo-V1.0-java i zawiera link do odpowiednie pliki. Skrypt, który robi to automatycznie w przypadku projektu pełnego pod adresem hardware/interfaces/update-makefiles.sh. Ścieżki w tym przykładzie są względne, sprzęt/interfejsy mogą być tymczasowym w drzewie kodu, aby umożliwić opracowanie kodu HAL przed podczas publikacji.

Uruchom usługę

HAL udostępnia interfejs IFoo, który musi być asynchroniczny wywołania zwrotne do platformy w interfejsie IFooCallback. Interfejs IFooCallback nie jest zarejestrowany z nazwy jako wykrywalny Service; zamiast tego IFoo musi zawierać metodę, taką jak setFooCallback(IFooCallback x)

Aby skonfigurować IFooCallback z wersji 1.0 pakiet android.hardware.foo, dodaj android.hardware.foo-V1.0-java do Android.mk. Kod aby uruchomić usługę:

import android.hardware.foo.V1_0.IFoo;
import android.hardware.foo.V1_0.IFooCallback.Stub;
....
class FooCallback extends IFooCallback.Stub {
    // implement methods
}
....
// Get the service from which you will be receiving callbacks.
// This also starts the threadpool for your callback service.
IFoo server = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
....
// This must be a persistent instance variable, not local,
//   to avoid premature garbage collection.
FooCallback mFooCallback = new FooCallback();
....
// Do this once to create the callback service and tell the "foo-bar" service
server.setFooCallback(mFooCallback);

Rozszerzenia interfejsu

Przy założeniu, że dana usługa implementuje interfejs IFoo we wszystkich na określonych urządzeniach może być ona udostępniana dodatkowe możliwości zaimplementowane w rozszerzeniu interfejsu IBetterFoo w następujący sposób:

interface IFoo {
   ...
};

interface IBetterFoo extends IFoo {
   ...
};

Kod połączenia znający rozszerzony interfejs może używać funkcji Metoda Java castFrom() do bezpiecznego przesyłania interfejsu podstawowego na rozszerzony interfejs:

IFoo baseService = IFoo.getService(true /* retry */); // throws NoSuchElementException if not available
IBetterFoo extendedService = IBetterFoo.castFrom(baseService);
if (extendedService != null) {
  // The service implements the extended interface.
} else {
  // The service implements only the base interface.
}