Esta página especifica a linguagem de definição de interface de serviço de veículo (VSIDL) usando a forma de Backus-Naur estendida (EBNF) ISO/IEC 14977 e protobuf. Esta página se concentra na gramática livre de contexto da linguagem e no significado dos elementos dela.
Hierarquia de idiomas
De acordo com a Meta Object Facility (MOF), o compilador VSIDL (VSIDLC) usa as linguagens mostradas na Figura 1:
Figura 1. Idiomas do VSIDLC.
O VSIDLC é baseado principalmente na linguagem de buffer de protocolo (protobuf). O Protobuf
é usado para especificar os tipos de dados trocados usando publicação/assinatura e
chamadas de procedimento remoto (RPCs). Do ponto de vista técnico, os modelos VSIDL são arquivos TextProto, em que a sintaxe do VSIDL é definida em um arquivo protobuf (syntax.proto). Os arquivos protobuf para especificar tipos de dados e os modelos VSIDL são usados para gerar código Rust. O código gerado contém principalmente
structs que implementam as estruturas de dados para as mensagens trocadas e funções
do Rust que implementam funções para criar unidades de serviço em Rust, sem
chamar essas unidades de serviço automaticamente. Esse código Rust gerado é
acompanhado de um código Rust personalizado que usa o código gerado para instanciar
unidades de serviço e implementar a lógica de negócios do aplicativo.
Sintaxe abstrata
A Figura 2 mostra os principais tipos de mensagens em VSIDL:
Figura 2. Tipos de mensagens principais em VSIDL.
Entrada VSIDL
Esta seção explica o tipo de mensagem de entrada do VSIDL.
Gramática EBNF
start VsidlEntry =
"package" , ":" , String , ";" ,
{ "service_bundle" , ServiceBundle } ,
{ "extension" , ":" , Any } ,
{ "some_ip_mapping" , ":" , SomeIpMapping } ,
{ "vhal_mapping" , ":" , VhalMapping }
;
Definição 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;
}
Exemplo de uso
package: "com.android.sdv.sample.vsidl"
service_bundle {
name: "Manager"
publisher {
message: "TirePressure"
topic: "front-left"
topic: "front-right"
capacity: 10
}
}
Explicação
A mensagem VsidlEntry serve como o contêiner raiz do arquivo VSIDL (com a extensão .vsidl). Essa mensagem encapsula todas as definições e configurações em um único arquivo VSIDL. O VsidlEntry é o elemento de nível superior
que vincula todo o resto.
Finalidade:
- Define a estrutura geral de um arquivo VSIDL.
- Especifica o namespace do pacote para todas as entidades no arquivo.
- Contém uma coleção de definições de pacote de serviços.
- Permite extensões personalizadas ao modelo VSIDL.
- Inclui regras de mapeamento para SOME/IP e VHAL.
Restrições
- Nome do pacote (E211): o nome do pacote não pode exceder 127 caracteres.
- Arquivos soltos (E10B): todos os arquivos em um catálogo precisam ser referenciados em um grupo de arquivos
Android.bp.
Pacote de serviços
Esta seção explica o tipo de mensagem do pacote de serviços.
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
;
Definição 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;
}
Exemplo de uso
service_bundle {
name: "SeatController"
publisher {
message: "SeatHeating"
topic: "driver-seat"
capacity: 10
}
}
Explicação
Um pacote de serviços define um agrupamento lógico de serviços, editores, assinantes, servidores RPC e clientes RPC relacionados. Um pacote de serviços funciona como um contêiner para um conjunto específico de funcionalidades e interações.
Restrições
- Requisitos para nome do pacote (E209, E20A, E20B, E20C):
- Um pacote de serviços precisa ter um nome preenchido.
- O nome precisa começar com um caractere inicial de identificador Unicode válido (normalmente uma letra).
- Os caracteres subsequentes no nome precisam ser caracteres de continuação de identificador Unicode válidos (normalmente letras ou números).
- O nome não pode ser uma palavra-chave reservada em Rust, Java ou C++.
- Unicidade global do pacote (E309): cada pacote de serviços precisa ter um nome totalmente qualificado exclusivo (com base no pacote e no nome).
- Unicidade interna (E100, E300, E302, E303, E308):
- Em um único pacote de serviços, cada serviço RPC pode ser veiculado por no máximo uma definição de servidor.
- Em um único pacote de serviços, cada tipo de publicação
MULTI_PUBpode ser publicado por no máximo uma definição de editor. - Em um único pacote de serviços, todos os nomes de unidades de serviço definidos pelo usuário (para editores ou servidores) precisam ser exclusivos.
- Em um único pacote de serviços, todos os nomes de unidades de serviço (definidos pelo usuário ou gerados automaticamente) precisam ser exclusivos.
- Convenções de nomenclatura de destino de build (E205, E206, E207, E208): se um nome de destino de build personalizado (
build_cfg.target_name) for fornecido, ele precisará seguir o formato snake case (letras minúsculas, números e sublinhados únicos, sem começar ou terminar com um sublinhado). - Unicidade do nome da build target (E301): um nome de build target definido pelo usuário não pode entrar em conflito com nenhum nome de destino gerado automaticamente para outros pacotes de serviços.
Editor
Esta seção explica o tipo de mensagem do publisher.
Gramática EBNF
Publisher = "{" , { PublisherElement } , "}" ;
PublisherElement =
"message" , ":" , String |
"topic" , ":" , String |
"capacity" , ":" , Integer |
"service_unit_name" , ":" , String
;
Definição 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;
}
Exemplo de uso
publisher {
message: "SeatHeating"
topic: "driver-heating"
capacity: 10
}
Explicação
O tipo de mensagem Publisher define uma fonte de dados que o ServiceBundle
fornece. Esse tipo de mensagem especifica o tipo de dados que estão sendo publicados e os tópicos e a capacidade específicos desses dados.
Tópicos
Cada instância Publisher tem um campo message que se refere à mensagem
proto publicada. Ele precisa especificar um tópico (representado por topic) e uma capacidade (representada por capacity).
- Tema:um identificador exclusivo do tema da publicação. Ele precisa seguir
o formato minúsculo com traços (por exemplo,
my-topic). - Capacidade:especifica o tamanho da fila, ou seja, quantas mensagens ela pode armazenar antes que as mensagens não lidas sejam descartadas. Precisa ser um número par maior ou igual a 2.
Nomes definidos pelo usuário
Os editores podem ter nomes de unidade de serviço definidos pelo usuário que substituem os nomes escolhidos automaticamente. Isso permite escolher nomes mais curtos. Se um publisher usar um nome de unidade de serviço definido pelo usuário, ele poderá usar apenas uma instância para que o nome da unidade de serviço seja atribuído exclusivamente a uma instância.
# 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"
}
Restrições
- Posicionamento do editor (E300): os editores do mesmo tipo
MULTI_PUBprecisam ser definidos em pacotes de serviços separados. - Exclusividade do nome local (E302): em um único pacote de serviços, todos os editores precisam ter nomes de unidades de serviço exclusivos definidos pelo usuário.
- Unicidade global de nomes (E304): os editores do mesmo tipo de publicação precisam ter nomes de unidades de serviço definidos pelo usuário globalmente exclusivos em todos os pacotes de serviços.
- Nomeação de canais únicos (E306): os nomes de unidades de serviço definidos pelo usuário só podem ser atribuídos a editores que processam exatamente uma instância.
- Limite de um único editor (E307): uma mensagem protobuf marcada como
SINGLE_PUBsó pode ser publicada por um editor em todo o sistema. - Exclusividade do nome da unidade de serviço (E308): todos os nomes de unidades de serviço (gerados ou definidos pelo usuário) precisam ser exclusivos no pacote de serviços. Os nomes definidos pelo usuário devem ser usados para resolver conflitos com nomes gerados.
- Requisito de especificação de variante (E501): quando um editor usa um nome definido pelo usuário para um tipo com várias variantes, ele precisa especificar explicitamente a variante que publica.
- Existência do editor para assinantes (E504): cada assinante definido exige pelo menos um editor correspondente para o tipo e a variante especificados.
- Tipo de editor válido (E601): um editor precisa fazer referência a um tipo que corresponda a uma mensagem protobuf existente.
- Requisito de anotação de publicação (E602): o tipo de mensagem protobuf
referenciado por um publisher precisa incluir a anotação
SdvPublication. - Uso válido de variantes (E606): se um publisher especificar uma variante (instância), ela precisará existir no
instances_enumdefinido para o tipo de publicação em protobuf. - Condição de especificação da variante (E607): um editor só pode especificar uma variante explícita (instância) se o tipo de publicação definir um
instances_enumem protobuf. - Nomenclatura de tópicos (E20D, E20F): os tópicos precisam estar em minúsculas com traços e não podem exceder 127 caracteres.
- Exclusividade do tema (E314): os temas precisam ser globalmente exclusivos em todos os editores.
- Requisitos de capacidade (E406, E407): a capacidade é obrigatória e precisa ser um número par >= 2.
Assinante
Esta seção explica o tipo de mensagem "Subscriber".
Gramática EBNF
Subscriber = "{" , { SubscriberElement } , "}" ;
SubscriberElement =
"message" , ":" , String |
"topic" , ":" , String
;
Definição 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;
}
Exemplo de uso
subscriber {
message: "SeatHeating"
topic: "driver-seat"
}
Explicação
A mensagem Subscriber define um receptor de publicação que o ServiceBundle
fornece. Essa mensagem especifica o tipo de dados a que o usuário está se inscrevendo e os tópicos específicos da publicação. Se houver vários editores para um
tópico, o assinante vai receber as mensagens publicadas por todos eles.
Restrições
- Existência do editor (E504): para cada assinante definido, é necessário que exista pelo menos um editor correspondente que publique o tipo e a variante de publicação especificados.
- Tipo de assinatura válido (E608): um assinante precisa fazer referência a um tipo que
corresponde a uma mensagem protobuf definida com a anotação
SdvPublication. - Assinatura de variante válida (E609): se um assinante especificar uma variante (instância), ela precisará ser um valor válido definido em
instances_enumdo tipo de publicação protobuf correspondente. - Tópico obrigatório (E408): o tópico é obrigatório para os assinantes.
- Redeclaração de tópico (E311): os tópicos do assinante não podem ser redeclarados no mesmo pacote de serviços.
Servidor RPC
Esta seção explica o tipo de mensagem do servidor RPC.
Gramática EBNF
Server = "{" , { ServerElement } , "}" ;
ServerElement =
"service" , ":" , String |
"channel" , ":" , String |
"service_unit_name" , ":" , String
;
Definição 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;
}
Exemplo de uso
server {
service: "SetTemperature"
channel: "temp-setter"
}
Explicação
A mensagem Server define um servidor RPC que o ServiceBundle fornece. Essa
mensagem especifica o serviço que o servidor implementa e o canal RPC.
Um servidor RPC expõe um conjunto de métodos que os clientes podem invocar remotamente. O campo service especifica o nome do serviço RPC que o servidor implementa. Esse serviço é definido em um arquivo proto e implementado em código Rust personalizado. Os serviços RPC podem incluir métodos unários, de streaming do cliente e
de streaming do servidor, conforme definido na definição de serviço do protobuf. O campo
channel define o endpoint de comunicação e é obrigatório (E409).
Restrições
- Definição de serviço (E603): um servidor RPC precisa especificar um valor
serviceque corresponda a um valorserviceRPC protobuf existente. - Limite de servidor por serviço (E100): em um único pacote de serviços, uma
RPC
serviceespecífica pode ser atendida por no máximo uma definição de servidor. - Nomenclatura de canais (E20E): os canais RPC precisam estar em letras minúsculas e separados por traços.
- Canal obrigatório (E409): o canal RPC é obrigatório.
- Unicidade do canal (E40B): o canal RPC só pode ser usado por um serviço.
Cliente RPC
Esta seção explica o tipo de mensagem do cliente RPC.
Gramática EBNF
Client = "{" , { ClientElement } , "}" ;
ClientElement =
"service" , ":" , String |
"channel" , ":" , String
;
Definição 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;
}
Exemplo de uso
client {
service: "SetTemperature"
channel: "temp-setter"
}
Explicação
client define um cliente RPC que ServiceBundle consome. client especifica
o serviço com que o cliente interage e o canal a que se conectar. O
cliente pode interagir com métodos unários, de streaming do cliente e de streaming do servidor,
dependendo da definição do serviço.
Restrições
- Definição de serviço (E60A): um cliente RPC precisa especificar um
serviceque corresponda a uma definição deserviceprotobuf existente. - Origem de serviço única (E60B): a definição de
serviceprotobuf referenciada peloservicede um cliente RPC precisa ser definida de forma exclusiva (não várias vezes) em todos os arquivos protobuf. - Canal obrigatório (E409): o canal RPC é obrigatório.
Configuração do build
Esta seção explica o tipo de mensagem de configuração do build.
Gramática EBNF
BuildConfiguration = "{" , BuildConfigurationElement, "}" ;
BuildConfigurationElement =
"target_name" , ":" , String |
"skip_codegen" , ":" , Boolean
;
Definição 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;
}
Exemplo de uso
build_cfg {
target_name: "my_custom_target_name"
skip_codegen: false
}
Explicação
BuildConfiguration configura parâmetros não padrão de ServiceBundle para geração de código. Todas as configurações de build são opcionais.
target_name(opcionalstring): especifica o nome do destino de build nos arquivosAndroid.bp. Use isso para definir nomes de destino mais curtos do que os escolhidos automaticamente.skip_codegen(opcionalbool): indica se a geração de código precisa ser ignorada para este pacote de serviços. Se definido comotrue, nenhum código será gerado para esse pacote de serviços específico. Isso pode ser útil para pacotes de serviços implementados manualmente. Por padrão, essa opção é definida comofalse.
Restrições
- Formato do nome da segmentação (E205, E206, E207, E208): se um nome de segmentação de build personalizado (
build_cfg.target_name) for fornecido, ele precisará seguir estritamente a formatação snake_case:- Ele precisa conter apenas letras minúsculas (de
aaz), números (de0a9) e sublinhados (_). - Não pode conter sublinhados consecutivos (
__). - Não pode começar com um sublinhado.
- Não pode terminar com um sublinhado.
- Ele precisa conter apenas letras minúsculas (de
- Unicidade do nome de destino (E301): um
build_cfg.target_namedefinido pelo usuário precisa ser exclusivo em todo o sistema de build e não pode entrar em conflito com nenhum nome de destino gerado automaticamente derivado de outras definições de pacote de serviços.