Sprachangabe

Auf dieser Seite wird die Vehicle Service Interface Definition Language (VSIDL) mit ISO/IEC 14977 Extended Backus-Naur Form (EBNF) und Protobuf angegeben. Auf dieser Seite geht es um die kontextfreie Grammatik der Sprache und die Bedeutung der Sprachelemente.

Sprachhierarchie

Gemäß der Meta Object Facility (MOF) verwendet der VSIDL-Compiler (VSIDLC) die in Abbildung 1 gezeigten Sprachen:

VSIDLC-Sprachen

Abbildung 1. VSIDLC-Sprachen.

VSIDLC basiert hauptsächlich auf der Protokollzwischenspeicher-Sprache (protobuf). Protobuf wird verwendet, um die Datentypen anzugeben, die über Publish/Subscribe- und RPC-Aufrufe (Remote Procedure Calls) ausgetauscht werden. Aus technischer Sicht sind VSIDL-Modelle TextProto-Dateien, deren Syntax in einer Protobuf-Datei (syntax.proto) definiert ist. Sowohl die Protobuf-Dateien zum Angeben von Datentypen als auch VSIDL-Modelle werden zum Generieren von Rust-Code verwendet. Der generierte Code enthält hauptsächlich Strukturen, die die Datenstrukturen für die ausgetauschten Nachrichten implementieren, und Rust-Funktionen, die Funktionen zum Erstellen von Serviceeinheiten in Rust implementieren, ohne diese Serviceeinheiten automatisch aufzurufen. Der generierte Rust-Code wird von benutzerdefiniertem Rust-Code begleitet, der den generierten Code verwendet, um Serviceeinheiten zu instanziieren und die Geschäftslogik der Anwendung zu implementieren.

Abstrakte Syntax

Abbildung 2 zeigt die wichtigsten Nachrichtentypen in VSIDL:

Wichtige Nachrichtentypen in VSIDL

Abbildung 2: Wichtige Nachrichtentypen in VSIDL.

VSIDL-Eintrag

In diesem Abschnitt wird der VSIDL-Eintragstyp „message“ erläutert.

EBNF-Grammatik

start VsidlEntry =
  "package" , ":" , String , ";" ,
  { "service_bundle" , ServiceBundle } ,
  { "extension" , ":" , Any } ,
  { "some_ip_mapping" , ":" , SomeIpMapping } ,
  { "vhal_mapping" , ":" , VhalMapping }
;

Proto-Definition

// The root message for VSIDL files
message VsidlEntry {
  // Required. Package name for entities mentioned in the file.
  string package = 1;
  // Enables custom extensions beyond the standard VSIDL model.
  repeated google.protobuf.Any extension = 3;

  // SOMEIP mapping rules
  repeated sdv.someip.v1.SomeIpMapping some_ip_mapping = 4;
  // VHAL mapping rules
  repeated VhalMapping vhal_mapping = 5;
  // List of SDV service bundles defined in the file.
  repeated ServiceBundle service_bundle = 6;
}

Verwendungsbeispiel

package: "com.android.sdv.sample.vsidl"

service_bundle {
  name: "Manager"

  publisher {
    message: "TirePressure"
    topic: "front-left"
    topic: "front-right"
    capacity: 10
  }
}

Erklärung

Die Meldung VsidlEntry dient als Root-Container für die VSIDL-Datei (mit der Erweiterung .vsidl). Diese Meldung kapselt alle Definitionen und Konfigurationen in einer einzelnen VSIDL-Datei. Das VsidlEntry ist das Element der obersten Ebene, das alles andere verbindet.

Zweck:

  • Definiert die Gesamtstruktur einer VSIDL-Datei.
  • Gibt den Paket-Namespace für alle Entitäten in der Datei an.
  • Enthält eine Sammlung von Dienstpaketdefinitionen.
  • Ermöglicht benutzerdefinierte Erweiterungen des VSIDL-Modells.
  • Enthält Zuordnungsregeln für SOME/IP und VHAL.

Einschränkungen

  • Paketname (E211): Der Paketname darf nicht länger als 127 Zeichen sein.
  • Verwaiste Dateien (E10B): Auf alle Dateien in einem Katalog muss in einer Android.bp-Dateigruppe verwiesen werden.

Dienstpaket

In diesem Abschnitt wird der Nachrichtentyp für Service-Bundles erläutert.

EBNF-Grammatik

ServiceBundle = "{" , { ServiceBundleElement } , "}" ;

ServiceBundleElement =
  "name" , ":" , String |
  "publisher" , Publisher |
  "subscriber" , Subscriber |
  "server" , Server |
  "client" , Client |
  "extension" , ":" , Any |
  "diagnostics_declaration" , DiagnosticsDeclaration |
  "build_cfg" , BuildConfiguration |
  "register_reflection_metadata" , Boolean
;

Proto-Definition

// Defines an SDV service
message ServiceBundle {
  // Required. Name of the service bundle (without the package name).
  string name = 1;
  // List of publications the service bundle provides.
  repeated Publisher publisher = 2;
  // List of publications a service bundle subscribes to.
  repeated Subscriber subscriber = 3;
  // RPC services offered by a service bundle.
  repeated Server server = 4;
  // RPC services consumed by a service bundle.
  repeated Client client = 5;
  // Enables custom extensions beyond the standard VSIDL model.
  repeated google.protobuf.Any extension = 7;

  // Diagnostics declarations
  sdv.diagnostics.v1.DiagnosticsDeclaration diagnostics_declaration = 8;

  // Build Configuration
  optional BuildConfiguration build_cfg = 9;

  // Register metadata for service units provided by this service bundle.
  // Setting this to true will increase the memory footprint
  // and network load significantly.
  bool register_reflection_metadata = 10;
}

Verwendungsbeispiel

service_bundle {
    name: "SeatController"

    publisher {
      message: "SeatHeating"
      topic: "driver-seat"
      capacity: 10
    }
}

Erklärung

Ein Dienstpaket definiert eine logische Gruppierung von zugehörigen Diensten, Publishern, Abonnenten, RPC-Servern und RPC-Clients. Ein Service-Bundle fungiert als Container für eine bestimmte Reihe von Funktionen und deren Interaktionen.

Einschränkungen

  • Anforderungen für Setnamen (E209, E20A, E20B, E20C):
    • Ein Dienstpaket muss einen Namen haben.
    • Der Name muss mit einem gültigen Unicode-Kennzeichner-Startzeichen beginnen (in der Regel ein Buchstabe).
    • Die nachfolgenden Zeichen im Namen müssen gültige Unicode-Kennzeichner-Fortsetzungszeichen sein (in der Regel Buchstaben oder Zahlen).
    • Der Name darf kein reserviertes Schlüsselwort in Rust, Java oder C++ sein.
  • Globale Eindeutigkeit von Bundles (E309): Jedes Dienst-Bundle muss einen eindeutigen vollständig qualifizierten Namen haben (basierend auf seinem Paket und Namen).
  • Interne Eindeutigkeit (E100, E300, E302, E303, E308):
    • Innerhalb eines einzelnen Dienst-Bundles kann jeder RPC-Dienst von höchstens einer Serverdefinition bereitgestellt werden.
    • Innerhalb eines einzelnen Service-Bundles kann jeder MULTI_PUB-Veröffentlichungstyp von höchstens einer Publisher-Definition veröffentlicht werden.
    • Innerhalb eines einzelnen Service-Bundles müssen alle nutzerdefinierten Namen von Serviceeinheiten (für Publisher oder Server) eindeutig sein.
    • Innerhalb eines einzelnen Dienstbündels müssen alle Namen von Dienst-Units (ob nutzerdefiniert oder automatisch generiert) eindeutig sein.
  • Namenskonventionen für Build-Ziele (E205, E206, E207, E208): Wenn ein benutzerdefinierter Name für das Build-Ziel (build_cfg.target_name) angegeben wird, muss er dem Snake-Case-Format entsprechen (Kleinbuchstaben, Ziffern und einzelne Unterstriche, darf nicht mit einem Unterstrich beginnen oder enden).
  • Eindeutigkeit des Build-Zielnamens (E301): Ein benutzerdefinierter Build-Zielname darf nicht mit automatisch generierten Zielnamen für andere Service-Bundles in Konflikt stehen.

Publisher

In diesem Abschnitt wird der Nachrichtentyp für Publisher erläutert.

EBNF-Grammatik

Publisher = "{" , { PublisherElement } , "}" ;

PublisherElement =
  "message" , ":" , String |
  "topic" , ":" , String |
  "capacity" , ":" , Integer |
  "service_unit_name" , ":" , String
;

Proto-Definition

// Represents a publisher within a service bundle.
message Publisher {
  // Name of the service unit. Name may only use characters from [a-z0-9\-]+,
  // must start with [a-z], may not end with a hyphen,
  // and may not contain consecutive hyphens.
  string service_unit_name = 3;
  // Required. The type of data being published.
  string message = 4;
  // Required. The number of messages a publication queue can hold.
  // Must be an even number >= 2.
  int64 capacity = 6;
  // Required. Unique identifier for the publication topic.
  // Must be in lowercase dash-case.
  repeated string topic = 7;
}

Verwendungsbeispiel

publisher {
  message: "SeatHeating"
  topic: "driver-heating"
  capacity: 10
}

Erklärung

Der Nachrichtentyp Publisher definiert eine Datenquelle, die von ServiceBundle bereitgestellt wird. Mit diesem Nachrichtentyp wird der Typ der veröffentlichten Daten sowie die spezifischen Themen und die Kapazität dieser Daten angegeben.

Themen

Jede Publisher-Instanz hat ein message-Feld, das auf die veröffentlichte Proto-Nachricht verweist. Es muss ein Thema (dargestellt durch topic) und eine Kapazität (dargestellt durch capacity) angegeben werden.

  • Thema:Eine eindeutige Kennung für das Thema der Publikation. Er muss dem Format „Kleinbuchstaben-Bindestrich-Schreibweise“ entsprechen (z. B. my-topic).
  • Kapazität:Gibt die Größe der Warteschlange an, d. h., wie viele Nachrichten die Warteschlange aufnehmen kann, bevor ungelesene Nachrichten verworfen werden. Es muss eine gerade Zahl größer oder gleich 2 sein.

Benutzerdefinierte Namen

Publisher können benutzerdefinierte Namen für Serviceeinheiten festlegen, die die automatisch ausgewählten Namen für Serviceeinheiten überschreiben. So können Sie kürzere Namen wählen. Wenn ein Publisher einen benutzerdefinierten Namen für die Serviceeinheit verwendet, wird möglicherweise nur eine Instanz verwendet, sodass der Name der Serviceeinheit eindeutig einer Instanz zugewiesen ist.

# VALID: A publisher assigns a user-defined name to a single instance
publisher {
  message: "SeatHeating"
  topic: "seat-heating-status"
  service_unit_name: "heating-is-off"
}

# ERROR: user-defined names are only allowed if there's only a single instance
publisher {
  message: "SeatHeating"
  topic: "seat-heating-status"
  service_unit_name: "heating-status"
}

Einschränkungen

  • Publisher-Placement (E300): Publisher für denselben MULTI_PUB-Typ müssen in separaten Servicepaketen definiert werden.
  • Eindeutigkeit des lokalen Namens (E302): Innerhalb eines einzelnen Servicepakets müssen alle Publisher eindeutige nutzerdefinierte Namen für Serviceeinheiten haben.
  • Globale Eindeutigkeit von Namen (E304): Verlage und Webpublisher mit demselben Publikationstyp müssen für alle Servicepakete global eindeutige nutzerdefinierte Namen für Serviceeinheiten haben.
  • Einzelne Channels benennen (E306): Benutzerdefinierte Namen für Serviceeinheiten können nur Publishern zugewiesen werden, die genau eine Instanz verwalten.
  • Limit für einzelne Publisher (E307): Eine als SINGLE_PUB markierte Protobuf-Nachricht kann im gesamten System nur von einem Publisher veröffentlicht werden.
  • Eindeutigkeit von Namen von Serviceeinheiten (E308): Alle Namen von Serviceeinheiten (ob generiert oder vom Nutzer definiert) müssen innerhalb des jeweiligen Servicebündels eindeutig sein. Nutzerdefinierte Namen sollten verwendet werden, um Konflikte mit generierten Namen zu beheben.
  • Anforderung für die Angabe von Varianten (E501): Wenn ein Verlag oder Webpublisher einen benutzerdefinierten Namen für einen Typ mit mehreren Varianten verwendet, muss er die veröffentlichte Variante explizit angeben.
  • Publisher-Existenz für Abonnenten (E504): Für jeden definierten Abonnenten ist mindestens ein entsprechender Publisher für den angegebenen Typ und die angegebene Variante erforderlich.
  • Gültiger Publisher-Typ (E601): Ein Publisher muss auf einen Typ verweisen, der einer vorhandenen Protobuf-Nachricht entspricht.
  • Anforderung für Publikationsannotation (E602): Der vom Publisher referenzierte Protobuf-Nachrichtentyp muss die Annotation SdvPublication enthalten.
  • Gültige Verwendung von Varianten (E606): Wenn ein Verlag oder Webpublisher eine Variante (Instanz) angibt, muss diese Variante in der instances_enum vorhanden sein, die für den Publikationstyp in Protobuf definiert ist.
  • Bedingung für die Variantenspezifikation (E607): Ein Verlag oder Webpublisher kann nur dann eine explizite Variante (Instanz) angeben, wenn der Publikationstyp ein instances_enum in protobuf definiert.
  • Themenbenennung (E20D, E20F): Themen müssen in Kleinbuchstaben mit Bindestrichen geschrieben sein und dürfen nicht länger als 127 Zeichen sein.
  • Eindeutigkeit von Themen (E314): Themen müssen global für alle Verlage und Webpublisher eindeutig sein.
  • Kapazitätsanforderungen (E406, E407): Die Kapazität ist erforderlich und muss eine gerade Zahl >= 2 sein.

Abonnent

In diesem Abschnitt wird der Nachrichtentyp „Abonnent“ erläutert.

EBNF-Grammatik

Subscriber = "{" , { SubscriberElement } , "}" ;

SubscriberElement =
  "message" , ":" , String |
  "topic" , ":" , String
;

Proto-Definition

// Represents a subscriber within a service bundle.
message Subscriber {
  // Required. The type of data being subscribed to.
  string message = 4;
  // Required. Specific topic(s) of the message to subscribe to.
  // Must match the publisher's topic.
  repeated string topic = 6;
}

Verwendungsbeispiel

subscriber {
  message: "SeatHeating"
  topic: "driver-seat"
}

Erklärung

Die Subscriber-Nachricht definiert einen Publikationsempfänger, der von ServiceBundle bereitgestellt wird. In dieser Nachricht wird der Typ der abonnierten Daten und die spezifischen Themen dieser Publikation angegeben. Wenn es mehrere Publisher für ein Thema gibt, erhält der Abonnent die von allen veröffentlichten Nachrichten.

Einschränkungen

  • Vorhandensein des Verlags (E504): Für jeden definierten Abonnenten muss mindestens ein entsprechender Verlag vorhanden sein, der den angegebenen Publikationstyp und die angegebene Variante veröffentlicht.
  • Gültiger Abotyp (E608): Ein Abonnent muss auf einen Typ verweisen, der einer vorhandenen Protobuf-Nachricht entspricht, die mit der Annotation SdvPublication definiert ist.
  • Gültiges Abo für Variante (E609): Wenn ein Abonnent eine Variante (Instanz) angibt, muss diese Variante ein gültiger Wert sein, der in instances_enum des entsprechenden Protobuf-Veröffentlichungstyps definiert ist.
  • Thema erforderlich (E408): Das Thema ist für Abonnenten erforderlich.
  • Themen neu deklarieren (E311): Abonnententhemen sollten nicht im selben Service-Bundle neu deklariert werden.

RPC-Server

In diesem Abschnitt wird der RPC-Server-Nachrichtentyp erläutert.

EBNF-Grammatik

Server = "{" , { ServerElement } , "}" ;

ServerElement =
  "service" , ":" , String |
  "channel" , ":" , String |
  "service_unit_name" , ":" , String
;

Proto-Definition

// Represents an RPC server within a service bundle.
message Server {
  // Deprecated. Name of the service unit.
  string service_unit_name = 3 [ deprecated = true ];
  // Required. Name of the RPC service.
  string service = 4;
  // Required. Name of the RPC channel.
  // Must be in lowercase dash-case.
  string channel = 5;
}

Verwendungsbeispiel

server {
  service: "SetTemperature"
  channel: "temp-setter"
}

Erklärung

Die Server-Nachricht definiert einen RPC-Server, der von ServiceBundle bereitgestellt wird. Diese Nachricht gibt den Dienst an, den der Server implementiert, und den RPC-Channel.

Ein RPC-Server stellt eine Reihe von Methoden bereit, die Clients remote aufrufen können. Das Feld service gibt den Namen des RPC-Dienstes an, den der Server implementiert. Dieser Dienst ist in einer Proto-Datei definiert und in benutzerdefiniertem Rust-Code implementiert. RPC-Dienste können Unary-, Client-Streaming- und Server-Streaming-Methoden enthalten, wie in der Protobuf-Dienstdefinition definiert. Das Feld channel definiert den Kommunikationsendpunkt und ist obligatorisch (E409).

Einschränkungen

  • Dienstdefinition (E603): Ein RPC-Server muss einen service-Wert angeben, der einem vorhandenen Protobuf-RPC-service-Wert entspricht.
  • Serverlimit pro Dienst (E100): Innerhalb eines einzelnen Dienstpakets kann ein bestimmter RPC service von höchstens einer Serverdefinition bereitgestellt werden.
  • Benennung von Channels (E20E): RPC-Channels müssen in Kleinbuchstaben mit Bindestrichen geschrieben werden.
  • Channel mandatory (E409): Der RPC-Channel ist erforderlich.
  • Eindeutigkeit des Channels (E40B): Der RPC-Channel darf nur von einem Dienst verwendet werden.

RPC-Client

In diesem Abschnitt wird der RPC-Client-Nachrichtentyp erläutert.

EBNF-Grammatik

Client = "{" , { ClientElement } , "}" ;

ClientElement =
  "service" , ":" , String |
  "channel" , ":" , String
;

Proto-Definition

// Represents an RPC client within a service bundle.
message Client {
  // Required. Name of the RPC service.
  string service = 2;
  // Required. Name of the RPC channel.
  // Must match the server's channel and be in lowercase dash-case.
  string channel = 3;
}

Verwendungsbeispiel

client {
  service: "SetTemperature"
  channel: "temp-setter"
}

Erklärung

client definiert einen RPC-Client, der von ServiceBundle verwendet wird. client gibt den Dienst an, mit dem der Client interagiert, und den Kanal, zu dem eine Verbindung hergestellt werden soll. Der Client kann je nach Dienstdefinition mit unären Methoden sowie Client-Streaming- und Server-Streaming-Methoden interagieren.

Einschränkungen

  • Dienstdefinition (E60A): Ein RPC-Client muss ein service angeben, das einer vorhandenen Protobuf-service-Definition entspricht.
  • Eindeutige Dienstquelle (E60B): Die Protobuf-Definition service, auf die vom service eines RPC-Clients verwiesen wird, muss in allen Protobuf-Dateien eindeutig definiert sein (nicht mehrfach).
  • Channel mandatory (E409): Der RPC-Channel ist erforderlich.

Build-Konfiguration

In diesem Abschnitt wird der Nachrichtentyp „Build-Konfiguration“ erläutert.

EBNF-Grammatik

BuildConfiguration = "{" , BuildConfigurationElement, "}" ;

BuildConfigurationElement =
  "target_name" , ":" , String |
  "skip_codegen" , ":" , Boolean
;

Proto-Definition

// Defines additional information used to configure build settings
message BuildConfiguration {
  /// Build target name
  optional string target_name = 1;
  // Do not generate code for this service bundle
  optional bool skip_codegen = 2;
}

Verwendungsbeispiel

build_cfg {
  target_name: "my_custom_target_name"
  skip_codegen: false
}

Erklärung

BuildConfiguration konfiguriert nicht standardmäßige Parameter von ServiceBundle für die Code-Generierung. Alle Build-Konfigurationen sind optional.

  • target_name (optional string): Gibt den Namen des Build-Ziels in Android.bp-Dateien an. Damit können Sie Zielnamen mit kürzeren Namen als den automatisch ausgewählten Namen festlegen.
  • skip_codegen (optional bool): Gibt an, ob die Codegenerierung für dieses Dienstpaket übersprungen werden soll. Wenn der Wert auf true festgelegt ist, wird für dieses bestimmte Dienstpaket kein Code generiert. Das kann bei manuell implementierten Servicepaketen nützlich sein. Standardmäßig ist dies auf false eingestellt.

Einschränkungen

  • Format des Zielnamens (E205, E206, E207, E208): Wenn ein benutzerdefinierter Name für das Build-Ziel (build_cfg.target_name) angegeben wird, muss er dem Snake-Case-Format entsprechen:
    • Sie darf nur Kleinbuchstaben (a bis z), Ziffern (0 bis 9) und Unterstriche (_) enthalten.
    • Er darf keine aufeinanderfolgenden Unterstriche (__) enthalten.
    • Er darf nicht mit einem Unterstrich beginnen.
    • Er darf nicht mit einem Unterstrich enden.
  • Eindeutigkeit des Zielnamens (E301): Ein nutzerdefinierter build_cfg.target_name muss im gesamten Build-System eindeutig sein und darf nicht mit automatisch generierten Zielnamen aus anderen Dienstbündeldefinitionen in Konflikt stehen.