Jede in einem HIDL-Paket definierte Schnittstelle hat eine eigene automatisch generierte C++-Klasse. im Namespace des Pakets enthalten. Clients und Server arbeiten mit Schnittstellen in verschiedene Möglichkeiten:
- Server implementieren Schnittstellen.
- Clients rufen Methoden für Schnittstellen auf.
Schnittstellen können entweder vom Server namentlich registriert oder als Parameter zu HIDL-definierten Methoden hinzufügen. Framework-Code kann beispielsweise Schnittstelle, um asynchrone Nachrichten vom HAL zu empfangen und diese Schnittstelle zu übergeben. direkt im HAL, ohne sie zu registrieren.
Serverimplementierung
Ein Server, der die IFoo
-Schnittstelle implementiert, muss Folgendes enthalten:
IFoo
-Headerdatei, die automatisch generiert wurde:
#include <android/hardware/samples/1.0/IFoo.h>
Der Header wird automatisch von der gemeinsam genutzten Bibliothek des
IFoo
-Schnittstelle, die verknüpft werden soll. Beispiel für IFoo.hal
:
// IFoo.hal interface IFoo { someMethod() generates (vec<uint32_t>); ... }
Beispielskelett für eine Serverimplementierung der IFoo-Schnittstelle:
// From the IFoo.h header using android::hardware::samples::V1_0::IFoo; class FooImpl : public IFoo { Return<void> someMethod(foo my_foo, someMethod_cb _cb) { vec<uint32_t> return_data; // Compute return_data _cb(return_data); return Void(); } ... };
Um einem Client die Implementierung einer Serverschnittstelle zur Verfügung zu stellen, müssen Sie kann:
- Registrieren Sie die Schnittstellenimplementierung bei der
hwservicemanager
(siehe Details unten),
ODER
- Übergeben Sie die Schnittstellenimplementierung als Argument eines (für weitere Details siehe Asynchrones Callbacks.
Bei der Registrierung der Schnittstellenimplementierung wird der Parameter
Der hwservicemanager
-Prozess verfolgt registrierte HIDL-Schnittstellen
Name und Version
auf dem Gerät ausgeführt werden. Server können eine HIDL-Schnittstelle registrieren.
Implementierung nach Name und Kunden können Dienstimplementierungen über den Namen anfordern
und Version. Dieser Prozess dient der HIDL-Schnittstelle
android.hidl.manager@1.0::IServiceManager
Jede automatisch generierte HIDL-Schnittstellen-Headerdatei (z. B. IFoo.h
)
verfügt über eine registerAsService()
-Methode, die zum Registrieren des
mithilfe der hwservicemanager
implementieren. Die einzige
Das erforderliche Argument ist der Name der Schnittstellenimplementierungen als Clients.
Verwenden Sie diesen Namen, um die Schnittstelle aus hwservicemanager
abzurufen.
später:
::android::sp<IFoo> myFoo = new FooImpl(); ::android::sp<IFoo> mySecondFoo = new FooAnotherImpl(); status_t status = myFoo->registerAsService(); status_t anotherStatus = mySecondFoo->registerAsService("another_foo");
hwservicemanager
behandelt die Kombination aus
„[package@version::interface, instance_name]
“ muss eindeutig sein, um die Funktion zu aktivieren.
verschiedene Schnittstellen (oder verschiedene Versionen derselben Schnittstelle) zu registrieren,
mit identischen Instanznamen ohne Konflikte. Wenn Sie
registerAsService()
mit exakt derselben Paketversion, Schnittstelle
und Instanznamen entfernt, verwirft hwservicemanager
seinen Verweis auf den
registriert und den neuen verwendet.
Client-Implementierung
Genau wie der Server muss ein Client jede Schnittstelle #include
.
sich auf Folgendes bezieht:
#include <android/hardware/samples/1.0/IFoo.h>
Ein Client kann eine Schnittstelle auf zwei Arten abrufen:
- Bis
I<InterfaceName>::getService
(über diehwservicemanager
) - Über eine Schnittstellenmethode
Jede automatisch generierte Schnittstellen-Header-Datei hat einen statischen getService
, die zum Abrufen einer Dienstinstanz aus dem
hwservicemanager
:
// getService returns nullptr if the service can't be found sp<IFoo> myFoo = IFoo::getService(); sp<IFoo> myAlternateFoo = IFoo::getService("another_foo");
Jetzt hat der Client eine IFoo
-Schnittstelle und kann Methoden aufrufen,
wie eine lokale Klassenimplementierung. Tatsächlich wird die Implementierung
können im selben, in einem anderen Prozess oder sogar auf einem anderen Gerät ausgeführt werden.
(mit HAL-Remoting). Da der Client getService
auf einem
IFoo
-Objekt aus Version 1.0
des Pakets,
hwservicemanager
gibt nur dann eine Serverimplementierung zurück, wenn diese
-Implementierung ist mit 1.0
-Clients kompatibel. In der Praxis bedeutet das
bedeutet nur Serverimplementierungen mit Version 1.n
(Version
x.(y+1)
einer Schnittstelle muss erweitert werden (übernehmen von)
x.y
.
Außerdem wird die Methode castFrom
zum Umwandeln zwischen
verschiedenen Benutzeroberflächen. Bei dieser Methode wird ein IPC-Aufruf an die Remote-
um sicherzustellen, dass der zugrunde liegende Typ
angefordert. Wenn der angeforderte Typ nicht verfügbar ist, gilt: nullptr
zurückgegeben.
sp<V1_0::IFoo> foo1_0 = V1_0::IFoo::getService(); sp<V1_1::IFoo> foo1_1 = V1_1::IFoo::castFrom(foo1_0);
Asynchrone Callbacks
Viele bestehende HAL-Implementierungen kommunizieren mit asynchroner Hardware, was bedeutet, Sie benötigen eine asynchrone Methode, um Kunden über neue Ereignisse zu informieren, aufgetreten. Eine HIDL-Schnittstelle kann als asynchroner Rückruf verwendet werden, da HIDL -Schnittstellenfunktionen können HIDL-Schnittstellenobjekte als Parameter verwenden.
Beispieldatei IFooCallback.hal
:
package android.hardware.samples@1.0; interface IFooCallback { sendEvent(uint32_t event_id); sendData(vec<uint8_t> data); }
Beispiel für eine neue Methode in IFoo
, die eine
IFooCallback
-Parameter:
package android.hardware.samples@1.0; interface IFoo { struct Foo { int64_t someValue; handle myHandle; }; someMethod(Foo foo) generates (int32_t ret); anotherMethod() generates (vec<uint32_t>); registerCallback(IFooCallback callback); };
Der Client, der die IFoo
-Schnittstelle verwendet, ist der
server der IFooCallback
-Schnittstelle bietet es eine
Implementierung von IFooCallback
:
class FooCallback : public IFooCallback { Return<void> sendEvent(uint32_t event_id) { // process the event from the HAL } Return<void> sendData(const hidl_vec<uint8_t>& data) { // process data from the HAL } };
Er kann diese auch einfach an eine vorhandene Instanz des
IFoo
-Schnittstelle:
sp<IFooCallback> myFooCallback = new FooCallback(); myFoo.registerCallback(myFooCallback);
Der Server, der IFoo
implementiert, empfängt dies als
sp<IFooCallback>
-Objekt. Er kann den Callback speichern
wenn er diese Schnittstelle verwenden möchte.
Todesopfer
Da Dienstimplementierungen
in einem anderen Prozess ausgeführt werden können,
dass der Prozess zur Implementierung einer Schnittstelle beendet wird, während der Client aktiv bleibt.
Alle Aufrufe eines Interface-Objekts, das in einem abgebrochenen Prozess gehostet wird, schlagen fehl
mit einem Transportfehler (isOK()
gibt false
zurück). Die einzige Möglichkeit,
Wiederherstellung nach einem solchen Fehler
ist die Anforderung einer neuen Instanz des Dienstes,
I<InterfaceName>::getService()
wird angerufen. Dies funktioniert nur, wenn
Der abgestürzte Prozess wurde neu gestartet und seine Dienste wurden neu registriert
servicemanager
(gilt generell für HAL-Implementierungen).
Anstatt reaktiv damit zu arbeiten, können Benutzeroberflächen-Clients auch
Registrieren Sie einen Empfänger der Todesfälle, um über die Beendigung eines Dienstes benachrichtigt zu werden.
Um sich für solche Benachrichtigungen auf einer abgerufenen IFoo
-Oberfläche zu registrieren,
kann er Folgendes tun:
foo->linkToDeath(recipient, 1481 /* cookie */);
Der recipient
-Parameter muss eine Implementierung der
android::hardware::hidl_death_recipient
-Schnittstelle von HIDL bereitgestellt,
mit einer einzigen serviceDied()
-Methode, die
aus einem Thread im RPC-Threadpool, wenn der Prozess, der die Schnittstelle hostet, beendet wird:
class MyDeathRecipient : public android::hardware::hidl_death_recipient { virtual void serviceDied(uint64_t cookie, const android::wp<::android::hidl::base::V1_0::IBase>& who) { // Deal with the fact that the service died } }
Der Parameter cookie
enthält das Cookie, das mit übergeben wurde:
linkToDeath()
, während der who
-Parameter ein
Schwachstellenzeiger auf das Objekt, das den Dienst im Client darstellt. Mit der
oben angegebener Beispielaufruf; cookie
ist 1.481 und who
gleich foo
.
Es ist auch möglich, einen Empfänger, der verstorben ist, nach der Registrierung abzumelden:
foo->unlinkToDeath(recipient);