このページでは、ISO/IEC 14977 拡張バッカス・ナウア記法(EBNF)と protobuf を使用して、車両サービス インターフェース定義言語(VSIDL)を指定します。このページでは、言語のコンテキストフリー文法と言語要素の意味に焦点を当てています。
言語の階層
Meta Object Facility(MOF)によると、VSIDL コンパイラ(VSIDLC)は図 1 に示す言語を使用します。
図 1. VSIDLC 言語。
VSIDLC は主にプロトコル バッファ(protobuf)言語に基づいています。Protobuf は、パブリッシュ / サブスクライブとリモート プロシージャ コール(RPC)を使用して交換されるデータ型を指定します。技術的には、VSIDL モデルは TextProto ファイルであり、VSIDL 構文は protobuf ファイル(syntax.proto)で定義されます。
データ型を指定するための protobuf ファイルと VSIDL モデルの両方が、Rust コードの生成に使用されます。生成されたコードには、交換されたメッセージ データ構造の構造体と、サービス ユニットを作成するための Rust 関数が含まれています。これらのサービス ユニットは自動的に呼び出されません。カスタム Rust コードは、生成されたコードを使用してサービス ユニットをインスタンス化し、アプリケーション ロジックを実装します。
抽象構文
図 2 に、VSIDL のコア メッセージ タイプを示します。
図 2. VSIDL のコア メッセージ タイプ。
VSIDL エントリ
このセクションでは、VSIDL エントリ メッセージ タイプについて説明します。
EBNF 文法
start VsidlEntry =
"package" , ":" , String , ";" ,
{ "service_bundle" , ServiceBundle } ,
{ "extension" , ":" , Any } ,
{ "some_ip_mapping" , ":" , SomeIpMapping } ,
{ "vhal_mapping" , ":" , VhalMapping }
;
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;
}
使用例
package: "com.android.sdv.sample.vsidl"
service_bundle {
name: "Manager"
publisher {
message: "TirePressure"
topic: "front-left"
topic: "front-right"
capacity: 10
}
}
説明
VsidlEntry メッセージは、VSIDL ファイル(拡張子 .vsidl)のルートコンテナとして機能します。このメッセージは、すべての定義と構成を 1 つの 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
;
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;
}
使用例
service_bundle {
name: "SeatController"
publisher {
message: "SeatHeating"
topic: "driver-seat"
capacity: 10
}
}
説明
サービス バンドルは、関連するサービス、パブリッシャー、サブスクライバー、RPC サーバー、RPC クライアントの論理グループを定義します。サービス バンドルは、特定の機能セットとそのインタラクションのコンテナとして機能します。
制約
- バンドル名の要件(E209、E20A、E20B、E20C):
- サービス バンドルには名前を入力する必要があります。
- 名前の先頭は、有効な Unicode 識別子の開始文字(通常は英字)にする必要があります。
- 名前の 2 文字目以降は、有効な Unicode 識別子の継続文字(通常は英字または数字)にする必要があります。
- 名前は、Rust、Java、C++ の予約済みキーワードにすることはできません。
- グローバル バンドルの一意性(E309): すべてのサービス バンドルには、一意の完全修飾名(パッケージと名前に基づく)が必要です。
- 内部の一意性(E100、E300、E302、E303、E308):
- 1 つのサービス バンドル内で、各 RPC サービスは最大 1 つのサーバー定義で提供できます。
- 1 つのサービス バンドル内で、各
MULTI_PUBパブリケーション タイプは、最大 1 つのパブリッシャー定義で公開できます。 - 1 つのサービス バンドル内で、ユーザー定義のサービス ユニット名(パブリッシャーまたはサーバー用)はすべて一意である必要があります。
- 1 つのサービス バンドル内で、すべてのサービス ユニット名(ユーザー定義または自動生成)は一意である必要があります。
- ビルド ターゲットの命名規則(E205、E206、E207、E208): カスタム ビルド ターゲット名(
build_cfg.target_name)を指定する場合は、スネークケース形式(小文字、数字、単一のアンダースコア。アンダースコアで開始または終了しない)に準拠する必要があります。 - ビルド ターゲット名の一意性(E301): ユーザー定義のビルド ターゲット名は、他のサービス バンドル用に自動生成されたターゲット名と競合してはなりません。
パブリッシャー
このセクションでは、Publisher メッセージ タイプについて説明します。
EBNF 文法
Publisher = "{" , { PublisherElement } , "}" ;
PublisherElement =
"message" , ":" , String |
"topic" , ":" , String |
"capacity" , ":" , Integer |
"service_unit_name" , ":" , String
;
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;
}
使用例
publisher {
message: "SeatHeating"
topic: "driver-heating"
capacity: 10
}
説明
Publisher メッセージ タイプは、ServiceBundle が提供するデータソースを定義します。このメッセージ タイプは、パブリッシュされるデータのタイプと、そのデータの特定のトピックと容量を指定します。
トピック
すべての Publisher インスタンスには、公開される proto メッセージを参照する message フィールドがあります。トピック(topic で表される)と容量(capacity で表される)を指定する必要があります。
- トピック: パブリケーション トピックの固有識別子。小文字のダッシュケース(
my-topicなど)にする必要があります。 - 容量: キューのサイズを指定します。つまり、未読メッセージが破棄される前にキューに保持できるメッセージの数を指定します。2 以上の偶数にする必要があります。
ユーザー定義の名前
パブリッシャーは、自動的に選択されたサービス ユニット名をオーバーライドするユーザー定義のサービス ユニット名を使用できます。このアフォーダンスにより、短い名前を選択できます。パブリッシャーがユーザー定義のサービス ユニット名を使用する場合、サービス ユニット名が 1 つのインスタンスに一意に割り当てられるように、1 つのインスタンスのみを使用することがあります。
# 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): 1 つのサービス バンドル内で、すべてのパブリッシャーに一意のユーザー定義サービス ユニット名が必要です。
- グローバル名の固有性(E304): 同じパブリケーション タイプのパブリッシャーは、すべてのサービス バンドルでグローバルに一意のユーザー定義サービス ユニット名を持つ必要があります。
- 単一チャンネルの命名(E306): ユーザー定義のサービス ユニット名は、1 つのインスタンスのみを処理するパブリッシャーにのみ割り当てることができます。
- 単一パブリッシャーの制限(E307):
SINGLE_PUBとマークされた protobuf メッセージは、システム全体で 1 つのパブリッシャーのみがパブリッシュできます。 - サービス ユニット名の一意性(E308): すべてのサービス ユニット名(生成された名前かユーザー定義の名前かに関係なく)は、サービス バンドル内で一意である必要があります。ユーザー定義の名前は、生成された名前との競合を解決するために使用する必要があります。
- バリアント仕様の要件(E501): パブリッシャーが複数のバリアントを持つタイプにユーザー定義の名前を使用する場合は、公開するバリアントを明示的に指定する必要があります。
- サブスクライバーのパブリッシャーの存在(E504): 定義されたすべてのサブスクライバーには、指定されたタイプとバリアントに対応するパブリッシャーが少なくとも 1 つ必要です。
- 有効なパブリッシャー タイプ(E601): パブリッシャーは、既存の protobuf メッセージに対応するタイプを参照する必要があります。
- パブリケーション アノテーションの要件(E602): パブリッシャーが参照する protobuf メッセージ タイプには、
SdvPublicationアノテーションを含める必要があります。 - 有効なバリアントの使用(E606): パブリッシャーがバリアント(インスタンス)を指定する場合、そのバリアントは、protobuf のパブリケーション タイプに定義されている
instances_enum内に存在する必要があります。 - バリアント仕様条件(E607): パブリッシャーは、パブリケーション タイプが protobuf で
instances_enumを定義している場合にのみ、明示的なバリアント(インスタンス)を指定できます。 - トピックの命名(E20D、E20F): トピックは小文字のダッシュケースで、127 文字以下にする必要があります。
- トピックの一意性(E314): トピックは、すべてのパブリッシャーでグローバルに一意である必要があります。
- 容量の要件(E406、E407): 容量は必須で、2 以上の偶数にする必要があります。
サブスクライバー
このセクションでは、サブスクライバー メッセージ タイプについて説明します。
EBNF 文法
Subscriber = "{" , { SubscriberElement } , "}" ;
SubscriberElement =
"message" , ":" , String |
"topic" , ":" , String
;
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;
}
使用例
subscriber {
message: "SeatHeating"
topic: "driver-seat"
}
説明
Subscriber メッセージは、ServiceBundle が提供するパブリケーション レシーバを定義します。このメッセージは、サブスクライブするデータのタイプと、そのパブリケーションの特定のトピックを指定します。トピックに複数のパブリッシャーがある場合、サブスクライバーはすべてのパブリッシャーからパブリッシュされたメッセージを受信します。
制約
- パブリッシャーの存在(E504): 定義されたサブスクライバーごとに、指定されたパブリケーション タイプとバリアントをパブリッシュする対応するパブリッシャーが少なくとも 1 つ存在する必要があります。
- 有効なサブスクリプション タイプ(E608): サブスクライバーは、
SdvPublicationアノテーションで定義された既存の protobuf メッセージに対応するタイプを参照する必要があります。 - 有効なバリアント サブスクリプション(E609): サブスクライバーがバリアント(インスタンス)を指定する場合、そのバリアントは、対応する protobuf パブリケーション タイプの
instances_enum内で定義された有効な値である必要があります。 - トピックは必須(E408): サブスクライバーにはトピックが必須です。
- トピックの再宣言(E311): サブスクライバー トピックは、同じサービス バンドル内で再宣言しないでください。
RPC サーバー
このセクションでは、RPC サーバーのメッセージ タイプについて説明します。
EBNF 文法
Server = "{" , { ServerElement } , "}" ;
ServerElement =
"service" , ":" , String |
"channel" , ":" , String |
"service_unit_name" , ":" , String
;
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;
}
使用例
server {
service: "SetTemperature"
channel: "temp-setter"
}
説明
Server メッセージは、ServiceBundle が提供する RPC サーバーを定義します。このメッセージでは、サーバーが実装するサービスと RPC チャネルを指定します。
RPC サーバーは、クライアントがリモートで呼び出すことができる一連のメソッドを公開します。service フィールドには、サーバーが実装する RPC サービスの名前を指定します。このサービスは proto ファイルで定義され、カスタム Rust コードで実装されます。RPC サービスには、protobuf サービス定義で定義されている単項、クライアント ストリーミング、サーバー ストリーミングのメソッドを含めることができます。channel フィールドは通信エンドポイントを定義するもので、必須です(E409)。
制約
- サービス定義(E603): RPC サーバーは、既存の protobuf RPC
service値に対応するservice値を指定する必要があります。 - サービスあたりのサーバーの上限(E100): 1 つのサービス バンドル内で、特定の RPC
serviceを処理できるサーバー定義は 1 つだけです。 - チャンネルの命名(E20E): RPC チャンネルは、小文字のダッシュケースにする必要があります。
- チャンネルは必須(E409): RPC チャンネルは必須です。
- チャネルの一意性(E40B): RPC チャネルは 1 つのサービスでのみ使用する必要があります。
RPC クライアント
このセクションでは、RPC クライアント メッセージ タイプについて説明します。
EBNF 文法
Client = "{" , { ClientElement } , "}" ;
ClientElement =
"service" , ":" , String |
"channel" , ":" , String
;
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;
}
使用例
client {
service: "SetTemperature"
channel: "temp-setter"
}
説明
client は、ServiceBundle が使用する RPC クライアントを定義します。client は、クライアントがやり取りするサービスと、接続するチャネルを指定します。クライアントは、サービス定義に応じて、単項メソッド、クライアント ストリーミング メソッド、サーバー ストリーミング メソッドを操作できます。
制約
- サービス定義(E60A): RPC クライアントは、既存の protobuf
service定義に対応するserviceを指定する必要があります。 - 一意のサービスソース(E60B): RPC クライアントの
serviceによって参照される protobufservice定義は、すべての protobuf ファイルで一意に定義されている必要があります(複数回定義されていない)。 - チャンネルは必須(E409): RPC チャンネルは必須です。
ビルド構成
このセクションでは、ビルド構成メッセージ タイプについて説明します。
EBNF 文法
BuildConfiguration = "{" , BuildConfigurationElement, "}" ;
BuildConfigurationElement =
"target_name" , ":" , String |
"skip_codegen" , ":" , Boolean
;
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;
}
使用例
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は、ビルドシステム全体で一意である必要があり、他のサービス バンドル定義から派生した自動生成されたターゲット名と競合してはなりません。