HIDL setzt voraus, dass jede in HIDL geschriebene Schnittstelle versioniert ist. Nach einem HAL angezeigt wird, ist sie eingefroren und weitere Änderungen an einer neue Version dieser Benutzeroberfläche. Eine veröffentlichte Oberfläche kann geändert wurde, kann er durch eine andere Schnittstelle erweitert werden.
HIDL-Codestruktur
HIDL-Code ist in benutzerdefinierten -Typen, Schnittstellen und Pakete:
- Benutzerdefinierte Typen (User-Defined types, UDFs): HIDL bietet Zugriff auf eine Reihe von primitive Datentypen, die zur Erstellung komplexerer Typen über Strukturen, Vereinigungen und Aufzählungen. UDTs werden an Methoden der Schnittstellen und können auf Paketebene (allgemein für alle oder lokal zu einer Schnittstelle.
- Schnittstellen. Ein Grundbaustein von HIDL ist eine Benutzeroberfläche, besteht aus UDT- und Methodendeklarationen. Schnittstellen können auch von eine andere Schnittstelle.
- Pakete: Organisiert verwandte HIDL-Schnittstellen und die Daten
Typen, für die sie zuständig sind. Ein Paket wird durch einen Namen, eine Version
umfasst Folgendes:
<ph type="x-smartling-placeholder">
- </ph>
- Datentyp-Definitionsdatei mit dem Namen
types.hal
. - Null oder mehr Schnittstellen, jede in einer eigenen
.hal
-Datei.
- Datentyp-Definitionsdatei mit dem Namen
Die Datentypdefinitionsdatei types.hal
enthält nur UDTs (alle
UDTs auf Paketebene werden in einer einzigen Datei gespeichert). Darstellungen im Ziel
Sprache für alle Oberflächen im Paket verfügbar.
Philosophie der Versionsverwaltung
Ein HIDL-Paket (z. B. android.hardware.nfc
), nachdem es
die für eine bestimmte Version (z. B. 1.0
) veröffentlicht wurden, unveränderlich ist. sie
kann nicht geändert werden. Änderungen an den Schnittstellen im Paket oder an anderen
können Änderungen an seinen UDTs nur in einem anderen Paket erfolgen.
In HIDL wird die Versionsverwaltung auf Paketebene angewendet, nicht auf und alle Schnittstellen und UDTs in einem Paket haben dieselbe Version. Paket Versionen folgen semantisch Versionsverwaltung, ohne die Patch- und Build-Metadatenkomponenten zu verwenden. Innerhalb eines eines bestimmten Pakets impliziert ein Bump der Nebenversion die neue Version von Das Paket ist abwärtskompatibel mit dem alten Paket und einer Hauptversion. version bump impliziert, dass die neue Version des Pakets nicht abwärtskompatibel mit dem alten Paket ist.
Konzeptionell kann ein Paket auf mehrere Arten mit einem anderen Paket verknüpft werden:
- Überhaupt nicht.
- Abwärtskompatible Erweiterbarkeit auf Paketebene. Dieses
erfolgt bei neuen Uprevs der Nebenversion (nächste inkrementierte Überarbeitung) eines Pakets;
hat das neue Paket denselben Namen und dieselbe Hauptversion wie das alte Paket, aber ein
höhere Nebenversion. Funktionstechnisch ist das neue Paket eine Obermenge des alten
Paket, was bedeutet:
<ph type="x-smartling-placeholder">
- </ph>
- Oberflächen der obersten Ebene des übergeordneten Pakets sind im neuen Paket vorhanden,
obwohl die Schnittstellen über neue Methoden verfügen, neue Schnittstellen-lokale UDTs (die
wie unten beschrieben) und neue UDTs in
types.hal
- Neue Oberflächen können auch zum neuen Paket hinzugefügt werden.
- Alle Datentypen des übergeordneten Pakets sind im neuen Paket vorhanden und können von den (möglicherweise erneut implementiert) Methoden aus dem alten Paket gehandhabt werden.
- Neue Datentypen können auch zur Verwendung durch neue Methoden vorhandene Schnittstellen oder neue Benutzeroberflächen verwendet werden.
- Oberflächen der obersten Ebene des übergeordneten Pakets sind im neuen Paket vorhanden,
obwohl die Schnittstellen über neue Methoden verfügen, neue Schnittstellen-lokale UDTs (die
wie unten beschrieben) und neue UDTs in
- Abwärtskompatible Erweiterbarkeit auf Schnittstellenebene. Das neue
-Paket kann das ursprüngliche Paket auch erweitern, indem es aus logisch separaten
Schnittstellen, die einfach zusätzliche Funktionen bieten
und nicht die Hauptfunktion.
Zu diesem Zweck könnte Folgendes sinnvoll sein:
<ph type="x-smartling-placeholder">
- </ph>
- Schnittstellen im neuen Paket müssen auf die Datentypen der alten Paket.
- Schnittstellen im neuen Paket können Schnittstellen von einem oder mehreren alten Pakete.
- Die ursprüngliche Abwärtsinkompatibilität verlängern. Dies ist ein Aktualisierungen der Hauptversion des Pakets durchgeführt werden und keine Korrelation zwischen die beiden. Soweit dies vorhanden ist, kann sie mit einer Kombination aus aus der älteren Version des Pakets und die Übernahme einer Teilmenge von alten Paket-Schnittstellen.
Schnittstellenstrukturierung
Für eine gut strukturierte Oberfläche können nicht Teil des ursprünglichen Designs sind, sollte eine Änderung an der HIDL erforderlich sein. . Umgekehrt gilt: Ob Sie eine Änderung auf beiden Seiten des Die Benutzeroberfläche, die neue Funktionen bietet, ohne die Benutzeroberfläche zu ändern ist die Benutzeroberfläche nicht strukturiert.
Treble unterstützt separat kompilierte Anbieter- und Systemkomponenten, bei denen der
vendor.img
auf einem Gerät und das system.img
kann
kompiliert werden. Alle Interaktionen zwischen vendor.img
und
system.img
muss explizit und ausführlich definiert werden,
weiterzubilden. Dies umfasst viele API-Oberflächen, aber
ist der IPC-Mechanismus, den HIDL für die Interprozesskommunikation auf der
Grenze: system.img
/vendor.img
.
Voraussetzungen
Alle über HIDL übergebenen Daten müssen explizit definiert werden. Um sicherzustellen, Implementierung und Client können weiter zusammenarbeiten, auch wenn separat oder unabhängig entwickelt wurden, müssen die Daten Anforderungen:
- Können direkt in HIDL beschrieben werden (mithilfe von Structs enums usw.) mit semantische Namen und ihre Bedeutung.
- Sie können durch einen öffentlichen Standard wie ISO/IEC 7816 beschrieben werden.
- Kann durch einen Hardwarestandard oder ein physisches Layout der Hardware beschrieben werden.
- Bei Bedarf können intransparente Daten wie öffentliche Schlüssel oder IDs sein.
Wenn opake Daten verwendet werden, dürfen sie nur von einer Seite des HIDL gelesen werden
. Wenn zum Beispiel der vendor.img
-Code eine Komponente
system.img
ist eine Stringnachricht oder vec<uint8_t>
Daten enthalten, können diese Daten nicht vom system.img
selbst geparst werden. kann es
nur zur Interpretation an vendor.img
zurückgegeben werden. Wann
Wert von vendor.img
an Anbietercode übergeben auf
system.img
oder auf ein anderes Gerät übertragen werden,
muss genau beschrieben werden und dennoch Teil des
Schnittstelle.
Richtlinien
Sie sollten in der Lage sein, eine Implementierung oder einen Client eines HAL nur mit die .hal-Dateien (Sie sollten sich also nicht die Android-Quelle oder öffentliche Standards). Wir empfehlen, das genaue erforderliche Verhalten anzugeben. Aussagen wie „Eine Implementierung könnte A oder B tun“, Implementierungen dazu anzuregen, die mit den Auftraggebenden verflochten sind, mit denen sie entwickelt werden.
HIDL-Codelayout
HIDL umfasst Kern- und Anbieterpakete.
Die wichtigsten HIDL-Schnittstellen werden von Google angegeben. Pakete, zu denen sie gehören
mit android.hardware.
beginnen und nach Subsystem benannt sind,
möglicherweise mit verschachtelten
Benennungsebenen. Das NFC-Paket trägt beispielsweise
android.hardware.nfc
und das Kamerapaket sind
android.hardware.camera
. Im Allgemeinen hat ein Kernpaket
android.hardware.
[name1
].[name2
]...
HIDL-Pakete haben neben ihrem Namen auch eine Version. Zum Beispiel enthält das Paket
android.hardware.camera
ist möglicherweise Version 3.4
. das ist
da die Version eines Pakets seine Platzierung in der Quellstruktur beeinflusst.
Alle Kernpakete befinden sich unter hardware/interfaces/
in der
zu erstellen. Das Paket
android.hardware.
[name1
].[name2
]...
in Version $m.$n
ist unter
hardware/interfaces/name1/name2/
.../$m.$n/
; Paket
android.hardware.camera
-Version 3.4
befindet sich im Verzeichnis
hardware/interfaces/camera/3.4/.
Eine hartcodierte Zuordnung ist vorhanden.
zwischen dem Paketpräfix android.hardware.
und dem Pfad
hardware/interfaces/
Nicht-Core-Pakete (Anbieter) werden vom SoC-Anbieter oder ODM erstellt. Die
Präfix für Nicht-Kernpakete ist vendor.$(VENDOR).hardware.
, wobei
$(VENDOR)
bezieht sich auf einen SoC-Anbieter oder OEM/ODM. Dies entspricht dem Pfad
vendor/$(VENDOR)/interfaces
in der Baumstruktur (diese Zuordnung ist auch
hartcodiert).
Voll qualifizierte Namen von benutzerdefinierten Typen
In HIDL hat jede UDT einen voll qualifizierten Namen, der aus dem UDT-Namen,
den Namen des Pakets, in dem die UDT definiert ist, und die Paketversion. Die
voll qualifizierter Name wird nur verwendet, wenn Instanzen des Typs deklariert sind und
und nicht dort, wo der Typ selbst definiert ist. Angenommen, ein Paket
android.hardware.nfc,
Version 1.0
definiert eine Struktur
mit dem Namen NfcData
. Auf der Website der Erklärung (ob in
types.hal
oder in der Deklaration einer Benutzeroberfläche) enthalten ist), die Deklaration.
lautet einfach:
struct NfcData { vec<uint8_t> data; };
Bei der Deklaration einer Instanz dieses Typs (innerhalb einer Datenstruktur oder als Methodenparameter) verwenden, verwenden Sie den voll qualifizierten Typnamen:
android.hardware.nfc@1.0::NfcData
Die allgemeine Syntax lautet
PACKAGE@VERSION::UDT
. Dabei gilt:
PACKAGE
ist der durch Punkte getrennte Name eines HIDL-Pakets. (z.B.android.hardware.nfc
.VERSION
ist die durch Punkte getrennte Hauptversion. Format des Pakets (z.B.1.0
.UDT
ist der durch Punkte getrennte Name einer HIDL UDT. Da HIDL verschachtelte UDTs unterstützt und HIDL-Schnittstellen UDTs (eine Art von verschachtelte Deklaration) werden Punkte verwendet, um auf die Namen zuzugreifen.
Wenn beispielsweise die folgende verschachtelte Deklaration im allgemeinen
Typendatei in Version des Pakets android.hardware.example
1.0
:
// types.hal package android.hardware.example@1.0; struct Foo { struct Bar { // … }; Bar cheers; };
Der voll qualifizierte Name für Bar
lautet
android.hardware.example@1.0::Foo.Bar
. Wenn Sie nicht nur in
im obigen Paket befanden sich die verschachtelte Deklaration in einer Schnittstelle namens
IQuux
:
// IQuux.hal package android.hardware.example@1.0; interface IQuux { struct Foo { struct Bar { // … }; Bar cheers; }; doSomething(Foo f) generates (Foo.Bar fb); };
Der voll qualifizierte Name für Bar
lautet
android.hardware.example@1.0::IQuux.Foo.Bar
.
In beiden Fällen kann Bar
nur als Bar
bezeichnet werden
im Geltungsbereich der Erklärung von Foo
liegen. Am Paket oder
Oberflächenebene müssen Sie über Foo
auf Bar
verweisen:
Foo.Bar
, wie in der Deklaration der Methode doSomething
oben. Alternativ können Sie die Methode ausführlicher wie folgt deklarieren:
// IQuux.hal doSomething(android.hardware.example@1.0::IQuux.Foo f) generates (android.hardware.example@1.0::IQuux.Foo.Bar fb);
Voll qualifizierte Aufzählungswerte
Wenn es sich bei einer UDT um einen Enum-Typ handelt, hat jeder Wert des enum-Typs eine
vollständig qualifizierter Name, der mit dem voll qualifizierten Namen des enum-Typs beginnt,
gefolgt von einem Doppelpunkt und dem Namen des enum-Werts. Beispiel:
von Paket android.hardware.nfc,
Version 1.0
ausgehen
definiert einen Enum-Typ NfcStatus
:
enum NfcStatus { STATUS_OK, STATUS_FAILED };
Wenn auf STATUS_OK
verwiesen wird, lautet der vollständig qualifizierte Name:
android.hardware.nfc@1.0::NfcStatus:STATUS_OK
Die allgemeine Syntax lautet
PACKAGE@VERSION::UDT:VALUE
,
Dabei gilt:
PACKAGE@VERSION::UDT
ist der/die/das genau denselben vollständig qualifizierten Namen für den Enum-Typ.VALUE
ist der Name des Werts.
Regeln für die automatische Inferenz
Ein voll qualifizierter UDT-Name muss nicht angegeben werden. Ein UDT-Name kann Lassen Sie Folgendes weg:
- Das Paket, z.B.
@1.0::IFoo.Type
- Sowohl Paket als auch Version, z.B.
IFoo.Type
HIDL versucht, den Namen mithilfe von Regeln für automatische Interferenzen zu vervollständigen (untere Regel Zahl bedeutet höhere Priorität).
Regel 1
Wenn kein Paket und keine Version angegeben werden, wird eine lokale Namenssuche durchgeführt. Beispiel:
interface Nfc { typedef string NfcErrorMessage; send(NfcData d) generates (@1.0::NfcStatus s, NfcErrorMessage m); };
NfcErrorMessage
wurde lokal gesucht und typedef
darüber gefunden wird. NfcData
wurde auch lokal gesucht, aber da es derzeit ist
nicht lokal definiert ist, werden Regel 2 und 3 angewendet. @1.0::NfcStatus
stellt eine Version bereit, sodass Regel 1 nicht zutrifft.
Regel 2
Wenn Regel 1 fehlschlägt und eine Komponente des voll qualifizierten Namens fehlt
(Paket, Version oder Paket und Version) enthält, wird die Komponente automatisch
aus dem aktuellen Paket. Der HIDL-Compiler sucht dann im
der aktuellen Datei (und aller Importe), um den automatisch ausgefüllten, voll qualifizierten Namen zu finden.
Nehmen wir für das obige Beispiel die Deklaration ExtendedNfcData
an.
wurde im selben Paket (android.hardware.nfc
) zur selben Zeit
Version (1.0
) als NfcData
:
struct ExtendedNfcData { NfcData base; // … additional members };
Der HIDL-Compiler füllt den Paketnamen und Versionsnamen aus der
Aktuelles Paket zum Erstellen des voll qualifizierten UDT-Namens
android.hardware.nfc@1.0::NfcData
Da der Name bereits im
(vorausgesetzt, es wurde ordnungsgemäß importiert), wird es für den
Erklärung.
Ein Name im aktuellen Paket wird nur importiert, wenn einer der folgenden Punkte zutrifft: true:
- Sie wird explizit mit einer
import
-Anweisung importiert. - Sie ist im aktuellen Paket in
types.hal
definiert.
Dies gilt auch, wenn NfcData
nur durch
Die Versionsnummer:
struct ExtendedNfcData { // autofill the current package name (android.hardware.nfc) @1.0::NfcData base; // … additional members };
Regel 3
Wenn Regel 2 keine Übereinstimmung erzeugt (die UDT ist nicht in der aktuellen
-Paket), sucht der HIDL-Compiler in allen importierten Paketen nach einer Übereinstimmung.
Im obigen Beispiel wird davon ausgegangen, dass ExtendedNfcData
deklariert ist in
Version 1.1
des Pakets android.hardware.nfc
,
1.1
importiert 1.0
wie vorgesehen (siehe
Erweiterungen auf Paketebene) und die Definition
gibt nur den UDT-Namen an:
struct ExtendedNfcData { NfcData base; // … additional members };
Der Compiler sucht nach jeder UDT mit dem Namen NfcData
und findet eine in
android.hardware.nfc
mit Version 1.0
, was zu einer
voll qualifizierte UDT von android.hardware.nfc@1.0::NfcData
. Wenn mehr
als eine Übereinstimmung für eine bestimmte teilweise qualifizierte UDT, den HIDL-Compiler, gefunden wird.
wird ein Fehler ausgegeben.
Beispiel
Bei Verwendung von Regel 2 wird ein im aktuellen Paket definierter importierter Typ bevorzugt einem importierten Typ aus einem anderen Paket:
// hardware/interfaces/foo/1.0/types.hal package android.hardware.foo@1.0; struct S {}; // hardware/interfaces/foo/1.0/IFooCallback.hal package android.hardware.foo@1.0; interface IFooCallback {}; // hardware/interfaces/bar/1.0/types.hal package android.hardware.bar@1.0; typedef string S; // hardware/interfaces/bar/1.0/IFooCallback.hal package android.hardware.bar@1.0; interface IFooCallback {}; // hardware/interfaces/bar/1.0/IBar.hal package android.hardware.bar@1.0; import android.hardware.foo@1.0; interface IBar { baz1(S s); // android.hardware.bar@1.0::S baz2(IFooCallback s); // android.hardware.foo@1.0::IFooCallback };
S
wird so interpoliert:android.hardware.bar@1.0::S
und wird gefunden inbar/1.0/types.hal
(weiltypes.hal
automatisch importiert).IFooCallback
wird so interpoliert:android.hardware.bar@1.0::IFooCallback
mithilfe von Regel 2, wurde nicht gefunden, dabar/1.0/IFooCallback.hal
nicht importiert wurde automatisch (so wietypes.hal
). Somit wird sie durch Regel 3 in Stattdessenandroid.hardware.foo@1.0::IFooCallback
, das importiert wird überimport android.hardware.foo@1.0;
).
Typen.hal
Jedes HIDL-Paket enthält eine types.hal
-Datei mit UDTs.
die von allen Benutzeroberflächen gemeinsam genutzt werden,
die zu diesem Paket gehören. HIDL-Typen
immer öffentlich sind; unabhängig davon, ob in den Dateien
types.hal
oder in einer Schnittstellendeklaration sind diese Typen
die außerhalb des Bereichs zugänglich sind,
in dem sie definiert sind. types.hal
ist nicht dazu gedacht, die öffentliche API eines Pakets zu beschreiben, sondern vielmehr zum Hosten von UDTs.
von allen Schnittstellen innerhalb des Pakets verwendet. Aufgrund der Beschaffenheit von HIDL werden alle UDTs
sind Teil der Benutzeroberfläche.
types.hal
besteht aus UDTs und import
-Anweisungen.
Da types.hal
für jede Schnittstelle des
Paket (Es handelt sich um einen impliziten Import), sind diese import
-Anweisungen
auf Paketebene festlegen. UDTs in types.hal
können auch
Auf diese Weise importierte UDTs und Schnittstellen.
Für ein IFoo.hal
-Objekt beispielsweise:
package android.hardware.foo@1.0; // whole package import import android.hardware.bar@1.0; // types only import import android.hardware.baz@1.0::types; // partial imports import android.hardware.qux@1.0::IQux.Quux; // partial imports import android.hardware.quuz@1.0::Quuz;
Folgendes wird importiert:
android.hidl.base@1.0::IBase
(implizit)android.hardware.foo@1.0::types
(implizit)- Alle Inhalte in
android.hardware.bar@1.0
(einschließlich aller und seinetypes.hal
) types.hal
vonandroid.hardware.baz@1.0::types
(Schnittstellen inandroid.hardware.baz@1.0
werden nicht importiert)IQux.hal
undtypes.hal
vonandroid.hardware.qux@1.0
Quuz
vonandroid.hardware.quuz@1.0
(vorausgesetzt,Quuz
ist intypes.hal
definiert, der gesamtetypes.hal
Datei wurde geparst, aber andere Typen alsQuuz
werden nicht importiert).
Versionsverwaltung auf Benutzeroberfläche
Jede Schnittstelle innerhalb eines Pakets befindet sich in einer eigenen Datei. Das Paket
wird im oberen Bereich der Schnittstelle mit der Methode
package
-Anweisung. Nach der Paketdeklaration sind null oder mehr
Möglicherweise sind Importe auf Schnittstellenebene (teilweise oder ganzes Paket) aufgeführt. Beispiel:
package android.hardware.nfc@1.0;
In HIDL können Schnittstellen mithilfe der
extends
Keyword. Damit eine Schnittstelle eine andere Schnittstelle erweitert,
muss über eine import
-Anweisung Zugriff darauf haben. Der Name des
Erweiterung der Schnittstelle (Basisschnittstelle) folgt den Regeln für den Typnamen
die oben erläuterten Voraussetzungen erfüllt. Eine Schnittstelle kann nur von einer Schnittstelle übernehmen.
HIDL unterstützt keine mehrfache Vererbung.
In den folgenden Beispielen für die Uprev-Versionsverwaltung wird das folgende Paket verwendet:
// types.hal package android.hardware.example@1.0 struct Foo { struct Bar { vec<uint32_t> val; }; }; // IQuux.hal package android.hardware.example@1.0 interface IQuux { fromFooToBar(Foo f) generates (Foo.Bar b); }
Uprev-Regeln
Um ein Paket package@major.minor
zu definieren, entweder A oder alle B
muss wahr sein:
Regel A | "Ist eine Start-Nebenversion": alle früheren Nebenversionen,
package@major.0 , package@major.1 , ...,
package@major.(minor-1) darf nicht definiert sein.
|
---|
Regel B | Alle folgenden Aussagen treffen zu:
|
---|
Aufgrund von Regel A gilt:
- Das Paket kann mit einer beliebigen Nebenversionsnummer beginnen (z. B.
android.hardware.biometrics.fingerprint
beginnt um@2.1
) - Die Anforderung „
android.hardware.foo@1.0
ist nicht definiert“ bedeutet Das Verzeichnishardware/interfaces/foo/1.0
sollte noch gar nicht vorhanden sein.
Regel A wirkt sich jedoch nicht auf ein Paket aus, das denselben Paketnamen,
eine andere Hauptversion hat, z. B.
android.hardware.camera.device
enthält sowohl @1.0
als auch
@3.2
definiert; @3.2
muss nicht mit
@1.0
. Daher kann @3.2::IExtFoo
das Volumen
@1.0::IFoo
Falls der Paketname abweicht,
package@major.minor::IBar
kann von einer Schnittstelle mit einem
einen anderen Namen haben (z. B. kann android.hardware.bar@1.0::IBar
erweitern android.hardware.baz@2.2::IBaz
). Wenn eine Schnittstelle nicht
explizit mit dem Keyword extend
einen Super-Typ deklarieren,
gilt für android.hidl.base@1.0::IBase
(außer IBase
)
B.2 und B.3 müssen gleichzeitig befolgt werden. Selbst wenn beispielsweise
android.hardware.foo@1.1::IFoo
erweitert
android.hardware.foo@1.0::IFoo
, um Regel B.2 zu bestehen, wenn eine
android.hardware.foo@1.1::IExtBar
verlängert
android.hardware.foo@1.0::IBar
, dies ist immer noch keine gültige Steigerung.
Uprev-Schnittstellen
Um android.hardware.example@1.0
(wie oben definiert) zu erhöhen auf
@1.1
:
// types.hal package android.hardware.example@1.1; import android.hardware.example@1.0; // IQuux.hal package android.hardware.example@1.1 interface IQuux extends @1.0::IQuux { fromBarToFoo(Foo.Bar b) generates (Foo f); }
Dies ist eine import
auf Paketebene der Version 1.0
von
„android.hardware.example
“ in types.hal
. Obwohl keine neuen
UDTs werden in Version 1.1
des Pakets hinzugefügt, Verweise auf UDTs in
Version 1.0
wird noch benötigt, daher der Import auf Paketebene
in types.hal
. (Derselbe Effekt hätte auch mit einem
Import auf Schnittstellenebene in IQuux.hal
.)
In extends @1.0::IQuux
in der Deklaration von
IQuux
haben wir die Version von IQuux
angegeben,
übernommen (Definition ist erforderlich, da IQuux
für Folgendes verwendet wird:
eine Schnittstelle deklarieren und von einer Schnittstelle übernehmen). Da Deklarationen
einfach Namen, die alle Paket- und Versionsattribute auf der Website des
-Deklaration im Namen der Basisschnittstelle. wir
Es hätte auch die voll qualifizierte UDT nutzen können,
redundant.
Die neue Schnittstelle IQuux
deklariert die Methode nicht noch einmal
fromFooToBar()
wird von @1.0::IQuux
übernommen. es einfach
listet die neue Methode auf, die hinzugefügt wird fromBarToFoo()
. In HIDL übernommen
können in den untergeordneten Oberflächen nicht erneut deklariert werden.
Die IQuux
-Schnittstelle kann die fromFooToBar()
nicht deklarieren
explizit auf.
Uprev-Konventionen
Manchmal müssen Schnittstellennamen die erweiternde Schnittstelle umbenennen. Wir empfehlen, dass Enum-Erweiterungen, Structs und Unions denselben Namen haben wie die, die sie erweitern. es sei denn, sie unterscheiden sich so stark, dass ein neuer Name gerechtfertigt ist. Beispiele:
// in parent hal file enum Brightness : uint32_t { NONE, WHITE }; // in child hal file extending the existing set with additional similar values enum Brightness : @1.0::Brightness { AUTOMATIC }; // extending the existing set with values that require a new, more descriptive name: enum Color : @1.0::Brightness { HW_GREEN, RAINBOW };
Wenn eine Methode einen neuen semantischen Namen haben kann (z. B.
fooWithLocation
) ist das bevorzugt. Andernfalls sollte es
einen ähnlichen Namen wie die Erweiterung hat. Die Methode
foo_1_1
in @1.1::IFoo
kann die Funktion ersetzen
der foo
-Methode in @1.0::IFoo
, wenn es keine bessere
Alternativname.
Versionsverwaltung auf Paketebene
Die HIDL-Versionsverwaltung erfolgt auf Paketebene. nachdem ein Paket veröffentlicht wurde, ist unveränderlich (seine Gruppe von Schnittstellen und UDTs kann nicht geändert werden). Pakete können beziehen sich in vielerlei Hinsicht aufeinander. All dies lässt sich über ein Kombination aus Vererbung auf Schnittstellenebene und Erstellen von UDTs durch Zusammensetzung.
Eine Art von Beziehung ist jedoch genau definiert und muss erzwungen werden: Abwärtskompatible Übernahme auf Paketebene: In diesem Szenario parent-Paket ist das Paket, von dem übernommen wird, und das child-Paket erweitert das übergeordnete Paket. Paketebene Für abwärtskompatible Übernahmeregeln gelten folgende Regeln:
- Alle Oberflächen der obersten Ebene des übergeordneten Pakets werden von Schnittstellen im Child-Paket.
- Neue Benutzeroberflächen können auch zum neuen Paket hinzugefügt werden (keine Einschränkungen hinsichtlich Beziehungen zu anderen Schnittstellen in anderen Paketen).
- Neue Datentypen können auch zur Verwendung durch neue Methoden vorhandene Schnittstellen oder neue Benutzeroberflächen verwendet werden.
Diese Regeln können mithilfe von HIDL-Schnittstellenvererbung und UDT implementiert werden. Komposition, erfordert aber Kenntnisse auf Metaebene, um diese Zusammenhänge zu verstehen eine abwärtskompatible Paketerweiterung darstellen. Dieses Wissen basiert auf wie folgt:
Wenn ein Paket diese Anforderung erfüllt, erzwingt hidl-gen
Abwärtskompatibilitätsregeln.