Language specification

This page specifies the Vehicle Service Interface Definition Language (VSIDL) using ISO/IEC 14977 Extended Backus-Naur Form (EBNF) and protobuf. This page focuses on the context-free grammar of the language and the meaning of the language elements.

Language hierarchy

According to the Meta Object Facility (MOF), VSIDL compiler (VSIDLC) uses the languages shown in Figure 1:

VSIDLC languages

Figure 1. VSIDLC languages.

VSIDLC is mainly based on the protocol buffer (protobuf) language. Protobuf is used to specify the data types that are exchanged using publish-subscribe and remote procedure calls (RPCs) calls. From a technical point of view, VSIDL models are TextProto files, where VSIDL's syntax is defined in a protobuf file (syntax.proto). Both the protobuf files for specifying data types and VSIDL models are used to generate Rust code. The generated code mainly contains structs that implement the data structures for the exchanged messages and Rust functions that implement functions for creating service units in Rust, without calling these service units automatically. This generated Rust code is accompanied by custom Rust code that uses the generated code to instantiate service units and implement the business logic of the application.

Abstract syntax

Figure 2 shows the core message types in VSIDL:

Core message types in VSIDL

Figure 2. Core message types in VSIDL.

VSIDL entry

This section explains the VSIDL entry message type.

EBNF grammar

start VsidlEntry =
  "package" , ":" , String , ";" ,
  { "service_bundle" , ServiceBundle } ,
  { "extension" , ":" , Any } ,
  { "some_ip_mapping" , ":" , SomeIpMapping } ,
  { "vhal_mapping" , ":" , VhalMapping }
;

Proto definition

// 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;
}

Usage example

package: "com.android.sdv.sample.vsidl"

service_bundle {
  name: "Manager"

  publisher {
    message: "TirePressure"
    topic: "front-left"
    topic: "front-right"
    capacity: 10
  }
}

Explanation

The VsidlEntry message serves as the root container for VSIDL file (with the extension .vsidl). This message encapsulates all definitions and configurations in a single VSIDL file. The VsidlEntry is the top-level element that binds everything else.

Purpose:

  • Defines the overall structure of a VSIDL file.
  • Specifies the package namespace for all entities within the file.
  • Contains a collection of service bundle definitions.
  • Allows custom extensions to the VSIDL model.
  • Includes mapping rules for SOME/IP and VHAL.

Constraints

  • Package name (E211): The package name must not exceed 127 characters.
  • Dangling files (E10B): All files in a catalog must be referenced in an Android.bp filegroup.

Service bundle

This section explains the service bundle message type.

EBNF grammar

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
;

Proto definition

// 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;
}

Usage example

service_bundle {
    name: "SeatController"

    publisher {
      message: "SeatHeating"
      topic: "driver-seat"
      capacity: 10
    }
}

Explanation

A service bundle defines a logical grouping of related services, publishers, subscribers, RPC servers, and RPC clients. A service bundle acts as a container for a specific set of functionalities and their interactions.

Constraints

  • Bundle name requirements (E209, E20A, E20B, E20C):
    • A service bundle must have a populated name.
    • The name must start with a valid Unicode identifier start character (typically a letter).
    • Subsequent characters in the name must be valid Unicode identifier continuation characters (typically letters or numbers).
    • The name must not be a reserved keyword in Rust, Java, or C++.
  • Global bundle uniqueness (E309): Every service bundle must have a unique fully qualified name (based on its package and name).
  • Internal uniqueness (E100, E300, E302, E303, E308):
    • Within a single service bundle, each RPC service can be served by at most one server definition.
    • Within a single service bundle, each MULTI_PUB publication type can be published by at most one publisher definition.
    • Within a single service bundle, all user-defined service unit names (for publishers or servers) must be unique.
    • Within a single service bundle, all service unit names (whether user-defined or automatically generated) must be unique.
  • Build target naming conventions (E205, E206, E207, E208): If a custom build target name (build_cfg.target_name) is provided, it must adhere to snake case format (lowercase letters, numbers, and single underscores, not starting or ending with an underscore).
  • Build target name uniqueness (E301): A user-defined build target name must not clash with any automatically generated target names for other service bundles.

Publisher

This section explains the Publisher message type.

EBNF grammar

Publisher = "{" , { PublisherElement } , "}" ;

PublisherElement =
  "message" , ":" , String |
  "topic" , ":" , String |
  "capacity" , ":" , Integer |
  "service_unit_name" , ":" , String
;

Proto definition

// 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;
}

Usage example

publisher {
  message: "SeatHeating"
  topic: "driver-heating"
  capacity: 10
}

Explanation

The Publisher message type defines a data source that ServiceBundle provides. This message type specifies the type of data being published and the specific topics and capacity of that data.

Topics

Every Publisher instance has a message field that refers to the proto message being published. It must specify a topic (represented by topic) and a capacity (represented by capacity).

  • Topic: A unique identifier for the publication topic. It must follow lowercase dash-case (for example, my-topic).
  • Capacity: Specifies the size of the queue, that is, how many messages the queue can hold before unread messages are discarded. It must be an even number greater than or equal to 2.

User-defined names

Publishers can have user-defined service unit names that override the automatically chosen service unit names. This affordance enables choosing shorter names. If a publisher uses a user-defined service unit name, it might use only a single instance, so that the service unit name is uniquely assigned to one instance.

# 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"
}

Constraints

  • Publisher placement (E300): Publishers for the same MULTI_PUB type must be defined in separate service bundles.
  • Local name uniqueness (E302): Within any single service bundle, all publishers must have unique user-defined service unit names.
  • Global name uniqueness (E304): Publishers of the same publication type must have globally unique user-defined service unit names across all service bundles.
  • Naming single channels (E306): User-defined service unit names can be assigned only to publishers that handle exactly one instance.
  • Single publisher limit (E307): A protobuf message marked as SINGLE_PUB can be published by only one publisher across the entire system.
  • Service unit name uniqueness (E308): All service unit names (whether generated or user defined) must be unique within their service bundle; user-defined names should be used to resolve conflicts with generated names.
  • Variant specification requirement (E501): When a publisher uses a user-defined name for a type with multiple variants, it must explicitly specify the variant it publishes.
  • Publisher existence for subscribers (E504): Every defined subscriber requires at least one corresponding publisher for the specified type and variant.
  • Valid publisher type (E601): A publisher must reference a type that corresponds to an existing protobuf message.
  • Publication annotation requirement (E602): The protobuf message type referenced by a publisher must include the SdvPublication annotation.
  • Valid variant usage (E606): If a publisher specifies a variant (instance), that variant must exist within the instances_enum defined for the publication type in protobuf.
  • Variant specification condition (E607): A publisher can specify an explicit variant (instance) only if the publication type defines an instances_enum in protobuf.
  • Topic naming (E20D, E20F): Topics must be in lowercase dash-case and not exceed 127 characters.
  • Topic uniqueness (E314): Topics must be globally unique across all publishers.
  • Capacity requirements (E406, E407): Capacity is mandatory and must be an even number >= 2.

Subscriber

This section explains the Subscriber message type.

EBNF grammar

Subscriber = "{" , { SubscriberElement } , "}" ;

SubscriberElement =
  "message" , ":" , String |
  "topic" , ":" , String
;

Proto definition

// 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;
}

Usage example

subscriber {
  message: "SeatHeating"
  topic: "driver-seat"
}

Explanation

The Subscriber message defines a publication receiver that ServiceBundle provides. This message specifies the type of data being subscribed to and the specific topics of that publication. If there are multiple publishers for a topic, the subscriber receives the messages published by all of them.

Constraints

  • Publisher existence (E504): For every defined subscriber, at least one corresponding publisher must exist that publishes the specified publication type and variant.
  • Valid subscription type (E608): A subscriber must reference a type that corresponds to an existing protobuf message defined with the SdvPublication annotation.
  • Valid variant subscription (E609): If a subscriber specifies a variant (instance), that variant must be a valid value defined within instances_enum of the corresponding protobuf publication type.
  • Topic mandatory (E408): Topic is mandatory for subscribers.
  • Topic redeclaration (E311): Subscriber topics shouldn't be redeclared in the same service bundle.

RPC server

This section explains the RPC server message type.

EBNF grammar

Server = "{" , { ServerElement } , "}" ;

ServerElement =
  "service" , ":" , String |
  "channel" , ":" , String |
  "service_unit_name" , ":" , String
;

Proto definition

// 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;
}

Usage example

server {
  service: "SetTemperature"
  channel: "temp-setter"
}

Explanation

The Server message defines an RPC server that ServiceBundle provides. This message specifies the service that the server implements and the RPC channel.

An RPC server exposes a set of methods that clients can invoke remotely. The service field specifies the name of the RPC service that the server implements. This service is defined in a proto file and implemented in custom Rust code. RPC services can include unary, client-streaming, and server-streaming methods, as defined in the protobuf service definition. The channel field defines the communication endpoint and is mandatory (E409).

Constraints

  • Service definition (E603): An RPC server must specify a service value that corresponds to an existing protobuf RPC service value.
  • Server limit per service (E100): Within a single service bundle, a specific RPC service can be served by at most one server definition.
  • Channel naming (E20E): RPC channels must be in lowercase dash-case.
  • Channel mandatory (E409): RPC channel is mandatory.
  • Channel uniqueness (E40B): RPC channel must be used by only one service.

RPC client

This section explains the RPC client message type.

EBNF grammar

Client = "{" , { ClientElement } , "}" ;

ClientElement =
  "service" , ":" , String |
  "channel" , ":" , String
;

Proto definition

// 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;
}

Usage example

client {
  service: "SetTemperature"
  channel: "temp-setter"
}

Explanation

client defines an RPC client that ServiceBundle consumes. client specifies the service that the client interacts with and the channel to connect to. The client can interact with unary, client-streaming, and server-streaming methods, depending on the service definition.

Constraints

  • Service definition (E60A): An RPC client must specify a service that corresponds to an existing protobuf service definition.
  • Unique service source (E60B): The protobuf service definition referenced by an RPC client's service must be uniquely defined (not defined multiple times) across all protobuf files.
  • Channel mandatory (E409): RPC channel is mandatory.

Build configuration

This section explains the Build configuration message type.

EBNF grammar

BuildConfiguration = "{" , BuildConfigurationElement, "}" ;

BuildConfigurationElement =
  "target_name" , ":" , String |
  "skip_codegen" , ":" , Boolean
;

Proto definition

// 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;
}

Usage example

build_cfg {
  target_name: "my_custom_target_name"
  skip_codegen: false
}

Explanation

BuildConfiguration configures nonstandard parameters of ServiceBundle for code generation. All build configurations are optional.

  • target_name (optional string): Specifies the name of the build target in Android.bp files. Use this to set target names with shorter names than the automatically chosen names.
  • skip_codegen (optional bool): Indicates whether code generation should be skipped for this service bundle. If set to true, no code is generated for this particular service bundle. This can be useful for service bundles that are implemented manually. By default, this is set to false.

Constraints

  • Target name format (E205, E206, E207, E208): If a custom build target name (build_cfg.target_name) is provided, it must strictly follow snake case formatting:
    • It must contain only lowercase letters (a through z), numbers (0 through 9), and underscores (_).
    • It must not contain consecutive underscores (__).
    • It must not start with an underscore.
    • It must not end with an underscore.
  • Target name uniqueness (E301): A user-defined build_cfg.target_name must be unique across the build system and must not conflict with any automatically generated target names derived from other service bundle definitions.