Auf dieser Seite wird beschrieben, wie Sie Dienste registrieren und entdecken
Daten an einen Dienst durch Aufrufen von Methoden, die in Schnittstellen in .hal
definiert sind
Dateien.
Registrierungsdienste
HIDL-Schnittstellenserver (Objekte, die die Schnittstelle implementieren) können registriert werden. als benannte Dienste. Der registrierte Name muss nicht mit der Schnittstelle in Verbindung stehen oder Paketname. Wenn kein Name angegeben ist, lautet der Name „default“. verwendet wird; Dies sollte werden für HALs verwendet, die nicht zwei Implementierungen . Der C++-Aufruf für die Dienstregistrierung, der in den einzelnen ist:
status_t status = myFoo->registerAsService(); status_t anotherStatus = anotherFoo->registerAsService("another_foo_service"); // if needed
Die Version einer HIDL-Schnittstelle ist in der Schnittstelle selbst enthalten. Es ist
automatisch mit der Dienstregistrierung verknüpft und kann über eine
Methodenaufruf (android::hardware::IInterface::getInterfaceVersion()
)
auf jeder HIDL-Benutzeroberfläche. Serverobjekte müssen nicht registriert sein und können übergeben werden
über HIDL-Methodenparameter zu einem anderen Prozess, der HIDL-Methodenaufrufe durchführt
auf dem Server.
Dienste entdecken
Anfragen von Clientcode werden für eine bestimmte Schnittstelle anhand des Namens und
Version und rufen getService
für die gewünschte HAL-Klasse auf:
// C++ sp<V1_1::IFooService> service = V1_1::IFooService::getService(); sp<V1_1::IFooService> alternateService = V1_1::IFooService::getService("another_foo_service"); // Java V1_1.IFooService service = V1_1.IFooService.getService(true /* retry */); V1_1.IFooService alternateService = V1_1.IFooService.getService("another", true /* retry */);
Jede Version einer HIDL-Schnittstelle wird als separate Schnittstelle behandelt. Das heißt:
IFooService
Version 1.1 und IFooService
Version 2.2
können beide als „foo_service“ registriert werden und
Für getService("foo_service")
auf einer der beiden Schnittstelle wird die Registrierung
für diese Schnittstelle. Daher ist in den meisten Fällen kein Namensparameter
für die Registrierung oder Erkennung bereitgestellt werden soll (d. h. der Name "Standard").
Das Vendor Interface Object spielt auch eine Rolle bei der Transportmethode der
zurückgegebene Schnittstelle. Für eine Schnittstelle im Paket IFoo
android.hardware.foo@1.0
, die von
IFoo::getService
verwendet immer die Transportmethode, die für
android.hardware.foo
im Gerätemanifest, wenn der Eintrag vorhanden ist
Wenn die Transportmethode nicht verfügbar ist, wird nullptr zurückgegeben.
In einigen Fällen kann es notwendig sein, sofort fortzufahren,
den Service zu erhalten. Das kann zum Beispiel passieren, wenn ein Kunde
Dienstbenachrichtigungen selbst oder in einem Diagnoseprogramm (z. B.
atrace
), der alle Hardwaredienste abrufen und abrufen muss. In
In diesem Fall werden zusätzliche APIs bereitgestellt, z. B. tryGetService
in C++ oder
getService("instance-name", false)
in Java. Die alte API
getService
in Java muss auch mit dem Dienst verwendet werden
Benachrichtigungen. Die Verwendung dieser API verhindert nicht die Race-Bedingung, bei der ein Server
registriert sich selbst, nachdem der Client sie mit einer dieser No-Wiederholungs-APIs anfordert.
Benachrichtigungen bei Dienstmängeln
Kunden, die benachrichtigt werden möchten, wenn ein Dienst stirbt, können die vom Framework gelieferten Benachrichtigungen. Um Benachrichtigungen zu erhalten, muss der Client muss:
- Erstellen Sie abgeleitete Klassen der HIDL-Klasse/Schnittstelle
hidl_death_recipient
(in C++ und nicht in HIDL). - Überschreibt die zugehörige
serviceDied()
-Methode. - Instanziieren Sie ein Objekt der abgeleiteten
hidl_death_recipient
-Klasse. - Rufen Sie die Methode
linkToDeath()
für den zu überwachenden Dienst auf. und übergeben das Interface-Objekt derIDeathRecipient
. Beachten Sie, dass dies übernimmt weder den Todempfänger noch den Proxy, aufgerufen wird.
Hier ein Pseudocode-Beispiel (C++ und Java sind ähnlich):
class IMyDeathReceiver : hidl_death_recipient { virtual void serviceDied(uint64_t cookie, wp<IBase>& service) override { log("RIP service %d!", cookie); // Cookie should be 42 } }; .... IMyDeathReceiver deathReceiver = new IMyDeathReceiver(); m_importantService->linkToDeath(deathReceiver, 42);
Ein Todesempfänger kann bei mehreren verschiedenen Diensten registriert werden.
Datenübertragung
Daten können an einen Dienst gesendet werden, indem Methoden aufgerufen werden, die in Schnittstellen in
.hal
-Dateien. Es gibt zwei Arten von Methoden:
- Blocking-Methoden warten, bis der Server einen Fehler ausgegeben hat. Ergebnis.
- Einwegmethoden senden Daten nur in eine Richtung und blockieren. Wenn die Menge der laufenden Daten in RPC-Aufrufen die Implementierung überschreitet können die Aufrufe entweder blockieren oder eine Fehlermeldung zurückgeben (Verhalten ist noch nicht festgelegt).
Eine Methode, die keinen Wert zurückgibt, aber nicht als deklariert
oneway
wird immer noch blockiert.
Alle in einer HIDL-Schnittstelle deklarierten Methoden werden in eine Richtung aufgerufen. entweder aus dem HAL oder in den HAL. In der Schnittstelle wird nicht angegeben, in welcher Richtung sie aufgerufen wird. Architekturen, von denen Aufrufe stammen müssen sollte der HAL zwei (oder mehr) Schnittstellen im HAL-Paket bereitstellen und den Schnittstelle von jedem Prozess aus. Die Wörter client und server werden in Bezug auf die Aufrufrichtung der Schnittstelle verwendet. (d.h., der HAL kann ein Server der einen Schnittstelle und ein Client einer anderen Schnittstelle sein) .
Rückrufe
Das Wort Callback bezieht sich auf zwei verschiedene Konzepte, die sich synchroner Callback und asynchroner Callback.
Synchrone Callbacks werden in einigen HIDL-Methoden verwendet, die Daten. Eine HIDL-Methode, die mehr als einen Wert (oder einen Wert von nicht primitiven Typ) gibt seine Ergebnisse über eine Callback-Funktion zurück. Wenn nur eines zurückgegeben und es sich um einen primitiven Typ handelt, wird kein Callback verwendet und der Parameter wird von der Methode zurückgegeben. Der Server implementiert die HIDL-Methoden und implementiert der Client die Callbacks.
Asynchrone Rückrufe ermöglichen dem Server einer HIDL-Schnittstelle Folgendes:
Anrufe zu generieren. Dazu wird eine Instanz einer zweiten Schnittstelle übergeben.
über die erste Benutzeroberfläche. Der Client der ersten Schnittstelle muss als
des zweiten Servers. Der Server der ersten Schnittstelle kann Methoden im
zweiten Schnittstellenobjekts. Beispielsweise kann eine HAL-Implementierung Informationen
asynchron zurück zu dem Prozess, der sie verwendet, indem Methoden auf einem
das durch diesen Prozess erstellt und bereitgestellt wird. Methoden in verwendeten Schnittstellen
für einen asynchronen Callback möglicherweise blockiert (und Werte an den Aufrufer zurückgeben).
oder oneway
. Ein Beispiel finden Sie unter „Asynchrone Callbacks“. in
HIDL C++:
Um die Inhaberschaft von Arbeitsspeicher zu vereinfachen, benötigen Methodenaufrufe und Callbacks nur
in
-Parameter und unterstützen nicht out
oder
inout
-Parameter.
Limits pro Transaktion
Für die Datenmenge, die im HIDL gesendet wird, gibt es keine Limits pro Transaktion
Methoden und Callbacks verwenden. Aufrufe mit mehr als 4 KB pro Transaktion werden jedoch
als übertrieben empfunden werden. In diesem Fall wird die vorhandene HIDL-Schnittstelle
wird empfohlen. Eine weitere Einschränkung sind die für die HIDL verfügbaren Ressourcen
um mehrere Transaktionen gleichzeitig abzuwickeln. Mehrere
Transaktionen können aufgrund mehrerer Threads oder
das Senden von Aufrufen an einen Prozess oder mehrere oneway
-Aufrufe,
vom Empfangsprozess
nicht schnell verarbeitet werden. Der maximale Gesamtspeicher
ist standardmäßig 1 MB groß.
In einer gut gestalteten Oberfläche sollte das Überschreiten dieser Ressourcenbeschränkungen passieren, Ist dies der Fall, kann der entsprechende Aufruf blockiert werden, bis Ressourcen verfügbar werden oder einen Transportfehler signalisieren. Bei jedem Auftreten von das Überschreiten von Transaktionslimits oder überlaufende HIDL-Implementierungsressourcen, aggregierte In-Flight-Transaktionen protokolliert, um die Fehlerbehebung zu erleichtern.
Methodenimplementierungen
HIDL generiert Header-Dateien, in denen die erforderlichen Typen, Methoden und -Callbacks in der Zielsprache (C++ oder Java) zu erstellen. Der Prototyp eines HIDL-definierten und Callbacks sind für Client- und Servercode identisch. Das HIDL Proxy-Implementierungen der Methoden im Aufruferseite, die die Daten für den IPC-Transport organisiert, und Stub Code auf der Seite des aufgerufenen Nutzers, der die Daten an Methoden.
Der Aufrufer einer Funktion (HIDL-Methode oder Callback) ist Eigentümer der Daten. an die Funktion übergebene Strukturen und behält nach dem Aufruf die Inhaberschaft. in In allen Fällen muss der Aufgerufene den Speicherplatz nicht freigeben oder freigeben.
- In C++ sind die Daten möglicherweise schreibgeschützt (Versuche, in sie zu schreiben, Segmentierungsfehler) und sind für die Dauer des Aufrufs gültig. Der Kunde kann die Daten tief kopieren, um sie über den Aufruf hinaus zu verbreiten.
- In Java empfängt der Code eine lokale Kopie der Daten (ein normales Java-Objekt). die möglicherweise beibehalten und änderbar sind oder die automatische Speicherbereinigung erlaubt.
Nicht-RPC-Datenübertragung
HIDL bietet zwei Möglichkeiten, Daten ohne einen RPC-Aufruf zu übertragen: freigegeben Arbeitsspeicher und eine Fast Message Queue (FMQ), die beide nur in C++ unterstützt werden.
- Gemeinsamer Speicher: Der integrierte HIDL-Typ
memory
wird verwendet, um ein Objekt zu übergeben, das den zugewiesenen gemeinsamen Speicher darstellt. Kann in einem Empfangsprozess verwendet werden, um den gemeinsamen Speicher zuzuordnen. - Fast Message Queue (FMQ): HIDL stellt eine
Vorlagennachricht bereit,
Warteschlangentyp, der die Übergabe von Nachrichten ohne Warteschleifen implementiert. Es verwendet nicht den Kernel
Planer im Passthrough- oder binderized-Modus (die geräteübergreifende Kommunikation
diese Eigenschaften haben). In der Regel richtet der HAL das Ende der Warteschlange ein.
Erstellen eines Objekts, das über RPC über einen Parameter der integrierten
HIDL-Typ
MQDescriptorSync
oderMQDescriptorUnsync
. Dieses -Objekt kann vom empfangenden Prozess zum Einrichten des anderen Endes der Warteschlange verwendet werden.- Synchronisierungswarteschlangen dürfen nicht überlaufen und dürfen nur eine enthalten Leser.
- Unsync-Warteschlangen können überlaufen und viele Leser umfassen. von denen jeder Daten rechtzeitig lesen oder verlieren muss.
Weitere Informationen zu FMQ finden Sie unter Fast Message Queue (FMQ):