HIDL

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 Clientprozess, 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 Modus von HIDL, 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 bei der Arbeitsspeicherinhaberschaft, unter Verwendung von in-Parametern für RPC (siehe Android 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.

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, dlopened. 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 Funktion IFoo* HIDL_FETCH_IFoo(const char* name) bereit. An alten Geräten ist, ist dieses Paket dlopenbeinhaltet und die Implementierung ist mit HIDL_FETCH_IFoo instanziiert werden. Sie können den Basiscode generieren mit hidl-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 wie integer oder identifier (Standard-C Parsing-Regeln).
  • constexpr ist ein konstanter C-Stilausdruck (z. B. 1 + 1 und 1L << 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