Questa pagina specifica il linguaggio di definizione dell'interfaccia di servizio del veicolo (VSIDL) utilizzando la forma Backus-Naur estesa (EBNF) ISO/IEC 14977 e protobuf. Questa pagina si concentra sulla grammatica libera dal contesto del linguaggio e sul significato degli elementi del linguaggio.
Gerarchia delle lingue
Secondo Meta Object Facility (MOF), il compilatore VSIDL (VSIDLC) utilizza le lingue mostrate nella Figura 1:
Figura 1. Lingue VSIDLC.
VSIDLC si basa principalmente sul linguaggio del buffer di protocollo (protobuf). Protobuf
viene utilizzato per specificare i tipi di dati scambiati tramite la pubblicazione/sottoscrizione e le chiamate di procedura remota (RPC). Da un punto di vista tecnico, i modelli VSIDL
sono file TextProto, in cui la sintassi di VSIDL è definita in un file protobuf
(syntax.proto). Sia i file protobuf per specificare i tipi di dati sia i modelli VSIDL
vengono utilizzati per generare codice Rust. Il codice generato contiene principalmente
struct che implementano le strutture di dati per i messaggi scambiati e funzioni Rust
che implementano funzioni per la creazione di unità di servizio in Rust, senza
chiamare automaticamente queste unità di servizio. Questo codice Rust generato è
accompagnato da codice Rust personalizzato che utilizza il codice generato per creare istanze
di unità di servizio e implementare la logica di business dell'applicazione.
Sintassi astratta
La Figura 2 mostra i tipi di messaggi principali in VSIDL:
Figura 2. Tipi di messaggi principali in VSIDL.
Voce VSIDL
Questa sezione spiega il tipo di messaggio di voce VSIDL.
Grammatica EBNF
start VsidlEntry =
"package" , ":" , String , ";" ,
{ "service_bundle" , ServiceBundle } ,
{ "extension" , ":" , Any } ,
{ "some_ip_mapping" , ":" , SomeIpMapping } ,
{ "vhal_mapping" , ":" , VhalMapping }
;
Definizione del 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;
}
Esempio di utilizzo
package: "com.android.sdv.sample.vsidl"
service_bundle {
name: "Manager"
publisher {
message: "TirePressure"
topic: "front-left"
topic: "front-right"
capacity: 10
}
}
Spiegazione
Il messaggio VsidlEntry funge da contenitore principale per il file VSIDL (con estensione .vsidl). Questo messaggio racchiude tutte le definizioni e le configurazioni in un unico file VSIDL. VsidlEntry è l'elemento di primo livello
che lega tutto il resto.
Finalità:
- Definisce la struttura generale di un file VSIDL.
- Specifica lo spazio dei nomi del pacchetto per tutte le entità all'interno del file.
- Contiene una raccolta di definizioni di bundle di servizi.
- Consente estensioni personalizzate al modello VSIDL.
- Include regole di mappatura per SOME/IP e VHAL.
Vincoli
- Nome pacchetto (E211): il nome del pacchetto non deve superare i 127 caratteri.
- File orfani (E10B): tutti i file di un catalogo devono essere inclusi in un
Android.bpfilegroup.
Pacchetto di servizi
Questa sezione spiega il tipo di messaggio del pacchetto di servizi.
Grammatica 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
;
Definizione del 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;
}
Esempio di utilizzo
service_bundle {
name: "SeatController"
publisher {
message: "SeatHeating"
topic: "driver-seat"
capacity: 10
}
}
Spiegazione
Un bundle di servizi definisce un raggruppamento logico di servizi, editori, abbonati, server RPC e client RPC correlati. Un bundle di servizi funge da container per un insieme specifico di funzionalità e le relative interazioni.
Vincoli
- Requisiti per il nome del bundle (E209, E20A, E20B, E20C):
- Un pacchetto di servizi deve avere un nome compilato.
- Il nome deve iniziare con un carattere iniziale di identificatore Unicode valido (in genere una lettera).
- I caratteri successivi nel nome devono essere caratteri di continuazione validi dell'identificatore Unicode (in genere lettere o numeri).
- Il nome non deve essere una parola chiave riservata in Rust, Java o C++.
- Unicità del bundle globale (E309): ogni bundle di servizi deve avere un nome completo univoco (in base al pacchetto e al nome).
- Unicità interna (E100, E300, E302, E303, E308):
- All'interno di un singolo bundle di servizi, ogni servizio RPC può essere gestito da al massimo una definizione di server.
- All'interno di un singolo pacchetto di servizi, ogni tipo di pubblicazione
MULTI_PUBpuò essere pubblicato da al massimo una definizione di editore. - All'interno di un singolo bundle di servizi, tutti i nomi delle unità di servizio definite dall'utente (per publisher o server) devono essere univoci.
- All'interno di un singolo pacchetto di servizi, tutti i nomi delle unità di servizio (definiti dall'utente o generati automaticamente) devono essere univoci.
- Convenzioni di denominazione dei target di build (E205, E206, E207, E208): se viene fornito un nome di target di build personalizzato (
build_cfg.target_name), deve rispettare il formato snake case (lettere minuscole, numeri e singoli trattini bassi, senza iniziare o terminare con un trattino basso). - Crea un nome di target univoco (E301): un nome di target di build definito dall'utente non deve entrare in conflitto con i nomi di target generati automaticamente per altri bundle di servizi.
Publisher
Questa sezione descrive il tipo di messaggio dell'editore.
Grammatica EBNF
Publisher = "{" , { PublisherElement } , "}" ;
PublisherElement =
"message" , ":" , String |
"topic" , ":" , String |
"capacity" , ":" , Integer |
"service_unit_name" , ":" , String
;
Definizione del 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;
}
Esempio di utilizzo
publisher {
message: "SeatHeating"
topic: "driver-heating"
capacity: 10
}
Spiegazione
Il tipo di messaggio Publisher definisce un'origine dati che ServiceBundle
fornisce. Questo tipo di messaggio specifica il tipo di dati pubblicati e gli argomenti e la capacità specifici di questi dati.
Argomenti
Ogni istanza Publisher ha un campo message che fa riferimento al messaggio proto
che viene pubblicato. Deve specificare un argomento (rappresentato da topic) e una
capacità (rappresentata da capacity).
- Argomento: un identificatore univoco per l'argomento della pubblicazione. Deve seguire
il formato con trattino e lettere minuscole (ad esempio,
my-topic). - Capacità:specifica le dimensioni della coda, ovvero il numero di messaggi che la coda può contenere prima che i messaggi non letti vengano eliminati. Deve essere un numero pari maggiore o uguale a 2.
Nomi definiti dall'utente
I publisher possono avere nomi di unità di servizio definiti dall'utente che sostituiscono i nomi di unità di servizio scelti automaticamente. Questa funzionalità consente di scegliere nomi più brevi. Se un publisher utilizza un nome di unità di servizio definito dall'utente, potrebbe utilizzare una sola istanza, in modo che il nome dell'unità di servizio venga assegnato in modo univoco a un'istanza.
# 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"
}
Vincoli
- Posizionamento del publisher (E300): i publisher per lo stesso tipo
MULTI_PUBdevono essere definiti in bundle di servizi separati. - Unicità del nome locale (E302): all'interno di un singolo bundle di servizi, tutti gli editori devono avere nomi di unità di servizio univoci definiti dall'utente.
- Unicità del nome globale (E304): gli editori dello stesso tipo di pubblicazione devono avere nomi di unità di servizio definiti dall'utente univoci a livello globale in tutti i bundle di servizi.
- Denominazione di singoli canali (E306): i nomi delle unità di servizio definite dall'utente possono essere assegnati solo agli editori che gestiscono esattamente un'istanza.
- Limite per singolo publisher (E307): un messaggio protobuf contrassegnato come
SINGLE_PUBpuò essere pubblicato da un solo publisher nell'intero sistema. - Unicità del nome dell'unità di servizio (E308): tutti i nomi delle unità di servizio (generati o definiti dall'utente) devono essere univoci all'interno del bundle di servizi; i nomi definiti dall'utente devono essere utilizzati per risolvere i conflitti con i nomi generati.
- Requisito di specifica della variante (E501): quando un publisher utilizza un nome definito dall'utente per un tipo con più varianti, deve specificare esplicitamente la variante che pubblica.
- Esistenza dell'editore per gli abbonati (E504): ogni abbonato definito richiede almeno un editore corrispondente per il tipo e la variante specificati.
- Tipo di publisher valido (E601): un publisher deve fare riferimento a un tipo che corrisponde a un messaggio protobuf esistente.
- Requisito di annotazione della pubblicazione (E602): il tipo di messaggio protobuf
a cui fa riferimento un publisher deve includere l'annotazione
SdvPublication. - Utilizzo valido della variante (E606): se un editore specifica una variante (istanza), questa deve esistere all'interno di
instances_enumdefinito per il tipo di pubblicazione in protobuf. - Condizione di specifica della variante (E607): un editore può specificare una variante (istanza) esplicita solo se il tipo di pubblicazione definisce un
instances_enumin protobuf. - Denominazione degli argomenti (E20D, E20F): gli argomenti devono essere in formato dash-case minuscolo e non superare i 127 caratteri.
- Unicità dell'argomento (E314): gli argomenti devono essere univoci a livello globale per tutti i publisher.
- Requisiti di capacità (E406, E407): la capacità è obbligatoria e deve essere un numero pari >= 2.
Sottoscrittore
Questa sezione descrive il tipo di messaggio Abbonato.
Grammatica EBNF
Subscriber = "{" , { SubscriberElement } , "}" ;
SubscriberElement =
"message" , ":" , String |
"topic" , ":" , String
;
Definizione del 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;
}
Esempio di utilizzo
subscriber {
message: "SeatHeating"
topic: "driver-seat"
}
Spiegazione
Il messaggio Subscriber definisce un destinatario della pubblicazione fornito da ServiceBundle. Questo messaggio specifica il tipo di dati a cui è stato effettuato l'abbonamento e gli argomenti specifici della pubblicazione. Se ci sono più editori per un argomento, l'abbonato riceve i messaggi pubblicati da tutti.
Vincoli
- Esistenza editore (E504): per ogni abbonato definito, deve esistere almeno un editore corrispondente che pubblica il tipo e la variante di pubblicazione specificati.
- Tipo di abbonamento valido (E608): un abbonato deve fare riferimento a un tipo che
corrisponde a un messaggio protobuf esistente definito con l'annotazione
SdvPublication. - Abbonamento a una variante valido (E609): se un abbonato specifica una variante (istanza), questa deve essere un valore valido definito all'interno di
instances_enumdel tipo di pubblicazione protobuf corrispondente. - Argomento obbligatorio (E408): l'argomento è obbligatorio per gli abbonati.
- Dichiarazione di nuovo dell'argomento (E311): gli argomenti degli abbonati non devono essere dichiarati di nuovo nello stesso pacchetto di servizi.
Server RPC
Questa sezione spiega il tipo di messaggio del server RPC.
Grammatica EBNF
Server = "{" , { ServerElement } , "}" ;
ServerElement =
"service" , ":" , String |
"channel" , ":" , String |
"service_unit_name" , ":" , String
;
Definizione del 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;
}
Esempio di utilizzo
server {
service: "SetTemperature"
channel: "temp-setter"
}
Spiegazione
Il messaggio Server definisce un server RPC fornito da ServiceBundle. Questo
messaggio specifica il servizio implementato dal server e il canale RPC.
Un server RPC espone un insieme di metodi che i client possono richiamare da remoto. Il campo
service specifica il nome del servizio RPC implementato dal server. Questo servizio è definito in un file proto e implementato in codice Rust personalizzato. I servizi RPC possono includere metodi unari, di streaming dal client e
di streaming dal server, come definito nella definizione del servizio protobuf. Il campo
channel definisce l'endpoint di comunicazione ed è obbligatorio (E409).
Vincoli
- Definizione del servizio (E603): un server RPC deve specificare un valore
serviceche corrisponda a un valoreserviceRPC protobuf esistente. - Limite di server per servizio (E100): all'interno di un singolo bundle di servizi, una
RPC specifica
servicepuò essere gestita da al massimo una definizione di server. - Denominazione dei canali (E20E): i canali RPC devono essere in formato dash-case minuscolo.
- Canale obbligatorio (E409): il canale RPC è obbligatorio.
- Unicità del canale (E40B): il canale RPC deve essere utilizzato da un solo servizio.
Client RPC
Questa sezione spiega il tipo di messaggio del client RPC.
Grammatica EBNF
Client = "{" , { ClientElement } , "}" ;
ClientElement =
"service" , ":" , String |
"channel" , ":" , String
;
Definizione del 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;
}
Esempio di utilizzo
client {
service: "SetTemperature"
channel: "temp-setter"
}
Spiegazione
client definisce un client RPC che ServiceBundle utilizza. client specifica
il servizio con cui interagisce il client e il canale a cui connettersi. Il
client può interagire con i metodi di streaming unari, client e server,
a seconda della definizione del servizio.
Vincoli
- Definizione del servizio (E60A): un client RPC deve specificare un
serviceche corrisponde a una definizioneserviceprotobuf esistente. - Origine del servizio univoca (E60B): la definizione protobuf
servicea cui fa riferimentoservicedi un client RPC deve essere definita in modo univoco (non più volte) in tutti i file protobuf. - Canale obbligatorio (E409): il canale RPC è obbligatorio.
Configurazione build
Questa sezione descrive il tipo di messaggio di configurazione della build.
Grammatica EBNF
BuildConfiguration = "{" , BuildConfigurationElement, "}" ;
BuildConfigurationElement =
"target_name" , ":" , String |
"skip_codegen" , ":" , Boolean
;
Definizione del 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;
}
Esempio di utilizzo
build_cfg {
target_name: "my_custom_target_name"
skip_codegen: false
}
Spiegazione
BuildConfiguration configura i parametri non standard di ServiceBundle per
la generazione di codice. Tutte le configurazioni di build sono facoltative.
target_name(facoltativostring): specifica il nome del target di build nei fileAndroid.bp. Utilizza questa opzione per impostare nomi di destinazione più brevi rispetto a quelli scelti automaticamente.skip_codegen(facoltativobool): indica se la generazione del codice deve essere ignorata per questo pacchetto di servizi. Se impostato sutrue, non viene generato alcun codice per questo particolare pacchetto di servizi. Questa opzione può essere utile per i pacchetti di servizi implementati manualmente. Per impostazione predefinita, questo valore è impostato sufalse.
Vincoli
- Formato del nome del target (E205, E206, E207, E208): se viene fornito un nome di target di build personalizzato (
build_cfg.target_name), deve seguire rigorosamente la formattazione snake case:- Deve contenere solo lettere minuscole (da
aaz), numeri (da0a9) e trattini bassi (_). - Non deve contenere trattini bassi consecutivi (
__). - Non deve iniziare con un trattino basso.
- Non deve terminare con un trattino basso.
- Deve contenere solo lettere minuscole (da
- Unicità del nome target (E301): un
build_cfg.target_namedefinito dall'utente deve essere univoco in tutto il sistema di compilazione e non deve entrare in conflitto con i nomi target generati automaticamente derivati da altre definizioni di bundle di servizi.