語言規格

本頁面使用 ISO/IEC 14977 擴充 Backus-Naur Form (EBNF) 和 protobuf,指定車輛服務介面定義語言 (VSIDL)。本頁著重於語言的無關聯文法,以及語言元素的意義。

語言階層

根據 Meta Object Facility (MOF),VSIDL 編譯器 (VSIDLC) 使用圖 1 所示的語言:

VSIDLC 語言

圖 1. VSIDLC 語言。

VSIDLC 主要以通訊協定緩衝區 (protobuf) 語言為基礎。Protobuf 用於指定透過發布/訂閱和遠端程序呼叫 (RPC) 呼叫交換的資料類型。從技術角度來看,VSIDL 模型是 TextProto 檔案,而 VSIDL 的語法是在 protobuf 檔案 (syntax.proto) 中定義。指定資料型別的 protobuf 檔案和 VSIDL 模型都會用於產生 Rust 程式碼。產生的程式碼主要包含實作所交換訊息資料結構的結構體,以及實作函式的 Rust 函式,可在 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 filegroup 中參照。

服務組合

本節說明服務套裝組合訊息類型。

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 欄位,參照發布的 proto 訊息。其中必須指定主題 (以 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):主題必須採用小寫破折號格式,且不得超過 127 個字元。
  • 主題不得重複 (E314):所有發布商的主題不得重複。
  • 容量規定 (E406、E407):容量為必填欄位,且必須是 >= 2 的偶數。

訂閱端

本節說明 Subscriber 訊息類型。

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 中定義的有效值。
  • 主題為必填欄位 (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 管道必須為小寫連字號格式。
  • 管道為必填欄位 (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 檔案中不重複定義 (不得定義多次)。
  • 管道為必填欄位 (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),則必須嚴格遵守蛇形命名法格式:
    • 只能包含小寫英文字母 (az)、數字 (09) 和底線 (_)。
    • 不得包含連續底線 (__)。
    • 開頭不得為底線。
    • 結尾不得為底線。
  • 目標名稱不得重複 (E301):使用者定義的 build_cfg.target_name 在整個建構系統中不得重複,且不得與從其他服務套件定義衍生的任何自動產生目標名稱衝突。