En esta página, se especifica el Lenguaje de Definición de Interfaz de Servicio de Vehículo (VSIDL) con la forma Backus-Naur extendida (EBNF) ISO/IEC 14977 y protobuf. Esta página se enfoca en la gramática independiente del contexto del lenguaje y el significado de los elementos del lenguaje.
Jerarquía de lenguaje
Según el Meta Object Facility (MOF), el compilador VSIDL (VSIDLC) usa los lenguajes que se muestran en la Figura 1:
Figura 1: Lenguajes VSIDLC
VSIDLC se basa principalmente en el lenguaje de búferes de protocolo (protobuf). Protobuf se usa para especificar los tipos de datos que se intercambian con llamadas de publicación-suscripción y llamadas de procedimiento remoto (RPC). Desde un punto de vista técnico, los modelos VSIDL son archivos TextProto, en los que la sintaxis de VSIDL se define en un archivo protobuf (syntax.proto). Los archivos protobuf para especificar tipos de datos y los modelos VSIDL se usan para generar código Rust. El código generado contiene principalmente structs que implementan las estructuras de datos para los mensajes intercambiados y las funciones de Rust que implementan funciones para crear unidades de servicio en Rust, sin llamar a estas unidades de servicio automáticamente. Este código Rust generado se acompaña de código Rust personalizado que usa el código generado para crear instancias de unidades de servicio y, también, implementar la lógica empresarial 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 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 configuraciones 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 al modelo 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 colgantes (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 de paquete de servicios.
Gramática 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 propagado.
- 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 completamente calificado único (según su paquete y nombre).
- Unicidad interna (E100, E300, E302, E303, E308):
- Dentro de un solo paquete de servicios, cada servicio RPC puede publicarse en, como máximo, una definición de servidor.
- Dentro de un solo paquete de servicios, cada tipo de publicación
MULTI_PUBpuede publicarse en, 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 unidades de servicio (ya sean definidos por el usuario o generados automáticamente) deben ser únicos.
- Convenciones de nomenclatura de destino 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 snake case (letras minúsculas, números y guiones bajos únicos, sin comenzar ni terminar con un guion bajo). - Unicidad del nombre de 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.
Publisher
En esta sección, se explica el tipo de mensaje Publisher.
Gramática 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 y los temas y la capacidad específicos de esos datos.
Temas
Cada instancia 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: Un identificador único para el tema de publicación. Debe seguir el formato dash-case en minúscula (por ejemplo,
my-topic). - Capacidad: Especifica el tamaño de la cola, es decir, cuántos mensajes puede contener la cola antes de que se descarten los mensajes no leídos. Debe ser un número par igual o mayor que 2.
Nombres definidos por el usuario
Los publicadores pueden tener nombres de unidades de servicio definidos por el usuario que anulan los nombres de unidades de servicio elegidos automáticamente. Esta indicación visual 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 del mismo tipo
MULTI_PUBdeben definirse en paquetes de servicios separados. - Unicidad del nombre local (E302): Dentro de un solo paquete de servicios, todos los publicadores deben tener nombres de unidades de servicio definidos por el usuario únicos.
- Unicidad del nombre global (E304): Los publicadores del mismo tipo de publicación deben tener nombres de unidades de servicio definidos por el usuario únicos a nivel global en todos los paquetes de servicios.
- Nombres de canales únicos (E306): Los nombres de unidades de servicio definidos por el usuario solo se pueden asignar a los publicadores que controlan exactamente una instancia.
- Límite de publicador único (E307): Un mensaje protobuf marcado como
SINGLE_PUBsolo puede ser publicado por un publicador en todo el sistema. - Unicidad del nombre de la unidad de servicio (E308): Todos los nombres de 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 se deben usar 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 explícitamente la variante que publica.
- Existencia del publicador para los 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 protobuf existente.
- Requisito de anotación de publicación (E602): El tipo de mensaje protobuf al que hace referencia un publicador debe incluir la anotación
SdvPublication. - Uso de variantes válidas (E606): Si un publicador especifica una variante (instancia), esa variante debe existir dentro de
instances_enumdefinida para el tipo de publicación en protobuf. - Condición de especificación de variante (E607): Un publicador puede especificar una variante explícita (instancia) solo si el tipo de publicación define un
instances_enumen protobuf. - Nombres de temas (E20D, E20F): Los temas deben estar en formato dash-case en minúscula y no superar los 127 caracteres.
- Unicidad del tema (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 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 al 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 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 protobuf correspondiente. - Tema obligatorio (E408): El tema es obligatorio para los suscriptores.
- Redeclaración de tema (E311): Los temas de suscriptores no se deben redeclarar en el mismo paquete de servicios.
Servidor RPC
En esta sección, se explica el tipo de mensaje de servidor RPC.
Gramática 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 RPC.
Un servidor RPC expone un conjunto de métodos que los clientes pueden invocar de forma remota. El campo service especifica el nombre del servicio RPC que implementa el servidor. Este servicio se define en un archivo proto y se implementa en código Rust personalizado. Los servicios RPC pueden incluir métodos unarios, de transmisión por secuencias del cliente y de transmisión por secuencias del servidor, como se define en la definición del servicio protobuf. El campo channel define el extremo de comunicación y es obligatorio (E409).
Limitaciones
- Definición de servicio (E603): Un servidor RPC debe especificar un valor
serviceque corresponda a un valorserviceRPC protobuf existente. - Límite de servidor por servicio (E100): Dentro de un solo paquete de servicios, un
serviceRPC específico puede publicarse en, como máximo, una definición de servidor. - Nombres de canales (E20E): Los canales RPC deben estar en formato dash-case en minúscula.
- Canal obligatorio (E409): El canal RPC es obligatorio.
- Unicidad del canal (E40B): El canal RPC debe ser usado por un solo servicio.
Cliente RPC
En esta sección, se explica el tipo de mensaje de cliente RPC.
Gramática 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 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 por secuencias del cliente y de transmisión por secuencias del servidor, según la definición del servicio.
Limitaciones
- Definición de servicio (E60A): Un cliente RPC debe especificar un
serviceque corresponda a una definiciónserviceprotobuf existente. - Fuente de servicio única (E60B): La definición
serviceprotobuf a la que hace referencia elservicede un cliente RPC debe definirse de forma única (no se define varias veces) en todos los archivos protobuf. - Canal obligatorio (E409): El canal 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 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. Todas las configuraciones de compilación son opcionales.
target_name(stringopcional): Especifica el nombre del destino de compilación en los archivosAndroid.bp. Úsalo para establecer nombres de destino con nombres más cortos que los 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. De forma predeterminada, se establece enfalse.
Limitaciones
- Formato del nombre de 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 snake case:- Debe contener solo letras minúsculas (
aaz), números (0a9) y guiones bajos (_). - No debe contener guiones bajos consecutivos (
__). - No debe comenzar con un guion bajo.
- No debe terminar con un guion bajo.
- Debe contener solo letras minúsculas (
- 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 derivado de otras definiciones de paquetes de servicios.