語言規格

本頁面使用 ISO/IEC 14977 擴充巴克斯-諾爾範式 (EBNF) 和 protobuf,指定車輛服務介面定義語言 (VSIDL)。本頁著重於語言的上下文無關文法和語言元素的意義。

語言階層

根據中繼物件設施 (MOF),VSIDL 編譯器 (VSIDLC) 會使用圖 1 所示的語言:

VSIDLC 語言

圖 1. VSIDLC 語言。

VSIDLC 主要以通訊協定緩衝區 (protobuf) 語言為基礎。Protobuf 會指定使用發布/訂閱和遠端程序呼叫 (RPC) 交換的資料類型。嚴格來說,VSIDL 模型是 TextProto 檔案,VSIDL 語法定義於 protobuf 檔案 (syntax.proto)。

用於指定資料類型的 protobuf 檔案和 VSIDL 模型,都會用來產生 Rust 程式碼。產生的程式碼包含交換訊息資料結構的結構體,以及用於建立服務單元的 Rust 函式,但不會自動呼叫這些服務單元。接著,自訂 Rust 程式碼會使用產生的程式碼,將服務單元例項化並實作應用程式邏輯。

抽象語法

圖 2 顯示 VSIDL 中的核心訊息類型:

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) 的根容器。這則訊息會將所有定義和設定封裝在單一 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 識別項起始字元 (通常是英文字母)。
    • 名稱中的後續字元必須是有效的 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
;

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 執行個體都有一個 message 欄位,參照要發布的原型訊息。必須指定主題 (以 topic 表示) 和容量 (以 capacity 表示)。

  • 主題:發布主題的專屬 ID。必須採用小寫連字號格式 (例如 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):標示為 SINGLE_PUB 的 protobuf 訊息,在整個系統中只能由一個發布者發布。
  • 服務單位名稱不重複 (E308):所有服務單位名稱 (無論是產生的或使用者定義的) 在服務套件中都不得重複;使用者定義的名稱應用於解決與產生的名稱衝突。
  • 變體規格規定 (E501):如果發布者為具有多個變體的類型使用使用者定義的名稱,則必須明確指定發布的變體。
  • 訂閱者是否有對應的發布者 (E504):每個定義的訂閱者都必須至少有一個對應的發布者,且類型和變體必須與訂閱者相同。
  • 有效的發布者類型 (E601):發布者必須參照與現有 protobuf 訊息對應的類型。
  • 發布註解規定 (E602):發布者參照的 protobuf 訊息類型必須包含 SdvPublication 註解。
  • 有效變體用法 (E606):如果發布者指定變體 (例項),該變體必須存在於 protobuf 中為發布類型定義的 instances_enum 內。
  • 變體規格條件 (E607):只有在發布類型於 protobuf 中定義 instances_enum 時,發布者才能指定明確的變體 (例項)。
  • 主題命名 (E20D、E20F):主題必須採用小寫 dash-case 格式,且不得超過 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):對於每個定義的訂閱者,必須至少有一個對應的發布者,發布指定的發布類型和變化版本。
  • 有效的訂閱類型 (E608):訂閱者必須參照與現有 protobuf 訊息對應的類型,該訊息是以 SdvPublication 註解定義。
  • 有效的變體訂閱 (E609):如果訂閱者指定變體 (例項),該變體必須是相應 protobuf 發布類型 instances_enum 中定義的有效值。
  • Topic mandatory (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):在單一服務套件中,特定 RPC service 最多只能由一個伺服器定義提供。
  • 管道命名 (E20E):RPC 管道必須採用小寫連字號命名法。
  • Channel mandatory (E409):必須提供 RPC 管道。
  • 管道不重複 (E40B):RPC 管道只能由一項服務使用。

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 參照的 protobuf service 定義,必須在所有 protobuf 檔案中不重複定義 (不得定義多次)。
  • Channel mandatory (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 在建構系統中不得重複,且不得與其他服務套件定義衍生的任何自動產生目標名稱衝突。