Cette page spécifie le langage de définition d'interface de service de véhicule (VSIDL) à l'aide de la forme Backus-Naur étendue (EBNF) ISO/IEC 14977 et de protobuf. Cette page se concentre sur la grammaire non contextuelle du langage et sur la signification des éléments du langage.
Hiérarchie des langues
Selon la Meta Object Facility (MOF), le compilateur VSIDL (VSIDLC) utilise les langages indiqués sur la figure 1 :
Figure 1. Langues VSIDLC.
VSIDLC est principalement basé sur le langage de tampon de protocole (protobuf). Protobuf est utilisé pour spécifier les types de données échangés à l'aide des appels de publication/abonnement et des appels de procédure à distance (RPC). D'un point de vue technique, les modèles VSIDL sont des fichiers TextProto, dont la syntaxe est définie dans un fichier protobuf (syntax.proto). Les fichiers protobuf permettant de spécifier les types de données et les modèles VSIDL sont utilisés pour générer du code Rust. Le code généré contient principalement des structs qui implémentent les structures de données pour les messages échangés et des fonctions Rust qui implémentent des fonctions pour créer des unités de service en Rust, sans appeler automatiquement ces unités de service. Ce code Rust généré est accompagné d'un code Rust personnalisé qui utilise le code généré pour instancier les unités de service et implémenter la logique métier de l'application.
Syntaxe abstraite
La figure 2 montre les principaux types de messages dans VSIDL :
Figure 2. Types de messages principaux dans VSIDL.
Entrée VSIDL
Cette section explique le type de message d'entrée VSIDL.
Grammaire EBNF
start VsidlEntry =
"package" , ":" , String , ";" ,
{ "service_bundle" , ServiceBundle } ,
{ "extension" , ":" , Any } ,
{ "some_ip_mapping" , ":" , SomeIpMapping } ,
{ "vhal_mapping" , ":" , VhalMapping }
;
Définition proto
// 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;
}
Exemple d'utilisation
package: "com.android.sdv.sample.vsidl"
service_bundle {
name: "Manager"
publisher {
message: "TirePressure"
topic: "front-left"
topic: "front-right"
capacity: 10
}
}
Explication
Le message VsidlEntry sert de conteneur racine pour le fichier VSIDL (avec l'extension .vsidl). Ce message encapsule toutes les définitions et configurations dans un seul fichier VSIDL. VsidlEntry est l'élément de premier niveau qui lie tous les autres éléments.
Objectif :
- Définit la structure globale d'un fichier VSIDL.
- Spécifie l'espace de noms du package pour toutes les entités du fichier.
- Contient une collection de définitions de packs de services.
- Permet des extensions personnalisées au modèle VSIDL.
- Inclut des règles de mappage pour SOME/IP et VHAL.
Contraintes
- Nom du package (E211) : le nom du package ne doit pas dépasser 127 caractères.
- Fichiers orphelins (E10B) : tous les fichiers d'un catalogue doivent être référencés dans un groupe de fichiers
Android.bp.
Pack de services
Cette section explique le type de message du pack de services.
Grammaire EBNF
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
;
Définition proto
// 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;
}
Exemple d'utilisation
service_bundle {
name: "SeatController"
publisher {
message: "SeatHeating"
topic: "driver-seat"
capacity: 10
}
}
Explication
Un bundle de services définit un regroupement logique de services, d'éditeurs, d'abonnés, de serveurs RPC et de clients RPC associés. Un bundle de services sert de conteneur pour un ensemble spécifique de fonctionnalités et leurs interactions.
Contraintes
- Exigences relatives aux noms de packs (E209, E20A, E20B, E20C) :
- Un bundle de services doit avoir un nom.
- Le nom doit commencer par un caractère de début d'identifiant Unicode valide (généralement une lettre).
- Les caractères suivants du nom doivent être des caractères de continuation d'identifiant Unicode valides (généralement des lettres ou des chiffres).
- Le nom ne doit pas être un mot clé réservé en Rust, Java ou C++.
- Unicité globale du bundle (E309) : chaque bundle de services doit avoir un nom complet unique (basé sur son package et son nom).
- Unicité interne (E100, E300, E302, E303, E308) :
- Dans un même bundle de services, chaque service RPC ne peut être fourni que par une seule définition de serveur.
- Dans un même bundle de services, chaque type de publication
MULTI_PUBne peut être publié que par une seule définition d'éditeur. - Dans un même bundle de services, tous les noms d'unités de service définis par l'utilisateur (pour les éditeurs ou les serveurs) doivent être uniques.
- Dans un même bundle de services, tous les noms d'unités de service (qu'ils soient définis par l'utilisateur ou générés automatiquement) doivent être uniques.
- Conventions de dénomination des cibles de compilation (E205, E206, E207, E208) : si un nom de cible de compilation personnalisé (
build_cfg.target_name) est fourni, il doit respecter le format snake case (lettres minuscules, chiffres et traits de soulignement uniques, ne commençant ni ne se terminant par un trait de soulignement). - Unicité du nom de la cible de compilation (E301) : un nom de cible de compilation défini par l'utilisateur ne doit pas entrer en conflit avec les noms de cibles générés automatiquement pour d'autres bundles de services.
Éditeur
Cette section explique le type de message "Éditeur".
Grammaire EBNF
Publisher = "{" , { PublisherElement } , "}" ;
PublisherElement =
"message" , ":" , String |
"topic" , ":" , String |
"capacity" , ":" , Integer |
"service_unit_name" , ":" , String
;
Définition proto
// 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;
}
Exemple d'utilisation
publisher {
message: "SeatHeating"
topic: "driver-heating"
capacity: 10
}
Explication
Le type de message Publisher définit une source de données fournie par ServiceBundle. Ce type de message spécifie le type de données publiées, ainsi que les thèmes et la capacité spécifiques de ces données.
Thèmes
Chaque instance Publisher comporte un champ message qui fait référence au message proto publié. Il doit spécifier un sujet (représenté par topic) et une capacité (représentée par capacity).
- Thème : identifiant unique du thème de la publication. Il doit respecter la casse à tirets (par exemple,
my-topic). - Capacité : spécifie la taille de la file d'attente, c'est-à-dire le nombre de messages que la file d'attente peut contenir avant que les messages non lus ne soient supprimés. Il doit s'agir d'un nombre pair supérieur ou égal à 2.
Noms définis par l'utilisateur
Les éditeurs peuvent définir des noms d'unités de service qui remplacent ceux choisis automatiquement. Cette affordance permet de choisir des noms plus courts. Si un éditeur utilise un nom d'unité de service défini par l'utilisateur, il ne peut utiliser qu'une seule instance. Le nom de l'unité de service est donc attribué de manière unique à une instance.
# 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"
}
Contraintes
- Emplacement de l'éditeur (E300) : les éditeurs du même type
MULTI_PUBdoivent être définis dans des bundles de services distincts. - Unicité du nom local (E302) : dans un même bouquet de services, tous les éditeurs doivent avoir des noms d'unités de service uniques définis par l'utilisateur.
- Unicité du nom global (E304) : les éditeurs du même type de publication doivent avoir des noms d'unités de service définis par l'utilisateur et uniques au niveau mondial pour tous les bundles de services.
- Nommer des chaînes individuelles (E306) : les noms d'unités de service définis par l'utilisateur ne peuvent être attribués qu'aux éditeurs qui gèrent une seule instance.
- Limite pour un seul éditeur (E307) : un message protobuf marqué comme
SINGLE_PUBne peut être publié que par un seul éditeur dans l'ensemble du système. - Unicité des noms d'unités de service (E308) : tous les noms d'unités de service (générés ou définis par l'utilisateur) doivent être uniques dans leur offre groupée de services. Les noms définis par l'utilisateur doivent être utilisés pour résoudre les conflits avec les noms générés.
- Exigence de spécification de variante (E501) : lorsqu'un éditeur utilise un nom défini par l'utilisateur pour un type comportant plusieurs variantes, il doit spécifier explicitement la variante qu'il publie.
- Existence d'un éditeur pour les abonnés (E504) : chaque abonné défini doit avoir au moins un éditeur correspondant pour le type et la variante spécifiés.
- Type d'éditeur valide (E601) : un éditeur doit faire référence à un type qui correspond à un message protobuf existant.
- Exigence concernant l'annotation de publication (E602) : le type de message protobuf référencé par un éditeur doit inclure l'annotation
SdvPublication. - Utilisation valide des variantes (E606) : si un éditeur spécifie une variante (instance), celle-ci doit exister dans le
instances_enumdéfini pour le type de publication dans protobuf. - Condition de spécification de variante (E607) : un éditeur ne peut spécifier une variante (instance) explicite que si le type de publication définit un
instances_enumdans protobuf. - Nommage des thèmes (E20D, E20F) : les thèmes doivent être en minuscules et au format "dash-case", et ne pas dépasser 127 caractères.
- Unicité des thèmes (E314) : les thèmes doivent être uniques pour tous les éditeurs.
- Exigences concernant la capacité (E406, E407) : la capacité est obligatoire et doit être un nombre pair supérieur ou égal à 2.
Abonné
Cette section explique le type de message "Abonné".
Grammaire EBNF
Subscriber = "{" , { SubscriberElement } , "}" ;
SubscriberElement =
"message" , ":" , String |
"topic" , ":" , String
;
Définition proto
// 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;
}
Exemple d'utilisation
subscriber {
message: "SeatHeating"
topic: "driver-seat"
}
Explication
Le message Subscriber définit un récepteur de publication fourni par ServiceBundle. Ce message spécifie le type de données auxquelles l'utilisateur est abonné et les thèmes spécifiques de cette publication. S'il existe plusieurs éditeurs pour un sujet, l'abonné reçoit les messages publiés par chacun d'eux.
Contraintes
- Existence de l'éditeur (E504) : pour chaque abonné défini, il doit exister au moins un éditeur correspondant qui publie le type et la variante de publication spécifiés.
- Type d'abonnement valide (E608) : un abonné doit faire référence à un type qui correspond à un message protobuf existant défini avec l'annotation
SdvPublication. - Abonnement à une variante valide (E609) : si un abonné spécifie une variante (instance), cette variante doit être une valeur valide définie dans
instances_enumdu type de publication protobuf correspondant. - Sujet obligatoire (E408) : le sujet est obligatoire pour les abonnés.
- Redéclaration de thèmes (E311) : les thèmes d'abonné ne doivent pas être redéclarés dans le même bundle de services.
Serveur RPC
Cette section explique le type de message du serveur RPC.
Grammaire EBNF
Server = "{" , { ServerElement } , "}" ;
ServerElement =
"service" , ":" , String |
"channel" , ":" , String |
"service_unit_name" , ":" , String
;
Définition proto
// 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;
}
Exemple d'utilisation
server {
service: "SetTemperature"
channel: "temp-setter"
}
Explication
Le message Server définit un serveur RPC fourni par ServiceBundle. Ce message spécifie le service que le serveur implémente et le canal RPC.
Un serveur RPC expose un ensemble de méthodes que les clients peuvent appeler à distance. Le champ service spécifie le nom du service RPC que le serveur implémente. Ce service est défini dans un fichier .proto et implémenté dans du code Rust personnalisé. Les services RPC peuvent inclure des méthodes unaires, de streaming côté client et de streaming côté serveur, telles que définies dans la définition de service protobuf. Le champ channel définit le point de terminaison de la communication et est obligatoire (E409).
Contraintes
- Définition de service (E603) : un serveur RPC doit spécifier une valeur
servicequi correspond à une valeurserviceRPC protobuf existante. - Limite de serveurs par service (E100) : dans un même bundle de services, un
serviceRPC spécifique ne peut être fourni que par une seule définition de serveur. - Nommage des canaux (E20E) : les canaux RPC doivent être en minuscules et séparés par des tirets.
- Canal obligatoire (E409) : le canal RPC est obligatoire.
- Unicité du canal (E40B) : le canal RPC ne doit être utilisé que par un seul service.
Client RPC
Cette section explique le type de message du client RPC.
Grammaire EBNF
Client = "{" , { ClientElement } , "}" ;
ClientElement =
"service" , ":" , String |
"channel" , ":" , String
;
Définition proto
// 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;
}
Exemple d'utilisation
client {
service: "SetTemperature"
channel: "temp-setter"
}
Explication
client définit un client RPC que ServiceBundle consomme. client spécifie le service avec lequel le client interagit et le canal auquel se connecter. Le client peut interagir avec les méthodes de streaming unaire, client et serveur, en fonction de la définition du service.
Contraintes
- Définition du service (E60A) : un client RPC doit spécifier un
servicequi correspond à une définitionserviceprotobuf existante. - Source de service unique (E60B) : la définition protobuf
serviceréférencée par leserviced'un client RPC doit être définie de manière unique (et non plusieurs fois) dans tous les fichiers protobuf. - Canal obligatoire (E409) : le canal RPC est obligatoire.
Configuration de la compilation
Cette section explique le type de message de configuration de compilation.
Grammaire EBNF
BuildConfiguration = "{" , BuildConfigurationElement, "}" ;
BuildConfigurationElement =
"target_name" , ":" , String |
"skip_codegen" , ":" , Boolean
;
Définition proto
// 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;
}
Exemple d'utilisation
build_cfg {
target_name: "my_custom_target_name"
skip_codegen: false
}
Explication
BuildConfiguration configure les paramètres non standards de ServiceBundle pour la génération de code. Toutes les configurations de compilation sont facultatives.
target_name(facultatifstring) : spécifie le nom de la cible de compilation dans les fichiersAndroid.bp. Utilisez cette option pour définir des noms cibles plus courts que ceux choisis automatiquement.skip_codegen(facultatifbool) : indique si la génération de code doit être ignorée pour ce bundle de services. Si la valeur est définie surtrue, aucun code n'est généré pour ce bundle de services spécifique. Cela peut être utile pour les forfaits de services implémentés manuellement. Par défaut, cette valeur est définie surfalse.
Contraintes
- Format du nom de la cible (E205, E206, E207, E208) : si un nom de cible de compilation personnalisée (
build_cfg.target_name) est fourni, il doit respecter strictement le format snake_case :- Il ne doit contenir que des lettres minuscules (de
aàz), des chiffres (de0à9) et des traits de soulignement (_). - Il ne doit pas contenir de traits de soulignement consécutifs (
__). - Il ne doit pas commencer par un trait de soulignement.
- Il ne doit pas se terminer par un trait de soulignement.
- Il ne doit contenir que des lettres minuscules (de
- Unicité du nom de la cible (E301) : un
build_cfg.target_namedéfini par l'utilisateur doit être unique dans le système de compilation et ne doit pas entrer en conflit avec les noms de cibles générés automatiquement à partir d'autres définitions de bundle de services.