На этой странице описывается язык определения интерфейса сервиса транспортного средства (VSIDL) с использованием расширенной формы Бэкуса-Наура (EBNF) ISO/IEC 14977 и protobuf. На этой странице рассматривается контекстно-свободная грамматика языка и значение его элементов.
Иерархия языков
Согласно Meta Object Facility (MOF), компилятор VSIDL (VSIDLC) использует языки, показанные на рисунке 1:
Рисунок 1. Языки VSIDLC.
VSIDLC в основном основан на языке буфера протокола (protobuf). Protobuf определяет типы данных, которыми обмениваются с помощью публикации-подписки и вызовов удаленных процедур (RPC). Технически модели VSIDL – это файлы TextProto, а синтаксис VSIDL определяется в файле protobuf (syntax.proto).
Для генерации кода Rust используются как файлы protobuf, определяющие типы данных, так и модели VSIDL. Сгенерированный код содержит структуры для структур данных обмениваемых сообщений и функции Rust для создания сервисных блоков без их автоматического вызова. Затем пользовательский код Rust использует сгенерированный код для создания экземпляров сервисных блоков и реализации логики приложения.
Абстрактный синтаксис
На рисунке 2 показаны основные типы сообщений в VSIDL:
Рисунок 2. Основные типы сообщений в VSIDL.
Запись VSIDL
В этом разделе описывается тип сообщения VSIDL entry.
Грамматика EBNF
start VsidlEntry =
"package" , ":" , String , ";" ,
{ "service_bundle" , ServiceBundle } ,
{ "extension" , ":" , Any } ,
{ "some_ip_mapping" , ":" , SomeIpMapping } ,
{ "vhal_mapping" , ":" , VhalMapping }
;
Определение протокола
// 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;
}
Пример использования
package: "com.android.sdv.sample.vsidl"
service_bundle {
name: "Manager"
publisher {
message: "TirePressure"
topic: "front-left"
topic: "front-right"
capacity: 10
}
}
Описание
Сообщение VsidlEntry служит корневым контейнером для файла VSIDL (с расширением .vsidl). Это сообщение инкапсулирует все определения и конфигурации в одном файле VSIDL. VsidlEntry – это элемент верхнего уровня,
который связывает все остальные.
Назначение
- Определяет общую структуру файла VSIDL.
- Указывает пространство имен пакета для всех объектов в файле.
- Содержит набор определений пакетов услуг.
- Позволяет добавлять собственные расширения в модель VSIDL.
- Включает правила сопоставления для SOME/IP и VHAL.
Ограничения
- Название пакета (E211). Название пакета не должно превышать 127 символов.
- Несвязанные файлы (E10B). Все файлы в каталоге должны быть указаны в группе файлов
Android.bp.
Пакет услуг
В этом разделе описывается тип сообщения о пакете услуг.
Грамматика 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
;
Определение протокола
// 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;
}
Пример использования
service_bundle {
name: "SeatController"
publisher {
message: "SeatHeating"
topic: "driver-seat"
capacity: 10
}
}
Описание
Пакет сервисов определяет логическую группировку связанных сервисов, издателей, подписчиков, серверов RPC и клиентов RPC. Пакет услуг действует как контейнер для определенного набора функций и их взаимодействий.
Ограничения
- Требования к названию пакета (E209, E20A, E20B, E20C):
- У пакета услуг должно быть название.
- Название должно начинаться с допустимого начального символа идентификатора Unicode (обычно это буква).
- Последующие символы в названии должны быть допустимыми символами продолжения идентификатора Unicode (обычно это буквы или цифры).
- Название не должно быть зарезервированным ключевым словом в Rust, Java или C++.
- Глобальная уникальность пакета (E309). У каждого пакета сервисов должно быть уникальное полное имя (на основе его пакета и имени).
- Внутренняя уникальность (E100, E300, E302, E303, E308):
- В одном пакете сервисов каждый сервис RPC может обслуживаться не более чем одним определением сервера.
- В одном пакете сервисов каждый тип публикации
MULTI_PUBможет быть опубликован не более чем одним определением издателя. - В рамках одного пакета услуг все названия единиц обслуживания, заданные пользователем (для издателей или серверов), должны быть уникальными.
- В одном пакете услуг все названия единиц обслуживания (как заданные пользователем, так и сгенерированные автоматически) должны быть уникальными.
- Правила именования целевых объектов сборки (E205, E206, E207, E208). Если указано название целевого объекта сборки (
build_cfg.target_name), оно должно быть написано в змеином регистре (строчные буквы, цифры и одиночные символы подчеркивания, не в начале и не в конце). - Уникальность названия целевого объекта сборки (E301). Название целевого объекта сборки, заданное пользователем, не должно совпадать с автоматически созданными названиями целевых объектов для других пакетов сервисов.
Издатель
В этом разделе описывается тип сообщения издателя.
Грамматика EBNF
Publisher = "{" , { PublisherElement } , "}" ;
PublisherElement =
"message" , ":" , String |
"topic" , ":" , String |
"capacity" , ":" , Integer |
"service_unit_name" , ":" , String
;
Определение протокола
// 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;
}
Пример использования
publisher {
message: "SeatHeating"
topic: "driver-heating"
capacity: 10
}
Описание
Тип сообщения Publisher определяет источник данных, который предоставляет ServiceBundle. Этот тип сообщения указывает тип публикуемых данных, а также конкретные темы и емкость этих данных.
Темы
Каждый экземпляр Publisher содержит поле message, которое ссылается на публикуемое сообщение proto. В нем должны быть указаны тема (topic) и вместимость (capacity).
- Тема. Уникальный идентификатор темы публикации. Оно должно быть написано строчными буквами через дефис (например,
my-topic). - Емкость. Размер очереди, то есть количество сообщений, которое она может вместить, прежде чем непрочитанные сообщения будут удалены. Это должно быть четное число, большее или равное 2.
Пользовательские названия
Издатели могут задавать собственные названия рекламных блоков, которые будут использоваться вместо автоматически выбранных. Это позволяет выбирать более короткие названия. Если издатель использует пользовательское название сервисного блока, он может использовать только один экземпляр, чтобы название сервисного блока было уникально назначено одному экземпляру.
# 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"
}
Ограничения
- Место размещения издателя (E300). Издатели для одного и того же типа
MULTI_PUBдолжны быть определены в отдельных пакетах услуг. - Уникальность локального названия (E302). В рамках одного пакета услуг все издатели должны иметь уникальные названия единиц услуг, заданные пользователем.
- Глобальная уникальность названий (E304). Издатели одного типа должны иметь глобально уникальные названия единиц обслуживания, заданные пользователем, во всех пакетах услуг.
- Назначение названий отдельным каналам (E306). Названия рекламных блоков, заданные пользователем, можно назначать только издателям, которые управляют одним экземпляром.
- Ограничение на одного издателя (E307). Сообщение protobuf, помеченное как
SINGLE_PUB, может быть опубликовано только одним издателем во всей системе. - Уникальность названий единиц обслуживания (E308). Все названия единиц обслуживания (как сгенерированные, так и заданные пользователем) должны быть уникальными в пределах пакета услуг. Заданные пользователем названия следует использовать для разрешения конфликтов со сгенерированными названиями.
- Требование к указанию варианта (E501). Если издатель использует заданное пользователем название для типа с несколькими вариантами, он должен явно указать, какой вариант публикует.
- Наличие издателя для подписчиков (E504). Для каждого определенного подписчика требуется по крайней мере один соответствующий издатель для указанного типа и варианта.
- Недопустимый тип издателя (E601). Издатель должен ссылаться на тип, который соответствует существующему сообщению protobuf.
- Требование к аннотации публикации (E602). Тип сообщения protobuf, на который ссылается издатель, должен включать аннотацию
SdvPublication. - Допустимое использование вариантов (E606). Если издатель указывает вариант (экземпляр), этот вариант должен существовать в
instances_enum, определенном для типа публикации в protobuf. - Условие указания варианта (E607). Издатель может указать явный вариант (экземпляр), только если тип публикации определяет
instances_enumв protobuf. - Название темы (E20D, E20F). Названия тем должны быть написаны строчными буквами через дефис и не превышать 127 символов.
- Уникальность тем (E314). Темы должны быть уникальными для всех издателей.
- Требования к вместимости (E406, E407). Вместимость – обязательный параметр. Значение должно быть четным числом, равным или большим 2.
Подписчики
В этом разделе описывается тип сообщения для подписчиков.
Грамматика EBNF
Subscriber = "{" , { SubscriberElement } , "}" ;
SubscriberElement =
"message" , ":" , String |
"topic" , ":" , String
;
Определение протокола
// 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;
}
Пример использования
subscriber {
message: "SeatHeating"
topic: "driver-seat"
}
Описание
Сообщение Subscriber определяет получателя публикации, которого предоставляет ServiceBundle. В этом сообщении указывается тип данных, на которые оформляется подписка, и конкретные темы этой публикации. Если у темы несколько издателей, подписчик получает сообщения, опубликованные всеми ими.
Ограничения
- Наличие издателя (E504). Для каждого определенного подписчика должен существовать хотя бы один соответствующий издатель, который публикует указанный тип и вариант публикации.
- Недопустимый тип подписки (E608). Подписчик должен ссылаться на тип, который соответствует существующему сообщению protobuf, определенному с помощью аннотации
SdvPublication. - Действительная подписка на вариант (E609). Если подписчик указывает вариант (экземпляр), этот вариант должен быть действительным значением, определенным в
instances_enumсоответствующего типа публикации protobuf. - Topic mandatory (E408). Тема обязательна для подписчиков.
- Повторное объявление темы (E311). Темы подписчиков не должны повторно объявляться в одном и том же пакете сервисов.
RPC-сервер
В этом разделе описывается тип сообщения сервера RPC.
Грамматика EBNF
Server = "{" , { ServerElement } , "}" ;
ServerElement =
"service" , ":" , String |
"channel" , ":" , String |
"service_unit_name" , ":" , String
;
Определение протокола
// 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;
}
Пример использования
server {
service: "SetTemperature"
channel: "temp-setter"
}
Описание
Сообщение Server определяет сервер RPC, который предоставляет ServiceBundle. Это сообщение указывает сервис, который реализует сервер, и канал RPC.
Сервер RPC предоставляет набор методов, которые клиенты могут вызывать удаленно. Поле service указывает название сервиса RPC, который реализует сервер. Этот сервис определен в файле proto и реализован в пользовательском коде Rust. Сервисы RPC могут включать унарные методы, а также методы потоковой передачи на стороне клиента и сервера, как указано в определении сервиса protobuf. Поле channel определяет конечную точку связи и является обязательным (E409).
Ограничения
- Определение сервиса (E603). Сервер RPC должен указывать значение
service, которое соответствует существующему значениюserviceRPC protobuf. - Ограничение на количество серверов для одного сервиса (E100). В рамках одного пакета сервисов определенный RPC
serviceможет обслуживаться не более чем одним определением сервера. - Название канала (E20E). Названия каналов RPC должны быть написаны строчными буквами через дефис.
- Channel mandatory (E409). Обязательно укажите канал RPC.
- Уникальность канала (E40B). Канал RPC должен использоваться только одним сервисом.
RPC-клиент
В этом разделе описывается тип сообщения клиента RPC.
Грамматика EBNF
Client = "{" , { ClientElement } , "}" ;
ClientElement =
"service" , ":" , String |
"channel" , ":" , String
;
Определение протокола
// 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;
}
Пример использования
client {
service: "SetTemperature"
channel: "temp-setter"
}
Описание
client определяет клиент RPC, который использует ServiceBundle. client указывает сервис, с которым взаимодействует клиент, и канал для подключения. Клиент может взаимодействовать с унарными методами, а также методами потоковой передачи на стороне клиента и сервера в зависимости от определения сервиса.
Ограничения
- Определение сервиса (E60A). Клиент RPC должен указать
service, соответствующий существующему определениюserviceprotobuf. - Уникальный источник сервиса (E60B). Определение protobuf
service, на которое ссылаетсяserviceклиента RPC, должно быть уникальным (не должно определяться несколько раз) во всех файлах protobuf. - Channel mandatory (E409). Обязательно укажите канал RPC.
Конфигурация сборки
В этом разделе описывается тип сообщения "Конфигурация сборки".
Грамматика EBNF
BuildConfiguration = "{" , BuildConfigurationElement, "}" ;
BuildConfigurationElement =
"target_name" , ":" , String |
"skip_codegen" , ":" , Boolean
;
Определение протокола
// 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;
}
Пример использования
build_cfg {
target_name: "my_custom_target_name"
skip_codegen: false
}
Описание
BuildConfiguration настраивает нестандартные параметры ServiceBundle для генерации кода. Все конфигурации сборки необязательны.
target_name(необязательный параметр,string) – название цели сборки в файлахAndroid.bp. Используйте этот параметр, чтобы задать более короткие названия целей, чем те, которые выбираются автоматически.skip_codegen(необязательный параметрbool) указывает, нужно ли пропускать генерацию кода для этого пакета сервисов. Если задано значениеtrue, код для этого пакета услуг не генерируется. Это может быть полезно для пакетов услуг, которые реализуются вручную. По умолчанию установлено значениеfalse.
Ограничения
- Формат названия цели (E205, E206, E207, E208). Если указано название цели специальной сборки (
build_cfg.target_name), оно должно быть написано в змеином регистре:- Оно должно содержать только строчные буквы (от
aдоz), цифры (от0до9) и символы подчеркивания (_). - В нем не должно быть нескольких символов подчеркивания подряд (
__). - и не должно начинаться с символа подчеркивания.
- и не может заканчиваться символом подчеркивания.
- Оно должно содержать только строчные буквы (от
- Уникальность названия цели (E301). Заданное пользователем значение
build_cfg.target_nameдолжно быть уникальным в системе сборки и не должно конфликтовать с автоматически сгенерированными названиями целей, полученными из других определений пакетов сервисов.