HAL-Schnittstellendefinitionssprache (HIDL) ist eine Schnittstellenbeschreibungssprache (IDL), die Sie angeben müssen. der Schnittstelle zwischen einem HAL und für die Nutzenden. HIDL ermöglicht die Angabe von Typen und Methodenaufrufen, die in Schnittstellen und Pakete. Im Allgemeinen ist HIDL ein System zur Kommunikation zwischen Codebasen zu erstellen, die unabhängig kompiliert werden können.
<ph type="x-smartling-placeholder">HIDL ist für die Inter-Process-Kommunikation (IPC) vorgesehen. Mit HDL erstellte HALs sind sogenannte binderisierte HALs, da sie über Binder mit anderen Architekturebenen kommunizieren können. IPC-Aufrufe (Inter-Process Communication) Gebundene HALs werden in einem separaten Prozess vom Client ausgeführt der sie verwendet. Für Bibliotheken, die mit einem Prozess verknüpft sein müssen, einem Passthrough mode ist ebenfalls verfügbar (in Java nicht unterstützt).
HIDL gibt Datenstrukturen und Methodensignaturen an, die in Schnittstellen organisiert sind. (ähnlich einer Klasse), die in Paketen zusammengefasst werden. Die Syntax von HIDL kommt in C++ und mit einem anderen Satz an Java-Programmierern Keywords. HIDL verwendet auch Anmerkungen im Java-Stil.
Terminologie
In diesem Abschnitt werden die folgenden HIDL-bezogenen Begriffe verwendet:
binderhaltig | Gibt an, dass HIDL für Remote-Prozeduraufrufe zwischen Prozessen verwendet wird. über einen Binder-ähnlichen Mechanismus implementiert. Siehe auch Passthrough. |
---|---|
Callback, asynchron | Schnittstelle, die von einem HAL-Nutzer bereitgestellt und mithilfe einer HIDL-Methode an den HAL übergeben wird von HAL aufgerufen werden, um jederzeit Daten zurückzugeben. |
Callback, synchron | Gibt Daten von der HIDL-Methodenimplementierung eines Servers an den Client zurück. Nicht verwendet für Methoden, die void oder einen einzelnen primitiven Wert zurückgeben. |
client | Prozess, der Methoden einer bestimmten Schnittstelle aufruft. Ein HAL- oder Android-Framework kann ein Client der einen Schnittstelle und ein Server der anderen Schnittstelle sein. Siehe auch Passthrough an. |
erweitert | Gibt eine Schnittstelle an, die Methoden und/oder Typen einer anderen Schnittstelle hinzufügt. Eine Schnittstelle kann nur eine andere Schnittstelle erweitern. Kann für Minderjährige verwendet werden Versionserhöhung im selben Paketnamen oder für ein neues Paket (z.B. für einen Anbieter Erweiterung) auf ein älteres Paket zu bauen. |
generieren | Gibt eine Schnittstellenmethode an, die Werte an den Client zurückgibt. Zurückgeben ein nicht primitiver Wert oder mehrere Werte, eine synchrone Callback-Funktion generiert wird. |
interface | Sammlung von Methoden und Typen. Übersetzt in eine Klasse in C++ oder Java. Alle werden Methoden in einer Schnittstelle in die gleiche Richtung aufgerufen: ein Client-Prozess, ruft Methoden auf, die von einem Serverprozess implementiert wurden. |
Nur Hinflug | Bei Anwendung auf eine HIDL-Methode wird angegeben, dass die Methode keine Werte zurückgibt und nicht blockiert. |
Paket | Sammlung von Schnittstellen und Datentypen mit derselben Version. |
Durchschleifen | HIDL-Modus, bei dem der Server eine gemeinsam genutzte Bibliothek ist, dlopen
der Kundschaft. Im Passthrough-Modus sind Client und Server der gleiche Prozess,
separate Codebasen. Wird nur verwendet, um Legacy-Codebasen in das HIDL-Modell zu importieren.
Siehe auch Binderized. |
Server | Prozess, der Methoden einer Schnittstelle implementiert. Siehe auch Passthrough an. |
Verkehrsmittel | HIDL-Infrastruktur, die Daten zwischen dem Server und dem Client verschiebt |
Version | Version eines Pakets. Besteht aus zwei Ganzzahlen, groß und klein. Geringfügig Versionsstufen können Typen und Methoden hinzufügen, aber nicht ändern. |
HIDL-Design
Das Ziel von HIDL ist es, dass das Android-Framework ersetzt werden kann, ohne
HALs neu erstellen. HALs werden von Zulieferunternehmen oder SOC-Herstellern
/vendor
-Partition auf dem Gerät, wodurch das Android-Framework separat aktiviert wird
ohne Neukompilierung der HALs durch ein OTA-Laufwerk zu ersetzen.
Das HIDL-Design bietet einen Ausgleich zu den folgenden Anforderungen:
- Interoperabilität. Zuverlässig interoperable Schnittstellen erstellen zwischen Prozessen, die mit verschiedenen Architekturen, Toolchains, und Build-Konfigurationen. HIDL-Schnittstellen sind versioniert und können nicht geändert werden nachdem sie veröffentlicht wurden.
- Effizienz: HIDL versucht, die Anzahl der Kopien Geschäftsabläufe. HIDL-definierte Daten werden an C++-Code im C++-Standardlayout übergeben. Datenstrukturen, die ohne Entpacken genutzt werden können. HIDL bietet außerdem Speicherschnittstellen. Da RPCs grundsätzlich langsam sind, unterstützt HIDL zwei Möglichkeiten zur Datenübertragung ohne RPC-Aufruf: gemeinsamer Speicher und ein schnelles Message Queue (FMQ).
- Intuitiv: HIDL vermeidet holprige Probleme der Arbeitsspeicherinhaberschaft,
unter Verwendung von
in
-Parametern für RPC (siehe Android-Geräte Interface Definition Language (AIDL) Werte, die nicht effizient Methoden werden über Callback-Funktionen zurückgegeben. Weder übergeben noch Daten oder der Empfang von Daten von HIDL ändert Daten – bleibt die Eigentümerschaft immer bei der aufrufenden Funktion. Daten müssen bleiben nur für die Dauer der aufgerufenen Funktion bestehen und können gelöscht werden. direkt nach Rückgabe der aufgerufenen Funktion.
Passthrough-Modus verwenden
Wenn Sie Geräte mit älteren Android-Versionen auf Android O aktualisieren möchten, haben Sie folgende Möglichkeiten: sowohl herkömmliche (als auch ältere) HALs in eine neue HIDL-Schnittstelle packen, die den HAL im binderisierten und Same-Prozess-Modus (Passthrough). Dieses Wrapping ist sowohl für das HAL- als auch für das Android-Framework transparent sind.
Der Passthrough-Modus ist nur für C++-Clients und -Implementierungen verfügbar. Auf Geräten mit älteren Android-Versionen sind HALs nicht in Java geschrieben. Java-HALs sind von Natur aus binderbasiert.
Passthrough-Header-Dateien
Wenn eine .hal
-Datei kompiliert wird, erzeugt hidl-gen
einen
zusätzliche Passthrough-Header-Datei BsFoo.h
zusätzlich zu den Headern
zur Binder-Kommunikation verwendet werden; mit dieser Kopfzeile definiert,
dlopen
ed. Da Passthrough-HALs im selben Prozess ausgeführt werden,
werden sie aufgerufen. In den meisten Fällen werden Passthrough-Methoden durch direkte
Funktionsaufruf (derselbe Thread). oneway
Methoden werden in einem eigenen Thread ausgeführt
da sie nicht darauf warten sollen, bis der HAL sie verarbeitet hat (d. h. alle HAL
die oneway
-Methoden im Passthrough-Modus verwenden, müssen threadsicher sein.
Bei einem IFoo.hal
umschließt BsFoo.h
das HIDL-generierte
Methoden zur Bereitstellung zusätzlicher Funktionen (z. B. zum Erstellen von oneway
)
Transaktionen, die in einem anderen Thread ausgeführt werden). Diese Datei ähnelt
BpFoo.h
, anstatt IPC-Aufrufe jedoch mit binder zu übergeben,
die gewünschten Funktionen
direkt aufgerufen werden. Zukünftige Implementierungen von HALs
können mehrere Implementierungen wie FooFast HAL und einen
Genaue HAL. In diesen Fällen würde eine Datei für jede zusätzliche Implementierung
erstellt werden (z.B. PTFooFast.cpp
und
PTFooAccurate.cpp
).
Passthrough-HALs binden
Sie können HAL-Implementierungen, die den Passthrough-Modus unterstützen, in eine Bindung einbinden. Bei
HAL-Schnittstelle a.b.c.d@M.N::IFoo
, zwei Pakete werden erstellt:
a.b.c.d@M.N::IFoo-impl
Enthält die Implementierung der HAL und stellt die FunktionIFoo* HIDL_FETCH_IFoo(const char* name)
bereit. An alten Geräten ist, ist dieses Paketdlopen
beinhaltet und die Implementierung ist mitHIDL_FETCH_IFoo
instanziiert werden. Sie können den Basiscode generieren mithidl-gen
und-Lc++-impl
und-Landroidbp-impl
a.b.c.d@M.N::IFoo-service
Öffnet den Passthrough-HAL und registriert sich als binderisierter Dienst, wodurch dieselbe HAL-Implementierung aktiviert wird verwendet als Passthrough und binderisiert.
Mit dem Typ IFoo
können Sie sp<IFoo>
IFoo::getService(string name, bool getStub)
aufrufen, um Zugriff auf eine Instanz zu erhalten.
von IFoo
. Wenn getStub
„true“ ist, getService
versucht, den HAL nur im Passthrough-Modus zu öffnen. Wenn getStub
gleich
false, getService
versucht, einen verknüpften Dienst zu finden. wenn das
schlägt er fehl,
wird versucht, den Passthrough-Dienst zu finden. Das getStub
sollte niemals verwendet werden, außer in
defaultPassthroughServiceImplementation
. (Geräte werden mit
Android O sind vollständig gebundene Geräte, sodass ein Dienst im Passthrough-Modus geöffnet wird.
ist nicht zulässig.)
HIDL-Grammatik
Die HIDL-Sprache ist so konzipiert, dass sie C ähnelt (sie verwendet jedoch nicht das C
Präprozessor). Alle Satzzeichen, die unten nicht beschrieben sind (abgesehen von der offensichtlichen Verwendung)
=
und |
) ist Teil der Grammatik.
Hinweis:Weitere Informationen zum HIDL-Codestil finden Sie in der Code-Styleguide.
/** */
gibt einen Kommentar in der Dokumentation an. Diese können angewendet werden, nur für Typ-, Methode-, Feld- und ENUM-Wertdeklarationen./* */
gibt einen mehrzeiligen Kommentar an.//
steht für einen Kommentar bis zum Zeilenende. Abgesehen von//
, sind Zeilenumbrüche identisch mit allen anderen Leerzeichen.- In der Beispielgrammatik unten wird der Text aus
//
bis zum Ende des ist kein Bestandteil der Grammatik, sondern ein Kommentar zur Grammatik. [empty]
bedeutet, dass der Begriff leer sein kann.?
nach einem Literal oder Begriff bedeutet, dass es optional ist....
gibt eine Sequenz an, die null oder mehr Elemente mit wie angegeben das Satzzeichen. In HIDL gibt es keine variadischen Argumente.- Kommas trennen Sequenzelemente.
- Semikolons enden jedes Element, auch das letzte.
- GROSSBUCHSTABEN sind kein Terminal.
italics
ist eine Tokenfamilie wieinteger
oderidentifier
(Standard-C Parsing-Regeln).constexpr
ist ein konstanter C-Stilausdruck (z. B.1 + 1
und1L << 3
).import_name
ist der Name eines Pakets oder einer Schnittstelle, qualifiziert wie in HIDL beschrieben Versionsverwaltung.words
in Kleinbuchstaben sind Literaltokens.
Beispiel:
ROOT = PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... } // not for types.hal | PACKAGE IMPORTS ITEM ITEM... // only for types.hal; no method definitions ITEM = ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?; | safe_union identifier { UFIELD; UFIELD; ...}; | struct identifier { SFIELD; SFIELD; ...}; // Note - no forward declarations | union identifier { UFIELD; UFIELD; ...}; | enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... }; // TYPE = enum or scalar | typedef TYPE identifier; VERSION = integer.integer; PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION; PREAMBLE = interface identifier EXTENDS EXTENDS = <empty> | extends import_name // must be interface, not package GENERATES = generates (FIELD, FIELD ...) // allows the Binder interface to be used as a type // (similar to typedef'ing the final identifier) IMPORTS = [empty] | IMPORTS import import_name; TYPE = uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t | float | double | bool | string | identifier // must be defined as a typedef, struct, union, enum or import // including those defined later in the file | memory | pointer | vec<TYPE> | bitfield<TYPE> // TYPE is user-defined enum | fmq_sync<TYPE> | fmq_unsync<TYPE> | TYPE[SIZE] FIELD = TYPE identifier UFIELD = TYPE identifier | safe_union identifier { FIELD; FIELD; ...} identifier; | struct identifier { FIELD; FIELD; ...} identifier; | union identifier { FIELD; FIELD; ...} identifier; SFIELD = TYPE identifier | safe_union identifier { FIELD; FIELD; ...}; | struct identifier { FIELD; FIELD; ...}; | union identifier { FIELD; FIELD; ...}; | safe_union identifier { FIELD; FIELD; ...} identifier; | struct identifier { FIELD; FIELD; ...} identifier; | union identifier { FIELD; FIELD; ...} identifier; SIZE = // Must be greater than zero constexpr ANNOTATIONS = [empty] | ANNOTATIONS ANNOTATION ANNOTATION = | @identifier | @identifier(VALUE) | @identifier(ANNO_ENTRY, ANNO_ENTRY ...) ANNO_ENTRY = identifier=VALUE VALUE = "any text including \" and other escapes" | constexpr | {VALUE, VALUE ...} // only in annotations ENUM_ENTRY = identifier | identifier = constexpr