En esta página, se especifica el lenguaje de definición de interfaz de servicio del vehículo (VSIDL) con la forma de Backus-Naur extendida (EBNF) de ISO/IEC 14977 y protobuf. En esta página, se aborda la gramática independiente del contexto del lenguaje y el significado de sus elementos.
Jerarquía de idiomas
Según la Meta Object Facility (MOF), el compilador de VSIDL (VSIDLC) usa los lenguajes que se muestran en la Figura 1:
Figura 1: Idiomas de VSIDLC.
VSIDLC se basa principalmente en el lenguaje de búfer de protocolo (protobuf). Protobuf
especifica los tipos de datos que se intercambian con las llamadas a procedimientos remotos (RPC)
y de publicación-suscripción. Técnicamente, los modelos de VSIDL son archivos TextProto, y la sintaxis de VSIDL se define en un archivo protobuf (syntax.proto).
Tanto los archivos protobuf para especificar tipos de datos como los modelos de VSIDL se usan para generar código de Rust. El código generado contiene structs para las estructuras de datos de mensajes intercambiados y funciones de Rust para crear unidades de servicio, sin llamar a esas unidades de servicio automáticamente. Luego, el código personalizado de Rust usa el código generado para crear instancias de unidades de servicio y, además, implementar la lógica de la aplicación.
Sintaxis abstracta
En la Figura 2, se muestran los tipos de mensajes principales en VSIDL:
Figura 2: Tipos de mensajes principales en VSIDL.
Entrada de VSIDL
En esta sección, se explica el tipo de mensaje de entrada de VSIDL.
Gramática de EBNF
start VsidlEntry =
"package" , ":" , String , ";" ,
{ "service_bundle" , ServiceBundle } ,
{ "extension" , ":" , Any } ,
{ "some_ip_mapping" , ":" , SomeIpMapping } ,
{ "vhal_mapping" , ":" , VhalMapping }
;
Definición de 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;
}
Ejemplo de uso
package: "com.android.sdv.sample.vsidl"
service_bundle {
name: "Manager"
publisher {
message: "TirePressure"
topic: "front-left"
topic: "front-right"
capacity: 10
}
}
Explicación
El mensaje VsidlEntry sirve como contenedor raíz para el archivo VSIDL (con la
extensión .vsidl). Este mensaje encapsula todas las definiciones y
parámetros de configuración en un solo archivo VSIDL. VsidlEntry es el elemento de nivel superior
que vincula todo lo demás.
Propósito:
- Define la estructura general de un archivo VSIDL.
- Especifica el espacio de nombres del paquete para todas las entidades dentro del archivo.
- Contiene una colección de definiciones de paquetes de servicios.
- Permite extensiones personalizadas para el modelo de VSIDL.
- Incluye reglas de asignación para SOME/IP y VHAL.
Limitaciones
- Nombre del paquete (E211): El nombre del paquete no debe superar los 127 caracteres.
- Archivos sueltos (E10B): Se debe hacer referencia a todos los archivos de un catálogo en un
grupo de archivos
Android.bp.
Paquete de servicios
En esta sección, se explica el tipo de mensaje del paquete de servicios.
Gramática de 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
;
Definición de 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;
}
Ejemplo de uso
service_bundle {
name: "SeatController"
publisher {
message: "SeatHeating"
topic: "driver-seat"
capacity: 10
}
}
Explicación
Un paquete de servicios define una agrupación lógica de servicios, publicadores, suscriptores, servidores RPC y clientes RPC relacionados. Un paquete de servicios actúa como un contenedor para un conjunto específico de funcionalidades y sus interacciones.
Limitaciones
- Requisitos para los nombres de paquetes (E209, E20A, E20B, E20C):
- Un paquete de servicios debe tener un nombre completo.
- El nombre debe comenzar con un carácter de inicio de identificador Unicode válido (por lo general, una letra).
- Los caracteres posteriores del nombre deben ser caracteres de continuación de identificador Unicode válidos (por lo general, letras o números).
- El nombre no debe ser una palabra clave reservada en Rust, Java o C++.
- Unicidad global del paquete (E309): Cada paquete de servicios debe tener un nombre único completamente calificado (según su paquete y nombre).
- Unicidad interna (E100, E300, E302, E303, E308):
- Dentro de un solo paquete de servicios, cada servicio de RPC se puede entregar con una definición de servidor como máximo.
- Dentro de un solo paquete de servicios, cada tipo de publicación
MULTI_PUBse puede publicar con, como máximo, una definición de publicador. - Dentro de un solo paquete de servicios, todos los nombres de unidades de servicio definidos por el usuario (para publicadores o servidores) deben ser únicos.
- Dentro de un solo paquete de servicios, todos los nombres de las unidades de servicio (ya sean definidos por el usuario o generados automáticamente) deben ser únicos.
- Convenciones de nombres de destinos de compilación (E205, E206, E207, E208): Si se proporciona un nombre de destino de compilación personalizado (
build_cfg.target_name), debe cumplir con el formato de minúsculas con guiones bajos (letras minúsculas, números y guiones bajos simples, sin comenzar ni terminar con un guion bajo). - Unicidad del nombre del destino de compilación (E301): Un nombre de destino de compilación definido por el usuario no debe entrar en conflicto con ningún nombre de destino generado automáticamente para otros paquetes de servicios.
Publicador
En esta sección, se explica el tipo de mensaje Publisher.
Gramática de EBNF
Publisher = "{" , { PublisherElement } , "}" ;
PublisherElement =
"message" , ":" , String |
"topic" , ":" , String |
"capacity" , ":" , Integer |
"service_unit_name" , ":" , String
;
Definición de 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;
}
Ejemplo de uso
publisher {
message: "SeatHeating"
topic: "driver-heating"
capacity: 10
}
Explicación
El tipo de mensaje Publisher define una fuente de datos que proporciona ServiceBundle. Este tipo de mensaje especifica el tipo de datos que se publican, así como los temas específicos y la capacidad de esos datos.
Temas
Cada instancia de Publisher tiene un campo message que hace referencia al mensaje proto
que se publica. Debe especificar un tema (representado por topic) y una
capacidad (representada por capacity).
- Tema: Es un identificador único para el tema de la publicación. Debe seguir
el formato de guiones en minúsculas (por ejemplo,
my-topic). - Capacidad: Especifica el tamaño de la cola, es decir, cuántos mensajes puede contener antes de que se descarten los mensajes no leídos. Debe ser un número par mayor o igual que 2.
Nombres definidos por el usuario
Los publicadores pueden tener nombres de unidades de servicio definidos por el usuario que anulen los nombres de unidades de servicio elegidos automáticamente. Esta posibilidad permite elegir nombres más cortos. Si un publicador usa un nombre de unidad de servicio definido por el usuario, es posible que solo use una instancia, de modo que el nombre de la unidad de servicio se asigne de forma única a una instancia.
# 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"
}
Limitaciones
- Ubicación del publicador (E300): Los publicadores para el mismo tipo de
MULTI_PUBse deben definir en paquetes de servicios independientes. - Unicidad del nombre local (E302): Dentro de cualquier paquete de servicios, todos los publicadores deben tener nombres de unidades de servicio únicos definidos por el usuario.
- Unicidad de nombre global (E304): Los publicadores del mismo tipo de publicación deben tener nombres de unidades de servicio definidos por el usuario que sean únicos a nivel global en todos los paquetes de servicios.
- Asignación de nombres a canales individuales (E306): Los nombres de unidades de servicio definidos por el usuario solo se pueden asignar a publicadores que controlen exactamente una instancia.
- Límite de publicador único (E307): Solo un publicador puede publicar un mensaje de protobuf marcado como
SINGLE_PUBen todo el sistema. - Unicidad del nombre de la unidad de servicio (E308): Todos los nombres de las unidades de servicio (ya sean generados o definidos por el usuario) deben ser únicos dentro de su paquete de servicios. Los nombres definidos por el usuario deben usarse para resolver conflictos con los nombres generados.
- Requisito de especificación de variante (E501): Cuando un publicador usa un nombre definido por el usuario para un tipo con varias variantes, debe especificar de forma explícita la variante que publica.
- Existencia de publicadores para suscriptores (E504): Cada suscriptor definido requiere al menos un publicador correspondiente para el tipo y la variante especificados.
- Tipo de publicador válido (E601): Un publicador debe hacer referencia a un tipo que corresponda a un mensaje de protobuf existente.
- Requisito de anotación de publicación (E602): El tipo de mensaje de protobuf
al que hace referencia un publicador debe incluir la anotación
SdvPublication. - Uso de variante válido (E606): Si un publicador especifica una variante
(instancia), esa variante debe existir dentro de la
instances_enumdefinida para el tipo de publicación en protobuf. - Condición de especificación de variante (E607): Un publicador puede especificar una variante (instancia) explícita solo si el tipo de publicación define un
instances_enumen protobuf. - Nombres de temas (E20D, E20F): Los temas deben estar en minúsculas, con guiones y no superar los 127 caracteres.
- Unicidad de los temas (E314): Los temas deben ser únicos a nivel global en todos los publicadores.
- Requisitos de capacidad (E406, E407): La capacidad es obligatoria y debe ser un número par >= 2.
Suscriptor
En esta sección, se explica el tipo de mensaje Subscriber.
Gramática de EBNF
Subscriber = "{" , { SubscriberElement } , "}" ;
SubscriberElement =
"message" , ":" , String |
"topic" , ":" , String
;
Definición de 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;
}
Ejemplo de uso
subscriber {
message: "SeatHeating"
topic: "driver-seat"
}
Explicación
El mensaje Subscriber define un receptor de publicación que proporciona ServiceBundle. Este mensaje especifica el tipo de datos a los que se suscribe y los
temas específicos de esa publicación. Si hay varios publicadores para un
tema, el suscriptor recibe los mensajes publicados por todos ellos.
Limitaciones
- Existencia del publicador (E504): Para cada suscriptor definido, debe existir al menos un publicador correspondiente que publique el tipo y la variante de publicación especificados.
- Tipo de suscripción válido (E608): Un suscriptor debe hacer referencia a un tipo que
corresponda a un mensaje de protobuf existente definido con la anotación
SdvPublication. - Suscripción de variante válida (E609): Si un suscriptor especifica una variante
(instancia), esa variante debe ser un valor válido definido dentro de
instances_enumdel tipo de publicación de protobuf correspondiente. - Tema obligatorio (E408): El tema es obligatorio para los suscriptores.
- Nueva declaración de temas (E311): Los temas de los suscriptores no se deben volver a declarar en el mismo paquete de servicios.
Servidor RPC
En esta sección, se explica el tipo de mensaje del servidor RPC.
Gramática de EBNF
Server = "{" , { ServerElement } , "}" ;
ServerElement =
"service" , ":" , String |
"channel" , ":" , String |
"service_unit_name" , ":" , String
;
Definición de 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;
}
Ejemplo de uso
server {
service: "SetTemperature"
channel: "temp-setter"
}
Explicación
El mensaje Server define un servidor RPC que proporciona ServiceBundle. Este
mensaje especifica el servicio que implementa el servidor y el canal de RPC.
Un servidor de RPC expone un conjunto de métodos que los clientes pueden invocar de forma remota. El campo service especifica el nombre del servicio de RPC que implementa el servidor. Este servicio se define en un archivo proto y se implementa en código de Rust personalizado. Los servicios de RPC pueden incluir métodos unarios, de transmisión de cliente y
de transmisión de servidor, como se define en la definición del servicio de protobuf. El campo channel define el extremo de comunicación y es obligatorio (E409).
Limitaciones
- Definición del servicio (E603): Un servidor RPC debe especificar un valor
serviceque corresponda a un valorservicede RPC de Protobuf existente. - Límite de servidores por servicio (E100): Dentro de un solo paquete de servicios, una
servicede RPC específica se puede entregar con, como máximo, una definición de servidor. - Nombres de canales (E20E): Los canales de RPC deben estar en minúsculas y con guiones.
- Canal obligatorio (E409): El canal de RPC es obligatorio.
- Unicidad del canal (E40B): Solo un servicio debe usar el canal de RPC.
Cliente de RPC
En esta sección, se explica el tipo de mensaje del cliente de RPC.
Gramática de EBNF
Client = "{" , { ClientElement } , "}" ;
ClientElement =
"service" , ":" , String |
"channel" , ":" , String
;
Definición de 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;
}
Ejemplo de uso
client {
service: "SetTemperature"
channel: "temp-setter"
}
Explicación
client define un cliente de RPC que consume ServiceBundle. client especifica
el servicio con el que interactúa el cliente y el canal al que se conectará. El
cliente puede interactuar con métodos unarios, de transmisión del cliente y de transmisión del servidor,
según la definición del servicio.
Limitaciones
- Definición del servicio (E60A): Un cliente de RPC debe especificar un
serviceque corresponda a una definición de protobufserviceexistente. - Fuente de servicio única (E60B): La definición de
servicede protobuf a la que hace referencia elservicede un cliente de RPC debe definirse de forma única (no definirse varias veces) en todos los archivos protobuf. - Canal obligatorio (E409): El canal de RPC es obligatorio.
Configuración de compilación
En esta sección, se explica el tipo de mensaje de configuración de compilación.
Gramática de EBNF
BuildConfiguration = "{" , BuildConfigurationElement, "}" ;
BuildConfigurationElement =
"target_name" , ":" , String |
"skip_codegen" , ":" , Boolean
;
Definición de 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;
}
Ejemplo de uso
build_cfg {
target_name: "my_custom_target_name"
skip_codegen: false
}
Explicación
BuildConfiguration configura parámetros no estándar de ServiceBundle para
la generación de código. Todos los parámetros de configuración de compilación son opcionales.
target_name(stringopcional): Especifica el nombre del destino de compilación en los archivosAndroid.bp. Usa esta opción para establecer nombres de destino con nombres más cortos que los nombres elegidos automáticamente.skip_codegen(boolopcional): Indica si se debe omitir la generación de código para este paquete de servicios. Si se establece entrue, no se genera código para este paquete de servicios en particular. Esto puede ser útil para los paquetes de servicios que se implementan de forma manual. El valor predeterminado es defalse.
Limitaciones
- Formato del nombre del destino (E205, E206, E207, E208): Si se proporciona un nombre de destino de compilación personalizado (
build_cfg.target_name), debe seguir estrictamente el formato de minúsculas con guiones bajos:- Solo debe contener letras minúsculas (de la
aa laz), números (del0al9) y guiones bajos (_). - No debe contener guiones bajos consecutivos (
__). - No debe comenzar con un guion bajo.
- No debe terminar con un guion bajo.
- Solo debe contener letras minúsculas (de la
- Unicidad del nombre de destino (E301): Un
build_cfg.target_namedefinido por el usuario debe ser único en todo el sistema de compilación y no debe entrar en conflicto con ningún nombre de destino generado automáticamente que se derive de otras definiciones de paquetes de servicios.