Der HIDL-Codestil ähnelt dem C++-Code im Android-Framework. Er hat vier Leerzeichen Einzüge und Dateinamen mit Groß- und Kleinschreibung. Paketdeklarationen, Importe und Docstrings ähneln denen in Java, mit geringfügigen Änderungen.
Die folgenden Beispiele für IFoo.hal
und types.hal
HIDL-Code-Stile veranschaulichen und Quick Links zu Details zu jedem Stil bereitstellen
(IFooClientCallback.hal
, IBar.hal
und
IBaz.hal
wurden ausgelassen.
hardware/interfaces/foo/1.0/IFoo.hal |
---|
/* * (License Notice) */ package android.hardware.foo@1.0; import android.hardware.bar@1.0::IBar; import IBaz; import IFooClientCallback; /** * IFoo is an interface that… */ interface IFoo { /** * This is a multiline docstring. * * @return result 0 if successful, nonzero otherwise. */ foo() generates (FooStatus result); /** * Restart controller by power cycle. * * @param bar callback interface that… * @return result 0 if successful, nonzero otherwise. */ powerCycle(IBar bar) generates (FooStatus result); /** Single line docstring. */ baz(); /** * The bar function. * * @param clientCallback callback after function is called * @param baz related baz object * @param data input data blob */ bar(IFooClientCallback clientCallback, IBaz baz, FooData data); }; |
hardware/interfaces/foo/1.0/types.hal |
---|
/* * (License Notice) */ package android.hardware.foo@1.0; /** Replied status. */ enum Status : int32_t { OK, /* invalid arguments */ ERR_ARG, /* note, no transport related errors */ ERR_UNKNOWN = -1, }; struct ArgData { int32_t[20] someArray; vec<uint8_t> data; }; |
Namenskonventionen
Funktions-, Variablen- und Dateinamen sollten beschreibend sein. vermeiden
zu viele Abkürzungen. Akronyme wie Wörter behandeln (z. B. INfc
verwenden)
von INFC
).
Verzeichnisstruktur und Dateibenennung
Die Verzeichnisstruktur sollte wie folgt aussehen:
ROOT-DIRECTORY
MODULE
SUBMODULE
(optional, mehr als eins möglich) Level) <ph type="x-smartling-placeholder">- </ph>
VERSION
Android.mk
IINTERFACE_1.hal
IINTERFACE_2.hal
…
IINTERFACE_N.hal
types.hal
(optional)
Dabei gilt:
ROOT-DIRECTORY
ist: <ph type="x-smartling-placeholder">- </ph>
hardware/interfaces
für HIDL-Kernpakete.vendor/VENDOR/interfaces
für Anbieterpakete, Dabei bezieht sichVENDOR
auf einen SoC-Anbieter oder einen OEM/ODM
MODULE
muss ein kleingeschriebenes Wort sein, das folgendes beschreibt: des Subsystems (z. B.nfc
). Wenn mehr als ein Wort erforderlich ist, verwenden Sie verschachtelteSUBMODULE
. Es können mehrere Ebenen von Verschachtelung.VERSION
sollte genau die gleiche Version sein (major.minor) wie unter Versionen beschrieben.IINTERFACE_X
sollte der Name der Schnittstelle mitUpperCamelCase
/PascalCase
(z. B.INfc
) enthalten, wie unter Schnittstellennamen beschrieben.
Beispiel:
hardware/interfaces
nfc
1.0
Android.mk
INfc.hal
INfcClientCallback.hal
types.hal
Hinweis:Alle Dateien müssen nicht ausführbare Dateien haben. Berechtigungen (in Git).
Paketnamen
Paketnamen müssen den folgenden vollständig qualifizierten Namen verwenden:
(FQN) (bezeichnet als PACKAGE-NAME
):
PACKAGE.MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION
Dabei gilt:
PACKAGE
ist das Paket, das derROOT-DIRECTORY
. InsbesonderePACKAGE
ist: <ph type="x-smartling-placeholder">- </ph>
android.hardware
für Kern-HIDL-Pakete (Zuordnung zuhardware/interfaces
).vendor.VENDOR.hardware
für Anbieterpakete, wobeiVENDOR
bezieht sich auf einen SoC-Anbieter oder einen OEM/ODM (Zuordnungs- anvendor/VENDOR/interfaces
).
MODULE[.SUBMODULE[.SUBMODULE[…]]]@VERSION
Ordnernamen in der unter Verzeichnisstruktur.- Paketnamen sollten in Kleinbuchstaben geschrieben werden. Wenn sie aus mehr als einem Wort bestehen,
Wörter sollten entweder als untergeordnete Module verwendet oder in
snake_case
geschrieben werden. - Leerzeichen sind nicht zulässig.
Die FQN wird immer in Paketdeklarationen verwendet.
Versionen
Versionen sollten das folgende Format haben:
MAJOR.MINOR
Sowohl die Version MAJOR als auch die Version MINOR sollten eine einzelne Version sein. Integer HIDL verwendet semantische Versionsverwaltungsregeln.
Importe
Importe haben eines der folgenden drei Formate:
- Gesamtpaketimporte:
import PACKAGE-NAME;
- Teilimporte:
import PACKAGE-NAME::UDT;
(oder, wenn die importierten Typ befindet sich im selben Paket,import UDT;
- Nur-Typen-Importe:
import PACKAGE-NAME::types;
PACKAGE-NAME
hat folgendes Format:
Paketnamen: Das aktuelle Paket
types.hal
(falls vorhanden) wird automatisch importiert (nicht importieren)
explizit).
Voll qualifizierte Namen (Fully Qualified Names, FQNs)
Verwenden Sie für einen Import benutzerdefinierter Typen nur dann voll qualifizierte Namen, wenn dies erforderlich ist.
Lassen Sie PACKAGE-NAME
aus, wenn der Importtyp im selben
Paket. Eine Voll qualifizierter Name (FQN) darf keine Leerzeichen enthalten. Beispiel für einen voll qualifizierten Namen:
android.hardware.nfc@1.0::INfcClientCallback
In einer anderen Datei unter android.hardware.nfc@1.0
finden Sie weitere Informationen im
oben als INfcClientCallback
angezeigt. Andernfalls verwenden Sie nur das Feld
vollständig qualifizierter Name.
Importe gruppieren und sortieren
Fügen Sie nach der Paketdeklaration (vor den Importen) eine leere Zeile ein. Jeder Import sollte eine einzelne Zeile belegen und nicht eingerückt sein. Gruppenimporte in der folgende Reihenfolge:
- Andere
android.hardware
-Pakete (voll qualifizierte Namen verwenden) - Andere
vendor.VENDOR
-Pakete (vollständig qualifiziertes Paket verwenden) Namen).- Bei jedem Anbieter sollte es sich um eine Gruppe handeln.
- Sortieren Sie die Anbieter alphabetisch.
- Importiert aus anderen Schnittstellen im selben Paket (einfache Namen verwenden).
Verwenden Sie eine leere Zeile zwischen Gruppen. Importe in jeder Gruppe sortieren alphabetisch sortiert. Beispiel:
import android.hardware.nfc@1.0::INfc; import android.hardware.nfc@1.0::INfcClientCallback; /* Importing the whole module. */ import vendor.barvendor.bar@3.1; import vendor.foovendor.foo@2.2::IFooBar; import vendor.foovendor.foo@2.2::IFooFoo; import IBar; import IFoo;
Schnittstellennamen
Schnittstellennamen müssen mit einem I
beginnen, gefolgt von einem
UpperCamelCase
/PascalCase
Name. Eine Schnittstelle mit Namen
IFoo
muss in der Datei IFoo.hal
definiert sein. Diese Datei
kann nur Definitionen für die IFoo
-Schnittstelle (die Schnittstelle) enthalten.
INAME
sollte in INAME.hal
sein.
Funktionen
Für Funktionsnamen, Argumente und Rückgabevariablennamen verwenden Sie
lowerCamelCase
Beispiel:
open(INfcClientCallback clientCallback) generates (int32_t retVal); oneway pingAlive(IFooCallback cb);
Namen von Struct- und Union-Feldern
Verwenden Sie für Struct- oder Union-Feldnamen lowerCamelCase
. Beispiel:
struct FooReply { vec<uint8_t> replyData; }
Typnamen
Typnamen beziehen sich auf Struktur- oder Union-Definitionen, Enum-Typdefinitionen
typedef
Sek. Verwenden Sie für diese Namen
UpperCamelCase
/PascalCase
. Beispiele:
enum NfcStatus : int32_t { /*...*/ }; struct NfcData { /*...*/ };
Enum-Werte
Enum-Werte sollten UPPER_CASE_WITH_UNDERSCORES
sein. Beim Bestehen
enum-Werte als Funktionsargumente zu ermitteln und als Funktionsrückgaben zurückzugeben,
den tatsächlichen enum-Typ (nicht den zugrunde liegenden Ganzzahltyp) Beispiel:
enum NfcStatus : int32_t { HAL_NFC_STATUS_OK = 0, HAL_NFC_STATUS_FAILED = 1, HAL_NFC_STATUS_ERR_TRANSPORT = 2, HAL_NFC_STATUS_ERR_CMD_TIMEOUT = 3, HAL_NFC_STATUS_REFUSED = 4 };
Hinweis:Der einem Enum-Typ zugrunde liegende Typ ist explizit nach dem Doppelpunkt angegeben wird. Da die Anwendung nicht Compiler-abhängig ist, verwenden Sie ist der tatsächliche enum-Typ klarer.
Für voll qualifizierte Namen für enum-Werte wird ein Doppelpunkt verwendet. zwischen dem Namen des Enum-Typs und dem Namen des enum-Werts:
PACKAGE-NAME::UDT[.UDT[.UDT[…]]:ENUM_VALUE_NAME
Vollständig qualifizierte Namen dürfen keine Leerzeichen enthalten. Verwenden Sie eine voll qualifizierte und lassen Sie unnötige Teile weg. Beispiel:
android.hardware.foo@1.0::IFoo.IFooInternal.FooEnum:ENUM_OK
Kommentare
Für einen einzeiligen Kommentar: //
, /* */
und /** */
sind in Ordnung.
// This is a single line comment /* This is also single line comment */ /** This is documentation comment */
-
/* */
für Kommentare verwenden. HIDL unterstützt zwar//
für Kommentare, da sie in der generierten Ausgabe nicht enthalten sind. - Verwenden Sie
/** */
für die generierte Dokumentation. Diese können angewendet werden, nur für Typ-, Methode-, Feld- und ENUM-Wertdeklarationen. Beispiel:/** Replied status */ enum TeleportStatus { /** Object entirely teleported. */ OK = 0, /** Methods return this if teleportation is not completed. */ ERROR_TELEPORT = 1, /** * Teleportation could not be completed due to an object * obstructing the path. */ ERROR_OBJECT = 2, ... }
- Beginnen Sie mehrzeilige Kommentare mit
/**
in einer separaten Zeile. Verwende*
am Anfang jeder Zeile. Schließen Sie den Kommentar mit*/
in einer separaten Zeile ab und richten Sie dabei die Sternchen aus. Beispiel:/** * My multi-line * comment */
- Im Lizenzierungshinweis und in Änderungsprotokollen sollte eine neue Zeile mit „
/*
“ beginnen (ein einzelnes Sternchen), verwenden Sie*
am Anfang jeder Zeile und setzen Sie*/
in der letzten Zeile für sich alleine (Sternchen sollten übereinstimmen). Beispiel:/* * Copyright (C) 2017 The Android Open Source Project * ... */ /* * Changelog: * ... */
Dateikommentare
Beginnen Sie jede Datei mit dem entsprechenden Lizenzhinweis. Für Kern-HALs
die AOSP Apache-Lizenz in
development/docs/copyright-templates/c.txt
Vergiss nicht, das Jahr zu aktualisieren und mehrzeilige /* */
Kommentare im Stil von mehrzeiligen Kommentaren zu verwenden.
wie oben beschrieben.
Optional kannst du nach dem Lizenzhinweis eine leere Zeile einfügen, gefolgt von
Änderungsprotokoll/Versionierungsinformationen. /* */
-Stil verwenden
mehrzeiligen Kommentaren wie oben erläutert, platzieren Sie die leere Zeile nach dem
und folge dann der Paketdeklaration.
TODO-Kommentare
TODOs sollten den String TODO
in Großbuchstaben enthalten, gefolgt von einem
Doppelpunkt. Beispiel:
// TODO: remove this code before foo is checked in.
TODO-Kommentare sind nur während der Entwicklung erlaubt. sie müssen nicht in veröffentlichten Benutzeroberflächen vorhanden.
Kommentare zur Benutzeroberfläche und zu Funktionen (Docstrings)
Verwenden Sie /** */
für mehrzeilige und einzeilige Dokumentstrings. Nicht verwenden
//
für docstrings.
In Docstrings für Schnittstellen sollten allgemeine Mechanismen der Benutzeroberfläche, Designgrundsätze, Zweck usw. Docstrings für Funktionen sollten speziell für die Funktion (Dokumentation auf Paketebene befindet sich in einer README-Datei in Paketverzeichnis).
/** * IFooController is the controller for foos. */ interface IFooController { /** * Opens the controller. * * @return status HAL_FOO_OK if successful. */ open() generates (FooStatus status); /** Close the controller. */ close(); };
Du musst jeweils @param
- und @return
-Werte hinzufügen.
Parameter/Rückgabewert:
- Für jeden Parameter muss
@param
hinzugefügt werden. Es sollte gefolgt vom Namen des Parameters und dann dem docstring. - Für jeden Rückgabewert muss
@return
hinzugefügt werden. Es muss der Name des Rückgabewerts und dann der docstring folgen.
Beispiel:
/** * Explain what foo does. * * @param arg1 explain what arg1 is * @param arg2 explain what arg2 is * @return ret1 explain what ret1 is * @return ret2 explain what ret2 is */ foo(T arg1, T arg2) generates (S ret1, S ret2);
Regeln formatieren
Zu den allgemeinen Formatierungsregeln gehören:
- Zeilenlänge: Jede Textzeile sollte höchstens 100 Spalten lang.
- Leerräume: Keine Leerzeichen am Ende der Zeilen Leere Zeilen darf keine Leerzeichen enthalten.
- Gruppenbereiche und Tabs im Vergleich Verwenden Sie nur Leerzeichen.
- Einzugsgröße: Verwenden Sie 4 Leerzeichen für Blöcke und 8 Leerzeichen für Zeilenumbruch
- Verband: Mit Ausnahme von Anmerkungen
Werte steht, steht eine offene geschweifte Klammer in dieselbe Zeile wie die vorherige
sondern mit einer schließenden geschweiften Klammer und dem folgenden Semikolon
die gesamte Linie. Beispiel:
interface INfc { close(); };
Paketdeklaration
Die Paketdeklaration muss sich nach der Lizenz oben in der Datei befinden die gesamte Zeile einnehmen und nicht eingerückt werden darf. Pakete sind im folgenden Format deklariert (Informationen zur Namensformatierung siehe Paketnamen):
package PACKAGE-NAME;
Beispiel:
package android.hardware.nfc@1.0;
Funktionsdeklarationen
Funktionsname, Parameter, generates
und Rückgabewerte sollten
auf derselben Linie stehen,
wenn sie passen. Beispiel:
interface IFoo { /** ... */ easyMethod(int32_t data) generates (int32_t result); };
Wenn sie nicht in dieselbe Zeile passen, versuchen Sie, Parameter einzufügen und
derselben Einrückung gegliedert sind und generate
voneinander abgrenzen,
können die Lesenden die Parameter
und Rückgabewerte schnell sehen. Beispiel:
interface IFoo { suchALongMethodThatCannotFitInOneLine(int32_t theFirstVeryLongParameter, int32_t anotherVeryLongParameter); anEvenLongerMethodThatCannotFitInOneLine(int32_t theFirstLongParameter, int32_t anotherVeryLongParameter) generates (int32_t theFirstReturnValue, int32_t anotherReturnValue); superSuperSuperSuperSuperSuperSuperLongMethodThatYouWillHateToType( int32_t theFirstVeryLongParameter, // 8 spaces int32_t anotherVeryLongParameter ) generates ( int32_t theFirstReturnValue, int32_t anotherReturnValue ); /* method name is even shorter than 'generates' */ foobar(AReallyReallyLongType aReallyReallyLongParameter, AReallyReallyLongType anotherReallyReallyLongParameter) generates (ASuperLongType aSuperLongReturnValue, // 4 spaces ASuperLongType anotherSuperLongReturnValue); }
Weitere Informationen:
- Eine offene Klammer steht immer in derselben Zeile wie der Funktionsname.
- Keine Leerzeichen zwischen dem Funktionsnamen und der öffnenden Klammer.
- Keine Leerzeichen zwischen Klammern und Parametern, es sei denn, sind Zeilenumbrüche dazwischen.
- Wenn sich
generates
in derselben Zeile wie die vorherige schließende Klammer ein und verwenden Sie ein vorangestelltes Leerzeichen. Wenngenerates
auf demselben gefolgt von einem Leerzeichen. - Richten Sie alle Parameter aus und geben Sie Werte zurück (falls möglich).
- Der Standardeinzug beträgt 4 Leerzeichen.
- Umgebrochene Parameter werden an den ersten Parametern der vorherigen Zeile Andernfalls haben sie einen Einzug 8 Leerzeichen.
Anmerkungen
Verwenden Sie für Anmerkungen das folgende Format:
@annotate(keyword = value, keyword = {value, value, value})
Sortieren Sie Anmerkungen in alphabetischer Reihenfolge und verwenden Sie Leerzeichen um Gleichheitszeichen. Beispiel:
@callflow(key = value) @entry @exit
Eine Anmerkung muss die gesamte Zeile ausfüllen. Beispiele:
/* Good */ @entry @exit /* Bad */ @entry @exit
Wenn die Anmerkungen nicht in dieselbe Zeile passen, rücken Sie sie mit acht Leerzeichen ein. Beispiel:
@annotate( keyword = value, keyword = { value, value }, keyword = value)
Wenn nicht das gesamte Wertearray in dieselbe Zeile passt, setzen Sie Zeilenumbrüche nach
{
und nach jedem Komma im Array müssen geschweifte Klammern angegeben werden. Ort wird geschlossen
direkt nach dem letzten Wert ein. Setzen Sie die Klammern nicht, wenn
nur einen Wert.
Wenn das gesamte Werte-Array in dieselbe Zeile passen kann, verwenden Sie nach dem Absatz keine Leerzeichen. vor und nach schließenden Klammern. Verwenden Sie nach jedem Komma ein Leerzeichen. Beispiele:
/* Good */ @callflow(key = {"val", "val"}) /* Bad */ @callflow(key = { "val","val" })
Zwischen Anmerkungen und der Funktion dürfen KEINE leeren Zeilen stehen Erklärung. Beispiele:
/* Good */ @entry foo(); /* Bad */ @entry foo();
Enum-Deklarationen
Verwenden Sie für enum-Deklarationen die folgenden Regeln:
- Wenn Enum-Deklarationen für ein anderes Paket freigegeben werden, platzieren Sie die Deklarationen
in
types.hal
, anstatt sie in eine Schnittstelle einzubetten. - Verwenden Sie vor und nach dem Doppelpunkt ein Leerzeichen und nach dem zugrunde liegenden Typ ein Leerzeichen. vor die öffnende geschweifte Klammer.
- Der letzte enum-Wert darf kein zusätzliches Komma enthalten.
Strukturdeklarationen
Verwenden Sie für Strukturdeklarationen die folgenden Regeln:
- Wenn Struct-Deklarationen mit einem anderen Paket geteilt werden, platziere die Deklarationen
in
types.hal
, anstatt sie in eine Schnittstelle einzubetten. - Fügen Sie nach dem Namen des Strukturtyps ein Leerzeichen vor der öffnenden geschweiften Klammer ein.
- Feldnamen ausrichten (optional). Beispiel:
struct MyStruct { vec<uint8_t> data; int32_t someInt; }
Array-Deklarationen
Fügen Sie keine Leerzeichen zwischen den folgenden Elementen ein:
- Elementtyp und offene eckige Klammer.
- Offene eckige Klammer und Arraygröße.
- Arraygröße und schließende eckige Klammer.
- Eckige Klammer und die nächste offene eckige Klammer schließen (falls mehrere vorhanden) Dimension existiert.
Beispiele:
/* Good */ int32_t[5] array; /* Good */ int32_t[5][6] multiDimArray; /* Bad */ int32_t [ 5 ] [ 6 ] array;
Vektoren
Fügen Sie keine Leerzeichen zwischen den folgenden Elementen ein:
vec
und spitze Klammer auf.- Öffnende spitze Klammer und Elementtyp (Ausnahme: Der Elementtyp ist ebenfalls ein
vec
. - Elementtyp und schließende spitze Klammer (Ausnahme: Der Elementtyp ist ebenfalls ein
vec
)
Beispiele:
/* Good */ vec<int32_t> array; /* Good */ vec<vec<int32_t>> array; /* Good */ vec< vec<int32_t> > array; /* Bad */ vec < int32_t > array; /* Bad */ vec < vec < int32_t > > array;